Skip to content

Commit 0d8efe2

Browse files
Sprinkles: Support multiple default conditions (#334)
1 parent 0b743e7 commit 0d8efe2

File tree

5 files changed

+121
-17
lines changed

5 files changed

+121
-17
lines changed

.changeset/eleven-moles-flow.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
'@vanilla-extract/sprinkles': minor
3+
---
4+
5+
Support multiple default conditions
6+
7+
If your conditions are mutually exclusive (e.g. light mode and dark mode), you can now provide an array of default conditions. For example, the following configuration would automatically expand `atoms({ background: 'white' })` to the equivalent of `atoms({ background: { lightMode: 'white', darkMode: 'white' }})`.
8+
9+
```ts
10+
import { createAtomicStyles } from '@vanilla-extract/sprinkles';
11+
12+
const responsiveStyles = createAtomicStyles({
13+
conditions: {
14+
lightMode: { '@media': '(prefers-color-scheme: light)' },
15+
darkMode: { '@media': '(prefers-color-scheme: dark)' }
16+
},
17+
defaultCondition: ['lightMode', 'darkMode'],
18+
// etc.
19+
});
20+
```

packages/sprinkles/README.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -453,9 +453,9 @@ const styles = createAtomicStyles({
453453

454454
#### `defaultCondition`
455455

456-
Defines which condition should be used when a non-conditional value is requested, e.g. `atoms({ display: 'flex' })`.
456+
Defines which condition(s) should be used when a non-conditional value is requested, e.g. `atoms({ display: 'flex' })`.
457457

458-
> 💡 When using mobile-first responsive conditions, this should be your lowest breakpoint.
458+
If you're using mobile-first responsive conditions, this should be your lowest breakpoint.
459459

460460
```ts
461461
import { createAtomicStyles } from '@vanilla-extract/sprinkles';
@@ -471,9 +471,22 @@ const responsiveStyles = createAtomicStyles({
471471
});
472472
```
473473

474-
You can also set `defaultCondition` to `false`. This forces you to be explicit about which conditions you’re targeting.
474+
If your conditions are mutually exclusive (e.g. light mode and dark mode), you can provide an array of default conditions. For example, the following configuration would automatically expand `atoms({ background: 'white' })` to the equivalent of `atoms({ background: { lightMode: 'white', darkMode: 'white' }})`.
475+
476+
```ts
477+
import { createAtomicStyles } from '@vanilla-extract/sprinkles';
478+
479+
const responsiveStyles = createAtomicStyles({
480+
conditions: {
481+
lightMode: { '@media': '(prefers-color-scheme: light)' },
482+
darkMode: { '@media': '(prefers-color-scheme: dark)' }
483+
},
484+
defaultCondition: ['lightMode', 'darkMode'],
485+
// etc.
486+
});
487+
```
475488

476-
> 💡 This is useful when your conditions are mutually exclusive.
489+
You can also set `defaultCondition` to `false`. This forces you to be explicit about which conditions you’re targeting.
477490

478491
```ts
479492
import { createAtomicStyles } from '@vanilla-extract/sprinkles';

packages/sprinkles/src/index.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ type ResponsiveArrayOptions<
5757
type ConditionalAtomicOptions<
5858
Properties extends AtomicProperties,
5959
Conditions extends { [conditionName: string]: Condition },
60-
DefaultCondition extends keyof Conditions | false,
60+
DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false,
6161
> = UnconditionalAtomicOptions<Properties> & {
6262
conditions: Conditions;
6363
defaultCondition: DefaultCondition;
@@ -83,7 +83,7 @@ type UnconditionalAtomicStyles<Properties extends AtomicProperties> = {
8383
type ConditionalAtomicStyles<
8484
Properties extends AtomicProperties,
8585
Conditions extends { [conditionName: string]: Condition },
86-
DefaultCondition extends keyof Conditions | false,
86+
DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false,
8787
> = {
8888
conditions: {
8989
defaultCondition: DefaultCondition;
@@ -94,7 +94,7 @@ type ConditionalAtomicStyles<
9494
values: Values<
9595
Properties[Property],
9696
{
97-
defaultClass: DefaultCondition extends string ? string : undefined;
97+
defaultClass: DefaultCondition extends false ? undefined : string;
9898
conditions: {
9999
[Rule in keyof Conditions]: string;
100100
};
@@ -108,7 +108,7 @@ type ConditionalWithResponsiveArrayAtomicStyles<
108108
Properties extends AtomicProperties,
109109
Conditions extends { [conditionName: string]: Condition },
110110
ResponsiveLength extends number,
111-
DefaultCondition extends keyof Conditions | false,
111+
DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false,
112112
> = {
113113
conditions: {
114114
defaultCondition: DefaultCondition;
@@ -121,7 +121,7 @@ type ConditionalWithResponsiveArrayAtomicStyles<
121121
values: Values<
122122
Properties[Property],
123123
{
124-
defaultClass: DefaultCondition extends string ? string : undefined;
124+
defaultClass: DefaultCondition extends false ? undefined : string;
125125
conditions: {
126126
[Rule in keyof Conditions]: string;
127127
};
@@ -149,7 +149,7 @@ export function createAtomicStyles<
149149
ResponsiveLength extends number,
150150
Conditions extends BaseConditions,
151151
Shorthands extends { [shorthandName: string]: Array<keyof Properties> },
152-
DefaultCondition extends keyof Conditions | false,
152+
DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false,
153153
>(
154154
options: ConditionalAtomicOptions<Properties, Conditions, DefaultCondition> &
155155
ShorthandOptions<Properties, Shorthands> &
@@ -166,7 +166,7 @@ export function createAtomicStyles<
166166
Properties extends AtomicProperties,
167167
Conditions extends BaseConditions,
168168
Shorthands extends { [shorthandName: string]: Array<keyof Properties> },
169-
DefaultCondition extends keyof Conditions | false,
169+
DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false,
170170
>(
171171
options: ConditionalAtomicOptions<Properties, Conditions, DefaultCondition> &
172172
ShorthandOptions<Properties, Shorthands>,
@@ -177,7 +177,7 @@ export function createAtomicStyles<
177177
Properties extends AtomicProperties,
178178
Conditions extends BaseConditions,
179179
ResponsiveLength extends number,
180-
DefaultCondition extends keyof Conditions | false,
180+
DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false,
181181
>(
182182
options: ConditionalAtomicOptions<Properties, Conditions, DefaultCondition> &
183183
ResponsiveArrayOptions<Conditions, ResponsiveLength>,
@@ -191,7 +191,7 @@ export function createAtomicStyles<
191191
export function createAtomicStyles<
192192
Properties extends AtomicProperties,
193193
Conditions extends BaseConditions,
194-
DefaultCondition extends keyof Conditions | false,
194+
DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false,
195195
>(
196196
options: ConditionalAtomicOptions<Properties, Conditions, DefaultCondition>,
197197
): ConditionalAtomicStyles<Properties, Conditions, DefaultCondition>;
@@ -237,6 +237,14 @@ export function createAtomicStyles(options: any): any {
237237
conditions: {},
238238
};
239239

240+
const defaultConditions = options.defaultCondition
241+
? Array.isArray(options.defaultCondition)
242+
? options.defaultCondition
243+
: [options.defaultCondition]
244+
: [];
245+
246+
const defaultClasses = [];
247+
240248
for (const conditionName in options.conditions) {
241249
let styleValue: StyleRule =
242250
typeof value === 'object' ? value : { [key]: value };
@@ -277,10 +285,14 @@ export function createAtomicStyles(options: any): any {
277285

278286
styles[key].values[valueName].conditions[conditionName] = className;
279287

280-
if (conditionName === options.defaultCondition) {
281-
styles[key].values[valueName].defaultClass = className;
288+
if (defaultConditions.indexOf(conditionName) > -1) {
289+
defaultClasses.push(className);
282290
}
283291
}
292+
293+
if (defaultClasses.length > 0) {
294+
styles[key].values[valueName].defaultClass = defaultClasses.join(' ');
295+
}
284296
} else {
285297
const styleValue: StyleRule =
286298
typeof value === 'object' ? value : { [key]: value };

tests/sprinkles/index.css.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,18 @@ export const conditionalAtomicStyles = createAtomicStyles({
5757
},
5858
});
5959

60+
export const conditionalAtomicStylesWithMultipleDefaultConditions =
61+
createAtomicStyles({
62+
defaultCondition: ['lightMode', 'darkMode'],
63+
conditions: {
64+
lightMode: { '@media': '(prefers-color-scheme: light)' },
65+
darkMode: { '@media': '(prefers-color-scheme: dark)' },
66+
},
67+
properties: {
68+
background: ['red', 'green', 'blue'],
69+
},
70+
});
71+
6072
export const conditionalStylesWithoutDefaultCondition = createAtomicStyles({
6173
defaultCondition: false,
6274
conditions: {

tests/sprinkles/sprinkles.test.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
atomicWithPaddingShorthandStyles,
1010
atomicWithShorthandStyles,
1111
conditionalAtomicStyles,
12+
conditionalAtomicStylesWithMultipleDefaultConditions,
1213
conditionalStylesWithoutDefaultCondition,
1314
conditionalStylesWithoutResponsiveArray,
1415
} from './index.css';
@@ -259,7 +260,7 @@ describe('sprinkles', () => {
259260
padding: 'large',
260261
}),
261262
).toMatchInlineSnapshot(
262-
`"sprinkles_paddingTop_small__1kw4bre1x sprinkles_paddingBottom_medium__1kw4bre21 sprinkles_paddingLeft_small__1kw4bre1r sprinkles_paddingRight_small__1kw4bre1u"`,
263+
`"sprinkles_paddingTop_small__1kw4bre23 sprinkles_paddingBottom_medium__1kw4bre27 sprinkles_paddingLeft_small__1kw4bre1x sprinkles_paddingRight_small__1kw4bre20"`,
263264
);
264265
});
265266

@@ -272,7 +273,7 @@ describe('sprinkles', () => {
272273
padding: 'large',
273274
}),
274275
).toMatchInlineSnapshot(
275-
`"sprinkles_paddingTop_large__1kw4bre1z sprinkles_paddingBottom_large__1kw4bre22 sprinkles_paddingLeft_small__1kw4bre1r sprinkles_paddingRight_small__1kw4bre1u"`,
276+
`"sprinkles_paddingTop_large__1kw4bre25 sprinkles_paddingBottom_large__1kw4bre28 sprinkles_paddingLeft_small__1kw4bre1x sprinkles_paddingRight_small__1kw4bre20"`,
276277
);
277278
});
278279

@@ -877,4 +878,50 @@ describe('sprinkles', () => {
877878
}
878879
`);
879880
});
881+
882+
it('should create conditional atomic styles with multiple default condition classes in "defaultClass"', () => {
883+
expect(conditionalAtomicStylesWithMultipleDefaultConditions)
884+
.toMatchInlineSnapshot(`
885+
Object {
886+
"conditions": Object {
887+
"conditionNames": Array [
888+
"lightMode",
889+
"darkMode",
890+
],
891+
"defaultCondition": Array [
892+
"lightMode",
893+
"darkMode",
894+
],
895+
"responsiveArray": undefined,
896+
},
897+
"styles": Object {
898+
"background": Object {
899+
"values": Object {
900+
"blue": Object {
901+
"conditions": Object {
902+
"darkMode": "sprinkles_background_blue_darkMode__1kw4bre1l",
903+
"lightMode": "sprinkles_background_blue_lightMode__1kw4bre1k",
904+
},
905+
"defaultClass": "sprinkles_background_blue_lightMode__1kw4bre1k sprinkles_background_blue_darkMode__1kw4bre1l",
906+
},
907+
"green": Object {
908+
"conditions": Object {
909+
"darkMode": "sprinkles_background_green_darkMode__1kw4bre1j",
910+
"lightMode": "sprinkles_background_green_lightMode__1kw4bre1i",
911+
},
912+
"defaultClass": "sprinkles_background_green_lightMode__1kw4bre1i sprinkles_background_green_darkMode__1kw4bre1j",
913+
},
914+
"red": Object {
915+
"conditions": Object {
916+
"darkMode": "sprinkles_background_red_darkMode__1kw4bre1h",
917+
"lightMode": "sprinkles_background_red_lightMode__1kw4bre1g",
918+
},
919+
"defaultClass": "sprinkles_background_red_lightMode__1kw4bre1g sprinkles_background_red_darkMode__1kw4bre1h",
920+
},
921+
},
922+
},
923+
},
924+
}
925+
`);
926+
});
880927
});

0 commit comments

Comments
 (0)