Skip to content

Commit 50dcd37

Browse files
committed
feat: add unstyled prop to styled factory
1 parent 5409ea9 commit 50dcd37

File tree

16 files changed

+179
-29
lines changed

16 files changed

+179
-29
lines changed

.changeset/grumpy-cobras-win.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,18 @@
33
---
44

55
- Add reset styles for `::selection` pseudo element that maps to `var(--global-color-selection, revert)`.
6+
- Add support for `unstyled` prop in the `styled` factory. This makes it possible to opt out recipe styles as needed.
7+
8+
```tsx
9+
const Notice = styled('div', {
10+
base: {
11+
bg: 'red',
12+
color: 'white',
13+
},
14+
})
15+
16+
// This will remove the recipe styles and only apply the inline styles
17+
<Notice unstyled bg="pink" color="green">
18+
Hello
19+
</Notice>
20+
```

packages/generator/src/artifacts/preact-jsx/jsx.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export function generatePreactJsxFactory(ctx: Context) {
3636
const __base__ = Dynamic.__base__ || Dynamic
3737
3838
const ${componentName} = /* @__PURE__ */ forwardRef(function ${componentName}(props, ref) {
39-
const { as: Element = __base__, children, ...restProps } = props
39+
const { as: Element = __base__, unstyled, children, ...restProps } = props
4040
4141
4242
const combinedProps = useMemo(() => Object.assign({}, defaultProps, restProps), [restProps])
@@ -57,7 +57,13 @@ export function generatePreactJsxFactory(ctx: Context) {
5757
return cx(css(cvaStyles, propStyles, cssStyles), combinedProps.class, combinedProps.className)
5858
}
5959
60-
const classes = configOrCva.__recipe__ ? recipeClass : cvaClass
60+
const classes = () => {
61+
if (unstyled) {
62+
const { css: cssStyles, ...propStyles } = styleProps
63+
return cx(css(propStyles, cssStyles), combinedProps.class, combinedProps.className)
64+
}
65+
return configOrCva.__recipe__ ? recipeClass() : cvaClass()
66+
}
6167
6268
return h(Element, {
6369
...forwardedProps,

packages/generator/src/artifacts/preact-jsx/types.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,15 @@ interface Dict {
2323
[k: string]: unknown
2424
}
2525
26+
export interface UnstyledProps {
27+
/**
28+
* Whether to remove recipe styles
29+
*/
30+
unstyled?: boolean | undefined
31+
}
32+
2633
export interface ${componentName}<T extends ElementType, P extends Dict = {}> {
27-
(props: JsxHTMLProps<ComponentProps<T>, Assign<JsxStyleProps, P>>): JSX.Element
34+
(props: JsxHTMLProps<ComponentProps<T> & UnstyledProps, Assign<JsxStyleProps, P>>): JSX.Element
2835
displayName?: string
2936
}
3037
@@ -39,7 +46,7 @@ export interface JsxFactoryOptions<TProps extends Dict> {
3946
forwardProps?: string[]
4047
}
4148
42-
export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T>, P>
49+
export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T> & UnstyledProps, P>
4350
4451
export type JsxElement<T extends ElementType, P extends Dict> = T extends ${componentName}<infer A, infer B>
4552
? ${componentName}<A, Pretty<DistributiveUnion<P, B>>>
@@ -60,7 +67,7 @@ export type JsxElements = {
6067
6168
export type ${upperName} = JsxFactory & JsxElements
6269
63-
export type ${typeName}<T extends ElementType> = JsxHTMLProps<ComponentProps<T>, JsxStyleProps>
70+
export type ${typeName}<T extends ElementType> = JsxHTMLProps<ComponentProps<T> & UnstyledProps, JsxStyleProps>
6471
6572
export type ${variantName}<T extends ${componentName}<any, any>> = T extends ${componentName}<any, infer Props> ? Props : never
6673
`,

packages/generator/src/artifacts/qwik-jsx/jsx.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function generateQwikJsxFactory(ctx: Context) {
3434
const __base__ = Dynamic.__base__ || Dynamic
3535
3636
const ${componentName} = function ${componentName}(props) {
37-
const { as: Element = __base__, children, className, ...restProps } = props
37+
const { as: Element = __base__, unstyled, children, className, ...restProps } = props
3838
3939
const combinedProps = Object.assign({}, defaultProps, restProps)
4040
@@ -55,7 +55,13 @@ export function generateQwikJsxFactory(ctx: Context) {
5555
return cx(css(cvaStyles, propStyles, cssStyles), combinedProps.class, className)
5656
}
5757
58-
const classes = configOrCva.__recipe__ ? recipeClass : cvaClass
58+
const classes = () => {
59+
if (unstyled) {
60+
const { css: cssStyles, ...propStyles } = styleProps
61+
return cx(css(propStyles, cssStyles), combinedProps.class, className)
62+
}
63+
return configOrCva.__recipe__ ? recipeClass() : cvaClass()
64+
}
5965
6066
return h(Element, {
6167
...forwardedProps,

packages/generator/src/artifacts/qwik-jsx/types.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ interface Dict {
2929
[k: string]: unknown
3030
}
3131
32-
export interface ${componentName}<T extends ElementType, P extends Dict = {}> extends Component<Assign<ComponentProps<T>, Assign<PatchedHTMLProps, Assign<JsxStyleProps, P>>>> {}
32+
export interface UnstyledProps {
33+
/**
34+
* Whether to remove recipe styles
35+
*/
36+
unstyled?: boolean | undefined
37+
}
38+
39+
export interface ${componentName}<T extends ElementType, P extends Dict = {}> extends Component<Assign<ComponentProps<T> & UnstyledProps, Assign<PatchedHTMLProps, Assign<JsxStyleProps, P>>>> {}
3340
3441
interface RecipeFn {
3542
__type: any
@@ -42,7 +49,7 @@ export interface JsxFactoryOptions<TProps extends Dict> {
4249
forwardProps?: string[]
4350
}
4451
45-
export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T>, P>;
52+
export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T> & UnstyledProps, P>;
4653
4754
export type JsxElement<T extends ElementType, P extends Dict> = T extends ${componentName}<infer A, infer B>
4855
? ${componentName}<A, Pretty<DistributiveUnion<P, B>>>
@@ -63,7 +70,7 @@ export type JsxElements = {
6370
6471
export type ${upperName} = JsxFactory & JsxElements
6572
66-
export type ${typeName}<T extends ElementType> = Assign<ComponentProps<T>, JsxStyleProps>
73+
export type ${typeName}<T extends ElementType> = Assign<ComponentProps<T> & UnstyledProps, JsxStyleProps>
6774
6875
export type ${variantName}<T extends ${componentName}<any, any>> = T extends ${componentName}<any, infer Props> ? Props : never
6976
`,

packages/generator/src/artifacts/react-jsx/jsx.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function generateReactJsxFactory(ctx: Context) {
3434
const __base__ = Dynamic.__base__ || Dynamic
3535
3636
const ${componentName} = /* @__PURE__ */ forwardRef(function ${componentName}(props, ref) {
37-
const { as: Element = __base__, children, ...restProps } = props
37+
const { as: Element = __base__, unstyled, children, ...restProps } = props
3838
3939
const combinedProps = useMemo(() => Object.assign({}, defaultProps, restProps), [restProps])
4040
@@ -54,7 +54,13 @@ export function generateReactJsxFactory(ctx: Context) {
5454
return cx(css(cvaStyles, propStyles, cssStyles), combinedProps.className)
5555
}
5656
57-
const classes = configOrCva.__recipe__ ? recipeClass : cvaClass
57+
const classes = () => {
58+
if (unstyled) {
59+
const { css: cssStyles, ...propStyles } = styleProps
60+
return cx(css(propStyles, cssStyles), combinedProps.className)
61+
}
62+
return configOrCva.__recipe__ ? recipeClass() : cvaClass()
63+
}
5864
5965
return createElement(Element, {
6066
ref,

packages/generator/src/artifacts/react-jsx/types.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,19 @@ interface Dict {
2121
[k: string]: unknown
2222
}
2323
24+
export interface UnstyledProps {
25+
/**
26+
* Whether to remove recipe styles
27+
*/
28+
unstyled?: boolean | undefined
29+
}
30+
2431
export type ComponentProps<T extends ElementType> = DistributiveOmit<ComponentPropsWithoutRef<T>, 'ref'> & {
2532
ref?: Ref<ElementRef<T>>
2633
}
2734
2835
export interface ${componentName}<T extends ElementType, P extends Dict = {}> {
29-
(props: JsxHTMLProps<ComponentProps<T>, Assign<JsxStyleProps, P>>): JSX.Element
36+
(props: JsxHTMLProps<ComponentProps<T> & UnstyledProps, Assign<JsxStyleProps, P>>): JSX.Element
3037
displayName?: string
3138
}
3239
@@ -41,7 +48,7 @@ interface JsxFactoryOptions<TProps extends Dict> {
4148
forwardProps?: string[]
4249
}
4350
44-
export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T>, P>;
51+
export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T> & UnstyledProps, P>;
4552
4653
export type JsxElement<T extends ElementType, P extends Dict> = T extends ${componentName}<infer A, infer B>
4754
? ${componentName}<A, Pretty<DistributiveUnion<P, B>>>
@@ -62,7 +69,7 @@ export type JsxElements = {
6269
6370
export type ${upperName} = JsxFactory & JsxElements
6471
65-
export type ${typeName}<T extends ElementType> = JsxHTMLProps<ComponentProps<T>, JsxStyleProps>
72+
export type ${typeName}<T extends ElementType> = JsxHTMLProps<ComponentProps<T> & UnstyledProps, JsxStyleProps>
6673
6774
export type ${variantName}<T extends ${componentName}<any, any>> = T extends ${componentName}<any, infer Props> ? Props : never
6875
`,

packages/generator/src/artifacts/solid-jsx/jsx.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export function generateSolidJsxFactory(ctx: Context) {
4949
5050
const [localProps, restProps] = splitProps(mergedProps, [
5151
'as',
52+
'unstyled',
5253
'class',
5354
'className',
5455
])
@@ -91,7 +92,13 @@ export function generateSolidJsxFactory(ctx: Context) {
9192
)
9293
}
9394
94-
const classes = configOrCva.__recipe__ ? recipeClass : cvaClass
95+
const classes = () => {
96+
if (localProps.unstyled) {
97+
const { css: cssStyles, ...propStyles } = styleProps
98+
return cx(css(propStyles, cssStyles), localProps.class, localProps.className)
99+
}
100+
return configOrCva.__recipe__ ? recipeClass() : cvaClass()
101+
}
95102
96103
if (forwardedProps.className) {
97104
delete forwardedProps.className

packages/generator/src/artifacts/solid-jsx/types.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,17 @@ interface Dict {
2121
[k: string]: unknown
2222
}
2323
24+
export interface UnstyledProps {
25+
/**
26+
* Whether to remove recipe styles
27+
*/
28+
unstyled?: boolean | undefined
29+
}
30+
2431
export type ElementType<P = any> = keyof JSX.IntrinsicElements | Component<P>
2532
2633
export interface ${componentName}<T extends ElementType, P extends Dict = {}> {
27-
(props: JsxHTMLProps<ComponentProps<T>, Assign<JsxStyleProps, P>>): JSX.Element
34+
(props: JsxHTMLProps<ComponentProps<T> & UnstyledProps, Assign<JsxStyleProps, P>>): JSX.Element
2835
displayName?: string
2936
}
3037
@@ -39,7 +46,7 @@ export interface JsxFactoryOptions<TProps extends Dict> {
3946
forwardProps?: string[]
4047
}
4148
42-
export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T>, P>;
49+
export type JsxRecipeProps<T extends ElementType, P extends Dict> = JsxHTMLProps<ComponentProps<T> & UnstyledProps, P>;
4350
4451
export type JsxElement<T extends ElementType, P extends Dict> = T extends ${componentName}<infer A, infer B>
4552
? ${componentName}<A, Pretty<DistributiveUnion<P, B>>>
@@ -60,7 +67,7 @@ export type JsxElements = {
6067
6168
export type ${upperName} = JsxFactory & JsxElements
6269
63-
export type ${typeName}<T extends ElementType> = JsxHTMLProps<ComponentProps<T>, JsxStyleProps>
70+
export type ${typeName}<T extends ElementType> = JsxHTMLProps<ComponentProps<T> & UnstyledProps, JsxStyleProps>
6471
6572
export type ${variantName}<T extends ${componentName}<any, any>> = T extends ${componentName}<any, infer Props> ? Props : never
6673
`,

packages/generator/src/artifacts/vue-jsx/jsx.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export function generateVueJsxFactory(ctx: Context) {
4040
inheritAttrs: false,
4141
props: {
4242
modelValue: null,
43+
unstyled: { type: Boolean, default: false },
4344
as: { type: [String, Object], default: __base__ }
4445
},
4546
setup(props, { slots, attrs, emit }) {
@@ -63,7 +64,14 @@ export function generateVueJsxFactory(ctx: Context) {
6364
return cx(css(cvaStyles, propStyles, cssStyles), combinedProps.value.className, combinedProps.value.class)
6465
})
6566
66-
const classes = configOrCva.__recipe__ ? recipeClass : cvaClass
67+
const classes = computed(() => {
68+
if (props.unstyled) {
69+
const [_htmlProps, _forwardedProps, _variantProps, styleProps, _elementProps] = splittedProps.value
70+
const { css: cssStyles, ...propStyles } = styleProps
71+
return cx(css(propStyles, cssStyles), combinedProps.value.className, combinedProps.value.class)
72+
}
73+
return configOrCva.__recipe__ ? recipeClass.value : cvaClass.value
74+
})
6775
6876
const vModelProps = computed(() => {
6977
const result = {};

0 commit comments

Comments
 (0)