|
| 1 | +--- |
| 2 | +outline: deep |
| 3 | +--- |
| 4 | + |
| 5 | +# Theming |
| 6 | + |
| 7 | +`vue3-styled-components` provides a `ThemeProvider` component for theming your components. This component passes a theme |
| 8 | +to all its descendant Vue components via props. All styled components within the render tree will have access to the |
| 9 | +provided theme. |
| 10 | + |
| 11 | +## Basic Theming |
| 12 | + |
| 13 | +The `ThemeProvider` wraps its children components and passes a theme object to them. All styled components within |
| 14 | +the `ThemeProvider`'s scope can access this theme object. |
| 15 | + |
| 16 | +:::demo |
| 17 | + |
| 18 | +```vue |
| 19 | +
|
| 20 | +<script setup lang="ts"> |
| 21 | + import { styled, ThemeProvider } from '@vue3-styled-components/package' |
| 22 | +
|
| 23 | + const StyledWrapper = styled.div` |
| 24 | + display: flex; |
| 25 | + justify-content: space-around; |
| 26 | + ` |
| 27 | +
|
| 28 | + const StyledLink = styled.a` |
| 29 | + margin-right: 8px; |
| 30 | + color: ${(props) => props.theme.primary} !important; |
| 31 | + font-weight: bold; |
| 32 | +` |
| 33 | +</script> |
| 34 | +
|
| 35 | +<template> |
| 36 | + <StyledWrapper> |
| 37 | + <a>This a normal link</a> |
| 38 | + <ThemeProvider :theme="{ primary: 'red' }"> |
| 39 | + <StyledLink>This a theming link</StyledLink> |
| 40 | + </ThemeProvider> |
| 41 | + </StyledWrapper> |
| 42 | +</template> |
| 43 | +``` |
| 44 | + |
| 45 | +::: |
| 46 | + |
| 47 | +In this example, the `StyledLink` component uses the primary color from the provided theme. |
| 48 | + |
| 49 | +## Reactive Theming |
| 50 | + |
| 51 | +You can also make your theme reactive by using Vue's reactivity system. This allows you to dynamically change the theme |
| 52 | +and see the updates reflected in your styled components. |
| 53 | + |
| 54 | +:::demo |
| 55 | + |
| 56 | +```vue |
| 57 | +
|
| 58 | +<script setup lang="ts"> |
| 59 | + import { styled, ThemeProvider } from '@vue3-styled-components/package' |
| 60 | + import { ref } from 'vue' |
| 61 | +
|
| 62 | + const theme = ref<Record<string, string>>({ primary: 'blue' }) |
| 63 | +
|
| 64 | + const StyledWrapper = styled.div` |
| 65 | + display: flex; |
| 66 | + justify-content: space-between; |
| 67 | + align-items: center; |
| 68 | + ` |
| 69 | +
|
| 70 | + const StyledLink = styled.a` |
| 71 | + color: ${(props) => props.theme.primary} !important; |
| 72 | + ` |
| 73 | +
|
| 74 | + const StyledButton = styled.button` |
| 75 | + width: 140px; |
| 76 | + height: 36px; |
| 77 | + margin-left: 20px; |
| 78 | + padding: 4px 12px; |
| 79 | + border-radius: 9999px; |
| 80 | + box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); |
| 81 | + background-color: skyblue; |
| 82 | + font-weight: bold; |
| 83 | + ` |
| 84 | +
|
| 85 | + const changeTheme = () => { |
| 86 | + if (theme.value.primary === 'red') { |
| 87 | + theme.value.primary = 'blue' |
| 88 | + } else { |
| 89 | + theme.value.primary = 'red' |
| 90 | + } |
| 91 | + } |
| 92 | +
|
| 93 | +</script> |
| 94 | +
|
| 95 | +<template> |
| 96 | + <ThemeProvider :theme="theme"> |
| 97 | + <StyledWrapper> |
| 98 | + <StyledLink>This a theming link</StyledLink> |
| 99 | + <StyledButton @click="changeTheme">Change Theme</StyledButton> |
| 100 | + </StyledWrapper> |
| 101 | + </ThemeProvider> |
| 102 | +</template> |
| 103 | +``` |
| 104 | + |
| 105 | +::: |
| 106 | + |
| 107 | +## Using Theme in Non-Styled Components |
| 108 | + |
| 109 | +By defining themes within the `ThemeProvider`, you ensure that all components have access to the |
| 110 | +same theme styles, achieving |
| 111 | +a globally consistent visual appearance. Even `non-styled components` in Vue can access the theme by injecting `$theme` |
| 112 | +and use properties defined in the theme for their styles. |
| 113 | + |
| 114 | +:::demo |
| 115 | + |
| 116 | +```vue |
| 117 | +
|
| 118 | +<script setup lang="ts"> |
| 119 | + import { ThemeProvider } from '@vue3-styled-components/package' |
| 120 | + import { defineComponent, h, inject } from 'vue' |
| 121 | +
|
| 122 | + const Link = defineComponent(() => { |
| 123 | + const theme = inject('$theme') |
| 124 | + return () => h('a', { style: { color: theme.primary } }, 'This is a link') |
| 125 | + }) |
| 126 | +
|
| 127 | +</script> |
| 128 | +
|
| 129 | +<template> |
| 130 | + <ThemeProvider :theme="{ primary: 'green' }"> |
| 131 | + <Link /> |
| 132 | + </ThemeProvider> |
| 133 | +</template> |
| 134 | +``` |
| 135 | + |
| 136 | +::: |
0 commit comments