@jirawatpyk/aura-react 5.22.0 → 5.24.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,16 @@ 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.24 — Chamber-OS addendum 26
190
+
191
+ - **`touchHeight` follows the pointer, not only the width** (item 123): Button, IconButton and the ActionBar Clear are 44px wherever the primary pointer is coarse — a tablet in portrait (768px) or landscape (1024–1366px) — as well as below 640px. With a mouse (`pointer: fine`) from 640px up nothing changes. Visible on tablets for every control that already passes `touchHeight`. A touch laptop reports its trackpad as the primary pointer (`pointer: fine`), so it keeps the compact size, as AURA's other touch rules do.
192
+
193
+ ## 5.23 — Chamber-OS addenda 23–25
194
+
195
+ - **DataTable `card: 'wide'`** (item 120): in a stacked card the column is a field on a line of its own at the card's full inner width, after the half-width fields (and before a `footer`), its label above and its text wrapping — a reason with its evidence line. The grid is unchanged (an ordinary column at its `width`).
196
+ - **Underline Tabs show their whole 2px indicator** (item 121): the list scrolls sideways, and a scroll container clips at its padding box, so the indicator pulled 1px over the list's border showed only 1px. The track is now an inset shadow inside the list and the indicator paints over its bottom row; the tabs' size is unchanged. In forced colours the track is a border again, with the indicator just above it (the list is 1px taller there).
197
+ - **ActionBar `touchHeight`** (item 122): the bar's own Clear button takes Button's `touchHeight` — 44px below 640px — to match action buttons that use it.
198
+
189
199
  ## 5.22 — Chamber-OS addendum 22
190
200
 
191
201
  - **DataTable `card: 'footer'`** (item 118): in a stacked card the column becomes the card's last row, full width, after every other cell — row actions such as "Send reminder" and a menu. A Button placed directly in the cell grows to fill the row; an IconButton or menu keeps its size. The grid is unchanged (an ordinary column at its `width`).
@@ -5298,12 +5298,13 @@ window.Aura = (() => {
5298
5298
  const part = cardPart(c, i), lv = hideLevel(c);
5299
5299
  return {
5300
5300
  "data-card": part,
5301
- "data-label": part === "field" ? c.label || void 0 : void 0,
5301
+ "data-label": part === "field" || part === "wide" ? c.label || void 0 : void 0,
5302
5302
  "data-hide": lv ? String(lv) : void 0
5303
5303
  };
5304
5304
  }
5305
5305
  const hasFields = vis.some(function(c, i) {
5306
- return cardPart(c, i) === "field";
5306
+ const p = cardPart(c, i);
5307
+ return p === "field" || p === "wide";
5307
5308
  });
5308
5309
  const hasFlex = vis.some(function(c) {
5309
5310
  return widthOf(c) == null;
@@ -7198,7 +7199,7 @@ window.Aura = (() => {
7198
7199
  props.className
7199
7200
  )
7200
7201
  },
7201
- /* @__PURE__ */ React42.createElement("div", { className: cx("aura-actionbar__inner", hasStart && "has-start") }, /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle && hasStart ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__start" }, props.start) : null, !idle ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React42.createElement(Button, { variant: "ghost", size: "sm", onClick: clear }, t.clear()) : null, props.children) : null)
7202
+ /* @__PURE__ */ React42.createElement("div", { className: cx("aura-actionbar__inner", hasStart && "has-start") }, /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle && hasStart ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__start" }, props.start) : null, !idle ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React42.createElement(Button, { variant: "ghost", size: "sm", touchHeight: props.touchHeight, onClick: clear }, t.clear()) : null, props.children) : null)
7202
7203
  );
7203
7204
  });
7204
7205
 
@@ -5280,12 +5280,13 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
5280
5280
  const part = cardPart(c, i), lv = hideLevel(c);
5281
5281
  return {
5282
5282
  "data-card": part,
5283
- "data-label": part === "field" ? c.label || void 0 : void 0,
5283
+ "data-label": part === "field" || part === "wide" ? c.label || void 0 : void 0,
5284
5284
  "data-hide": lv ? String(lv) : void 0
5285
5285
  };
5286
5286
  }
5287
5287
  const hasFields = vis.some(function(c, i) {
5288
- return cardPart(c, i) === "field";
5288
+ const p = cardPart(c, i);
5289
+ return p === "field" || p === "wide";
5289
5290
  });
5290
5291
  const hasFlex = vis.some(function(c) {
5291
5292
  return widthOf(c) == null;
@@ -7180,7 +7181,7 @@ var ActionBar = React42.forwardRef(function ActionBar2(props, ref) {
7180
7181
  props.className
7181
7182
  )
7182
7183
  },
7183
- /* @__PURE__ */ React42.createElement("div", { className: cx("aura-actionbar__inner", hasStart && "has-start") }, /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle && hasStart ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__start" }, props.start) : null, !idle ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React42.createElement(Button, { variant: "ghost", size: "sm", onClick: clear }, t.clear()) : null, props.children) : null)
7184
+ /* @__PURE__ */ React42.createElement("div", { className: cx("aura-actionbar__inner", hasStart && "has-start") }, /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle && hasStart ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__start" }, props.start) : null, !idle ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React42.createElement(Button, { variant: "ghost", size: "sm", touchHeight: props.touchHeight, onClick: clear }, t.clear()) : null, props.children) : null)
7184
7185
  );
7185
7186
  });
7186
7187
 
@@ -42,7 +42,7 @@ const ActionBar = React.forwardRef(function ActionBar2(props, ref) {
42
42
  props.className
43
43
  )
44
44
  },
45
- /* @__PURE__ */ React.createElement("div", { className: cx("aura-actionbar__inner", hasStart && "has-start") }, /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle && hasStart ? /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__start" }, props.start) : null, !idle ? /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React.createElement(Button, { variant: "ghost", size: "sm", onClick: clear }, t.clear()) : null, props.children) : null)
45
+ /* @__PURE__ */ React.createElement("div", { className: cx("aura-actionbar__inner", hasStart && "has-start") }, /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle && hasStart ? /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__start" }, props.start) : null, !idle ? /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React.createElement(Button, { variant: "ghost", size: "sm", touchHeight: props.touchHeight, onClick: clear }, t.clear()) : null, props.children) : null)
46
46
  );
47
47
  });
48
48
  export {
@@ -299,12 +299,13 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
299
299
  const part = cardPart(c, i), lv = hideLevel(c);
300
300
  return {
301
301
  "data-card": part,
302
- "data-label": part === "field" ? c.label || void 0 : void 0,
302
+ "data-label": part === "field" || part === "wide" ? c.label || void 0 : void 0,
303
303
  "data-hide": lv ? String(lv) : void 0
304
304
  };
305
305
  }
306
306
  const hasFields = vis.some(function(c, i) {
307
- return cardPart(c, i) === "field";
307
+ const p = cardPart(c, i);
308
+ return p === "field" || p === "wide";
308
309
  });
309
310
  const hasFlex = vis.some(function(c) {
310
311
  return widthOf(c) == null;
package/dist/index.d.cts CHANGED
@@ -20,8 +20,9 @@ export interface ButtonProps extends React$1.ButtonHTMLAttributes<HTMLButtonElem
20
20
  fullWidth?: boolean | undefined;
21
21
  /** `sm` is 32px with tighter padding, for toolbars, table rows and card footers. Default `md` (44px). */
22
22
  size?: ButtonSize | undefined;
23
- /** 44px tall below 640px (the viewport's), whatever `size` — a small button that phones get at full touch height
24
- * (5.15, Chamber-OS 100). From 640px up it keeps its size. */
23
+ /** 44px tall below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24), whatever
24
+ * `size` — a small button that touch screens get at full touch height (5.15, Chamber-OS 100). With a mouse from
25
+ * 640px up it keeps its size. */
25
26
  touchHeight?: boolean | undefined;
26
27
  }
27
28
  /** A link that looks like a Button: give `Button` an `href` and it renders an `<a>` (navigation, not actions). */
@@ -41,8 +42,9 @@ export interface ButtonLinkProps extends Omit<React$1.AnchorHTMLAttributes<HTMLA
41
42
  fullWidth?: boolean | undefined;
42
43
  /** `sm` is 32px with tighter padding. Default `md` (44px). */
43
44
  size?: ButtonSize | undefined;
44
- /** 44px tall below 640px (the viewport's), whatever `size` — a small button that phones get at full touch height
45
- * (5.15, Chamber-OS 100). From 640px up it keeps its size. */
45
+ /** 44px tall below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24), whatever
46
+ * `size` — a small button that touch screens get at full touch height (5.15, Chamber-OS 100). With a mouse from
47
+ * 640px up it keeps its size. */
46
48
  touchHeight?: boolean | undefined;
47
49
  /** A router's link to render instead of `<a>`, e.g. `Link` from `next/link` (client-side navigation). It gets `href`, `className`, the children and the ref. */
48
50
  linkComponent?: React$1.ElementType | undefined;
@@ -108,8 +110,10 @@ export interface DataTableColumn<Row extends Record<string, any> = Record<string
108
110
  * make it the card's title or the pill beside it (instead of the first column / first pill column), `'field'` a
109
111
  * label/value field. `'footer'` (5.22, Chamber-OS 118) makes it the card's last row, full width — row actions
110
112
  * such as "Send reminder" and a menu: a Button placed directly in the cell grows to fill the row, an IconButton or
111
- * menu keeps its size. Default: today's rule. The grid is unchanged by any of them. */
112
- card?: "hide" | "field" | "title" | "pill" | "footer" | undefined;
113
+ * menu keeps its size. `'wide'` (5.23, Chamber-OS 120) is a field on a line of its own at the card's full width,
114
+ * after the half-width fields (in column order; `cardOrder` doesn't move it), its label above and its text wrapping —
115
+ * a reason with its evidence. Default: today's rule. The grid is unchanged by any of them. */
116
+ card?: "hide" | "field" | "title" | "pill" | "footer" | "wide" | undefined;
113
117
  /** The order of fields in a stacked card (5.13), lowest first; the grid's column order is unchanged. Fields
114
118
  * without one sort by their column index (0-based). Screen readers and arrow keys follow the grid's order. */
115
119
  cardOrder?: number | undefined;
@@ -319,8 +323,8 @@ export interface IconButtonProps extends React$1.ButtonHTMLAttributes<HTMLButton
319
323
  label: string;
320
324
  /** Icon size. Default `sm` (16). */
321
325
  size?: "sm" | "md" | undefined;
322
- /** 44×44 below 640px (the viewport's) instead of 32×32 — a phone sheet's close button, a card's ⋯ trigger
323
- * (5.15, Chamber-OS 100). */
326
+ /** 44×44 instead of 32×32 below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24) —
327
+ * a phone sheet's close button, a card's ⋯ trigger (5.15, Chamber-OS 100). */
324
328
  touchHeight?: boolean | undefined;
325
329
  }
326
330
  export interface MenuItem {
@@ -1072,7 +1076,7 @@ export interface DrawerProps extends Pick<React$1.HTMLAttributes<HTMLDivElement>
1072
1076
  * built-in "Close" in the provider's language. (5.9) */
1073
1077
  closeLabel?: string | undefined;
1074
1078
  /** Attributes for the close button, e.g. `{ 'data-testid': 'pay-sheet-close' }` (5.9), or `touchHeight: true` for a
1075
- * 44px close button on phones (5.15). */
1079
+ * 44px close button on phones and tablets (5.15, 5.24). */
1076
1080
  closeProps?: (ButtonAttributes & {
1077
1081
  touchHeight?: boolean | undefined;
1078
1082
  }) | undefined;
@@ -1201,6 +1205,9 @@ export interface ActionBarProps {
1201
1205
  selected?: number | undefined;
1202
1206
  /** Adds a "Clear" button next to the count. */
1203
1207
  onClearSelection?: (() => void) | undefined;
1208
+ /** 5.23 (Chamber-OS 122): the bar's own Clear button takes Button's `touchHeight` — 44px below 640px or on a
1209
+ * coarse pointer — to match action buttons that use it. */
1210
+ touchHeight?: boolean | undefined;
1204
1211
  /** Name of the region. Default "Actions". */
1205
1212
  label?: string | undefined;
1206
1213
  className?: string | undefined;
package/dist/index.d.ts CHANGED
@@ -20,8 +20,9 @@ export interface ButtonProps extends React$1.ButtonHTMLAttributes<HTMLButtonElem
20
20
  fullWidth?: boolean | undefined;
21
21
  /** `sm` is 32px with tighter padding, for toolbars, table rows and card footers. Default `md` (44px). */
22
22
  size?: ButtonSize | undefined;
23
- /** 44px tall below 640px (the viewport's), whatever `size` — a small button that phones get at full touch height
24
- * (5.15, Chamber-OS 100). From 640px up it keeps its size. */
23
+ /** 44px tall below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24), whatever
24
+ * `size` — a small button that touch screens get at full touch height (5.15, Chamber-OS 100). With a mouse from
25
+ * 640px up it keeps its size. */
25
26
  touchHeight?: boolean | undefined;
26
27
  }
27
28
  /** A link that looks like a Button: give `Button` an `href` and it renders an `<a>` (navigation, not actions). */
@@ -41,8 +42,9 @@ export interface ButtonLinkProps extends Omit<React$1.AnchorHTMLAttributes<HTMLA
41
42
  fullWidth?: boolean | undefined;
42
43
  /** `sm` is 32px with tighter padding. Default `md` (44px). */
43
44
  size?: ButtonSize | undefined;
44
- /** 44px tall below 640px (the viewport's), whatever `size` — a small button that phones get at full touch height
45
- * (5.15, Chamber-OS 100). From 640px up it keeps its size. */
45
+ /** 44px tall below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24), whatever
46
+ * `size` — a small button that touch screens get at full touch height (5.15, Chamber-OS 100). With a mouse from
47
+ * 640px up it keeps its size. */
46
48
  touchHeight?: boolean | undefined;
47
49
  /** A router's link to render instead of `<a>`, e.g. `Link` from `next/link` (client-side navigation). It gets `href`, `className`, the children and the ref. */
48
50
  linkComponent?: React$1.ElementType | undefined;
@@ -108,8 +110,10 @@ export interface DataTableColumn<Row extends Record<string, any> = Record<string
108
110
  * make it the card's title or the pill beside it (instead of the first column / first pill column), `'field'` a
109
111
  * label/value field. `'footer'` (5.22, Chamber-OS 118) makes it the card's last row, full width — row actions
110
112
  * such as "Send reminder" and a menu: a Button placed directly in the cell grows to fill the row, an IconButton or
111
- * menu keeps its size. Default: today's rule. The grid is unchanged by any of them. */
112
- card?: "hide" | "field" | "title" | "pill" | "footer" | undefined;
113
+ * menu keeps its size. `'wide'` (5.23, Chamber-OS 120) is a field on a line of its own at the card's full width,
114
+ * after the half-width fields (in column order; `cardOrder` doesn't move it), its label above and its text wrapping —
115
+ * a reason with its evidence. Default: today's rule. The grid is unchanged by any of them. */
116
+ card?: "hide" | "field" | "title" | "pill" | "footer" | "wide" | undefined;
113
117
  /** The order of fields in a stacked card (5.13), lowest first; the grid's column order is unchanged. Fields
114
118
  * without one sort by their column index (0-based). Screen readers and arrow keys follow the grid's order. */
115
119
  cardOrder?: number | undefined;
@@ -319,8 +323,8 @@ export interface IconButtonProps extends React$1.ButtonHTMLAttributes<HTMLButton
319
323
  label: string;
320
324
  /** Icon size. Default `sm` (16). */
321
325
  size?: "sm" | "md" | undefined;
322
- /** 44×44 below 640px (the viewport's) instead of 32×32 — a phone sheet's close button, a card's ⋯ trigger
323
- * (5.15, Chamber-OS 100). */
326
+ /** 44×44 instead of 32×32 below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24) —
327
+ * a phone sheet's close button, a card's ⋯ trigger (5.15, Chamber-OS 100). */
324
328
  touchHeight?: boolean | undefined;
325
329
  }
326
330
  export interface MenuItem {
@@ -1072,7 +1076,7 @@ export interface DrawerProps extends Pick<React$1.HTMLAttributes<HTMLDivElement>
1072
1076
  * built-in "Close" in the provider's language. (5.9) */
1073
1077
  closeLabel?: string | undefined;
1074
1078
  /** Attributes for the close button, e.g. `{ 'data-testid': 'pay-sheet-close' }` (5.9), or `touchHeight: true` for a
1075
- * 44px close button on phones (5.15). */
1079
+ * 44px close button on phones and tablets (5.15, 5.24). */
1076
1080
  closeProps?: (ButtonAttributes & {
1077
1081
  touchHeight?: boolean | undefined;
1078
1082
  }) | undefined;
@@ -1201,6 +1205,9 @@ export interface ActionBarProps {
1201
1205
  selected?: number | undefined;
1202
1206
  /** Adds a "Clear" button next to the count. */
1203
1207
  onClearSelection?: (() => void) | undefined;
1208
+ /** 5.23 (Chamber-OS 122): the bar's own Clear button takes Button's `touchHeight` — 44px below 640px or on a
1209
+ * coarse pointer — to match action buttons that use it. */
1210
+ touchHeight?: boolean | undefined;
1204
1211
  /** Name of the region. Default "Actions". */
1205
1212
  label?: string | undefined;
1206
1213
  className?: string | undefined;
@@ -20,8 +20,9 @@ export interface ButtonProps extends React$1.ButtonHTMLAttributes<HTMLButtonElem
20
20
  fullWidth?: boolean | undefined;
21
21
  /** `sm` is 32px with tighter padding, for toolbars, table rows and card footers. Default `md` (44px). */
22
22
  size?: ButtonSize | undefined;
23
- /** 44px tall below 640px (the viewport's), whatever `size` — a small button that phones get at full touch height
24
- * (5.15, Chamber-OS 100). From 640px up it keeps its size. */
23
+ /** 44px tall below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24), whatever
24
+ * `size` — a small button that touch screens get at full touch height (5.15, Chamber-OS 100). With a mouse from
25
+ * 640px up it keeps its size. */
25
26
  touchHeight?: boolean | undefined;
26
27
  }
27
28
  /** An AURA icon name, or any icon element (e.g. `<Building />` from lucide-react). AURA sizes it and hides it from screen readers. */
@@ -20,8 +20,9 @@ export interface ButtonProps extends React$1.ButtonHTMLAttributes<HTMLButtonElem
20
20
  fullWidth?: boolean | undefined;
21
21
  /** `sm` is 32px with tighter padding, for toolbars, table rows and card footers. Default `md` (44px). */
22
22
  size?: ButtonSize | undefined;
23
- /** 44px tall below 640px (the viewport's), whatever `size` — a small button that phones get at full touch height
24
- * (5.15, Chamber-OS 100). From 640px up it keeps its size. */
23
+ /** 44px tall below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24), whatever
24
+ * `size` — a small button that touch screens get at full touch height (5.15, Chamber-OS 100). With a mouse from
25
+ * 640px up it keeps its size. */
25
26
  touchHeight?: boolean | undefined;
26
27
  }
27
28
  /** An AURA icon name, or any icon element (e.g. `<Building />` from lucide-react). AURA sizes it and hides it from screen readers. */
package/dist/styles.css CHANGED
@@ -312,8 +312,10 @@ a.aura-icon-btn { text-decoration: none; }
312
312
  .aura-icon-btn--danger:hover { background: var(--aura-alert-danger-bg); }
313
313
  .aura-icon-btn:disabled { opacity: var(--aura-disabled-opacity); pointer-events: none; }
314
314
  .aura-icon-btn:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
315
- /* 5.15 (Chamber-OS 100): touchHeight — visibly 44px on phones, for buttons and icon buttons a phone design wants full size. */
316
- @media (max-width: 639.98px) {
315
+ /* 5.15 (Chamber-OS 100): touchHeight — visibly 44px on phones, for buttons and icon buttons a phone design wants full size.
316
+ * 5.24 (Chamber-OS 123): also wherever the primary pointer is coarse — a tablet at 768–1366px is a finger, not a mouse.
317
+ * A mouse on a wide screen (pointer: fine) keeps the compact size. */
318
+ @media (max-width: 639.98px), (pointer: coarse) {
317
319
  .aura-btn.aura-btn--touch { height: var(--aura-touch-target); }
318
320
  .aura-btn.aura-btn--touch.aura-btn--full { height: auto; min-height: var(--aura-touch-target); }
319
321
  .aura-icon-btn.aura-icon-btn--touch { width: var(--aura-touch-target); height: var(--aura-touch-target); }
@@ -669,10 +671,13 @@ a.aura-icon-btn { text-decoration: none; }
669
671
 
670
672
  /* ---------- Tabs ---------- */
671
673
  .aura-tabs { font-family: var(--font-sans); }
672
- .aura-tabs__list { display: flex; gap: var(--aura-space-6); border-bottom: 1px solid var(--aura-border-default); overflow-x: auto; scrollbar-width: none; }
674
+ /* 5.23 (Chamber-OS 121): the 1px track is an inset shadow inside the list's padding box, and the active tab's 2px
675
+ * indicator paints over its bottom row. The list scrolls sideways (overflow-x), and a scroll container clips at its
676
+ * padding box: an indicator pulled 1px over a border (as up to 5.22) showed only half its height. Same box height. */
677
+ .aura-tabs__list { display: flex; gap: var(--aura-space-6); box-shadow: inset 0 -1px 0 var(--aura-border-default); overflow-x: auto; scrollbar-width: none; }
673
678
  .aura-tab {
674
679
  position: relative; display: inline-flex; align-items: center; gap: var(--aura-space-2); flex: none;
675
- height: var(--aura-input-height); padding: 0; margin-bottom: -1px;
680
+ height: var(--aura-input-height); padding: 0;
676
681
  border: 0; border-bottom: 2px solid transparent; background: transparent;
677
682
  color: var(--aura-fg-secondary); font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
678
683
  transition: color var(--aura-duration-fast) var(--aura-ease), border-color var(--aura-duration-fast) var(--aura-ease);
@@ -1335,9 +1340,8 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1335
1340
  * ring is drawn inside the pill, so neither the scrolling list (many tabs on a phone) nor the next pill can cover it;
1336
1341
  * full-width tabs share the track but never shrink below their label (the track scrolls instead). The phone rule's
1337
1342
  * wider tab gap doesn't apply. */
1338
- .aura-tabs--segmented .aura-tabs__list.aura-segmented { gap: 2px; }
1343
+ .aura-tabs--segmented .aura-tabs__list.aura-segmented { gap: 2px; box-shadow: none; }
1339
1344
  .aura-tabs--segmented .aura-tabs__list.aura-segmented.is-full .aura-tab { min-width: max-content; }
1340
- .aura-tabs--segmented .aura-tab.aura-segmented__option { margin-bottom: 0; }
1341
1345
  /* 5.15 (Chamber-OS 90): underline tabs sharing the width, always or below a breakpoint; the segmented track below one. */
1342
1346
  .aura-tabs__list.is-fill { gap: 0; }
1343
1347
  .aura-tabs__list.is-fill > .aura-tab { flex: 1 1 0; min-width: max-content; justify-content: center; padding: 0 var(--aura-space-3); }
@@ -1861,6 +1865,8 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1861
1865
  .aura-table__row > .aura-table__sel { align-self: flex-start; margin-top: 2px; }
1862
1866
  /* Actions top-right sit on that first line too (a 32px button centred on 20px, the same 24px footprint as before). */
1863
1867
  .aura-table__td[data-card='actions'] { align-self: flex-start; margin-top: calc(-1 * var(--aura-space-1) - 2px); margin-bottom: -2px; }
1868
+ /* 5.23 (Chamber-OS 120): card: 'wide' — a field on its own full-width line after the half-width ones, wrapping. */
1869
+ .aura-table__td[data-card='wide'] { order: 90; flex: 0 0 100%; white-space: normal; overflow: visible; overflow-wrap: anywhere; }
1864
1870
  /* 5.22 (Chamber-OS 118): card: 'footer' — the card's last row, full width; a Button in it grows, an IconButton or a
1865
1871
  * menu keeps its size. */
1866
1872
  .aura-table__td[data-card='footer'] {
@@ -1901,6 +1907,8 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1901
1907
  .aura-segmented__option.is-selected { outline: 2px solid Highlight; outline-offset: -2px; }
1902
1908
  .aura-tab { border-bottom-color: Canvas; }
1903
1909
  .aura-tab.is-active { border-bottom-color: Highlight; }
1910
+ /* Shadows are dropped in forced colours: the track is a real border again, the indicator just above it. */
1911
+ .aura-tabs__list:not(.aura-segmented) { border-bottom: 1px solid CanvasText; }
1904
1912
  /* 5.10: segmented tabs mark the selection with a border and focus with a dashed ring inside it, so a focused tab
1905
1913
  * and the selected one never look alike (manual activation moves focus without selecting). */
1906
1914
  .aura-tabs--segmented .aura-tab.aura-segmented__option.is-selected { outline: none; border: 2px solid Highlight; }
@@ -314,8 +314,10 @@ a.aura-icon-btn { text-decoration: none; }
314
314
  .aura-icon-btn--danger:hover { background: var(--aura-alert-danger-bg); }
315
315
  .aura-icon-btn:disabled { opacity: var(--aura-disabled-opacity); pointer-events: none; }
316
316
  .aura-icon-btn:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
317
- /* 5.15 (Chamber-OS 100): touchHeight — visibly 44px on phones, for buttons and icon buttons a phone design wants full size. */
318
- @media (max-width: 639.98px) {
317
+ /* 5.15 (Chamber-OS 100): touchHeight — visibly 44px on phones, for buttons and icon buttons a phone design wants full size.
318
+ * 5.24 (Chamber-OS 123): also wherever the primary pointer is coarse — a tablet at 768–1366px is a finger, not a mouse.
319
+ * A mouse on a wide screen (pointer: fine) keeps the compact size. */
320
+ @media (max-width: 639.98px), (pointer: coarse) {
319
321
  .aura-btn.aura-btn--touch { height: var(--aura-touch-target); }
320
322
  .aura-btn.aura-btn--touch.aura-btn--full { height: auto; min-height: var(--aura-touch-target); }
321
323
  .aura-icon-btn.aura-icon-btn--touch { width: var(--aura-touch-target); height: var(--aura-touch-target); }
@@ -671,10 +673,13 @@ a.aura-icon-btn { text-decoration: none; }
671
673
 
672
674
  /* ---------- Tabs ---------- */
673
675
  .aura-tabs { font-family: var(--font-sans); }
674
- .aura-tabs__list { display: flex; gap: var(--aura-space-6); border-bottom: 1px solid var(--aura-border-default); overflow-x: auto; scrollbar-width: none; }
676
+ /* 5.23 (Chamber-OS 121): the 1px track is an inset shadow inside the list's padding box, and the active tab's 2px
677
+ * indicator paints over its bottom row. The list scrolls sideways (overflow-x), and a scroll container clips at its
678
+ * padding box: an indicator pulled 1px over a border (as up to 5.22) showed only half its height. Same box height. */
679
+ .aura-tabs__list { display: flex; gap: var(--aura-space-6); box-shadow: inset 0 -1px 0 var(--aura-border-default); overflow-x: auto; scrollbar-width: none; }
675
680
  .aura-tab {
676
681
  position: relative; display: inline-flex; align-items: center; gap: var(--aura-space-2); flex: none;
677
- height: var(--aura-input-height); padding: 0; margin-bottom: -1px;
682
+ height: var(--aura-input-height); padding: 0;
678
683
  border: 0; border-bottom: 2px solid transparent; background: transparent;
679
684
  color: var(--aura-fg-secondary); font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
680
685
  transition: color var(--aura-duration-fast) var(--aura-ease), border-color var(--aura-duration-fast) var(--aura-ease);
@@ -1337,9 +1342,8 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1337
1342
  * ring is drawn inside the pill, so neither the scrolling list (many tabs on a phone) nor the next pill can cover it;
1338
1343
  * full-width tabs share the track but never shrink below their label (the track scrolls instead). The phone rule's
1339
1344
  * wider tab gap doesn't apply. */
1340
- .aura-tabs--segmented .aura-tabs__list.aura-segmented { gap: 2px; }
1345
+ .aura-tabs--segmented .aura-tabs__list.aura-segmented { gap: 2px; box-shadow: none; }
1341
1346
  .aura-tabs--segmented .aura-tabs__list.aura-segmented.is-full .aura-tab { min-width: max-content; }
1342
- .aura-tabs--segmented .aura-tab.aura-segmented__option { margin-bottom: 0; }
1343
1347
  /* 5.15 (Chamber-OS 90): underline tabs sharing the width, always or below a breakpoint; the segmented track below one. */
1344
1348
  .aura-tabs__list.is-fill { gap: 0; }
1345
1349
  .aura-tabs__list.is-fill > .aura-tab { flex: 1 1 0; min-width: max-content; justify-content: center; padding: 0 var(--aura-space-3); }
@@ -1863,6 +1867,8 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1863
1867
  .aura-table__row > .aura-table__sel { align-self: flex-start; margin-top: 2px; }
1864
1868
  /* Actions top-right sit on that first line too (a 32px button centred on 20px, the same 24px footprint as before). */
1865
1869
  .aura-table__td[data-card='actions'] { align-self: flex-start; margin-top: calc(-1 * var(--aura-space-1) - 2px); margin-bottom: -2px; }
1870
+ /* 5.23 (Chamber-OS 120): card: 'wide' — a field on its own full-width line after the half-width ones, wrapping. */
1871
+ .aura-table__td[data-card='wide'] { order: 90; flex: 0 0 100%; white-space: normal; overflow: visible; overflow-wrap: anywhere; }
1866
1872
  /* 5.22 (Chamber-OS 118): card: 'footer' — the card's last row, full width; a Button in it grows, an IconButton or a
1867
1873
  * menu keeps its size. */
1868
1874
  .aura-table__td[data-card='footer'] {
@@ -1903,6 +1909,8 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1903
1909
  .aura-segmented__option.is-selected { outline: 2px solid Highlight; outline-offset: -2px; }
1904
1910
  .aura-tab { border-bottom-color: Canvas; }
1905
1911
  .aura-tab.is-active { border-bottom-color: Highlight; }
1912
+ /* Shadows are dropped in forced colours: the track is a real border again, the indicator just above it. */
1913
+ .aura-tabs__list:not(.aura-segmented) { border-bottom: 1px solid CanvasText; }
1906
1914
  /* 5.10: segmented tabs mark the selection with a border and focus with a dashed ring inside it, so a focused tab
1907
1915
  * and the selected one never look alike (manual activation moves focus without selecting). */
1908
1916
  .aura-tabs--segmented .aura-tab.aura-segmented__option.is-selected { outline: none; border: 2px solid Highlight; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.22.0",
3
+ "version": "5.24.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",