twico-ui 1.48.0 → 1.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.
package/dist/index.d.cts CHANGED
@@ -258,7 +258,11 @@ declare function Accordion(props: AccordionProps): React.JSX.Element;
258
258
  /** The canonical six-value color/intent scale used by status & control components. */
259
259
  type Tone = "primary" | "success" | "warning" | "danger" | "info" | "neutral";
260
260
 
261
- /** Action controls (Button, IconButton) — brand or destructive only. */
261
+ /**
262
+ * The two intents most actions want. Button and IconButton accepted ONLY these until #504; they now
263
+ * take the full {@link Tone} scale, so this is a convenience alias for the common pair rather than a
264
+ * ceiling. Still exported, still accurate for anything that genuinely is brand-or-destructive.
265
+ */
262
266
  type ActionTone = "primary" | "danger";
263
267
 
264
268
  /** Text roles, the full color scale, and `"inherit"` (adopt the parent color) — Text. */
@@ -557,8 +561,20 @@ declare function Breadcrumb(props: BreadcrumbProps): React.JSX.Element;
557
561
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
558
562
  /** Fill style. @default "solid" */
559
563
  variant?: "solid" | "soft" | "outline" | "ghost";
560
- /** Color/intent, orthogonal to `variant`. @default "primary" */
561
- tone?: ActionTone;
564
+ /**
565
+ * Color/intent, orthogonal to `variant`. @default "primary"
566
+ *
567
+ * #504: the full {@link Tone} scale, widened from `ActionTone` (`primary | danger`). A standalone
568
+ * affirmative action — a row-level confirm sitting beside a `danger` sibling, reading as
569
+ * "yes / no" — could not be green, so the colour carrying that distinction came out the same blue
570
+ * as every neutral action on the page. `ActionTone` is still exported and still describes the two
571
+ * intents most actions want; it is no longer the ceiling.
572
+ *
573
+ * `neutral` follows Badge's mapping rather than an accent ramp of its own: `--color-text` on
574
+ * `--color-surface` for `solid`, `--color-surface-sunken` for `soft`. Note `variant="ghost"` and
575
+ * `variant="outline"` already express a quiet action, so reach for those first.
576
+ */
577
+ tone?: Tone;
562
578
  /** Control size; "xs" (~26px) is smaller than "sm". @default "md" */
563
579
  size?: "xs" | "sm" | "md" | "lg";
564
580
  /** Icon node rendered before the label. */
@@ -576,9 +592,10 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
576
592
  /** #405: toggle "on" state — sets `aria-pressed` and shows a soft fill + border in the current `tone`
577
593
  * (works with any `variant`). Omit for a plain (non-toggle) button. @default undefined */
578
594
  pressed?: boolean;
579
- /** #411: tone of the pressed ("on") fill — the full status `Tone` scale, so a toggle can carry its own
580
- * selected-state meaning (e.g. success/warning/info/neutral) while `tone` stays `ActionTone` for the
581
- * unpressed action look. Defaults to `tone`. @default undefined */
595
+ /** #411: tone of the pressed ("on") fill, so a toggle can carry a different selected-state meaning
596
+ * from its unpressed look. Both are the full `Tone` scale since #504 — before that `tone` was
597
+ * `ActionTone` and this was the only way to reach the other four. Defaults to `tone`.
598
+ * @default undefined */
582
599
  pressedTone?: Tone;
583
600
  /** Render as a different element (e.g. "a"). @default "button" */
584
601
  as?: "button" | "a";
@@ -3939,9 +3956,16 @@ interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
3939
3956
  icon?: React.ReactNode;
3940
3957
  /** Fill style (same axes as Button). @default "ghost" */
3941
3958
  variant?: "solid" | "soft" | "outline" | "ghost";
3942
- /** Color/intent, orthogonal to `variant` (mirrors Button). A destructive icon button is
3943
- * `tone="danger"` with any variant. @default "primary" */
3944
- tone?: ActionTone;
3959
+ /**
3960
+ * Color/intent, orthogonal to `variant` (mirrors Button). A destructive icon button is
3961
+ * `tone="danger"` with any variant. @default "primary"
3962
+ *
3963
+ * #504: the full {@link Tone} scale, widened from `ActionTone` (`primary | danger`), so an
3964
+ * affirmative icon action can be green beside a destructive one. `ActionTone` is still exported
3965
+ * and still names the two intents most actions want; it is no longer the ceiling. `neutral`
3966
+ * follows Badge's mapping rather than an accent ramp of its own.
3967
+ */
3968
+ tone?: Tone;
3945
3969
  /** Control size; "xs" (~26px) is smaller than "sm". @default "md" */
3946
3970
  size?: "xs" | "sm" | "md" | "lg";
3947
3971
  /** Fully rounded (circular). @default false */
@@ -3953,8 +3977,9 @@ interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
3953
3977
  /** #405: toggle "on" state — sets `aria-pressed` and shows a soft fill + border in the current `tone`
3954
3978
  * (works with any `variant`), e.g. a pin/unpin or bold/italic icon toggle. @default undefined */
3955
3979
  pressed?: boolean;
3956
- /** #411: tone of the pressed ("on") fill — the full status `Tone` scale, so a toggle can carry its own
3957
- * selected-state meaning while `tone` stays `ActionTone` for the unpressed look. Defaults to `tone`. @default undefined */
3980
+ /** #411: tone of the pressed ("on") fill, so a toggle can carry a different selected-state meaning
3981
+ * from its unpressed look. Both are the full `Tone` scale since #504. Defaults to `tone`.
3982
+ * @default undefined */
3958
3983
  pressedTone?: Tone;
3959
3984
  /** #342: render as a different element — use `"a"` for an icon **link** (GitHub icon, external nav, …) so
3960
3985
  * navigation is a real link, not a button. @default "button" */
package/dist/index.d.ts CHANGED
@@ -258,7 +258,11 @@ declare function Accordion(props: AccordionProps): React.JSX.Element;
258
258
  /** The canonical six-value color/intent scale used by status & control components. */
259
259
  type Tone = "primary" | "success" | "warning" | "danger" | "info" | "neutral";
260
260
 
261
- /** Action controls (Button, IconButton) — brand or destructive only. */
261
+ /**
262
+ * The two intents most actions want. Button and IconButton accepted ONLY these until #504; they now
263
+ * take the full {@link Tone} scale, so this is a convenience alias for the common pair rather than a
264
+ * ceiling. Still exported, still accurate for anything that genuinely is brand-or-destructive.
265
+ */
262
266
  type ActionTone = "primary" | "danger";
263
267
 
264
268
  /** Text roles, the full color scale, and `"inherit"` (adopt the parent color) — Text. */
@@ -557,8 +561,20 @@ declare function Breadcrumb(props: BreadcrumbProps): React.JSX.Element;
557
561
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
558
562
  /** Fill style. @default "solid" */
559
563
  variant?: "solid" | "soft" | "outline" | "ghost";
560
- /** Color/intent, orthogonal to `variant`. @default "primary" */
561
- tone?: ActionTone;
564
+ /**
565
+ * Color/intent, orthogonal to `variant`. @default "primary"
566
+ *
567
+ * #504: the full {@link Tone} scale, widened from `ActionTone` (`primary | danger`). A standalone
568
+ * affirmative action — a row-level confirm sitting beside a `danger` sibling, reading as
569
+ * "yes / no" — could not be green, so the colour carrying that distinction came out the same blue
570
+ * as every neutral action on the page. `ActionTone` is still exported and still describes the two
571
+ * intents most actions want; it is no longer the ceiling.
572
+ *
573
+ * `neutral` follows Badge's mapping rather than an accent ramp of its own: `--color-text` on
574
+ * `--color-surface` for `solid`, `--color-surface-sunken` for `soft`. Note `variant="ghost"` and
575
+ * `variant="outline"` already express a quiet action, so reach for those first.
576
+ */
577
+ tone?: Tone;
562
578
  /** Control size; "xs" (~26px) is smaller than "sm". @default "md" */
563
579
  size?: "xs" | "sm" | "md" | "lg";
564
580
  /** Icon node rendered before the label. */
@@ -576,9 +592,10 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
576
592
  /** #405: toggle "on" state — sets `aria-pressed` and shows a soft fill + border in the current `tone`
577
593
  * (works with any `variant`). Omit for a plain (non-toggle) button. @default undefined */
578
594
  pressed?: boolean;
579
- /** #411: tone of the pressed ("on") fill — the full status `Tone` scale, so a toggle can carry its own
580
- * selected-state meaning (e.g. success/warning/info/neutral) while `tone` stays `ActionTone` for the
581
- * unpressed action look. Defaults to `tone`. @default undefined */
595
+ /** #411: tone of the pressed ("on") fill, so a toggle can carry a different selected-state meaning
596
+ * from its unpressed look. Both are the full `Tone` scale since #504 — before that `tone` was
597
+ * `ActionTone` and this was the only way to reach the other four. Defaults to `tone`.
598
+ * @default undefined */
582
599
  pressedTone?: Tone;
583
600
  /** Render as a different element (e.g. "a"). @default "button" */
584
601
  as?: "button" | "a";
@@ -3939,9 +3956,16 @@ interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
3939
3956
  icon?: React.ReactNode;
3940
3957
  /** Fill style (same axes as Button). @default "ghost" */
3941
3958
  variant?: "solid" | "soft" | "outline" | "ghost";
3942
- /** Color/intent, orthogonal to `variant` (mirrors Button). A destructive icon button is
3943
- * `tone="danger"` with any variant. @default "primary" */
3944
- tone?: ActionTone;
3959
+ /**
3960
+ * Color/intent, orthogonal to `variant` (mirrors Button). A destructive icon button is
3961
+ * `tone="danger"` with any variant. @default "primary"
3962
+ *
3963
+ * #504: the full {@link Tone} scale, widened from `ActionTone` (`primary | danger`), so an
3964
+ * affirmative icon action can be green beside a destructive one. `ActionTone` is still exported
3965
+ * and still names the two intents most actions want; it is no longer the ceiling. `neutral`
3966
+ * follows Badge's mapping rather than an accent ramp of its own.
3967
+ */
3968
+ tone?: Tone;
3945
3969
  /** Control size; "xs" (~26px) is smaller than "sm". @default "md" */
3946
3970
  size?: "xs" | "sm" | "md" | "lg";
3947
3971
  /** Fully rounded (circular). @default false */
@@ -3953,8 +3977,9 @@ interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
3953
3977
  /** #405: toggle "on" state — sets `aria-pressed` and shows a soft fill + border in the current `tone`
3954
3978
  * (works with any `variant`), e.g. a pin/unpin or bold/italic icon toggle. @default undefined */
3955
3979
  pressed?: boolean;
3956
- /** #411: tone of the pressed ("on") fill — the full status `Tone` scale, so a toggle can carry its own
3957
- * selected-state meaning while `tone` stays `ActionTone` for the unpressed look. Defaults to `tone`. @default undefined */
3980
+ /** #411: tone of the pressed ("on") fill, so a toggle can carry a different selected-state meaning
3981
+ * from its unpressed look. Both are the full `Tone` scale since #504. Defaults to `tone`.
3982
+ * @default undefined */
3958
3983
  pressedTone?: Tone;
3959
3984
  /** #342: render as a different element — use `"a"` for an icon **link** (GitHub icon, external nav, …) so
3960
3985
  * navigation is a real link, not a button. @default "button" */
package/dist/index.mjs CHANGED
@@ -434,6 +434,22 @@ var ICONBTN_CSS = `
434
434
  --_accent-fg: var(--color-primary-fg); --_accent-subtle: var(--color-primary-subtle); --_accent-subtle-fg: var(--color-primary-subtle-fg); }
435
435
  .twc-iconbtn[data-tone="danger"] { --_accent: var(--color-danger); --_accent-hover: var(--color-danger-hover);
436
436
  --_accent-fg: var(--color-danger-fg); --_accent-subtle: var(--color-danger-subtle); --_accent-subtle-fg: var(--color-danger-subtle-fg); }
437
+ /* #504: the full Tone scale, not just primary|danger. A standalone affirmative action - a row-level
438
+ confirm sitting next to a danger sibling, reading as "yes / no" - could not be green, so the colour
439
+ that carried the distinction came out the same blue as every neutral action on the page.
440
+ success/warning/info now have real -hover/-active tokens (added in tokens/colors.css on the same
441
+ step rule as primary and danger: light goes darker, dark goes lighter), so hover always moves AWAY
442
+ from the ink and contrast only improves. neutral has no accent tokens anywhere and is mapped the way
443
+ Badge already maps it - --color-text on --color-surface solid, --color-surface-sunken soft - with its
444
+ hover mixed from currentColor, since there is no --color-text-hover to point at. */
445
+ .twc-iconbtn[data-tone="success"] { --_accent: var(--color-success); --_accent-hover: var(--color-success-hover);
446
+ --_accent-fg: var(--color-success-fg); --_accent-subtle: var(--color-success-subtle); --_accent-subtle-fg: var(--color-success-subtle-fg); }
447
+ .twc-iconbtn[data-tone="warning"] { --_accent: var(--color-warning); --_accent-hover: var(--color-warning-hover);
448
+ --_accent-fg: var(--color-warning-fg); --_accent-subtle: var(--color-warning-subtle); --_accent-subtle-fg: var(--color-warning-subtle-fg); }
449
+ .twc-iconbtn[data-tone="info"] { --_accent: var(--color-info); --_accent-hover: var(--color-info-hover);
450
+ --_accent-fg: var(--color-info-fg); --_accent-subtle: var(--color-info-subtle); --_accent-subtle-fg: var(--color-info-subtle-fg); }
451
+ .twc-iconbtn[data-tone="neutral"] { --_accent: var(--color-text); --_accent-hover: color-mix(in srgb, var(--color-text) 88%, var(--color-surface));
452
+ --_accent-fg: var(--color-surface); --_accent-subtle: var(--color-surface-sunken); --_accent-subtle-fg: var(--color-text-muted); }
437
453
  .twc-iconbtn[data-variant="solid"] { background: var(--_accent); color: var(--_accent-fg); }
438
454
  .twc-iconbtn[data-variant="solid"]:hover:not(:disabled) { background: var(--_accent-hover); box-shadow: var(--shadow-brand); }
439
455
  .twc-iconbtn[data-variant="solid"]:active:not(:disabled) { filter: brightness(0.92); }
@@ -1811,6 +1827,31 @@ var CSS2 = `
1811
1827
  --_accent: var(--color-danger); --_accent-hover: var(--color-danger-hover); --_accent-active: var(--color-danger-hover);
1812
1828
  --_accent-fg: var(--color-danger-fg); --_accent-subtle: var(--color-danger-subtle); --_accent-subtle-fg: var(--color-danger-subtle-fg);
1813
1829
  }
1830
+ /* #504: the full Tone scale, not just primary|danger. A standalone affirmative action - a row-level
1831
+ confirm sitting next to a danger sibling, reading as "yes / no" - could not be green, so the colour
1832
+ that carried the distinction came out the same blue as every neutral action on the page.
1833
+ success/warning/info now have real -hover/-active tokens (added in tokens/colors.css on the same
1834
+ step rule as primary and danger: light goes darker, dark goes lighter), so hover always moves AWAY
1835
+ from the ink and contrast only improves. neutral has no accent tokens anywhere and is mapped the way
1836
+ Badge already maps it - --color-text on --color-surface solid, --color-surface-sunken soft - with its
1837
+ hover mixed from currentColor, since there is no --color-text-hover to point at. */
1838
+ .twc-btn[data-tone="success"] {
1839
+ --_accent: var(--color-success); --_accent-hover: var(--color-success-hover); --_accent-active: var(--color-success-active);
1840
+ --_accent-fg: var(--color-success-fg); --_accent-subtle: var(--color-success-subtle); --_accent-subtle-fg: var(--color-success-subtle-fg);
1841
+ }
1842
+ .twc-btn[data-tone="warning"] {
1843
+ --_accent: var(--color-warning); --_accent-hover: var(--color-warning-hover); --_accent-active: var(--color-warning-active);
1844
+ --_accent-fg: var(--color-warning-fg); --_accent-subtle: var(--color-warning-subtle); --_accent-subtle-fg: var(--color-warning-subtle-fg);
1845
+ }
1846
+ .twc-btn[data-tone="info"] {
1847
+ --_accent: var(--color-info); --_accent-hover: var(--color-info-hover); --_accent-active: var(--color-info-active);
1848
+ --_accent-fg: var(--color-info-fg); --_accent-subtle: var(--color-info-subtle); --_accent-subtle-fg: var(--color-info-subtle-fg);
1849
+ }
1850
+ .twc-btn[data-tone="neutral"] {
1851
+ --_accent: var(--color-text); --_accent-hover: color-mix(in srgb, var(--color-text) 88%, var(--color-surface));
1852
+ --_accent-active: color-mix(in srgb, var(--color-text) 78%, var(--color-surface));
1853
+ --_accent-fg: var(--color-surface); --_accent-subtle: var(--color-surface-sunken); --_accent-subtle-fg: var(--color-text-muted);
1854
+ }
1814
1855
  /* solid */
1815
1856
  .twc-btn[data-variant="solid"] { background: var(--_accent); color: var(--_accent-fg); }
1816
1857
  .twc-btn[data-variant="solid"]:hover:not(:disabled) { background: var(--_accent-hover); box-shadow: var(--shadow-brand); }