Skip to content

Commit d236e21

Browse files
committed
refactor(style-context): classname
1 parent 0019184 commit d236e21

File tree

14 files changed

+199
-167
lines changed

14 files changed

+199
-167
lines changed

.changeset/cyan-buckets-remain.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@pandacss/generator': patch
3+
---
4+
5+
- **createStyleContext**: Ensure the `defaultProps.className` is applied correctly when no explicit `class` prop is
6+
provided

packages/generator/src/artifacts/preact-jsx/create-style-context.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ export function generatePreactCreateStyleContext(ctx: Context) {
6161
const slotStyles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
6262
slotStyles._classNameMap = svaFn.classNameMap
6363
64-
const resolvedProps = getResolvedProps(restProps, slotStyles[slot])
64+
const propsWithClass = { ...restProps, className: restProps.className ?? options?.defaultProps?.className }
65+
const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
6566
return createElement(StyleContext.Provider, {
6667
value: slotStyles,
6768
children: createElement(StyledComponent, {
@@ -84,7 +85,8 @@ export function generatePreactCreateStyleContext(ctx: Context) {
8485
const WithContext = forwardRef((props, ref) => {
8586
const slotStyles = useContext(StyleContext)
8687
87-
const resolvedProps = getResolvedProps(props, slotStyles[slot])
88+
const propsWithClass = { ...props, className: props.className ?? options?.defaultProps?.className }
89+
const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
8890
return createElement(StyledComponent, {
8991
...resolvedProps,
9092
className: cx(resolvedProps.className, slotStyles._classNameMap[slot]),
@@ -144,7 +146,8 @@ export function generatePreactCreateStyleContext(ctx: Context) {
144146
) => StyleContextProvider<T, R>
145147
withContext: <T extends ElementType>(
146148
Component: T,
147-
slot: InferSlot<R>
149+
slot: InferSlot<R>,
150+
options?: JsxFactoryOptions<ComponentProps<T>>
148151
) => StyleContextConsumer<T>
149152
}
150153

packages/generator/src/artifacts/react-jsx/create-style-context.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ export function generateReactCreateStyleContext(ctx: Context) {
6060
const slotStyles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
6161
slotStyles._classNameMap = svaFn.classNameMap
6262
63-
const resolvedProps = getResolvedProps(restProps, slotStyles[slot])
63+
const propsWithClass = { ...restProps, className: restProps.className ?? options?.defaultProps?.className }
64+
const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
6465
return createElement(StyleContext.Provider, {
6566
value: slotStyles,
6667
children: createElement(StyledComponent, {
@@ -83,7 +84,8 @@ export function generateReactCreateStyleContext(ctx: Context) {
8384
const WithContext = forwardRef((props, ref) => {
8485
const slotStyles = useContext(StyleContext)
8586
86-
const resolvedProps = getResolvedProps(props, slotStyles[slot])
87+
const propsWithClass = { ...props, className: props.className ?? options?.defaultProps?.className }
88+
const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
8789
return createElement(StyledComponent, {
8890
...resolvedProps,
8991
className: cx(resolvedProps.className, slotStyles._classNameMap[slot]),

packages/generator/src/artifacts/solid-jsx/create-style-context.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ export function generateSolidCreateStyleContext(ctx: Context) {
7676
const slotStyles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
7777
slotStyles._classNameMap = svaFn.classNameMap
7878
79-
const resolvedProps = getResolvedProps(restProps, slotStyles[slot])
79+
const propsWithClass = { ...restProps, class: restProps.class ?? options?.defaultProps?.class }
80+
const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
8081
resolvedProps.class = cx(resolvedProps.class, slotStyles._classNameMap[slot])
8182
8283
return { slotStyles, resolvedProps }
@@ -103,14 +104,15 @@ export function generateSolidCreateStyleContext(ctx: Context) {
103104
return WithProvider
104105
}
105106
106-
const withContext = (Component, slot) => {
107-
const StyledComponent = ${factoryName}(Component)
107+
const withContext = (Component, slot, options) => {
108+
const StyledComponent = ${factoryName}(Component, {}, options)
108109
109110
const WithContext = (props) => {
110111
const slotStyles = useContext(StyleContext)
111112
const finalProps = createMemo(() => {
112-
const resolvedProps = getResolvedProps(props, slotStyles[slot])
113-
resolvedProps.class = cx(resolvedProps.class, resolvedProps.className, slotStyles._classNameMap?.[slot])
113+
const propsWithClass = { ...props, class: props.class ?? options?.defaultProps?.class }
114+
const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
115+
resolvedProps.class = cx(resolvedProps.class, slotStyles._classNameMap?.[slot])
114116
return resolvedProps
115117
})
116118

packages/generator/src/artifacts/vue-jsx/create-style-context.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ export function generateVueCreateStyleContext(ctx: Context) {
2121
const { unstyled, ...restProps } = props
2222
if (unstyled) return restProps
2323
if (isConfigRecipe) {
24-
return { ...restProps, className: cx(slotStyles, restProps.className) }
24+
return { ...restProps, class: cx(slotStyles, restProps.class) }
2525
}
2626
${outdent.string(
2727
match(ctx.config.jsxStyleProps)
2828
.with('all', () => `return { ...slotStyles, ...restProps }`)
2929
.with('minimal', () => `return { ...restProps, css: css.raw(slotStyles, restProps.css) }`)
30-
.with('none', () => `return { ...restProps, className: cx(css(slotStyles), restProps.className) }`)
30+
.with('none', () => `return { ...restProps, class: cx(css(slotStyles), restProps.class) }`)
3131
.otherwise(() => `return restProps`),
3232
)}
3333
}
@@ -61,8 +61,13 @@ export function generateVueCreateStyleContext(ctx: Context) {
6161
6262
const WithProvider = defineComponent({
6363
props: ["unstyled", ...svaFn.variantKeys],
64+
inheritAttrs: false,
6465
setup(inProps, { slots, attrs }) {
65-
const props = computed(() => Object.assign({}, inProps, attrs))
66+
const props = computed(() => {
67+
const propsWithClass = { ...inProps, ...attrs }
68+
propsWithClass.class = propsWithClass.class ?? options?.defaultProps?.class
69+
return propsWithClass
70+
})
6671
const res = computed(() => {
6772
const [variantProps, restProps] = svaFn.splitVariantProps(props.value)
6873
return { variantProps, restProps }
@@ -90,16 +95,22 @@ export function generateVueCreateStyleContext(ctx: Context) {
9095
return WithProvider
9196
}
9297
93-
const withContext = (Component, slot) => {
94-
const StyledComponent = ${factoryName}(Component)
98+
const withContext = (Component, slot, options) => {
99+
const StyledComponent = ${factoryName}(Component, {}, options)
95100
96101
const WithContext = defineComponent({
97102
props: ["unstyled"],
98-
setup(props, { slots, attrs }) {
103+
inheritAttrs: false,
104+
setup(inProps, { slots, attrs }) {
105+
const props = computed(() => {
106+
const propsWithClass = { ...inProps, ...attrs }
107+
propsWithClass.class = propsWithClass.class ?? options?.defaultProps?.class
108+
return propsWithClass
109+
})
99110
const slotStyles = inject(StyleContext)
100111
101112
return () => {
102-
const resolvedProps = getResolvedProps(props, slotStyles.value[slot])
113+
const resolvedProps = getResolvedProps(props.value, slotStyles.value[slot])
103114
resolvedProps.class = cx(resolvedProps.class, slotStyles.value._classNameMap[slot], attrs.class)
104115
return h(StyledComponent, resolvedProps, slots)
105116
}
@@ -129,6 +140,12 @@ export function generateVueCreateStyleContext(ctx: Context) {
129140
unstyled?: boolean
130141
}
131142
143+
// Add v-model support types
144+
interface VModelProps {
145+
modelValue?: any
146+
'onUpdate:modelValue'?: (value: any) => void
147+
}
148+
132149
type SvaFn<S extends string = any> = SlotRecipeRuntimeFn<S, any>
133150
interface SlotRecipeFn {
134151
__type: any
@@ -149,11 +166,11 @@ export function generateVueCreateStyleContext(ctx: Context) {
149166
: never
150167
151168
type StyleContextProvider<T extends ElementType, R extends SlotRecipe> = FunctionalComponent<
152-
JsxHTMLProps<ComponentProps<T> & UnstyledProps, Assign<RecipeVariantProps<R>, JsxStyleProps>>
169+
JsxHTMLProps<ComponentProps<T> & UnstyledProps & VModelProps, Assign<RecipeVariantProps<R>, JsxStyleProps>>
153170
>
154171
155172
type StyleContextConsumer<T extends ElementType> = FunctionalComponent<
156-
JsxHTMLProps<ComponentProps<T> & UnstyledProps, JsxStyleProps>
173+
JsxHTMLProps<ComponentProps<T> & UnstyledProps & VModelProps, JsxStyleProps>
157174
>
158175
159176
export interface StyleContext<R extends SlotRecipe> {

packages/studio/styled-system/jsx/create-style-context.mjs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ export function createStyleContext(recipe) {
4747
const slotStyles = isConfigRecipe ? svaFn(variantProps) : svaFn.raw(variantProps)
4848
slotStyles._classNameMap = svaFn.classNameMap
4949

50-
const resolvedProps = getResolvedProps(restProps, slotStyles[slot])
50+
const propsWithClass = { ...restProps, className: restProps.className ?? options?.defaultProps?.className }
51+
const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
5152
return createElement(StyleContext.Provider, {
5253
value: slotStyles,
5354
children: createElement(StyledComponent, {
@@ -70,7 +71,8 @@ export function createStyleContext(recipe) {
7071
const WithContext = forwardRef((props, ref) => {
7172
const slotStyles = useContext(StyleContext)
7273

73-
const resolvedProps = getResolvedProps(props, slotStyles[slot])
74+
const propsWithClass = { ...props, className: props.className ?? options?.defaultProps?.className }
75+
const resolvedProps = getResolvedProps(propsWithClass, slotStyles[slot])
7476
return createElement(StyledComponent, {
7577
...resolvedProps,
7678
className: cx(resolvedProps.className, slotStyles._classNameMap[slot]),

sandbox/next-js-pages/src/components/custom.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,5 @@ const _custom = sva({
3535

3636
const { withProvider, withContext } = createStyleContext(custom)
3737

38-
export const Root = withProvider('div', 'root')
39-
export const Label = withContext('label', 'label')
38+
export const Root = withProvider('div', 'root', { defaultProps: { className: 'group' } })
39+
export const Label = withContext('label', 'label', { defaultProps: { className: 'group__item' } })
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import { css } from '../../styled-system/css'
2+
import { stack } from '../../styled-system/patterns'
3+
4+
export const RadialGradient = () => {
5+
return (
6+
<div className={stack({ fontSize: '2xl', fontWeight: 'bold', padding: '4' })}>
7+
<div
8+
className={css({
9+
boxSize: '20',
10+
rounded: 'full',
11+
bgRadial: 'in srgb',
12+
gradientFrom: 'pink.400',
13+
gradientFromPosition: '40%',
14+
gradientTo: 'fuchsia.700',
15+
})}
16+
/>
17+
<div
18+
className={css({
19+
boxSize: '20',
20+
rounded: 'full',
21+
bgRadial: 'at 50% 75%',
22+
gradientFrom: 'sky.200',
23+
gradientVia: 'blue.400',
24+
gradientTo: 'indigo.900',
25+
gradientToPosition: '90%',
26+
})}
27+
/>
28+
<div
29+
className={css({
30+
boxSize: '20',
31+
rounded: 'full',
32+
bgRadial: 'at 25% 25%',
33+
gradientFrom: 'white',
34+
gradientTo: 'zinc.900',
35+
gradientToPosition: '75%',
36+
})}
37+
/>
38+
</div>
39+
)
40+
}
41+
42+
export const LinearGradient = () => {
43+
return (
44+
<div>
45+
<div className={stack({ fontSize: '2xl', fontWeight: 'bold', padding: '4' })}>
46+
<div
47+
className={css({
48+
height: '14',
49+
bgLinear: 'to-r',
50+
gradientFrom: 'cyan.500',
51+
gradientTo: 'blue.500',
52+
})}
53+
/>
54+
<div
55+
className={css({
56+
height: '14',
57+
bgLinear: 'to-t',
58+
gradientFrom: 'sky.500',
59+
gradientTo: 'indigo.500',
60+
})}
61+
/>
62+
<div
63+
className={css({
64+
height: '14',
65+
bgLinear: 'to-bl',
66+
gradientFrom: 'violet.500',
67+
gradientTo: 'fuchsia.500',
68+
})}
69+
/>
70+
<div
71+
className={css({
72+
height: '14',
73+
bgLinear: '65deg',
74+
gradientFrom: 'purple.500',
75+
gradientTo: 'pink.500',
76+
})}
77+
/>
78+
</div>
79+
</div>
80+
)
81+
}
82+
83+
export const ConicGradient = () => {
84+
return (
85+
<div className={stack({ fontSize: '2xl', fontWeight: 'bold', padding: '4' })}>
86+
<div
87+
className={css({
88+
boxSize: '24',
89+
rounded: 'full',
90+
bgConic: 'in srgb',
91+
gradientFrom: 'blue.600',
92+
gradientTo: 'sky.400',
93+
gradientToPosition: '50%',
94+
})}
95+
/>
96+
<div
97+
className={css({
98+
boxSize: '24',
99+
rounded: 'full',
100+
bgConic: 'from 180deg',
101+
gradientFrom: 'blue.600',
102+
gradientVia: 'blue.50',
103+
gradientTo: 'blue.600',
104+
})}
105+
/>
106+
<div
107+
className={css({
108+
boxSize: '24',
109+
rounded: 'full',
110+
bgConic: 'in oklch decreasing hue',
111+
gradientFrom: 'violet.700',
112+
gradientVia: 'lime.300',
113+
gradientTo: 'violet.700',
114+
})}
115+
/>
116+
</div>
117+
)
118+
}

0 commit comments

Comments
 (0)