@databricks/design-system 2.0.5 → 2.0.7
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.
- package/AGENTS.md +239 -166
- package/CHANGELOG.md +47 -0
- package/design-guidance/docs/README.md +40 -0
- package/design-guidance/docs/review-contract.md +22 -0
- package/design-guidance/docs/tokens.md +35 -0
- package/design-guidance/docs/voice.md +40 -0
- package/design-guidance/skills/dbui-build-screen.md +24 -0
- package/design-guidance/skills/dbui-check-ecosystem.md +21 -0
- package/design-guidance/skills/dbui-check-guidelines.md +29 -0
- package/design-guidance/skills/dbui-check-principles.md +26 -0
- package/design-guidance/skills/dbui-check-voice.md +17 -0
- package/design-guidance/skills/dbui-pick-component.md +23 -0
- package/design-guidance/skills/dbui-pick-icon.md +23 -0
- package/design-guidance/skills/dbui-review.md +30 -0
- package/design-guidance/skills/dbui-validate.md +23 -0
- package/dist/{RHFControlledTypeaheadComboboxV2-DsH-nIEk.js → RHFControlledTypeaheadComboboxV2-nSSYj16I.js} +5 -5
- package/dist/{RHFControlledTypeaheadComboboxV2-DsH-nIEk.js.map → RHFControlledTypeaheadComboboxV2-nSSYj16I.js.map} +1 -1
- package/dist/{WizardStepContentWrapper-Bq1wm0V7.js → WizardStepContentWrapper-bbh_CoIf.js} +644 -679
- package/dist/WizardStepContentWrapper-bbh_CoIf.js.map +1 -0
- package/dist/dubois-colors.less +1 -1
- package/dist/icon-metadata.json +2069 -0
- package/dist/{index-BRAVZg-S.js → index-CUCuUviS.js} +350 -139
- package/dist/index-CUCuUviS.js.map +1 -0
- package/dist/index-dark.css +593 -191
- package/dist/index-dark.mitigated.css +623 -208
- package/dist/index.css +1536 -1049
- package/dist/index.js +4 -4
- package/dist/index.mitigated.css +1566 -1066
- package/dist/patterns.js +3 -3
- package/dist-types/design-system/Alert/Alert.d.ts +21 -4
- package/dist-types/design-system/Button/Button.d.ts +2 -1
- package/dist-types/design-system/Drawer/Drawer.d.ts +3 -1
- package/dist-types/design-system/Icon/AntdIcon.d.ts +3 -0
- package/dist-types/design-system/Icon/Icon.d.ts +20 -6
- package/dist-types/design-system/Icon/NativeIcon.d.ts +3 -0
- package/dist-types/design-system/Icon/__generated/icons/LakewatchIcon.d.ts +4 -0
- package/dist-types/design-system/Icon/__generated/icons/SlidesIcon.d.ts +4 -0
- package/dist-types/design-system/Icon/__generated/icons/index.d.ts +2 -0
- package/dist-types/design-system/Icon/index.d.ts +1 -0
- package/dist-types/design-system/Icon/utils.d.ts +1 -0
- package/dist-types/design-system/TypeaheadCombobox/TypeaheadComboboxControls.d.ts +0 -2
- package/dist-types/design-system/_shared_/Tabs/styles.d.ts +2 -3
- package/dist-types/design-system/index.d.ts +0 -1
- package/dist-types/design-system/utils/safex.d.ts +4 -2
- package/dist-types/theme/generalVariables.d.ts +0 -1
- package/dist-types/~patterns/Wizard/WizardModal.d.ts +1 -1
- package/package.json +8 -5
- package/setup.mjs +586 -0
- package/dist/WizardStepContentWrapper-Bq1wm0V7.js.map +0 -1
- package/dist/index-BRAVZg-S.js.map +0 -1
- package/dist-types/design-system/LegacyTooltip/LegacyTooltip.d.ts +0 -47
- package/dist-types/design-system/LegacyTooltip/index.d.ts +0 -1
package/dist/index.css
CHANGED
|
@@ -16046,7 +16046,7 @@ span.du-bois-light-typography-ellipsis-single-line {
|
|
|
16046
16046
|
|
|
16047
16047
|
--db-surface-selected: var(--db-color-table-background-selected-hover);
|
|
16048
16048
|
--db-surface-selected-hover: initial; /* TODO */;
|
|
16049
|
-
--db-surface-selected-active:
|
|
16049
|
+
--db-surface-selected-active: var(--db-color-table-background-selected-hover); /* no distinct active value */
|
|
16050
16050
|
|
|
16051
16051
|
/* Surface alpha-blending modifiers */
|
|
16052
16052
|
--db-surface-backdrop: initial; /* TODO */;
|
|
@@ -16072,7 +16072,7 @@ span.du-bois-light-typography-ellipsis-single-line {
|
|
|
16072
16072
|
--db-accent-surface-strong: var(--db-color-action-primary-background-hover);
|
|
16073
16073
|
|
|
16074
16074
|
--db-accent-surface-hover: var(--db-color-action-primary-background-hover);
|
|
16075
|
-
--db-accent-surface-active:
|
|
16075
|
+
--db-accent-surface-active: var(--db-color-action-primary-background-press); /* no distinct active value */
|
|
16076
16076
|
--db-accent-surface-selected: var(--db-color-action-primary-background-press);
|
|
16077
16077
|
|
|
16078
16078
|
/* In the current design, the text color for an accent surface does not change with hover, active, etc. */
|
|
@@ -16089,7 +16089,7 @@ span.du-bois-light-typography-ellipsis-single-line {
|
|
|
16089
16089
|
--db-negative-surface-strong: var(--db-color-action-danger-primary-background-hover);
|
|
16090
16090
|
|
|
16091
16091
|
--db-negative-surface-hover: var(--db-color-action-danger-primary-background-hover);
|
|
16092
|
-
--db-negative-surface-active:
|
|
16092
|
+
--db-negative-surface-active: var(--db-color-action-danger-primary-background-press); /* no distinct active value */
|
|
16093
16093
|
--db-negative-surface-selected: var(--db-color-action-danger-primary-background-press);
|
|
16094
16094
|
|
|
16095
16095
|
--db-negative-text: var(--db-color-text-validation-danger);
|
|
@@ -16130,6 +16130,11 @@ span.du-bois-light-typography-ellipsis-single-line {
|
|
|
16130
16130
|
--db-positive-border: initial; /* TODO */
|
|
16131
16131
|
--db-positive-border-hover: initial; /* TODO */
|
|
16132
16132
|
--db-positive-border-active: initial; /* TODO */
|
|
16133
|
+
|
|
16134
|
+
/* Branded */
|
|
16135
|
+
--db-ai-gradient-start: #4299e0;
|
|
16136
|
+
--db-ai-gradient-mid: #ca42e0;
|
|
16137
|
+
--db-ai-gradient-end: #ff5f46;
|
|
16133
16138
|
}
|
|
16134
16139
|
|
|
16135
16140
|
|
|
@@ -16210,6 +16215,59 @@ span.du-bois-light-typography-ellipsis-single-line {
|
|
|
16210
16215
|
--db-shape-pill: 999px;
|
|
16211
16216
|
}
|
|
16212
16217
|
|
|
16218
|
+
:where(:root), :where(.du-bois-light) {
|
|
16219
|
+
/* Shape */
|
|
16220
|
+
/* Mirrors the ShapeTokens host-override var used by Card; falls back to the theme radius. */
|
|
16221
|
+
--db-card-border-radius: var(--info-container-border-radius, 8px);
|
|
16222
|
+
|
|
16223
|
+
/* Color */
|
|
16224
|
+
--db-card-surface: var(--db-surface-base);
|
|
16225
|
+
--db-card-text: var(--db-text-base);
|
|
16226
|
+
--db-card-border: var(--db-border-base);
|
|
16227
|
+
--db-card-border-hover: var(--db-border-strong);
|
|
16228
|
+
}
|
|
16229
|
+
|
|
16230
|
+
:where(:root), :where(.du-bois-light) {
|
|
16231
|
+
/* Shape */
|
|
16232
|
+
/* Mirrors the ShapeTokens host-override var used by list items; falls back to the theme radius. */
|
|
16233
|
+
--db-list-item-border-radius: var(--list-item-border-radius, 4px);
|
|
16234
|
+
|
|
16235
|
+
/* Color */
|
|
16236
|
+
--db-list-surface: var(--db-surface-base);
|
|
16237
|
+
--db-list-text: var(--db-text-base);
|
|
16238
|
+
--db-list-header-text: var(--db-text-subtle);
|
|
16239
|
+
--db-list-separator: var(--db-border-subtle);
|
|
16240
|
+
|
|
16241
|
+
--db-list-item-surface-hover: var(--db-surface-hover);
|
|
16242
|
+
--db-list-item-surface-active: var(--db-surface-active);
|
|
16243
|
+
--db-list-item-surface-selected: var(--db-accent-surface-subtle);
|
|
16244
|
+
--db-list-item-surface-disabled: var(--db-surface-disabled);
|
|
16245
|
+
|
|
16246
|
+
--db-list-item-text-selected: var(--db-accent-text);
|
|
16247
|
+
--db-list-item-text-disabled: var(--db-text-disabled);
|
|
16248
|
+
|
|
16249
|
+
--db-list-item-danger-text: var(--db-negative-text);
|
|
16250
|
+
--db-list-item-danger-surface-hover: var(--db-negative-surface-subtle);
|
|
16251
|
+
|
|
16252
|
+
/* Density */
|
|
16253
|
+
--db-list-item-padding: var(--db-space-2);
|
|
16254
|
+
--db-list-item-height: var(--db-size-8);
|
|
16255
|
+
}
|
|
16256
|
+
|
|
16257
|
+
:where(:root), :where(.du-bois-light) {
|
|
16258
|
+
/* Shape */
|
|
16259
|
+
/* Mirrors the ShapeTokens host-override var; falls back to the v1 value (borderRadiusSm). */
|
|
16260
|
+
--db-popup-border-radius: var(--popup-border-radius, 4px);
|
|
16261
|
+
|
|
16262
|
+
/* Color */
|
|
16263
|
+
--db-popup-surface: var(--db-surface-base);
|
|
16264
|
+
--db-popup-text: var(--db-text-base);
|
|
16265
|
+
--db-popup-border: var(--db-border-base);
|
|
16266
|
+
|
|
16267
|
+
/* Elevation */
|
|
16268
|
+
--db-popup-elevation: var(--db-elevation-med);
|
|
16269
|
+
}
|
|
16270
|
+
|
|
16213
16271
|
:where(:root), :where(.du-bois-light) {
|
|
16214
16272
|
/* Shape */
|
|
16215
16273
|
--db-selection-toggle-border-radius: 4px;
|
|
@@ -16221,15 +16279,15 @@ span.du-bois-light-typography-ellipsis-single-line {
|
|
|
16221
16279
|
--db-selection-toggle-border: var(--db-border-strong);
|
|
16222
16280
|
|
|
16223
16281
|
--db-selection-toggle-surface-hover: var(--db-surface-hover);
|
|
16224
|
-
--db-selection-toggle-surface-
|
|
16282
|
+
--db-selection-toggle-surface-active: var(--db-surface-selected-active);
|
|
16225
16283
|
--db-selection-toggle-surface-checked: var(--db-accent-surface);
|
|
16226
16284
|
--db-selection-toggle-surface-checked-hover: var(--db-accent-surface-hover);
|
|
16227
|
-
--db-selection-toggle-surface-checked-
|
|
16285
|
+
--db-selection-toggle-surface-checked-active: var(--db-accent-surface-active);
|
|
16228
16286
|
--db-selection-toggle-surface-disabled: var(--db-surface-disabled);
|
|
16229
16287
|
--db-selection-toggle-surface-checked-disabled: var(--db-surface-disabled);
|
|
16230
16288
|
|
|
16231
16289
|
--db-selection-toggle-border-hover: var(--db-accent-surface-hover);
|
|
16232
|
-
--db-selection-toggle-border-
|
|
16290
|
+
--db-selection-toggle-border-active: var(--db-accent-surface-active);
|
|
16233
16291
|
--db-selection-toggle-border-disabled: var(--db-border-base);
|
|
16234
16292
|
|
|
16235
16293
|
--db-selection-toggle-mark-disabled: var(--db-text-disabled);
|
|
@@ -16247,338 +16305,492 @@ span.du-bois-light-typography-ellipsis-single-line {
|
|
|
16247
16305
|
|
|
16248
16306
|
:where(:root), :where(.du-bois-light) {
|
|
16249
16307
|
/* Shape */
|
|
16250
|
-
--db-
|
|
16251
|
-
--db-checkbox-border-width: 1px;
|
|
16252
|
-
|
|
16253
|
-
/* Color */
|
|
16254
|
-
--db-checkbox-surface: var(--db-selection-toggle-surface);
|
|
16255
|
-
--db-checkbox-surface-hover: var(--db-color-action-default-background-hover);
|
|
16256
|
-
--db-checkbox-surface-press: var(--db-color-action-default-background-press);
|
|
16257
|
-
--db-checkbox-surface-checked: var(--db-selection-toggle-surface-checked);
|
|
16258
|
-
--db-checkbox-surface-checked-hover: var(--db-selection-toggle-surface-checked-hover);
|
|
16259
|
-
--db-checkbox-surface-checked-press: var(--db-selection-toggle-surface-checked-press);
|
|
16260
|
-
--db-checkbox-surface-disabled: var(--db-selection-toggle-surface-disabled);
|
|
16261
|
-
|
|
16262
|
-
--db-checkbox-border: var(--db-color-action-default-border-default);
|
|
16263
|
-
--db-checkbox-border-hover: var(--db-selection-toggle-border-hover);
|
|
16264
|
-
--db-checkbox-border-press: var(--db-selection-toggle-border-press);
|
|
16265
|
-
--db-checkbox-focus-ring: var(--db-focus-ring-color);
|
|
16266
|
-
--db-checkbox-border-disabled: var(--db-color-action-disabled-border);
|
|
16267
|
-
|
|
16268
|
-
--db-checkbox-mark: #ffffff;
|
|
16269
|
-
--db-checkbox-mark-disabled: var(--db-selection-toggle-mark-disabled);
|
|
16270
|
-
--db-checkbox-text: var(--db-selection-toggle-text);
|
|
16271
|
-
--db-checkbox-text-disabled: var(--db-selection-toggle-text-disabled);
|
|
16272
|
-
|
|
16273
|
-
--db-checkbox-shadow-checked: var(--db-selection-toggle-shadow-checked);
|
|
16308
|
+
--db-avatar-border-radius: var(--db-radius-sm);
|
|
16274
16309
|
|
|
16275
16310
|
/* Density */
|
|
16276
|
-
--db-
|
|
16277
|
-
--db-
|
|
16278
|
-
--db-checkbox-focus-ring-width: var(--db-focus-ring-width);
|
|
16279
|
-
--db-checkbox-indeterminate-mark-width: var(--db-size-2); /* 8px */
|
|
16280
|
-
--db-checkbox-indeterminate-mark-height: calc(var(--db-size-1) * 0.75); /* 3px */
|
|
16311
|
+
--db-avatar-group-gap: var(--db-space-1);
|
|
16312
|
+
--db-avatar-group-border-width: 1px;
|
|
16281
16313
|
|
|
16282
|
-
/*
|
|
16283
|
-
|
|
16314
|
+
/* Color */
|
|
16315
|
+
/* No v2 token holds the secondary icon glyph yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
16316
|
+
--db-avatar-icon: var(--db-color-text-secondary);
|
|
16317
|
+
/* No v2 token holds the default avatar surface yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
16318
|
+
--db-avatar-surface: var(--db-color-tag-background-default);
|
|
16319
|
+
/* No v2 token holds the group divider border yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
16320
|
+
--db-avatar-group-border-color: var(--db-color-background-primary);
|
|
16284
16321
|
}
|
|
16285
16322
|
|
|
16286
|
-
|
|
16287
|
-
|
|
16288
|
-
|
|
16289
|
-
|
|
16290
|
-
* the native <input>; that feature has the support coverage we need.
|
|
16291
|
-
*
|
|
16292
|
-
* Structure (assumed by the React component):
|
|
16293
|
-
*
|
|
16294
|
-
* <label class="db-checkbox">
|
|
16295
|
-
* <input type="checkbox" class="db-checkbox-input" />
|
|
16296
|
-
* <span class="db-checkbox-indicator"> ← border + fill react to state
|
|
16297
|
-
* <svg class="db-checkbox-checkmark" .../> ← visible when :checked
|
|
16298
|
-
* <span class="db-checkbox-dash" /> ← visible when :indeterminate
|
|
16299
|
-
* </span>
|
|
16300
|
-
* <span class="db-checkbox-label">{children}</span>
|
|
16301
|
-
* </label>
|
|
16302
|
-
*
|
|
16303
|
-
* State and hiding rules target `.db-checkbox-input` — the checkbox's OWN input —
|
|
16304
|
-
* never a bare `input`: consumers may render an inline <input> (e.g. a number
|
|
16305
|
-
* field) inside the label children, and a descendant `input` selector would hide
|
|
16306
|
-
* / absolutely-position that field and mis-drive the `:has(…)` state rules. */
|
|
16307
|
-
|
|
16308
|
-
.db-checkbox {
|
|
16309
|
-
/* `display: flex` (block-level), NOT `inline-flex`: an inline-flex root puts
|
|
16310
|
-
* the label inside an inline-line-box whose leading pushes block-level siblings
|
|
16311
|
-
* (e.g. `<FormMessage>`) down by a few pixels — making validation messages sit
|
|
16312
|
-
* lower under the native checkbox than under the AntD checkbox (which itself is
|
|
16313
|
-
* wrapped in a block `<div>`, so its label's inline-line-box is consumed inside
|
|
16314
|
-
* that div and never leaks into sibling spacing). `width: fit-content` keeps the
|
|
16315
|
-
* label behaving like an inline-flex item inside a flex-row parent (the group,
|
|
16316
|
-
* or any consumer's flex container). */
|
|
16317
|
-
display: flex;
|
|
16318
|
-
align-items: flex-start;
|
|
16319
|
-
position: relative;
|
|
16320
|
-
cursor: pointer;
|
|
16321
|
-
user-select: none;
|
|
16322
|
-
/* No `gap` here — spacing between indicator and label, plus the trailing
|
|
16323
|
-
* whitespace that gives sibling checkboxes their visual separation, lives
|
|
16324
|
-
* on `.db-checkbox-label` as padding-inline. Matches AntD's `.{prefix}-checkbox + span`
|
|
16325
|
-
* rule and the prior Emotion-based NativeCheckbox implementation. */
|
|
16326
|
-
min-height: var(--db-line-height-base, 20px);
|
|
16327
|
-
width: fit-content;
|
|
16323
|
+
:where(:root), :where(.du-bois-light) {
|
|
16324
|
+
/* Color */
|
|
16325
|
+
/* No v2 token holds the initials/icon glyph on a colored avatar yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
16326
|
+
--db-avatar-text: #ffffff;
|
|
16328
16327
|
}
|
|
16329
16328
|
|
|
16330
|
-
/* Hover/press live on the root (label), not on the input: the input is
|
|
16331
|
-
* visually hidden (opacity:0), so an `input:hover` rule wouldn't be visible
|
|
16332
|
-
* anyway. Putting `:hover` on the root also makes the entire label area
|
|
16333
|
-
* — not just the indicator square — drive the visual feedback. */
|
|
16334
|
-
.db-checkbox:hover:has(.db-checkbox-input:not(:disabled, :checked, :indeterminate)) .db-checkbox-indicator {
|
|
16335
|
-
background-color: var(--db-checkbox-surface-hover);
|
|
16336
|
-
border-color: var(--db-checkbox-border-hover);
|
|
16337
|
-
}
|
|
16338
16329
|
|
|
16339
|
-
|
|
16340
|
-
|
|
16341
|
-
|
|
16342
|
-
|
|
16330
|
+
/* Component-tier tokens for the native <Button>, grouped by area (density, shape, typography, color).
|
|
16331
|
+
* Colors alias the action-* system tokens; sizes alias the system density scale.
|
|
16332
|
+
*
|
|
16333
|
+
* Follows the mortar/action.css pattern: one semantic set (surface / border / text, each with
|
|
16334
|
+
* -hover / -active / -disabled) whose defaults are the secondary variant. The variant classes that
|
|
16335
|
+
* re-set these tokens per variant live in NativeButton.css; this file declares only tokens. */
|
|
16343
16336
|
|
|
16344
|
-
/*
|
|
16345
|
-
|
|
16346
|
-
|
|
16347
|
-
|
|
16348
|
-
|
|
16337
|
+
/* Declared under the theme classes too (not just :root) so the var() chain re-resolves inside a
|
|
16338
|
+
* `.du-bois-dark` subtree (or a portal that re-applies the theme class) instead of freezing at the root values. */
|
|
16339
|
+
:where(:root), :where(.du-bois-light) {
|
|
16340
|
+
/* ── Density ──────────────────────────────────────────────────────────── */
|
|
16341
|
+
--db-btn-height: var(--db-size-8);
|
|
16342
|
+
--db-btn-height-small: var(--db-size-6);
|
|
16343
|
+
--db-btn-icon-size: var(--db-size-4);
|
|
16344
|
+
--db-btn-border-width: 1px;
|
|
16345
|
+
--db-btn-padding-vertical: var(--db-space-1);
|
|
16346
|
+
--db-btn-padding-horizontal: var(--db-space-3);
|
|
16347
|
+
--db-btn-padding-horizontal-small: var(--db-space-2);
|
|
16348
|
+
/* Icon/force-icon horizontal padding: half the standard horizontal padding. */
|
|
16349
|
+
--db-btn-padding-horizontal-icon: calc(var(--db-space-3) / 2); /* 6px */
|
|
16350
|
+
--db-btn-gap: var(--db-space-1);
|
|
16351
|
+
--db-btn-end-icon-gap: var(--db-space-2);
|
|
16352
|
+
--db-btn-end-icon-gap-small: var(--db-space-1);
|
|
16353
|
+
/* Width of a content-less button while loading, so the standalone spinner has room. */
|
|
16354
|
+
--db-btn-loading-empty-width: var(--db-size-10);
|
|
16349
16355
|
|
|
16350
|
-
|
|
16351
|
-
|
|
16352
|
-
border-color: var(--db-checkbox-surface-checked-hover);
|
|
16353
|
-
}
|
|
16356
|
+
/* ── Shape ────────────────────────────────────────────────────────────── */
|
|
16357
|
+
--db-btn-border-radius: var(--db-shape-control);
|
|
16354
16358
|
|
|
16355
|
-
|
|
16356
|
-
|
|
16357
|
-
|
|
16358
|
-
|
|
16359
|
+
/* ── Typography ───────────────────────────────────────────────────────── */
|
|
16360
|
+
--db-btn-font-size: var(--db-font-size-base);
|
|
16361
|
+
--db-btn-icon-only-font-size: var(--db-font-size-lg); /* 15px */
|
|
16362
|
+
--db-btn-font-weight: var(--db-font-weight-normal);
|
|
16363
|
+
/* Line heights are hard-coded until the typography scale ships computed per-level line-height tokens. */
|
|
16364
|
+
--db-btn-line-height: 1.25rem; /* 20px */
|
|
16365
|
+
--db-btn-line-height-small: 1rem; /* 16px */
|
|
16359
16366
|
|
|
16360
|
-
/*
|
|
16361
|
-
|
|
16362
|
-
|
|
16363
|
-
|
|
16367
|
+
/* ── Color: semantic set (defaults = secondary variant) ───────────────── */
|
|
16368
|
+
--db-btn-surface: var(--db-color-action-default-background-default);
|
|
16369
|
+
--db-btn-surface-hover: var(--db-color-action-default-background-hover);
|
|
16370
|
+
--db-btn-surface-active: var(--db-color-action-default-background-press);
|
|
16371
|
+
--db-btn-surface-disabled: transparent;
|
|
16372
|
+
--db-btn-border: var(--db-color-action-default-border-default);
|
|
16373
|
+
--db-btn-border-hover: var(--db-color-action-default-border-hover);
|
|
16374
|
+
--db-btn-border-active: var(--db-color-action-default-border-press);
|
|
16375
|
+
--db-btn-border-disabled: var(--db-color-action-disabled-border);
|
|
16376
|
+
--db-btn-text: var(--db-color-action-default-text-default);
|
|
16377
|
+
--db-btn-text-hover: var(--db-color-action-default-text-hover);
|
|
16378
|
+
--db-btn-text-active: var(--db-color-action-default-text-press);
|
|
16379
|
+
--db-btn-text-disabled: var(--db-color-action-disabled-text);
|
|
16364
16380
|
|
|
16365
|
-
|
|
16366
|
-
|
|
16381
|
+
/* ── Focus & icon ─────────────────────────────────────────────────────── */
|
|
16382
|
+
--db-btn-focus-ring: var(--db-color-action-default-border-focus);
|
|
16383
|
+
--db-btn-danger-focus-ring: var(--db-color-action-danger-primary-background-default);
|
|
16384
|
+
--db-btn-icon-glyph: var(--db-color-text-secondary);
|
|
16367
16385
|
}
|
|
16368
16386
|
|
|
16369
|
-
/*
|
|
16370
|
-
|
|
16371
|
-
|
|
16372
|
-
outline-offset: 4px;
|
|
16373
|
-
}
|
|
16387
|
+
/* Native <Button> visual styles. Consumes the component-tier `--db-btn-*` tokens (see tokens.css);
|
|
16388
|
+
* the variant classes below re-set those tokens per variant and the rules that follow paint them.
|
|
16389
|
+
* Shipped via mortar.css. */
|
|
16374
16390
|
|
|
16375
|
-
/*
|
|
16376
|
-
*
|
|
16377
|
-
*
|
|
16378
|
-
.db-
|
|
16379
|
-
|
|
16391
|
+
/* ── 0. Variant token re-sets ──────────────────────────────────────────────
|
|
16392
|
+
* Each variant class re-sets the semantic tokens declared in tokens.css; combined classes win by
|
|
16393
|
+
* specificity, which beats the `:where(:root)` (specificity 0) defaults regardless of file order. */
|
|
16394
|
+
.db-btn-primary {
|
|
16395
|
+
--db-btn-surface: var(--db-color-action-primary-background-default);
|
|
16396
|
+
--db-btn-surface-hover: var(--db-color-action-primary-background-hover);
|
|
16397
|
+
--db-btn-surface-active: var(--db-color-action-primary-background-press);
|
|
16398
|
+
--db-btn-surface-disabled: var(--db-color-action-disabled-border);
|
|
16399
|
+
--db-btn-border: transparent;
|
|
16400
|
+
--db-btn-border-hover: transparent;
|
|
16401
|
+
--db-btn-border-active: transparent;
|
|
16402
|
+
--db-btn-border-disabled: transparent;
|
|
16403
|
+
--db-btn-text: var(--db-color-action-primary-text-default);
|
|
16404
|
+
--db-btn-text-hover: var(--db-color-action-primary-text-hover);
|
|
16405
|
+
--db-btn-text-active: var(--db-color-action-primary-text-press);
|
|
16406
|
+
--db-btn-text-disabled: var(--db-color-action-primary-text-default);
|
|
16380
16407
|
}
|
|
16381
|
-
|
|
16382
|
-
.db-
|
|
16383
|
-
|
|
16408
|
+
.db-btn-tertiary,
|
|
16409
|
+
.db-btn-link {
|
|
16410
|
+
--db-btn-surface: var(--db-color-action-tertiary-background-default);
|
|
16411
|
+
--db-btn-surface-disabled: var(--db-color-action-tertiary-background-default);
|
|
16412
|
+
--db-btn-border: var(--db-color-action-tertiary-background-default);
|
|
16413
|
+
--db-btn-border-hover: transparent;
|
|
16414
|
+
--db-btn-border-active: transparent;
|
|
16415
|
+
--db-btn-border-disabled: transparent;
|
|
16416
|
+
--db-btn-text: var(--db-color-action-tertiary-text-default);
|
|
16417
|
+
--db-btn-text-hover: var(--db-color-action-tertiary-text-hover);
|
|
16418
|
+
--db-btn-text-active: var(--db-color-action-tertiary-text-press);
|
|
16419
|
+
--db-btn-text-disabled: var(--db-color-action-disabled-text);
|
|
16384
16420
|
}
|
|
16385
|
-
|
|
16386
|
-
|
|
16387
|
-
|
|
16388
|
-
border-color: var(--db-checkbox-border-disabled);
|
|
16389
|
-
box-shadow: none;
|
|
16421
|
+
.db-btn-tertiary {
|
|
16422
|
+
--db-btn-surface-hover: var(--db-color-action-tertiary-background-hover);
|
|
16423
|
+
--db-btn-surface-active: var(--db-color-action-tertiary-background-press);
|
|
16390
16424
|
}
|
|
16391
|
-
|
|
16392
|
-
.db-
|
|
16393
|
-
|
|
16425
|
+
/* Link is borderless and text-only, so its hover/press surface stays transparent. */
|
|
16426
|
+
.db-btn-link {
|
|
16427
|
+
--db-btn-surface-hover: transparent;
|
|
16428
|
+
--db-btn-surface-active: transparent;
|
|
16394
16429
|
}
|
|
16395
|
-
|
|
16396
|
-
.db-
|
|
16397
|
-
|
|
16430
|
+
/* Every danger button (icon included) disables to the filled treatment. */
|
|
16431
|
+
.db-btn-danger {
|
|
16432
|
+
--db-btn-surface-disabled: var(--db-color-action-disabled-border);
|
|
16433
|
+
--db-btn-border-disabled: transparent;
|
|
16434
|
+
--db-btn-text-disabled: var(--db-color-action-primary-text-default);
|
|
16398
16435
|
}
|
|
16399
|
-
|
|
16400
|
-
|
|
16401
|
-
|
|
16402
|
-
|
|
16403
|
-
|
|
16404
|
-
* (Playwright, and any coordinate click that lands on the box) resolves to the
|
|
16405
|
-
* real control instead of the decorative indicator overlay. Making the input
|
|
16406
|
-
* `pointer-events: none` (the prior native-only behavior) is what regressed
|
|
16407
|
-
* interaction tests vs. the AntD variant. `cursor: inherit` tracks the label's
|
|
16408
|
-
* pointer / disabled `not-allowed` cursor so the box keeps AntD's cursor too. */
|
|
16409
|
-
.db-checkbox .db-checkbox-input {
|
|
16410
|
-
position: absolute;
|
|
16411
|
-
inset: 0;
|
|
16412
|
-
inline-size: var(--db-checkbox-size);
|
|
16413
|
-
block-size: var(--db-checkbox-size);
|
|
16414
|
-
margin: 0;
|
|
16415
|
-
opacity: 0;
|
|
16416
|
-
cursor: inherit;
|
|
16436
|
+
/* Danger, filled (primary): re-set only the surface; text/transparent border come from primary. */
|
|
16437
|
+
.db-btn-primary.db-btn-danger:not(.db-btn-icon-only) {
|
|
16438
|
+
--db-btn-surface: var(--db-color-action-danger-primary-background-default);
|
|
16439
|
+
--db-btn-surface-hover: var(--db-color-action-danger-primary-background-hover);
|
|
16440
|
+
--db-btn-surface-active: var(--db-color-action-danger-primary-background-press);
|
|
16417
16441
|
}
|
|
16418
|
-
|
|
16419
|
-
|
|
16420
|
-
|
|
16421
|
-
|
|
16422
|
-
|
|
16423
|
-
|
|
16424
|
-
|
|
16425
|
-
|
|
16426
|
-
|
|
16427
|
-
|
|
16428
|
-
|
|
16429
|
-
|
|
16430
|
-
|
|
16431
|
-
|
|
16432
|
-
|
|
16433
|
-
|
|
16434
|
-
|
|
16435
|
-
|
|
16436
|
-
|
|
16437
|
-
|
|
16438
|
-
|
|
16442
|
+
/* Danger, secondary/outlined. */
|
|
16443
|
+
.db-btn-danger:not(.db-btn-primary):not(.db-btn-tertiary):not(.db-btn-link):not(.db-btn-icon-only) {
|
|
16444
|
+
--db-btn-surface: var(--db-color-action-danger-default-background-default);
|
|
16445
|
+
--db-btn-surface-hover: var(--db-color-action-danger-default-background-hover);
|
|
16446
|
+
--db-btn-surface-active: var(--db-color-action-danger-default-background-press);
|
|
16447
|
+
--db-btn-border: var(--db-color-action-danger-default-border-default);
|
|
16448
|
+
--db-btn-border-hover: var(--db-color-action-danger-default-border-hover);
|
|
16449
|
+
--db-btn-border-active: var(--db-color-action-danger-default-border-press);
|
|
16450
|
+
--db-btn-text: var(--db-color-action-danger-default-text-default);
|
|
16451
|
+
--db-btn-text-hover: var(--db-color-action-danger-default-text-hover);
|
|
16452
|
+
--db-btn-text-active: var(--db-color-action-danger-default-text-press);
|
|
16453
|
+
}
|
|
16454
|
+
/* Danger, tertiary/link: danger text everywhere, danger surface on hover/press; resting/disabled
|
|
16455
|
+
* surface stay the tertiary ghost (override the filled danger-disabled set above). */
|
|
16456
|
+
.db-btn-tertiary.db-btn-danger,
|
|
16457
|
+
.db-btn-link.db-btn-danger {
|
|
16458
|
+
--db-btn-surface-hover: var(--db-color-action-danger-default-background-hover);
|
|
16459
|
+
--db-btn-surface-active: var(--db-color-action-danger-default-background-press);
|
|
16460
|
+
--db-btn-surface-disabled: var(--db-color-action-tertiary-background-default);
|
|
16461
|
+
--db-btn-text: var(--db-color-action-danger-default-text-default);
|
|
16462
|
+
--db-btn-text-hover: var(--db-color-action-danger-default-text-hover);
|
|
16463
|
+
--db-btn-text-active: var(--db-color-action-danger-default-text-press);
|
|
16464
|
+
--db-btn-text-disabled: var(--db-color-action-disabled-text);
|
|
16465
|
+
}
|
|
16466
|
+
/* Icon-only renders as the ghost (tertiary) treatment regardless of variant; re-set the semantic set
|
|
16467
|
+
* so the icon-only rules paint from these component tokens. */
|
|
16468
|
+
.db-btn-icon-only {
|
|
16469
|
+
--db-btn-surface: var(--db-color-action-tertiary-background-default);
|
|
16470
|
+
--db-btn-surface-hover: var(--db-color-action-tertiary-background-hover);
|
|
16471
|
+
--db-btn-surface-active: var(--db-color-action-tertiary-background-press);
|
|
16472
|
+
--db-btn-text: var(--db-color-action-tertiary-text-default);
|
|
16473
|
+
--db-btn-text-hover: var(--db-color-action-tertiary-text-hover);
|
|
16474
|
+
--db-btn-text-active: var(--db-color-action-tertiary-text-press);
|
|
16475
|
+
}
|
|
16476
|
+
/* Danger icon-only keeps the ghost resting surface (inherited above) but uses danger text and a
|
|
16477
|
+
* danger hover/press surface. */
|
|
16478
|
+
.db-btn-icon-only.db-btn-danger {
|
|
16479
|
+
--db-btn-surface-hover: var(--db-color-action-danger-default-background-hover);
|
|
16480
|
+
--db-btn-surface-active: var(--db-color-action-danger-default-background-press);
|
|
16481
|
+
--db-btn-text: var(--db-color-action-danger-default-text-default);
|
|
16482
|
+
--db-btn-text-hover: var(--db-color-action-danger-default-text-hover);
|
|
16483
|
+
--db-btn-text-active: var(--db-color-action-danger-default-text-press);
|
|
16484
|
+
}
|
|
16485
|
+
|
|
16486
|
+
/* ── 1. Base — paints the default (secondary) variant ────────────────────── */
|
|
16487
|
+
.db-btn {
|
|
16488
|
+
appearance: none;
|
|
16439
16489
|
box-sizing: border-box;
|
|
16440
|
-
|
|
16441
|
-
|
|
16442
|
-
|
|
16443
|
-
|
|
16490
|
+
position: relative; /* anchors the loading spinner */
|
|
16491
|
+
display: inline-flex !important;
|
|
16492
|
+
align-items: center !important;
|
|
16493
|
+
justify-content: center !important;
|
|
16494
|
+
vertical-align: middle;
|
|
16495
|
+
white-space: nowrap;
|
|
16496
|
+
user-select: none;
|
|
16497
|
+
cursor: pointer;
|
|
16498
|
+
height: var(--db-btn-height) !important;
|
|
16499
|
+
font-family: inherit;
|
|
16500
|
+
font-size: var(--db-btn-font-size);
|
|
16501
|
+
font-weight: var(--db-btn-font-weight);
|
|
16502
|
+
line-height: var(--db-btn-line-height) !important;
|
|
16503
|
+
text-decoration: none !important;
|
|
16504
|
+
border: var(--db-btn-border-width) solid var(--db-btn-border);
|
|
16505
|
+
border-color: var(--db-btn-border) !important;
|
|
16506
|
+
border-radius: var(--db-btn-border-radius) !important;
|
|
16507
|
+
box-shadow: none !important;
|
|
16508
|
+
background-color: var(--db-btn-surface) !important;
|
|
16509
|
+
color: var(--db-btn-text) !important;
|
|
16444
16510
|
}
|
|
16445
16511
|
|
|
16446
|
-
|
|
16447
|
-
|
|
16448
|
-
|
|
16449
|
-
|
|
16450
|
-
|
|
16451
|
-
|
|
16452
|
-
|
|
16512
|
+
/* ── 2. Padding ──────────────────────────────────────────────────────────── */
|
|
16513
|
+
.db-btn.db-btn:where(:not(.db-btn-icon-only, .db-btn-force-icon, .db-btn-link)) {
|
|
16514
|
+
padding: var(--db-btn-padding-vertical) var(--db-btn-padding-horizontal) !important;
|
|
16515
|
+
}
|
|
16516
|
+
.db-btn.db-btn-small:where(:not(.db-btn-icon-only, .db-btn-force-icon, .db-btn-link)) {
|
|
16517
|
+
padding: 0 var(--db-btn-padding-horizontal-small) !important;
|
|
16518
|
+
}
|
|
16519
|
+
.db-btn.db-btn-link {
|
|
16520
|
+
padding: 0 !important;
|
|
16521
|
+
}
|
|
16522
|
+
.db-btn.db-btn-force-icon {
|
|
16523
|
+
padding: 0 var(--db-btn-padding-horizontal-icon) !important;
|
|
16453
16524
|
}
|
|
16454
16525
|
|
|
16455
|
-
|
|
16456
|
-
|
|
16457
|
-
|
|
16458
|
-
|
|
16459
|
-
|
|
16460
|
-
|
|
16526
|
+
/* ── 3. Interactive states ───────────────────────────────────────────────── */
|
|
16527
|
+
.db-btn:hover:not(:disabled, .db-btn-loading) {
|
|
16528
|
+
background-color: var(--db-btn-surface-hover) !important;
|
|
16529
|
+
border-color: var(--db-btn-border-hover) !important;
|
|
16530
|
+
color: var(--db-btn-text-hover) !important;
|
|
16531
|
+
}
|
|
16532
|
+
.db-btn:active:not(:disabled, .db-btn-loading) {
|
|
16533
|
+
background-color: var(--db-btn-surface-active) !important;
|
|
16534
|
+
border-color: var(--db-btn-border-active) !important;
|
|
16535
|
+
color: var(--db-btn-text-active) !important;
|
|
16461
16536
|
}
|
|
16462
16537
|
|
|
16463
|
-
|
|
16464
|
-
|
|
16465
|
-
|
|
16466
|
-
|
|
16467
|
-
|
|
16468
|
-
|
|
16469
|
-
|
|
16470
|
-
|
|
16471
|
-
|
|
16472
|
-
|
|
16538
|
+
/* ── 4. Focus ────────────────────────────────────────────────────────────── */
|
|
16539
|
+
.db-btn:focus-visible {
|
|
16540
|
+
outline: 2px solid var(--db-btn-focus-ring);
|
|
16541
|
+
outline-offset: -2px;
|
|
16542
|
+
}
|
|
16543
|
+
.db-btn-primary:focus-visible {
|
|
16544
|
+
outline-offset: 1px;
|
|
16545
|
+
}
|
|
16546
|
+
.db-btn-use-focus-pseudo-class:focus {
|
|
16547
|
+
outline: 2px solid var(--db-btn-focus-ring);
|
|
16548
|
+
outline-offset: 1px;
|
|
16473
16549
|
}
|
|
16474
16550
|
|
|
16475
|
-
/*
|
|
16476
|
-
|
|
16477
|
-
|
|
16478
|
-
|
|
16479
|
-
|
|
16480
|
-
|
|
16481
|
-
|
|
16482
|
-
|
|
16483
|
-
|
|
16551
|
+
/* ── 5. Small / block (full-width) / empty ────────────────────────────────── */
|
|
16552
|
+
.db-btn-small {
|
|
16553
|
+
height: var(--db-btn-height-small) !important;
|
|
16554
|
+
}
|
|
16555
|
+
.db-btn-block {
|
|
16556
|
+
width: 100%;
|
|
16557
|
+
}
|
|
16558
|
+
.db-btn-empty {
|
|
16559
|
+
background-color: transparent !important;
|
|
16560
|
+
border-color: transparent !important;
|
|
16561
|
+
}
|
|
16562
|
+
.db-btn-default.db-btn-empty {
|
|
16563
|
+
color: var(--db-btn-icon-glyph) !important;
|
|
16564
|
+
}
|
|
16565
|
+
.db-btn-empty.db-btn-loading {
|
|
16566
|
+
width: var(--db-btn-loading-empty-width);
|
|
16484
16567
|
}
|
|
16485
16568
|
|
|
16486
|
-
/*
|
|
16487
|
-
|
|
16488
|
-
|
|
16489
|
-
|
|
16490
|
-
|
|
16491
|
-
|
|
16492
|
-
* `
|
|
16493
|
-
|
|
16494
|
-
|
|
16495
|
-
|
|
16496
|
-
|
|
16569
|
+
/* ── 6. Tertiary & link ──────────────────────────────────────────────────── */
|
|
16570
|
+
.db-btn-link {
|
|
16571
|
+
height: auto !important;
|
|
16572
|
+
border: none !important;
|
|
16573
|
+
}
|
|
16574
|
+
/* Re-declare the text color for a non-icon-only tertiary/link at two-class weight so a plain
|
|
16575
|
+
* call-site `color` override loses; an icon-only glyph stays at base weight so its override wins. */
|
|
16576
|
+
.db-btn-tertiary:not(.db-btn-icon-only),
|
|
16577
|
+
.db-btn-link:not(.db-btn-icon-only) {
|
|
16578
|
+
color: var(--db-btn-text) !important;
|
|
16579
|
+
}
|
|
16580
|
+
/* Keep the resting border at two-class weight (parity with the shielded border-color). */
|
|
16581
|
+
.db-btn.db-btn-tertiary,
|
|
16582
|
+
.db-btn.db-btn-link {
|
|
16583
|
+
border-color: var(--db-btn-border) !important;
|
|
16584
|
+
}
|
|
16497
16585
|
|
|
16498
|
-
/*
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
.db-checkbox.db-checkbox + .du-bois-light-hint,
|
|
16502
|
-
.db-checkbox.db-checkbox + .du-bois-dark-hint,
|
|
16503
|
-
.db-checkbox.db-checkbox + .du-bois-light-form-message,
|
|
16504
|
-
.db-checkbox.db-checkbox + .du-bois-dark-form-message,
|
|
16505
|
-
.db-checkbox.db-checkbox + .du-bois-light-hint + .du-bois-light-form-message,
|
|
16506
|
-
.db-checkbox.db-checkbox + .du-bois-dark-hint + .du-bois-dark-form-message {
|
|
16507
|
-
padding-left: var(--db-space-6);
|
|
16508
|
-
margin-top: 0;
|
|
16586
|
+
/* ── 7. Danger ───────────────────────────────────────────────────────────── */
|
|
16587
|
+
.db-btn-danger:focus-visible {
|
|
16588
|
+
outline-color: var(--db-btn-danger-focus-ring);
|
|
16509
16589
|
}
|
|
16510
16590
|
|
|
16511
|
-
/*
|
|
16512
|
-
|
|
16513
|
-
|
|
16514
|
-
|
|
16515
|
-
|
|
16516
|
-
|
|
16517
|
-
|
|
16518
|
-
|
|
16591
|
+
/* ── 8. Icon-only ────────────────────────────────────────────────────────── */
|
|
16592
|
+
.db-btn-icon-only {
|
|
16593
|
+
padding: 0;
|
|
16594
|
+
border: none !important;
|
|
16595
|
+
background-color: var(--db-btn-surface) !important;
|
|
16596
|
+
font-size: var(--db-btn-icon-only-font-size);
|
|
16597
|
+
}
|
|
16598
|
+
/* `:where()` keeps this at (0,1,0) so a call-site `css` width override wins, as it does for `height`. */
|
|
16599
|
+
.db-btn-icon-only:where(:not(.db-btn-small)) {
|
|
16600
|
+
width: var(--db-btn-height) !important;
|
|
16601
|
+
}
|
|
16602
|
+
.db-btn-icon-only:not(.db-btn-link, .db-btn-tertiary, [href], :hover, :active, :disabled) {
|
|
16603
|
+
color: var(--db-btn-icon-glyph) !important;
|
|
16604
|
+
}
|
|
16605
|
+
/* `:where()` on the exclusion holds this at (0,2,0): enough to tint an un-overridden icon-only link
|
|
16606
|
+
* over the base color, while still letting a consumer's own icon-color override win on source order. */
|
|
16607
|
+
.db-btn-icon-only[href]:where(:not(.db-btn-tertiary, .db-btn-link, .db-btn-danger, :disabled)) {
|
|
16608
|
+
color: var(--db-btn-text) !important;
|
|
16609
|
+
}
|
|
16610
|
+
.db-btn-icon-only:where(.db-btn-small) {
|
|
16611
|
+
width: var(--db-btn-height-small);
|
|
16612
|
+
}
|
|
16613
|
+
.db-btn-icon-only.db-btn-small {
|
|
16614
|
+
line-height: var(--db-btn-line-height-small) !important;
|
|
16615
|
+
}
|
|
16616
|
+
.db-btn-icon-only:hover:not(:disabled, .db-btn-loading) {
|
|
16617
|
+
background-color: var(--db-btn-surface-hover) !important;
|
|
16618
|
+
color: var(--db-btn-text-hover) !important;
|
|
16619
|
+
}
|
|
16620
|
+
.db-btn-icon-only:active:not(:disabled, .db-btn-loading) {
|
|
16621
|
+
background-color: var(--db-btn-surface-active) !important;
|
|
16622
|
+
color: var(--db-btn-text-active) !important;
|
|
16623
|
+
}
|
|
16624
|
+
.db-btn-icon-only:enabled:not(.db-btn-primary, .db-btn-tertiary, .db-btn-link, .db-btn-danger, :hover, :active)
|
|
16625
|
+
> .anticon, .db-btn-icon-only:enabled:not(.db-btn-primary, .db-btn-tertiary, .db-btn-link, .db-btn-danger, :hover, :active)
|
|
16626
|
+
> .db-icon {
|
|
16627
|
+
color: var(--db-btn-icon-glyph);
|
|
16628
|
+
}
|
|
16629
|
+
.db-btn-icon-only.db-btn-danger:not(:hover, :active) > .anticon, .db-btn-icon-only.db-btn-danger:not(:hover, :active) > .db-icon {
|
|
16630
|
+
color: var(--db-btn-text);
|
|
16631
|
+
}
|
|
16632
|
+
.db-btn-icon-only.db-btn-danger:hover:not(:disabled, .db-btn-loading) {
|
|
16633
|
+
background-color: var(--db-btn-surface-hover) !important;
|
|
16634
|
+
color: var(--db-btn-text-hover) !important;
|
|
16635
|
+
}
|
|
16636
|
+
.db-btn-icon-only.db-btn-danger:active:not(:disabled, .db-btn-loading) {
|
|
16637
|
+
background-color: var(--db-btn-surface-active) !important;
|
|
16638
|
+
color: var(--db-btn-text-active) !important;
|
|
16519
16639
|
}
|
|
16520
16640
|
|
|
16521
|
-
/*
|
|
16522
|
-
|
|
16523
|
-
|
|
16524
|
-
|
|
16525
|
-
|
|
16526
|
-
|
|
16527
|
-
|
|
16641
|
+
/* ── 9. Disabled — base rules paint the per-variant `*-disabled` tokens (see tokens.css) ──────── */
|
|
16642
|
+
.db-btn:disabled {
|
|
16643
|
+
cursor: not-allowed;
|
|
16644
|
+
background-color: var(--db-btn-surface-disabled) !important;
|
|
16645
|
+
color: var(--db-btn-text-disabled) !important;
|
|
16646
|
+
}
|
|
16647
|
+
/* Empty disabled buttons keep a transparent border (set elsewhere), so exclude them.
|
|
16648
|
+
* `:where()` on the exclusion holds this at (0,2,0): enough to beat the base border, while still
|
|
16649
|
+
* letting a consumer's own `[disabled]` border override win on source order. */
|
|
16650
|
+
.db-btn:disabled:where(:not(.db-btn-empty)) {
|
|
16651
|
+
border-color: var(--db-btn-border-disabled) !important;
|
|
16652
|
+
}
|
|
16653
|
+
.db-btn-icon-only:disabled {
|
|
16654
|
+
border: none;
|
|
16655
|
+
}
|
|
16656
|
+
.db-btn-icon-only:disabled:hover {
|
|
16657
|
+
background-color: transparent !important;
|
|
16658
|
+
}
|
|
16659
|
+
.db-btn:disabled > .anticon,
|
|
16660
|
+
.db-btn:disabled > .db-icon {
|
|
16661
|
+
color: inherit !important;
|
|
16662
|
+
}
|
|
16663
|
+
|
|
16664
|
+
/* ── 10. Icon & content layout ───────────────────────────────────────────── */
|
|
16665
|
+
/* The leading icon renders unwrapped as the button's direct `.anticon` child (see NativeButton.tsx),
|
|
16666
|
+
* so `> .anticon` targets only a real icon glyph — a non-glyph `icon` (e.g. a Spinner) keeps its own
|
|
16667
|
+
* sizing — and out-specifies AntD's runtime-injected global `.anticon` rule. */
|
|
16668
|
+
.db-btn > .anticon,
|
|
16669
|
+
.db-btn > .db-icon,
|
|
16670
|
+
.db-btn-end-icon,
|
|
16671
|
+
.db-btn-end-icon > .anticon,
|
|
16672
|
+
.db-btn-end-icon > .db-icon {
|
|
16673
|
+
display: inline-flex;
|
|
16674
|
+
align-items: center;
|
|
16675
|
+
font-size: var(--db-btn-icon-size) !important;
|
|
16676
|
+
line-height: 0;
|
|
16677
|
+
}
|
|
16678
|
+
.db-btn-small > .anticon .anticon,
|
|
16679
|
+
.db-btn-small > .anticon .db-icon,
|
|
16680
|
+
.db-btn-small > .db-icon .anticon,
|
|
16681
|
+
.db-btn-small > .db-icon .db-icon {
|
|
16682
|
+
line-height: 0;
|
|
16683
|
+
}
|
|
16684
|
+
.db-btn > .db-btn-content > .anticon,
|
|
16685
|
+
.db-btn > .db-btn-content > .db-icon {
|
|
16686
|
+
display: inline-flex;
|
|
16687
|
+
align-items: center;
|
|
16688
|
+
line-height: 0;
|
|
16689
|
+
}
|
|
16690
|
+
.db-btn-content {
|
|
16691
|
+
display: inline-flex;
|
|
16692
|
+
align-items: center;
|
|
16693
|
+
}
|
|
16694
|
+
.db-btn > .anticon + .db-btn-content,
|
|
16695
|
+
.db-btn > .db-icon + .db-btn-content {
|
|
16696
|
+
margin-inline-start: var(--db-btn-gap) !important;
|
|
16697
|
+
}
|
|
16698
|
+
.db-btn-end-icon {
|
|
16699
|
+
margin-inline-start: var(--db-btn-end-icon-gap) !important;
|
|
16700
|
+
}
|
|
16701
|
+
.db-btn-small .db-btn-end-icon {
|
|
16702
|
+
margin-inline-start: var(--db-btn-end-icon-gap-small) !important;
|
|
16703
|
+
}
|
|
16704
|
+
.db-btn-default:not(.db-btn-danger, [href], :hover, :active, :disabled) > .anticon, .db-btn-default:not(.db-btn-danger, [href], :hover, :active, :disabled) > .db-icon {
|
|
16705
|
+
color: var(--db-btn-icon-glyph);
|
|
16706
|
+
}
|
|
16707
|
+
.db-btn-default[href]:not(.db-btn-danger, :hover, :active, :disabled) .db-btn-end-icon {
|
|
16708
|
+
color: var(--db-btn-icon-glyph);
|
|
16709
|
+
}
|
|
16710
|
+
.db-btn-default:not([href], .db-btn-danger, :hover, :active, :disabled)
|
|
16711
|
+
> .db-btn-content
|
|
16712
|
+
> .db-btn-end-icon
|
|
16713
|
+
> .anticon, .db-btn-default:not([href], .db-btn-danger, :hover, :active, :disabled)
|
|
16714
|
+
> .db-btn-content
|
|
16715
|
+
> .db-btn-end-icon
|
|
16716
|
+
> .db-icon {
|
|
16717
|
+
color: var(--db-btn-icon-glyph);
|
|
16718
|
+
}
|
|
16719
|
+
|
|
16720
|
+
/* ── 11. Loading ─────────────────────────────────────────────────────────── */
|
|
16721
|
+
.db-btn-loading {
|
|
16722
|
+
cursor: default;
|
|
16723
|
+
}
|
|
16724
|
+
.db-btn-force-icon.db-btn-loading:disabled {
|
|
16725
|
+
border-color: transparent !important;
|
|
16726
|
+
}
|
|
16727
|
+
.db-btn-spinner {
|
|
16728
|
+
color: inherit !important;
|
|
16729
|
+
pointer-events: none;
|
|
16730
|
+
}
|
|
16731
|
+
.db-btn-loading-with-icon .db-btn-content {
|
|
16732
|
+
padding-inline-start: calc(var(--db-btn-icon-size) + var(--db-btn-gap));
|
|
16733
|
+
}
|
|
16734
|
+
.db-btn-loading .db-btn-spinner {
|
|
16735
|
+
position: absolute;
|
|
16736
|
+
left: 50%;
|
|
16737
|
+
top: 50%;
|
|
16738
|
+
transform: translate(-50%, -50%);
|
|
16528
16739
|
}
|
|
16529
|
-
|
|
16530
|
-
|
|
16531
|
-
|
|
16532
|
-
.db-checkbox-group:not(.db-stack) {
|
|
16533
|
-
flex-wrap: nowrap;
|
|
16534
|
-
column-gap: var(--db-checkbox-label-spacing);
|
|
16535
|
-
row-gap: 0;
|
|
16740
|
+
.db-btn-loading.db-btn-icon-only .db-btn-spinner {
|
|
16741
|
+
position: static;
|
|
16742
|
+
transform: none;
|
|
16536
16743
|
}
|
|
16537
16744
|
|
|
16538
|
-
/*
|
|
16539
|
-
.db-
|
|
16540
|
-
|
|
16745
|
+
/* ── 12. dangerouslySetForceIconStyles ───────────────────────────────────── */
|
|
16746
|
+
.db-btn-force-icon {
|
|
16747
|
+
width: var(--db-btn-height) !important;
|
|
16748
|
+
color: var(--db-btn-icon-glyph) !important;
|
|
16749
|
+
}
|
|
16750
|
+
.db-btn-force-icon.db-btn-small {
|
|
16751
|
+
width: var(--db-btn-height-small) !important;
|
|
16541
16752
|
}
|
|
16542
16753
|
|
|
16754
|
+
|
|
16543
16755
|
:where(:root), :where(.du-bois-light) {
|
|
16544
16756
|
/* Shape */
|
|
16545
|
-
--db-
|
|
16546
|
-
--db-
|
|
16757
|
+
--db-checkbox-border-radius: var(--db-selection-toggle-border-radius);
|
|
16758
|
+
--db-checkbox-border-width: 1px;
|
|
16547
16759
|
|
|
16548
16760
|
/* Color */
|
|
16549
|
-
--db-
|
|
16550
|
-
--db-
|
|
16551
|
-
--db-
|
|
16552
|
-
--db-
|
|
16553
|
-
--db-
|
|
16554
|
-
--db-
|
|
16555
|
-
--db-
|
|
16761
|
+
--db-checkbox-surface: var(--db-selection-toggle-surface);
|
|
16762
|
+
--db-checkbox-surface-hover: var(--db-color-action-default-background-hover);
|
|
16763
|
+
--db-checkbox-surface-active: var(--db-color-action-default-background-press);
|
|
16764
|
+
--db-checkbox-surface-checked: var(--db-selection-toggle-surface-checked);
|
|
16765
|
+
--db-checkbox-surface-checked-hover: var(--db-selection-toggle-surface-checked-hover);
|
|
16766
|
+
--db-checkbox-surface-checked-active: var(--db-selection-toggle-surface-checked-active);
|
|
16767
|
+
--db-checkbox-surface-disabled: var(--db-selection-toggle-surface-disabled);
|
|
16556
16768
|
|
|
16557
|
-
--db-
|
|
16558
|
-
--db-
|
|
16559
|
-
--db-
|
|
16560
|
-
--db-
|
|
16561
|
-
--db-
|
|
16562
|
-
--db-radio-border-checked-hover: var(--db-selection-toggle-border-press);
|
|
16563
|
-
--db-radio-border-checked-press: var(--db-color-action-default-border-press);
|
|
16564
|
-
--db-radio-border-unchecked-focus: var(--db-color-action-primary-background-default);
|
|
16565
|
-
--db-radio-outline-checked-focus: var(--db-color-action-primary-background-default);
|
|
16769
|
+
--db-checkbox-border: var(--db-color-action-default-border-default);
|
|
16770
|
+
--db-checkbox-border-hover: var(--db-selection-toggle-border-hover);
|
|
16771
|
+
--db-checkbox-border-active: var(--db-selection-toggle-border-active);
|
|
16772
|
+
--db-checkbox-focus-ring: var(--db-focus-ring-color);
|
|
16773
|
+
--db-checkbox-border-disabled: var(--db-color-action-disabled-border);
|
|
16566
16774
|
|
|
16567
|
-
--db-
|
|
16568
|
-
--db-
|
|
16569
|
-
--db-
|
|
16570
|
-
--db-
|
|
16775
|
+
--db-checkbox-mark: #ffffff;
|
|
16776
|
+
--db-checkbox-mark-disabled: var(--db-selection-toggle-mark-disabled);
|
|
16777
|
+
--db-checkbox-text: var(--db-selection-toggle-text);
|
|
16778
|
+
--db-checkbox-text-disabled: var(--db-selection-toggle-text-disabled);
|
|
16779
|
+
|
|
16780
|
+
--db-checkbox-shadow-checked: var(--db-selection-toggle-shadow-checked);
|
|
16571
16781
|
|
|
16572
16782
|
/* Density */
|
|
16573
|
-
--db-
|
|
16574
|
-
--db-
|
|
16575
|
-
--db-
|
|
16783
|
+
--db-checkbox-size: var(--db-selection-toggle-size);
|
|
16784
|
+
--db-checkbox-label-spacing: var(--db-selection-toggle-label-spacing);
|
|
16785
|
+
--db-checkbox-focus-ring-width: var(--db-focus-ring-width);
|
|
16786
|
+
--db-checkbox-indeterminate-mark-width: var(--db-size-2); /* 8px */
|
|
16787
|
+
--db-checkbox-indeterminate-mark-height: calc(var(--db-size-1) * 0.75); /* 3px */
|
|
16576
16788
|
|
|
16577
16789
|
/* Motion */
|
|
16578
|
-
--db-
|
|
16790
|
+
--db-checkbox-transition-duration: var(--db-selection-toggle-transition-duration);
|
|
16579
16791
|
}
|
|
16580
16792
|
|
|
16581
|
-
/* Native-input <
|
|
16793
|
+
/* Native-input <Checkbox> styles. Classic CSS only — no native nesting (the
|
|
16582
16794
|
* `&`-style nesting feature ships in Chrome/Edge 120, Safari 17.2, Firefox 117
|
|
16583
16795
|
* which leaves a non-trivial slice of our production traffic uncovered today;
|
|
16584
16796
|
* see PR #1954620 thread). `:has()` lookups are still used to read state from
|
|
@@ -16586,981 +16798,1285 @@ span.du-bois-light-typography-ellipsis-single-line {
|
|
|
16586
16798
|
*
|
|
16587
16799
|
* Structure (assumed by the React component):
|
|
16588
16800
|
*
|
|
16589
|
-
* <label class="db-
|
|
16590
|
-
* <input type="
|
|
16591
|
-
* <span class="db-
|
|
16592
|
-
* <
|
|
16801
|
+
* <label class="db-checkbox">
|
|
16802
|
+
* <input type="checkbox" class="db-checkbox-input" />
|
|
16803
|
+
* <span class="db-checkbox-indicator"> ← border + fill react to state
|
|
16804
|
+
* <svg class="db-checkbox-checkmark" .../> ← visible when :checked
|
|
16805
|
+
* <span class="db-checkbox-dash" /> ← visible when :indeterminate
|
|
16593
16806
|
* </span>
|
|
16594
|
-
* <span class="db-
|
|
16807
|
+
* <span class="db-checkbox-label">{children}</span>
|
|
16595
16808
|
* </label>
|
|
16596
16809
|
*
|
|
16597
|
-
*
|
|
16598
|
-
*
|
|
16599
|
-
*
|
|
16600
|
-
*
|
|
16601
|
-
*
|
|
16602
|
-
* TODO(DUBOIS-452): the indicator/dot state styles below are identical to
|
|
16603
|
-
* NativeCheckbox.css — consolidate them into a shared `.db-selection-toggle` class. */
|
|
16810
|
+
* State and hiding rules target `.db-checkbox-input` — the checkbox's OWN input —
|
|
16811
|
+
* never a bare `input`: consumers may render an inline <input> (e.g. a number
|
|
16812
|
+
* field) inside the label children, and a descendant `input` selector would hide
|
|
16813
|
+
* / absolutely-position that field and mis-drive the `:has(…)` state rules. */
|
|
16604
16814
|
|
|
16605
|
-
.db-
|
|
16606
|
-
/* `display: flex` (block-level), NOT `inline-flex`:
|
|
16607
|
-
* the line-box
|
|
16815
|
+
.db-checkbox {
|
|
16816
|
+
/* `display: flex` (block-level), NOT `inline-flex`: an inline-flex root puts
|
|
16817
|
+
* the label inside an inline-line-box whose leading pushes block-level siblings
|
|
16818
|
+
* (e.g. `<FormMessage>`) down by a few pixels — making validation messages sit
|
|
16819
|
+
* lower under the native checkbox than under the AntD checkbox (which itself is
|
|
16820
|
+
* wrapped in a block `<div>`, so its label's inline-line-box is consumed inside
|
|
16821
|
+
* that div and never leaks into sibling spacing). `width: fit-content` keeps the
|
|
16822
|
+
* label behaving like an inline-flex item inside a flex-row parent (the group,
|
|
16823
|
+
* or any consumer's flex container). */
|
|
16608
16824
|
display: flex;
|
|
16609
16825
|
align-items: flex-start;
|
|
16610
16826
|
position: relative;
|
|
16611
16827
|
cursor: pointer;
|
|
16612
16828
|
user-select: none;
|
|
16829
|
+
/* No `gap` here — spacing between indicator and label, plus the trailing
|
|
16830
|
+
* whitespace that gives sibling checkboxes their visual separation, lives
|
|
16831
|
+
* on `.db-checkbox-label` as padding-inline. Matches AntD's `.{prefix}-checkbox + span`
|
|
16832
|
+
* rule and the prior Emotion-based NativeCheckbox implementation. */
|
|
16613
16833
|
min-height: var(--db-line-height-base, 20px);
|
|
16614
16834
|
width: fit-content;
|
|
16615
16835
|
}
|
|
16616
16836
|
|
|
16617
16837
|
/* Hover/press live on the root (label), not on the input: the input is
|
|
16618
16838
|
* visually hidden (opacity:0), so an `input:hover` rule wouldn't be visible
|
|
16619
|
-
* anyway
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16839
|
+
* anyway. Putting `:hover` on the root also makes the entire label area
|
|
16840
|
+
* — not just the indicator square — drive the visual feedback. */
|
|
16841
|
+
.db-checkbox:hover:has(.db-checkbox-input:not(:disabled, :checked, :indeterminate)) .db-checkbox-indicator {
|
|
16842
|
+
background-color: var(--db-checkbox-surface-hover);
|
|
16843
|
+
border-color: var(--db-checkbox-border-hover);
|
|
16623
16844
|
}
|
|
16624
16845
|
|
|
16625
|
-
.db-
|
|
16626
|
-
background-color: var(--db-
|
|
16627
|
-
border-color: var(--db-
|
|
16846
|
+
.db-checkbox:active:has(.db-checkbox-input:not(:disabled, :checked, :indeterminate)) .db-checkbox-indicator {
|
|
16847
|
+
background-color: var(--db-checkbox-surface-active);
|
|
16848
|
+
border-color: var(--db-checkbox-border-active);
|
|
16628
16849
|
}
|
|
16629
16850
|
|
|
16630
|
-
/* Selected fill. */
|
|
16631
|
-
.db-
|
|
16632
|
-
background-color: var(--db-
|
|
16633
|
-
border-color: var(--db-
|
|
16851
|
+
/* Selected fill — checked and indeterminate share the same surface. */
|
|
16852
|
+
.db-checkbox:has(.db-checkbox-input:is(:checked, :indeterminate)) .db-checkbox-indicator {
|
|
16853
|
+
background-color: var(--db-checkbox-surface-checked);
|
|
16854
|
+
border-color: var(--db-checkbox-surface-checked);
|
|
16634
16855
|
}
|
|
16635
16856
|
|
|
16636
|
-
|
|
16637
|
-
|
|
16638
|
-
|
|
16639
|
-
background-color: var(--db-radio-surface-checked-hover);
|
|
16640
|
-
border-color: var(--db-radio-border-checked-hover);
|
|
16857
|
+
.db-checkbox:hover:has(.db-checkbox-input:is(:checked, :indeterminate):not(:disabled)) .db-checkbox-indicator {
|
|
16858
|
+
background-color: var(--db-checkbox-surface-checked-hover);
|
|
16859
|
+
border-color: var(--db-checkbox-surface-checked-hover);
|
|
16641
16860
|
}
|
|
16642
16861
|
|
|
16643
|
-
|
|
16644
|
-
|
|
16645
|
-
|
|
16646
|
-
background-color: var(--db-radio-surface-checked-press);
|
|
16647
|
-
border-color: var(--db-radio-border-checked-press);
|
|
16862
|
+
.db-checkbox:active:has(.db-checkbox-input:is(:checked, :indeterminate):not(:disabled)) .db-checkbox-indicator {
|
|
16863
|
+
background-color: var(--db-checkbox-surface-checked-active);
|
|
16864
|
+
border-color: var(--db-checkbox-surface-checked-active);
|
|
16648
16865
|
}
|
|
16649
16866
|
|
|
16650
|
-
/*
|
|
16651
|
-
.db-
|
|
16867
|
+
/* Mark visibility. */
|
|
16868
|
+
.db-checkbox:has(.db-checkbox-input:checked) .db-checkbox-checkmark {
|
|
16652
16869
|
opacity: 1;
|
|
16653
16870
|
}
|
|
16654
16871
|
|
|
16655
|
-
|
|
16656
|
-
|
|
16657
|
-
*
|
|
16658
|
-
* UNCHECKED focus (AntD `&:not(disabled) > input:focus + inner`): only the border
|
|
16659
|
-
* color changes to actionPrimaryBackgroundDefault — NO outline ring. */
|
|
16660
|
-
.db-radio:has(input:focus-visible:not(:checked)) .db-radio-indicator {
|
|
16661
|
-
border-color: var(--db-radio-border-unchecked-focus);
|
|
16872
|
+
.db-checkbox:has(.db-checkbox-input:indeterminate) .db-checkbox-dash {
|
|
16873
|
+
opacity: 1;
|
|
16662
16874
|
}
|
|
16663
16875
|
|
|
16664
|
-
/*
|
|
16665
|
-
|
|
16666
|
-
|
|
16667
|
-
|
|
16668
|
-
background-color: var(--db-radio-surface-checked);
|
|
16669
|
-
border-color: var(--db-radio-border-focus);
|
|
16670
|
-
outline: 1px solid var(--db-radio-outline-checked-focus);
|
|
16671
|
-
outline-offset: 1px;
|
|
16876
|
+
/* Focus-visible (keyboard only). */
|
|
16877
|
+
.db-checkbox:has(.db-checkbox-input:focus-visible) .db-checkbox-indicator {
|
|
16878
|
+
outline: var(--db-checkbox-focus-ring-width) solid var(--db-checkbox-focus-ring);
|
|
16879
|
+
outline-offset: 4px;
|
|
16672
16880
|
}
|
|
16673
16881
|
|
|
16674
|
-
/* Disabled (covers checked
|
|
16675
|
-
* standalone-disabled and group-disabled paths both
|
|
16676
|
-
.
|
|
16882
|
+
/* Disabled (covers unchecked, checked, indeterminate). Sourced from
|
|
16883
|
+
* `input:disabled` so the standalone-disabled and group-disabled paths both
|
|
16884
|
+
* land here without needing a separate root modifier class. */
|
|
16885
|
+
.db-checkbox:has(.db-checkbox-input:disabled) {
|
|
16677
16886
|
cursor: not-allowed;
|
|
16678
16887
|
}
|
|
16679
16888
|
|
|
16680
|
-
.db-
|
|
16681
|
-
color: var(--db-
|
|
16889
|
+
.db-checkbox:has(.db-checkbox-input:disabled) .db-checkbox-label {
|
|
16890
|
+
color: var(--db-checkbox-text-disabled);
|
|
16682
16891
|
}
|
|
16683
16892
|
|
|
16684
|
-
.db-
|
|
16685
|
-
background-color: var(--db-
|
|
16686
|
-
border-color: var(--db-
|
|
16893
|
+
.db-checkbox:has(.db-checkbox-input:disabled) .db-checkbox-indicator {
|
|
16894
|
+
background-color: var(--db-checkbox-surface-disabled);
|
|
16895
|
+
border-color: var(--db-checkbox-border-disabled);
|
|
16687
16896
|
box-shadow: none;
|
|
16688
16897
|
}
|
|
16689
16898
|
|
|
16690
|
-
.db-
|
|
16691
|
-
|
|
16899
|
+
.db-checkbox:has(.db-checkbox-input:disabled) .db-checkbox-checkmark {
|
|
16900
|
+
color: var(--db-checkbox-mark-disabled);
|
|
16692
16901
|
}
|
|
16693
16902
|
|
|
16694
|
-
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16903
|
+
.db-checkbox:has(.db-checkbox-input:disabled) .db-checkbox-dash {
|
|
16904
|
+
background-color: var(--db-checkbox-mark-disabled);
|
|
16905
|
+
}
|
|
16906
|
+
|
|
16907
|
+
/* Visually-hidden native input (opacity:0) overlaying the indicator square,
|
|
16908
|
+
* kept interactive and in the tab order so `:has()` lookups above can read its
|
|
16909
|
+
* state. It stays pointer-clickable — matching AntD's `.ant-checkbox-input` —
|
|
16910
|
+
* so it is the top-most hit-test target over the box: `getByRole('checkbox').click()`
|
|
16911
|
+
* (Playwright, and any coordinate click that lands on the box) resolves to the
|
|
16699
16912
|
* real control instead of the decorative indicator overlay. Making the input
|
|
16700
16913
|
* `pointer-events: none` (the prior native-only behavior) is what regressed
|
|
16701
16914
|
* interaction tests vs. the AntD variant. `cursor: inherit` tracks the label's
|
|
16702
|
-
* pointer / disabled `not-allowed` cursor so the
|
|
16703
|
-
.db-
|
|
16915
|
+
* pointer / disabled `not-allowed` cursor so the box keeps AntD's cursor too. */
|
|
16916
|
+
.db-checkbox .db-checkbox-input {
|
|
16704
16917
|
position: absolute;
|
|
16705
16918
|
inset: 0;
|
|
16706
|
-
inline-size: var(--db-
|
|
16707
|
-
block-size: var(--db-
|
|
16919
|
+
inline-size: var(--db-checkbox-size);
|
|
16920
|
+
block-size: var(--db-checkbox-size);
|
|
16708
16921
|
margin: 0;
|
|
16709
16922
|
opacity: 0;
|
|
16710
16923
|
cursor: inherit;
|
|
16711
16924
|
}
|
|
16712
16925
|
|
|
16713
|
-
/* Indicator —
|
|
16714
|
-
* Vertical math aligns the indicator to the cap-height of the first text
|
|
16715
|
-
* so
|
|
16716
|
-
|
|
16926
|
+
/* Indicator — square with the border/fill that responds to state above.
|
|
16927
|
+
* Vertical math: aligns the indicator to the cap-height of the first text
|
|
16928
|
+
* line so checkbox + label sit on the same visual baseline even when the
|
|
16929
|
+
* label wraps. */
|
|
16930
|
+
.db-checkbox .db-checkbox-indicator {
|
|
16717
16931
|
display: grid;
|
|
16718
16932
|
place-items: center;
|
|
16719
16933
|
flex-shrink: 0;
|
|
16720
16934
|
/* Decorative only — the overlaid input owns hit-testing. Without this, the
|
|
16721
|
-
* indicator (and its inherited
|
|
16722
|
-
* clicks on any edge sliver the input does
|
|
16723
|
-
* which toggles via label/input
|
|
16935
|
+
* indicator (and its inherited checkmark/dash children) intercept
|
|
16936
|
+
* `getByRole('checkbox').click()`; clicks on any edge sliver the input does
|
|
16937
|
+
* not cover fall through to the label, which toggles via label/input
|
|
16938
|
+
* association. */
|
|
16724
16939
|
pointer-events: none;
|
|
16725
|
-
inline-size: var(--db-
|
|
16726
|
-
block-size: var(--db-
|
|
16727
|
-
margin-top: calc((var(--db-line-height-base, 20px) - var(--db-
|
|
16728
|
-
border: var(--db-
|
|
16729
|
-
border-radius: var(--db-
|
|
16730
|
-
background-color: var(--db-
|
|
16940
|
+
inline-size: var(--db-checkbox-size);
|
|
16941
|
+
block-size: var(--db-checkbox-size);
|
|
16942
|
+
margin-top: calc((var(--db-line-height-base, 20px) - var(--db-checkbox-size)) / 2);
|
|
16943
|
+
border: var(--db-checkbox-border-width) solid var(--db-checkbox-border);
|
|
16944
|
+
border-radius: var(--db-checkbox-border-radius);
|
|
16945
|
+
background-color: var(--db-checkbox-surface);
|
|
16731
16946
|
box-sizing: border-box;
|
|
16732
16947
|
transition:
|
|
16733
|
-
background-color var(--db-
|
|
16734
|
-
border-color var(--db-
|
|
16735
|
-
box-shadow var(--db-
|
|
16948
|
+
background-color var(--db-checkbox-transition-duration) ease,
|
|
16949
|
+
border-color var(--db-checkbox-transition-duration) ease,
|
|
16950
|
+
box-shadow var(--db-checkbox-transition-duration) ease;
|
|
16736
16951
|
}
|
|
16737
16952
|
|
|
16738
|
-
.db-
|
|
16953
|
+
.db-checkbox .db-checkbox-indicator > .db-checkbox-checkmark {
|
|
16739
16954
|
grid-area: 1 / 1;
|
|
16740
|
-
inline-size:
|
|
16741
|
-
block-size:
|
|
16742
|
-
|
|
16743
|
-
|
|
16744
|
-
|
|
16745
|
-
transition: opacity var(--db-radio-transition-duration) ease;
|
|
16746
|
-
}
|
|
16747
|
-
|
|
16748
|
-
/* Honour the user's reduced-motion preference: drop the state-change
|
|
16749
|
-
* transitions on the indicator and dot so checking/hovering is instant. */
|
|
16750
|
-
@media (prefers-reduced-motion: reduce) {
|
|
16751
|
-
.db-radio .db-radio-indicator,
|
|
16752
|
-
.db-radio .db-radio-indicator > .db-radio-dot {
|
|
16753
|
-
transition: none;
|
|
16754
|
-
}
|
|
16955
|
+
inline-size: 100%;
|
|
16956
|
+
block-size: 100%;
|
|
16957
|
+
color: var(--db-checkbox-mark);
|
|
16958
|
+
opacity: 0;
|
|
16959
|
+
transition: opacity var(--db-checkbox-transition-duration) ease;
|
|
16755
16960
|
}
|
|
16756
16961
|
|
|
16757
|
-
|
|
16758
|
-
|
|
16759
|
-
|
|
16760
|
-
|
|
16761
|
-
|
|
16762
|
-
|
|
16962
|
+
.db-checkbox .db-checkbox-indicator > .db-checkbox-checkmark path {
|
|
16963
|
+
fill: none;
|
|
16964
|
+
stroke: currentColor;
|
|
16965
|
+
stroke-width: 2;
|
|
16966
|
+
stroke-linecap: round;
|
|
16967
|
+
stroke-linejoin: round;
|
|
16763
16968
|
}
|
|
16764
16969
|
|
|
16765
|
-
|
|
16766
|
-
|
|
16767
|
-
|
|
16768
|
-
|
|
16769
|
-
|
|
16770
|
-
|
|
16771
|
-
|
|
16772
|
-
|
|
16773
|
-
|
|
16774
|
-
|
|
16775
|
-
padding-inline-start: var(--db-space-6);
|
|
16776
|
-
margin-top: 0;
|
|
16970
|
+
.db-checkbox .db-checkbox-indicator > .db-checkbox-dash {
|
|
16971
|
+
grid-area: 1 / 1;
|
|
16972
|
+
inline-size: var(--db-checkbox-indeterminate-mark-width);
|
|
16973
|
+
block-size: var(--db-checkbox-indeterminate-mark-height);
|
|
16974
|
+
/* CSS clamps this to half the 3px height, giving fully rounded end caps so the
|
|
16975
|
+
* dash reads as a pill rather than a flat bar. */
|
|
16976
|
+
border-radius: 4px;
|
|
16977
|
+
background-color: var(--db-checkbox-mark);
|
|
16978
|
+
opacity: 0;
|
|
16979
|
+
transition: opacity var(--db-checkbox-transition-duration) ease;
|
|
16777
16980
|
}
|
|
16778
16981
|
|
|
16779
|
-
/*
|
|
16780
|
-
*
|
|
16781
|
-
* `
|
|
16782
|
-
*
|
|
16783
|
-
* the
|
|
16784
|
-
|
|
16785
|
-
|
|
16786
|
-
|
|
16787
|
-
|
|
16788
|
-
.db-radio-group.db-stack > .db-radio.db-radio + .du-bois-dark-form-message,
|
|
16789
|
-
.db-radio-group.db-stack > .db-radio.db-radio + .du-bois-light-hint + .du-bois-light-form-message,
|
|
16790
|
-
.db-radio-group.db-stack > .db-radio.db-radio + .du-bois-dark-hint + .du-bois-dark-form-message {
|
|
16791
|
-
margin-top: calc(-1 * var(--db-space-2));
|
|
16792
|
-
margin-bottom: var(--db-space-2);
|
|
16982
|
+
/* Padding-inline replicates AntD's `.{prefix}-checkbox + span { padding: 0 8px }`.
|
|
16983
|
+
* `padding-left` provides the visible gap between indicator and label text.
|
|
16984
|
+
* `padding-right` extends the checkbox's bounding box so adjacent checkboxes in a
|
|
16985
|
+
* flex row sit ~16px apart (8px trailing + 8px group `gap`) — same visual rhythm
|
|
16986
|
+
* as the AntD variant. */
|
|
16987
|
+
.db-checkbox .db-checkbox-label {
|
|
16988
|
+
color: var(--db-checkbox-text);
|
|
16989
|
+
padding-inline: var(--db-checkbox-label-spacing);
|
|
16990
|
+
word-break: break-word;
|
|
16793
16991
|
}
|
|
16794
16992
|
|
|
16795
|
-
/*
|
|
16796
|
-
*
|
|
16797
|
-
|
|
16798
|
-
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
|
|
16993
|
+
/* Form-flow integration: when a checkbox or group sits next to a `<Hint>` or
|
|
16994
|
+
* `<FormMessage>` in a form layout, collapse the inherited sibling margin and
|
|
16995
|
+
* align the helper text under the checkbox label. Mirrors the AntD-era rules
|
|
16996
|
+
* carried in `getWrapperStyle` and `getNativeCheckboxWrapperStyles`.
|
|
16997
|
+
*
|
|
16998
|
+
* Each helper-text class is listed once per theme (`du-bois-light-*` /
|
|
16999
|
+
* `du-bois-dark-*`). The selectors deliberately repeat the root/group class
|
|
17000
|
+
* (`.db-checkbox.db-checkbox`) to push specificity to (0,3,0). That
|
|
17001
|
+
* overrides `FormMessage`'s own `&&`-doubled `margin-top: 8px` declared with
|
|
17002
|
+
* Emotion at runtime — without doubling we'd lose on the specificity tie and
|
|
17003
|
+
* the validation message would keep an 8px gap below the checkbox. */
|
|
17004
|
+
|
|
17005
|
+
/* Single checkbox followed by Hint and/or FormMessage. Indents the helper text
|
|
17006
|
+
* by 24px so it aligns with the start of the label, and removes the default
|
|
17007
|
+
* vertical margin Hint/FormMessage carry. */
|
|
17008
|
+
.db-checkbox.db-checkbox + .du-bois-light-hint,
|
|
17009
|
+
.db-checkbox.db-checkbox + .du-bois-dark-hint,
|
|
17010
|
+
.db-checkbox.db-checkbox + .du-bois-light-form-message,
|
|
17011
|
+
.db-checkbox.db-checkbox + .du-bois-dark-form-message,
|
|
17012
|
+
.db-checkbox.db-checkbox + .du-bois-light-hint + .du-bois-light-form-message,
|
|
17013
|
+
.db-checkbox.db-checkbox + .du-bois-dark-hint + .du-bois-dark-form-message {
|
|
17014
|
+
padding-left: var(--db-space-6);
|
|
16803
17015
|
margin-top: 0;
|
|
16804
17016
|
}
|
|
16805
17017
|
|
|
16806
|
-
|
|
16807
|
-
|
|
16808
|
-
|
|
16809
|
-
.
|
|
17018
|
+
/* Group spacing against sibling form text — 8px gap above the group when it
|
|
17019
|
+
* follows a Label or Hint, 8px gap above a FormMessage when it follows the group.
|
|
17020
|
+
* Doubled class on the group side beats FormMessage's `&&` for the same reason. */
|
|
17021
|
+
.du-bois-light-label + .db-checkbox-group.db-checkbox-group,
|
|
17022
|
+
.du-bois-dark-label + .db-checkbox-group.db-checkbox-group,
|
|
17023
|
+
.du-bois-light-hint + .db-checkbox-group.db-checkbox-group,
|
|
17024
|
+
.du-bois-dark-hint + .db-checkbox-group.db-checkbox-group,
|
|
17025
|
+
.db-checkbox-group.db-checkbox-group + .du-bois-light-form-message,
|
|
17026
|
+
.db-checkbox-group.db-checkbox-group + .du-bois-dark-form-message {
|
|
16810
17027
|
margin-top: var(--db-space-2);
|
|
16811
17028
|
}
|
|
16812
17029
|
|
|
16813
|
-
/*
|
|
16814
|
-
*
|
|
16815
|
-
|
|
17030
|
+
/* CheckboxGroup layout. Vertical delegates to the `.db-stack` primitive; the
|
|
17031
|
+
* horizontal default stays bespoke because it must NOT wrap (a long row of
|
|
17032
|
+
* checkboxes overflows horizontally rather than reflowing onto multiple lines),
|
|
17033
|
+
* which is the one thing `.db-cluster` won't do. Both wire their gap to the
|
|
17034
|
+
* checkbox spacing token so a retheme moves with the rest of the component. */
|
|
17035
|
+
.db-checkbox-group {
|
|
16816
17036
|
display: flex;
|
|
16817
17037
|
}
|
|
16818
17038
|
|
|
16819
|
-
/*
|
|
16820
|
-
*
|
|
16821
|
-
|
|
16822
|
-
|
|
16823
|
-
|
|
16824
|
-
|
|
16825
|
-
.db-radio-group.db-stack {
|
|
16826
|
-
--db-stack-gap: 0;
|
|
17039
|
+
/* Horizontal (default): single non-wrapping row. `:not(.db-stack)` keeps this
|
|
17040
|
+
* off the vertical element so it never fights the stack primitive's gap. */
|
|
17041
|
+
.db-checkbox-group:not(.db-stack) {
|
|
17042
|
+
flex-wrap: nowrap;
|
|
17043
|
+
column-gap: var(--db-checkbox-label-spacing);
|
|
17044
|
+
row-gap: 0;
|
|
16827
17045
|
}
|
|
16828
17046
|
|
|
16829
|
-
/*
|
|
16830
|
-
.db-
|
|
16831
|
-
|
|
17047
|
+
/* Vertical: .db-stack supplies flex-direction + gap; we only retarget the knob. */
|
|
17048
|
+
.db-checkbox-group.db-stack {
|
|
17049
|
+
--db-stack-gap: var(--db-checkbox-label-spacing);
|
|
16832
17050
|
}
|
|
16833
17051
|
|
|
16834
|
-
/* AntD `& > label:last-of-type { paddingBottom: 0 }`. */
|
|
16835
|
-
.db-radio-group.db-stack > .db-radio:last-of-type {
|
|
16836
|
-
padding-bottom: 0;
|
|
16837
|
-
}
|
|
16838
17052
|
|
|
16839
|
-
/* AntD getVerticalRadioGroupStyles `.${prefix}-radio-tile + .${prefix}-radio-tile {
|
|
16840
|
-
* marginTop: md }`: RadioTiles are not matched by the `.db-radio` padding-bottom
|
|
16841
|
-
* rhythm above (the tile's own class is du-bois-{light,dark}-radio-tile), so space
|
|
16842
|
-
* consecutive tiles explicitly. The .db-stack gap is 0, so this margin is the spacing. */
|
|
16843
|
-
.db-radio-group.db-stack > .du-bois-light-radio-tile + .du-bois-light-radio-tile,
|
|
16844
|
-
.db-radio-group.db-stack > .du-bois-light-radio-tile + .du-bois-dark-radio-tile,
|
|
16845
|
-
.db-radio-group.db-stack > .du-bois-dark-radio-tile + .du-bois-light-radio-tile,
|
|
16846
|
-
.db-radio-group.db-stack > .du-bois-dark-radio-tile + .du-bois-dark-radio-tile {
|
|
16847
|
-
margin-top: var(--db-space-4);
|
|
16848
|
-
}
|
|
16849
17053
|
|
|
16850
|
-
|
|
16851
|
-
|
|
16852
|
-
|
|
16853
|
-
|
|
16854
|
-
|
|
16855
|
-
|
|
16856
|
-
|
|
16857
|
-
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
}
|
|
17054
|
+
:where(:root), :where(.du-bois-light) {
|
|
17055
|
+
/* Density */
|
|
17056
|
+
--db-drawer-padding-horizontal: var(--db-space-6);
|
|
17057
|
+
--db-drawer-padding-horizontal-small: var(--db-space-4);
|
|
17058
|
+
--db-drawer-content-padding-top: var(--db-space-4);
|
|
17059
|
+
--db-drawer-content-padding-top-small: var(--db-space-2);
|
|
17060
|
+
--db-drawer-footer-padding-top: var(--db-space-4);
|
|
17061
|
+
--db-drawer-footer-padding-bottom: var(--db-space-6);
|
|
17062
|
+
--db-drawer-footer-padding-bottom-small: var(--db-space-4);
|
|
17063
|
+
--db-drawer-title-margin-bottom: var(--db-space-2);
|
|
17064
|
+
--db-drawer-close-button-margin: var(--db-space-1);
|
|
16862
17065
|
|
|
16863
|
-
/*
|
|
16864
|
-
|
|
16865
|
-
|
|
17066
|
+
/* Color */
|
|
17067
|
+
--db-drawer-surface: var(--db-surface-base);
|
|
17068
|
+
--db-drawer-text: var(--db-text-base);
|
|
17069
|
+
--db-drawer-border: var(--db-border-base);
|
|
17070
|
+
/* No v2 token holds the drawer scrim yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17071
|
+
--db-drawer-overlay: var(--db-color-overlay-overlay);
|
|
16866
17072
|
}
|
|
16867
17073
|
|
|
16868
|
-
|
|
16869
|
-
|
|
16870
|
-
|
|
16871
|
-
* label row. grid-auto-flow defaults to row, so successive items advance the implicit
|
|
16872
|
-
* column. */
|
|
16873
|
-
.db-radio-group--horizontal > .db-radio,
|
|
16874
|
-
.db-radio-group--horizontal > .du-bois-light-radio-tile,
|
|
16875
|
-
.db-radio-group--horizontal > .du-bois-dark-radio-tile {
|
|
16876
|
-
grid-row: label / label;
|
|
16877
|
-
margin-inline-end: 0;
|
|
17074
|
+
:where(:root), :where(.du-bois-light) {
|
|
17075
|
+
/* Elevation */
|
|
17076
|
+
--db-drawer-shadow: var(--db-elevation-high);
|
|
16878
17077
|
}
|
|
16879
17078
|
|
|
16880
|
-
/* AntD `& > label + hint { display: inline-block; gridRow: hint / hint }`: a hint
|
|
16881
|
-
* following a radio drops into the hint row of the column its radio occupies. The
|
|
16882
|
-
* vertical negative-margin rules are scoped to .db-stack, so nothing to reset here. */
|
|
16883
|
-
.db-radio-group--horizontal > .du-bois-light-hint,
|
|
16884
|
-
.db-radio-group--horizontal > .du-bois-dark-hint {
|
|
16885
|
-
display: inline-block;
|
|
16886
|
-
grid-row: hint / hint;
|
|
16887
|
-
}
|
|
16888
17079
|
|
|
16889
|
-
|
|
16890
|
-
|
|
16891
|
-
|
|
16892
|
-
|
|
16893
|
-
margin-top: var(--db-space-2);
|
|
16894
|
-
}
|
|
17080
|
+
:where(:root), :where(.du-bois-light) {
|
|
17081
|
+
/* Color */
|
|
17082
|
+
--db-empty-text: var(--db-text-subtle);
|
|
17083
|
+
--db-empty-image-color: var(--db-text-disabled);
|
|
16895
17084
|
|
|
16896
|
-
/*
|
|
16897
|
-
*
|
|
16898
|
-
|
|
16899
|
-
|
|
16900
|
-
|
|
17085
|
+
/* Density */
|
|
17086
|
+
--db-empty-image-size: calc(var(--db-size-8) * 2);
|
|
17087
|
+
--db-empty-image-spacing: var(--db-space-4);
|
|
17088
|
+
--db-empty-description-spacing: var(--db-space-4);
|
|
17089
|
+
--db-empty-max-width: 600px;
|
|
16901
17090
|
}
|
|
16902
17091
|
|
|
16903
|
-
:where(:root), :where(.du-bois-light) {
|
|
16904
|
-
/* Shape */
|
|
16905
|
-
--db-switch-border-radius: var(--db-radius-full);
|
|
16906
|
-
--db-switch-border-width: 1px;
|
|
16907
|
-
|
|
16908
|
-
/* Color */
|
|
16909
|
-
--db-switch-surface: var(--db-selection-toggle-surface);
|
|
16910
|
-
--db-switch-surface-hover: var(--db-color-action-default-background-hover);
|
|
16911
|
-
--db-switch-surface-press: var(--db-color-action-default-background-press);
|
|
16912
|
-
--db-switch-surface-checked: var(--db-selection-toggle-surface-checked);
|
|
16913
|
-
--db-switch-surface-checked-hover: var(--db-selection-toggle-surface-checked-hover);
|
|
16914
|
-
--db-switch-surface-checked-press: var(--db-selection-toggle-surface-checked-press);
|
|
16915
|
-
--db-switch-surface-disabled: var(--db-selection-toggle-surface-disabled);
|
|
16916
|
-
--db-switch-surface-checked-disabled: var(--db-color-action-disabled-text);
|
|
16917
17092
|
|
|
16918
|
-
--db-switch-border: var(--db-color-action-default-border-default);
|
|
16919
|
-
--db-switch-border-hover: var(--db-selection-toggle-border-hover);
|
|
16920
|
-
--db-switch-border-press: var(--db-selection-toggle-border-press);
|
|
16921
|
-
--db-switch-border-disabled: var(--db-color-action-disabled-border);
|
|
16922
|
-
--db-switch-border-checked: var(--db-selection-toggle-surface-checked);
|
|
16923
|
-
--db-switch-border-checked-hover: var(--db-selection-toggle-surface-checked-hover);
|
|
16924
|
-
--db-switch-border-checked-press: var(--db-selection-toggle-surface-checked-press);
|
|
16925
|
-
--db-switch-border-focus: var(--db-selection-toggle-surface-checked);
|
|
16926
17093
|
|
|
16927
|
-
--db-switch-thumb: var(--db-selection-toggle-surface);
|
|
16928
17094
|
|
|
16929
|
-
--db-switch-text: var(--db-selection-toggle-text);
|
|
16930
|
-
--db-switch-text-disabled: var(--db-selection-toggle-text-disabled);
|
|
16931
17095
|
|
|
16932
|
-
/* Density */
|
|
16933
|
-
--db-switch-track-width: calc(var(--db-size-4) * 1.75); /* 28px */
|
|
16934
|
-
--db-switch-track-height: var(--db-size-4); /* 16px */
|
|
16935
|
-
--db-switch-thumb-size: var(--db-switch-track-height);
|
|
16936
|
-
--db-switch-label-spacing: var(--db-selection-toggle-label-spacing);
|
|
16937
17096
|
|
|
16938
|
-
/* Motion */
|
|
16939
|
-
--db-switch-transition-duration: var(--db-selection-toggle-transition-duration);
|
|
16940
|
-
}
|
|
16941
17097
|
|
|
16942
|
-
.db-switch {
|
|
16943
|
-
/* flex, not inline-flex: an inline-flex root's line-box leading pushes block siblings
|
|
16944
|
-
* (e.g. a following FormMessage) down a few px, breaking the form-flow spacing. */
|
|
16945
|
-
display: flex;
|
|
16946
|
-
align-items: center;
|
|
16947
|
-
cursor: pointer;
|
|
16948
|
-
user-select: none;
|
|
16949
|
-
width: fit-content;
|
|
16950
|
-
margin-inline-end: var(--db-switch-label-spacing);
|
|
16951
|
-
}
|
|
16952
17098
|
|
|
16953
|
-
.
|
|
16954
|
-
|
|
17099
|
+
/* Component tokens for the native Icon. */
|
|
17100
|
+
:where(:root),
|
|
17101
|
+
:where(.du-bois-light) {
|
|
17102
|
+
--db-icon-size: var(--db-font-size-xl);
|
|
17103
|
+
--db-icon-color-danger: var(--db-color-text-validation-danger);
|
|
17104
|
+
--db-icon-color-warning: var(--db-color-text-validation-warning);
|
|
17105
|
+
--db-icon-color-success: var(--db-color-text-validation-success);
|
|
17106
|
+
--db-icon-ai-gradient-start: var(--db-ai-gradient-start);
|
|
17107
|
+
--db-icon-ai-gradient-mid: var(--db-ai-gradient-mid);
|
|
17108
|
+
--db-icon-ai-gradient-end: var(--db-ai-gradient-end);
|
|
16955
17109
|
}
|
|
16956
17110
|
|
|
16957
|
-
/*
|
|
16958
|
-
|
|
16959
|
-
|
|
16960
|
-
|
|
16961
|
-
|
|
16962
|
-
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
|
|
16966
|
-
|
|
16967
|
-
|
|
16968
|
-
|
|
16969
|
-
|
|
16970
|
-
|
|
16971
|
-
|
|
16972
|
-
border-color var(--db-switch-transition-duration) ease;
|
|
17111
|
+
/* Native Icon styles. Ships through mortar.css and reads only component-tier --db-icon-* tokens.
|
|
17112
|
+
* Icon size is driven solely by the `--db-icon-size` design token: to resize an icon, set that
|
|
17113
|
+
* token in scope (default 16px in tokens.css) rather than overriding `font-size`. */
|
|
17114
|
+
.db-icon {
|
|
17115
|
+
display: inline-block;
|
|
17116
|
+
color: inherit;
|
|
17117
|
+
font-style: normal;
|
|
17118
|
+
font-size: var(--db-icon-size);
|
|
17119
|
+
line-height: 0;
|
|
17120
|
+
text-align: center;
|
|
17121
|
+
text-transform: none;
|
|
17122
|
+
vertical-align: -0.125em;
|
|
17123
|
+
text-rendering: optimizelegibility;
|
|
17124
|
+
-webkit-font-smoothing: antialiased;
|
|
17125
|
+
-moz-osx-font-smoothing: grayscale;
|
|
16973
17126
|
}
|
|
16974
17127
|
|
|
16975
|
-
|
|
16976
|
-
|
|
16977
|
-
|
|
16978
|
-
content: '';
|
|
16979
|
-
position: absolute;
|
|
16980
|
-
top: 50%;
|
|
16981
|
-
left: calc(-1 * var(--db-switch-border-width));
|
|
16982
|
-
inline-size: var(--db-switch-thumb-size);
|
|
16983
|
-
block-size: var(--db-switch-thumb-size);
|
|
16984
|
-
border: var(--db-switch-border-width) solid;
|
|
16985
|
-
border-color: inherit;
|
|
16986
|
-
border-radius: var(--db-switch-border-radius);
|
|
16987
|
-
background-color: var(--db-switch-thumb);
|
|
16988
|
-
box-sizing: border-box;
|
|
16989
|
-
transform: translateY(-50%);
|
|
16990
|
-
transition: transform var(--db-switch-transition-duration) ease;
|
|
17128
|
+
.db-icon svg {
|
|
17129
|
+
display: inline-block;
|
|
17130
|
+
line-height: 1;
|
|
16991
17131
|
}
|
|
16992
17132
|
|
|
16993
|
-
/*
|
|
16994
|
-
.
|
|
16995
|
-
|
|
16996
|
-
|
|
17133
|
+
/* TODO: remove once clickable-icon callsites are gone. Kept for backwards compatibility with the
|
|
17134
|
+
* AntD icon, which made icons clickable via onClick; some callsites still rely on it. Actual icons
|
|
17135
|
+
* should never carry a tabindex — a clickable icon belongs inside a button. */
|
|
17136
|
+
.db-icon[tabindex] {
|
|
17137
|
+
cursor: pointer;
|
|
16997
17138
|
}
|
|
16998
17139
|
|
|
16999
|
-
|
|
17000
|
-
|
|
17001
|
-
|
|
17140
|
+
/* Semantic colors set `color` only; the SVG glyph paints its `fill`/`stroke` from `currentColor`,
|
|
17141
|
+
* so setting the text color recolors the icon. */
|
|
17142
|
+
.db-icon-danger {
|
|
17143
|
+
color: var(--db-icon-color-danger);
|
|
17002
17144
|
}
|
|
17003
17145
|
|
|
17004
|
-
.db-
|
|
17005
|
-
|
|
17006
|
-
border-color: var(--db-switch-border-checked);
|
|
17146
|
+
.db-icon-warning {
|
|
17147
|
+
color: var(--db-icon-color-warning);
|
|
17007
17148
|
}
|
|
17008
17149
|
|
|
17009
|
-
.db-
|
|
17010
|
-
|
|
17011
|
-
border-color: var(--db-switch-border-checked-hover);
|
|
17150
|
+
.db-icon-success {
|
|
17151
|
+
color: var(--db-icon-color-success);
|
|
17012
17152
|
}
|
|
17013
17153
|
|
|
17014
|
-
.db-
|
|
17015
|
-
|
|
17016
|
-
|
|
17154
|
+
.db-icon-ai svg path,
|
|
17155
|
+
.db-icon-ai svg rect,
|
|
17156
|
+
.db-icon-ai svg circle,
|
|
17157
|
+
.db-icon-ai svg ellipse,
|
|
17158
|
+
.db-icon-ai svg line,
|
|
17159
|
+
.db-icon-ai svg polygon,
|
|
17160
|
+
.db-icon-ai svg polyline,
|
|
17161
|
+
.db-icon-ai svg text,
|
|
17162
|
+
.db-icon-ai svg tspan,
|
|
17163
|
+
.db-icon-ai svg textPath,
|
|
17164
|
+
.db-icon-ai svg use {
|
|
17165
|
+
fill: var(--db-icon-gradient);
|
|
17017
17166
|
}
|
|
17018
17167
|
|
|
17019
|
-
.db-
|
|
17020
|
-
|
|
17168
|
+
.db-icon-ai-gradient-start {
|
|
17169
|
+
stop-color: var(--db-icon-ai-gradient-start);
|
|
17021
17170
|
}
|
|
17022
17171
|
|
|
17023
|
-
|
|
17024
|
-
|
|
17025
|
-
* TODO: width/offset are hardcoded 1px to preserve the AntD look; adopt the system 2px focus ring
|
|
17026
|
-
* (var(--db-focus-ring-width)) in a separate change. */
|
|
17027
|
-
.db-switch input:focus-visible {
|
|
17028
|
-
border-color: var(--db-switch-border-focus);
|
|
17029
|
-
outline: 1px solid var(--db-focus-ring-color);
|
|
17030
|
-
outline-offset: 0;
|
|
17172
|
+
.db-icon-ai-gradient-mid {
|
|
17173
|
+
stop-color: var(--db-icon-ai-gradient-mid);
|
|
17031
17174
|
}
|
|
17032
17175
|
|
|
17033
|
-
.db-
|
|
17034
|
-
|
|
17176
|
+
.db-icon-ai-gradient-end {
|
|
17177
|
+
stop-color: var(--db-icon-ai-gradient-end);
|
|
17035
17178
|
}
|
|
17036
17179
|
|
|
17037
|
-
.db-
|
|
17038
|
-
|
|
17039
|
-
|
|
17040
|
-
|
|
17180
|
+
.db-icon-gradient-definitions {
|
|
17181
|
+
position: absolute;
|
|
17182
|
+
width: 1px;
|
|
17183
|
+
height: 1px;
|
|
17184
|
+
padding: 0;
|
|
17185
|
+
margin: -1px;
|
|
17186
|
+
overflow: hidden;
|
|
17187
|
+
clip: rect(0, 0, 0, 0);
|
|
17188
|
+
white-space: nowrap;
|
|
17189
|
+
border: 0;
|
|
17041
17190
|
}
|
|
17042
17191
|
|
|
17043
|
-
|
|
17044
|
-
|
|
17045
|
-
|
|
17046
|
-
|
|
17192
|
+
.db-icon-spin {
|
|
17193
|
+
display: inline-block;
|
|
17194
|
+
animation: db-icon-loading-circle 1s infinite linear;
|
|
17195
|
+
}
|
|
17196
|
+
|
|
17197
|
+
@keyframes db-icon-loading-circle {
|
|
17198
|
+
100% {
|
|
17199
|
+
transform: rotate(360deg);
|
|
17200
|
+
}
|
|
17047
17201
|
}
|
|
17048
17202
|
|
|
17049
17203
|
@media (prefers-reduced-motion: reduce) {
|
|
17050
|
-
.db-
|
|
17051
|
-
|
|
17052
|
-
transition: none;
|
|
17204
|
+
.db-icon-spin {
|
|
17205
|
+
animation: none;
|
|
17053
17206
|
}
|
|
17054
17207
|
}
|
|
17055
17208
|
|
|
17056
|
-
|
|
17057
|
-
|
|
17058
|
-
|
|
17209
|
+
|
|
17210
|
+
:where(:root), :where(.du-bois-light) {
|
|
17211
|
+
/* Shape */
|
|
17212
|
+
--db-listbox-border-radius: var(--db-list-item-border-radius);
|
|
17213
|
+
--db-listbox-focus-ring-width: var(--db-focus-ring-width);
|
|
17214
|
+
|
|
17215
|
+
/* Color */
|
|
17216
|
+
--db-listbox-surface: var(--db-list-surface);
|
|
17217
|
+
--db-listbox-empty-text: var(--db-text-subtle);
|
|
17218
|
+
--db-listbox-focus-ring-color: var(--db-focus-ring-color);
|
|
17219
|
+
|
|
17220
|
+
/* Density */
|
|
17221
|
+
--db-listbox-spacing: var(--db-space-2);
|
|
17222
|
+
--db-listbox-empty-spacing-horizontal: var(--db-space-3);
|
|
17223
|
+
--db-listbox-empty-spacing-vertical: calc(var(--db-space-2) * 0.75);
|
|
17059
17224
|
}
|
|
17060
17225
|
|
|
17061
|
-
|
|
17062
|
-
|
|
17063
|
-
|
|
17226
|
+
|
|
17227
|
+
:where(:root), :where(.du-bois-light) {
|
|
17228
|
+
/* Shape */
|
|
17229
|
+
/* Must not scale with density; no non-scaling system token holds it. TODO(FEINF-6505): adopt a v2 system token when one is added. */
|
|
17230
|
+
--db-navigation-menu-indicator-thickness: 4px;
|
|
17231
|
+
/* No system token holds this control-specific inset. TODO(FEINF-6505): adopt a v2 system token when one is added. */
|
|
17232
|
+
--db-navigation-menu-focus-ring-offset: -1px;
|
|
17233
|
+
|
|
17234
|
+
/* Color */
|
|
17235
|
+
--db-navigation-menu-indicator: var(--db-accent-surface);
|
|
17236
|
+
--db-navigation-menu-focus-ring: var(--db-focus-ring-color);
|
|
17237
|
+
--db-navigation-menu-text: var(--db-text-subtle);
|
|
17238
|
+
--db-navigation-menu-text-selected: var(--db-text-base);
|
|
17239
|
+
/* No v2 semantic for default-action link text yet; bridges on the v1 --db-color-* token. */
|
|
17240
|
+
--db-navigation-menu-text-hover: var(--db-color-action-default-text-hover);
|
|
17241
|
+
--db-navigation-menu-text-active: var(--db-color-action-default-text-press);
|
|
17242
|
+
|
|
17243
|
+
/* Density */
|
|
17244
|
+
--db-navigation-menu-item-height: var(--db-size-8);
|
|
17245
|
+
--db-navigation-menu-item-min-width: var(--db-size-6);
|
|
17246
|
+
--db-navigation-menu-link-padding-top: var(--db-space-1);
|
|
17247
|
+
--db-navigation-menu-link-padding-bottom: var(--db-space-2);
|
|
17248
|
+
--db-navigation-menu-focus-ring-width: var(--db-focus-ring-width);
|
|
17064
17249
|
}
|
|
17065
17250
|
|
|
17066
|
-
|
|
17067
|
-
|
|
17068
|
-
|
|
17069
|
-
|
|
17251
|
+
:where(:root), :where(.du-bois-light) {
|
|
17252
|
+
/* Shape */
|
|
17253
|
+
--db-notification-border-radius: var(--db-popup-border-radius);
|
|
17254
|
+
|
|
17255
|
+
/* Density */
|
|
17256
|
+
--db-notification-padding: var(--db-space-3);
|
|
17257
|
+
--db-notification-column-gap: var(--db-space-1);
|
|
17258
|
+
--db-notification-description-gap: var(--db-space-1);
|
|
17259
|
+
--db-notification-close-offset: calc(var(--db-space-1) * 1.5);
|
|
17260
|
+
--db-notification-close-size: var(--db-size-5);
|
|
17261
|
+
--db-notification-viewport-padding: var(--db-space-3);
|
|
17262
|
+
--db-notification-viewport-gap: var(--db-space-3);
|
|
17263
|
+
--db-notification-viewport-margin: var(--db-space-6);
|
|
17264
|
+
--db-notification-viewport-width: 440px;
|
|
17265
|
+
|
|
17266
|
+
/* Color */
|
|
17267
|
+
--db-notification-surface: var(--db-popup-surface);
|
|
17268
|
+
--db-notification-border: var(--db-popup-border);
|
|
17269
|
+
--db-notification-text: var(--db-popup-text);
|
|
17270
|
+
--db-notification-icon: var(--db-text-subtle);
|
|
17271
|
+
--db-notification-icon-success: var(--db-positive-text);
|
|
17272
|
+
--db-notification-icon-warning: var(--db-caution-text);
|
|
17273
|
+
--db-notification-icon-error: var(--db-negative-text);
|
|
17070
17274
|
}
|
|
17071
17275
|
|
|
17072
|
-
.
|
|
17073
|
-
|
|
17276
|
+
:where(:root), :where(.du-bois-light) {
|
|
17277
|
+
/* Elevation */
|
|
17278
|
+
--db-notification-shadow: var(--db-elevation-med);
|
|
17074
17279
|
}
|
|
17075
17280
|
|
|
17076
|
-
|
|
17077
|
-
|
|
17078
|
-
.
|
|
17079
|
-
|
|
17281
|
+
:where(:root), :where(.du-bois-light) {
|
|
17282
|
+
/* Color */
|
|
17283
|
+
/* No v2 token holds tertiary action-text states yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17284
|
+
--db-overflow-trigger-text: var(--db-color-action-tertiary-text-default);
|
|
17285
|
+
--db-overflow-trigger-text-hover: var(--db-color-action-tertiary-text-hover);
|
|
17286
|
+
--db-overflow-trigger-text-press: var(--db-color-action-tertiary-text-press);
|
|
17287
|
+
|
|
17288
|
+
/* Density */
|
|
17289
|
+
--db-overflow-spacing: var(--db-space-2);
|
|
17290
|
+
--db-overflow-menu-spacing: var(--db-space-1);
|
|
17080
17291
|
}
|
|
17081
17292
|
|
|
17082
|
-
|
|
17083
|
-
|
|
17084
|
-
|
|
17085
|
-
*
|
|
17086
|
-
|
|
17087
|
-
|
|
17088
|
-
|
|
17089
|
-
|
|
17090
|
-
|
|
17091
|
-
|
|
17293
|
+
|
|
17294
|
+
|
|
17295
|
+
/* Popover is a neutral-card member of the popup family: surface, text, border, and radius come
|
|
17296
|
+
* from --db-popup-*. Link, focus, and spacing are popover-specific and reference system tokens
|
|
17297
|
+
* directly. The popup elevation scale is light-only, so the dark shadow is re-declared below. */
|
|
17298
|
+
|
|
17299
|
+
:where(:root), :where(.du-bois-light) {
|
|
17300
|
+
/* Shape */
|
|
17301
|
+
--db-popover-border-radius: var(--db-popup-border-radius);
|
|
17302
|
+
|
|
17303
|
+
/* Color */
|
|
17304
|
+
--db-popover-surface: var(--db-popup-surface);
|
|
17305
|
+
--db-popover-text: var(--db-popup-text);
|
|
17306
|
+
--db-popover-border: var(--db-popup-border);
|
|
17307
|
+
/* No v2 token holds the tertiary link text yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17308
|
+
--db-popover-link-text: var(--db-color-action-tertiary-text-default);
|
|
17309
|
+
--db-popover-link-text-hover: var(--db-color-action-tertiary-text-hover);
|
|
17310
|
+
--db-popover-focus-ring: var(--db-focus-ring-color);
|
|
17311
|
+
|
|
17312
|
+
/* Density */
|
|
17313
|
+
--db-popover-spacing: var(--db-space-2);
|
|
17314
|
+
--db-popover-focus-ring-width: var(--db-focus-ring-width);
|
|
17315
|
+
|
|
17316
|
+
/* Elevation */
|
|
17317
|
+
--db-popover-shadow: var(--db-popup-elevation);
|
|
17092
17318
|
}
|
|
17093
17319
|
|
|
17094
|
-
:
|
|
17095
|
-
|
|
17096
|
-
|
|
17097
|
-
|
|
17098
|
-
|
|
17099
|
-
|
|
17320
|
+
:where(:root), :where(.du-bois-light) {
|
|
17321
|
+
/* Shape */
|
|
17322
|
+
--db-preview-card-border-radius: var(--db-card-border-radius);
|
|
17323
|
+
--db-preview-card-image-border-radius: var(--info-container-border-radius, 4px);
|
|
17324
|
+
--db-preview-card-border-width: 1px;
|
|
17325
|
+
|
|
17326
|
+
/* Density */
|
|
17327
|
+
--db-preview-card-padding: var(--db-space-4);
|
|
17328
|
+
--db-preview-card-padding-large: var(--db-space-6);
|
|
17329
|
+
--db-preview-card-gap: var(--db-space-2);
|
|
17330
|
+
--db-preview-card-gap-large: var(--db-space-4);
|
|
17331
|
+
--db-preview-card-action-spacing: var(--db-space-4);
|
|
17332
|
+
|
|
17333
|
+
/* Color */
|
|
17334
|
+
--db-preview-card-text: var(--db-text-subtle);
|
|
17335
|
+
--db-preview-card-title-text: var(--db-card-text);
|
|
17336
|
+
--db-preview-card-border: var(--db-card-border);
|
|
17337
|
+
/* No v2 token holds the active/focus border yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17338
|
+
--db-preview-card-border-hover: var(--db-color-action-default-border-hover);
|
|
17339
|
+
/* No v2 token holds the focus outline ring yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17340
|
+
--db-preview-card-border-focus: var(--db-color-action-default-border-focus);
|
|
17341
|
+
/* No v2 token holds the active surface tint yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17342
|
+
--db-preview-card-surface-active: var(--db-color-action-tertiary-background-press);
|
|
17343
|
+
--db-preview-card-surface-disabled: var(--db-surface-disabled);
|
|
17344
|
+
/* No v2 token holds the disabled border yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17345
|
+
--db-preview-card-border-disabled: var(--db-color-action-disabled-border);
|
|
17346
|
+
--db-preview-card-text-disabled: var(--db-text-disabled);
|
|
17347
|
+
|
|
17348
|
+
/* Typography */
|
|
17349
|
+
--db-preview-card-title-font-weight: var(--db-font-weight-semibold);
|
|
17100
17350
|
}
|
|
17101
17351
|
|
|
17102
|
-
|
|
17103
|
-
|
|
17104
|
-
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
|
|
17352
|
+
:where(:root), :where(.du-bois-light) {
|
|
17353
|
+
/* Elevation */
|
|
17354
|
+
--db-preview-card-shadow: var(--db-elevation-low);
|
|
17355
|
+
/* No v2 elevation token holds the hover/focus shadow yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17356
|
+
--db-preview-card-shadow-hover: 0px 3px 6px 0px rgba(0, 0, 0, 0.05);
|
|
17357
|
+
}
|
|
17108
17358
|
|
|
17109
17359
|
/* Declared under the theme classes too (not just :root) so the var() chain re-resolves inside a
|
|
17110
|
-
* `.du-bois-dark` subtree
|
|
17360
|
+
* `.du-bois-dark` subtree instead of freezing at the light values. */
|
|
17111
17361
|
:where(:root), :where(.du-bois-light) {
|
|
17112
|
-
/*
|
|
17113
|
-
--db-
|
|
17114
|
-
--db-btn-height-small: var(--db-size-6);
|
|
17115
|
-
--db-btn-icon-size: var(--db-size-4);
|
|
17116
|
-
--db-btn-border-width: 1px;
|
|
17117
|
-
--db-btn-padding-vertical: var(--db-space-1);
|
|
17118
|
-
--db-btn-padding-horizontal: var(--db-space-3);
|
|
17119
|
-
--db-btn-padding-horizontal-small: var(--db-space-2);
|
|
17120
|
-
/* Icon/force-icon horizontal padding: half the standard horizontal padding. */
|
|
17121
|
-
--db-btn-padding-horizontal-icon: calc(var(--db-space-3) / 2); /* 6px */
|
|
17122
|
-
--db-btn-gap: var(--db-space-1);
|
|
17123
|
-
--db-btn-end-icon-gap: var(--db-space-2);
|
|
17124
|
-
--db-btn-end-icon-gap-small: var(--db-space-1);
|
|
17125
|
-
/* Width of a content-less button while loading, so the standalone spinner has room. */
|
|
17126
|
-
--db-btn-loading-empty-width: var(--db-size-10);
|
|
17362
|
+
/* Shape */
|
|
17363
|
+
--db-progress-border-radius: var(--db-shape-pill);
|
|
17127
17364
|
|
|
17128
|
-
/*
|
|
17129
|
-
--db-
|
|
17365
|
+
/* Color */
|
|
17366
|
+
--db-progress-track: var(--db-color-progress-track);
|
|
17367
|
+
--db-progress-fill: var(--db-color-progress-fill);
|
|
17130
17368
|
|
|
17131
|
-
/*
|
|
17132
|
-
--db-
|
|
17133
|
-
--db-btn-icon-only-font-size: var(--db-font-size-lg); /* 15px */
|
|
17134
|
-
--db-btn-font-weight: var(--db-font-weight-normal);
|
|
17135
|
-
/* Line heights are hard-coded until the typography scale ships computed per-level line-height tokens. */
|
|
17136
|
-
--db-btn-line-height: 1.25rem; /* 20px */
|
|
17137
|
-
--db-btn-line-height-small: 1rem; /* 16px */
|
|
17369
|
+
/* Density */
|
|
17370
|
+
--db-progress-size: var(--db-size-2);
|
|
17138
17371
|
|
|
17139
|
-
/*
|
|
17140
|
-
|
|
17141
|
-
--db-
|
|
17142
|
-
|
|
17143
|
-
|
|
17144
|
-
|
|
17145
|
-
|
|
17146
|
-
--db-
|
|
17147
|
-
--db-
|
|
17148
|
-
|
|
17149
|
-
|
|
17150
|
-
--db-
|
|
17151
|
-
--db-
|
|
17372
|
+
/* Motion */
|
|
17373
|
+
/* No v2 motion token holds this duration. TODO(FEINF-6505): adopt a v2 motion token when one is added. */
|
|
17374
|
+
--db-progress-transition-duration: 300ms;
|
|
17375
|
+
}
|
|
17376
|
+
|
|
17377
|
+
:where(:root), :where(.du-bois-light) {
|
|
17378
|
+
/* Shape */
|
|
17379
|
+
--db-radio-border-radius: var(--db-radius-full);
|
|
17380
|
+
--db-radio-border-width: 1px;
|
|
17381
|
+
|
|
17382
|
+
/* Color */
|
|
17383
|
+
--db-radio-surface: var(--db-selection-toggle-surface);
|
|
17384
|
+
--db-radio-surface-hover: var(--db-color-action-default-background-hover);
|
|
17385
|
+
--db-radio-surface-active: var(--db-color-action-default-background-press);
|
|
17386
|
+
--db-radio-surface-checked: var(--db-selection-toggle-surface-checked);
|
|
17387
|
+
--db-radio-surface-checked-hover: var(--db-selection-toggle-surface-checked-hover);
|
|
17388
|
+
--db-radio-surface-checked-active: var(--db-color-action-default-background-press);
|
|
17389
|
+
--db-radio-surface-disabled: var(--db-selection-toggle-surface-disabled);
|
|
17390
|
+
|
|
17391
|
+
--db-radio-border: var(--db-color-action-default-border-default);
|
|
17392
|
+
--db-radio-border-hover: var(--db-selection-toggle-border-hover);
|
|
17393
|
+
--db-radio-border-active: var(--db-selection-toggle-border-active);
|
|
17394
|
+
--db-radio-border-focus: var(--db-focus-ring-color);
|
|
17395
|
+
--db-radio-border-disabled: var(--db-color-action-disabled-border);
|
|
17396
|
+
--db-radio-border-checked-hover: var(--db-selection-toggle-border-active);
|
|
17397
|
+
--db-radio-border-checked-active: var(--db-color-action-default-border-press);
|
|
17398
|
+
--db-radio-border-unchecked-focus: var(--db-color-action-primary-background-default);
|
|
17399
|
+
--db-radio-outline-checked-focus: var(--db-color-action-primary-background-default);
|
|
17400
|
+
|
|
17401
|
+
--db-radio-mark: #ffffff;
|
|
17402
|
+
--db-radio-mark-disabled: var(--db-selection-toggle-mark-disabled);
|
|
17403
|
+
--db-radio-text: var(--db-selection-toggle-text);
|
|
17404
|
+
--db-radio-text-disabled: var(--db-selection-toggle-text-disabled);
|
|
17405
|
+
|
|
17406
|
+
/* Density */
|
|
17407
|
+
--db-radio-size: var(--db-selection-toggle-size);
|
|
17408
|
+
--db-radio-label-spacing: var(--db-selection-toggle-label-spacing);
|
|
17409
|
+
--db-radio-mark-size: var(--db-size-1);
|
|
17410
|
+
|
|
17411
|
+
/* Motion */
|
|
17412
|
+
--db-radio-transition-duration: var(--db-selection-toggle-transition-duration);
|
|
17413
|
+
}
|
|
17414
|
+
|
|
17415
|
+
/* Native-input <Radio> styles. Classic CSS only — no native nesting (the
|
|
17416
|
+
* `&`-style nesting feature ships in Chrome/Edge 120, Safari 17.2, Firefox 117
|
|
17417
|
+
* which leaves a non-trivial slice of our production traffic uncovered today;
|
|
17418
|
+
* see PR #1954620 thread). `:has()` lookups are still used to read state from
|
|
17419
|
+
* the native <input>; that feature has the support coverage we need.
|
|
17420
|
+
*
|
|
17421
|
+
* Structure (assumed by the React component):
|
|
17422
|
+
*
|
|
17423
|
+
* <label class="db-radio">
|
|
17424
|
+
* <input type="radio" />
|
|
17425
|
+
* <span class="db-radio-indicator"> ← circle border + fill react to state
|
|
17426
|
+
* <span class="db-radio-dot" /> ← visible when :checked
|
|
17427
|
+
* </span>
|
|
17428
|
+
* <span class="db-radio-label">{children}</span>
|
|
17429
|
+
* </label>
|
|
17430
|
+
*
|
|
17431
|
+
* The root only ever has one <input> descendant, so a bare `input` selector is
|
|
17432
|
+
* safe and clearer than a class. Mirrors NativeCheckbox.css; the differences are
|
|
17433
|
+
* the circular indicator (border-radius: full) and the filled dot instead of a
|
|
17434
|
+
* checkmark/dash, and there is no indeterminate state.
|
|
17435
|
+
*
|
|
17436
|
+
* TODO(DUBOIS-452): the indicator/dot state styles below are identical to
|
|
17437
|
+
* NativeCheckbox.css — consolidate them into a shared `.db-selection-toggle` class. */
|
|
17152
17438
|
|
|
17153
|
-
|
|
17154
|
-
|
|
17155
|
-
|
|
17156
|
-
|
|
17439
|
+
.db-radio {
|
|
17440
|
+
/* `display: flex` (block-level), NOT `inline-flex`: see NativeCheckbox.css for
|
|
17441
|
+
* the line-box / sibling-spacing rationale. */
|
|
17442
|
+
display: flex;
|
|
17443
|
+
align-items: flex-start;
|
|
17444
|
+
position: relative;
|
|
17445
|
+
cursor: pointer;
|
|
17446
|
+
user-select: none;
|
|
17447
|
+
min-height: var(--db-line-height-base, 20px);
|
|
17448
|
+
width: fit-content;
|
|
17157
17449
|
}
|
|
17158
17450
|
|
|
17159
|
-
/*
|
|
17160
|
-
*
|
|
17161
|
-
*
|
|
17162
|
-
|
|
17163
|
-
|
|
17164
|
-
|
|
17165
|
-
* specificity, which beats the `:where(:root)` (specificity 0) defaults regardless of file order. */
|
|
17166
|
-
.db-btn-primary {
|
|
17167
|
-
--db-btn-surface: var(--db-color-action-primary-background-default);
|
|
17168
|
-
--db-btn-surface-hover: var(--db-color-action-primary-background-hover);
|
|
17169
|
-
--db-btn-surface-press: var(--db-color-action-primary-background-press);
|
|
17170
|
-
--db-btn-surface-disabled: var(--db-color-action-disabled-border);
|
|
17171
|
-
--db-btn-border: transparent;
|
|
17172
|
-
--db-btn-border-hover: transparent;
|
|
17173
|
-
--db-btn-border-press: transparent;
|
|
17174
|
-
--db-btn-border-disabled: transparent;
|
|
17175
|
-
--db-btn-text: var(--db-color-action-primary-text-default);
|
|
17176
|
-
--db-btn-text-hover: var(--db-color-action-primary-text-hover);
|
|
17177
|
-
--db-btn-text-press: var(--db-color-action-primary-text-press);
|
|
17178
|
-
--db-btn-text-disabled: var(--db-color-action-primary-text-default);
|
|
17179
|
-
}
|
|
17180
|
-
.db-btn-tertiary,
|
|
17181
|
-
.db-btn-link {
|
|
17182
|
-
--db-btn-surface: var(--db-color-action-tertiary-background-default);
|
|
17183
|
-
--db-btn-surface-disabled: var(--db-color-action-tertiary-background-default);
|
|
17184
|
-
--db-btn-border: var(--db-color-action-tertiary-background-default);
|
|
17185
|
-
--db-btn-border-hover: transparent;
|
|
17186
|
-
--db-btn-border-press: transparent;
|
|
17187
|
-
--db-btn-border-disabled: transparent;
|
|
17188
|
-
--db-btn-text: var(--db-color-action-tertiary-text-default);
|
|
17189
|
-
--db-btn-text-hover: var(--db-color-action-tertiary-text-hover);
|
|
17190
|
-
--db-btn-text-press: var(--db-color-action-tertiary-text-press);
|
|
17191
|
-
--db-btn-text-disabled: var(--db-color-action-disabled-text);
|
|
17192
|
-
}
|
|
17193
|
-
.db-btn-tertiary {
|
|
17194
|
-
--db-btn-surface-hover: var(--db-color-action-tertiary-background-hover);
|
|
17195
|
-
--db-btn-surface-press: var(--db-color-action-tertiary-background-press);
|
|
17196
|
-
}
|
|
17197
|
-
/* Link is borderless and text-only, so its hover/press surface stays transparent. */
|
|
17198
|
-
.db-btn-link {
|
|
17199
|
-
--db-btn-surface-hover: transparent;
|
|
17200
|
-
--db-btn-surface-press: transparent;
|
|
17451
|
+
/* Hover/press live on the root (label), not on the input: the input is
|
|
17452
|
+
* visually hidden (opacity:0), so an `input:hover` rule wouldn't be visible
|
|
17453
|
+
* anyway, and the whole label area should drive the feedback. */
|
|
17454
|
+
.db-radio:hover:has(input:not(:disabled, :checked)) .db-radio-indicator {
|
|
17455
|
+
background-color: var(--db-radio-surface-hover);
|
|
17456
|
+
border-color: var(--db-radio-border-hover);
|
|
17201
17457
|
}
|
|
17202
|
-
|
|
17203
|
-
.db-
|
|
17204
|
-
|
|
17205
|
-
--db-
|
|
17206
|
-
--db-btn-text-disabled: var(--db-color-action-primary-text-default);
|
|
17458
|
+
|
|
17459
|
+
.db-radio:active:has(input:not(:disabled, :checked)) .db-radio-indicator {
|
|
17460
|
+
background-color: var(--db-radio-surface-active);
|
|
17461
|
+
border-color: var(--db-radio-border-active);
|
|
17207
17462
|
}
|
|
17208
|
-
|
|
17209
|
-
.
|
|
17210
|
-
|
|
17211
|
-
|
|
17212
|
-
|
|
17463
|
+
|
|
17464
|
+
/* Selected fill. */
|
|
17465
|
+
.db-radio:has(input:checked) .db-radio-indicator {
|
|
17466
|
+
background-color: var(--db-radio-surface-checked);
|
|
17467
|
+
border-color: var(--db-radio-surface-checked);
|
|
17213
17468
|
}
|
|
17214
|
-
|
|
17215
|
-
|
|
17216
|
-
|
|
17217
|
-
|
|
17218
|
-
|
|
17219
|
-
|
|
17220
|
-
--db-btn-border-hover: var(--db-color-action-danger-default-border-hover);
|
|
17221
|
-
--db-btn-border-press: var(--db-color-action-danger-default-border-press);
|
|
17222
|
-
--db-btn-text: var(--db-color-action-danger-default-text-default);
|
|
17223
|
-
--db-btn-text-hover: var(--db-color-action-danger-default-text-hover);
|
|
17224
|
-
--db-btn-text-press: var(--db-color-action-danger-default-text-press);
|
|
17469
|
+
|
|
17470
|
+
/* AntD getRadioInputStyles checked hover: background = actionPrimaryBackgroundHover,
|
|
17471
|
+
* borderColor = actionPrimaryBackgroundPress (a darker ring than the fill). */
|
|
17472
|
+
.db-radio:hover:has(input:checked:not(:disabled)) .db-radio-indicator {
|
|
17473
|
+
background-color: var(--db-radio-surface-checked-hover);
|
|
17474
|
+
border-color: var(--db-radio-border-checked-hover);
|
|
17225
17475
|
}
|
|
17226
|
-
|
|
17227
|
-
|
|
17228
|
-
|
|
17229
|
-
.db-
|
|
17230
|
-
|
|
17231
|
-
|
|
17232
|
-
--db-btn-surface-disabled: var(--db-color-action-tertiary-background-default);
|
|
17233
|
-
--db-btn-text: var(--db-color-action-danger-default-text-default);
|
|
17234
|
-
--db-btn-text-hover: var(--db-color-action-danger-default-text-hover);
|
|
17235
|
-
--db-btn-text-press: var(--db-color-action-danger-default-text-press);
|
|
17236
|
-
--db-btn-text-disabled: var(--db-color-action-disabled-text);
|
|
17476
|
+
|
|
17477
|
+
/* AntD getRadioInputStyles checked active: background = actionDefaultBackgroundPress,
|
|
17478
|
+
* borderColor = actionDefaultBorderPress (two-tone, not flat). */
|
|
17479
|
+
.db-radio:active:has(input:checked:not(:disabled)) .db-radio-indicator {
|
|
17480
|
+
background-color: var(--db-radio-surface-checked-active);
|
|
17481
|
+
border-color: var(--db-radio-border-checked-active);
|
|
17237
17482
|
}
|
|
17238
|
-
|
|
17239
|
-
|
|
17240
|
-
.db-
|
|
17241
|
-
|
|
17242
|
-
--db-btn-surface-hover: var(--db-color-action-tertiary-background-hover);
|
|
17243
|
-
--db-btn-surface-press: var(--db-color-action-tertiary-background-press);
|
|
17244
|
-
--db-btn-text: var(--db-color-action-tertiary-text-default);
|
|
17245
|
-
--db-btn-text-hover: var(--db-color-action-tertiary-text-hover);
|
|
17246
|
-
--db-btn-text-press: var(--db-color-action-tertiary-text-press);
|
|
17483
|
+
|
|
17484
|
+
/* Dot visibility. */
|
|
17485
|
+
.db-radio:has(input:checked) .db-radio-dot {
|
|
17486
|
+
opacity: 1;
|
|
17247
17487
|
}
|
|
17248
|
-
|
|
17249
|
-
|
|
17250
|
-
.
|
|
17251
|
-
|
|
17252
|
-
|
|
17253
|
-
|
|
17254
|
-
|
|
17255
|
-
|
|
17488
|
+
|
|
17489
|
+
/* Focus-visible (keyboard only). AntD getRadioInputStyles splits focus by checked
|
|
17490
|
+
* state, so we do too.
|
|
17491
|
+
*
|
|
17492
|
+
* UNCHECKED focus (AntD `&:not(disabled) > input:focus + inner`): only the border
|
|
17493
|
+
* color changes to actionPrimaryBackgroundDefault — NO outline ring. */
|
|
17494
|
+
.db-radio:has(input:focus-visible:not(:checked)) .db-radio-indicator {
|
|
17495
|
+
border-color: var(--db-radio-border-unchecked-focus);
|
|
17256
17496
|
}
|
|
17257
17497
|
|
|
17258
|
-
/*
|
|
17259
|
-
|
|
17260
|
-
|
|
17261
|
-
|
|
17262
|
-
|
|
17263
|
-
|
|
17264
|
-
|
|
17265
|
-
|
|
17266
|
-
vertical-align: middle;
|
|
17267
|
-
white-space: nowrap;
|
|
17268
|
-
user-select: none;
|
|
17269
|
-
cursor: pointer;
|
|
17270
|
-
height: var(--db-btn-height) !important;
|
|
17271
|
-
font-family: inherit;
|
|
17272
|
-
font-size: var(--db-btn-font-size);
|
|
17273
|
-
font-weight: var(--db-btn-font-weight);
|
|
17274
|
-
line-height: var(--db-btn-line-height) !important;
|
|
17275
|
-
text-decoration: none !important;
|
|
17276
|
-
border: var(--db-btn-border-width) solid var(--db-btn-border);
|
|
17277
|
-
border-color: var(--db-btn-border) !important;
|
|
17278
|
-
border-radius: var(--db-btn-border-radius) !important;
|
|
17279
|
-
box-shadow: none !important;
|
|
17280
|
-
background-color: var(--db-btn-surface) !important;
|
|
17281
|
-
color: var(--db-btn-text) !important;
|
|
17498
|
+
/* CHECKED focus-visible (AntD `&.checked &:not(disabled) > input:focus-visible + inner`):
|
|
17499
|
+
* background = actionPrimaryBackgroundDefault, borderColor = actionDefaultBorderFocus,
|
|
17500
|
+
* outline = 1px solid actionPrimaryBackgroundDefault, outlineOffset = 1. */
|
|
17501
|
+
.db-radio:has(input:focus-visible:checked) .db-radio-indicator {
|
|
17502
|
+
background-color: var(--db-radio-surface-checked);
|
|
17503
|
+
border-color: var(--db-radio-border-focus);
|
|
17504
|
+
outline: 1px solid var(--db-radio-outline-checked-focus);
|
|
17505
|
+
outline-offset: 1px;
|
|
17282
17506
|
}
|
|
17283
17507
|
|
|
17284
|
-
/*
|
|
17285
|
-
|
|
17286
|
-
|
|
17508
|
+
/* Disabled (covers checked and unchecked). Sourced from `input:disabled` so the
|
|
17509
|
+
* standalone-disabled and group-disabled paths both land here. */
|
|
17510
|
+
.db-radio:has(input:disabled) {
|
|
17511
|
+
cursor: not-allowed;
|
|
17287
17512
|
}
|
|
17288
|
-
|
|
17289
|
-
|
|
17513
|
+
|
|
17514
|
+
.db-radio:has(input:disabled) .db-radio-label {
|
|
17515
|
+
color: var(--db-radio-text-disabled);
|
|
17290
17516
|
}
|
|
17291
|
-
|
|
17292
|
-
|
|
17517
|
+
|
|
17518
|
+
.db-radio:has(input:disabled) .db-radio-indicator {
|
|
17519
|
+
background-color: var(--db-radio-surface-disabled);
|
|
17520
|
+
border-color: var(--db-radio-border-disabled);
|
|
17521
|
+
box-shadow: none;
|
|
17293
17522
|
}
|
|
17294
|
-
|
|
17295
|
-
|
|
17523
|
+
|
|
17524
|
+
.db-radio:has(input:disabled) .db-radio-dot {
|
|
17525
|
+
background-color: var(--db-radio-mark-disabled);
|
|
17296
17526
|
}
|
|
17297
17527
|
|
|
17298
|
-
/*
|
|
17299
|
-
|
|
17300
|
-
|
|
17301
|
-
|
|
17302
|
-
|
|
17528
|
+
/* Visually-hidden native input (opacity:0) overlaying the indicator circle,
|
|
17529
|
+
* kept interactive and in the tab order so the `:has()` lookups above can read
|
|
17530
|
+
* its state. It stays pointer-clickable — matching AntD's `.ant-radio-input` —
|
|
17531
|
+
* so it is the top-most hit-test target over the circle: `getByRole('radio').click()`
|
|
17532
|
+
* (Playwright, and any coordinate click that lands on the circle) resolves to the
|
|
17533
|
+
* real control instead of the decorative indicator overlay. Making the input
|
|
17534
|
+
* `pointer-events: none` (the prior native-only behavior) is what regressed
|
|
17535
|
+
* interaction tests vs. the AntD variant. `cursor: inherit` tracks the label's
|
|
17536
|
+
* pointer / disabled `not-allowed` cursor so the circle keeps AntD's cursor too. */
|
|
17537
|
+
.db-radio input {
|
|
17538
|
+
position: absolute;
|
|
17539
|
+
inset: 0;
|
|
17540
|
+
inline-size: var(--db-radio-size);
|
|
17541
|
+
block-size: var(--db-radio-size);
|
|
17542
|
+
margin: 0;
|
|
17543
|
+
opacity: 0;
|
|
17544
|
+
cursor: inherit;
|
|
17303
17545
|
}
|
|
17304
|
-
|
|
17305
|
-
|
|
17306
|
-
|
|
17307
|
-
|
|
17546
|
+
|
|
17547
|
+
/* Indicator — circle with the border/fill that responds to state above.
|
|
17548
|
+
* Vertical math aligns the indicator to the cap-height of the first text line
|
|
17549
|
+
* so radio + label sit on the same visual baseline even when the label wraps. */
|
|
17550
|
+
.db-radio .db-radio-indicator {
|
|
17551
|
+
display: grid;
|
|
17552
|
+
place-items: center;
|
|
17553
|
+
flex-shrink: 0;
|
|
17554
|
+
/* Decorative only — the overlaid input owns hit-testing. Without this, the
|
|
17555
|
+
* indicator (and its inherited dot child) intercept `getByRole('radio').click()`;
|
|
17556
|
+
* clicks on any edge sliver the input does not cover fall through to the label,
|
|
17557
|
+
* which toggles via label/input association. */
|
|
17558
|
+
pointer-events: none;
|
|
17559
|
+
inline-size: var(--db-radio-size);
|
|
17560
|
+
block-size: var(--db-radio-size);
|
|
17561
|
+
margin-top: calc((var(--db-line-height-base, 20px) - var(--db-radio-size)) / 2);
|
|
17562
|
+
border: var(--db-radio-border-width) solid var(--db-radio-border);
|
|
17563
|
+
border-radius: var(--db-radio-border-radius);
|
|
17564
|
+
background-color: var(--db-radio-surface);
|
|
17565
|
+
box-sizing: border-box;
|
|
17566
|
+
transition:
|
|
17567
|
+
background-color var(--db-radio-transition-duration) ease,
|
|
17568
|
+
border-color var(--db-radio-transition-duration) ease,
|
|
17569
|
+
box-shadow var(--db-radio-transition-duration) ease;
|
|
17308
17570
|
}
|
|
17309
17571
|
|
|
17310
|
-
|
|
17311
|
-
|
|
17312
|
-
|
|
17313
|
-
|
|
17572
|
+
.db-radio .db-radio-indicator > .db-radio-dot {
|
|
17573
|
+
grid-area: 1 / 1;
|
|
17574
|
+
inline-size: var(--db-radio-mark-size);
|
|
17575
|
+
block-size: var(--db-radio-mark-size);
|
|
17576
|
+
border-radius: var(--db-radius-full);
|
|
17577
|
+
background-color: var(--db-radio-mark);
|
|
17578
|
+
opacity: 0;
|
|
17579
|
+
transition: opacity var(--db-radio-transition-duration) ease;
|
|
17314
17580
|
}
|
|
17315
|
-
|
|
17316
|
-
|
|
17581
|
+
|
|
17582
|
+
/* Honour the user's reduced-motion preference: drop the state-change
|
|
17583
|
+
* transitions on the indicator and dot so checking/hovering is instant. */
|
|
17584
|
+
@media (prefers-reduced-motion: reduce) {
|
|
17585
|
+
.db-radio .db-radio-indicator,
|
|
17586
|
+
.db-radio .db-radio-indicator > .db-radio-dot {
|
|
17587
|
+
transition: none;
|
|
17588
|
+
}
|
|
17317
17589
|
}
|
|
17318
|
-
|
|
17319
|
-
|
|
17320
|
-
|
|
17590
|
+
|
|
17591
|
+
/* Padding-inline replicates the AntD `.{prefix} + span` label gap and the
|
|
17592
|
+
* trailing whitespace that separates adjacent radios in a row. */
|
|
17593
|
+
.db-radio .db-radio-label {
|
|
17594
|
+
color: var(--db-radio-text);
|
|
17595
|
+
padding-inline: var(--db-radio-label-spacing);
|
|
17596
|
+
word-break: break-word;
|
|
17321
17597
|
}
|
|
17322
17598
|
|
|
17323
|
-
/*
|
|
17324
|
-
|
|
17325
|
-
|
|
17599
|
+
/* Form-flow integration: align helper text under the radio label. The `paddingLeft`
|
|
17600
|
+
* indent comes from AntD's getCommonRadioGroupStyles (`& > label + hint`) and applies
|
|
17601
|
+
* to BOTH layouts. The doubled root class pushes specificity to (0,3,0) to beat
|
|
17602
|
+
* FormMessage's runtime `&&` margin. */
|
|
17603
|
+
.db-radio.db-radio + .du-bois-light-hint,
|
|
17604
|
+
.db-radio.db-radio + .du-bois-dark-hint,
|
|
17605
|
+
.db-radio.db-radio + .du-bois-light-form-message,
|
|
17606
|
+
.db-radio.db-radio + .du-bois-dark-form-message,
|
|
17607
|
+
.db-radio.db-radio + .du-bois-light-hint + .du-bois-light-form-message,
|
|
17608
|
+
.db-radio.db-radio + .du-bois-dark-hint + .du-bois-dark-form-message {
|
|
17609
|
+
padding-inline-start: var(--db-space-6);
|
|
17610
|
+
margin-top: 0;
|
|
17326
17611
|
}
|
|
17327
|
-
|
|
17328
|
-
|
|
17612
|
+
|
|
17613
|
+
/* Vertical hint rhythm (AntD getVerticalRadioGroupStyles, vertical-only): a hint
|
|
17614
|
+
* after a radio gets `marginTop: -sm` (cancels the preceding radio's
|
|
17615
|
+
* `paddingBottom: sm` so the hint tucks directly under its label) and
|
|
17616
|
+
* `marginBottom: sm` (gap before the next radio). The negative top margin relies on
|
|
17617
|
+
* the .db-stack gap being 0 (set below). Scoped to .db-stack so it never perturbs
|
|
17618
|
+
* the horizontal grid, where hints are positioned by grid-row instead. */
|
|
17619
|
+
.db-radio-group.db-stack > .db-radio.db-radio + .du-bois-light-hint,
|
|
17620
|
+
.db-radio-group.db-stack > .db-radio.db-radio + .du-bois-dark-hint,
|
|
17621
|
+
.db-radio-group.db-stack > .db-radio.db-radio + .du-bois-light-form-message,
|
|
17622
|
+
.db-radio-group.db-stack > .db-radio.db-radio + .du-bois-dark-form-message,
|
|
17623
|
+
.db-radio-group.db-stack > .db-radio.db-radio + .du-bois-light-hint + .du-bois-light-form-message,
|
|
17624
|
+
.db-radio-group.db-stack > .db-radio.db-radio + .du-bois-dark-hint + .du-bois-dark-form-message {
|
|
17625
|
+
margin-top: calc(-1 * var(--db-space-2));
|
|
17626
|
+
margin-bottom: var(--db-space-2);
|
|
17329
17627
|
}
|
|
17330
|
-
|
|
17331
|
-
|
|
17332
|
-
|
|
17628
|
+
|
|
17629
|
+
/* AntD `& > label:last-of-type + hint { marginTop: 0 }`: the last radio has no
|
|
17630
|
+
* `paddingBottom` to cancel, so its trailing hint keeps its natural top position. */
|
|
17631
|
+
.db-radio-group.db-stack > .db-radio.db-radio:last-of-type + .du-bois-light-hint,
|
|
17632
|
+
.db-radio-group.db-stack > .db-radio.db-radio:last-of-type + .du-bois-dark-hint,
|
|
17633
|
+
.db-radio-group.db-stack > .db-radio.db-radio:last-of-type + .du-bois-light-form-message,
|
|
17634
|
+
.db-radio-group.db-stack > .db-radio.db-radio:last-of-type + .du-bois-dark-form-message,
|
|
17635
|
+
.db-radio-group.db-stack > .db-radio.db-radio:last-of-type + .du-bois-light-hint + .du-bois-light-form-message,
|
|
17636
|
+
.db-radio-group.db-stack > .db-radio.db-radio:last-of-type + .du-bois-dark-hint + .du-bois-dark-form-message {
|
|
17637
|
+
margin-top: 0;
|
|
17333
17638
|
}
|
|
17334
|
-
|
|
17335
|
-
|
|
17639
|
+
|
|
17640
|
+
.du-bois-light-label + .db-radio-group.db-radio-group,
|
|
17641
|
+
.du-bois-dark-label + .db-radio-group.db-radio-group,
|
|
17642
|
+
.du-bois-light-hint + .db-radio-group.db-radio-group,
|
|
17643
|
+
.du-bois-dark-hint + .db-radio-group.db-radio-group,
|
|
17644
|
+
.db-radio-group.db-radio-group + .du-bois-light-form-message,
|
|
17645
|
+
.db-radio-group.db-radio-group + .du-bois-dark-form-message {
|
|
17646
|
+
margin-top: var(--db-space-2);
|
|
17336
17647
|
}
|
|
17337
|
-
|
|
17338
|
-
|
|
17648
|
+
|
|
17649
|
+
/* RadioGroup layout. Vertical (the default) delegates flex-direction to the
|
|
17650
|
+
* .db-stack primitive; horizontal is a two-row grid (mirroring AntD). */
|
|
17651
|
+
.db-radio-group {
|
|
17652
|
+
display: flex;
|
|
17339
17653
|
}
|
|
17340
17654
|
|
|
17341
|
-
/*
|
|
17342
|
-
|
|
17343
|
-
|
|
17344
|
-
|
|
17655
|
+
/* Vertical: .db-stack supplies flex-direction: column. AntD's vertical helper
|
|
17656
|
+
* (getVerticalRadioGroupStyles) produces its item rhythm purely from
|
|
17657
|
+
* `& > label { paddingBottom: sm }` plus the negative-margin hint trick above — it
|
|
17658
|
+
* uses NO flex gap. The negative `marginTop` on hints only works if the stack adds
|
|
17659
|
+
* no gap of its own, so we zero out the gap and reproduce the rhythm via
|
|
17660
|
+
* padding-bottom on each radio. */
|
|
17661
|
+
.db-radio-group.db-stack {
|
|
17662
|
+
--db-stack-gap: 0;
|
|
17345
17663
|
}
|
|
17346
|
-
|
|
17347
|
-
|
|
17348
|
-
.db-
|
|
17349
|
-
|
|
17350
|
-
color: var(--db-btn-text) !important;
|
|
17664
|
+
|
|
17665
|
+
/* AntD `& > label { paddingBottom: sm }`. */
|
|
17666
|
+
.db-radio-group.db-stack > .db-radio {
|
|
17667
|
+
padding-bottom: var(--db-space-2);
|
|
17351
17668
|
}
|
|
17352
|
-
|
|
17353
|
-
|
|
17354
|
-
.db-
|
|
17355
|
-
|
|
17669
|
+
|
|
17670
|
+
/* AntD `& > label:last-of-type { paddingBottom: 0 }`. */
|
|
17671
|
+
.db-radio-group.db-stack > .db-radio:last-of-type {
|
|
17672
|
+
padding-bottom: 0;
|
|
17356
17673
|
}
|
|
17357
17674
|
|
|
17358
|
-
/*
|
|
17359
|
-
|
|
17360
|
-
|
|
17675
|
+
/* AntD getVerticalRadioGroupStyles `.${prefix}-radio-tile + .${prefix}-radio-tile {
|
|
17676
|
+
* marginTop: md }`: RadioTiles are not matched by the `.db-radio` padding-bottom
|
|
17677
|
+
* rhythm above (the tile's own class is du-bois-{light,dark}-radio-tile), so space
|
|
17678
|
+
* consecutive tiles explicitly. The .db-stack gap is 0, so this margin is the spacing. */
|
|
17679
|
+
.db-radio-group.db-stack > .du-bois-light-radio-tile + .du-bois-light-radio-tile,
|
|
17680
|
+
.db-radio-group.db-stack > .du-bois-light-radio-tile + .du-bois-dark-radio-tile,
|
|
17681
|
+
.db-radio-group.db-stack > .du-bois-dark-radio-tile + .du-bois-light-radio-tile,
|
|
17682
|
+
.db-radio-group.db-stack > .du-bois-dark-radio-tile + .du-bois-dark-radio-tile {
|
|
17683
|
+
margin-top: var(--db-space-4);
|
|
17361
17684
|
}
|
|
17362
17685
|
|
|
17363
|
-
/*
|
|
17364
|
-
|
|
17365
|
-
|
|
17366
|
-
|
|
17367
|
-
|
|
17368
|
-
|
|
17686
|
+
/* Horizontal: AntD `getHorizontalRadioGroupStyles` is a TWO-ROW grid (NOT a flex
|
|
17687
|
+
* row) so each radio sits in the [label] row and its following hint drops into the
|
|
17688
|
+
* [hint] row of the same auto-column. `&&` in AntD doubles specificity; the doubled
|
|
17689
|
+
* group class here matches that.
|
|
17690
|
+
* AntD: `display: grid; gridTemplateRows: [label] auto [hint] auto;
|
|
17691
|
+
* gridAutoColumns: max-content; gridColumnGap: md`. */
|
|
17692
|
+
.db-radio-group--horizontal.db-radio-group--horizontal {
|
|
17693
|
+
display: grid;
|
|
17694
|
+
grid-template-rows: [label] auto [hint] auto;
|
|
17695
|
+
grid-auto-columns: max-content;
|
|
17696
|
+
column-gap: var(--db-space-4);
|
|
17369
17697
|
}
|
|
17370
|
-
|
|
17371
|
-
|
|
17372
|
-
|
|
17698
|
+
|
|
17699
|
+
/* Equal column widths: AntD `gridAutoColumns: minmax(0, 1fr)`. */
|
|
17700
|
+
.db-radio-group--horizontal.db-radio-group--equal-width {
|
|
17701
|
+
grid-auto-columns: minmax(0, 1fr);
|
|
17373
17702
|
}
|
|
17374
|
-
|
|
17375
|
-
|
|
17703
|
+
|
|
17704
|
+
/* AntD `& > label, & > .${prefix}-radio-tile { gridRow: label / label; marginRight: 0 }`:
|
|
17705
|
+
* every radio (and every RadioTile button, whose own class is
|
|
17706
|
+
* du-bois-{light,dark}-radio-tile and is NOT matched by `> .db-radio`) lives in the
|
|
17707
|
+
* label row. grid-auto-flow defaults to row, so successive items advance the implicit
|
|
17708
|
+
* column. */
|
|
17709
|
+
.db-radio-group--horizontal > .db-radio,
|
|
17710
|
+
.db-radio-group--horizontal > .du-bois-light-radio-tile,
|
|
17711
|
+
.db-radio-group--horizontal > .du-bois-dark-radio-tile {
|
|
17712
|
+
grid-row: label / label;
|
|
17713
|
+
margin-inline-end: 0;
|
|
17376
17714
|
}
|
|
17377
|
-
|
|
17378
|
-
|
|
17379
|
-
|
|
17380
|
-
|
|
17715
|
+
|
|
17716
|
+
/* AntD `& > label + hint { display: inline-block; gridRow: hint / hint }`: a hint
|
|
17717
|
+
* following a radio drops into the hint row of the column its radio occupies. The
|
|
17718
|
+
* vertical negative-margin rules are scoped to .db-stack, so nothing to reset here. */
|
|
17719
|
+
.db-radio-group--horizontal > .du-bois-light-hint,
|
|
17720
|
+
.db-radio-group--horizontal > .du-bois-dark-hint {
|
|
17721
|
+
display: inline-block;
|
|
17722
|
+
grid-row: hint / hint;
|
|
17381
17723
|
}
|
|
17382
|
-
|
|
17383
|
-
|
|
17724
|
+
|
|
17725
|
+
/* AntD `:has(> hint) { marginTop: sm }`: when the horizontal group contains a hint,
|
|
17726
|
+
* the group itself gets a top margin (room above the two-row grid). */
|
|
17727
|
+
.db-radio-group--horizontal:has(> .du-bois-light-hint),
|
|
17728
|
+
.db-radio-group--horizontal:has(> .du-bois-dark-hint) {
|
|
17729
|
+
margin-top: var(--db-space-2);
|
|
17384
17730
|
}
|
|
17385
|
-
|
|
17386
|
-
|
|
17731
|
+
|
|
17732
|
+
/* AntD `&& + form-message { marginTop: sm }` (horizontal): a form-message following
|
|
17733
|
+
* the whole group is separated by sm. */
|
|
17734
|
+
.db-radio-group--horizontal + .du-bois-light-form-message,
|
|
17735
|
+
.db-radio-group--horizontal + .du-bois-dark-form-message {
|
|
17736
|
+
margin-top: var(--db-space-2);
|
|
17387
17737
|
}
|
|
17388
|
-
|
|
17389
|
-
|
|
17390
|
-
|
|
17738
|
+
|
|
17739
|
+
|
|
17740
|
+
|
|
17741
|
+
|
|
17742
|
+
|
|
17743
|
+
:where(:root), :where(.du-bois-light) {
|
|
17744
|
+
/* Shape */
|
|
17745
|
+
--db-slider-border-radius: var(--db-shape-pill);
|
|
17746
|
+
|
|
17747
|
+
/* Color */
|
|
17748
|
+
/* No v2 token holds the track + disabled-range surface yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17749
|
+
--db-slider-track-surface: #e8ecf0;
|
|
17750
|
+
--db-slider-range-surface-disabled: #e8ecf0;
|
|
17751
|
+
/* No v2 token holds the range fill yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17752
|
+
--db-slider-range-surface: #2272b4;
|
|
17753
|
+
|
|
17754
|
+
--db-slider-thumb-surface: var(--db-accent-surface);
|
|
17755
|
+
--db-slider-thumb-surface-hover: var(--db-accent-surface-hover);
|
|
17756
|
+
--db-slider-thumb-surface-press: var(--db-accent-surface-active);
|
|
17757
|
+
/* No v2 token holds the disabled thumb yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17758
|
+
--db-slider-thumb-surface-disabled: #d1d9e1;
|
|
17759
|
+
|
|
17760
|
+
/* Density */
|
|
17761
|
+
--db-slider-size: var(--db-size-5); /* 20px */
|
|
17762
|
+
--db-slider-thumb-size: var(--db-size-5); /* 20px */
|
|
17763
|
+
--db-slider-track-thickness: calc(var(--db-size-1) * 0.75); /* 3px */
|
|
17391
17764
|
}
|
|
17392
|
-
|
|
17393
|
-
|
|
17394
|
-
|
|
17765
|
+
|
|
17766
|
+
:where(:root), :where(.du-bois-light) {
|
|
17767
|
+
/* Shape */
|
|
17768
|
+
/* TODO(FEINF-6505): adopt --db-shape-container-* once a 4px container radius exists; kept on --db-radius-sm to preserve 4px. */
|
|
17769
|
+
--db-snackbar-border-radius: var(--db-radius-sm);
|
|
17770
|
+
|
|
17771
|
+
/* Density */
|
|
17772
|
+
--db-snackbar-spacing-vertical: var(--db-space-3);
|
|
17773
|
+
--db-snackbar-spacing-horizontal: var(--db-space-4);
|
|
17774
|
+
--db-snackbar-close-button-spacing: var(--db-space-2);
|
|
17775
|
+
|
|
17776
|
+
/* Color */
|
|
17777
|
+
/* No v1/v2 system token holds this theme-invariant white. TODO(FEINF-6505): adopt a v2 system token when one is added. */
|
|
17778
|
+
--db-snackbar-text: #ffffff;
|
|
17779
|
+
/* No v1/v2 system token holds these theme-invariant close-icon colors. TODO(FEINF-6505): adopt a v2 system token when one is added. */
|
|
17780
|
+
--db-snackbar-close-icon: #e8ecf0;
|
|
17781
|
+
--db-snackbar-close-icon-hover: #8acaff;
|
|
17782
|
+
--db-snackbar-close-icon-active: #bae1fc;
|
|
17395
17783
|
}
|
|
17396
|
-
|
|
17397
|
-
|
|
17398
|
-
|
|
17784
|
+
|
|
17785
|
+
:where(:root), :where(.du-bois-light) {
|
|
17786
|
+
/* Color */
|
|
17787
|
+
/* No v1/v2 system token holds this light/dark surface pair. TODO(FEINF-6505): adopt a v2 system token when one is added. */
|
|
17788
|
+
--db-snackbar-surface: #11171c;
|
|
17789
|
+
|
|
17790
|
+
/* Elevation */
|
|
17791
|
+
--db-snackbar-shadow: var(--db-elevation-med);
|
|
17399
17792
|
}
|
|
17400
|
-
|
|
17401
|
-
|
|
17793
|
+
|
|
17794
|
+
/* Spacer's height is a spacing step. The size prop (xs/sm/mid/md/lg) selects one component token,
|
|
17795
|
+
* each aliasing the system space scale — theme-invariant, so a single block (no light/dark split). */
|
|
17796
|
+
|
|
17797
|
+
:where(:root), :where(.du-bois-light) {
|
|
17798
|
+
/* Density */
|
|
17799
|
+
--db-spacer-size-xs: var(--db-space-1); /* 4px */
|
|
17800
|
+
--db-spacer-size-sm: var(--db-space-2); /* 8px */
|
|
17801
|
+
--db-spacer-size-mid: var(--db-space-3); /* 12px */
|
|
17802
|
+
--db-spacer-size-md: var(--db-space-4); /* 16px */
|
|
17803
|
+
--db-spacer-size-lg: var(--db-space-6); /* 24px */
|
|
17402
17804
|
}
|
|
17403
|
-
|
|
17404
|
-
|
|
17405
|
-
|
|
17805
|
+
|
|
17806
|
+
|
|
17807
|
+
|
|
17808
|
+
:where(:root), :where(.du-bois-light) {
|
|
17809
|
+
/* Shape */
|
|
17810
|
+
--db-switch-border-radius: var(--db-radius-full);
|
|
17811
|
+
--db-switch-border-width: 1px;
|
|
17812
|
+
|
|
17813
|
+
/* Color */
|
|
17814
|
+
--db-switch-surface: var(--db-selection-toggle-surface);
|
|
17815
|
+
--db-switch-surface-hover: var(--db-color-action-default-background-hover);
|
|
17816
|
+
--db-switch-surface-active: var(--db-color-action-default-background-press);
|
|
17817
|
+
--db-switch-surface-checked: var(--db-selection-toggle-surface-checked);
|
|
17818
|
+
--db-switch-surface-checked-hover: var(--db-selection-toggle-surface-checked-hover);
|
|
17819
|
+
--db-switch-surface-checked-active: var(--db-selection-toggle-surface-checked-active);
|
|
17820
|
+
--db-switch-surface-disabled: var(--db-selection-toggle-surface-disabled);
|
|
17821
|
+
--db-switch-surface-checked-disabled: var(--db-color-action-disabled-text);
|
|
17822
|
+
|
|
17823
|
+
--db-switch-border: var(--db-color-action-default-border-default);
|
|
17824
|
+
--db-switch-border-hover: var(--db-selection-toggle-border-hover);
|
|
17825
|
+
--db-switch-border-active: var(--db-selection-toggle-border-active);
|
|
17826
|
+
--db-switch-border-disabled: var(--db-color-action-disabled-border);
|
|
17827
|
+
--db-switch-border-checked: var(--db-selection-toggle-surface-checked);
|
|
17828
|
+
--db-switch-border-checked-hover: var(--db-selection-toggle-surface-checked-hover);
|
|
17829
|
+
--db-switch-border-checked-active: var(--db-selection-toggle-surface-checked-active);
|
|
17830
|
+
--db-switch-border-focus: var(--db-selection-toggle-surface-checked);
|
|
17831
|
+
|
|
17832
|
+
--db-switch-thumb: var(--db-selection-toggle-surface);
|
|
17833
|
+
|
|
17834
|
+
--db-switch-text: var(--db-selection-toggle-text);
|
|
17835
|
+
--db-switch-text-disabled: var(--db-selection-toggle-text-disabled);
|
|
17836
|
+
|
|
17837
|
+
/* Density */
|
|
17838
|
+
--db-switch-track-width: calc(var(--db-size-4) * 1.75); /* 28px */
|
|
17839
|
+
--db-switch-track-height: var(--db-size-4); /* 16px */
|
|
17840
|
+
--db-switch-thumb-size: var(--db-switch-track-height);
|
|
17841
|
+
--db-switch-label-spacing: var(--db-selection-toggle-label-spacing);
|
|
17842
|
+
|
|
17843
|
+
/* Motion */
|
|
17844
|
+
--db-switch-transition-duration: var(--db-selection-toggle-transition-duration);
|
|
17406
17845
|
}
|
|
17407
|
-
|
|
17408
|
-
|
|
17409
|
-
|
|
17846
|
+
|
|
17847
|
+
.db-switch {
|
|
17848
|
+
/* flex, not inline-flex: an inline-flex root's line-box leading pushes block siblings
|
|
17849
|
+
* (e.g. a following FormMessage) down a few px, breaking the form-flow spacing. */
|
|
17850
|
+
display: flex;
|
|
17851
|
+
align-items: center;
|
|
17852
|
+
cursor: pointer;
|
|
17853
|
+
user-select: none;
|
|
17854
|
+
width: fit-content;
|
|
17855
|
+
margin-inline-end: var(--db-switch-label-spacing);
|
|
17410
17856
|
}
|
|
17411
17857
|
|
|
17412
|
-
|
|
17413
|
-
.db-btn:disabled {
|
|
17858
|
+
.db-switch:has(.db-switch-input:disabled) {
|
|
17414
17859
|
cursor: not-allowed;
|
|
17415
|
-
background-color: var(--db-btn-surface-disabled) !important;
|
|
17416
|
-
color: var(--db-btn-text-disabled) !important;
|
|
17417
|
-
}
|
|
17418
|
-
/* Empty and loading disabled buttons keep a transparent border (set elsewhere), so exclude them.
|
|
17419
|
-
* `:where()` on the exclusion holds this at (0,2,0): enough to beat the base border, while still
|
|
17420
|
-
* letting a consumer's own `[disabled]` border override win on source order. */
|
|
17421
|
-
.db-btn:disabled:where(:not(.db-btn-empty, .db-btn-loading)) {
|
|
17422
|
-
border-color: var(--db-btn-border-disabled) !important;
|
|
17423
|
-
}
|
|
17424
|
-
.db-btn-icon-only:disabled {
|
|
17425
|
-
border: none;
|
|
17426
17860
|
}
|
|
17427
|
-
|
|
17428
|
-
|
|
17861
|
+
|
|
17862
|
+
/* The track. `appearance: none` strips the native checkbox rendering so the input itself can be styled.
|
|
17863
|
+
* Scoped via the `.db-switch-input` class, never a bare `input`: `.db-switch .db-switch-input` is
|
|
17864
|
+
* specificity (0,2,0), which out-ranks a host app's `input[type='checkbox'] { width: auto }` reset
|
|
17865
|
+
* (e.g. Bootstrap, loaded in webapp). A bare `.db-switch input` (0,1,1) merely ties that reset and, losing
|
|
17866
|
+
* on load order, has its `inline-size` overridden to `auto` — collapsing the track to zero width and
|
|
17867
|
+
* leaving only the floating thumb. Mirrors NativeCheckbox's `.db-checkbox-input`. */
|
|
17868
|
+
.db-switch .db-switch-input {
|
|
17869
|
+
appearance: none;
|
|
17870
|
+
position: relative;
|
|
17871
|
+
flex-shrink: 0;
|
|
17872
|
+
margin: 0;
|
|
17873
|
+
cursor: pointer;
|
|
17874
|
+
inline-size: var(--db-switch-track-width);
|
|
17875
|
+
block-size: var(--db-switch-track-height);
|
|
17876
|
+
border: var(--db-switch-border-width) solid var(--db-switch-border);
|
|
17877
|
+
border-radius: var(--db-switch-border-radius);
|
|
17878
|
+
background-color: var(--db-switch-surface);
|
|
17879
|
+
box-sizing: border-box;
|
|
17880
|
+
transition:
|
|
17881
|
+
background-color var(--db-switch-transition-duration) ease,
|
|
17882
|
+
border-color var(--db-switch-transition-duration) ease;
|
|
17429
17883
|
}
|
|
17430
|
-
|
|
17431
|
-
|
|
17884
|
+
|
|
17885
|
+
/* The thumb. A pseudo-element keeps the input the switch's only element, so nothing can overlay it
|
|
17886
|
+
* and intercept clicks. Offset left by the border width to sit flush with the track's outer edge. */
|
|
17887
|
+
.db-switch .db-switch-input::before {
|
|
17888
|
+
content: '';
|
|
17889
|
+
position: absolute;
|
|
17890
|
+
top: 50%;
|
|
17891
|
+
left: calc(-1 * var(--db-switch-border-width));
|
|
17892
|
+
inline-size: var(--db-switch-thumb-size);
|
|
17893
|
+
block-size: var(--db-switch-thumb-size);
|
|
17894
|
+
border: var(--db-switch-border-width) solid;
|
|
17895
|
+
border-color: inherit;
|
|
17896
|
+
border-radius: var(--db-switch-border-radius);
|
|
17897
|
+
background-color: var(--db-switch-thumb);
|
|
17898
|
+
box-sizing: border-box;
|
|
17899
|
+
transform: translateY(-50%);
|
|
17900
|
+
transition: transform var(--db-switch-transition-duration) ease;
|
|
17432
17901
|
}
|
|
17433
17902
|
|
|
17434
|
-
/*
|
|
17435
|
-
|
|
17436
|
-
|
|
17437
|
-
|
|
17438
|
-
.db-btn > .anticon,
|
|
17439
|
-
.db-btn-end-icon,
|
|
17440
|
-
.db-btn-end-icon > .anticon {
|
|
17441
|
-
display: inline-flex;
|
|
17442
|
-
align-items: center;
|
|
17443
|
-
font-size: var(--db-btn-icon-size) !important;
|
|
17444
|
-
line-height: 0;
|
|
17903
|
+
/* `<label for>` propagates `:hover` to the input, so scope hover/press to the control, not `input:hover`. */
|
|
17904
|
+
.db-switch:hover .db-switch-input:not(:disabled):not(:checked) {
|
|
17905
|
+
background-color: var(--db-switch-surface-hover);
|
|
17906
|
+
border-color: var(--db-switch-border-hover);
|
|
17445
17907
|
}
|
|
17446
|
-
|
|
17447
|
-
|
|
17908
|
+
|
|
17909
|
+
.db-switch:active .db-switch-input:not(:disabled):not(:checked) {
|
|
17910
|
+
background-color: var(--db-switch-surface-active);
|
|
17911
|
+
border-color: var(--db-switch-border-active);
|
|
17448
17912
|
}
|
|
17449
|
-
|
|
17450
|
-
|
|
17451
|
-
|
|
17452
|
-
|
|
17913
|
+
|
|
17914
|
+
.db-switch .db-switch-input:checked {
|
|
17915
|
+
background-color: var(--db-switch-surface-checked);
|
|
17916
|
+
border-color: var(--db-switch-border-checked);
|
|
17453
17917
|
}
|
|
17454
|
-
|
|
17455
|
-
|
|
17456
|
-
|
|
17918
|
+
|
|
17919
|
+
.db-switch:hover .db-switch-input:checked:not(:disabled) {
|
|
17920
|
+
background-color: var(--db-switch-surface-checked-hover);
|
|
17921
|
+
border-color: var(--db-switch-border-checked-hover);
|
|
17457
17922
|
}
|
|
17458
|
-
|
|
17459
|
-
|
|
17923
|
+
|
|
17924
|
+
.db-switch:active .db-switch-input:checked:not(:disabled) {
|
|
17925
|
+
background-color: var(--db-switch-surface-checked-active);
|
|
17926
|
+
border-color: var(--db-switch-border-checked-active);
|
|
17460
17927
|
}
|
|
17461
|
-
|
|
17462
|
-
|
|
17928
|
+
|
|
17929
|
+
.db-switch .db-switch-input:checked::before {
|
|
17930
|
+
transform: translateY(-50%) translateX(calc(var(--db-switch-track-width) - var(--db-switch-thumb-size)));
|
|
17463
17931
|
}
|
|
17464
|
-
|
|
17465
|
-
|
|
17932
|
+
|
|
17933
|
+
/* On focus, recolor the border to the checked-fill color on top of the outline ring. Matching AntD,
|
|
17934
|
+
* the ring sits flush when off and gains a 1px offset when checked.
|
|
17935
|
+
* TODO: width/offset are hardcoded 1px to preserve the AntD look; adopt the system 2px focus ring
|
|
17936
|
+
* (var(--db-focus-ring-width)) in a separate change. */
|
|
17937
|
+
.db-switch .db-switch-input:focus-visible {
|
|
17938
|
+
border-color: var(--db-switch-border-focus);
|
|
17939
|
+
outline: 1px solid var(--db-focus-ring-color);
|
|
17940
|
+
outline-offset: 0;
|
|
17466
17941
|
}
|
|
17467
|
-
|
|
17468
|
-
|
|
17942
|
+
|
|
17943
|
+
.db-switch .db-switch-input:checked:focus-visible {
|
|
17944
|
+
outline-offset: 1px;
|
|
17469
17945
|
}
|
|
17470
|
-
|
|
17471
|
-
|
|
17946
|
+
|
|
17947
|
+
.db-switch .db-switch-input:disabled {
|
|
17948
|
+
cursor: not-allowed;
|
|
17949
|
+
background-color: var(--db-switch-surface-disabled);
|
|
17950
|
+
border-color: var(--db-switch-border-disabled);
|
|
17472
17951
|
}
|
|
17473
|
-
|
|
17474
|
-
|
|
17475
|
-
|
|
17476
|
-
|
|
17477
|
-
color: var(--db-
|
|
17952
|
+
|
|
17953
|
+
/* Disabled + on: more specific than the plain disabled rule, so it wins regardless of source order. */
|
|
17954
|
+
.db-switch .db-switch-input:checked:disabled {
|
|
17955
|
+
background-color: var(--db-switch-surface-checked-disabled);
|
|
17956
|
+
border-color: var(--db-switch-surface-checked-disabled);
|
|
17478
17957
|
}
|
|
17479
17958
|
|
|
17480
|
-
|
|
17481
|
-
.db-
|
|
17482
|
-
|
|
17959
|
+
@media (prefers-reduced-motion: reduce) {
|
|
17960
|
+
.db-switch .db-switch-input,
|
|
17961
|
+
.db-switch .db-switch-input::before {
|
|
17962
|
+
transition: none;
|
|
17963
|
+
}
|
|
17483
17964
|
}
|
|
17484
|
-
|
|
17485
|
-
|
|
17965
|
+
|
|
17966
|
+
.db-switch-wrapper {
|
|
17967
|
+
display: flex;
|
|
17968
|
+
align-items: center;
|
|
17486
17969
|
}
|
|
17487
|
-
|
|
17488
|
-
|
|
17489
|
-
|
|
17970
|
+
|
|
17971
|
+
.db-switch-wrapper .db-switch-state-message {
|
|
17972
|
+
margin-inline-start: auto;
|
|
17973
|
+
margin-inline-end: var(--db-switch-label-spacing);
|
|
17490
17974
|
}
|
|
17491
|
-
|
|
17492
|
-
|
|
17975
|
+
|
|
17976
|
+
/* `:first-child` scopes this to the label-first layout; the plain layout renders the label last. */
|
|
17977
|
+
.db-switch-wrapper > .du-bois-light-label:first-child,
|
|
17978
|
+
.db-switch-wrapper > .du-bois-dark-label:first-child {
|
|
17979
|
+
margin-inline-end: var(--db-switch-label-spacing);
|
|
17493
17980
|
}
|
|
17494
|
-
|
|
17495
|
-
|
|
17496
|
-
|
|
17497
|
-
top: 50%;
|
|
17498
|
-
transform: translate(-50%, -50%);
|
|
17981
|
+
|
|
17982
|
+
.db-switch-state-message {
|
|
17983
|
+
color: var(--db-switch-text);
|
|
17499
17984
|
}
|
|
17500
|
-
|
|
17501
|
-
|
|
17502
|
-
|
|
17985
|
+
|
|
17986
|
+
/* Target the <Label>'s class, not a bare `label` — that would also match the .db-switch root <label>. */
|
|
17987
|
+
.db-switch-wrapper:has(.db-switch-input:disabled) .du-bois-light-label,
|
|
17988
|
+
.db-switch-wrapper:has(.db-switch-input:disabled) .du-bois-dark-label {
|
|
17989
|
+
color: var(--db-switch-text-disabled);
|
|
17503
17990
|
}
|
|
17504
17991
|
|
|
17505
|
-
/*
|
|
17506
|
-
.
|
|
17507
|
-
|
|
17508
|
-
|
|
17992
|
+
/* Indent a following hint/message past the track. The class is doubled to out-specify FormMessage's
|
|
17993
|
+
* own margin rule. Each rule's key (rightmost) selector is a single class, not a multi-item :is(),
|
|
17994
|
+
* so Chromium can hash-reject it instead of attempting the match against every element on every
|
|
17995
|
+
* recalc (the leading/middle :is() groups aren't the key selector, so they're left as-is). */
|
|
17996
|
+
:is(.db-switch.db-switch, .db-switch-wrapper.db-switch-wrapper) + .du-bois-light-hint, :is(.db-switch.db-switch, .db-switch-wrapper.db-switch-wrapper) + .du-bois-dark-hint, :is(.db-switch.db-switch, .db-switch-wrapper.db-switch-wrapper) + .du-bois-light-form-message, :is(.db-switch.db-switch, .db-switch-wrapper.db-switch-wrapper) + .du-bois-dark-form-message, :is(.db-switch.db-switch, .db-switch-wrapper.db-switch-wrapper)
|
|
17997
|
+
+ :is(.du-bois-light-hint, .du-bois-dark-hint)
|
|
17998
|
+
+ .du-bois-light-form-message, :is(.db-switch.db-switch, .db-switch-wrapper.db-switch-wrapper)
|
|
17999
|
+
+ :is(.du-bois-light-hint, .du-bois-dark-hint)
|
|
18000
|
+
+ .du-bois-dark-form-message {
|
|
18001
|
+
padding-inline-start: calc(var(--db-space-2) + var(--db-switch-track-width));
|
|
17509
18002
|
}
|
|
17510
|
-
|
|
17511
|
-
|
|
18003
|
+
|
|
18004
|
+
:is(.db-switch.db-switch, .db-switch-wrapper.db-switch-wrapper) + .du-bois-light-form-message, :is(.db-switch.db-switch, .db-switch-wrapper.db-switch-wrapper) + .du-bois-dark-form-message, :is(.db-switch.db-switch, .db-switch-wrapper.db-switch-wrapper)
|
|
18005
|
+
+ :is(.du-bois-light-hint, .du-bois-dark-hint)
|
|
18006
|
+
+ .du-bois-light-form-message, :is(.db-switch.db-switch, .db-switch-wrapper.db-switch-wrapper)
|
|
18007
|
+
+ :is(.du-bois-light-hint, .du-bois-dark-hint)
|
|
18008
|
+
+ .du-bois-dark-form-message {
|
|
18009
|
+
margin-top: 0;
|
|
17512
18010
|
}
|
|
17513
18011
|
|
|
18012
|
+
/* Component tokens for Tabs (no family). Re-declared under the theme classes, not only :root, so the
|
|
18013
|
+
* var() chain re-resolves inside a .du-bois-dark subtree instead of freezing at the light value. */
|
|
17514
18014
|
:where(:root), :where(.du-bois-light) {
|
|
17515
|
-
/*
|
|
17516
|
-
|
|
17517
|
-
--db-
|
|
17518
|
-
|
|
17519
|
-
--db-
|
|
18015
|
+
/* ── Density ──────────────────────────────────────────────────────────── */
|
|
18016
|
+
--db-tabs-height: var(--db-size-8);
|
|
18017
|
+
--db-tabs-trigger-min-width: var(--db-size-6);
|
|
18018
|
+
--db-tabs-trigger-min-width-closable: var(--db-size-10);
|
|
18019
|
+
--db-tabs-list-margin-bottom: var(--db-space-4);
|
|
18020
|
+
--db-tabs-trigger-gap: var(--db-space-4);
|
|
18021
|
+
--db-tabs-trigger-padding-top: var(--db-space-1);
|
|
18022
|
+
--db-tabs-trigger-padding-bottom: var(--db-space-2);
|
|
18023
|
+
--db-tabs-close-icon-gap: var(--db-space-1);
|
|
18024
|
+
--db-tabs-add-button-margin-top: var(--db-space-0-5);
|
|
18025
|
+
/* No 1.5-unit space step exists; synthesize 6px from the nearest. TODO: use a direct step if one lands. */
|
|
18026
|
+
--db-tabs-add-button-margin-bottom: calc(var(--db-space-1) * 1.5);
|
|
17520
18027
|
|
|
17521
|
-
/*
|
|
17522
|
-
--db-
|
|
17523
|
-
--db-
|
|
17524
|
-
--db-navigation-menu-text: var(--db-text-subtle);
|
|
17525
|
-
--db-navigation-menu-text-active: var(--db-text-base);
|
|
17526
|
-
/* No v2 semantic for default-action link text yet; bridges on the v1 --db-color-* token. */
|
|
17527
|
-
--db-navigation-menu-text-hover: var(--db-color-action-default-text-hover);
|
|
17528
|
-
--db-navigation-menu-text-press: var(--db-color-action-default-text-press);
|
|
18028
|
+
/* ── Shape ────────────────────────────────────────────────────────────── */
|
|
18029
|
+
--db-tabs-scrollbar-radius: var(--db-shape-control);
|
|
18030
|
+
--db-tabs-focus-ring-width: var(--db-focus-ring-width);
|
|
17529
18031
|
|
|
17530
|
-
/*
|
|
17531
|
-
--db-
|
|
17532
|
-
--db-
|
|
17533
|
-
|
|
17534
|
-
--db-
|
|
17535
|
-
|
|
18032
|
+
/* ── Typography ───────────────────────────────────────────────────────── */
|
|
18033
|
+
--db-tabs-font-size: var(--db-font-size-base);
|
|
18034
|
+
--db-tabs-font-weight: var(--db-font-weight-semibold);
|
|
18035
|
+
/* No v2 token holds the tab line-height yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
18036
|
+
--db-tabs-line-height: 1.25rem;
|
|
18037
|
+
|
|
18038
|
+
/* ── Color ────────────────────────────────────────────────────────────── */
|
|
18039
|
+
/* No v2 token holds the tab text / hover / press / active / disabled colors yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
18040
|
+
--db-tabs-text: var(--db-color-text-secondary);
|
|
18041
|
+
--db-tabs-text-hover: var(--db-color-action-default-text-hover);
|
|
18042
|
+
--db-tabs-text-press: var(--db-color-action-default-text-press);
|
|
18043
|
+
--db-tabs-text-active: var(--db-color-text-primary);
|
|
18044
|
+
--db-tabs-text-disabled: var(--db-color-action-disabled-text);
|
|
18045
|
+
/* No v2 token holds the tab panel content text color yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
18046
|
+
--db-tabs-content-text: var(--db-color-text-primary);
|
|
18047
|
+
/* No v2 token holds the active-tab underline yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
18048
|
+
--db-tabs-indicator: var(--db-color-action-primary-background-default);
|
|
18049
|
+
/* No v2 token holds the list divider yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
18050
|
+
--db-tabs-border: var(--db-color-action-default-border-default);
|
|
18051
|
+
/* No v2 token holds the focus ring color yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
18052
|
+
--db-tabs-focus-ring: var(--db-color-action-default-border-focus);
|
|
17536
18053
|
}
|
|
17537
18054
|
|
|
18055
|
+
/* No v2 token holds the scrollbar thumb yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17538
18056
|
:where(:root), :where(.du-bois-light) {
|
|
17539
|
-
|
|
17540
|
-
|
|
17541
|
-
|
|
18057
|
+
--db-tabs-scrollbar-thumb: rgba(17, 23, 28, 0.2);
|
|
18058
|
+
--db-tabs-scrollbar-thumb-hover: rgba(17, 23, 28, 0.3);
|
|
18059
|
+
}
|
|
17542
18060
|
|
|
17543
|
-
/* Density */
|
|
17544
|
-
--db-snackbar-spacing-vertical: var(--db-space-3);
|
|
17545
|
-
--db-snackbar-spacing-horizontal: var(--db-space-4);
|
|
17546
|
-
--db-snackbar-close-button-spacing: var(--db-space-2);
|
|
17547
18061
|
|
|
17548
|
-
/* Color */
|
|
17549
|
-
/* No v1/v2 system token holds this theme-invariant white. TODO(FEINF-6505): adopt a v2 system token when one is added. */
|
|
17550
|
-
--db-snackbar-text: #ffffff;
|
|
17551
|
-
/* No v1/v2 system token holds these theme-invariant close-icon colors. TODO(FEINF-6505): adopt a v2 system token when one is added. */
|
|
17552
|
-
--db-snackbar-close-icon: #e8ecf0;
|
|
17553
|
-
--db-snackbar-close-icon-hover: #8acaff;
|
|
17554
|
-
--db-snackbar-close-icon-press: #bae1fc;
|
|
17555
|
-
}
|
|
17556
18062
|
|
|
17557
18063
|
:where(:root), :where(.du-bois-light) {
|
|
18064
|
+
/* Shape */
|
|
18065
|
+
--db-toolbar-border-radius: var(--db-shape-control);
|
|
18066
|
+
|
|
17558
18067
|
/* Color */
|
|
17559
|
-
|
|
17560
|
-
--db-
|
|
18068
|
+
--db-toolbar-surface: var(--db-surface-subtle);
|
|
18069
|
+
--db-toolbar-border: var(--db-border-base);
|
|
18070
|
+
--db-toolbar-separator-surface: var(--db-border-base);
|
|
18071
|
+
--db-toolbar-toggle-item-text: var(--db-text-base);
|
|
18072
|
+
/* No v2 token holds the toggle hover / press text yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
18073
|
+
--db-toolbar-toggle-item-text-hover: var(--db-color-action-default-text-hover);
|
|
18074
|
+
--db-toolbar-toggle-item-text-press: var(--db-color-action-default-text-press);
|
|
18075
|
+
--db-toolbar-shadow: var(--db-elevation-med);
|
|
17561
18076
|
|
|
17562
|
-
/*
|
|
17563
|
-
--db-
|
|
18077
|
+
/* Density */
|
|
18078
|
+
--db-toolbar-gap: var(--db-space-4);
|
|
18079
|
+
--db-toolbar-spacing: var(--db-space-2);
|
|
17564
18080
|
}
|
|
17565
18081
|
|
|
17566
18082
|
/* Tooltip renders an inverted surface (dark chip in light mode, light chip in dark mode), so it does
|
|
@@ -17587,38 +18103,9 @@ span.du-bois-light-typography-ellipsis-single-line {
|
|
|
17587
18103
|
/* v1 blue primitives, held as literals until a v2 link-on-tooltip semantic exists. */
|
|
17588
18104
|
--db-tooltip-link-text: #4299e0; /* blue500 */
|
|
17589
18105
|
--db-tooltip-link-text-hover: #8acaff; /* blue400 */
|
|
17590
|
-
--db-tooltip-link-text-
|
|
18106
|
+
--db-tooltip-link-text-active: #bae1fc; /* blue300 */
|
|
17591
18107
|
|
|
17592
18108
|
/* Elevation */
|
|
17593
18109
|
--db-tooltip-shadow: var(--db-elevation-med);
|
|
17594
18110
|
}
|
|
17595
18111
|
|
|
17596
|
-
/* Declared under the theme classes too (not just :root) so the var() chain re-resolves inside a
|
|
17597
|
-
* `.du-bois-dark` subtree instead of freezing at the light values. */
|
|
17598
|
-
:where(:root), :where(.du-bois-light) {
|
|
17599
|
-
/* Shape */
|
|
17600
|
-
--db-progress-border-radius: var(--db-shape-pill);
|
|
17601
|
-
|
|
17602
|
-
/* Color */
|
|
17603
|
-
--db-progress-track: var(--db-color-progress-track);
|
|
17604
|
-
--db-progress-fill: var(--db-color-progress-fill);
|
|
17605
|
-
|
|
17606
|
-
/* Density */
|
|
17607
|
-
--db-progress-size: var(--db-size-2);
|
|
17608
|
-
|
|
17609
|
-
/* Motion */
|
|
17610
|
-
/* No v2 motion token holds this duration. TODO(FEINF-6505): adopt a v2 motion token when one is added. */
|
|
17611
|
-
--db-progress-transition-duration: 300ms;
|
|
17612
|
-
}
|
|
17613
|
-
|
|
17614
|
-
:where(:root), :where(.du-bois-light) {
|
|
17615
|
-
/* Color */
|
|
17616
|
-
/* No v2 token holds tertiary action-text states yet. TODO(FEINF-6505): adopt a v2 token when one lands. */
|
|
17617
|
-
--db-overflow-trigger-text: var(--db-color-action-tertiary-text-default);
|
|
17618
|
-
--db-overflow-trigger-text-hover: var(--db-color-action-tertiary-text-hover);
|
|
17619
|
-
--db-overflow-trigger-text-press: var(--db-color-action-tertiary-text-press);
|
|
17620
|
-
|
|
17621
|
-
/* Density */
|
|
17622
|
-
--db-overflow-spacing: var(--db-space-2);
|
|
17623
|
-
--db-overflow-menu-spacing: var(--db-space-1);
|
|
17624
|
-
}
|