Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

Commit 0b9eb23

Browse files
committed
feat(c-alert): add alert component base styling
1 parent 0380707 commit 0b9eb23

File tree

18 files changed

+298
-60
lines changed

18 files changed

+298
-60
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"c-box": "yarn workspace @chakra-ui/c-box",
2323
"c-button": "yarn workspace @chakra-ui/c-button",
2424
"system": "yarn workspace @chakra-ui/system-vue",
25+
"theme": "yarn workspace @chakra-ui/vue-theme",
2526
"nuxt": "yarn workspace @chakra-ui/nuxt-next"
2627
},
2728
"license": "MIT",

packages/c-alert/examples/base-alert.vue

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
11
<template>
2-
<c-alert
3-
font-weight="bold"
4-
px="4"
5-
py="3"
6-
:bg="['yellow.300', 'blue.200']"
7-
aria-role="alert"
8-
rounded="md"
9-
>
10-
HELLO ALERT
11-
</c-alert>
12-
<p>Alert paragraph</p>
2+
<c-alert> HELLO ALERT </c-alert>
133
</template>
144

155
<script lang="ts">
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<template>
2+
<c-alert status="info" mb="3"> Info alert </c-alert>
3+
<c-alert status="success" mb="3"> Success alert </c-alert>
4+
<c-alert status="warning" mb="3"> Warning alert </c-alert>
5+
<c-alert status="error" mb="3"> Error alert </c-alert>
6+
</template>
7+
8+
<script lang="ts">
9+
import CAlert from '@chakra-ui/c-alert/src'
10+
import { defineComponent } from 'vue'
11+
12+
export default defineComponent({
13+
name: 'BaseAlertExample',
14+
components: { CAlert },
15+
})
16+
</script>

packages/c-alert/src/alert.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { h, defineComponent, PropType, provide } from 'vue'
2+
import {
3+
chakra,
4+
ColorScheme,
5+
DeepComponentThemeConfig,
6+
ThemingProps,
7+
useMultiStyleConfig,
8+
provideComponentStyles,
9+
} from '@chakra-ui/system-vue'
10+
import { DOMElements } from '@chakra-ui/system-vue'
11+
import { SystemStyleObject } from '@chakra-ui/styled-system'
12+
13+
const STATUSES = {
14+
info: {
15+
colorScheme: 'blue' as ColorScheme,
16+
},
17+
success: {
18+
colorScheme: 'green' as ColorScheme,
19+
},
20+
warning: {
21+
colorScheme: 'orange' as ColorScheme,
22+
},
23+
error: {
24+
colorScheme: 'red' as ColorScheme,
25+
},
26+
}
27+
28+
type AlertStatus = keyof typeof STATUSES
29+
export type AlertVariant = 'solid' | 'subtle' | 'left-accent' | 'top-accent'
30+
31+
interface AlertState {
32+
status: AlertStatus
33+
}
34+
35+
const CAlert = defineComponent({
36+
name: 'CAlert',
37+
props: {
38+
as: {
39+
type: [String, Object] as PropType<DOMElements>,
40+
default: 'div',
41+
},
42+
status: {
43+
type: [String] as PropType<AlertStatus>,
44+
default: 'info',
45+
},
46+
colorScheme: {
47+
type: [String] as PropType<ColorScheme>,
48+
},
49+
styleConfig: {
50+
type: [Object] as PropType<DeepComponentThemeConfig>,
51+
},
52+
variant: {
53+
type: [String] as PropType<AlertVariant>,
54+
default: 'solid',
55+
},
56+
},
57+
setup(props, { slots, attrs }) {
58+
const colorScheme: ColorScheme =
59+
props.colorScheme || STATUSES[props.status].colorScheme
60+
61+
const themingProps: ThemingProps = {
62+
colorScheme,
63+
variant: props.variant,
64+
}
65+
const styles = useMultiStyleConfig('Alert', themingProps)
66+
const alertStyles: SystemStyleObject = {
67+
width: '100%',
68+
display: 'flex',
69+
alignItems: 'center',
70+
position: 'relative',
71+
overflow: 'hidden',
72+
...styles.value.container,
73+
}
74+
75+
provideComponentStyles('Alert', alertStyles)
76+
provide('$AlertState', { status: props.status } as AlertState)
77+
78+
return () =>
79+
h(
80+
chakra(props.as, 'alert'),
81+
{
82+
role: 'alert',
83+
...alertStyles,
84+
...attrs,
85+
},
86+
slots
87+
)
88+
},
89+
})
90+
91+
export default CAlert

packages/c-alert/src/index.ts

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,2 @@
1-
import { h, defineComponent, PropType } from 'vue'
2-
import { chakra } from '@chakra-ui/system-vue'
3-
import { DOMElements } from '@chakra-ui/system-vue/dist/types/system.utils'
4-
5-
const CAlert = defineComponent({
6-
name: 'CAlert',
7-
props: {
8-
as: {
9-
type: [String, Object] as PropType<DOMElements>,
10-
default: 'div',
11-
},
12-
},
13-
setup(props, { slots, attrs }) {
14-
return () =>
15-
h(
16-
chakra(props.as, 'alert'),
17-
{
18-
...attrs,
19-
role: 'alert',
20-
},
21-
slots
22-
)
23-
},
24-
})
25-
26-
export default CAlert
1+
import Alert from './alert'
2+
export default Alert

packages/c-theme-provider/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,3 @@ const CThemeProvider = defineComponent({
2626
})
2727

2828
export default CThemeProvider
29-
export * from './theme.hooks'

packages/c-theme-provider/src/theme.hooks.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

packages/core/src/index.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Plugin } from 'vue'
2-
import defaultTheme from '@chakra-ui/vue-theme'
2+
import defaultTheme, { ColorMode } from '@chakra-ui/vue-theme'
33
import { extendTheme, ThemeOverride } from './extend-theme'
44

55
interface ExtendIconsPath {
@@ -14,13 +14,16 @@ interface IconsOptions {
1414
interface ChakraUIVuePluginOptions {
1515
extendTheme?: ThemeOverride
1616
icons?: IconsOptions
17+
defaultColorMode?: ColorMode
1718
}
1819

1920
const ChakraUIVuePlugin: Plugin = {
2021
install(app, options: ChakraUIVuePluginOptions = {}) {
2122
const theme = options.extendTheme || defaultTheme
23+
const colorMode = options.defaultColorMode || 'light'
2224
app.config.globalProperties.$chakraTheme = theme
23-
app.provide('$chakraTheme', theme)
25+
app.provide('$chakraTheme', theme as ThemeOverride)
26+
app.provide('$chakraColorMode', colorMode as ColorMode)
2427
},
2528
}
2629

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { ThemeProviderProps } from '@chakra-ui/vue-next'
2+
import { ColorMode } from '@chakra-ui/vue-theme'
3+
import { inject, ref } from 'vue'
4+
5+
/** Provides theme object in component context */
6+
export const useTheme = (): ThemeProviderProps => {
7+
const theme = inject('$chakraTheme') as ThemeProviderProps
8+
return theme
9+
}
10+
11+
/** Injects color mode into component instance */
12+
export const useColorMode = () => {
13+
const _colorMode = inject('$chakraColorMode') as ColorMode
14+
const colorMode = ref(_colorMode)
15+
16+
const toggleColorMode = () => {
17+
colorMode.value = 'light'
18+
? (colorMode.value = 'dark')
19+
: (colorMode.value = 'light')
20+
}
21+
22+
return {
23+
colorMode,
24+
toggleColorMode,
25+
}
26+
}
27+
28+
/** Single hook to provide theme and color mode values */
29+
export const useChakra = () => {
30+
const theme = useTheme()
31+
const { colorMode } = useColorMode()
32+
return {
33+
theme,
34+
colorMode,
35+
}
36+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { computed, ComputedRef, inject, provide, ref } from 'vue'
2+
3+
import { SystemStyleObject } from '@chakra-ui/styled-system'
4+
import { ChakraComponentName, ComponentThemeConfig } from '@chakra-ui/vue-theme'
5+
import { ThemingProps } from '../system.types'
6+
import { DeepPartial } from '../system.utils'
7+
import { filterUndefined, get, mergeWith, runIfFn } from '@chakra-ui/vue-utils'
8+
import { useChakra } from './use-chakra'
9+
10+
export type AllThemedComponents = ChakraComponentName &
11+
keyof Record<string, any>
12+
13+
/**
14+
* This type allows us to loosely type values for consumer provided
15+
* components in the theme config.
16+
*
17+
* @note At the time of writing this, I'm not sure whether this should
18+
* be loosely typed with a {DeepComponentThemeConfig} or should be strictly
19+
* typed with as the {ComponentThemeConfig}
20+
*/
21+
export type DeepComponentThemeConfig = DeepPartial<ComponentThemeConfig>
22+
23+
export function useStyleConfig(
24+
themeKey: AllThemedComponents,
25+
themingProps: ThemingProps,
26+
options: { isMultiPart: true },
27+
userStyleConfig?: DeepComponentThemeConfig
28+
): ComputedRef<Record<string, SystemStyleObject>>
29+
30+
export function useStyleConfig(
31+
themeKey: AllThemedComponents,
32+
themingProps?: ThemingProps,
33+
options?: { isMultiPart?: boolean },
34+
userStyleConfig?: DeepComponentThemeConfig
35+
): ComputedRef<SystemStyleObject>
36+
37+
export function useStyleConfig(
38+
themeKey: any,
39+
themingProps: any,
40+
options: any = {},
41+
userStyleConfig?: any
42+
) {
43+
const { theme, colorMode } = useChakra()
44+
const themeStyleConfig = get(theme, `components.${themeKey}`)
45+
46+
const styleConfig = userStyleConfig || themeStyleConfig
47+
48+
const mergedProps = mergeWith(
49+
{ theme, colorMode },
50+
styleConfig?.defaultProps ?? {},
51+
filterUndefined(themingProps)
52+
)
53+
54+
return computed(() => {
55+
const baseStyles = runIfFn(styleConfig.baseStyle ?? {}, mergedProps)
56+
const variants = runIfFn(
57+
styleConfig.variants?.[mergedProps.variant] ?? {},
58+
mergedProps
59+
)
60+
61+
const sizes = runIfFn(
62+
styleConfig.sizes?.[mergedProps.size] ?? {},
63+
mergedProps
64+
)
65+
66+
type ComponentStyles = SystemStyleObject | Record<string, SystemStyleObject>
67+
const styles = mergeWith({}, baseStyles, sizes, variants) as ComponentStyles
68+
69+
if (options.isMultiPart && styleConfig.parts) {
70+
styleConfig.parts.forEach((part: keyof ComponentStyles) => {
71+
// @ts-expect-error
72+
styles[part] = styles[part] ?? {}
73+
})
74+
}
75+
76+
return styles
77+
})
78+
}
79+
80+
export function useMultiStyleConfig(
81+
themeKey: AllThemedComponents,
82+
themingProps: any
83+
) {
84+
return useStyleConfig(themeKey, themingProps, { isMultiPart: true })
85+
}
86+
87+
/** Provides Chakra Multi-parted component styles to descendants */
88+
export const provideComponentStyles = (
89+
component: AllThemedComponents,
90+
styles: SystemStyleObject
91+
) => {
92+
provide<SystemStyleObject>(`$chakra${component}Styles`, styles)
93+
}
94+
95+
/** Injects Chakra Multi-parted component styles from ancestor */
96+
export const useComponentStyles = (component: AllThemedComponents) => {
97+
return inject<SystemStyleObject>(`$chakra${component}Styles`)
98+
}

0 commit comments

Comments
 (0)