@eifi1/ui-kit 0.48.1 → 0.49.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 (318) hide show
  1. package/README.md +28 -13
  2. package/dist/admin/admin-action-confirm.js +1 -1
  3. package/dist/admin/admin-action-confirm.js.map +1 -1
  4. package/dist/admin/invitations-panel.js +5 -1
  5. package/dist/admin/invitations-panel.js.map +1 -1
  6. package/dist/admin/user-roster.d.ts +11 -5
  7. package/dist/admin/user-roster.js +15 -4
  8. package/dist/admin/user-roster.js.map +1 -1
  9. package/dist/auth/accept-invitation.js +2 -2
  10. package/dist/auth/accept-invitation.js.map +1 -1
  11. package/dist/auth/not-found-page.js +1 -1
  12. package/dist/auth/not-found-page.js.map +1 -1
  13. package/dist/auth/reset-password-form.js +2 -2
  14. package/dist/auth/reset-password-form.js.map +1 -1
  15. package/dist/auth/verify-email.js +2 -2
  16. package/dist/auth/verify-email.js.map +1 -1
  17. package/dist/billing/plan-card.js +2 -2
  18. package/dist/billing/plan-card.js.map +1 -1
  19. package/dist/components/breadcrumbs.d.ts +19 -1
  20. package/dist/components/breadcrumbs.js +11 -4
  21. package/dist/components/breadcrumbs.js.map +1 -1
  22. package/dist/components/button-look.d.ts +37 -7
  23. package/dist/components/button-look.js +33 -6
  24. package/dist/components/button-look.js.map +1 -1
  25. package/dist/components/button.d.ts +4 -1
  26. package/dist/components/button.js +2 -2
  27. package/dist/components/button.js.map +1 -1
  28. package/dist/components/calendar-heatmap.js +2 -1
  29. package/dist/components/calendar-heatmap.js.map +1 -1
  30. package/dist/components/chart-edge.d.ts +10 -0
  31. package/dist/components/chart-edge.js +57 -0
  32. package/dist/components/chart-edge.js.map +1 -0
  33. package/dist/components/chart.js +2 -1
  34. package/dist/components/chart.js.map +1 -1
  35. package/dist/components/chip.d.ts +8 -1
  36. package/dist/components/chip.js +4 -1
  37. package/dist/components/chip.js.map +1 -1
  38. package/dist/components/confirm-context.d.ts +5 -0
  39. package/dist/components/confirm-context.js +7 -0
  40. package/dist/components/confirm-context.js.map +1 -0
  41. package/dist/components/confirm-dialog.js +3 -3
  42. package/dist/components/confirm-dialog.js.map +1 -1
  43. package/dist/components/danger-confirm.d.ts +2 -2
  44. package/dist/components/danger-confirm.js +1 -1
  45. package/dist/components/danger-confirm.js.map +1 -1
  46. package/dist/components/data-table-fit.d.ts +8 -1
  47. package/dist/components/data-table-fit.js +28 -4
  48. package/dist/components/data-table-fit.js.map +1 -1
  49. package/dist/components/data-table-groups.d.ts +3 -1
  50. package/dist/components/data-table-groups.js +11 -5
  51. package/dist/components/data-table-groups.js.map +1 -1
  52. package/dist/components/data-table-head.d.ts +8 -1
  53. package/dist/components/data-table-head.js +11 -3
  54. package/dist/components/data-table-head.js.map +1 -1
  55. package/dist/components/data-table-leading-row.d.ts +3 -1
  56. package/dist/components/data-table-leading-row.js +2 -1
  57. package/dist/components/data-table-leading-row.js.map +1 -1
  58. package/dist/components/data-table-mobile.d.ts +48 -2
  59. package/dist/components/data-table-mobile.js +87 -10
  60. package/dist/components/data-table-mobile.js.map +1 -1
  61. package/dist/components/data-table-row-actions.d.ts +2 -1
  62. package/dist/components/data-table-row-actions.js +9 -2
  63. package/dist/components/data-table-row-actions.js.map +1 -1
  64. package/dist/components/data-table-row.d.ts +84 -0
  65. package/dist/components/data-table-row.js +261 -0
  66. package/dist/components/data-table-row.js.map +1 -0
  67. package/dist/components/data-table-selection.d.ts +3 -0
  68. package/dist/components/data-table-selection.js +12 -1
  69. package/dist/components/data-table-selection.js.map +1 -1
  70. package/dist/components/data-table-virtual.d.ts +98 -0
  71. package/dist/components/data-table-virtual.js +369 -0
  72. package/dist/components/data-table-virtual.js.map +1 -0
  73. package/dist/components/data-table.d.ts +74 -2
  74. package/dist/components/data-table.js +241 -221
  75. package/dist/components/data-table.js.map +1 -1
  76. package/dist/components/error-boundary.js +2 -2
  77. package/dist/components/error-boundary.js.map +1 -1
  78. package/dist/components/floating-panel.d.ts +36 -13
  79. package/dist/components/floating-panel.js +27 -7
  80. package/dist/components/floating-panel.js.map +1 -1
  81. package/dist/components/form-actions.d.ts +1 -1
  82. package/dist/components/form-actions.js +1 -1
  83. package/dist/components/form-actions.js.map +1 -1
  84. package/dist/components/icon-button.d.ts +11 -0
  85. package/dist/components/icon-button.js +7 -5
  86. package/dist/components/icon-button.js.map +1 -1
  87. package/dist/components/nav-pills.d.ts +8 -1
  88. package/dist/components/nav-pills.js +61 -38
  89. package/dist/components/nav-pills.js.map +1 -1
  90. package/dist/components/page-header-context.d.ts +8 -0
  91. package/dist/components/page-header-context.js +7 -0
  92. package/dist/components/page-header-context.js.map +1 -0
  93. package/dist/components/page-header.d.ts +14 -2
  94. package/dist/components/page-header.js +10 -1
  95. package/dist/components/page-header.js.map +1 -1
  96. package/dist/components/pie-chart.js +2 -1
  97. package/dist/components/pie-chart.js.map +1 -1
  98. package/dist/components/progress-bar.js +5 -4
  99. package/dist/components/progress-bar.js.map +1 -1
  100. package/dist/components/reauth-dialog.js +1 -1
  101. package/dist/components/reauth-dialog.js.map +1 -1
  102. package/dist/components/row-actions-labels.js +3 -1
  103. package/dist/components/row-actions-labels.js.map +1 -1
  104. package/dist/components/row-actions.d.ts +43 -9
  105. package/dist/components/row-actions.js +78 -15
  106. package/dist/components/row-actions.js.map +1 -1
  107. package/dist/components/section-nav.d.ts +37 -0
  108. package/dist/components/section-nav.js +33 -0
  109. package/dist/components/section-nav.js.map +1 -0
  110. package/dist/components/series-chart.js +8 -3
  111. package/dist/components/series-chart.js.map +1 -1
  112. package/dist/components/share-card.js +1 -1
  113. package/dist/components/share-card.js.map +1 -1
  114. package/dist/components/signature-pad.js +1 -1
  115. package/dist/components/signature-pad.js.map +1 -1
  116. package/dist/components/sparkline.js +2 -1
  117. package/dist/components/sparkline.js.map +1 -1
  118. package/dist/components/stat-tile.js +14 -7
  119. package/dist/components/stat-tile.js.map +1 -1
  120. package/dist/components/status-dot.d.ts +5 -1
  121. package/dist/components/status-dot.js +4 -1
  122. package/dist/components/status-dot.js.map +1 -1
  123. package/dist/components/tooltip.js +1 -1
  124. package/dist/components/tooltip.js.map +1 -1
  125. package/dist/components/translation-review-editor.js +2 -2
  126. package/dist/components/translation-review-editor.js.map +1 -1
  127. package/dist/components/translation-review.js +2 -2
  128. package/dist/components/translation-review.js.map +1 -1
  129. package/dist/components/treemap.d.ts +5 -2
  130. package/dist/components/treemap.js +26 -6
  131. package/dist/components/treemap.js.map +1 -1
  132. package/dist/components/use-table-state.js +37 -6
  133. package/dist/components/use-table-state.js.map +1 -1
  134. package/dist/data-table.d.ts +1 -0
  135. package/dist/data-table.js.map +1 -1
  136. package/dist/demo/demo-banner.js +1 -1
  137. package/dist/demo/demo-banner.js.map +1 -1
  138. package/dist/demo/demo-ended.js +1 -1
  139. package/dist/demo/demo-ended.js.map +1 -1
  140. package/dist/demo/demo-start.js +1 -1
  141. package/dist/demo/demo-start.js.map +1 -1
  142. package/dist/eslint/index.js +1 -1
  143. package/dist/feedback/feedback-inbox.js +1 -1
  144. package/dist/feedback/feedback-inbox.js.map +1 -1
  145. package/dist/hooks/use-anchored-panel.js +2 -1
  146. package/dist/hooks/use-anchored-panel.js.map +1 -1
  147. package/dist/hooks/use-dismiss.d.ts +9 -1
  148. package/dist/hooks/use-dismiss.js +25 -5
  149. package/dist/hooks/use-dismiss.js.map +1 -1
  150. package/dist/hooks/use-document-title.d.ts +14 -0
  151. package/dist/hooks/use-document-title.js +22 -0
  152. package/dist/hooks/use-document-title.js.map +1 -0
  153. package/dist/i18n/german.js +6 -2
  154. package/dist/i18n/german.js.map +1 -1
  155. package/dist/i18n/kit-labels.d.ts +31 -1
  156. package/dist/i18n/kit-labels.js +43 -2
  157. package/dist/i18n/kit-labels.js.map +1 -1
  158. package/dist/i18n/locales/en.js +6 -2
  159. package/dist/i18n/locales/en.js.map +2 -2
  160. package/dist/i18n/locales/es.js +6 -2
  161. package/dist/i18n/locales/es.js.map +1 -1
  162. package/dist/i18n/locales/fr.js +6 -2
  163. package/dist/i18n/locales/fr.js.map +1 -1
  164. package/dist/i18n/locales/hu.js +6 -2
  165. package/dist/i18n/locales/hu.js.map +1 -1
  166. package/dist/i18n/locales/it.js +6 -2
  167. package/dist/i18n/locales/it.js.map +1 -1
  168. package/dist/i18n/locales/zh.js +6 -2
  169. package/dist/i18n/locales/zh.js.map +1 -1
  170. package/dist/i18n/review.js +2 -0
  171. package/dist/i18n/review.js.map +1 -1
  172. package/dist/i18n/shared-labels.js +1 -0
  173. package/dist/i18n/shared-labels.js.map +1 -1
  174. package/dist/index.d.ts +8 -1
  175. package/dist/index.js +11 -0
  176. package/dist/index.js.map +1 -1
  177. package/dist/landing/landing-actions.js +2 -2
  178. package/dist/landing/landing-actions.js.map +1 -1
  179. package/dist/landing/public-header.js +2 -2
  180. package/dist/landing/public-header.js.map +1 -1
  181. package/dist/lib/clipboard-minus.d.ts +27 -0
  182. package/dist/lib/clipboard-minus.js +63 -0
  183. package/dist/lib/clipboard-minus.js.map +1 -0
  184. package/dist/lib/document-title.d.ts +17 -0
  185. package/dist/lib/document-title.js +29 -0
  186. package/dist/lib/document-title.js.map +1 -0
  187. package/dist/lib/float-clearance.js +8 -2
  188. package/dist/lib/float-clearance.js.map +1 -1
  189. package/dist/lib/format.d.ts +35 -10
  190. package/dist/lib/format.js +55 -11
  191. package/dist/lib/format.js.map +1 -1
  192. package/dist/lib/minus.d.ts +22 -0
  193. package/dist/lib/minus.js +14 -0
  194. package/dist/lib/minus.js.map +1 -0
  195. package/dist/lib/status-tone.d.ts +30 -0
  196. package/dist/lib/status-tone.js +17 -0
  197. package/dist/lib/status-tone.js.map +1 -0
  198. package/dist/settings/settings-layout.js +3 -2
  199. package/dist/settings/settings-layout.js.map +1 -1
  200. package/dist/shell/account-menu-language.d.ts +1 -1
  201. package/dist/shell/account-menu-language.js +9 -1
  202. package/dist/shell/account-menu-language.js.map +1 -1
  203. package/dist/shell/app-shell-labels.js +2 -1
  204. package/dist/shell/app-shell-labels.js.map +1 -1
  205. package/dist/shell/app-shell.d.ts +58 -16
  206. package/dist/shell/app-shell.js +158 -44
  207. package/dist/shell/app-shell.js.map +1 -1
  208. package/dist/shell/language-code.d.ts +3 -0
  209. package/dist/shell/language-code.js +8 -0
  210. package/dist/shell/language-code.js.map +1 -0
  211. package/dist/shell/topbar-controls.d.ts +14 -6
  212. package/dist/shell/topbar-controls.js +14 -17
  213. package/dist/shell/topbar-controls.js.map +1 -1
  214. package/dist/testing/css-variables.generated.d.ts +1 -1
  215. package/dist/testing/css-variables.generated.js +1 -1
  216. package/dist/testing/css-variables.generated.js.map +1 -1
  217. package/dist/theme/chart-palette.d.ts +82 -15
  218. package/dist/theme/chart-palette.js +51 -24
  219. package/dist/theme/chart-palette.js.map +1 -1
  220. package/dist/theme/palette-presets.d.ts +9 -0
  221. package/dist/theme/palette-presets.js +77 -62
  222. package/dist/theme/palette-presets.js.map +1 -1
  223. package/dist/tour/tour.js +1 -1
  224. package/dist/tour/tour.js.map +1 -1
  225. package/dist/wizard/stepper-nav.d.ts +1 -1
  226. package/dist/wizard/stepper-nav.js +3 -3
  227. package/dist/wizard/stepper-nav.js.map +1 -1
  228. package/package.json +1 -1
  229. package/src/admin/admin-action-confirm.tsx +1 -1
  230. package/src/admin/invitations-panel.tsx +7 -3
  231. package/src/admin/user-roster.tsx +23 -6
  232. package/src/auth/accept-invitation.tsx +3 -3
  233. package/src/auth/not-found-page.tsx +1 -1
  234. package/src/auth/reset-password-form.tsx +3 -3
  235. package/src/auth/verify-email.tsx +3 -3
  236. package/src/billing/plan-card.tsx +2 -2
  237. package/src/components/breadcrumbs.tsx +32 -4
  238. package/src/components/button-look.ts +86 -15
  239. package/src/components/button.tsx +6 -3
  240. package/src/components/calendar-heatmap.tsx +2 -1
  241. package/src/components/chart-edge.ts +73 -0
  242. package/src/components/chart.tsx +3 -1
  243. package/src/components/chip.tsx +10 -1
  244. package/src/components/confirm-context.ts +7 -0
  245. package/src/components/confirm-dialog.tsx +3 -3
  246. package/src/components/danger-confirm.tsx +3 -3
  247. package/src/components/data-table-fit.ts +58 -8
  248. package/src/components/data-table-groups.tsx +15 -4
  249. package/src/components/data-table-head.tsx +25 -2
  250. package/src/components/data-table-leading-row.tsx +4 -1
  251. package/src/components/data-table-mobile.tsx +162 -11
  252. package/src/components/data-table-row-actions.tsx +12 -3
  253. package/src/components/data-table-row.tsx +485 -0
  254. package/src/components/data-table-selection.ts +17 -1
  255. package/src/components/data-table-virtual.ts +547 -0
  256. package/src/components/data-table.tsx +367 -326
  257. package/src/components/error-boundary.tsx +2 -2
  258. package/src/components/floating-panel.tsx +67 -16
  259. package/src/components/form-actions.tsx +2 -2
  260. package/src/components/icon-button.tsx +21 -8
  261. package/src/components/nav-pills.tsx +29 -2
  262. package/src/components/page-header-context.ts +8 -0
  263. package/src/components/page-header.tsx +34 -2
  264. package/src/components/pie-chart.tsx +2 -1
  265. package/src/components/progress-bar.tsx +6 -3
  266. package/src/components/reauth-dialog.tsx +1 -1
  267. package/src/components/row-actions-labels.ts +2 -0
  268. package/src/components/row-actions.tsx +154 -33
  269. package/src/components/section-nav.tsx +65 -0
  270. package/src/components/series-chart.tsx +12 -3
  271. package/src/components/share-card.tsx +1 -1
  272. package/src/components/signature-pad.tsx +1 -1
  273. package/src/components/sparkline.tsx +2 -1
  274. package/src/components/stat-tile.tsx +19 -7
  275. package/src/components/status-dot.tsx +7 -1
  276. package/src/components/tooltip.tsx +3 -1
  277. package/src/components/translation-review-editor.tsx +2 -2
  278. package/src/components/translation-review.tsx +2 -2
  279. package/src/components/treemap.tsx +34 -8
  280. package/src/components/use-table-state.ts +63 -8
  281. package/src/data-table.ts +5 -3
  282. package/src/demo/demo-banner.tsx +1 -1
  283. package/src/demo/demo-ended.tsx +1 -1
  284. package/src/demo/demo-start.tsx +1 -1
  285. package/src/feedback/feedback-inbox.tsx +1 -1
  286. package/src/hooks/use-anchored-panel.ts +9 -1
  287. package/src/hooks/use-dismiss.ts +43 -4
  288. package/src/hooks/use-document-title.ts +31 -0
  289. package/src/i18n/german.ts +4 -0
  290. package/src/i18n/kit-labels.tsx +76 -1
  291. package/src/i18n/locales/es.ts +4 -0
  292. package/src/i18n/locales/fr.ts +4 -0
  293. package/src/i18n/locales/hu.ts +4 -0
  294. package/src/i18n/locales/it.ts +4 -0
  295. package/src/i18n/locales/zh.ts +4 -0
  296. package/src/i18n/review.ts +2 -0
  297. package/src/i18n/shared-labels.ts +1 -0
  298. package/src/index.ts +13 -0
  299. package/src/landing/landing-actions.tsx +2 -2
  300. package/src/landing/public-header.tsx +2 -2
  301. package/src/lib/clipboard-minus.ts +94 -0
  302. package/src/lib/document-title.ts +41 -0
  303. package/src/lib/float-clearance.ts +19 -3
  304. package/src/lib/format.ts +115 -30
  305. package/src/lib/minus.ts +40 -0
  306. package/src/lib/status-tone.ts +43 -0
  307. package/src/settings/settings-layout.tsx +3 -2
  308. package/src/shell/account-menu-language.tsx +14 -2
  309. package/src/shell/app-shell-labels.ts +1 -0
  310. package/src/shell/app-shell.tsx +298 -69
  311. package/src/shell/language-code.ts +5 -0
  312. package/src/shell/topbar-controls.tsx +35 -15
  313. package/src/testing/css-variables.generated.ts +6 -6
  314. package/src/theme/chart-palette.ts +102 -20
  315. package/src/theme/palette-presets.ts +121 -84
  316. package/src/tour/tour.tsx +1 -1
  317. package/src/wizard/stepper-nav.tsx +4 -4
  318. package/tokens.css +28 -18
@@ -119,7 +119,7 @@ function ResendButton({
119
119
  }: {
120
120
  state: ReturnType<typeof useResend>;
121
121
  labels: VerifyEmailLabels;
122
- variant: "secondary" | "brand";
122
+ variant: "secondary" | "accent";
123
123
  }) {
124
124
  return (
125
125
  <Button
@@ -269,7 +269,7 @@ export function VerifyEmailStatus({
269
269
  const href = continueHref ?? (signedIn ? "/" : "/login");
270
270
  // `replace`: the token is spent, so Back must not land on this page again (keksdose F1).
271
271
  const continueButton = (
272
- <Button href={href} replace variant={outcome === "verified" ? "brand" : "secondary"}>
272
+ <Button href={href} replace variant={outcome === "verified" ? "accent" : "secondary"}>
273
273
  {labels.continue}
274
274
  </Button>
275
275
  );
@@ -304,7 +304,7 @@ export function VerifyEmailStatus({
304
304
  hint={hint}
305
305
  action={
306
306
  <>
307
- {canResend && <ResendButton state={resend} labels={labels} variant="brand" />}
307
+ {canResend && <ResendButton state={resend} labels={labels} variant="accent" />}
308
308
  {continueButton}
309
309
  </>
310
310
  }
@@ -471,7 +471,7 @@ export function PlanPicker({
471
471
  <div className="flex justify-end">
472
472
  <Button
473
473
  type="button"
474
- variant="primary"
474
+ variant="default"
475
475
  className="max-sm:w-full"
476
476
  disabledReason={blocked}
477
477
  pending={pending}
@@ -538,7 +538,7 @@ export function GrantWarningConfirm({ open, onOpenChange, onConfirm, labels: lab
538
538
  {common.back}
539
539
  </Button>
540
540
  <Button
541
- variant="primary"
541
+ variant="default"
542
542
  onClick={() => {
543
543
  onConfirm();
544
544
  onOpenChange(false);
@@ -1,4 +1,4 @@
1
- import { Fragment, useEffect, useRef, useState } from "react";
1
+ import { Fragment, useContext, useEffect, useRef, useState } from "react";
2
2
  import type { ComponentPropsWithRef, ReactElement, ReactNode } from "react";
3
3
  import { ChevronRight, MoreHorizontal } from "lucide-react";
4
4
  import { cn } from "../lib/cn";
@@ -6,6 +6,7 @@ import { FOCUS_RING } from "./focus-ring";
6
6
  import { useKitLabels, useKitLink, type LabelOverride } from "../i18n/kit-labels";
7
7
  import { pickLinkRenderer, RenderedKitLink } from "./text-link";
8
8
  import { DEFAULT_BREADCRUMBS_LABELS } from "./breadcrumbs-labels";
9
+ import { PageHeaderTrailContext } from "./page-header-context";
9
10
 
10
11
  export interface BreadcrumbsLabels {
11
12
  /** The `nav` landmark's name — what a screen reader lists it as. */
@@ -24,6 +25,12 @@ export interface BreadcrumbItem {
24
25
  href?: string;
25
26
  /** A stable React key, when `label` is not a string. */
26
27
  key?: string;
28
+ /**
29
+ * The app's home entry (0.49 KIT-9). Default: an entry whose `href` is `"/"`. No trail
30
+ * is drawn when only home entries are left — inside a `PageHeader`, or wherever the
31
+ * current entry is hidden (`hideCurrent`): "Home" above a page's title says nothing.
32
+ */
33
+ home?: boolean;
27
34
  }
28
35
 
29
36
  /** What {@link BreadcrumbsProps.renderLink} is handed. Spread it onto your router's
@@ -57,6 +64,18 @@ export interface BreadcrumbsProps extends Omit<ComponentPropsWithRef<"nav">, "ch
57
64
  keepEnd?: number;
58
65
  /** Overrides the {@link UiKitProvider}'s `breadcrumbs` labels. */
59
66
  labels?: LabelOverride<BreadcrumbsLabels>;
67
+ /**
68
+ * Leave out the last entry, the current page (0.49 KIT-9). The entry before it stays a
69
+ * link, and no entry carries `aria-current`: the page's title names where you are.
70
+ *
71
+ * Default `true` inside a `PageHeader`'s `breadcrumbs` (the title is right below, so
72
+ * the trail would repeat it), `false` elsewhere. With the current entry hidden — and
73
+ * inside a `PageHeader` either way — the trail is drawn only when at least one entry
74
+ * that is not home ({@link BreadcrumbItem.home}) is left, so a trail drawn by the
75
+ * layout above the page shows no lone "Home" link either. `false` keeps the current
76
+ * entry as text with `aria-current="page"`.
77
+ */
78
+ hideCurrent?: boolean;
60
79
  }
61
80
 
62
81
  /**
@@ -69,16 +88,18 @@ export interface BreadcrumbsProps extends Omit<ComponentPropsWithRef<"nav">, "ch
69
88
  * the server's first paint is already right.
70
89
  */
71
90
  export function Breadcrumbs({
72
- items,
91
+ items: allItems,
73
92
  renderLink,
74
93
  separator,
75
94
  collapse = true,
76
95
  keepEnd = 2,
77
96
  labels: labelsProp,
97
+ hideCurrent,
78
98
  className,
79
99
  "aria-label": ariaLabel,
80
100
  ...rest
81
101
  }: BreadcrumbsProps) {
102
+ const host = useContext(PageHeaderTrailContext);
82
103
  const labels = useKitLabels("breadcrumbs", DEFAULT_BREADCRUMBS_LABELS, labelsProp);
83
104
  const kitLink = useKitLink();
84
105
  const [expanded, setExpanded] = useState(false);
@@ -92,7 +113,13 @@ export function Breadcrumbs({
92
113
  const li = revealedRef.current;
93
114
  (li?.querySelector<HTMLElement>("a[href]") ?? li)?.focus();
94
115
  }, [expanded]);
95
- if (items.length === 0) return null;
116
+ const hides = hideCurrent ?? host?.titled ?? false;
117
+ const shown = hides ? allItems.slice(0, -1) : allItems;
118
+ if (shown.length === 0) return null;
119
+ // A trail of home entries alone repeats nothing worth a line: in a PageHeader, and
120
+ // wherever the current entry is hidden (a layout's trail above the page's title).
121
+ if ((host || hides) && !shown.some((item) => !(item.home ?? item.href === "/"))) return null;
122
+ const items = shown;
96
123
 
97
124
  const end = Math.max(1, keepEnd);
98
125
  // Crumbs [1, firstKept) are the collapsible middle. Collapsing a single crumb into a
@@ -116,7 +143,8 @@ export function Breadcrumbs({
116
143
  <nav {...rest} aria-label={ariaLabel ?? labels.label} className={cn("min-w-0 text-sm", className)}>
117
144
  <ol className="m-0 flex min-w-0 list-none flex-wrap items-center gap-x-1.5 gap-y-1 p-0 text-muted">
118
145
  {items.map((item, i) => {
119
- const last = i === items.length - 1;
146
+ // With the current entry hidden, the last one shown is a parent: a link.
147
+ const last = !hides && i === items.length - 1;
120
148
  const key = item.key ?? (typeof item.label === "string" ? `${i}-${item.label}` : String(i));
121
149
  let content: ReactNode;
122
150
  if (last) {
@@ -13,7 +13,75 @@ import type { KitLinkComponent, KitLinkProps } from "../i18n/kit-labels";
13
13
  * The other exports are the two buttons' shared parts (`@internal`).
14
14
  */
15
15
 
16
- export type ButtonVariant = "primary" | "secondary" | "ghost" | "danger" | "brand" | "link";
16
+ /**
17
+ * A button's look.
18
+ *
19
+ * - `default`: the quiet action — a warm filled chip with a hairline border. What a
20
+ * Button with no `variant` draws.
21
+ * - `accent`: the strong one, solid `--brand` with `--brand-contrast` text — the one
22
+ * call to action a view leads with. "Accent" is the button's role here, painted in
23
+ * `--brand`; it is not the palette's second anchor colour, also called `accent`
24
+ * (theme/palette-derive.ts), which no button paints.
25
+ * - `secondary`: an outline. `ghost`: text or glyph only. `danger`: solid `--danger`,
26
+ * for an action that destroys something. `link`: a text link that acts (a `<button>`).
27
+ * - `primary` and `brand` are **deprecated** aliases of `default` and `accent` (0.49,
28
+ * same look; a development build warns once per name). They are removed in 0.51, and
29
+ * `primary` will not come back with another meaning.
30
+ */
31
+ export type ButtonVariant =
32
+ | "default"
33
+ | "accent"
34
+ | "secondary"
35
+ | "ghost"
36
+ | "danger"
37
+ | "link"
38
+ /** @deprecated 0.49 — use `default` (same look); removed in 0.51. */
39
+ | "primary"
40
+ /** @deprecated 0.49 — use `accent` (same look); removed in 0.51. */
41
+ | "brand";
42
+
43
+ /** @internal A {@link ButtonVariant} without the deprecated aliases. */
44
+ export type CanonicalButtonVariant = Exclude<ButtonVariant, "primary" | "brand">;
45
+
46
+ /** The deprecated names and what they stand for — see {@link ButtonVariant}. */
47
+ const DEPRECATED_BUTTON_VARIANTS: Readonly<Record<string, CanonicalButtonVariant>> = {
48
+ primary: "default",
49
+ brand: "accent",
50
+ };
51
+
52
+ /** The kit's dev switch, as `lib/logger.ts` reads it: a development build, never a
53
+ * production one (the consumer's bundler makes `import.meta.env.DEV` false) and never
54
+ * under vitest. Read per call so a test can switch it on with `vi.stubEnv`. */
55
+ function devWarnings(): boolean {
56
+ return Boolean(import.meta.env?.DEV) && !import.meta.env?.VITEST;
57
+ }
58
+
59
+ const warnedVariants = new Set<string>();
60
+
61
+ /**
62
+ * @internal A deprecated variant name warns once (per `component` and name) in a
63
+ * development build, then reads as the name it stands for. `component` is the prop's
64
+ * owner in the message ("Button variant", "FormActions submitVariant", …).
65
+ */
66
+ export function warnDeprecatedVariant(component: string, name: string, replacement: string): void {
67
+ if (!devWarnings()) return;
68
+ const key = `${component}|${name}`;
69
+ if (warnedVariants.has(key)) return;
70
+ warnedVariants.add(key);
71
+ console.warn(
72
+ `[ui-kit] ${component}="${name}" is deprecated: use "${replacement}" (same look). ` +
73
+ `"${name}" is removed in 0.51.`,
74
+ );
75
+ }
76
+
77
+ /** @internal `primary` → `default`, `brand` → `accent` (warning once in development);
78
+ * every other variant as it is. Runs before every lookup keyed by the variant. */
79
+ export function resolveButtonVariant(variant: ButtonVariant, component = "Button variant"): CanonicalButtonVariant {
80
+ const replacement = DEPRECATED_BUTTON_VARIANTS[variant];
81
+ if (replacement === undefined) return variant as CanonicalButtonVariant;
82
+ warnDeprecatedVariant(component, variant, replacement);
83
+ return replacement;
84
+ }
17
85
 
18
86
  // Shared base ring for every button-styled element. Kept as a named const so the
19
87
  // <Button> component and the {@link buttonClasses} helper draw from one source and
@@ -83,13 +151,14 @@ const BUTTON_SIZES_LARGE: Record<ButtonSize, string> = {
83
151
  export const HOVER_INK = "hover:bg-[color-mix(in_srgb,var(--text-primary)_7%,transparent)]";
84
152
 
85
153
  // Warm, palette-token-driven so buttons blend with the fields + cards in every theme.
86
- // Actions default to a warm bordered look (primary = filled warm chip, secondary =
87
- // outline); `brand` stays the solid accent for the rare strong CTA; `danger` takes the
154
+ // Actions default to a warm bordered look (`default` = filled warm chip, secondary =
155
+ // outline); `accent` is the solid brand fill for the rare strong CTA; `danger` takes the
88
156
  // semantic `--danger` family (destructive semantics), so a consumer can re-point the
89
157
  // destructive hue instead of inheriting a hard-coded red. Focus rings follow each
90
- // variant's own accent: brand for the four neutral ones, danger for `danger`.
91
- export const buttonVariantClasses: Record<ButtonVariant, string> = {
92
- primary:
158
+ // variant's own accent: brand for the four neutral ones, danger for `danger`. Keyed by
159
+ // the canonical names: {@link resolveButtonVariant} maps the deprecated ones first.
160
+ export const buttonVariantClasses: Record<CanonicalButtonVariant, string> = {
161
+ default:
93
162
  // Hovers onto `--bg-active`, not `--border` (0.33, §12.9): More contrast steps the
94
163
  // border until it is a 3:1 LINE, and as a fill under the label that left 2.7:1.
95
164
  "border border-subtle bg-surface-2 text-primary hover:bg-active focus-visible:ring-brand",
@@ -97,7 +166,7 @@ export const buttonVariantClasses: Record<ButtonVariant, string> = {
97
166
  ghost: `bg-transparent text-primary ${HOVER_INK} focus-visible:ring-brand`,
98
167
  danger:
99
168
  "bg-danger text-danger-contrast hover:bg-danger-hover focus-visible:ring-danger-strong",
100
- brand:
169
+ accent:
101
170
  "bg-brand text-brand-contrast hover:bg-brand-hover focus-visible:ring-brand",
102
171
  // A text link that is still a `<button>` — keksdose's six hand-rolled
103
172
  // `<button className="text-brand underline">` sites ("Resend code", "Show all",
@@ -132,14 +201,14 @@ export const buttonVariantClasses: Record<ButtonVariant, string> = {
132
201
  *
133
202
  * `danger` also reaches the two NEUTRAL boxed variants, where the box carries it:
134
203
  * `secondary` becomes an outlined destructive button (`--danger` text and a
135
- * `--danger-border` outline, the quiet danger fill on hover) and `primary` a soft one
204
+ * `--danger-border` outline, the quiet danger fill on hover) and `default` a soft one
136
205
  * (the quiet fill at rest, solid `--danger` on hover). kastlan's meeting-invitations-
137
206
  * tab.tsx "Remove all" is `variant="secondary" className="text-destructive"` — a
138
207
  * destructive action that must sit in a row of secondary buttons without shouting
139
208
  * like the solid `variant="danger"` would, and whose red text alone left the border
140
209
  * and hover saying "neutral". `muted` stays a text look and does nothing on a box, and
141
- * `danger`, `brand` and `link`'s own colours are left alone: a tone that recoloured a
142
- * solid danger or brand button would be a second variant under another name.
210
+ * `danger`, `accent` and `link`'s own colours are left alone: a tone that recoloured a
211
+ * solid danger or accent button would be a second variant under another name.
143
212
  */
144
213
  export type ButtonTone = "default" | "muted" | "danger";
145
214
 
@@ -154,19 +223,19 @@ const BUTTON_TONES: Record<Exclude<ButtonTone, "default">, string> = {
154
223
  };
155
224
 
156
225
  /** Only the two transparent variants take every tone; see {@link ButtonTone}. */
157
- const TONED_VARIANTS = new Set<ButtonVariant>(["link", "ghost"]);
226
+ const TONED_VARIANTS = new Set<CanonicalButtonVariant>(["link", "ghost"]);
158
227
 
159
228
  // `tone="danger"` on the neutral boxed variants — see {@link ButtonTone}. Each string
160
229
  // restates every colour the variant sets (border, fill, text, hover, ring) so none of
161
230
  // the neutral ones survives the merge.
162
- const BUTTON_BOXED_DANGER: Partial<Record<ButtonVariant, string>> = {
231
+ const BUTTON_BOXED_DANGER: Partial<Record<CanonicalButtonVariant, string>> = {
163
232
  // Not boxed, but its hover is a fill: the danger wash under the danger text, as
164
233
  // IconButton's danger tone (0.33). On B′'s translucent ink `--danger` fell to 4.2:1
165
234
  // over a light page.
166
235
  ghost: "hover:bg-danger-soft",
167
236
  secondary:
168
237
  "border-danger bg-transparent text-danger hover:bg-danger-soft focus-visible:ring-danger-strong",
169
- primary:
238
+ default:
170
239
  "border-danger bg-danger-soft text-danger hover:border-[var(--danger)] hover:bg-danger hover:text-danger-contrast focus-visible:ring-danger-strong disabled:hover:border-danger disabled:hover:bg-danger-soft disabled:hover:text-danger",
171
240
  };
172
241
 
@@ -197,11 +266,12 @@ export interface ButtonClassesOptions {
197
266
  * compact toolbar links.
198
267
  */
199
268
  export function buttonClasses(
200
- variant: ButtonVariant = "primary",
269
+ given: ButtonVariant = "default",
201
270
  classNameOrOptions?: string | ButtonClassesOptions,
202
271
  ): string {
203
272
  const { size = "md", className } =
204
273
  typeof classNameOrOptions === "object" ? classNameOrOptions : { className: classNameOrOptions };
274
+ const variant = resolveButtonVariant(given, "buttonClasses variant");
205
275
  return cn(
206
276
  BUTTON_BASE,
207
277
  BUTTON_SIZES[size],
@@ -221,7 +291,8 @@ export const ICON_BUTTON_PRESSED =
221
291
  "bg-brand-soft text-brand hover:bg-brand-soft-hover hover:text-brand-muted disabled:hover:bg-brand-soft disabled:hover:text-brand";
222
292
 
223
293
  /** @internal The button look shared by the `<button>` and the `<a>` form. */
224
- export function buttonLook(variant: ButtonVariant, size: ButtonSize, stretch: boolean | undefined, tone: ButtonTone) {
294
+ export function buttonLook(given: ButtonVariant, size: ButtonSize, stretch: boolean | undefined, tone: ButtonTone) {
295
+ const variant = resolveButtonVariant(given);
225
296
  return cn(
226
297
  BUTTON_BASE,
227
298
  BUTTON_SIZES[size],
@@ -24,6 +24,9 @@ import type { ButtonSize, ButtonTone, ButtonVariant } from "./button-look";
24
24
  * link buttons submitting their form).
25
25
  */
26
26
  export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
27
+ /** `default` (the quiet action, what a Button without `variant` draws), `accent` (the
28
+ * strong call to action, solid brand), `secondary`, `ghost`, `danger` or `link`.
29
+ * `primary` / `brand` are deprecated aliases of `default` / `accent`. See {@link ButtonVariant}. */
27
30
  variant?: ButtonVariant;
28
31
  /** `md` (default) is the page's action button. `sm` is the compact one — 12px text
29
32
  * and `px-2 py-1` — for the secondary actions in a toolbar, a card header or a
@@ -39,7 +42,7 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
39
42
  ref?: Ref<HTMLButtonElement>;
40
43
  /** Text colour for `link` and `ghost`: `muted` (quiet, body colour on hover) or
41
44
  * `danger` (quiet, `--danger` on hover). `danger` also makes `secondary` an
42
- * outlined destructive button and `primary` a soft one; ignored by the other
45
+ * outlined destructive button and `default` a soft one; ignored by the other
43
46
  * variants. See {@link ButtonTone}. */
44
47
  tone?: ButtonTone;
45
48
  /**
@@ -181,7 +184,7 @@ function ButtonLink({
181
184
  replace,
182
185
  reloadDocument,
183
186
  disabled,
184
- variant = "primary",
187
+ variant = "default",
185
188
  size = "md",
186
189
  stretch,
187
190
  tone = "default",
@@ -257,7 +260,7 @@ function ButtonLink({
257
260
  }
258
261
 
259
262
  function ButtonElement({
260
- variant = "primary",
263
+ variant = "default",
261
264
  size = "md",
262
265
  stretch,
263
266
  tone = "default",
@@ -9,6 +9,7 @@ import { parseHex } from "../theme/color";
9
9
  import { Tooltip } from "./tooltip";
10
10
  import type { WeekDay } from "./mini-calendar";
11
11
  import { DEFAULT_CALENDAR_HEATMAP_LABELS } from "./calendar-heatmap-labels";
12
+ import { formatWithMinus } from "../lib/minus";
12
13
 
13
14
  /**
14
15
  * Every string the heatmap speaks — the `calendarHeatmap` namespace of
@@ -248,7 +249,7 @@ export function CalendarHeatmap({
248
249
  const providerWeekStart = useKitWeekStart();
249
250
  const weekStart: WeekDay = weekStartsOn ?? providerWeekStart ?? localeWeekStart(locale);
250
251
  const numberFormat = useMemo(() => new Intl.NumberFormat(locale), [locale]);
251
- const formatValue = formatValueProp ?? ((v: number) => numberFormat.format(v));
252
+ const formatValue = formatValueProp ?? ((v: number) => formatWithMinus(numberFormat, v));
252
253
 
253
254
  const values = useMemo(() => {
254
255
  const m = new Map<string, number>();
@@ -0,0 +1,73 @@
1
+ // The live side of `chartEdge` (theme/chart-palette.ts): which colours a FILLED mark is
2
+ // painted with and which grounds it sits on, read off <html> as the page resolves them —
3
+ // so the 1px ink edge follows a theme toggle and a palette switch without the chart
4
+ // knowing either store. Shared by SeriesChart (bars, areas) and Treemap (tiles).
5
+ import { useCallback, useSyncExternalStore } from "react";
6
+ import { chartEdge } from "../theme/chart-palette";
7
+ import { parseHex } from "../theme/color";
8
+
9
+ /** The tokens a theme or palette change can move, read as ONE string so
10
+ * `useSyncExternalStore` compares a primitive (a fresh array would never be equal). */
11
+ const WATCHED = [
12
+ "--bg-surface",
13
+ "--bg-page",
14
+ ...Array.from({ length: 9 }, (_, i) => `--chart-${i + 1}`),
15
+ "--chart-ink",
16
+ "--chart-muted",
17
+ "--money-income",
18
+ "--money-expense",
19
+ "--money-net",
20
+ "--money-neutral",
21
+ "--brand",
22
+ ];
23
+
24
+ function readWatched(): string {
25
+ const style = getComputedStyle(document.documentElement);
26
+ return WATCHED.map((name) => style.getPropertyValue(name).trim()).join(",");
27
+ }
28
+
29
+ function subscribe(onChange: () => void): () => void {
30
+ const observer = new MutationObserver(onChange);
31
+ observer.observe(document.documentElement, {
32
+ attributes: true,
33
+ attributeFilter: ["class", "style", "data-theme", "data-contrast"],
34
+ });
35
+ return () => observer.disconnect();
36
+ }
37
+
38
+ /** Server render: nothing measured, so no edge — the client adds it on hydration. */
39
+ const SERVER = "";
40
+
41
+ const BARE_VAR = /^var\(\s*(--[A-Za-z0-9_-]+)\s*\)$/;
42
+
43
+ /** A colour as the page resolves it: a hex as it is, a bare `var(--token)` read off
44
+ * <html>, anything else (a `color-mix()`, a var with a fallback) null. */
45
+ export function resolveChartColor(color: string, style: Pick<CSSStyleDeclaration, "getPropertyValue">): string | null {
46
+ const trimmed = color.trim();
47
+ if (parseHex(trimmed)) return trimmed;
48
+ const m = BARE_VAR.exec(trimmed);
49
+ if (!m) return null;
50
+ const value = style.getPropertyValue(m[1]).trim();
51
+ return parseHex(value) ? value : null;
52
+ }
53
+
54
+ /**
55
+ * `(fill) => edge`: the ink stroke a filled mark in `fill` needs on this page, or
56
+ * `undefined` — only for a colour under 3:1 against the card or the page (WCAG 1.4.11).
57
+ * `fill` may be a hex or a bare `var(--chart-N)` / `var(--money-…)`; anything it cannot
58
+ * measure gets no edge.
59
+ */
60
+ export function useChartEdge(): (fill: string | undefined) => string | undefined {
61
+ const snapshot = useSyncExternalStore(subscribe, readWatched, () => SERVER);
62
+ return useCallback(
63
+ (fill: string | undefined) => {
64
+ if (!fill || snapshot === SERVER || typeof document === "undefined") return undefined;
65
+ const style = getComputedStyle(document.documentElement);
66
+ const hex = resolveChartColor(fill, style);
67
+ if (!hex) return undefined;
68
+ const surfaces = ["--bg-surface", "--bg-page"].map((n) => style.getPropertyValue(n).trim());
69
+ return chartEdge(hex, surfaces);
70
+ },
71
+ [snapshot],
72
+ );
73
+ }
@@ -17,6 +17,7 @@ import {
17
17
  } from "recharts";
18
18
  import { cn } from "../lib/cn";
19
19
  import { isRtl } from "../lib/direction";
20
+ import { TYPOGRAPHIC_MINUS } from "../lib/minus";
20
21
 
21
22
  export interface ChartSeriesConfig {
22
23
  label: ReactNode;
@@ -376,7 +377,8 @@ export function ChartTooltipContent({
376
377
  if (inRow && !shown) text = NO_VALUE;
377
378
  else if (formatValue) text = formatValue(raw);
378
379
  else if (raw == null) text = NO_VALUE;
379
- else text = valueFormatter ? valueFormatter(raw) : raw;
380
+ // The bare number's minus is U+2212, as every kit figure's (0.49, KIT-1).
381
+ else text = valueFormatter ? valueFormatter(raw) : String(raw).replace(/-/g, TYPOGRAPHIC_MINUS);
380
382
  return (
381
383
  <div
382
384
  key={`${cfgKey}-${i}`}
@@ -3,6 +3,7 @@ import type { KeyboardEvent, MouseEvent, ReactElement, ReactNode, Ref } from "re
3
3
  import { Check, X } from "lucide-react";
4
4
  import type { LucideIcon } from "lucide-react";
5
5
  import { cn } from "../lib/cn";
6
+ import { statusTone, type StatusKind } from "../lib/status-tone";
6
7
  import { TOUCH_TARGET_LARGE } from "./button-look";
7
8
  import { FOCUS_RING } from "./focus-ring";
8
9
  import { assignRef, LockedReason, type DisabledReasonDisplay } from "./field-parts";
@@ -342,6 +343,12 @@ const REMOVE_HIT_AREA_LARGE =
342
343
  interface ChipBaseProps {
343
344
  children: ReactNode;
344
345
  tone?: ChipTone;
346
+ /**
347
+ * What the value means as a status (0.49 KIT-8), instead of a `tone`: `good` (success),
348
+ * `attention` (warning), `problem` (danger), `active` (info), `inactive` (neutral) —
349
+ * {@link statusTone}. An explicit `tone` wins. Never `brand` for a status.
350
+ */
351
+ status?: StatusKind;
345
352
  size?: ChipSize;
346
353
  /** See {@link ChipVariant}. Default `soft`. */
347
354
  variant?: ChipVariant;
@@ -537,7 +544,8 @@ export type ChipProps = ChipBaseProps &
537
544
  export function Chip({
538
545
  ref,
539
546
  children,
540
- tone = "neutral",
547
+ tone: toneProp,
548
+ status,
541
549
  size = "md",
542
550
  variant = "soft",
543
551
  shape = "pill",
@@ -563,6 +571,7 @@ export function Chip({
563
571
  commit,
564
572
  ...rest
565
573
  }: ChipProps) {
574
+ const tone: ChipTone = toneProp ?? (status ? statusTone(status) : "neutral");
566
575
  const common = useKitLabels("common", DEFAULT_COMMON_LABELS, { remove: removeLabel });
567
576
  const reasonId = useId();
568
577
  const disabledReason = useCommitReason(commit, ownDisabledReason);
@@ -0,0 +1,7 @@
1
+ import { createContext } from "react";
2
+ import type { ConfirmFn } from "./confirm-dialog";
3
+
4
+ /** The nearest `ConfirmProvider`'s `confirm`, or `null`. Internal: its own module so a
5
+ * part that may sit outside a provider (`RowActions`, 0.49 KIT-12) can ask without
6
+ * `useConfirm()`'s throw, and without adding a name to the barrel. */
7
+ export const ConfirmContext = createContext<ConfirmFn | null>(null);
@@ -1,4 +1,4 @@
1
- import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
1
+ import { useCallback, useContext, useEffect, useRef, useState } from "react";
2
2
  import type { ReactNode } from "react";
3
3
 
4
4
  import { useKitLabels } from "../i18n/kit-labels";
@@ -8,6 +8,7 @@ import { DialogFrame } from "./dialog-frame";
8
8
  import { Button } from "./button";
9
9
  import { useWriteLock, writeLockFor, type CommitScope } from "./write-lock";
10
10
  import { DEFAULT_CONFIRM_DIALOG_LABELS } from "./confirm-dialog-labels";
11
+ import { ConfirmContext } from "./confirm-context";
11
12
 
12
13
  /**
13
14
  * The `confirmDialog` namespace of `<UiKitProvider labels>`: the two buttons' fallback
@@ -89,7 +90,6 @@ export interface ConfirmOptions {
89
90
 
90
91
  export type ConfirmFn = (options: ConfirmOptions) => Promise<boolean>;
91
92
 
92
- const ConfirmContext = createContext<ConfirmFn | null>(null);
93
93
 
94
94
  /**
95
95
  * `const confirm = useConfirm()` → `if (!(await confirm({ title }))) return`.
@@ -298,7 +298,7 @@ function ConfirmDialogView({
298
298
  <Button
299
299
  ref={confirmRef}
300
300
  type="button"
301
- variant={tone === "danger" ? "danger" : "primary"}
301
+ variant={tone === "danger" ? "danger" : "default"}
302
302
  disabled={!matches}
303
303
  disabledReason={request.lockReason}
304
304
  onClick={() => {
@@ -449,14 +449,14 @@ export interface DangerConfirmProps extends Omit<ComponentPropsWithRef<"div">, "
449
449
  tone?: "danger" | "warning";
450
450
  /**
451
451
  * The confirm button's variant, apart from `tone` (0.24, keksdose). Default: what
452
- * `tone` picks, as before — `"danger"` for `"danger"`, `"primary"` for `"warning"`.
452
+ * `tone` picks, as before — `"danger"` for `"danger"`, `"default"` for `"warning"`.
453
453
  *
454
454
  * `tone` says how bad the outcome is; this says how loud the last press is, and the two
455
455
  * need not agree. keksdose's `UserActionConfirm` (an admin resets somebody else's
456
456
  * password) asks an AMBER question — what it guards against is mis-targeting, not data
457
457
  * loss, so the danger colour stays its one `severe` consequence's — and ends in a RED
458
458
  * Go, as its hand-built panel did before it moved onto this tile in 0.23; with only
459
- * `tone`, the amber question made Go the neutral primary fill. `tone="warning"
459
+ * `tone`, the amber question made Go the neutral `default` fill. `tone="warning"
460
460
  * confirmVariant="danger"` is that panel again.
461
461
  */
462
462
  confirmVariant?: ButtonVariant;
@@ -914,7 +914,7 @@ export function DangerConfirm({
914
914
  <Button
915
915
  id={confirmId}
916
916
  type="submit"
917
- variant={confirmVariant ?? (tone === "warning" ? "primary" : "danger")}
917
+ variant={confirmVariant ?? (tone === "warning" ? "default" : "danger")}
918
918
  disabled={!canConfirm}
919
919
  // Held by a guard (the caller's or a built-in one), or armed and then locked
920
920
  // (or rendered armed under a lock): the confirm says why the way Button