@dumiflex/wp-kit 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/CHANGELOG.md +92 -51
  2. package/LICENSE +674 -674
  3. package/README.md +73 -76
  4. package/package.json +78 -77
  5. package/src/Avatar.vue +83 -83
  6. package/src/Badge.vue +97 -97
  7. package/src/Banner.vue +118 -118
  8. package/src/BookmarkButton.vue +27 -27
  9. package/src/BundleMeta.vue +51 -51
  10. package/src/Button.vue +103 -103
  11. package/src/Card.vue +68 -68
  12. package/src/Checkbox.vue +109 -107
  13. package/src/Chip.vue +163 -97
  14. package/src/ChoiceCards.vue +133 -133
  15. package/src/CloseButton.vue +69 -69
  16. package/src/CodeBlock.vue +146 -119
  17. package/src/ColorField.vue +188 -206
  18. package/src/ColorPicker.vue +201 -201
  19. package/src/Combobox.vue +331 -334
  20. package/src/ConfirmDialog.vue +165 -163
  21. package/src/ConfirmModal.vue +147 -147
  22. package/src/ConstraintMatrixPreview.vue +708 -708
  23. package/src/ContextMenu.vue +386 -379
  24. package/src/CopyButton.vue +156 -156
  25. package/src/DataTable.vue +293 -292
  26. package/src/DatePicker.vue +234 -234
  27. package/src/DescriptionList.vue +73 -73
  28. package/src/DiffView.vue +68 -68
  29. package/src/Disclosure.vue +166 -166
  30. package/src/DragHandle.vue +49 -49
  31. package/src/Drawer.vue +131 -131
  32. package/src/DropZone.vue +196 -196
  33. package/src/DropdownMenu.vue +72 -72
  34. package/src/EmptyState.vue +111 -111
  35. package/src/Field.vue +28 -28
  36. package/src/HsvPicker.vue +208 -208
  37. package/src/Icon.vue +39 -39
  38. package/src/IconPicker.vue +209 -209
  39. package/src/ImageGrid.vue +127 -125
  40. package/src/InlineEdit.vue +183 -183
  41. package/src/Input.vue +99 -99
  42. package/src/Kbd.vue +56 -56
  43. package/src/Lightbox.vue +176 -173
  44. package/src/ListFilter.vue +85 -85
  45. package/src/ListRow.vue +204 -204
  46. package/src/LoadingMark.vue +217 -161
  47. package/src/Logo.vue +60 -60
  48. package/src/Modal.vue +78 -76
  49. package/src/ModalShell.vue +109 -107
  50. package/src/Pagination.vue +106 -106
  51. package/src/Popover.vue +180 -171
  52. package/src/PostCard.vue +210 -211
  53. package/src/ProgressBar.vue +90 -90
  54. package/src/RadioGroup.vue +177 -177
  55. package/src/RangeSlider.vue +183 -183
  56. package/src/RelativeDate.vue +35 -35
  57. package/src/ResizeHandle.vue +143 -143
  58. package/src/SearchInput.vue +192 -199
  59. package/src/Select.vue +644 -641
  60. package/src/Separator.vue +54 -54
  61. package/src/Skeleton.vue +98 -82
  62. package/src/Slider.vue +198 -198
  63. package/src/SortableList.vue +260 -260
  64. package/src/SplitPane.vue +68 -68
  65. package/src/StarButton.vue +40 -40
  66. package/src/Stepper.vue +141 -141
  67. package/src/SupportLinks.vue +93 -93
  68. package/src/TagInput.vue +297 -300
  69. package/src/Textarea.vue +57 -57
  70. package/src/Timeline.vue +92 -92
  71. package/src/ToastCard.vue +119 -119
  72. package/src/ToastHost.vue +40 -40
  73. package/src/Toggle.vue +36 -36
  74. package/src/TokenizedValue.vue +310 -310
  75. package/src/Toolbar.vue +110 -110
  76. package/src/VirtualList.vue +87 -87
  77. package/src/VisuallyHidden.vue +29 -29
  78. package/src/WpButton.vue +75 -75
  79. package/src/WpCheck.vue +104 -102
  80. package/src/WpIconButton.vue +107 -107
  81. package/src/WpImageZoom.vue +544 -544
  82. package/src/WpNumber.vue +178 -183
  83. package/src/WpSegmented.vue +175 -175
  84. package/src/WpSelect.vue +93 -89
  85. package/src/WpSwitch.vue +163 -163
  86. package/src/WpTabs.vue +188 -188
  87. package/src/_modal-motion.css +33 -33
  88. package/src/_skeleton.css +50 -50
  89. package/src/axis-color.ts +42 -42
  90. package/src/button.css +169 -169
  91. package/src/calendar.ts +59 -59
  92. package/src/clipboard.ts +50 -50
  93. package/src/colour-presets.ts +12 -12
  94. package/src/diff.ts +51 -51
  95. package/src/drop-zone.ts +41 -41
  96. package/src/field.css +50 -0
  97. package/src/flip.ts +237 -237
  98. package/src/floating-layer.ts +48 -0
  99. package/src/floating.ts +99 -99
  100. package/src/highlight.ts +199 -0
  101. package/src/hsv.ts +100 -100
  102. package/src/icon-catalog.ts +52 -52
  103. package/src/image-zoom.ts +93 -93
  104. package/src/kind-colour.ts +28 -0
  105. package/src/loading-mark-motion.ts +249 -0
  106. package/src/logo-paths.ts +21 -21
  107. package/src/matrix-axis.ts +91 -91
  108. package/src/pagination.ts +27 -27
  109. package/src/platform-keys.ts +29 -29
  110. package/src/rich-tokenize.ts +357 -357
  111. package/src/select-types.ts +32 -32
  112. package/src/slider-math.ts +45 -45
  113. package/src/sortable.ts +22 -22
  114. package/src/theme/fonts/OFL-Fraunces.txt +93 -93
  115. package/src/theme/fonts/OFL-JetBrainsMono.txt +93 -93
  116. package/src/theme/fonts/OFL-Manrope.txt +93 -93
  117. package/src/theme/looks.css +428 -428
  118. package/src/theme/palettes.css +254 -254
  119. package/src/theme/tokens.css +2896 -2894
  120. package/src/tokens.ts +56 -56
  121. package/src/tooltip.css +43 -43
  122. package/src/tooltip.ts +146 -146
  123. package/src/useDialogFocus.ts +73 -73
  124. package/src/useGrowableField.ts +357 -357
  125. package/src/useModalKeyShield.ts +116 -116
  126. package/src/useToast.ts +48 -48
  127. package/src/wp-logo.svg +14 -14
  128. package/src/ChipToggle.vue +0 -92
  129. package/src/KindChip.vue +0 -53
  130. package/src/RatingBadge.vue +0 -42
package/src/WpCheck.vue CHANGED
@@ -1,102 +1,104 @@
1
- <script setup lang="ts">
2
- /**
3
- * Shared checkbox box — the wildcard pool's per-option look (`.opt__check`
4
- * in OptionRow.vue), extracted so every checkmark box in the *embed/canvas*
5
- * tree reads the same.
6
- *
7
- * Why a component (not the global `.wp-check` class): the canvas bundle only
8
- * loads a hand-picked CSS set via `src/extension/settings.ts` — it does NOT
9
- * load the SPA's `manager/styles/tokens.css`, where global `.wp-check` lives.
10
- * A component's `<style scoped>` is compiled into the component's own chunk,
11
- * so it ships wherever the component renders — SPA *and* canvas. That's the
12
- * same reason `.opt__check` / `.row__check` / `.ex__check` are each scoped.
13
- *
14
- * Custom toggle BUTTONS (internal flag, seed-lock) stay as their own styled
15
- * buttons — this is only for true checkmark boxes.
16
- *
17
- * `aria-label` / `data-test` fall through to the single root span. Click /
18
- * Space / Enter toggle. `size="sm"` is the 12px box of the canvas rows' on/off
19
- * mark (modules, bundles, injector rows). A parent can tint the checked fill
20
- * with `--check-on` (a bundle header uses its bundle colour).
21
- */
22
- const props = withDefaults(
23
- defineProps<{
24
- /** Checked state — use with `v-model` or `:model-value` + `@update:model-value`. */
25
- modelValue?: boolean | undefined;
26
- disabled?: boolean | undefined;
27
- size?: "sm" | "md" | undefined;
28
- }>(),
29
- { modelValue: false, disabled: false, size: "md" },
30
- );
31
-
32
- const emit = defineEmits<{ "update:modelValue": [next: boolean] }>();
33
-
34
- function toggle(): void {
35
- if (props.disabled) return;
36
- emit("update:modelValue", !props.modelValue);
37
- }
38
- </script>
39
-
40
- <template>
41
- <span
42
- class="wp-check"
43
- :class="{ 'wp-check--sm': size === 'sm' }"
44
- role="checkbox"
45
- :aria-checked="modelValue === true"
46
- :aria-disabled="disabled || undefined"
47
- :tabindex="disabled ? -1 : 0"
48
- @click="toggle"
49
- @keydown.space.prevent="toggle"
50
- @keydown.enter.prevent="toggle"
51
- >
52
- <!-- 8×8 SVG tick inside the 14px box — identical to OptionRow's
53
- `.opt__check` so the canvas boxes match the wildcard options. -->
54
- <svg
55
- v-if="modelValue"
56
- width="8"
57
- height="8"
58
- viewBox="0 0 12 12"
59
- aria-hidden="true"
60
- >
61
- <path
62
- d="M2.5 6.5 L5 9 L9.5 3.5"
63
- fill="none"
64
- stroke="currentColor"
65
- stroke-width="2"
66
- stroke-linecap="round"
67
- stroke-linejoin="round"
68
- />
69
- </svg>
70
- </span>
71
- </template>
72
-
73
- <style scoped>
74
- /* Verbatim from OptionRow.vue `.opt__check`. Scoped so it ships into the
75
- * canvas bundle (no global tokens.css there). Vars resolve from the SPA's
76
- * tokens.css or the canvas theme.css — both define these. */
77
- .wp-check {
78
- width: 14px;
79
- height: 14px;
80
- border: 1.5px solid var(--wp-border-soft, var(--wp-border));
81
- border-radius: min(3px, var(--wp-radius-cap, 999px));
82
- display: inline-flex;
83
- align-items: center;
84
- justify-content: center;
85
- color: white;
86
- background: var(--wp-bg);
87
- flex-shrink: 0;
88
- cursor: pointer;
89
- }
90
- .wp-check svg { display: block; }
91
- .wp-check--sm { width: 12px; height: 12px; border-width: 1px; border-radius: min(2px, var(--wp-radius-cap, 999px)); }
92
- .wp-check--sm svg { width: 7px; height: 7px; }
93
- .wp-check:focus-visible { outline: none; box-shadow: var(--wp-focus-ring); }
94
- .wp-check[aria-checked="true"] {
95
- background: var(--check-on, var(--wp-accent));
96
- border-color: var(--check-on, var(--wp-accent));
97
- }
98
- .wp-check[aria-disabled="true"] {
99
- cursor: not-allowed;
100
- opacity: 0.45;
101
- }
102
- </style>
1
+ <script setup lang="ts">
2
+ /**
3
+ * Shared checkbox box — the wildcard pool's per-option look (`.opt__check`
4
+ * in OptionRow.vue), extracted so every checkmark box in the *embed/canvas*
5
+ * tree reads the same.
6
+ *
7
+ * Why a component (not the global `.wp-check` class): the canvas bundle only
8
+ * loads a hand-picked CSS set via `src/extension/settings.ts` — it does NOT
9
+ * load the SPA's `manager/styles/tokens.css`, where global `.wp-check` lives.
10
+ * A component's `<style scoped>` is compiled into the component's own chunk,
11
+ * so it ships wherever the component renders — SPA *and* canvas. That's the
12
+ * same reason `.opt__check` / `.row__check` / `.ex__check` are each scoped.
13
+ *
14
+ * Custom toggle BUTTONS (internal flag, seed-lock) stay as their own styled
15
+ * buttons — this is only for true checkmark boxes.
16
+ *
17
+ * `aria-label` / `data-test` fall through to the single root span. Click /
18
+ * Space / Enter toggle. `size="sm"` is the 12px box of the canvas rows' on/off
19
+ * mark (modules, bundles, injector rows). A parent can tint the checked fill
20
+ * with `--check-on` (a bundle header uses its bundle colour).
21
+ */
22
+ const props = withDefaults(
23
+ defineProps<{
24
+ /** Checked state — use with `v-model` or `:model-value` + `@update:model-value`. */
25
+ modelValue?: boolean | undefined;
26
+ disabled?: boolean | undefined;
27
+ size?: "sm" | "md" | undefined;
28
+ }>(),
29
+ { modelValue: false, disabled: false, size: "md" },
30
+ );
31
+
32
+ const emit = defineEmits<{ "update:modelValue": [next: boolean] }>();
33
+
34
+ function toggle(): void {
35
+ if (props.disabled) return;
36
+ emit("update:modelValue", !props.modelValue);
37
+ }
38
+ </script>
39
+
40
+ <template>
41
+ <!-- Focusable: tabindex is bound (-1 while disabled), which the rule can't see. -->
42
+ <!-- eslint-disable-next-line vuejs-accessibility/interactive-supports-focus -->
43
+ <span
44
+ class="wp-check"
45
+ :class="{ 'wp-check--sm': size === 'sm' }"
46
+ role="checkbox"
47
+ :aria-checked="modelValue === true"
48
+ :aria-disabled="disabled || undefined"
49
+ :tabindex="disabled ? -1 : 0"
50
+ @click="toggle"
51
+ @keydown.space.prevent="toggle"
52
+ @keydown.enter.prevent="toggle"
53
+ >
54
+ <!-- 8×8 SVG tick inside the 14px box — identical to OptionRow's
55
+ `.opt__check` so the canvas boxes match the wildcard options. -->
56
+ <svg
57
+ v-if="modelValue"
58
+ width="8"
59
+ height="8"
60
+ viewBox="0 0 12 12"
61
+ aria-hidden="true"
62
+ >
63
+ <path
64
+ d="M2.5 6.5 L5 9 L9.5 3.5"
65
+ fill="none"
66
+ stroke="currentColor"
67
+ stroke-width="2"
68
+ stroke-linecap="round"
69
+ stroke-linejoin="round"
70
+ />
71
+ </svg>
72
+ </span>
73
+ </template>
74
+
75
+ <style scoped>
76
+ /* Verbatim from OptionRow.vue `.opt__check`. Scoped so it ships into the
77
+ * canvas bundle (no global tokens.css there). Vars resolve from the SPA's
78
+ * tokens.css or the canvas theme.css — both define these. */
79
+ .wp-check {
80
+ width: 14px;
81
+ height: 14px;
82
+ border: 1.5px solid var(--wp-border-soft, var(--wp-border));
83
+ border-radius: min(3px, var(--wp-radius-cap, 999px));
84
+ display: inline-flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ color: white;
88
+ background: var(--wp-bg);
89
+ flex-shrink: 0;
90
+ cursor: pointer;
91
+ }
92
+ .wp-check svg { display: block; }
93
+ .wp-check--sm { width: 12px; height: 12px; border-width: 1px; border-radius: min(2px, var(--wp-radius-cap, 999px)); }
94
+ .wp-check--sm svg { width: 7px; height: 7px; }
95
+ .wp-check:focus-visible { outline: none; box-shadow: var(--wp-focus-ring); }
96
+ .wp-check[aria-checked="true"] {
97
+ background: var(--check-on, var(--wp-accent));
98
+ border-color: var(--check-on, var(--wp-accent));
99
+ }
100
+ .wp-check[aria-disabled="true"] {
101
+ cursor: not-allowed;
102
+ opacity: 0.45;
103
+ }
104
+ </style>
@@ -1,107 +1,107 @@
1
- <script setup lang="ts">
2
- /**
3
- * WpIconButton: the 20 px square icon button inside a canvas row (module,
4
- * injector, bundle and model rows, the Context toolbar). Rows are too tight
5
- * for the 24 px `WpButton size="sm"`, so this is the one smaller control on
6
- * the canvas, still at the 20 px hit-target floor.
7
- *
8
- * <WpIconButton icon="pi-trash" label="Remove module" tone="danger" @click="remove" />
9
- * <WpIconButton icon="pi-lock" label="Lock seed" tone="warn" :pressed="locked" />
10
- * <WpIconButton variant="bare" :icon="open ? 'pi-caret-down' : 'pi-caret-right'" label="Collapse" />
11
- *
12
- * - `tone` tints the icon on hover, and the whole button while `pressed`.
13
- * - `pressed` makes it a toggle (`aria-pressed`); `"mixed"` is the bundle
14
- * master toggle's "some children" state (dashed, half tint).
15
- * - `variant="bare"` is the row's fold caret: no box, drawn 14 px wide but
16
- * still 20 px to click.
17
- * - `label` names it for screen readers and is its tooltip, unless `hint`
18
- * gives a longer one.
19
- */
20
- import { vTooltip } from "./tooltip";
21
-
22
- withDefaults(defineProps<{
23
- /** PrimeIcons class, e.g. `pi-trash`. Leave it out to draw a short
24
- * glyph from the slot instead (the loop's Σ toggle). */
25
- icon?: string | undefined;
26
- label: string;
27
- /** A longer tooltip than the label. */
28
- hint?: string | undefined;
29
- tone?: "neutral" | "accent" | "warn" | "danger" | undefined;
30
- pressed?: boolean | "mixed" | undefined;
31
- variant?: "quiet" | "bare" | undefined;
32
- disabled?: boolean | undefined;
33
- }>(), { icon: undefined, hint: undefined, tone: "neutral", pressed: undefined, variant: "quiet" });
34
-
35
- const emit = defineEmits<{ click: [evt: MouseEvent] }>();
36
- </script>
37
-
38
- <template>
39
- <button
40
- v-tooltip="hint ?? label"
41
- type="button"
42
- class="wp-icon-btn"
43
- :data-tone="tone"
44
- :data-variant="variant"
45
- :aria-label="label"
46
- :aria-pressed="pressed"
47
- :disabled="disabled"
48
- @click="emit('click', $event)"
49
- >
50
- <i v-if="icon" class="pi" :class="icon" aria-hidden="true" />
51
- <span v-else class="wp-icon-btn__glyph" aria-hidden="true"><slot /></span>
52
- </button>
53
- </template>
54
-
55
- <style scoped>
56
- .wp-icon-btn {
57
- --tone: var(--wp-text);
58
- display: inline-flex;
59
- align-items: center;
60
- justify-content: center;
61
- flex: none;
62
- box-sizing: border-box;
63
- width: 20px;
64
- height: 20px;
65
- margin: 0;
66
- padding: 0;
67
- border: 1px solid var(--wp-border-strong);
68
- border-radius: var(--wp-radius);
69
- background: var(--wp-bg-2);
70
- color: var(--wp-text);
71
- font: 500 11px/1 var(--wp-font-sans);
72
- cursor: pointer;
73
- transition: background var(--wp-motion-quick), border-color var(--wp-motion-quick), color var(--wp-motion-quick);
74
- }
75
- .wp-icon-btn[data-tone="accent"] { --tone: var(--wp-accent); }
76
- .wp-icon-btn[data-tone="warn"] { --tone: var(--wp-warn); }
77
- .wp-icon-btn[data-tone="danger"] { --tone: var(--wp-danger); }
78
- .wp-icon-btn .pi { font-size: 11px; }
79
- .wp-icon-btn__glyph { font: 600 11px/1 var(--wp-font-mono); }
80
- .wp-icon-btn:hover:not(:disabled) { background: var(--wp-bg-4); color: var(--tone); }
81
- .wp-icon-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--wp-border-focus); }
82
- .wp-icon-btn:disabled { opacity: 0.45; cursor: not-allowed; }
83
- /* On: the tone tints the icon and washes the box, the same tint as hover. */
84
- .wp-icon-btn[aria-pressed="true"] {
85
- color: var(--tone);
86
- background: color-mix(in srgb, var(--tone) 14%, transparent);
87
- }
88
- .wp-icon-btn[aria-pressed="mixed"] {
89
- color: var(--tone);
90
- background: color-mix(in srgb, var(--tone) 7%, transparent);
91
- border-style: dashed;
92
- opacity: 0.75;
93
- }
94
- /* The fold caret: no box, 14 px of layout, 20 px of hit area. */
95
- .wp-icon-btn[data-variant="bare"] {
96
- width: 20px;
97
- margin-inline: -3px;
98
- border-color: transparent;
99
- background: none;
100
- color: var(--wp-text-dim);
101
- }
102
- .wp-icon-btn[data-variant="bare"] .pi { font-size: 10px; }
103
- .wp-icon-btn[data-variant="bare"]:hover:not(:disabled) { background: none; color: var(--wp-text); }
104
- @media (prefers-reduced-motion: reduce) {
105
- .wp-icon-btn { transition: none; }
106
- }
107
- </style>
1
+ <script setup lang="ts">
2
+ /**
3
+ * WpIconButton: the 20 px square icon button inside a canvas row (module,
4
+ * injector, bundle and model rows, the Context toolbar). Rows are too tight
5
+ * for the 24 px `WpButton size="sm"`, so this is the one smaller control on
6
+ * the canvas, still at the 20 px hit-target floor.
7
+ *
8
+ * <WpIconButton icon="pi-trash" label="Remove module" tone="danger" @click="remove" />
9
+ * <WpIconButton icon="pi-lock" label="Lock seed" tone="warn" :pressed="locked" />
10
+ * <WpIconButton variant="bare" :icon="open ? 'pi-caret-down' : 'pi-caret-right'" label="Collapse" />
11
+ *
12
+ * - `tone` tints the icon on hover, and the whole button while `pressed`.
13
+ * - `pressed` makes it a toggle (`aria-pressed`); `"mixed"` is the bundle
14
+ * master toggle's "some children" state (dashed, half tint).
15
+ * - `variant="bare"` is the row's fold caret: no box, drawn 14 px wide but
16
+ * still 20 px to click.
17
+ * - `label` names it for screen readers and is its tooltip, unless `hint`
18
+ * gives a longer one.
19
+ */
20
+ import { vTooltip } from "./tooltip";
21
+
22
+ withDefaults(defineProps<{
23
+ /** PrimeIcons class, e.g. `pi-trash`. Leave it out to draw a short
24
+ * glyph from the slot instead (the loop's Σ toggle). */
25
+ icon?: string | undefined;
26
+ label: string;
27
+ /** A longer tooltip than the label. */
28
+ hint?: string | undefined;
29
+ tone?: "neutral" | "accent" | "warn" | "danger" | undefined;
30
+ pressed?: boolean | "mixed" | undefined;
31
+ variant?: "quiet" | "bare" | undefined;
32
+ disabled?: boolean | undefined;
33
+ }>(), { icon: undefined, hint: undefined, tone: "neutral", pressed: undefined, variant: "quiet" });
34
+
35
+ const emit = defineEmits<{ click: [evt: MouseEvent] }>();
36
+ </script>
37
+
38
+ <template>
39
+ <button
40
+ v-tooltip="hint ?? label"
41
+ type="button"
42
+ class="wp-icon-btn"
43
+ :data-tone="tone"
44
+ :data-variant="variant"
45
+ :aria-label="label"
46
+ :aria-pressed="pressed"
47
+ :disabled="disabled"
48
+ @click="emit('click', $event)"
49
+ >
50
+ <i v-if="icon" class="pi" :class="icon" aria-hidden="true" />
51
+ <span v-else class="wp-icon-btn__glyph" aria-hidden="true"><slot /></span>
52
+ </button>
53
+ </template>
54
+
55
+ <style scoped>
56
+ .wp-icon-btn {
57
+ --tone: var(--wp-text);
58
+ display: inline-flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ flex: none;
62
+ box-sizing: border-box;
63
+ width: 20px;
64
+ height: 20px;
65
+ margin: 0;
66
+ padding: 0;
67
+ border: 1px solid var(--wp-border-strong);
68
+ border-radius: var(--wp-radius);
69
+ background: var(--wp-bg-2);
70
+ color: var(--wp-text);
71
+ font: 500 11px/1 var(--wp-font-sans);
72
+ cursor: pointer;
73
+ transition: background var(--wp-motion-quick), border-color var(--wp-motion-quick), color var(--wp-motion-quick);
74
+ }
75
+ .wp-icon-btn[data-tone="accent"] { --tone: var(--wp-accent); }
76
+ .wp-icon-btn[data-tone="warn"] { --tone: var(--wp-warn); }
77
+ .wp-icon-btn[data-tone="danger"] { --tone: var(--wp-danger); }
78
+ .wp-icon-btn .pi { font-size: 11px; }
79
+ .wp-icon-btn__glyph { font: 600 11px/1 var(--wp-font-mono); }
80
+ .wp-icon-btn:hover:not(:disabled) { background: var(--wp-bg-4); color: var(--tone); }
81
+ .wp-icon-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--wp-border-focus); }
82
+ .wp-icon-btn:disabled { opacity: 0.45; cursor: not-allowed; }
83
+ /* On: the tone tints the icon and washes the box, the same tint as hover. */
84
+ .wp-icon-btn[aria-pressed="true"] {
85
+ color: var(--tone);
86
+ background: color-mix(in srgb, var(--tone) 14%, transparent);
87
+ }
88
+ .wp-icon-btn[aria-pressed="mixed"] {
89
+ color: var(--tone);
90
+ background: color-mix(in srgb, var(--tone) 7%, transparent);
91
+ border-style: dashed;
92
+ opacity: 0.75;
93
+ }
94
+ /* The fold caret: no box, 14 px of layout, 20 px of hit area. */
95
+ .wp-icon-btn[data-variant="bare"] {
96
+ width: 20px;
97
+ margin-inline: -3px;
98
+ border-color: transparent;
99
+ background: none;
100
+ color: var(--wp-text-dim);
101
+ }
102
+ .wp-icon-btn[data-variant="bare"] .pi { font-size: 10px; }
103
+ .wp-icon-btn[data-variant="bare"]:hover:not(:disabled) { background: none; color: var(--wp-text); }
104
+ @media (prefers-reduced-motion: reduce) {
105
+ .wp-icon-btn { transition: none; }
106
+ }
107
+ </style>