@databricks/design-system 2.0.1 → 2.0.3

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.
Files changed (91) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/{WizardStepContentWrapper-CFCTOSm8.js → WizardStepContentWrapper-DsAS2ZAT.js} +1356 -686
  3. package/dist/WizardStepContentWrapper-DsAS2ZAT.js.map +1 -0
  4. package/dist/dubois-colors.less +2 -0
  5. package/dist/fonts/dm-mono/DMMono-Regular.woff2 +0 -0
  6. package/dist/fonts/dm-mono/dm-mono.css +11 -0
  7. package/dist/index-dark.css +305 -516
  8. package/dist/index-dark.mitigated.css +305 -516
  9. package/dist/index.css +438 -544
  10. package/dist/index.js +1971 -244
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mitigated.css +447 -553
  13. package/dist/patterns.js +12 -2
  14. package/dist/patterns.js.map +1 -1
  15. package/dist-types/design-system/Button/Button.d.ts +2 -2
  16. package/dist-types/design-system/ContextMenu/ContextMenu.d.ts +2 -2
  17. package/dist-types/design-system/DesignSystemProvider/DesignSystemProvider.d.ts +44 -0
  18. package/dist-types/design-system/Drawer/DrawerContext.d.ts +9 -0
  19. package/dist-types/design-system/FormV2/RHFAdapters.d.ts +8 -8
  20. package/dist-types/design-system/Grid/Col.d.ts +1 -3
  21. package/dist-types/design-system/Grid/NativeCol.d.ts +10 -0
  22. package/dist-types/design-system/Grid/NativeGridContext.d.ts +11 -0
  23. package/dist-types/design-system/Grid/NativeRow.d.ts +13 -0
  24. package/dist-types/design-system/Grid/Row.d.ts +3 -4
  25. package/dist-types/design-system/Grid/grid-styling.d.ts +22 -0
  26. package/dist-types/design-system/Grid/gridConstants.d.ts +2 -0
  27. package/dist-types/design-system/Grid/index.d.ts +1 -0
  28. package/dist-types/design-system/Grid/rowConstants.d.ts +7 -0
  29. package/dist-types/design-system/Grid/types.d.ts +49 -0
  30. package/dist-types/design-system/Hooks/index.d.ts +1 -1
  31. package/dist-types/design-system/Hooks/useDesignSystemTheme.d.ts +7 -7
  32. package/dist-types/design-system/Icon/LegacyAntDIcon.d.ts +21 -0
  33. package/dist-types/design-system/Icon/__generated/icons/FlowsIcon.d.ts +4 -0
  34. package/dist-types/design-system/Icon/__generated/icons/LakewatchAlertIcon.d.ts +4 -0
  35. package/dist-types/design-system/Icon/__generated/icons/LakewatchDatasourceIcon.d.ts +4 -0
  36. package/dist-types/design-system/Icon/__generated/icons/LakewatchDetectionRuleIcon.d.ts +4 -0
  37. package/dist-types/design-system/Icon/__generated/icons/LakewatchParserIcon.d.ts +4 -0
  38. package/dist-types/design-system/Icon/__generated/icons/index.d.ts +5 -0
  39. package/dist-types/design-system/Icon/index.d.ts +0 -1
  40. package/dist-types/design-system/LegacyTooltip/index.d.ts +0 -1
  41. package/dist-types/design-system/Skeleton/TitleSkeleton.d.ts +9 -3
  42. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxAddButton.d.ts +4 -0
  43. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxCheckboxItem.d.ts +8 -0
  44. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxControls.d.ts +2 -0
  45. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxFooter.d.ts +12 -0
  46. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxInput.d.ts +8 -0
  47. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxMenu.d.ts +8 -0
  48. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxMenuItem.d.ts +8 -0
  49. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxMultiSelectInput.d.ts +17 -0
  50. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxRoot.d.ts +8 -0
  51. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxSectionHeader.d.ts +4 -0
  52. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxSelectedItem.d.ts +8 -0
  53. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxSeparator.d.ts +4 -0
  54. package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxToggleButton.d.ts +8 -0
  55. package/dist-types/design-system/TypeaheadCombobox/hooks/downshiftHookWrappers.d.ts +8 -0
  56. package/dist-types/design-system/TypeaheadComboboxV2/CountBadge.d.ts +6 -0
  57. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxAddButton.d.ts +3 -0
  58. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxCheckboxItem.d.ts +10 -0
  59. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxControls.d.ts +11 -0
  60. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxFooter.d.ts +2 -0
  61. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxInput.d.ts +9 -0
  62. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxMenu.d.ts +17 -0
  63. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxMenuItem.d.ts +16 -0
  64. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxMultiSelectInput.d.ts +18 -0
  65. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxRoot.d.ts +17 -0
  66. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxSectionHeader.d.ts +1 -0
  67. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxSelectedItem.d.ts +11 -0
  68. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxSeparator.d.ts +1 -0
  69. package/dist-types/design-system/TypeaheadComboboxV2/TypeaheadComboboxToggleButton.d.ts +4 -0
  70. package/dist-types/design-system/TypeaheadComboboxV2/hooks/footerFocus.d.ts +13 -0
  71. package/dist-types/design-system/TypeaheadComboboxV2/hooks/index.d.ts +4 -0
  72. package/dist-types/design-system/TypeaheadComboboxV2/hooks/useComboboxItems.d.ts +32 -0
  73. package/dist-types/design-system/TypeaheadComboboxV2/hooks/useComboboxState.d.ts +81 -0
  74. package/dist-types/design-system/TypeaheadComboboxV2/hooks/useComboboxStateProps.d.ts +36 -0
  75. package/dist-types/design-system/TypeaheadComboboxV2/hooks/useMultipleSelectionState.d.ts +25 -0
  76. package/dist-types/design-system/TypeaheadComboboxV2/hooks/useRestoreHighlightedOption.d.ts +18 -0
  77. package/dist-types/design-system/TypeaheadComboboxV2/hooks/useScrollOptionIntoView.d.ts +11 -0
  78. package/dist-types/design-system/TypeaheadComboboxV2/hooks/useTypeaheadComboboxContext.d.ts +2 -0
  79. package/dist-types/design-system/TypeaheadComboboxV2/hooks/useVirtualizedComboboxScroll.d.ts +36 -0
  80. package/dist-types/design-system/TypeaheadComboboxV2/index.d.ts +13 -0
  81. package/dist-types/design-system/TypeaheadComboboxV2/providers/TypeaheadComboboxContext.d.ts +47 -0
  82. package/dist-types/design-system/Typography/titleLevel.d.ts +11 -0
  83. package/dist-types/design-system/_shared_/Menu/index.d.ts +1 -1
  84. package/dist-types/design-system/fonts.d.ts +1 -0
  85. package/dist-types/design-system/index.d.ts +1 -0
  86. package/dist-types/design-system/utils/useMediaQuery.d.ts +4 -1
  87. package/dist-types/theme/_generated/ValidSemanticColors.d.ts +2 -1
  88. package/package.json +14 -3
  89. package/dist/WizardStepContentWrapper-CFCTOSm8.js.map +0 -1
  90. package/dist-types/design-system/Icon/AntdIcon.d.ts +0 -114
  91. package/dist-types/design-system/LegacyTooltip/LegacyInfoTooltip.d.ts +0 -16
@@ -10725,220 +10725,6 @@ textarea.du-bois-light-input {
10725
10725
  background: rgba(255, 255, 255, 0.35) !important;
10726
10726
  }
10727
10727
 
10728
- /* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
10729
- /* stylelint-disable no-duplicate-selectors */
10730
- /* stylelint-disable */
10731
- /* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
10732
- .du-bois-light-modal {
10733
- box-sizing: border-box;
10734
- margin: 0;
10735
- padding: 0;
10736
- color: #161616;
10737
- font-size: 13px;
10738
- font-variant: tabular-nums;
10739
- line-height: 20px;
10740
- list-style: none;
10741
- font-feature-settings: 'tnum';
10742
- pointer-events: none;
10743
- position: relative;
10744
- top: 100px;
10745
- width: auto;
10746
- max-width: calc(100vw - 32px);
10747
- margin: 0 auto;
10748
- padding-bottom: 24px;
10749
- }
10750
- .du-bois-light-modal.du-bois-light-zoom-enter,
10751
- .du-bois-light-modal.du-bois-lightzoom-appear {
10752
- transform: none;
10753
- opacity: 0;
10754
- animation-duration: 0.3s;
10755
- user-select: none;
10756
- }
10757
- .du-bois-light-modal-mask {
10758
- position: fixed;
10759
- top: 0;
10760
- right: 0;
10761
- bottom: 0;
10762
- left: 0;
10763
- z-index: 1000;
10764
- height: 100%;
10765
- background-color: rgba(0, 0, 0, 0.45);
10766
- }
10767
- .du-bois-light-modal-mask-hidden {
10768
- display: none;
10769
- }
10770
- .du-bois-light-modal-wrap {
10771
- position: fixed;
10772
- top: 0;
10773
- right: 0;
10774
- bottom: 0;
10775
- left: 0;
10776
- overflow: auto;
10777
- outline: 0;
10778
- -webkit-overflow-scrolling: touch;
10779
- }
10780
- .du-bois-light-modal-wrap {
10781
- z-index: 1000;
10782
- }
10783
- .du-bois-light-modal-title {
10784
- margin: 0;
10785
- color: rgba(0, 0, 0, 0.85);
10786
- font-weight: 500;
10787
- font-size: 18px;
10788
- line-height: 22px;
10789
- word-wrap: break-word;
10790
- }
10791
- .du-bois-light-modal-content {
10792
- position: relative;
10793
- background-color: #fff;
10794
- background-clip: padding-box;
10795
- border: 0;
10796
- border-radius: 4px;
10797
- box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
10798
- pointer-events: auto;
10799
- }
10800
- .du-bois-light-modal-close {
10801
- position: absolute;
10802
- top: 0;
10803
- right: 0;
10804
- z-index: 10;
10805
- padding: 0;
10806
- color: #6F6F6F;
10807
- font-weight: 700;
10808
- line-height: 1;
10809
- text-decoration: none;
10810
- background: transparent;
10811
- border: 0;
10812
- outline: 0;
10813
- cursor: pointer;
10814
- transition: color 0.3s;
10815
- }
10816
- .du-bois-light-modal-close-x {
10817
- display: block;
10818
- width: 102px;
10819
- height: 102px;
10820
- font-size: 18px;
10821
- font-style: normal;
10822
- line-height: 102px;
10823
- text-align: center;
10824
- text-transform: none;
10825
- text-rendering: auto;
10826
- }
10827
- .du-bois-light-modal-close:focus,
10828
- .du-bois-light-modal-close:hover {
10829
- color: rgba(0, 0, 0, 0.75);
10830
- text-decoration: none;
10831
- }
10832
- .du-bois-light-modal-header {
10833
- padding: 40px 40px 20px;
10834
- color: #161616;
10835
- background: #fff;
10836
- border-bottom: 0px solid #f0f0f0;
10837
- border-radius: 4px 4px 0 0;
10838
- }
10839
- .du-bois-light-modal-body {
10840
- padding: 0 40px;
10841
- font-size: 13px;
10842
- line-height: 20px;
10843
- word-wrap: break-word;
10844
- }
10845
- .du-bois-light-modal-footer {
10846
- padding: 0px 0px;
10847
- text-align: right;
10848
- background: transparent;
10849
- border-top: 0px solid #f0f0f0;
10850
- border-radius: 0 0 4px 4px;
10851
- }
10852
- .du-bois-light-modal-footer .du-bois-light-btn + .du-bois-light-btn:not(.du-bois-light-dropdown-trigger) {
10853
- margin-bottom: 0;
10854
- margin-left: 8px;
10855
- }
10856
- .du-bois-light-modal-open {
10857
- overflow: hidden;
10858
- }
10859
- .du-bois-light-modal-centered {
10860
- text-align: center;
10861
- }
10862
- .du-bois-light-modal-centered::before {
10863
- display: inline-block;
10864
- width: 0;
10865
- height: 100%;
10866
- vertical-align: middle;
10867
- content: '';
10868
- }
10869
- .du-bois-light-modal-centered .du-bois-light-modal {
10870
- top: 0;
10871
- display: inline-block;
10872
- text-align: left;
10873
- vertical-align: middle;
10874
- }
10875
- @media (max-width: 767px) {
10876
- .du-bois-light-modal {
10877
- max-width: calc(100vw - 16px);
10878
- margin: 8px auto;
10879
- }
10880
- .du-bois-light-modal-centered .du-bois-light-modal {
10881
- flex: 1;
10882
- }
10883
- }
10884
- .du-bois-light-modal-confirm .du-bois-light-modal-header {
10885
- display: none;
10886
- }
10887
- .du-bois-light-modal-confirm .du-bois-light-modal-body {
10888
- padding: 32px 32px 24px;
10889
- }
10890
- .du-bois-light-modal-confirm-body-wrapper::before {
10891
- display: table;
10892
- content: '';
10893
- }
10894
- .du-bois-light-modal-confirm-body-wrapper::after {
10895
- display: table;
10896
- clear: both;
10897
- content: '';
10898
- }
10899
- .du-bois-light-modal-confirm-body .du-bois-light-modal-confirm-title {
10900
- display: block;
10901
- overflow: hidden;
10902
- color: rgba(0, 0, 0, 0.85);
10903
- font-weight: 500;
10904
- font-size: 18px;
10905
- line-height: 1.4;
10906
- }
10907
- .du-bois-light-modal-confirm-body .du-bois-light-modal-confirm-content {
10908
- margin-top: 8px;
10909
- color: #161616;
10910
- font-size: 13px;
10911
- }
10912
- .du-bois-light-modal-confirm-body > .anticon {
10913
- float: left;
10914
- margin-right: 16px;
10915
- font-size: 22px;
10916
- }
10917
- .du-bois-light-modal-confirm-body > .anticon + .du-bois-light-modal-confirm-title + .du-bois-light-modal-confirm-content {
10918
- margin-left: 38px;
10919
- }
10920
- .du-bois-light-modal-confirm .du-bois-light-modal-confirm-btns {
10921
- float: right;
10922
- margin-top: 24px;
10923
- }
10924
- .du-bois-light-modal-confirm .du-bois-light-modal-confirm-btns .du-bois-light-btn + .du-bois-light-btn {
10925
- margin-bottom: 0;
10926
- margin-left: 8px;
10927
- }
10928
- .du-bois-light-modal-confirm-error .du-bois-light-modal-confirm-body > .anticon {
10929
- color: #C82D4C;
10930
- }
10931
- .du-bois-light-modal-confirm-warning .du-bois-light-modal-confirm-body > .anticon,
10932
- .du-bois-light-modal-confirm-confirm .du-bois-light-modal-confirm-body > .anticon {
10933
- color: #AF5B23;
10934
- }
10935
- .du-bois-light-modal-confirm-info .du-bois-light-modal-confirm-body > .anticon {
10936
- color: #64727D;
10937
- }
10938
- .du-bois-light-modal-confirm-success .du-bois-light-modal-confirm-body > .anticon {
10939
- color: #34824F;
10940
- }
10941
-
10942
10728
  /* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
10943
10729
  /* stylelint-disable no-duplicate-selectors */
10944
10730
  /* stylelint-disable */
@@ -15876,7 +15662,7 @@ span.du-bois-light-typography-ellipsis-single-line {
15876
15662
  * Source: design-system/src/theme/tokens/*.json
15877
15663
  * Regenerate via: yarn theme-regenerate */
15878
15664
 
15879
- :where(:root, .du-bois-light) {
15665
+ :where(:root), :where(.du-bois-light) {
15880
15666
  --db-radius-0: 0px;
15881
15667
  --db-radius-full: 999px;
15882
15668
  --db-radius-lg: 12px;
@@ -16008,50 +15794,64 @@ span.du-bois-light-typography-ellipsis-single-line {
16008
15794
  --db-color-text-validation-success: #277c43;
16009
15795
  --db-color-text-validation-warning: #be501e;
16010
15796
  --db-color-tooltip-background-tooltip: #161616;
15797
+ --db-color-tooltip-text-tooltip: #ffffff;
16011
15798
  }
16012
15799
 
16013
15800
  /* THIS FILE IS AUTOMATICALLY GENERATED FROM Figma tokens. DO NOT EDIT.
16014
15801
  * Source: design-system/src/theme/tokens/*.json
16015
15802
  * Regenerate via: yarn theme-regenerate */
16016
15803
 
16017
- /* Layout primitive classes — internal Du Bois use for now (not a published
16018
- * consumer API yet; see the Stefan/Sheng weekly decision to "give it a try
16019
- * just within the Du Bois components"). Two primitives, both plain CSS so they
16020
- * ride the mortar cascade like the other component styles:
16021
- *
16022
- * .ds-stack — vertical flow, even gap between direct children.
16023
- * .ds-cluster — horizontal group that wraps, even gap between children.
16024
- *
16025
- * Each primitive exposes a small set of `--ds-*` knobs, defaulted on the class
16026
- * itself (not via a `var()` fallback, which would freeze the default at every
16027
- * call site). Override any of them on the element — inline
16028
- * `style={{ '--ds-stack-gap': ... }}` or a more specific selector — without a
16029
- * new modifier class:
16030
- *
16031
- * stack: --ds-stack-gap (spacing), --ds-stack-align (align-items)
16032
- * cluster: --ds-cluster-gap (spacing), --ds-cluster-align (align-items),
16033
- * --ds-cluster-justify (justify-content)
16034
- *
16035
- * Gap defaults point at the system spacing scale (`--db-space-*`). Padding is
16036
- * intentionally NOT a knob — a layout primitive owns the space between children,
16037
- * not its own box padding. */
15804
+ /*
15805
+ Vertical "stack" of elements.
15806
+ Use this for any layout where items are laid out vertically.
15807
+
15808
+ \3c !-- Basic: default gap between each child -->
15809
+ <div class="ds-stack">
15810
+ <h2>Title</h2>
15811
+ <p>Body</p>
15812
+ <button>Action</button>
15813
+ </div>
15814
+
15815
+ \3c !-- Wider gap for this instance -->
15816
+ <div class="ds-stack" style="--ds-stack-gap: var(--db-spacing-lg)">…</div>
16038
15817
 
15818
+ \3c !-- Don't stretch children to full width (e.g. left-aligned buttons) -->
15819
+ <div class="ds-stack" style="--ds-stack-align: flex-start">…</div>
15820
+ */
16039
15821
  .ds-stack {
16040
- --ds-stack-gap: var(--db-space-md);
15822
+ /* These variables act as the *parameters* for the stack instance. */
15823
+ --ds-stack-gap: var(--db-spacing-xs);
16041
15824
  --ds-stack-align: stretch;
15825
+
16042
15826
  display: flex;
16043
15827
  flex-direction: column;
16044
15828
  align-items: var(--ds-stack-align);
16045
15829
  gap: var(--ds-stack-gap);
16046
15830
  }
16047
15831
 
16048
- /* Cluster wraps by design: a long row reflows onto multiple lines rather than
16049
- * overflowing. A row that must NOT wrap (e.g. a single-line control strip) is
16050
- * not a cluster keep it bespoke. */
15832
+ /**
15833
+ Responsive, horizontal "cluster" of elements.
15834
+ Use this for any layout where items are laid out horizontally and should wrap on smaller viewport sizes.
15835
+
15836
+ \3c !-- Basic: items wrap as needed -->
15837
+ <div class="ds-cluster">
15838
+ <span>one</span>
15839
+ <span>two</span>
15840
+ <span>three</span>
15841
+ </div>
15842
+
15843
+ \3c !-- Push children apart (e.g. title left, actions right) -->
15844
+ <div class="ds-cluster" style="--ds-cluster-justify: space-between">…</div>
15845
+
15846
+ \3c !-- Looser gap for this instance -->
15847
+ <div class="ds-cluster" style="--ds-cluster-gap: var(--db-spacing-sm)">…</div>
15848
+ */
16051
15849
  .ds-cluster {
16052
- --ds-cluster-gap: var(--db-space-sm);
15850
+ /* These variables act as the *parameters* for the cluster instance. */
15851
+ --ds-cluster-gap: var(--db-spacing-2xs);
16053
15852
  --ds-cluster-align: center;
16054
15853
  --ds-cluster-justify: flex-start;
15854
+
16055
15855
  display: flex;
16056
15856
  flex-wrap: wrap;
16057
15857
  align-items: var(--ds-cluster-align);
@@ -16059,97 +15859,215 @@ span.du-bois-light-typography-ellipsis-single-line {
16059
15859
  gap: var(--ds-cluster-gap);
16060
15860
  }
16061
15861
 
16062
- /* Category-tier tokens shared by selection-control components:
16063
- * <Checkbox>, <Switch>, <Radio>. Each value here references a SYSTEM token
16064
- * from system-tokens.css — never a raw hex/px literal — so the only place a
16065
- * brand-level theme change has to land is the system tier.
16066
- *
16067
- * Component-tier files (e.g. design-system/Checkbox/tokens.css) inherit from
16068
- * these via `var()` so consumers can override a single selection control by
16069
- * targeting only its component tokens. */
16070
-
16071
- /* Re-declared under both theme classes as well as :root: these values are
16072
- * `var()` indirections onto SYSTEM tokens, and a custom property resolves its
16073
- * var() at its DECLARATION site. Declared only at :root, they would freeze at
16074
- * the root (light) system values and never re-read the dark system tokens
16075
- * inside a `.du-bois-dark` subtree. Re-declaring at every theme boundary makes
16076
- * the indirection re-resolve per theme. See DUBOIS-448 dark-mode scoping. */
16077
- :where(:root, .du-bois-light, .du-bois-dark) {
16078
- --db-selection-toggle-bg-default: var(--db-color-background-primary);
16079
- --db-selection-toggle-bg-hover: var(--db-color-action-default-background-hover);
16080
- --db-selection-toggle-bg-press: var(--db-color-action-default-background-press);
16081
- --db-selection-toggle-bg-checked: var(--db-color-action-primary-background-default);
16082
- --db-selection-toggle-bg-checked-hover: var(--db-color-action-primary-background-hover);
16083
- --db-selection-toggle-bg-checked-press: var(--db-color-action-primary-background-press);
16084
- --db-selection-toggle-bg-disabled: var(--db-color-action-disabled-background);
16085
-
16086
- --db-selection-toggle-border-default: var(--db-color-action-default-border-default);
16087
- --db-selection-toggle-border-hover: var(--db-color-action-primary-background-hover);
16088
- --db-selection-toggle-border-press: var(--db-color-action-primary-background-press);
16089
- --db-selection-toggle-border-focus: var(--db-color-action-default-border-focus);
16090
- --db-selection-toggle-border-disabled: var(--db-color-action-disabled-border);
16091
-
16092
- /* Raw literal, not a system token (exception to the file rule above): the mark
16093
- * sits on the theme-invariant blue checked fill, so it must stay white in BOTH
16094
- * themes. No non-flipping white system token exists — action-primary-icon flips
16095
- * to near-black under .du-bois-dark, which made the mark nearly invisible. */
16096
- --db-selection-toggle-icon-color: #ffffff;
16097
- --db-selection-toggle-icon-color-disabled: var(--db-color-action-disabled-text);
16098
- --db-selection-toggle-text: var(--db-color-text-primary);
16099
- --db-selection-toggle-text-disabled: var(--db-color-action-disabled-text);
16100
-
16101
- --db-selection-toggle-size: 16px;
16102
- --db-selection-toggle-border-radius: var(--db-radius-sm);
16103
- --db-selection-toggle-spacing: var(--db-space-sm);
16104
-
16105
- /* Focus ring matches AntD legacy variant; offset keeps it outside the toggle.
16106
- * Hard-coded for now — Figma export doesn't include shadow tokens. */
15862
+ :where(:root), :where(.du-bois-light) {
15863
+ /* Neutral */
15864
+ --db-neutral-surface: var(--db-color-background-primary);
15865
+ --db-subtle-neutral-surface: var(--db-color-background-secondary);
15866
+ --db-strong-neutral-surface: initial; /* TODO */
15867
+
15868
+ --db-text-on-neutral-surface: var(--db-color-text-primary);
15869
+ --db-subtle-text-on-neutral-surface: var(--db-color-text-secondary);
15870
+ --db-strong-text-on-neutral-surface: initial; /* TODO */
15871
+
15872
+ --db-neutral-border: var(--db-color-border);
15873
+ --db-subtle-neutral-border: initial; /* TODO */
15874
+ --db-strong-neutral-border: var(--db-color-border-accessible);
15875
+
15876
+ --db-neutral-surface-active: var(--db-color-table-background-selected-default);
15877
+ --db-neutral-surface-hover: var(--db-color-table-background-unselected-hover);
15878
+ --db-neutral-surface-pressed: var(--db-color-table-background-selected-hover);
15879
+ --db-neutral-surface-disabled: var(--db-color-action-disabled-background);
15880
+ --db-text-on-neutral-surface-disabled: var(--db-color-action-disabled-text);
15881
+
15882
+ /* Primary */
15883
+ --db-primary-surface: var(--db-color-action-primary-background-default);
15884
+ --db-subtle-primary-surface: var(--db-color-action-default-background-hover);
15885
+ --db-strong-primary-surface: var(--db-color-action-primary-background-hover);
15886
+
15887
+ --db-text-on-primary-surface: var(--db-color-action-primary-text-default);
15888
+ --db-primary-text-on-neutral-surface: var(--db-color-action-link-default);
15889
+ --db-subtle-text-on-primary-surface: initial; /* TODO */
15890
+ --db-strong-text-on-primary-surface: var(--db-color-action-primary-text-default);
15891
+
15892
+ --db-primary-border: var(--db-color-action-primary-background-default);
15893
+ --db-subtle-primary-border: initial; /* TODO */
15894
+ --db-strong-primary-border: var(--db-color-action-primary-background-press);
15895
+
15896
+ --db-primary-surface-active: initial; /* TODO */
15897
+ --db-primary-surface-hover: var(--db-color-action-primary-background-hover);
15898
+ --db-primary-surface-pressed: var(--db-color-action-primary-background-press);
15899
+ --db-primary-surface-disabled: var(--db-color-action-disabled-background);
15900
+ --db-text-on-primary-surface-disabled: var(--db-color-action-disabled-text);
15901
+
15902
+ /* Error */
15903
+ --db-error-surface: var(--db-color-action-danger-primary-background-default);
15904
+ --db-subtle-error-surface: var(--db-color-background-danger);
15905
+ --db-strong-error-surface: var(--db-color-action-danger-primary-background-hover);
15906
+
15907
+ --db-text-on-error-surface: var(--db-color-action-danger-primary-text);
15908
+ --db-error-text-on-neutral-surface: var(--db-color-text-validation-danger);
15909
+ --db-subtle-text-on-error-surface: initial; /* TODO */
15910
+ --db-strong-text-on-error-surface: var(--db-color-action-danger-primary-text);
15911
+
15912
+ --db-error-border: var(--db-color-action-danger-default-border-default);
15913
+ --db-subtle-error-border: var(--db-color-border-danger);
15914
+ --db-strong-error-border: var(--db-color-action-danger-primary-background-press);
15915
+
15916
+ --db-error-surface-active: initial; /* TODO */
15917
+ --db-error-surface-hover: var(--db-color-action-danger-primary-background-hover);
15918
+ --db-error-surface-pressed: var(--db-color-action-danger-primary-background-press);
15919
+ --db-error-surface-disabled: var(--db-color-action-disabled-background);
15920
+ --db-text-on-error-surface-disabled: var(--db-color-action-disabled-text);
15921
+
15922
+ /* Warning */
15923
+ --db-warning-surface: initial; /* TODO */
15924
+ --db-subtle-warning-surface: var(--db-color-background-warning);
15925
+
15926
+ --db-text-on-warning-surface: initial; /* TODO */
15927
+ --db-warning-text-on-neutral-surface: var(--db-color-text-validation-warning);
15928
+
15929
+ --db-warning-border: var(--db-color-border-warning);
15930
+
15931
+ /* Success */
15932
+ --db-success-surface: initial; /* TODO */
15933
+ --db-subtle-success-surface: var(--db-color-background-success);
15934
+
15935
+ --db-text-on-success-surface: initial; /* TODO */
15936
+ --db-success-text-on-neutral-surface: var(--db-color-text-validation-success);
15937
+
15938
+ --db-success-border: initial; /* TODO */
15939
+ }
15940
+
15941
+
15942
+
15943
+ :where(:root), :where(.du-bois-light) {
15944
+ --db-layout-unit: 0.25rem; /* 4px */
15945
+ --db-density-scalar: 1;
15946
+ --db-size-scalar: 1;
15947
+ --db-spacing-scalar: 1;
15948
+
15949
+ /* Size and spacing are the same steps, but with their own scalars included in the calc. */
15950
+
15951
+ --db-size-3xs: calc(var(--db-layout-unit) * 1 * var(--db-density-scalar) * var(--db-size-scalar)); /* 4px */
15952
+ --db-size-2xs: calc(var(--db-layout-unit) * 2 * var(--db-density-scalar) * var(--db-size-scalar)); /* 8px */
15953
+ --db-size-xs: calc(var(--db-layout-unit) * 4 * var(--db-density-scalar) * var(--db-size-scalar)); /* 16px */
15954
+ --db-size-sm: calc(var(--db-layout-unit) * 6 * var(--db-density-scalar) * var(--db-size-scalar)); /* 24px */
15955
+ --db-size-md: calc(var(--db-layout-unit) * 8 * var(--db-density-scalar) * var(--db-size-scalar)); /* 32px */
15956
+ --db-size-lg: calc(var(--db-layout-unit) * 10 * var(--db-density-scalar) * var(--db-size-scalar)); /* 40px */
15957
+
15958
+ --db-spacing-3xs: calc(var(--db-layout-unit) * 1 * var(--db-density-scalar) * var(--db-spacing-scalar)); /* 4px */
15959
+ --db-spacing-2xs: calc(var(--db-layout-unit) * 2 * var(--db-density-scalar) * var(--db-spacing-scalar)); /* 8px */
15960
+ --db-spacing-xs: calc(var(--db-layout-unit) * 4 * var(--db-density-scalar) * var(--db-spacing-scalar)); /* 16px */
15961
+ --db-spacing-sm: calc(var(--db-layout-unit) * 6 * var(--db-density-scalar) * var(--db-spacing-scalar)); /* 24px */
15962
+ --db-spacing-md: calc(var(--db-layout-unit) * 8 * var(--db-density-scalar) * var(--db-spacing-scalar)); /* 32px */
15963
+ --db-spacing-lg: calc(var(--db-layout-unit) * 10 * var(--db-density-scalar) * var(--db-spacing-scalar)); /* 40px */
15964
+ }
15965
+
15966
+ :where(:root), :where(.du-bois-light) {
15967
+ --db-font-family:
15968
+ "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
15969
+ --db-mono-font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
15970
+
15971
+ --db-font-size-2xs: 0.6875rem; /* 11px */
15972
+ --db-font-size-xs: 0.75rem; /* 12px */
15973
+ --db-font-size-base: 0.8125rem; /* 13px */
15974
+ --db-font-size-md: 0.875rem; /* 14px */
15975
+ --db-font-size-lg: 0.9375rem; /* 15px */
15976
+ --db-font-size-xl: 1rem; /* 16px */
15977
+ --db-font-size-2xl: 1.25rem; /* 20px */
15978
+ --db-font-size-3xl: 1.5rem; /* 24px */
15979
+ --db-font-size-4xl: 2rem; /* 32px */
15980
+
15981
+ /* Du Bois v1 ships 400 and 600 only */
15982
+ --db-font-weight-normal: 400;
15983
+ --db-font-weight-medium: initial; /* TODO */
15984
+ --db-font-weight-semibold: 600;
15985
+ --db-font-weight-bold: initial; /* TODO */
15986
+ }
15987
+
15988
+ :where(:root), :where(.du-bois-light) {
15989
+ --db-elevation-inset: initial; /* TODO */
15990
+ --db-elevation-low: 0px 2px 3px -1px rgba(0, 0, 0, 0.05), 0px 1px 0px 0px rgba(0, 0, 0, 0.02);
15991
+ --db-elevation-med: 0px 2px 16px 0px rgba(0, 0, 0, 0.08);
15992
+ --db-elevation-high: 0px 8px 40px 0px rgba(0, 0, 0, 0.13);
15993
+ }
15994
+
15995
+ :where(:root), :where(.du-bois-light) {
15996
+ --db-focus-ring-color: var(--db-color-action-default-border-focus);
15997
+ --db-focus-ring-width: 2px;
15998
+ }
15999
+
16000
+ :where(:root), :where(.du-bois-light) {
16001
+ /* Shape */
16002
+ --db-selection-toggle-border-radius: 4px;
16003
+
16004
+ /* Color */
16005
+ --db-selection-toggle-surface: var(--db-neutral-surface);
16006
+ --db-selection-toggle-mark: var(--db-text-on-primary-surface);
16007
+ --db-selection-toggle-text: var(--db-text-on-neutral-surface);
16008
+ --db-selection-toggle-border: var(--db-strong-neutral-border);
16009
+
16010
+ --db-selection-toggle-surface-hover: var(--db-neutral-surface-hover);
16011
+ --db-selection-toggle-surface-press: var(--db-neutral-surface-pressed);
16012
+ --db-selection-toggle-surface-checked: var(--db-primary-surface);
16013
+ --db-selection-toggle-surface-checked-hover: var(--db-primary-surface-hover);
16014
+ --db-selection-toggle-surface-checked-press: var(--db-primary-surface-pressed);
16015
+ --db-selection-toggle-surface-disabled: var(--db-neutral-surface-disabled);
16016
+ --db-selection-toggle-surface-checked-disabled: var(--db-neutral-surface-disabled);
16017
+
16018
+ --db-selection-toggle-border-hover: var(--db-primary-surface-hover);
16019
+ --db-selection-toggle-border-press: var(--db-primary-surface-pressed);
16020
+ --db-selection-toggle-border-disabled: var(--db-neutral-border);
16021
+
16022
+ --db-selection-toggle-mark-disabled: var(--db-text-on-neutral-surface-disabled);
16023
+ --db-selection-toggle-text-disabled: var(--db-text-on-neutral-surface-disabled);
16024
+
16107
16025
  --db-selection-toggle-shadow-checked: 0 0 0 1px var(--db-color-action-primary-background-default);
16108
- --db-selection-toggle-focus-ring-width: 2px;
16109
- --db-selection-toggle-focus-ring-offset: 2px;
16026
+
16027
+ /* Density */
16028
+ --db-selection-toggle-size: var(--db-size-xs);
16029
+ --db-selection-toggle-label-spacing: var(--db-spacing-2xs);
16030
+
16031
+ /* Motion */
16110
16032
  --db-selection-toggle-transition-duration: 120ms;
16111
16033
  }
16112
16034
 
16113
- /* Component-tier tokens for <Checkbox>. Each value defaults to a CATEGORY
16114
- * (selection-toggle) token via var(); consumers can override here to retheme
16115
- * checkboxes without affecting switch / radio. */
16116
-
16117
- /* Re-declared under both theme classes (not just :root) so the var() chain onto
16118
- * category/system tokens re-resolves inside a `.du-bois-dark` subtree instead of
16119
- * freezing at the root (light) values. See DUBOIS-448 dark-mode scoping. */
16120
- :where(:root, .du-bois-light, .du-bois-dark) {
16121
- --db-checkbox-size: var(--db-selection-toggle-size);
16035
+ :where(:root), :where(.du-bois-light) {
16036
+ /* Shape */
16122
16037
  --db-checkbox-border-radius: var(--db-selection-toggle-border-radius);
16123
16038
  --db-checkbox-border-width: 1px;
16124
- --db-checkbox-spacing: var(--db-selection-toggle-spacing);
16125
16039
 
16126
- --db-checkbox-bg-default: var(--db-selection-toggle-bg-default);
16127
- --db-checkbox-bg-hover: var(--db-selection-toggle-bg-hover);
16128
- --db-checkbox-bg-press: var(--db-selection-toggle-bg-press);
16129
- --db-checkbox-bg-checked: var(--db-selection-toggle-bg-checked);
16130
- --db-checkbox-bg-checked-hover: var(--db-selection-toggle-bg-checked-hover);
16131
- --db-checkbox-bg-checked-press: var(--db-selection-toggle-bg-checked-press);
16132
- --db-checkbox-bg-disabled: var(--db-selection-toggle-bg-disabled);
16040
+ /* Color */
16041
+ --db-checkbox-surface: var(--db-selection-toggle-surface);
16042
+ --db-checkbox-surface-hover: var(--db-color-action-default-background-hover);
16043
+ --db-checkbox-surface-press: var(--db-color-action-default-background-press);
16044
+ --db-checkbox-surface-checked: var(--db-selection-toggle-surface-checked);
16045
+ --db-checkbox-surface-checked-hover: var(--db-selection-toggle-surface-checked-hover);
16046
+ --db-checkbox-surface-checked-press: var(--db-selection-toggle-surface-checked-press);
16047
+ --db-checkbox-surface-disabled: var(--db-selection-toggle-surface-disabled);
16133
16048
 
16134
- --db-checkbox-border-default: var(--db-selection-toggle-border-default);
16049
+ --db-checkbox-border: var(--db-color-action-default-border-default);
16135
16050
  --db-checkbox-border-hover: var(--db-selection-toggle-border-hover);
16136
16051
  --db-checkbox-border-press: var(--db-selection-toggle-border-press);
16137
- --db-checkbox-border-focus: var(--db-selection-toggle-border-focus);
16138
- --db-checkbox-border-disabled: var(--db-selection-toggle-border-disabled);
16052
+ --db-checkbox-focus-ring: var(--db-focus-ring-color);
16053
+ --db-checkbox-border-disabled: var(--db-color-action-disabled-border);
16139
16054
 
16140
- --db-checkbox-icon-color: var(--db-selection-toggle-icon-color);
16141
- --db-checkbox-icon-color-disabled: var(--db-selection-toggle-icon-color-disabled);
16055
+ --db-checkbox-mark: #ffffff;
16056
+ --db-checkbox-mark-disabled: var(--db-selection-toggle-mark-disabled);
16142
16057
  --db-checkbox-text: var(--db-selection-toggle-text);
16143
16058
  --db-checkbox-text-disabled: var(--db-selection-toggle-text-disabled);
16144
16059
 
16145
16060
  --db-checkbox-shadow-checked: var(--db-selection-toggle-shadow-checked);
16146
- --db-checkbox-focus-ring-width: var(--db-selection-toggle-focus-ring-width);
16147
- --db-checkbox-focus-ring-offset: var(--db-selection-toggle-focus-ring-offset);
16148
- --db-checkbox-transition-duration: var(--db-selection-toggle-transition-duration);
16149
16061
 
16150
- /* Indeterminate mark — sized to look like AntD's `<inner>` ::after dash. */
16151
- --db-checkbox-indeterminate-mark-width: 8px;
16152
- --db-checkbox-indeterminate-mark-height: 2px;
16062
+ /* Density */
16063
+ --db-checkbox-size: var(--db-selection-toggle-size);
16064
+ --db-checkbox-label-spacing: var(--db-selection-toggle-label-spacing);
16065
+ --db-checkbox-focus-ring-width: var(--db-focus-ring-width);
16066
+ --db-checkbox-indeterminate-mark-width: var(--db-size-2xs); /* 8px */
16067
+ --db-checkbox-indeterminate-mark-height: calc(var(--db-size-3xs) * 0.75); /* 3px */
16068
+
16069
+ /* Motion */
16070
+ --db-checkbox-transition-duration: var(--db-selection-toggle-transition-duration);
16153
16071
  }
16154
16072
 
16155
16073
  /* Native-input <Checkbox> styles. Classic CSS only — no native nesting (the
@@ -16196,35 +16114,34 @@ span.du-bois-light-typography-ellipsis-single-line {
16196
16114
  width: fit-content;
16197
16115
  }
16198
16116
 
16199
- /* Hover/press live on the root (label), not on the input: the input has
16200
- * `pointer-events: none` (so a single click target stays on the label and
16201
- * label/input association toggles the box), which means `input:hover` would
16202
- * never match. Putting `:hover` on the root also makes the entire label area
16117
+ /* Hover/press live on the root (label), not on the input: the input is
16118
+ * visually hidden (opacity:0), so an `input:hover` rule wouldn't be visible
16119
+ * anyway. Putting `:hover` on the root also makes the entire label area
16203
16120
  * — not just the indicator square — drive the visual feedback. */
16204
16121
  .ds-checkbox:hover:has(.ds-checkbox-input:not(:disabled, :checked, :indeterminate)) .ds-checkbox-indicator {
16205
- background-color: var(--db-checkbox-bg-hover);
16122
+ background-color: var(--db-checkbox-surface-hover);
16206
16123
  border-color: var(--db-checkbox-border-hover);
16207
16124
  }
16208
16125
 
16209
16126
  .ds-checkbox:active:has(.ds-checkbox-input:not(:disabled, :checked, :indeterminate)) .ds-checkbox-indicator {
16210
- background-color: var(--db-checkbox-bg-press);
16127
+ background-color: var(--db-checkbox-surface-press);
16211
16128
  border-color: var(--db-checkbox-border-press);
16212
16129
  }
16213
16130
 
16214
16131
  /* Selected fill — checked and indeterminate share the same surface. */
16215
16132
  .ds-checkbox:has(.ds-checkbox-input:is(:checked, :indeterminate)) .ds-checkbox-indicator {
16216
- background-color: var(--db-checkbox-bg-checked);
16217
- border-color: var(--db-checkbox-bg-checked);
16133
+ background-color: var(--db-checkbox-surface-checked);
16134
+ border-color: var(--db-checkbox-surface-checked);
16218
16135
  }
16219
16136
 
16220
16137
  .ds-checkbox:hover:has(.ds-checkbox-input:is(:checked, :indeterminate):not(:disabled)) .ds-checkbox-indicator {
16221
- background-color: var(--db-checkbox-bg-checked-hover);
16222
- border-color: var(--db-checkbox-bg-checked-hover);
16138
+ background-color: var(--db-checkbox-surface-checked-hover);
16139
+ border-color: var(--db-checkbox-surface-checked-hover);
16223
16140
  }
16224
16141
 
16225
16142
  .ds-checkbox:active:has(.ds-checkbox-input:is(:checked, :indeterminate):not(:disabled)) .ds-checkbox-indicator {
16226
- background-color: var(--db-checkbox-bg-checked-press);
16227
- border-color: var(--db-checkbox-bg-checked-press);
16143
+ background-color: var(--db-checkbox-surface-checked-press);
16144
+ border-color: var(--db-checkbox-surface-checked-press);
16228
16145
  }
16229
16146
 
16230
16147
  /* Mark visibility. */
@@ -16238,8 +16155,8 @@ span.du-bois-light-typography-ellipsis-single-line {
16238
16155
 
16239
16156
  /* Focus-visible (keyboard only). */
16240
16157
  .ds-checkbox:has(.ds-checkbox-input:focus-visible) .ds-checkbox-indicator {
16241
- outline: var(--db-checkbox-focus-ring-width) solid var(--db-checkbox-border-focus);
16242
- outline-offset: var(--db-checkbox-focus-ring-offset);
16158
+ outline: var(--db-checkbox-focus-ring-width) solid var(--db-checkbox-focus-ring);
16159
+ outline-offset: 4px;
16243
16160
  }
16244
16161
 
16245
16162
  /* Disabled (covers unchecked, checked, indeterminate). Sourced from
@@ -16254,22 +16171,28 @@ span.du-bois-light-typography-ellipsis-single-line {
16254
16171
  }
16255
16172
 
16256
16173
  .ds-checkbox:has(.ds-checkbox-input:disabled) .ds-checkbox-indicator {
16257
- background-color: var(--db-checkbox-bg-disabled);
16174
+ background-color: var(--db-checkbox-surface-disabled);
16258
16175
  border-color: var(--db-checkbox-border-disabled);
16259
16176
  box-shadow: none;
16260
16177
  }
16261
16178
 
16262
16179
  .ds-checkbox:has(.ds-checkbox-input:disabled) .ds-checkbox-checkmark {
16263
- color: var(--db-checkbox-icon-color-disabled);
16180
+ color: var(--db-checkbox-mark-disabled);
16264
16181
  }
16265
16182
 
16266
16183
  .ds-checkbox:has(.ds-checkbox-input:disabled) .ds-checkbox-dash {
16267
- background-color: var(--db-checkbox-icon-color-disabled);
16184
+ background-color: var(--db-checkbox-mark-disabled);
16268
16185
  }
16269
16186
 
16270
- /* Visually-hidden native input, kept interactive and in the tab order so
16271
- * `:has()` lookups above can read its state. Pointer events fall through to
16272
- * the label, so clicking anywhere toggles the box. */
16187
+ /* Visually-hidden native input (opacity:0) overlaying the indicator square,
16188
+ * kept interactive and in the tab order so `:has()` lookups above can read its
16189
+ * state. It stays pointer-clickable matching AntD's `.ant-checkbox-input`
16190
+ * so it is the top-most hit-test target over the box: `getByRole('checkbox').click()`
16191
+ * (Playwright, and any coordinate click that lands on the box) resolves to the
16192
+ * real control instead of the decorative indicator overlay. Making the input
16193
+ * `pointer-events: none` (the prior native-only behavior) is what regressed
16194
+ * interaction tests vs. the AntD variant. `cursor: inherit` tracks the label's
16195
+ * pointer / disabled `not-allowed` cursor so the box keeps AntD's cursor too. */
16273
16196
  .ds-checkbox .ds-checkbox-input {
16274
16197
  position: absolute;
16275
16198
  inset: 0;
@@ -16277,7 +16200,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16277
16200
  block-size: var(--db-checkbox-size);
16278
16201
  margin: 0;
16279
16202
  opacity: 0;
16280
- pointer-events: none;
16203
+ cursor: inherit;
16281
16204
  }
16282
16205
 
16283
16206
  /* Indicator — square with the border/fill that responds to state above.
@@ -16288,12 +16211,18 @@ span.du-bois-light-typography-ellipsis-single-line {
16288
16211
  display: grid;
16289
16212
  place-items: center;
16290
16213
  flex-shrink: 0;
16214
+ /* Decorative only — the overlaid input owns hit-testing. Without this, the
16215
+ * indicator (and its inherited checkmark/dash children) intercept
16216
+ * `getByRole('checkbox').click()`; clicks on any edge sliver the input does
16217
+ * not cover fall through to the label, which toggles via label/input
16218
+ * association. */
16219
+ pointer-events: none;
16291
16220
  inline-size: var(--db-checkbox-size);
16292
16221
  block-size: var(--db-checkbox-size);
16293
16222
  margin-top: calc((var(--db-line-height-base, 20px) - var(--db-checkbox-size)) / 2);
16294
- border: var(--db-checkbox-border-width) solid var(--db-checkbox-border-default);
16223
+ border: var(--db-checkbox-border-width) solid var(--db-checkbox-border);
16295
16224
  border-radius: var(--db-checkbox-border-radius);
16296
- background-color: var(--db-checkbox-bg-default);
16225
+ background-color: var(--db-checkbox-surface);
16297
16226
  box-sizing: border-box;
16298
16227
  transition:
16299
16228
  background-color var(--db-checkbox-transition-duration) ease,
@@ -16305,7 +16234,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16305
16234
  grid-area: 1 / 1;
16306
16235
  inline-size: 100%;
16307
16236
  block-size: 100%;
16308
- color: var(--db-checkbox-icon-color);
16237
+ color: var(--db-checkbox-mark);
16309
16238
  opacity: 0;
16310
16239
  transition: opacity var(--db-checkbox-transition-duration) ease;
16311
16240
  }
@@ -16322,8 +16251,10 @@ span.du-bois-light-typography-ellipsis-single-line {
16322
16251
  grid-area: 1 / 1;
16323
16252
  inline-size: var(--db-checkbox-indeterminate-mark-width);
16324
16253
  block-size: var(--db-checkbox-indeterminate-mark-height);
16325
- border-radius: 1px;
16326
- background-color: var(--db-checkbox-icon-color);
16254
+ /* CSS clamps this to half the 3px height, giving fully rounded end caps so the
16255
+ * dash reads as a pill rather than a flat bar. */
16256
+ border-radius: 4px;
16257
+ background-color: var(--db-checkbox-mark);
16327
16258
  opacity: 0;
16328
16259
  transition: opacity var(--db-checkbox-transition-duration) ease;
16329
16260
  }
@@ -16335,7 +16266,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16335
16266
  * as the AntD variant. */
16336
16267
  .ds-checkbox .ds-checkbox-label {
16337
16268
  color: var(--db-checkbox-text);
16338
- padding-inline: var(--db-checkbox-spacing);
16269
+ padding-inline: var(--db-checkbox-label-spacing);
16339
16270
  word-break: break-word;
16340
16271
  }
16341
16272
 
@@ -16360,7 +16291,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16360
16291
  .ds-checkbox.ds-checkbox + .du-bois-dark-form-message,
16361
16292
  .ds-checkbox.ds-checkbox + .du-bois-light-hint + .du-bois-light-form-message,
16362
16293
  .ds-checkbox.ds-checkbox + .du-bois-dark-hint + .du-bois-dark-form-message {
16363
- padding-left: var(--db-space-lg);
16294
+ padding-left: var(--db-spacing-sm);
16364
16295
  margin-top: 0;
16365
16296
  }
16366
16297
 
@@ -16371,7 +16302,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16371
16302
  .du-bois-dark-hint + .ds-checkbox-group.ds-checkbox-group,
16372
16303
  .ds-checkbox-group.ds-checkbox-group + .du-bois-light-form-message,
16373
16304
  .ds-checkbox-group.ds-checkbox-group + .du-bois-dark-form-message {
16374
- margin-top: var(--db-space-sm);
16305
+ margin-top: var(--db-spacing-2xs);
16375
16306
  }
16376
16307
 
16377
16308
  /* CheckboxGroup layout. Vertical delegates to the `.ds-stack` primitive; the
@@ -16387,82 +16318,51 @@ span.du-bois-light-typography-ellipsis-single-line {
16387
16318
  * off the vertical element so it never fights the stack primitive's gap. */
16388
16319
  .ds-checkbox-group:not(.ds-stack) {
16389
16320
  flex-wrap: nowrap;
16390
- column-gap: var(--db-checkbox-spacing);
16321
+ column-gap: var(--db-checkbox-label-spacing);
16391
16322
  row-gap: 0;
16392
16323
  }
16393
16324
 
16394
16325
  /* Vertical: .ds-stack supplies flex-direction + gap; we only retarget the knob. */
16395
16326
  .ds-checkbox-group.ds-stack {
16396
- --ds-stack-gap: var(--db-checkbox-spacing);
16327
+ --ds-stack-gap: var(--db-checkbox-label-spacing);
16397
16328
  }
16398
16329
 
16399
- /* Component-tier tokens for <Radio>. Each value defaults to a CATEGORY
16400
- * (selection-toggle) token via var(); consumers can override here to retheme
16401
- * radios without affecting checkbox / switch.
16402
- *
16403
- * Radio differs from Checkbox in two ways: the indicator is a full circle
16404
- * (border-radius) and the "mark" is a filled dot rather than a checkmark/dash. */
16405
-
16406
- /* Re-declared under both theme classes (not just :root) so the var() chain onto
16407
- * category/system tokens re-resolves inside a `.du-bois-dark` subtree instead of
16408
- * freezing at the root (light) values. See DUBOIS-448 dark-mode scoping. */
16409
- :where(:root, .du-bois-light, .du-bois-dark) {
16410
- --db-radio-size: var(--db-selection-toggle-size);
16411
- /* Circle, not a rounded square — the one shape token that does NOT inherit
16412
- * the category (square) radius. */
16330
+ :where(:root), :where(.du-bois-light) {
16331
+ /* Shape */
16413
16332
  --db-radio-border-radius: var(--db-radius-full);
16414
16333
  --db-radio-border-width: 1px;
16415
- --db-radio-spacing: var(--db-selection-toggle-spacing);
16416
-
16417
- --db-radio-bg-default: var(--db-selection-toggle-bg-default);
16418
- --db-radio-bg-hover: var(--db-selection-toggle-bg-hover);
16419
- --db-radio-bg-press: var(--db-selection-toggle-bg-press);
16420
- --db-radio-bg-checked: var(--db-selection-toggle-bg-checked);
16421
- --db-radio-bg-checked-hover: var(--db-selection-toggle-bg-checked-hover);
16422
- /* AntD checked active/press background is actionDefaultBackgroundPress (NOT the
16423
- * primary press), so this maps to the default press bg category token — see
16424
- * getRadioInputStyles checked active in AntDRadioInternal.tsx. */
16425
- --db-radio-bg-checked-press: var(--db-selection-toggle-bg-press);
16426
- --db-radio-bg-disabled: var(--db-selection-toggle-bg-disabled);
16427
-
16428
- --db-radio-border-default: var(--db-selection-toggle-border-default);
16334
+
16335
+ /* Color */
16336
+ --db-radio-surface: var(--db-selection-toggle-surface);
16337
+ --db-radio-surface-hover: var(--db-color-action-default-background-hover);
16338
+ --db-radio-surface-press: var(--db-color-action-default-background-press);
16339
+ --db-radio-surface-checked: var(--db-selection-toggle-surface-checked);
16340
+ --db-radio-surface-checked-hover: var(--db-selection-toggle-surface-checked-hover);
16341
+ --db-radio-surface-checked-press: var(--db-color-action-default-background-press);
16342
+ --db-radio-surface-disabled: var(--db-selection-toggle-surface-disabled);
16343
+
16344
+ --db-radio-border: var(--db-color-action-default-border-default);
16429
16345
  --db-radio-border-hover: var(--db-selection-toggle-border-hover);
16430
16346
  --db-radio-border-press: var(--db-selection-toggle-border-press);
16431
- --db-radio-border-focus: var(--db-selection-toggle-border-focus);
16432
- --db-radio-border-disabled: var(--db-selection-toggle-border-disabled);
16433
-
16434
- /* Two-tone checked hover/press border ring (AntD getRadioInputStyles checked
16435
- * states): the border is a DARKER shade than the fill, not equal to it.
16436
- * - checked hover border = actionPrimaryBackgroundPress (== the press category
16437
- * token, which is action-primary-background-press).
16438
- * - checked press border = actionDefaultBorderPress; no selection-toggle
16439
- * category token equals this color, so reference the system token directly. */
16347
+ --db-radio-border-focus: var(--db-focus-ring-color);
16348
+ --db-radio-border-disabled: var(--db-color-action-disabled-border);
16440
16349
  --db-radio-border-checked-hover: var(--db-selection-toggle-border-press);
16441
16350
  --db-radio-border-checked-press: var(--db-color-action-default-border-press);
16351
+ --db-radio-border-unchecked-focus: var(--db-color-action-primary-background-default);
16352
+ --db-radio-outline-checked-focus: var(--db-color-action-primary-background-default);
16442
16353
 
16443
- /* Unchecked keyboard-focus border (AntD getRadioInputStyles unchecked focus):
16444
- * borderColor = actionPrimaryBackgroundDefault, with NO outline ring. No
16445
- * selection-toggle category token equals this color (the closest is a bg
16446
- * token), so reference the system token directly. */
16447
- --db-radio-border-focus-unchecked: var(--db-color-action-primary-background-default);
16448
- /* Checked focus-visible outline color (AntD: outline 1px solid
16449
- * actionPrimaryBackgroundDefault, outlineOffset 1). */
16450
- --db-radio-focus-outline-checked-color: var(--db-color-action-primary-background-default);
16451
-
16452
- /* The dot. Shares the category icon-color token (white over the filled
16453
- * primary surface) so a retheme moves checkbox checkmark + radio dot together. */
16454
- --db-radio-dot-color: var(--db-selection-toggle-icon-color);
16455
- --db-radio-dot-color-disabled: var(--db-selection-toggle-icon-color-disabled);
16354
+ --db-radio-mark: #ffffff;
16355
+ --db-radio-mark-disabled: var(--db-selection-toggle-mark-disabled);
16456
16356
  --db-radio-text: var(--db-selection-toggle-text);
16457
16357
  --db-radio-text-disabled: var(--db-selection-toggle-text-disabled);
16458
16358
 
16459
- --db-radio-focus-ring-width: var(--db-selection-toggle-focus-ring-width);
16460
- --db-radio-focus-ring-offset: var(--db-selection-toggle-focus-ring-offset);
16461
- --db-radio-transition-duration: var(--db-selection-toggle-transition-duration);
16359
+ /* Density */
16360
+ --db-radio-size: var(--db-selection-toggle-size);
16361
+ --db-radio-label-spacing: var(--db-selection-toggle-label-spacing);
16362
+ --db-radio-mark-size: var(--db-size-3xs);
16462
16363
 
16463
- /* Diameter of the inner dot. Mirrors the AntD checked `::after` size, which uses
16464
- * `theme.spacing.xs` (4px) — see getRadioInputStyles in AntDRadioInternal.tsx. */
16465
- --db-radio-dot-size: var(--db-space-xs);
16364
+ /* Motion */
16365
+ --db-radio-transition-duration: var(--db-selection-toggle-transition-duration);
16466
16366
  }
16467
16367
 
16468
16368
  /* Native-input <Radio> styles. Classic CSS only — no native nesting (the
@@ -16501,36 +16401,36 @@ span.du-bois-light-typography-ellipsis-single-line {
16501
16401
  width: fit-content;
16502
16402
  }
16503
16403
 
16504
- /* Hover/press live on the root (label), not on the input: the input has
16505
- * `pointer-events: none`, so `input:hover` would never match, and the whole
16506
- * label area should drive the feedback. */
16404
+ /* Hover/press live on the root (label), not on the input: the input is
16405
+ * visually hidden (opacity:0), so an `input:hover` rule wouldn't be visible
16406
+ * anyway, and the whole label area should drive the feedback. */
16507
16407
  .ds-radio:hover:has(input:not(:disabled, :checked)) .ds-radio-indicator {
16508
- background-color: var(--db-radio-bg-hover);
16408
+ background-color: var(--db-radio-surface-hover);
16509
16409
  border-color: var(--db-radio-border-hover);
16510
16410
  }
16511
16411
 
16512
16412
  .ds-radio:active:has(input:not(:disabled, :checked)) .ds-radio-indicator {
16513
- background-color: var(--db-radio-bg-press);
16413
+ background-color: var(--db-radio-surface-press);
16514
16414
  border-color: var(--db-radio-border-press);
16515
16415
  }
16516
16416
 
16517
16417
  /* Selected fill. */
16518
16418
  .ds-radio:has(input:checked) .ds-radio-indicator {
16519
- background-color: var(--db-radio-bg-checked);
16520
- border-color: var(--db-radio-bg-checked);
16419
+ background-color: var(--db-radio-surface-checked);
16420
+ border-color: var(--db-radio-surface-checked);
16521
16421
  }
16522
16422
 
16523
16423
  /* AntD getRadioInputStyles checked hover: background = actionPrimaryBackgroundHover,
16524
16424
  * borderColor = actionPrimaryBackgroundPress (a darker ring than the fill). */
16525
16425
  .ds-radio:hover:has(input:checked:not(:disabled)) .ds-radio-indicator {
16526
- background-color: var(--db-radio-bg-checked-hover);
16426
+ background-color: var(--db-radio-surface-checked-hover);
16527
16427
  border-color: var(--db-radio-border-checked-hover);
16528
16428
  }
16529
16429
 
16530
16430
  /* AntD getRadioInputStyles checked active: background = actionDefaultBackgroundPress,
16531
16431
  * borderColor = actionDefaultBorderPress (two-tone, not flat). */
16532
16432
  .ds-radio:active:has(input:checked:not(:disabled)) .ds-radio-indicator {
16533
- background-color: var(--db-radio-bg-checked-press);
16433
+ background-color: var(--db-radio-surface-checked-press);
16534
16434
  border-color: var(--db-radio-border-checked-press);
16535
16435
  }
16536
16436
 
@@ -16545,16 +16445,16 @@ span.du-bois-light-typography-ellipsis-single-line {
16545
16445
  * UNCHECKED focus (AntD `&:not(disabled) > input:focus + inner`): only the border
16546
16446
  * color changes to actionPrimaryBackgroundDefault — NO outline ring. */
16547
16447
  .ds-radio:has(input:focus-visible:not(:checked)) .ds-radio-indicator {
16548
- border-color: var(--db-radio-border-focus-unchecked);
16448
+ border-color: var(--db-radio-border-unchecked-focus);
16549
16449
  }
16550
16450
 
16551
16451
  /* CHECKED focus-visible (AntD `&.checked &:not(disabled) > input:focus-visible + inner`):
16552
16452
  * background = actionPrimaryBackgroundDefault, borderColor = actionDefaultBorderFocus,
16553
16453
  * outline = 1px solid actionPrimaryBackgroundDefault, outlineOffset = 1. */
16554
16454
  .ds-radio:has(input:focus-visible:checked) .ds-radio-indicator {
16555
- background-color: var(--db-radio-bg-checked);
16455
+ background-color: var(--db-radio-surface-checked);
16556
16456
  border-color: var(--db-radio-border-focus);
16557
- outline: 1px solid var(--db-radio-focus-outline-checked-color);
16457
+ outline: 1px solid var(--db-radio-outline-checked-focus);
16558
16458
  outline-offset: 1px;
16559
16459
  }
16560
16460
 
@@ -16569,18 +16469,24 @@ span.du-bois-light-typography-ellipsis-single-line {
16569
16469
  }
16570
16470
 
16571
16471
  .ds-radio:has(input:disabled) .ds-radio-indicator {
16572
- background-color: var(--db-radio-bg-disabled);
16472
+ background-color: var(--db-radio-surface-disabled);
16573
16473
  border-color: var(--db-radio-border-disabled);
16574
16474
  box-shadow: none;
16575
16475
  }
16576
16476
 
16577
16477
  .ds-radio:has(input:disabled) .ds-radio-dot {
16578
- background-color: var(--db-radio-dot-color-disabled);
16478
+ background-color: var(--db-radio-mark-disabled);
16579
16479
  }
16580
16480
 
16581
- /* Visually-hidden native input, kept interactive and in the tab order so the
16582
- * `:has()` lookups above can read its state. Pointer events fall through to the
16583
- * label, so clicking anywhere toggles the radio. */
16481
+ /* Visually-hidden native input (opacity:0) overlaying the indicator circle,
16482
+ * kept interactive and in the tab order so the `:has()` lookups above can read
16483
+ * its state. It stays pointer-clickable matching AntD's `.ant-radio-input`
16484
+ * so it is the top-most hit-test target over the circle: `getByRole('radio').click()`
16485
+ * (Playwright, and any coordinate click that lands on the circle) resolves to the
16486
+ * real control instead of the decorative indicator overlay. Making the input
16487
+ * `pointer-events: none` (the prior native-only behavior) is what regressed
16488
+ * interaction tests vs. the AntD variant. `cursor: inherit` tracks the label's
16489
+ * pointer / disabled `not-allowed` cursor so the circle keeps AntD's cursor too. */
16584
16490
  .ds-radio input {
16585
16491
  position: absolute;
16586
16492
  inset: 0;
@@ -16588,7 +16494,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16588
16494
  block-size: var(--db-radio-size);
16589
16495
  margin: 0;
16590
16496
  opacity: 0;
16591
- pointer-events: none;
16497
+ cursor: inherit;
16592
16498
  }
16593
16499
 
16594
16500
  /* Indicator — circle with the border/fill that responds to state above.
@@ -16598,12 +16504,17 @@ span.du-bois-light-typography-ellipsis-single-line {
16598
16504
  display: grid;
16599
16505
  place-items: center;
16600
16506
  flex-shrink: 0;
16507
+ /* Decorative only — the overlaid input owns hit-testing. Without this, the
16508
+ * indicator (and its inherited dot child) intercept `getByRole('radio').click()`;
16509
+ * clicks on any edge sliver the input does not cover fall through to the label,
16510
+ * which toggles via label/input association. */
16511
+ pointer-events: none;
16601
16512
  inline-size: var(--db-radio-size);
16602
16513
  block-size: var(--db-radio-size);
16603
16514
  margin-top: calc((var(--db-line-height-base, 20px) - var(--db-radio-size)) / 2);
16604
- border: var(--db-radio-border-width) solid var(--db-radio-border-default);
16515
+ border: var(--db-radio-border-width) solid var(--db-radio-border);
16605
16516
  border-radius: var(--db-radio-border-radius);
16606
- background-color: var(--db-radio-bg-default);
16517
+ background-color: var(--db-radio-surface);
16607
16518
  box-sizing: border-box;
16608
16519
  transition:
16609
16520
  background-color var(--db-radio-transition-duration) ease,
@@ -16613,10 +16524,10 @@ span.du-bois-light-typography-ellipsis-single-line {
16613
16524
 
16614
16525
  .ds-radio .ds-radio-indicator > .ds-radio-dot {
16615
16526
  grid-area: 1 / 1;
16616
- inline-size: var(--db-radio-dot-size);
16617
- block-size: var(--db-radio-dot-size);
16527
+ inline-size: var(--db-radio-mark-size);
16528
+ block-size: var(--db-radio-mark-size);
16618
16529
  border-radius: var(--db-radius-full);
16619
- background-color: var(--db-radio-dot-color);
16530
+ background-color: var(--db-radio-mark);
16620
16531
  opacity: 0;
16621
16532
  transition: opacity var(--db-radio-transition-duration) ease;
16622
16533
  }
@@ -16634,7 +16545,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16634
16545
  * trailing whitespace that separates adjacent radios in a row. */
16635
16546
  .ds-radio .ds-radio-label {
16636
16547
  color: var(--db-radio-text);
16637
- padding-inline: var(--db-radio-spacing);
16548
+ padding-inline: var(--db-radio-label-spacing);
16638
16549
  word-break: break-word;
16639
16550
  }
16640
16551
 
@@ -16648,7 +16559,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16648
16559
  .ds-radio.ds-radio + .du-bois-dark-form-message,
16649
16560
  .ds-radio.ds-radio + .du-bois-light-hint + .du-bois-light-form-message,
16650
16561
  .ds-radio.ds-radio + .du-bois-dark-hint + .du-bois-dark-form-message {
16651
- padding-inline-start: var(--db-space-lg);
16562
+ padding-inline-start: var(--db-spacing-sm);
16652
16563
  margin-top: 0;
16653
16564
  }
16654
16565
 
@@ -16664,8 +16575,8 @@ span.du-bois-light-typography-ellipsis-single-line {
16664
16575
  .ds-radio-group.ds-stack > .ds-radio.ds-radio + .du-bois-dark-form-message,
16665
16576
  .ds-radio-group.ds-stack > .ds-radio.ds-radio + .du-bois-light-hint + .du-bois-light-form-message,
16666
16577
  .ds-radio-group.ds-stack > .ds-radio.ds-radio + .du-bois-dark-hint + .du-bois-dark-form-message {
16667
- margin-top: calc(-1 * var(--db-space-sm));
16668
- margin-bottom: var(--db-space-sm);
16578
+ margin-top: calc(-1 * var(--db-spacing-2xs));
16579
+ margin-bottom: var(--db-spacing-2xs);
16669
16580
  }
16670
16581
 
16671
16582
  /* AntD `& > label:last-of-type + hint { marginTop: 0 }`: the last radio has no
@@ -16683,7 +16594,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16683
16594
  .du-bois-dark-hint + .ds-radio-group.ds-radio-group,
16684
16595
  .ds-radio-group.ds-radio-group + .du-bois-light-form-message,
16685
16596
  .ds-radio-group.ds-radio-group + .du-bois-dark-form-message {
16686
- margin-top: var(--db-space-sm);
16597
+ margin-top: var(--db-spacing-2xs);
16687
16598
  }
16688
16599
 
16689
16600
  /* RadioGroup layout. Vertical (the default) delegates flex-direction to the
@@ -16699,12 +16610,12 @@ span.du-bois-light-typography-ellipsis-single-line {
16699
16610
  * no gap of its own, so we zero out the gap and reproduce the rhythm via
16700
16611
  * padding-bottom on each radio. */
16701
16612
  .ds-radio-group.ds-stack {
16702
- --ds-stack-gap: var(--db-space-0);
16613
+ --ds-stack-gap: 0;
16703
16614
  }
16704
16615
 
16705
16616
  /* AntD `& > label { paddingBottom: sm }`. */
16706
16617
  .ds-radio-group.ds-stack > .ds-radio {
16707
- padding-bottom: var(--db-space-sm);
16618
+ padding-bottom: var(--db-spacing-2xs);
16708
16619
  }
16709
16620
 
16710
16621
  /* AntD `& > label:last-of-type { paddingBottom: 0 }`. */
@@ -16720,7 +16631,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16720
16631
  .ds-radio-group.ds-stack > .du-bois-light-radio-tile + .du-bois-dark-radio-tile,
16721
16632
  .ds-radio-group.ds-stack > .du-bois-dark-radio-tile + .du-bois-light-radio-tile,
16722
16633
  .ds-radio-group.ds-stack > .du-bois-dark-radio-tile + .du-bois-dark-radio-tile {
16723
- margin-top: var(--db-space-md);
16634
+ margin-top: var(--db-spacing-xs);
16724
16635
  }
16725
16636
 
16726
16637
  /* Horizontal: AntD `getHorizontalRadioGroupStyles` is a TWO-ROW grid (NOT a flex
@@ -16733,7 +16644,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16733
16644
  display: grid;
16734
16645
  grid-template-rows: [label] auto [hint] auto;
16735
16646
  grid-auto-columns: max-content;
16736
- column-gap: var(--db-space-md);
16647
+ column-gap: var(--db-spacing-xs);
16737
16648
  }
16738
16649
 
16739
16650
  /* Equal column widths: AntD `gridAutoColumns: minmax(0, 1fr)`. */
@@ -16766,64 +16677,52 @@ span.du-bois-light-typography-ellipsis-single-line {
16766
16677
  * the group itself gets a top margin (room above the two-row grid). */
16767
16678
  .ds-radio-group--horizontal:has(> .du-bois-light-hint),
16768
16679
  .ds-radio-group--horizontal:has(> .du-bois-dark-hint) {
16769
- margin-top: var(--db-space-sm);
16680
+ margin-top: var(--db-spacing-2xs);
16770
16681
  }
16771
16682
 
16772
16683
  /* AntD `&& + form-message { marginTop: sm }` (horizontal): a form-message following
16773
16684
  * the whole group is separated by sm. */
16774
16685
  .ds-radio-group--horizontal + .du-bois-light-form-message,
16775
16686
  .ds-radio-group--horizontal + .du-bois-dark-form-message {
16776
- margin-top: var(--db-space-sm);
16687
+ margin-top: var(--db-spacing-2xs);
16777
16688
  }
16778
16689
 
16779
- /* Component-tier tokens for <Switch>. Colors default to the selection-toggle category tokens;
16780
- * geometry is hand-authored (the pill track + sliding thumb are unique to Switch). */
16781
-
16782
- /* Re-declared under both theme classes (not just :root) so the var() chain onto
16783
- * category/system tokens re-resolves inside a `.du-bois-dark` subtree instead of
16784
- * freezing at the root (light) values. See DUBOIS-448 dark-mode scoping. */
16785
- :where(:root, .du-bois-light, .du-bois-dark) {
16786
- --db-switch-track-width: 28px;
16787
- --db-switch-track-height: 16px;
16788
- /* Thumb fills the track height by design; expressed via track-height so the two can't drift. */
16789
- --db-switch-thumb-size: var(--db-switch-track-height);
16790
- /* Pill radius overrides the category (square) radius, mirroring Radio's circular override. */
16690
+ :where(:root), :where(.du-bois-light) {
16691
+ /* Shape */
16791
16692
  --db-switch-border-radius: var(--db-radius-full);
16792
16693
  --db-switch-border-width: 1px;
16793
- --db-switch-spacing: var(--db-selection-toggle-spacing);
16794
16694
 
16795
- --db-switch-bg-default: var(--db-selection-toggle-bg-default);
16796
- --db-switch-bg-hover: var(--db-selection-toggle-bg-hover);
16797
- --db-switch-bg-press: var(--db-selection-toggle-bg-press);
16798
- --db-switch-bg-checked: var(--db-selection-toggle-bg-checked);
16799
- --db-switch-bg-checked-hover: var(--db-selection-toggle-bg-checked-hover);
16800
- --db-switch-bg-checked-press: var(--db-selection-toggle-bg-checked-press);
16801
- --db-switch-bg-disabled: var(--db-selection-toggle-bg-disabled);
16695
+ /* Color */
16696
+ --db-switch-surface: var(--db-selection-toggle-surface);
16697
+ --db-switch-surface-hover: var(--db-color-action-default-background-hover);
16698
+ --db-switch-surface-press: var(--db-color-action-default-background-press);
16699
+ --db-switch-surface-checked: var(--db-selection-toggle-surface-checked);
16700
+ --db-switch-surface-checked-hover: var(--db-selection-toggle-surface-checked-hover);
16701
+ --db-switch-surface-checked-press: var(--db-selection-toggle-surface-checked-press);
16702
+ --db-switch-surface-disabled: var(--db-selection-toggle-surface-disabled);
16703
+ --db-switch-surface-checked-disabled: var(--db-color-action-disabled-text);
16802
16704
 
16803
- --db-switch-border-default: var(--db-selection-toggle-border-default);
16705
+ --db-switch-border: var(--db-color-action-default-border-default);
16804
16706
  --db-switch-border-hover: var(--db-selection-toggle-border-hover);
16805
16707
  --db-switch-border-press: var(--db-selection-toggle-border-press);
16806
- --db-switch-border-disabled: var(--db-selection-toggle-border-disabled);
16807
- /* AntD paints the checked track border equal to the checked fill, so these alias the checked bg. */
16808
- --db-switch-border-checked: var(--db-selection-toggle-bg-checked);
16809
- --db-switch-border-checked-hover: var(--db-selection-toggle-bg-checked-hover);
16810
- --db-switch-border-checked-press: var(--db-selection-toggle-bg-checked-press);
16811
- --db-switch-border-focus: var(--db-selection-toggle-bg-checked);
16812
- /* AntD fills the disabled+checked track with actionDisabledText; no category token matches, so
16813
- * reference the system token directly (same escape hatch Radio uses for its checked-press border). */
16814
- --db-switch-bg-checked-disabled: var(--db-color-action-disabled-text);
16815
-
16816
- /* AntD paints the handle the off-track surface color in every state. */
16817
- --db-switch-thumb-color: var(--db-selection-toggle-bg-default);
16818
-
16819
- /* A token (not inherit) so the label text flips in dark mode. */
16820
- --db-switch-text: var(--db-color-text-primary);
16708
+ --db-switch-border-disabled: var(--db-color-action-disabled-border);
16709
+ --db-switch-border-checked: var(--db-selection-toggle-surface-checked);
16710
+ --db-switch-border-checked-hover: var(--db-selection-toggle-surface-checked-hover);
16711
+ --db-switch-border-checked-press: var(--db-selection-toggle-surface-checked-press);
16712
+ --db-switch-border-focus: var(--db-selection-toggle-surface-checked);
16713
+
16714
+ --db-switch-thumb: var(--db-selection-toggle-surface);
16715
+
16716
+ --db-switch-text: var(--db-selection-toggle-text);
16821
16717
  --db-switch-text-disabled: var(--db-selection-toggle-text-disabled);
16822
16718
 
16823
- /* AntD's focus ring is a 1px outline (the category default is 2px). */
16824
- --db-switch-focus-ring-width: 1px;
16825
- --db-switch-focus-ring-offset: 1px;
16826
- --db-switch-focus-ring-color: var(--db-selection-toggle-border-focus);
16719
+ /* Density */
16720
+ --db-switch-track-width: calc(var(--db-size-xs) * 1.75); /* 28px */
16721
+ --db-switch-track-height: var(--db-size-xs); /* 16px */
16722
+ --db-switch-thumb-size: var(--db-switch-track-height);
16723
+ --db-switch-label-spacing: var(--db-selection-toggle-label-spacing);
16724
+
16725
+ /* Motion */
16827
16726
  --db-switch-transition-duration: var(--db-selection-toggle-transition-duration);
16828
16727
  }
16829
16728
 
@@ -16832,116 +16731,111 @@ span.du-bois-light-typography-ellipsis-single-line {
16832
16731
  * (e.g. a following FormMessage) down a few px, breaking the form-flow spacing. */
16833
16732
  display: flex;
16834
16733
  align-items: center;
16835
- position: relative;
16836
16734
  cursor: pointer;
16837
16735
  user-select: none;
16838
16736
  width: fit-content;
16839
- margin-inline-end: var(--db-switch-spacing);
16737
+ margin-inline-end: var(--db-switch-label-spacing);
16738
+ }
16739
+
16740
+ .ds-switch:has(input:disabled) {
16741
+ cursor: not-allowed;
16742
+ }
16743
+
16744
+ /* The track. `appearance: none` strips the native checkbox rendering so the input itself can be styled. */
16745
+ .ds-switch input {
16746
+ appearance: none;
16747
+ position: relative;
16748
+ flex-shrink: 0;
16749
+ margin: 0;
16750
+ cursor: pointer;
16751
+ inline-size: var(--db-switch-track-width);
16752
+ block-size: var(--db-switch-track-height);
16753
+ border: var(--db-switch-border-width) solid var(--db-switch-border);
16754
+ border-radius: var(--db-switch-border-radius);
16755
+ background-color: var(--db-switch-surface);
16756
+ box-sizing: border-box;
16757
+ transition:
16758
+ background-color var(--db-switch-transition-duration) ease,
16759
+ border-color var(--db-switch-transition-duration) ease;
16760
+ }
16761
+
16762
+ /* The thumb. A pseudo-element keeps the input the switch's only element, so nothing can overlay it
16763
+ * and intercept clicks. Offset left by the border width to sit flush with the track's outer edge. */
16764
+ .ds-switch input::before {
16765
+ content: '';
16766
+ position: absolute;
16767
+ top: 50%;
16768
+ left: calc(-1 * var(--db-switch-border-width));
16769
+ inline-size: var(--db-switch-thumb-size);
16770
+ block-size: var(--db-switch-thumb-size);
16771
+ border: var(--db-switch-border-width) solid;
16772
+ border-color: inherit;
16773
+ border-radius: var(--db-switch-border-radius);
16774
+ background-color: var(--db-switch-thumb);
16775
+ box-sizing: border-box;
16776
+ transform: translateY(-50%);
16777
+ transition: transform var(--db-switch-transition-duration) ease;
16840
16778
  }
16841
16779
 
16842
- /* Hover/press live on the root (label), not the input: the input has `pointer-events: none`. */
16843
- .ds-switch:hover:has(input:not(:disabled, :checked)) .ds-switch-track {
16844
- background-color: var(--db-switch-bg-hover);
16780
+ /* `<label for>` propagates `:hover` to the input, so scope hover/press to the control, not `input:hover`. */
16781
+ .ds-switch:hover input:not(:disabled):not(:checked) {
16782
+ background-color: var(--db-switch-surface-hover);
16845
16783
  border-color: var(--db-switch-border-hover);
16846
16784
  }
16847
16785
 
16848
- .ds-switch:active:has(input:not(:disabled, :checked)) .ds-switch-track {
16849
- background-color: var(--db-switch-bg-press);
16786
+ .ds-switch:active input:not(:disabled):not(:checked) {
16787
+ background-color: var(--db-switch-surface-press);
16850
16788
  border-color: var(--db-switch-border-press);
16851
16789
  }
16852
16790
 
16853
- .ds-switch:has(input:checked) .ds-switch-track {
16854
- background-color: var(--db-switch-bg-checked);
16791
+ .ds-switch input:checked {
16792
+ background-color: var(--db-switch-surface-checked);
16855
16793
  border-color: var(--db-switch-border-checked);
16856
16794
  }
16857
16795
 
16858
- .ds-switch:hover:has(input:checked:not(:disabled)) .ds-switch-track {
16859
- background-color: var(--db-switch-bg-checked-hover);
16796
+ .ds-switch:hover input:checked:not(:disabled) {
16797
+ background-color: var(--db-switch-surface-checked-hover);
16860
16798
  border-color: var(--db-switch-border-checked-hover);
16861
16799
  }
16862
16800
 
16863
- .ds-switch:active:has(input:checked:not(:disabled)) .ds-switch-track {
16864
- background-color: var(--db-switch-bg-checked-press);
16801
+ .ds-switch:active input:checked:not(:disabled) {
16802
+ background-color: var(--db-switch-surface-checked-press);
16865
16803
  border-color: var(--db-switch-border-checked-press);
16866
16804
  }
16867
16805
 
16868
- .ds-switch:has(input:checked) .ds-switch-thumb {
16806
+ .ds-switch input:checked::before {
16869
16807
  transform: translateY(-50%) translateX(calc(var(--db-switch-track-width) - var(--db-switch-thumb-size)));
16870
16808
  }
16871
16809
 
16872
- /* On focus, recolor the track border to the checked-fill color on top of the outline ring. Matching
16873
- * AntD, the ring sits flush when off and gains a 1px offset when checked (see the checked rule below). */
16874
- .ds-switch:has(input:focus-visible) .ds-switch-track {
16810
+ /* On focus, recolor the border to the checked-fill color on top of the outline ring. Matching AntD,
16811
+ * the ring sits flush when off and gains a 1px offset when checked.
16812
+ * TODO: width/offset are hardcoded 1px to preserve the AntD look; adopt the system 2px focus ring
16813
+ * (var(--db-focus-ring-width)) in a separate change. */
16814
+ .ds-switch input:focus-visible {
16875
16815
  border-color: var(--db-switch-border-focus);
16876
- outline: var(--db-switch-focus-ring-width) solid var(--db-switch-focus-ring-color);
16816
+ outline: 1px solid var(--db-focus-ring-color);
16877
16817
  outline-offset: 0;
16878
16818
  }
16879
16819
 
16880
- .ds-switch:has(input:checked:focus-visible) .ds-switch-track {
16881
- outline-offset: var(--db-switch-focus-ring-offset);
16820
+ .ds-switch input:checked:focus-visible {
16821
+ outline-offset: 1px;
16882
16822
  }
16883
16823
 
16884
- .ds-switch:has(input:disabled) {
16824
+ .ds-switch input:disabled {
16885
16825
  cursor: not-allowed;
16886
- }
16887
-
16888
- .ds-switch:has(input:disabled) .ds-switch-track {
16889
- background-color: var(--db-switch-bg-disabled);
16826
+ background-color: var(--db-switch-surface-disabled);
16890
16827
  border-color: var(--db-switch-border-disabled);
16891
16828
  }
16892
16829
 
16893
16830
  /* Disabled + on: more specific than the plain disabled rule, so it wins regardless of source order. */
16894
- .ds-switch:has(input:checked:disabled) .ds-switch-track {
16895
- background-color: var(--db-switch-bg-checked-disabled);
16896
- border-color: var(--db-switch-bg-checked-disabled);
16897
- }
16898
-
16899
- /* Hidden but still focusable/in tab order so `:has()` can read its state; pointer events fall through
16900
- * to the label. */
16901
- .ds-switch input {
16902
- position: absolute;
16903
- inset: 0;
16904
- inline-size: var(--db-switch-track-width);
16905
- block-size: var(--db-switch-track-height);
16906
- margin: 0;
16907
- opacity: 0;
16908
- pointer-events: none;
16909
- }
16910
-
16911
- .ds-switch-track {
16912
- position: relative;
16913
- flex-shrink: 0;
16914
- inline-size: var(--db-switch-track-width);
16915
- block-size: var(--db-switch-track-height);
16916
- border: var(--db-switch-border-width) solid var(--db-switch-border-default);
16917
- border-radius: var(--db-switch-border-radius);
16918
- background-color: var(--db-switch-bg-default);
16919
- box-sizing: border-box;
16920
- transition:
16921
- background-color var(--db-switch-transition-duration) ease,
16922
- border-color var(--db-switch-transition-duration) ease;
16923
- }
16924
-
16925
- /* `border-color: inherit` picks up the track's per-state color, so it's only set on the track. */
16926
- .ds-switch-thumb {
16927
- position: absolute;
16928
- top: 50%;
16929
- /* Pull left by the border width so the thumb sits flush with the track's outer edge, not inside it. */
16930
- left: calc(-1 * var(--db-switch-border-width));
16931
- inline-size: var(--db-switch-thumb-size);
16932
- block-size: var(--db-switch-thumb-size);
16933
- border: var(--db-switch-border-width) solid;
16934
- border-color: inherit;
16935
- border-radius: var(--db-switch-border-radius);
16936
- background-color: var(--db-switch-thumb-color);
16937
- box-sizing: border-box;
16938
- transform: translateY(-50%);
16939
- transition: transform var(--db-switch-transition-duration) ease;
16831
+ .ds-switch input:checked:disabled {
16832
+ background-color: var(--db-switch-surface-checked-disabled);
16833
+ border-color: var(--db-switch-surface-checked-disabled);
16940
16834
  }
16941
16835
 
16942
16836
  @media (prefers-reduced-motion: reduce) {
16943
- .ds-switch-track,
16944
- .ds-switch-thumb {
16837
+ .ds-switch input,
16838
+ .ds-switch input::before {
16945
16839
  transition: none;
16946
16840
  }
16947
16841
  }
@@ -16953,13 +16847,13 @@ span.du-bois-light-typography-ellipsis-single-line {
16953
16847
 
16954
16848
  .ds-switch-wrapper .ds-switch-state-message {
16955
16849
  margin-inline-start: auto;
16956
- margin-inline-end: var(--db-switch-spacing);
16850
+ margin-inline-end: var(--db-switch-label-spacing);
16957
16851
  }
16958
16852
 
16959
16853
  /* `:first-child` scopes this to the label-first layout; the plain layout renders the label last. */
16960
16854
  .ds-switch-wrapper > .du-bois-light-label:first-child,
16961
16855
  .ds-switch-wrapper > .du-bois-dark-label:first-child {
16962
- margin-inline-end: var(--db-switch-spacing);
16856
+ margin-inline-end: var(--db-switch-label-spacing);
16963
16857
  }
16964
16858
 
16965
16859
  .ds-switch-state-message {
@@ -16978,7 +16872,7 @@ span.du-bois-light-typography-ellipsis-single-line {
16978
16872
  + :is(.du-bois-light-hint, .du-bois-dark-hint, .du-bois-light-form-message, .du-bois-dark-form-message), :is(.ds-switch.ds-switch, .ds-switch-wrapper.ds-switch-wrapper)
16979
16873
  + :is(.du-bois-light-hint, .du-bois-dark-hint)
16980
16874
  + :is(.du-bois-light-form-message, .du-bois-dark-form-message) {
16981
- padding-inline-start: calc(var(--db-space-sm) + var(--db-switch-track-width));
16875
+ padding-inline-start: calc(var(--db-spacing-2xs) + var(--db-switch-track-width));
16982
16876
  }
16983
16877
 
16984
16878
  :is(.ds-switch.ds-switch, .ds-switch-wrapper.ds-switch-wrapper)