@@ -522,6 +522,121 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s',
522
522
await expectCanonicalization ( input , candidate , expected )
523
523
} )
524
524
} )
525
+
526
+ describe ( 'arbitrary variants' , ( ) => {
527
+ let input = css `
528
+ @import 'tailwindcss' ;
529
+ @theme {
530
+ -- * : initial;
531
+ }
532
+ `
533
+
534
+ test . each ( [
535
+ // Arbitrary variant to static variant
536
+ [ '[&:focus]:flex' , 'focus:flex' ] ,
537
+
538
+ // Arbitrary variant to static variant with at-rules
539
+ [ '[@media(scripting:_none)]:flex' , 'noscript:flex' ] ,
540
+
541
+ // Arbitrary variant to static utility at-rules and with slight differences
542
+ // in whitespace. This will require some canonicalization.
543
+ [ '[@media(scripting:none)]:flex' , 'noscript:flex' ] ,
544
+ [ '[@media(scripting:_none)]:flex' , 'noscript:flex' ] ,
545
+ [ '[@media_(scripting:_none)]:flex' , 'noscript:flex' ] ,
546
+
547
+ // With compound variants
548
+ [ 'has-[&:focus]:flex' , 'has-focus:flex' ] ,
549
+ [ 'not-[&:focus]:flex' , 'not-focus:flex' ] ,
550
+ [ 'group-[&:focus]:flex' , 'group-focus:flex' ] ,
551
+ [ 'peer-[&:focus]:flex' , 'peer-focus:flex' ] ,
552
+ [ 'in-[&:focus]:flex' , 'in-focus:flex' ] ,
553
+ ] ) ( testName , async ( candidate , expected ) => {
554
+ await expectCanonicalization ( input , candidate , expected )
555
+ } )
556
+
557
+ test ( 'unsafe migrations keep the candidate as-is' , async ( ) => {
558
+ // `hover:` also includes an `@media` query in addition to the `&:hover`
559
+ // state. Migration is not safe because the functionality would be different.
560
+ let candidate = '[&:hover]:flex'
561
+ let expected = '[&:hover]:flex'
562
+ let input = css `
563
+ @import 'tailwindcss' ;
564
+ @theme {
565
+ -- * : initial;
566
+ }
567
+ `
568
+
569
+ await expectCanonicalization ( input , candidate , expected )
570
+ } )
571
+
572
+ test ( 'make unsafe migration safe (1)' , async ( ) => {
573
+ // Overriding the `hover:` variant to only use a selector will make the
574
+ // migration safe.
575
+ let candidate = '[&:hover]:flex'
576
+ let expected = 'hover:flex'
577
+ let input = css `
578
+ @import 'tailwindcss' ;
579
+ @theme {
580
+ -- * : initial;
581
+ }
582
+ @variant hover (& : hover);
583
+ `
584
+
585
+ await expectCanonicalization ( input , candidate , expected )
586
+ } )
587
+
588
+ test ( 'make unsafe migration safe (2)' , async ( ) => {
589
+ // Overriding the `hover:` variant to only use a selector will make the
590
+ // migration safe. This time with the long-hand `@variant` syntax.
591
+ let candidate = '[&:hover]:flex'
592
+ let expected = 'hover:flex'
593
+ let input = css `
594
+ @import 'tailwindcss' ;
595
+ @theme {
596
+ -- * : initial;
597
+ }
598
+ @variant hover {
599
+ & : hover {
600
+ @slot ;
601
+ }
602
+ }
603
+ `
604
+
605
+ await expectCanonicalization ( input , candidate , expected )
606
+ } )
607
+
608
+ test ( 'custom selector-based variants' , async ( ) => {
609
+ let candidate = '[&.macos]:flex'
610
+ let expected = 'is-macos:flex'
611
+ let input = css `
612
+ @import 'tailwindcss' ;
613
+ @theme {
614
+ -- * : initial;
615
+ }
616
+ @variant is-macos (& .macos );
617
+ `
618
+
619
+ await expectCanonicalization ( input , candidate , expected )
620
+ } )
621
+
622
+ test ( 'custom @media-based variants' , async ( ) => {
623
+ let candidate = '[@media(prefers-reduced-transparency:reduce)]:flex'
624
+ let expected = 'transparency-safe:flex'
625
+ let input = css `
626
+ @import 'tailwindcss' ;
627
+ @theme {
628
+ -- * : initial;
629
+ }
630
+ @variant transparency-safe {
631
+ @media (prefers-reduced-transparency : reduce) {
632
+ @slot ;
633
+ }
634
+ }
635
+ `
636
+
637
+ await expectCanonicalization ( input , candidate , expected )
638
+ } )
639
+ } )
525
640
} )
526
641
527
642
describe ( 'theme to var' , ( ) => {
0 commit comments