@jirawatpyk/aura-react 5.63.0 → 5.65.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/README.md CHANGED
@@ -186,6 +186,14 @@ DataTable with sort and page in the URL (4.17): `onStateChange={({ sort, page })
186
186
  - **Time zone**: `timeZone` on AuraProvider, DatePicker, DateRangePicker and Calendar decides "today" (the marker, `min`/`max="today"`, the first month shown); or pass `today` as an ISO date. `todayIn('Asia/Bangkok')` is exported from the root and `/server`.
187
187
  - **Toasts** queue past three instead of dropping: six in a row all show, in order, three at a time.
188
188
 
189
+ ## 5.65 — Chamber-OS addendum 81 (#180)
190
+
191
+ - **A pressed IconButton looks on:** an IconButton with `aria-pressed="true"` — or the new `pressed` prop, which sets `aria-pressed` for you — draws the selected fill (`aura-bg-selected`, as a selected Tag or nav item) with an accent icon (`aura-fg-accent`, at least 3:1 on it in light and dark); `tone` is ignored while pressed. Hover still shows on a pressed one (an accent hairline inside), an `outline` toggle takes an accent border, a pressed menu trigger stays on while its menu is open, and the focus ring is unchanged. In forced colours a pressed toggle is Highlight with a CanvasText focus ring. `pressed={false}`, no prop and `aria-pressed="mixed"` draw as before. Inside a field the reveal eye of PasswordField (which uses `aria-pressed`) stays quiet. On a selected DataTable row, which has the same fill, only the accent icon shows it. For an editor toolbar's Bold / Italic / lists; drop `aria-pressed:bg-… aria-pressed:text-…` stand-ins.
192
+
193
+ ## 5.64 — Chamber-OS addendum 80 (#179)
194
+
195
+ - **Progress `legend` — a key for the reserved part:** `legend={{ value: 'Used', secondary: 'Reserved (in review or scheduled)' }}` draws a key under the bar (above the `hint`): a swatch in the bar's tone for each part (`value` is optional), the second striped like the reserved segment, so it follows `tone="danger"`. It shows only while the reserved segment is drawn and wraps on a phone. It is `aria-hidden`, so while it shows the bar reads both counts ("2 of 6 used, 1 reserved") even when you pass a `valueLabel` — pass `valueText` to word it yourself. In forced colours the bar and the swatches use Highlight in every tone (before 5.64 a toned bar kept its colour). Drop a hand-drawn key that copies the stripe.
196
+
189
197
  ## 5.63 — Chamber-OS addendum 79 (#178)
190
198
 
191
199
  - **A lazy chip still makes `meta` the chip row:** a Server Component's Badge or StatusPill passed through a `'use client'` wrapper can arrive as a lazy node on Next's dev server. PageHeader now looks through a resolved lazy node (a chip makes the row, text keeps the line, as when it arrives resolved), and an unresolved one is neutral — the other children decide — so the layout no longer depends on the build mode. Anything else unresolved (a promise, an iterator) keeps a line.
@@ -1649,7 +1649,7 @@ window.Aura = (() => {
1649
1649
 
1650
1650
  // src/IconButton.tsx
1651
1651
  var IconButton = React8.forwardRef(function IconButton2(props, ref) {
1652
- const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant"]);
1652
+ const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant", "pressed"]);
1653
1653
  useAutoTip();
1654
1654
  const own = props.title !== void 0;
1655
1655
  return /* @__PURE__ */ React8.createElement(
@@ -1659,6 +1659,7 @@ window.Aura = (() => {
1659
1659
  ref,
1660
1660
  type: props.type || "button",
1661
1661
  "aria-label": props.label,
1662
+ "aria-pressed": props.pressed != null ? props.pressed : props["aria-pressed"],
1662
1663
  "data-aura-tip": own ? void 0 : props.label,
1663
1664
  className: cx(
1664
1665
  "aura-icon-btn",
@@ -10171,7 +10172,8 @@ window.Aura = (() => {
10171
10172
  const pct = det ? Math.max(0, Math.min(100, props.value / max * 100)) : 0;
10172
10173
  const sec = det && props.secondaryValue != null && props.secondaryValue > 0 ? props.secondaryValue : 0;
10173
10174
  const spct = sec ? Math.max(0, Math.min(100 - pct, sec / max * 100)) : 0;
10174
- const valueText = props.valueText != null ? props.valueText : props.valueLabel != null ? String(props.valueLabel) : sec ? t.progressReserved(props.value, sec, max) : void 0;
10175
+ const keyed = !!props.legend && spct > 0;
10176
+ const valueText = props.valueText != null ? props.valueText : keyed ? t.progressReserved(props.value, sec, max) : props.valueLabel != null ? String(props.valueLabel) : sec ? t.progressReserved(props.value, sec, max) : void 0;
10175
10177
  const shown = props.valueLabel != null ? props.valueLabel : det ? Math.round(pct) + "%" : null;
10176
10178
  return /* @__PURE__ */ React61.createElement(
10177
10179
  "div",
@@ -10206,6 +10208,7 @@ window.Aura = (() => {
10206
10208
  }
10207
10209
  ) : null
10208
10210
  ),
10211
+ keyed ? /* @__PURE__ */ React61.createElement("div", { className: "aura-progress__legend", "aria-hidden": "true" }, props.legend.value != null && props.legend.value !== false ? /* @__PURE__ */ React61.createElement("span", { className: "aura-progress__key" }, /* @__PURE__ */ React61.createElement("span", { className: "aura-progress__swatch" }), props.legend.value) : null, /* @__PURE__ */ React61.createElement("span", { className: "aura-progress__key" }, /* @__PURE__ */ React61.createElement("span", { className: "aura-progress__swatch aura-progress__swatch--reserved" }), props.legend.secondary)) : null,
10209
10212
  props.hint ? /* @__PURE__ */ React61.createElement("p", { className: "aura-progress__hint" }, props.hint) : null
10210
10213
  );
10211
10214
  });
@@ -1631,7 +1631,7 @@ function useAutoTip() {
1631
1631
 
1632
1632
  // src/IconButton.tsx
1633
1633
  var IconButton = React8.forwardRef(function IconButton2(props, ref) {
1634
- const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant"]);
1634
+ const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant", "pressed"]);
1635
1635
  useAutoTip();
1636
1636
  const own = props.title !== void 0;
1637
1637
  return /* @__PURE__ */ React8.createElement(
@@ -1641,6 +1641,7 @@ var IconButton = React8.forwardRef(function IconButton2(props, ref) {
1641
1641
  ref,
1642
1642
  type: props.type || "button",
1643
1643
  "aria-label": props.label,
1644
+ "aria-pressed": props.pressed != null ? props.pressed : props["aria-pressed"],
1644
1645
  "data-aura-tip": own ? void 0 : props.label,
1645
1646
  className: cx(
1646
1647
  "aura-icon-btn",
@@ -10153,7 +10154,8 @@ var Progress = React61.forwardRef(function Progress2(props, ref) {
10153
10154
  const pct = det ? Math.max(0, Math.min(100, props.value / max * 100)) : 0;
10154
10155
  const sec = det && props.secondaryValue != null && props.secondaryValue > 0 ? props.secondaryValue : 0;
10155
10156
  const spct = sec ? Math.max(0, Math.min(100 - pct, sec / max * 100)) : 0;
10156
- const valueText = props.valueText != null ? props.valueText : props.valueLabel != null ? String(props.valueLabel) : sec ? t.progressReserved(props.value, sec, max) : void 0;
10157
+ const keyed = !!props.legend && spct > 0;
10158
+ const valueText = props.valueText != null ? props.valueText : keyed ? t.progressReserved(props.value, sec, max) : props.valueLabel != null ? String(props.valueLabel) : sec ? t.progressReserved(props.value, sec, max) : void 0;
10157
10159
  const shown = props.valueLabel != null ? props.valueLabel : det ? Math.round(pct) + "%" : null;
10158
10160
  return /* @__PURE__ */ React61.createElement(
10159
10161
  "div",
@@ -10188,6 +10190,7 @@ var Progress = React61.forwardRef(function Progress2(props, ref) {
10188
10190
  }
10189
10191
  ) : null
10190
10192
  ),
10193
+ keyed ? /* @__PURE__ */ React61.createElement("div", { className: "aura-progress__legend", "aria-hidden": "true" }, props.legend.value != null && props.legend.value !== false ? /* @__PURE__ */ React61.createElement("span", { className: "aura-progress__key" }, /* @__PURE__ */ React61.createElement("span", { className: "aura-progress__swatch" }), props.legend.value) : null, /* @__PURE__ */ React61.createElement("span", { className: "aura-progress__key" }, /* @__PURE__ */ React61.createElement("span", { className: "aura-progress__swatch aura-progress__swatch--reserved" }), props.legend.secondary)) : null,
10191
10194
  props.hint ? /* @__PURE__ */ React61.createElement("p", { className: "aura-progress__hint" }, props.hint) : null
10192
10195
  );
10193
10196
  });
@@ -4,7 +4,7 @@ import { cx, omit } from "./internal.js";
4
4
  import { Icon } from "./Icon.js";
5
5
  import { useAutoTip } from "./autoTip.js";
6
6
  const IconButton = React.forwardRef(function IconButton2(props, ref) {
7
- const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant"]);
7
+ const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant", "pressed"]);
8
8
  useAutoTip();
9
9
  const own = props.title !== void 0;
10
10
  return /* @__PURE__ */ React.createElement(
@@ -14,6 +14,7 @@ const IconButton = React.forwardRef(function IconButton2(props, ref) {
14
14
  ref,
15
15
  type: props.type || "button",
16
16
  "aria-label": props.label,
17
+ "aria-pressed": props.pressed != null ? props.pressed : props["aria-pressed"],
17
18
  "data-aura-tip": own ? void 0 : props.label,
18
19
  className: cx(
19
20
  "aura-icon-btn",
@@ -9,7 +9,8 @@ const Progress = React.forwardRef(function Progress2(props, ref) {
9
9
  const pct = det ? Math.max(0, Math.min(100, props.value / max * 100)) : 0;
10
10
  const sec = det && props.secondaryValue != null && props.secondaryValue > 0 ? props.secondaryValue : 0;
11
11
  const spct = sec ? Math.max(0, Math.min(100 - pct, sec / max * 100)) : 0;
12
- const valueText = props.valueText != null ? props.valueText : props.valueLabel != null ? String(props.valueLabel) : sec ? t.progressReserved(props.value, sec, max) : void 0;
12
+ const keyed = !!props.legend && spct > 0;
13
+ const valueText = props.valueText != null ? props.valueText : keyed ? t.progressReserved(props.value, sec, max) : props.valueLabel != null ? String(props.valueLabel) : sec ? t.progressReserved(props.value, sec, max) : void 0;
13
14
  const shown = props.valueLabel != null ? props.valueLabel : det ? Math.round(pct) + "%" : null;
14
15
  return /* @__PURE__ */ React.createElement(
15
16
  "div",
@@ -44,6 +45,7 @@ const Progress = React.forwardRef(function Progress2(props, ref) {
44
45
  }
45
46
  ) : null
46
47
  ),
48
+ keyed ? /* @__PURE__ */ React.createElement("div", { className: "aura-progress__legend", "aria-hidden": "true" }, props.legend.value != null && props.legend.value !== false ? /* @__PURE__ */ React.createElement("span", { className: "aura-progress__key" }, /* @__PURE__ */ React.createElement("span", { className: "aura-progress__swatch" }), props.legend.value) : null, /* @__PURE__ */ React.createElement("span", { className: "aura-progress__key" }, /* @__PURE__ */ React.createElement("span", { className: "aura-progress__swatch aura-progress__swatch--reserved" }), props.legend.secondary)) : null,
47
49
  props.hint ? /* @__PURE__ */ React.createElement("p", { className: "aura-progress__hint" }, props.hint) : null
48
50
  );
49
51
  });
package/dist/index.d.cts CHANGED
@@ -384,6 +384,9 @@ export interface IconButtonProps extends React$1.ButtonHTMLAttributes<HTMLButton
384
384
  /** 44×44 instead of 32×32 below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24) —
385
385
  * a phone sheet's close button, a card's ⋯ trigger (5.15, Chamber-OS 100). */
386
386
  touchHeight?: boolean | undefined;
387
+ /** A toggle (5.65, Chamber-OS 180): sets `aria-pressed`, and a pressed button draws as on — the selected fill and the
388
+ * accent icon. Omit for an ordinary button. An `aria-pressed` you pass draws the same. */
389
+ pressed?: boolean | undefined;
387
390
  }
388
391
  export interface MenuItem {
389
392
  label?: string | undefined;
@@ -1653,6 +1656,14 @@ export interface ProgressProps {
1653
1656
  /** A reserved amount drawn after `value` as a striped segment of the same tone — queued sends on a quota
1654
1657
  * (5.15, Chamber-OS 89). Both counts are read out ("2 of 6 used, 1 reserved") unless `valueLabel` is given. */
1655
1658
  secondaryValue?: number | undefined;
1659
+ /** A key under the bar for its two parts (5.64, Chamber-OS 179): `{ value: 'Used', secondary: 'Reserved' }` — a
1660
+ * swatch in the bar's tone for each (`value` optional), the second striped like the reserved segment. Shown only
1661
+ * while the reserved segment is drawn; hidden from screen readers — so while it shows, the bar reads both counts
1662
+ * ("2 of 6 used, 1 reserved") even with a `valueLabel`, unless you pass `valueText`. */
1663
+ legend?: {
1664
+ value?: React$1.ReactNode;
1665
+ secondary: React$1.ReactNode;
1666
+ } | undefined;
1656
1667
  hint?: React$1.ReactNode | undefined;
1657
1668
  tone?: Tone | undefined;
1658
1669
  size?: "sm" | "md" | undefined;
package/dist/index.d.ts CHANGED
@@ -384,6 +384,9 @@ export interface IconButtonProps extends React$1.ButtonHTMLAttributes<HTMLButton
384
384
  /** 44×44 instead of 32×32 below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24) —
385
385
  * a phone sheet's close button, a card's ⋯ trigger (5.15, Chamber-OS 100). */
386
386
  touchHeight?: boolean | undefined;
387
+ /** A toggle (5.65, Chamber-OS 180): sets `aria-pressed`, and a pressed button draws as on — the selected fill and the
388
+ * accent icon. Omit for an ordinary button. An `aria-pressed` you pass draws the same. */
389
+ pressed?: boolean | undefined;
387
390
  }
388
391
  export interface MenuItem {
389
392
  label?: string | undefined;
@@ -1653,6 +1656,14 @@ export interface ProgressProps {
1653
1656
  /** A reserved amount drawn after `value` as a striped segment of the same tone — queued sends on a quota
1654
1657
  * (5.15, Chamber-OS 89). Both counts are read out ("2 of 6 used, 1 reserved") unless `valueLabel` is given. */
1655
1658
  secondaryValue?: number | undefined;
1659
+ /** A key under the bar for its two parts (5.64, Chamber-OS 179): `{ value: 'Used', secondary: 'Reserved' }` — a
1660
+ * swatch in the bar's tone for each (`value` optional), the second striped like the reserved segment. Shown only
1661
+ * while the reserved segment is drawn; hidden from screen readers — so while it shows, the bar reads both counts
1662
+ * ("2 of 6 used, 1 reserved") even with a `valueLabel`, unless you pass `valueText`. */
1663
+ legend?: {
1664
+ value?: React$1.ReactNode;
1665
+ secondary: React$1.ReactNode;
1666
+ } | undefined;
1656
1667
  hint?: React$1.ReactNode | undefined;
1657
1668
  tone?: Tone | undefined;
1658
1669
  size?: "sm" | "md" | undefined;
package/dist/styles.css CHANGED
@@ -358,6 +358,13 @@ a.aura-icon-btn { text-decoration: none; }
358
358
  .aura-icon-btn--outline { box-sizing: border-box; border: 1px solid var(--aura-button-secondary-border); } /* 5.44 (Chamber-OS 149): reads as a button beside outlined ones */
359
359
  .aura-icon-btn--danger:hover { background: var(--aura-alert-danger-bg); }
360
360
  .aura-icon-btn:disabled { opacity: var(--aura-disabled-opacity); pointer-events: none; }
361
+ /* 5.65 (Chamber-OS 180): a toggle (aria-pressed="true", or the pressed prop) looks on — the selected fill and the
362
+ * accent icon — and hover still shows on top of it (an accent hairline inside). Outline toggles take an accent border.
363
+ * The focus ring is unchanged. Not inside a field: PasswordField's reveal eye (aria-pressed) stays quiet (5.30 #14).
364
+ * One class stronger than the open-menu fill, so a pressed menu trigger stays on while its menu is open. */
365
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *) { background: var(--aura-bg-selected); color: var(--aura-fg-accent); }
366
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):hover { background: var(--aura-bg-selected); box-shadow: inset 0 0 0 1px var(--aura-fg-accent); }
367
+ .aura-icon-btn--outline[aria-pressed="true"]:not(.aura-input *) { border-color: var(--aura-fg-accent); }
361
368
  .aura-icon-btn:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
362
369
  /* 5.15 (Chamber-OS 100): touchHeight — visibly 44px on phones, for buttons and icon buttons a phone design wants full size.
363
370
  * 5.24 (Chamber-OS 123): also wherever the primary pointer is coarse — a tablet at 768–1366px is a finger, not a mouse.
@@ -1578,13 +1585,19 @@ a.aura-upload__name:focus-visible { outline: var(--aura-focus-ring-width) solid
1578
1585
  .aura-progress__track { position: relative; height: 8px; border-radius: var(--aura-radius-full); background: var(--aura-progress-track); box-shadow: inset 0 0 0 1px var(--aura-progress-track-edge); overflow: hidden; }
1579
1586
  .aura-progress.is-sm .aura-progress__track { height: 4px; }
1580
1587
  .aura-progress__bar { position: absolute; inset: 0 auto 0 0; border-radius: inherit; background: var(--aura-fg-accent); transition: width var(--aura-duration-base) var(--aura-ease); }
1581
- .aura-progress--success .aura-progress__bar { background: var(--aura-fg-positive); }
1582
- .aura-progress--warning .aura-progress__bar { background: var(--aura-alert-warning-fg); }
1583
- .aura-progress--danger .aura-progress__bar { background: var(--aura-fg-danger); }
1584
- .aura-progress--neutral .aura-progress__bar { background: var(--aura-fg-secondary); }
1588
+ /* 5.64 (Chamber-OS 179): legend — a swatch per part in the bar's tone, the reserved one striped like its segment. */
1589
+ .aura-progress__legend { display: flex; flex-wrap: wrap; gap: var(--aura-space-1) var(--aura-space-4); font-size: max(12px, .75rem); line-height: 1.5; color: var(--aura-fg-secondary); }
1590
+ .aura-progress__key { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
1591
+ .aura-progress__swatch { flex: none; width: 12px; height: 8px; border-radius: 2px; background: var(--aura-fg-accent); }
1592
+ .aura-progress--success :is(.aura-progress__bar, .aura-progress__swatch) { background: var(--aura-fg-positive); }
1593
+ .aura-progress--warning :is(.aura-progress__bar, .aura-progress__swatch) { background: var(--aura-alert-warning-fg); }
1594
+ .aura-progress--danger :is(.aura-progress__bar, .aura-progress__swatch) { background: var(--aura-fg-danger); }
1595
+ .aura-progress--neutral :is(.aura-progress__bar, .aura-progress__swatch) { background: var(--aura-fg-secondary); }
1585
1596
  /* 5.15 (Chamber-OS 89): a reserved amount after the value — the same tone, striped, so it reads without colour. */
1586
1597
  .aura-progress__bar--reserved {
1587
1598
  transition: left var(--aura-duration-base) var(--aura-ease), width var(--aura-duration-base) var(--aura-ease);
1599
+ }
1600
+ .aura-progress__bar--reserved, .aura-progress__swatch--reserved {
1588
1601
  -webkit-mask-image: repeating-linear-gradient(135deg, currentColor 0 3px, transparent 3px 6px);
1589
1602
  mask-image: repeating-linear-gradient(135deg, currentColor 0 3px, transparent 3px 6px);
1590
1603
  }
@@ -2545,7 +2558,10 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
2545
2558
  .aura-switch.is-on:disabled .aura-switch__thumb { background: Canvas; }
2546
2559
  .aura-switch-row.is-disabled .aura-choice__label { color: GrayText; }
2547
2560
  .aura-progress__track, .aura-upload__bar { border: 1px solid CanvasText; }
2548
- .aura-progress__bar, .aura-upload__bar > span { background: Highlight; forced-color-adjust: none; }
2561
+ .aura-progress :is(.aura-progress__bar, .aura-progress__swatch), .aura-upload__bar > span { background: Highlight; forced-color-adjust: none; } /* every tone (5.64) */
2562
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *) { background: Highlight; color: HighlightText; forced-color-adjust: none; } /* 5.65 */
2563
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):hover { box-shadow: inset 0 0 0 1px HighlightText; }
2564
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):focus-visible { outline-color: CanvasText; }
2549
2565
  .aura-segmented__option.is-selected { outline: 2px solid Highlight; outline-offset: -2px; }
2550
2566
  .aura-tab { border-bottom-color: Canvas; }
2551
2567
  .aura-tab.is-active { border-bottom-color: Highlight; }
@@ -360,6 +360,13 @@ a.aura-icon-btn { text-decoration: none; }
360
360
  .aura-icon-btn--outline { box-sizing: border-box; border: 1px solid var(--aura-button-secondary-border); } /* 5.44 (Chamber-OS 149): reads as a button beside outlined ones */
361
361
  .aura-icon-btn--danger:hover { background: var(--aura-alert-danger-bg); }
362
362
  .aura-icon-btn:disabled { opacity: var(--aura-disabled-opacity); pointer-events: none; }
363
+ /* 5.65 (Chamber-OS 180): a toggle (aria-pressed="true", or the pressed prop) looks on — the selected fill and the
364
+ * accent icon — and hover still shows on top of it (an accent hairline inside). Outline toggles take an accent border.
365
+ * The focus ring is unchanged. Not inside a field: PasswordField's reveal eye (aria-pressed) stays quiet (5.30 #14).
366
+ * One class stronger than the open-menu fill, so a pressed menu trigger stays on while its menu is open. */
367
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *) { background: var(--aura-bg-selected); color: var(--aura-fg-accent); }
368
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):hover { background: var(--aura-bg-selected); box-shadow: inset 0 0 0 1px var(--aura-fg-accent); }
369
+ .aura-icon-btn--outline[aria-pressed="true"]:not(.aura-input *) { border-color: var(--aura-fg-accent); }
363
370
  .aura-icon-btn:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
364
371
  /* 5.15 (Chamber-OS 100): touchHeight — visibly 44px on phones, for buttons and icon buttons a phone design wants full size.
365
372
  * 5.24 (Chamber-OS 123): also wherever the primary pointer is coarse — a tablet at 768–1366px is a finger, not a mouse.
@@ -1580,13 +1587,19 @@ a.aura-upload__name:focus-visible { outline: var(--aura-focus-ring-width) solid
1580
1587
  .aura-progress__track { position: relative; height: 8px; border-radius: var(--aura-radius-full); background: var(--aura-progress-track); box-shadow: inset 0 0 0 1px var(--aura-progress-track-edge); overflow: hidden; }
1581
1588
  .aura-progress.is-sm .aura-progress__track { height: 4px; }
1582
1589
  .aura-progress__bar { position: absolute; inset: 0 auto 0 0; border-radius: inherit; background: var(--aura-fg-accent); transition: width var(--aura-duration-base) var(--aura-ease); }
1583
- .aura-progress--success .aura-progress__bar { background: var(--aura-fg-positive); }
1584
- .aura-progress--warning .aura-progress__bar { background: var(--aura-alert-warning-fg); }
1585
- .aura-progress--danger .aura-progress__bar { background: var(--aura-fg-danger); }
1586
- .aura-progress--neutral .aura-progress__bar { background: var(--aura-fg-secondary); }
1590
+ /* 5.64 (Chamber-OS 179): legend — a swatch per part in the bar's tone, the reserved one striped like its segment. */
1591
+ .aura-progress__legend { display: flex; flex-wrap: wrap; gap: var(--aura-space-1) var(--aura-space-4); font-size: max(12px, .75rem); line-height: 1.5; color: var(--aura-fg-secondary); }
1592
+ .aura-progress__key { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
1593
+ .aura-progress__swatch { flex: none; width: 12px; height: 8px; border-radius: 2px; background: var(--aura-fg-accent); }
1594
+ .aura-progress--success :is(.aura-progress__bar, .aura-progress__swatch) { background: var(--aura-fg-positive); }
1595
+ .aura-progress--warning :is(.aura-progress__bar, .aura-progress__swatch) { background: var(--aura-alert-warning-fg); }
1596
+ .aura-progress--danger :is(.aura-progress__bar, .aura-progress__swatch) { background: var(--aura-fg-danger); }
1597
+ .aura-progress--neutral :is(.aura-progress__bar, .aura-progress__swatch) { background: var(--aura-fg-secondary); }
1587
1598
  /* 5.15 (Chamber-OS 89): a reserved amount after the value — the same tone, striped, so it reads without colour. */
1588
1599
  .aura-progress__bar--reserved {
1589
1600
  transition: left var(--aura-duration-base) var(--aura-ease), width var(--aura-duration-base) var(--aura-ease);
1601
+ }
1602
+ .aura-progress__bar--reserved, .aura-progress__swatch--reserved {
1590
1603
  -webkit-mask-image: repeating-linear-gradient(135deg, currentColor 0 3px, transparent 3px 6px);
1591
1604
  mask-image: repeating-linear-gradient(135deg, currentColor 0 3px, transparent 3px 6px);
1592
1605
  }
@@ -2547,7 +2560,10 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
2547
2560
  .aura-switch.is-on:disabled .aura-switch__thumb { background: Canvas; }
2548
2561
  .aura-switch-row.is-disabled .aura-choice__label { color: GrayText; }
2549
2562
  .aura-progress__track, .aura-upload__bar { border: 1px solid CanvasText; }
2550
- .aura-progress__bar, .aura-upload__bar > span { background: Highlight; forced-color-adjust: none; }
2563
+ .aura-progress :is(.aura-progress__bar, .aura-progress__swatch), .aura-upload__bar > span { background: Highlight; forced-color-adjust: none; } /* every tone (5.64) */
2564
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *) { background: Highlight; color: HighlightText; forced-color-adjust: none; } /* 5.65 */
2565
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):hover { box-shadow: inset 0 0 0 1px HighlightText; }
2566
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):focus-visible { outline-color: CanvasText; }
2551
2567
  .aura-segmented__option.is-selected { outline: 2px solid Highlight; outline-offset: -2px; }
2552
2568
  .aura-tab { border-bottom-color: Canvas; }
2553
2569
  .aura-tab.is-active { border-bottom-color: Highlight; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.63.0",
3
+ "version": "5.65.0",
4
4
  "description": "AURA Design System — React components (Enterprise Standard, Human Creative). Thai-first: Buddhist-era dates, Thai collation.",
5
5
  "license": "MIT",
6
6
  "type": "module",