Skip to content

Commit 7d8a2de

Browse files
committed
Add transform function for @starting-style and @position-try rules
1 parent 3d8176c commit 7d8a2de

File tree

3 files changed

+490
-0
lines changed

3 files changed

+490
-0
lines changed

.changeset/tender-beans-cheat.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@vanilla-extract/css': minor
3+
---
4+
5+
Add support for `@starting-style` and `@position-try` rules

packages/css/src/transformCss.test.ts

Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2500,6 +2500,363 @@ describe('transformCss', () => {
25002500
}
25012501
`);
25022502
});
2503+
2504+
it('should handle @position-try declaration', () => {
2505+
expect(
2506+
transformCss({
2507+
composedClassLists: [],
2508+
localClassNames: ['testClass'],
2509+
cssObjs: [
2510+
{
2511+
type: 'local',
2512+
selector: 'testClass',
2513+
rule: {
2514+
display: 'flex',
2515+
'@position-try': {
2516+
'--custom-left': {
2517+
positionArea: 'left',
2518+
width: '100px',
2519+
margin: '0 10px 0 0',
2520+
},
2521+
},
2522+
},
2523+
},
2524+
],
2525+
}).join('\n'),
2526+
).toMatchInlineSnapshot(`
2527+
.testClass {
2528+
display: flex;
2529+
}
2530+
@position-try --custom-left {
2531+
.testClass {
2532+
position-area: left;
2533+
width: 100px;
2534+
margin: 0 10px 0 0;
2535+
}
2536+
}
2537+
`);
2538+
});
2539+
2540+
it('should handle @position-try inside media queries', () => {
2541+
expect(
2542+
transformCss({
2543+
composedClassLists: [],
2544+
localClassNames: ['testClass'],
2545+
cssObjs: [
2546+
{
2547+
type: 'local',
2548+
selector: 'testClass',
2549+
rule: {
2550+
display: 'flex',
2551+
'@media': {
2552+
'screen and (min-width: 700px)': {
2553+
'@position-try': {
2554+
'--custom-left': {
2555+
positionArea: 'left',
2556+
width: '100px',
2557+
margin: '0 10px 0 0',
2558+
},
2559+
},
2560+
},
2561+
},
2562+
},
2563+
},
2564+
],
2565+
}).join('\n'),
2566+
).toMatchInlineSnapshot(`
2567+
.testClass {
2568+
display: flex;
2569+
}
2570+
@media screen and (min-width: 700px) {
2571+
@position-try --custom-left {
2572+
.testClass {
2573+
position-area: left;
2574+
width: 100px;
2575+
margin: 0 10px 0 0;
2576+
}
2577+
}
2578+
}
2579+
`);
2580+
});
2581+
2582+
it('should handle @position-try inside container queries', () => {
2583+
expect(
2584+
transformCss({
2585+
composedClassLists: [],
2586+
localClassNames: ['testClass'],
2587+
cssObjs: [
2588+
{
2589+
type: 'local',
2590+
selector: 'testClass',
2591+
rule: {
2592+
display: 'flex',
2593+
'@container': {
2594+
'sidebar (min-width: 700px)': {
2595+
'@position-try': {
2596+
'--custom-left': {
2597+
positionArea: 'left',
2598+
width: '100px',
2599+
margin: '0 10px 0 0',
2600+
},
2601+
},
2602+
},
2603+
},
2604+
},
2605+
},
2606+
],
2607+
}).join('\n'),
2608+
).toMatchInlineSnapshot(`
2609+
.testClass {
2610+
display: flex;
2611+
}
2612+
@container sidebar (min-width: 700px) {
2613+
@position-try --custom-left {
2614+
.testClass {
2615+
position-area: left;
2616+
width: 100px;
2617+
margin: 0 10px 0 0;
2618+
}
2619+
}
2620+
}
2621+
`);
2622+
});
2623+
2624+
it('should handle @position-try inside a layer', () => {
2625+
expect(
2626+
transformCss({
2627+
composedClassLists: [],
2628+
localClassNames: ['testClass'],
2629+
cssObjs: [
2630+
{
2631+
type: 'local',
2632+
selector: 'testClass',
2633+
rule: {
2634+
'@layer': {
2635+
'mock-layer': {
2636+
'@position-try': {
2637+
'--custom-left': {
2638+
positionArea: 'left',
2639+
width: '100px',
2640+
margin: '0 10px 0 0',
2641+
},
2642+
},
2643+
},
2644+
},
2645+
},
2646+
},
2647+
],
2648+
}).join('\n'),
2649+
).toMatchInlineSnapshot(`
2650+
@layer mock-layer;
2651+
@layer mock-layer {
2652+
@position-try --custom-left {
2653+
.testClass {
2654+
position-area: left;
2655+
width: 100px;
2656+
margin: 0 10px 0 0;
2657+
}
2658+
}
2659+
}
2660+
`);
2661+
});
2662+
2663+
it('should throw an error when a at-rule is use inside @position-try scope', () => {
2664+
expect(() =>
2665+
transformCss({
2666+
composedClassLists: [],
2667+
localClassNames: ['testClass'],
2668+
cssObjs: [
2669+
{
2670+
type: 'local',
2671+
selector: 'testClass',
2672+
rule: {
2673+
display: 'flex',
2674+
'@position-try': {
2675+
'--custom-left': {
2676+
positionArea: 'left',
2677+
width: '100px',
2678+
margin: '0 10px 0 0',
2679+
'@media': {
2680+
'screen and (min-width: 700px)': {
2681+
display: 'grid',
2682+
},
2683+
},
2684+
},
2685+
},
2686+
},
2687+
},
2688+
],
2689+
}),
2690+
).toThrowErrorMatchingInlineSnapshot(
2691+
'Nested at-rules (e.g. "@media") are not allowed inside @position-try block.',
2692+
);
2693+
});
2694+
2695+
it('should handle @starting-style declaration', () => {
2696+
expect(
2697+
transformCss({
2698+
composedClassLists: [],
2699+
localClassNames: ['testClass'],
2700+
cssObjs: [
2701+
{
2702+
type: 'local',
2703+
selector: 'testClass',
2704+
rule: {
2705+
opacity: 1,
2706+
top: '100%',
2707+
'@starting-style': {
2708+
opacity: 0,
2709+
top: '50%',
2710+
},
2711+
},
2712+
},
2713+
],
2714+
}).join('\n'),
2715+
).toMatchInlineSnapshot(`
2716+
.testClass {
2717+
opacity: 1;
2718+
top: 100%;
2719+
@starting-style {
2720+
opacity: 0;
2721+
top: 50%;
2722+
}
2723+
}
2724+
`);
2725+
});
2726+
2727+
it('should handle @starting-style inside media queries', () => {
2728+
expect(
2729+
transformCss({
2730+
composedClassLists: [],
2731+
localClassNames: ['testClass'],
2732+
cssObjs: [
2733+
{
2734+
type: 'local',
2735+
selector: 'testClass',
2736+
rule: {
2737+
display: 'flex',
2738+
'@media': {
2739+
'screen and (min-width: 700px)': {
2740+
top: '0',
2741+
'@starting-style': {
2742+
top: '100%',
2743+
},
2744+
},
2745+
},
2746+
},
2747+
},
2748+
],
2749+
}).join('\n'),
2750+
).toMatchInlineSnapshot(`
2751+
.testClass {
2752+
display: flex;
2753+
}
2754+
@media screen and (min-width: 700px) {
2755+
.testClass {
2756+
top: 0;
2757+
@starting-style {
2758+
top: 100%;
2759+
}
2760+
}
2761+
}
2762+
`);
2763+
});
2764+
2765+
it('should handle @starting-style inside container queries', () => {
2766+
expect(
2767+
transformCss({
2768+
composedClassLists: [],
2769+
localClassNames: ['testClass'],
2770+
cssObjs: [
2771+
{
2772+
type: 'local',
2773+
selector: 'testClass',
2774+
rule: {
2775+
'@container': {
2776+
'sidebar (min-width: 700px)': {
2777+
top: '0',
2778+
'@starting-style': {
2779+
top: '100%',
2780+
},
2781+
},
2782+
},
2783+
},
2784+
},
2785+
],
2786+
}).join('\n'),
2787+
).toMatchInlineSnapshot(`
2788+
@container sidebar (min-width: 700px) {
2789+
.testClass {
2790+
top: 0;
2791+
@starting-style {
2792+
top: 100%;
2793+
}
2794+
}
2795+
}
2796+
`);
2797+
});
2798+
2799+
it('should handle @starting-style inside a layer', () => {
2800+
expect(
2801+
transformCss({
2802+
composedClassLists: [],
2803+
localClassNames: ['testClass'],
2804+
cssObjs: [
2805+
{
2806+
type: 'local',
2807+
selector: 'testClass',
2808+
rule: {
2809+
'@layer': {
2810+
'mock-layer': {
2811+
top: '0',
2812+
'@starting-style': {
2813+
top: '100%',
2814+
},
2815+
},
2816+
},
2817+
},
2818+
},
2819+
],
2820+
}).join('\n'),
2821+
).toMatchInlineSnapshot(`
2822+
@layer mock-layer;
2823+
@layer mock-layer {
2824+
.testClass {
2825+
top: 0;
2826+
@starting-style {
2827+
top: 100%;
2828+
}
2829+
}
2830+
}
2831+
`);
2832+
});
2833+
2834+
it('should throw an error when a at-rule is use inside @starting-style scope', () => {
2835+
expect(() =>
2836+
transformCss({
2837+
composedClassLists: [],
2838+
localClassNames: ['testClass'],
2839+
cssObjs: [
2840+
{
2841+
type: 'local',
2842+
selector: 'testClass',
2843+
rule: {
2844+
'@starting-style': {
2845+
// @ts-expect-error - Using a media query inside @starting-style for testing purposes
2846+
'@media': {
2847+
'screen and (min-width: 700px)': {
2848+
display: 'grid',
2849+
},
2850+
},
2851+
},
2852+
},
2853+
},
2854+
],
2855+
}),
2856+
).toThrowErrorMatchingInlineSnapshot(
2857+
'Nested at-rules (e.g. "@media") are not allowed inside @starting-style.',
2858+
);
2859+
});
25032860
});
25042861

25052862
endFileScope();

0 commit comments

Comments
 (0)