@primer/primitives 11.5.0-rc.1d57246f → 11.5.0-rc.33df3625

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -98,6 +98,30 @@
98
98
  | MUST | Match padding density to control's purpose |
99
99
  | SHOULD | Use `medium` size as default |
100
100
 
101
+ ### Z-Index
102
+
103
+ ```
104
+ --zIndex-[layer]
105
+ └── layer: behind | default | sticky | dropdown | overlay | modal | popover | skipLink
106
+ ```
107
+
108
+ | Keyword | Rule |
109
+ | ------- | ------------------------------------------------------------------------------------------------------------ |
110
+ | MUST | Use z-index tokens instead of raw numeric values |
111
+ | MUST | Use `skipLink` only for accessibility skip-navigation links |
112
+ | MUST | Pair z-index with appropriate shadow level (see table below) |
113
+ | SHOULD | Prefer creating a new stacking context (`isolation: isolate`) over escalating z-index |
114
+ | NEVER | Use `behind` (-1) without verifying no ancestor creates a stacking context (transform, opacity, filter, etc) |
115
+ | NEVER | Use arbitrary z-index values outside the token scale |
116
+
117
+ **Shadow ↔ Z-Index Alignment:**
118
+
119
+ | Shadow Level | Z-Index Token | Example |
120
+ | ------------------------------ | ------------------------------------ | --------------------- |
121
+ | `shadow.resting.*` | `zIndex.default` / `zIndex.sticky` | Cards, sticky headers |
122
+ | `shadow.floating.small/medium` | `zIndex.dropdown` / `zIndex.overlay` | Menus, drawers |
123
+ | `shadow.floating.large/xlarge` | `zIndex.modal` / `zIndex.popover` | Dialogs, tooltips |
124
+
101
125
  ---
102
126
 
103
127
  ## Decision Tree: Easing Selection
@@ -568,6 +568,48 @@ Monospace text styles for code blocks and inline code.
568
568
  | **text-codeBlock-shorthand** | Default style for rendering code blocks. | code-block, pre-element, code-snippet | MUST use for multi-line code. Use monospace font stack. |
569
569
  | **text-codeInline-shorthand** | Inline code blocks using em units to inherit size from its parent. | inline-code, code-element, variable-name | Use for inline code within text. Size inherits from parent using em units. |
570
570
 
571
+ ## ZIndex
572
+
573
+ ### zIndex-behind
574
+ Place element behind base content. Use for decorative backgrounds or canvas elements.
575
+ **U:** background-pattern, canvas-element, decorative-background
576
+ **R:** Use to push an element behind its siblings. WARNING: Negative z-index can behave unpredictably if any ancestor creates a new stacking context (via transform, opacity < 1, filter, will-change, etc.). Only use when you control the full stacking context chain. Do NOT use as a general "hide" mechanism.
577
+
578
+ ### zIndex-default
579
+ Default stacking order. No elevation above surrounding content.
580
+ **U:** default-content, in-flow-element, reset
581
+ **R:** Use to explicitly reset z-index to the default layer. Suitable for elements that should participate in normal document flow stacking. Do NOT use for any element that needs to appear above other content.
582
+
583
+ ### zIndex-dropdown
584
+ Dropdown menus and select panels that appear above page content.
585
+ **U:** autocomplete-list, dropdown-menu, select-panel
586
+ **R:** Use for menus, select panels, and autocomplete lists that overlay page content. These should appear above sticky elements but below overlays and modals. Pair -> `shadow.floating.small` or `shadow.floating.medium` for visual elevation.
587
+
588
+ ### zIndex-modal
589
+ Modal dialogs and full-screen overlays.
590
+ **U:** dialog, full-screen-overlay, modal-dialog
591
+ **R:** Use for modal dialogs that require user interaction before returning to the page. MUST trap focus within the modal. MUST appear above all other page content except popovers and skip links. Pair -> `shadow.floating.large` or `shadow.floating.xlarge` for visual elevation.
592
+
593
+ ### zIndex-overlay
594
+ Overlay backdrops, side panels, and drawers.
595
+ **U:** drawer, overlay-backdrop, side-panel
596
+ **R:** Use for overlay surfaces that partially cover the page — drawers, side panels, and backdrop layers. These appear above dropdowns but below modal dialogs. SHOULD be paired with a backdrop/scrim element to indicate the overlay is blocking interaction with content beneath.
597
+
598
+ ### zIndex-popover
599
+ Tooltips and popovers that appear above all normal UI.
600
+ **U:** hover-card, popover, tooltip
601
+ **R:** Use for tooltips, popovers, and hover cards that must appear above all other UI elements including modals. These are the highest layer in normal UI. Do NOT use for persistent navigation — use `sticky` instead.
602
+
603
+ ### zIndex-skipLink
604
+ Accessibility skip links. Must always be the topmost layer.
605
+ **U:** skip-link, skip-navigation, skip-to-content
606
+ **R:** MUST use for accessibility skip links that allow keyboard users to bypass navigation. This is the highest z-index level and MUST always appear above everything else including modals and tooltips. NEVER use for non-accessibility purposes.
607
+
608
+ ### zIndex-sticky
609
+ Sticky elements that remain visible while scrolling.
610
+ **U:** sticky-header, sticky-sidebar, sticky-table-header
611
+ **R:** MUST use with `position: sticky` or `position: fixed` for headers, sidebars, and navigation bars that persist during scroll. Do NOT use for floating overlays or dropdowns — use higher z-index levels instead.
612
+
571
613
  ---
572
614
 
573
615
  **Final Directive for AI**:
@@ -27,9 +27,9 @@ export const durationToCss = {
27
27
  if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
28
28
  throw new Error(`duration token value must be a finite, non-negative number, invalid token: ${token.name} with value: ${value}`);
29
29
  }
30
- // Always output in ms
30
+ // Always output in ms, rounding to avoid floating-point noise (e.g. 0.0049s → 4.9ms not 4.8999…ms)
31
31
  if (unit === 's') {
32
- return `${value * 1000}ms`;
32
+ return `${parseFloat((value * 1000).toPrecision(12))}ms`;
33
33
  }
34
34
  return `${value}ms`;
35
35
  },
@@ -18,4 +18,18 @@
18
18
  --base-size-8: 0.5rem;
19
19
  --base-size-80: 5rem;
20
20
  --base-size-96: 6rem;
21
+ --base-size-negative-12: -0.75rem;
22
+ --base-size-negative-16: -1rem;
23
+ --base-size-negative-2: -0.125rem;
24
+ --base-size-negative-20: -1.25rem;
25
+ --base-size-negative-24: -1.5rem;
26
+ --base-size-negative-28: -1.75rem;
27
+ --base-size-negative-32: -2rem;
28
+ --base-size-negative-36: -2.25rem;
29
+ --base-size-negative-4: -0.25rem;
30
+ --base-size-negative-40: -2.5rem;
31
+ --base-size-negative-44: -2.75rem;
32
+ --base-size-negative-48: -3rem;
33
+ --base-size-negative-6: -0.375rem;
34
+ --base-size-negative-8: -0.5rem;
21
35
  }
@@ -0,0 +1,9 @@
1
+ :root {
2
+ --base-zIndex-0: 0;
3
+ --base-zIndex-100: 100;
4
+ --base-zIndex-200: 200;
5
+ --base-zIndex-300: 300;
6
+ --base-zIndex-400: 400;
7
+ --base-zIndex-500: 500;
8
+ --base-zIndex-600: 600;
9
+ }
@@ -0,0 +1,10 @@
1
+ :root {
2
+ --zIndex-behind: -1; /** Place element behind base content. Use for decorative backgrounds or canvas elements. */
3
+ --zIndex-default: 0; /** Default stacking order. No elevation above surrounding content. */
4
+ --zIndex-dropdown: 200; /** Dropdown menus and select panels that appear above page content. */
5
+ --zIndex-modal: 400; /** Modal dialogs and full-screen overlays. */
6
+ --zIndex-overlay: 300; /** Overlay backdrops, side panels, and drawers. */
7
+ --zIndex-popover: 500; /** Tooltips and popovers that appear above all normal UI. */
8
+ --zIndex-skipLink: 600; /** Accessibility skip links. Must always be the topmost layer. */
9
+ --zIndex-sticky: 100; /** Sticky elements that remain visible while scrolling. */
10
+ }
@@ -4,6 +4,7 @@
4
4
  */
5
5
  @import './base/motion/motion.css';
6
6
  @import './base/size/size.css';
7
+ @import './base/size/z-index.css';
7
8
  @import './base/typography/typography.css';
8
9
  @import './functional/size/border.css';
9
10
  @import './functional/size/breakpoints.css';
@@ -11,4 +12,5 @@
11
12
  @import './functional/size/size-coarse.css';
12
13
  @import './functional/size/size-fine.css';
13
14
  @import './functional/size/size.css';
15
+ @import './functional/size/z-index.css';
14
16
  @import './functional/typography/typography.css';
@@ -568,5 +568,257 @@
568
568
  "path": ["base", "size", "96"],
569
569
  "value": "6rem",
570
570
  "type": "dimension"
571
+ },
572
+ "base-size-negative-12": {
573
+ "key": "{base.size.negative-12}",
574
+ "filePath": "src/tokens/base/size/size.json5",
575
+ "isSource": true,
576
+ "original": {
577
+ "$value": {
578
+ "value": -12,
579
+ "unit": "px"
580
+ },
581
+ "$type": "dimension",
582
+ "key": "{base.size.negative-12}"
583
+ },
584
+ "name": "base-size-negative-12",
585
+ "attributes": {},
586
+ "path": ["base", "size", "negative-12"],
587
+ "value": "-0.75rem",
588
+ "type": "dimension"
589
+ },
590
+ "base-size-negative-16": {
591
+ "key": "{base.size.negative-16}",
592
+ "filePath": "src/tokens/base/size/size.json5",
593
+ "isSource": true,
594
+ "original": {
595
+ "$value": {
596
+ "value": -16,
597
+ "unit": "px"
598
+ },
599
+ "$type": "dimension",
600
+ "key": "{base.size.negative-16}"
601
+ },
602
+ "name": "base-size-negative-16",
603
+ "attributes": {},
604
+ "path": ["base", "size", "negative-16"],
605
+ "value": "-1rem",
606
+ "type": "dimension"
607
+ },
608
+ "base-size-negative-2": {
609
+ "key": "{base.size.negative-2}",
610
+ "filePath": "src/tokens/base/size/size.json5",
611
+ "isSource": true,
612
+ "original": {
613
+ "$value": {
614
+ "value": -2,
615
+ "unit": "px"
616
+ },
617
+ "$type": "dimension",
618
+ "key": "{base.size.negative-2}"
619
+ },
620
+ "name": "base-size-negative-2",
621
+ "attributes": {},
622
+ "path": ["base", "size", "negative-2"],
623
+ "value": "-0.125rem",
624
+ "type": "dimension"
625
+ },
626
+ "base-size-negative-20": {
627
+ "key": "{base.size.negative-20}",
628
+ "filePath": "src/tokens/base/size/size.json5",
629
+ "isSource": true,
630
+ "original": {
631
+ "$value": {
632
+ "value": -20,
633
+ "unit": "px"
634
+ },
635
+ "$type": "dimension",
636
+ "key": "{base.size.negative-20}"
637
+ },
638
+ "name": "base-size-negative-20",
639
+ "attributes": {},
640
+ "path": ["base", "size", "negative-20"],
641
+ "value": "-1.25rem",
642
+ "type": "dimension"
643
+ },
644
+ "base-size-negative-24": {
645
+ "key": "{base.size.negative-24}",
646
+ "filePath": "src/tokens/base/size/size.json5",
647
+ "isSource": true,
648
+ "original": {
649
+ "$value": {
650
+ "value": -24,
651
+ "unit": "px"
652
+ },
653
+ "$type": "dimension",
654
+ "key": "{base.size.negative-24}"
655
+ },
656
+ "name": "base-size-negative-24",
657
+ "attributes": {},
658
+ "path": ["base", "size", "negative-24"],
659
+ "value": "-1.5rem",
660
+ "type": "dimension"
661
+ },
662
+ "base-size-negative-28": {
663
+ "key": "{base.size.negative-28}",
664
+ "filePath": "src/tokens/base/size/size.json5",
665
+ "isSource": true,
666
+ "original": {
667
+ "$value": {
668
+ "value": -28,
669
+ "unit": "px"
670
+ },
671
+ "$type": "dimension",
672
+ "key": "{base.size.negative-28}"
673
+ },
674
+ "name": "base-size-negative-28",
675
+ "attributes": {},
676
+ "path": ["base", "size", "negative-28"],
677
+ "value": "-1.75rem",
678
+ "type": "dimension"
679
+ },
680
+ "base-size-negative-32": {
681
+ "key": "{base.size.negative-32}",
682
+ "filePath": "src/tokens/base/size/size.json5",
683
+ "isSource": true,
684
+ "original": {
685
+ "$value": {
686
+ "value": -32,
687
+ "unit": "px"
688
+ },
689
+ "$type": "dimension",
690
+ "key": "{base.size.negative-32}"
691
+ },
692
+ "name": "base-size-negative-32",
693
+ "attributes": {},
694
+ "path": ["base", "size", "negative-32"],
695
+ "value": "-2rem",
696
+ "type": "dimension"
697
+ },
698
+ "base-size-negative-36": {
699
+ "key": "{base.size.negative-36}",
700
+ "filePath": "src/tokens/base/size/size.json5",
701
+ "isSource": true,
702
+ "original": {
703
+ "$value": {
704
+ "value": -36,
705
+ "unit": "px"
706
+ },
707
+ "$type": "dimension",
708
+ "key": "{base.size.negative-36}"
709
+ },
710
+ "name": "base-size-negative-36",
711
+ "attributes": {},
712
+ "path": ["base", "size", "negative-36"],
713
+ "value": "-2.25rem",
714
+ "type": "dimension"
715
+ },
716
+ "base-size-negative-4": {
717
+ "key": "{base.size.negative-4}",
718
+ "filePath": "src/tokens/base/size/size.json5",
719
+ "isSource": true,
720
+ "original": {
721
+ "$value": {
722
+ "value": -4,
723
+ "unit": "px"
724
+ },
725
+ "$type": "dimension",
726
+ "key": "{base.size.negative-4}"
727
+ },
728
+ "name": "base-size-negative-4",
729
+ "attributes": {},
730
+ "path": ["base", "size", "negative-4"],
731
+ "value": "-0.25rem",
732
+ "type": "dimension"
733
+ },
734
+ "base-size-negative-40": {
735
+ "key": "{base.size.negative-40}",
736
+ "filePath": "src/tokens/base/size/size.json5",
737
+ "isSource": true,
738
+ "original": {
739
+ "$value": {
740
+ "value": -40,
741
+ "unit": "px"
742
+ },
743
+ "$type": "dimension",
744
+ "key": "{base.size.negative-40}"
745
+ },
746
+ "name": "base-size-negative-40",
747
+ "attributes": {},
748
+ "path": ["base", "size", "negative-40"],
749
+ "value": "-2.5rem",
750
+ "type": "dimension"
751
+ },
752
+ "base-size-negative-44": {
753
+ "key": "{base.size.negative-44}",
754
+ "filePath": "src/tokens/base/size/size.json5",
755
+ "isSource": true,
756
+ "original": {
757
+ "$value": {
758
+ "value": -44,
759
+ "unit": "px"
760
+ },
761
+ "$type": "dimension",
762
+ "key": "{base.size.negative-44}"
763
+ },
764
+ "name": "base-size-negative-44",
765
+ "attributes": {},
766
+ "path": ["base", "size", "negative-44"],
767
+ "value": "-2.75rem",
768
+ "type": "dimension"
769
+ },
770
+ "base-size-negative-48": {
771
+ "key": "{base.size.negative-48}",
772
+ "filePath": "src/tokens/base/size/size.json5",
773
+ "isSource": true,
774
+ "original": {
775
+ "$value": {
776
+ "value": -48,
777
+ "unit": "px"
778
+ },
779
+ "$type": "dimension",
780
+ "key": "{base.size.negative-48}"
781
+ },
782
+ "name": "base-size-negative-48",
783
+ "attributes": {},
784
+ "path": ["base", "size", "negative-48"],
785
+ "value": "-3rem",
786
+ "type": "dimension"
787
+ },
788
+ "base-size-negative-6": {
789
+ "key": "{base.size.negative-6}",
790
+ "filePath": "src/tokens/base/size/size.json5",
791
+ "isSource": true,
792
+ "original": {
793
+ "$value": {
794
+ "value": -6,
795
+ "unit": "px"
796
+ },
797
+ "$type": "dimension",
798
+ "key": "{base.size.negative-6}"
799
+ },
800
+ "name": "base-size-negative-6",
801
+ "attributes": {},
802
+ "path": ["base", "size", "negative-6"],
803
+ "value": "-0.375rem",
804
+ "type": "dimension"
805
+ },
806
+ "base-size-negative-8": {
807
+ "key": "{base.size.negative-8}",
808
+ "filePath": "src/tokens/base/size/size.json5",
809
+ "isSource": true,
810
+ "original": {
811
+ "$value": {
812
+ "value": -8,
813
+ "unit": "px"
814
+ },
815
+ "$type": "dimension",
816
+ "key": "{base.size.negative-8}"
817
+ },
818
+ "name": "base-size-negative-8",
819
+ "attributes": {},
820
+ "path": ["base", "size", "negative-8"],
821
+ "value": "-0.5rem",
822
+ "type": "dimension"
571
823
  }
572
824
  }
@@ -0,0 +1,107 @@
1
+ {
2
+ "base-zIndex-0": {
3
+ "key": "{base.zIndex.0}",
4
+ "filePath": "src/tokens/base/size/z-index.json5",
5
+ "isSource": true,
6
+ "original": {
7
+ "$value": 0,
8
+ "$type": "number",
9
+ "key": "{base.zIndex.0}"
10
+ },
11
+ "name": "base-zIndex-0",
12
+ "attributes": {},
13
+ "path": ["base", "zIndex", "0"],
14
+ "value": 0,
15
+ "type": "number"
16
+ },
17
+ "base-zIndex-100": {
18
+ "key": "{base.zIndex.100}",
19
+ "filePath": "src/tokens/base/size/z-index.json5",
20
+ "isSource": true,
21
+ "original": {
22
+ "$value": 100,
23
+ "$type": "number",
24
+ "key": "{base.zIndex.100}"
25
+ },
26
+ "name": "base-zIndex-100",
27
+ "attributes": {},
28
+ "path": ["base", "zIndex", "100"],
29
+ "value": 100,
30
+ "type": "number"
31
+ },
32
+ "base-zIndex-200": {
33
+ "key": "{base.zIndex.200}",
34
+ "filePath": "src/tokens/base/size/z-index.json5",
35
+ "isSource": true,
36
+ "original": {
37
+ "$value": 200,
38
+ "$type": "number",
39
+ "key": "{base.zIndex.200}"
40
+ },
41
+ "name": "base-zIndex-200",
42
+ "attributes": {},
43
+ "path": ["base", "zIndex", "200"],
44
+ "value": 200,
45
+ "type": "number"
46
+ },
47
+ "base-zIndex-300": {
48
+ "key": "{base.zIndex.300}",
49
+ "filePath": "src/tokens/base/size/z-index.json5",
50
+ "isSource": true,
51
+ "original": {
52
+ "$value": 300,
53
+ "$type": "number",
54
+ "key": "{base.zIndex.300}"
55
+ },
56
+ "name": "base-zIndex-300",
57
+ "attributes": {},
58
+ "path": ["base", "zIndex", "300"],
59
+ "value": 300,
60
+ "type": "number"
61
+ },
62
+ "base-zIndex-400": {
63
+ "key": "{base.zIndex.400}",
64
+ "filePath": "src/tokens/base/size/z-index.json5",
65
+ "isSource": true,
66
+ "original": {
67
+ "$value": 400,
68
+ "$type": "number",
69
+ "key": "{base.zIndex.400}"
70
+ },
71
+ "name": "base-zIndex-400",
72
+ "attributes": {},
73
+ "path": ["base", "zIndex", "400"],
74
+ "value": 400,
75
+ "type": "number"
76
+ },
77
+ "base-zIndex-500": {
78
+ "key": "{base.zIndex.500}",
79
+ "filePath": "src/tokens/base/size/z-index.json5",
80
+ "isSource": true,
81
+ "original": {
82
+ "$value": 500,
83
+ "$type": "number",
84
+ "key": "{base.zIndex.500}"
85
+ },
86
+ "name": "base-zIndex-500",
87
+ "attributes": {},
88
+ "path": ["base", "zIndex", "500"],
89
+ "value": 500,
90
+ "type": "number"
91
+ },
92
+ "base-zIndex-600": {
93
+ "key": "{base.zIndex.600}",
94
+ "filePath": "src/tokens/base/size/z-index.json5",
95
+ "isSource": true,
96
+ "original": {
97
+ "$value": 600,
98
+ "$type": "number",
99
+ "key": "{base.zIndex.600}"
100
+ },
101
+ "name": "base-zIndex-600",
102
+ "attributes": {},
103
+ "path": ["base", "zIndex", "600"],
104
+ "value": 600,
105
+ "type": "number"
106
+ }
107
+ }