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

Commit 911cf58

Browse files
committed
feat(system): provide overrides api for components
1 parent f2c7799 commit 911cf58

File tree

10 files changed

+195
-25
lines changed

10 files changed

+195
-25
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"c-button": "yarn workspace @chakra-ui/c-button",
2626
"c-icon": "yarn workspace @chakra-ui/c-icon",
2727
"system": "yarn workspace @chakra-ui/vue-system",
28+
"utils": "yarn workspace @chakra-ui/vue-utils",
2829
"theme": "yarn workspace @chakra-ui/vue-theme",
2930
"nuxt": "yarn workspace @chakra-ui/nuxt-next",
3031
"test-utils": "yarn workspace @chakra-ui/vue-test-utils",

packages/c-alert/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"dependencies": {
2727
"@chakra-ui/styled-system": "^1.4.1",
2828
"@chakra-ui/vue-system": "*",
29+
"@chakra-ui/vue-utils": "*",
2930
"@chakra-ui/c-icon": "*"
3031
}
3132
}

packages/c-button/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
},
2525
"dependencies": {
2626
"@chakra-ui/styled-system": "^1.4.1",
27-
"@chakra-ui/vue-system": "*"
27+
"@chakra-ui/vue-system": "*",
28+
"@chakra-ui/vue-utils": "*"
2829
}
2930
}

packages/c-button/src/button-group.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { computed, defineComponent, h, PropType } from 'vue'
2+
import {
3+
SystemCSSProperties,
4+
SystemStyleObject,
5+
} from '@chakra-ui/styled-system'
6+
import { chakra, ThemingProps } from '@chakra-ui/vue-system'
7+
import { ComponentThemeConfig } from '@chakra-ui/vue-theme'
8+
import { createContext } from '@chakra-ui/vue-utils'
9+
10+
export interface ButtonGroupProps extends ThemingProps {
11+
/**
12+
* If `true`, the borderRadius of button that are direct children will be altered
13+
* to look flushed together
14+
*/
15+
isAttached?: boolean
16+
/**
17+
* If `true`, all wrapped button will be disabled
18+
*/
19+
isDisabled?: boolean
20+
/**
21+
* The spacing between the buttons
22+
* @default '0.5rem'
23+
* @type SystemProps["marginRight"]
24+
*/
25+
spacing?: SystemCSSProperties['marginRight']
26+
}
27+
28+
const props = {
29+
isAttached: Boolean as PropType<ButtonGroupProps['isAttached']>,
30+
isDisabled: Boolean as PropType<ButtonGroupProps['isDisabled']>,
31+
spacing: [String, Number, Array] as PropType<ButtonGroupProps['spacing']>,
32+
variant: {
33+
type: String as PropType<string>,
34+
default: 'solid',
35+
},
36+
size: {
37+
type: String as PropType<string>,
38+
default: 'sm',
39+
},
40+
colorScheme: String as PropType<string>,
41+
styleConfig: String as PropType<ComponentThemeConfig>,
42+
}
43+
44+
interface ButtonGroupContext extends ThemingProps {
45+
isDisabled?: boolean
46+
}
47+
48+
const [ButtonGroupProvider, useButtonGroup] = createContext<ButtonGroupContext>(
49+
{
50+
strict: false,
51+
name: 'ButtonGroupContext',
52+
}
53+
)
54+
55+
export const CButtonGroup = defineComponent({
56+
name: 'CButtonGroup',
57+
props,
58+
setup(props, { slots }) {
59+
ButtonGroupProvider({
60+
size: props.size,
61+
colorScheme: props.colorScheme,
62+
variant: props.variant,
63+
isDisabled: props.isDisabled,
64+
})
65+
66+
const styles = computed(() => {
67+
let groupStyles: SystemStyleObject = {
68+
display: 'inline-flex',
69+
}
70+
71+
if (props.isAttached) {
72+
groupStyles = {
73+
...groupStyles,
74+
'> *:first-of-type:not(:last-of-type)': { borderRightRadius: 0 },
75+
'> *:not(:first-of-type):not(:last-of-type)': { borderRadius: 0 },
76+
'> *:not(:first-of-type):last-of-type': { borderLeftRadius: 0 },
77+
}
78+
} else {
79+
groupStyles = {
80+
...groupStyles,
81+
'& > *:not(style) ~ *:not(style)': { marginLeft: props.spacing },
82+
}
83+
}
84+
85+
return groupStyles
86+
})
87+
88+
return () => h(chakra.div)
89+
},
90+
})

packages/c-button/src/button.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,10 @@ import {
99
SystemCSSProperties,
1010
SystemStyleObject,
1111
} from '@chakra-ui/styled-system'
12-
import { Colors } from '@chakra-ui/vue-theme/dist/types/foundations/colors'
1312
import { ComponentThemeConfig } from '@chakra-ui/vue-theme'
1413
import { dataAttr } from '@chakra-ui/vue-utils'
1514

1615
type ButtonTypes = 'button' | 'reset' | 'submit'
17-
export type ButtonSizes = 'xs' | 'sm' | 'md' | 'lg'
18-
export type ButtonVariants =
19-
| 'subtle'
20-
| 'solid'
21-
| 'outline'
22-
| 'ghost'
23-
| 'link'
24-
| string
2516

2617
const props = {
2718
as: {
@@ -36,13 +27,13 @@ const props = {
3627
type: String as PropType<ButtonTypes>,
3728
leftIcon: String as PropType<string>,
3829
rightIcon: String as PropType<string>,
39-
colorScheme: String as PropType<keyof Colors>,
30+
colorScheme: String as PropType<string>,
4031
variant: {
41-
type: String as PropType<ButtonVariants>,
32+
type: String as PropType<string>,
4233
default: 'solid',
4334
},
4435
size: {
45-
type: String as PropType<ButtonSizes>,
36+
type: String as PropType<string>,
4637
default: 'md',
4738
},
4839
styleConfig: String as PropType<ComponentThemeConfig>,

packages/system/src/chakra.ts

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,46 @@
1-
import { DefineComponent, defineComponent, h } from 'vue'
2-
import { css } from '@chakra-ui/styled-system'
3-
import theme from '@chakra-ui/vue-theme'
4-
import { cx } from '@chakra-ui/vue-utils'
5-
import { css as _css } from '@emotion/css'
1+
import { computed, DefineComponent, defineComponent, h, PropType } from 'vue'
2+
import {
3+
css,
4+
ResponsiveValue,
5+
SystemProps,
6+
SystemStyleObject,
7+
} from '@chakra-ui/styled-system'
8+
import { cx, memoizedGet as get, objectAssign } from '@chakra-ui/vue-utils'
9+
import { css as _css, CSSObject } from '@emotion/css'
610
import { extractStyleAttrs } from './system.attrs'
711
import { domElements, DOMElements } from './system.utils'
12+
import { useTheme } from './composables/use-chakra'
13+
14+
interface StyleResolverProps extends SystemProps {
15+
__css?: SystemStyleObject
16+
sx?: SystemStyleObject
17+
css?: CSSObject
18+
noOfLines?: ResponsiveValue<number>
19+
isTruncated?: boolean
20+
layerStyle?: string
21+
textStyle?: string
22+
apply?: ResponsiveValue<string>
23+
componentName?: String
24+
}
25+
26+
interface ChakraFactoryOptions extends StyleResolverProps {
27+
label?: string
28+
baseStyle?: SystemStyleObject
29+
}
30+
31+
const chakraProps = {
32+
__css: Object as PropType<StyleResolverProps['__css']>,
33+
sx: Object as PropType<StyleResolverProps['sx']>,
34+
css: Object as PropType<StyleResolverProps['css']>,
35+
noOfLines: Number as PropType<StyleResolverProps['noOfLines']>,
36+
baseStyle: Object as PropType<ChakraFactoryOptions['baseStyle']>,
37+
isTruncated: Boolean as PropType<StyleResolverProps['isTruncated']>,
38+
layerStyle: String as PropType<StyleResolverProps['layerStyle']>,
39+
textStyle: String as PropType<StyleResolverProps['textStyle']>,
40+
apply: String as PropType<StyleResolverProps['apply']>,
41+
}
42+
43+
export type ChakraBaseComponentProps = typeof chakraProps
844

945
/**
1046
* Creates a Chakra UI Vue component
@@ -14,24 +50,70 @@ import { domElements, DOMElements } from './system.utils'
1450
// @ts-expect-error
1551
export const chakra: IChakraFactory = (
1652
tag: DOMElements,
17-
componentName?: string
53+
options?: ChakraFactoryOptions
1854
): DefineComponent => {
1955
return defineComponent({
2056
inheritAttrs: false,
57+
props: chakraProps,
2158
setup(props, { slots, attrs }) {
59+
const theme = useTheme()
2260
// Separate component style attributes from raw HTML attributes
61+
62+
const layerStyle = computed(() => props.layerStyle || options?.layerStyle)
63+
const textStyle = computed(() => props.textStyle || options?.textStyle)
64+
const baseStyle = computed(() => props.baseStyle || options?.baseStyle)
65+
const noOfLines = computed(() => props.noOfLines || options?.noOfLines)
66+
const isTruncated = computed(
67+
() => props.isTruncated || options?.isTruncated
68+
)
69+
const __css = computed(() => props.__css || options?.__css)
70+
const sx = computed(() => props.sx || options?.sx)
71+
const apply = computed(() => props.apply || options?.apply)
72+
2373
const { class: inheritedClass, ...rest } = attrs
24-
const { styles, attrs: _attrs } = extractStyleAttrs(rest)
25-
const className = _css(css(styles)({ theme }))
26-
const _componentName = componentName ? `chakra-${componentName}` : ''
74+
const _layerStyle = get(theme, `layerStyles.${layerStyle.value}`, {})
75+
const _textStyle = get(theme, `textStyles.${textStyle.value}`, {})
76+
const { styles, attrs: elementAttributes } = extractStyleAttrs(rest)
77+
78+
let truncateStyle: any = {}
79+
if (noOfLines.value != null) {
80+
truncateStyle = {
81+
overflow: 'hidden',
82+
textOverflow: 'ellipsis',
83+
display: '-webkit-box',
84+
WebkitBoxOrient: 'vertical',
85+
WebkitLineClamp: noOfLines.value,
86+
}
87+
} else if (isTruncated.value) {
88+
truncateStyle = {
89+
overflow: 'hidden',
90+
textOverflow: 'ellipsis',
91+
whiteSpace: 'nowrap',
92+
}
93+
}
94+
95+
const finalStyles = objectAssign(
96+
{},
97+
__css.value,
98+
baseStyle.value,
99+
{ apply: apply.value },
100+
_layerStyle,
101+
_textStyle,
102+
truncateStyle,
103+
styles,
104+
sx.value
105+
)
106+
107+
const className = _css(css(finalStyles)({ theme }))
108+
const _componentName = options?.label ? `chakra-${options?.label}` : ''
27109

28110
return () =>
29111
h(
30112
tag,
31113
{
32114
class: cx(inheritedClass, _componentName, className),
33115
...props,
34-
..._attrs,
116+
...elementAttributes,
35117
},
36118
slots
37119
)

packages/utils/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
"build": "concurrently yarn:build:*",
1414
"build:esm": "cross-env BABEL_ENV=esm babel src --root-mode upward --extensions .ts -d dist/esm --source-maps",
1515
"build:cjs": "cross-env BABEL_ENV=cjs babel src --root-mode upward --extensions .ts -d dist/cjs --source-maps",
16-
"build:types": "tsc --emitDeclarationOnly --declaration --declarationDir dist/types"
16+
"build:types": "tsc --emitDeclarationOnly --declaration --declarationDir dist/types",
17+
"watch": "concurrently yarn:watch:*",
18+
"watch:esm": "cross-env BABEL_ENV=esm babel src --root-mode upward --extensions .ts -d dist/esm --source-maps --watch",
19+
"watch:cjs": "cross-env BABEL_ENV=cjs babel src --root-mode upward --extensions .ts -d dist/cjs --source-maps --watch",
20+
"watch:types": "tsc --emitDeclarationOnly --declaration --declarationDir dist/types --watch"
1721
},
1822
"dependencies": {
1923
"@types/lodash.mergewith": "4.6.6",

playground/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8">
5-
<link rel="icon" href="/favicon.ico" />
5+
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0">
77
<title>Chakra UI Vue Next - Components playground</title>
88
</head>

playground/public/chakra.png

96.9 KB
Loading

playground/public/favicon.ico

0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)