@jirawatpyk/aura-react 5.48.0 → 5.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/README.md CHANGED
@@ -186,10 +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.49 — Chamber-OS addendum 56 (#155)
190
+
191
+ - **The short-screen threshold follows the browser's text size**: the height at which bottom bars stop pinning (5.48, #154) is `30rem`, not `480px`. In a media query `rem` is the browser's default font size (Chrome, Edge, Firefox; not iOS Dynamic Type or Safari's text size), not the page's `html` font size: 480px at the default 16px (nothing changes), 720px at 24px (an iPhone SE counts as short, an 844px phone keeps the bar), 960px at 32px (an 844px phone counts as short — it holds what a 422px screen holds at 16px). There the `actionsBarBelow` actions stay in the header, an ActionBar sits at the end of its container and AppShell's top bar scrolls away, as at 400% zoom. Changing the text size on an open page re-checks it (the bar-height tokens follow). The width breakpoints stay in px.
192
+
189
193
  ## 5.48 — Chamber-OS addendum 55 (#153–154)
190
194
 
191
195
  - **The `actionsBarBelow` bar is now ActionBar's edge strip** (#153): the full width of the screen, on its bottom edge (or on a BottomNav's top edge), a top border only — no radius, no shadow — with ActionBar's inner padding (8px block, 16px start, 12px end) and the home-indicator inset inside it, as the save and bulk bars of an app built on `ActionBar position="container"` look. The page's end padding and `scroll-padding-bottom` follow the new height. The layout inside is unchanged.
192
- - **Bottom bars on a short screen** (#154): on a screen 480px tall or less — 400% zoom on a desktop (320×256 CSS px), a phone held sideways — `actionsBarBelow` no longer fixes the actions to the bottom: they stay in the header's own row (laid out by `actionsFullWidthBelow` if set), with no status line, page-end space or scroll padding; and an `ActionBar` (either `position`) stops sticking and sits at the end of its container, in the flow. AppShell's top bar scrolls away with the page there too, so a field reached backwards (Shift+Tab) isn't left under it, and `--aura-shell-bar-height` is 0 meanwhile, so nothing sticky (a DataTable `stickyHeader`) leaves a gap for it. A focused control is never under a bar there (WCAG 2.4.11, 1.4.10); from 481px tall everything is as before. An ActionBar with `hidesBottomNav` still hides the BottomNav on a short screen while it sits at the end of its container. Wherever a BottomNav shows (any height), the page's `scroll-padding-bottom` now reserves its height, so a field tabbed into view stops above it.
196
+ - **Bottom bars on a short screen** (#154): on a screen 30rem tall or less — 480px at the browser's default 16px text, and since 5.49 (#155) it follows the default font size set in Chrome, Edge or Firefox (960px at 32px, 720px at 24px), so large-text users get the same room (iOS Dynamic Type and Safari's text-size controls don't change it); 400% zoom on a desktop (320×256 CSS px), a phone held sideways — `actionsBarBelow` no longer fixes the actions to the bottom: they stay in the header's own row (laid out by `actionsFullWidthBelow` if set), with no status line, page-end space or scroll padding; and an `ActionBar` (either `position`) stops sticking and sits at the end of its container, in the flow. AppShell's top bar scrolls away with the page there too, so a field reached backwards (Shift+Tab) isn't left under it, and `--aura-shell-bar-height` is 0 meanwhile, so nothing sticky (a DataTable `stickyHeader`) leaves a gap for it. A focused control is never under a bar there (WCAG 2.4.11, 1.4.10); taller than 30rem everything is as before. The width breakpoints stay in px. An ActionBar with `hidesBottomNav` still hides the BottomNav on a short screen while it sits at the end of its container. Wherever a BottomNav shows (any height), the page's `scroll-padding-bottom` now reserves its height, so a field tabbed into view stops above it.
193
197
  - **`actionsBarLook="floating"`** keeps 5.45's card (inset 16px, lifted 12px, bordered all round, rounded, with the overlay shadow) — the look of `ActionBar position="viewport"`. Only the bar's look changed; nothing else about `actionsBarBelow`.
194
198
 
195
199
  ## 5.47 — Chamber-OS addendum 54 (#152)
@@ -8333,6 +8333,7 @@ window.Aura = (() => {
8333
8333
  }
8334
8334
  const rootRef = React48.useRef(null);
8335
8335
  const barRef = React48.useRef(null);
8336
+ const probeRef = React48.useRef(null);
8336
8337
  const mergedRef = useMergedRef(ref, rootRef);
8337
8338
  const hasBar = !!(props.header || props.nav);
8338
8339
  const barH = React48.useState(null);
@@ -8362,6 +8363,7 @@ window.Aura = (() => {
8362
8363
  sync();
8363
8364
  const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(sync);
8364
8365
  if (ro) ro.observe(bar);
8366
+ if (ro && probeRef.current) ro.observe(probeRef.current);
8365
8367
  window.addEventListener("resize", sync);
8366
8368
  return function() {
8367
8369
  if (ro) ro.disconnect();
@@ -8445,7 +8447,8 @@ window.Aura = (() => {
8445
8447
  "aria-expanded": open
8446
8448
  }
8447
8449
  ) : null,
8448
- /* @__PURE__ */ React48.createElement("div", { className: "aura-shell__bar-content" }, props.header)
8450
+ /* @__PURE__ */ React48.createElement("div", { className: "aura-shell__bar-content" }, props.header),
8451
+ /* @__PURE__ */ React48.createElement("span", { className: "aura-shell__probe", "aria-hidden": "true", ref: probeRef })
8449
8452
  ) : null, /* @__PURE__ */ React48.createElement(
8450
8453
  "main",
8451
8454
  {
@@ -8315,6 +8315,7 @@ var AppShell = React48.forwardRef(function AppShell2(props, ref) {
8315
8315
  }
8316
8316
  const rootRef = React48.useRef(null);
8317
8317
  const barRef = React48.useRef(null);
8318
+ const probeRef = React48.useRef(null);
8318
8319
  const mergedRef = useMergedRef(ref, rootRef);
8319
8320
  const hasBar = !!(props.header || props.nav);
8320
8321
  const barH = React48.useState(null);
@@ -8344,6 +8345,7 @@ var AppShell = React48.forwardRef(function AppShell2(props, ref) {
8344
8345
  sync();
8345
8346
  const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(sync);
8346
8347
  if (ro) ro.observe(bar);
8348
+ if (ro && probeRef.current) ro.observe(probeRef.current);
8347
8349
  window.addEventListener("resize", sync);
8348
8350
  return function() {
8349
8351
  if (ro) ro.disconnect();
@@ -8427,7 +8429,8 @@ var AppShell = React48.forwardRef(function AppShell2(props, ref) {
8427
8429
  "aria-expanded": open
8428
8430
  }
8429
8431
  ) : null,
8430
- /* @__PURE__ */ React48.createElement("div", { className: "aura-shell__bar-content" }, props.header)
8432
+ /* @__PURE__ */ React48.createElement("div", { className: "aura-shell__bar-content" }, props.header),
8433
+ /* @__PURE__ */ React48.createElement("span", { className: "aura-shell__probe", "aria-hidden": "true", ref: probeRef })
8431
8434
  ) : null, /* @__PURE__ */ React48.createElement(
8432
8435
  "main",
8433
8436
  {
@@ -30,6 +30,7 @@ const AppShell = React.forwardRef(function AppShell2(props, ref) {
30
30
  }
31
31
  const rootRef = React.useRef(null);
32
32
  const barRef = React.useRef(null);
33
+ const probeRef = React.useRef(null);
33
34
  const mergedRef = useMergedRef(ref, rootRef);
34
35
  const hasBar = !!(props.header || props.nav);
35
36
  const barH = React.useState(null);
@@ -59,6 +60,7 @@ const AppShell = React.forwardRef(function AppShell2(props, ref) {
59
60
  sync();
60
61
  const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(sync);
61
62
  if (ro) ro.observe(bar);
63
+ if (ro && probeRef.current) ro.observe(probeRef.current);
62
64
  window.addEventListener("resize", sync);
63
65
  return function() {
64
66
  if (ro) ro.disconnect();
@@ -142,7 +144,8 @@ const AppShell = React.forwardRef(function AppShell2(props, ref) {
142
144
  "aria-expanded": open
143
145
  }
144
146
  ) : null,
145
- /* @__PURE__ */ React.createElement("div", { className: "aura-shell__bar-content" }, props.header)
147
+ /* @__PURE__ */ React.createElement("div", { className: "aura-shell__bar-content" }, props.header),
148
+ /* @__PURE__ */ React.createElement("span", { className: "aura-shell__probe", "aria-hidden": "true", ref: probeRef })
146
149
  ) : null, /* @__PURE__ */ React.createElement(
147
150
  "main",
148
151
  {
package/dist/styles.css CHANGED
@@ -1109,6 +1109,8 @@ a.aura-tab { text-decoration: none; }
1109
1109
  --aura-shell-bar-height: 56px; /* 5.14 (Chamber-OS 104): the top bar's height, for sticky offsets under it */
1110
1110
  }
1111
1111
  .aura-shell--no-bar { --aura-shell-bar-height: 0px; }
1112
+ /* 5.49 (Chamber-OS 155): AppShell watches this for changes of the browser's text size (see the 30rem queries). */
1113
+ .aura-shell__probe { position: absolute; top: 0; inset-inline-start: 0; font-size: medium; width: 1em; height: 0; overflow: hidden; visibility: hidden; pointer-events: none; }
1112
1114
  /* 5.35 (DxT Monitor 13): headerHideOnScroll — below lg the bar slides up out of view while the page scrolls down (its
1113
1115
  * shadow too); AppShell sets the bar-height token to 0 meanwhile. */
1114
1116
  .aura-shell__bar--hides { transition: transform var(--aura-duration-base) var(--aura-ease); }
@@ -1208,14 +1210,14 @@ a.aura-tab { text-decoration: none; }
1208
1210
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1209
1211
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; } /* 5.45 (Chamber-OS addendum 52): centred on a taller button */
1210
1212
  }
1211
- /* 5.48 (Chamber-OS 154): only on a screen taller than 480px — on a short one (400% zoom, a phone held sideways) the
1213
+ /* 5.48 (Chamber-OS 154): only on a screen taller than 30rem (5.49: 480px at the default text size) — on a short one (400% zoom, a phone held sideways) the
1212
1214
  * actions stay in the header's own row and the page keeps its full height.
1213
1215
  * 5.48 (Chamber-OS 153): the bar is ActionBar's edge strip (full width, on the bottom edge, top border, the safe area
1214
1216
  * inside); actionsBarLook="floating" keeps 5.45's inset card.
1215
1217
  * 5.45 (Chamber-OS 150): actionsBarBelow — the same actions become a fixed bar with a status line; the page gains its
1216
1218
  * height (--aura-page-actions-height, measured on the client) so its end and a focused field scroll clear. */
1217
1219
  .aura-page-header__status { display: none; }
1218
- @media (max-width: 639.98px) and (min-height: 480.02px) {
1220
+ @media (max-width: 639.98px) and (min-height: 30.00125rem) {
1219
1221
  .aura-page-header--actions-bar-below-sm > .aura-page-header__actions { position: fixed; z-index: var(--aura-z-bar); left: 0; right: 0; bottom: var(--aura-bottomnav-offset, 0px); box-sizing: border-box; min-height: 60px; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin: 0; padding: var(--aura-space-2) var(--aura-space-3) calc(var(--aura-space-2) + max(0px, env(safe-area-inset-bottom, 0px) - var(--aura-bottomnav-offset, 0px))) var(--aura-space-4); background: var(--aura-bg-surface); color: var(--aura-fg-primary); border: 0; border-top: 1px solid var(--aura-border-default); border-radius: 0; box-shadow: none; transition: bottom var(--aura-duration-base) var(--aura-ease); }
1220
1222
  .aura-page-header--actions-bar-below-sm.aura-page-header--actions-bar-floating > .aura-page-header__actions { left: var(--aura-space-4); right: var(--aura-space-4); bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px))); padding-bottom: var(--aura-space-2); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay); }
1221
1223
  .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > .aura-page-header__status { display: block; flex: 1 1 100%; min-width: 0; font-size: max(14px, .875rem); line-height: 1.5; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
@@ -1233,7 +1235,7 @@ a.aura-tab { text-decoration: none; }
1233
1235
  :root:has(.aura-page-header--actions-bar-below-sm) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-page-actions-space)); }
1234
1236
  :root:has(.aura-page-header--actions-bar-below-sm):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-page-actions-space); }
1235
1237
  }
1236
- @media (max-width: 767.98px) and (min-height: 480.02px) {
1238
+ @media (max-width: 767.98px) and (min-height: 30.00125rem) {
1237
1239
  .aura-page-header--actions-bar-below-md > .aura-page-header__actions { position: fixed; z-index: var(--aura-z-bar); left: 0; right: 0; bottom: var(--aura-bottomnav-offset, 0px); box-sizing: border-box; min-height: 60px; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin: 0; padding: var(--aura-space-2) var(--aura-space-3) calc(var(--aura-space-2) + max(0px, env(safe-area-inset-bottom, 0px) - var(--aura-bottomnav-offset, 0px))) var(--aura-space-4); background: var(--aura-bg-surface); color: var(--aura-fg-primary); border: 0; border-top: 1px solid var(--aura-border-default); border-radius: 0; box-shadow: none; transition: bottom var(--aura-duration-base) var(--aura-ease); }
1238
1240
  .aura-page-header--actions-bar-below-md.aura-page-header--actions-bar-floating > .aura-page-header__actions { left: var(--aura-space-4); right: var(--aura-space-4); bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px))); padding-bottom: var(--aura-space-2); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay); }
1239
1241
  .aura-page-header--actions-bar-below-md > .aura-page-header__actions > .aura-page-header__status { display: block; flex: 1 1 100%; min-width: 0; font-size: max(14px, .875rem); line-height: 1.5; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
@@ -2093,11 +2095,13 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
2093
2095
  border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay);
2094
2096
  }
2095
2097
  .aura-actionbar--container { bottom: 0; border-top: 1px solid var(--aura-border-default); }
2096
- /* 5.48 (Chamber-OS 154): on a short screen (480px or less: 400% zoom, a phone held sideways) the bar stops sticking —
2098
+ /* 5.48 (Chamber-OS 154): on a short screen (30rem or less: 400% zoom, a phone held sideways) the bar stops sticking —
2097
2099
  * it stays at the end of its container, in the flow, so it never covers a focused field (WCAG 2.4.11, 1.4.10). */
2098
- @media (max-height: 480px) { .aura-actionbar:not(.is-idle) { position: static; } }
2100
+ /* 5.49 (Chamber-OS 155): the threshold is 30rem, which in a media query is the browser's text size, not the page's:
2101
+ * 480px at the default 16px, 960px at 32px, so large text counts lines of text, not pixels. */
2102
+ @media (max-height: 30rem) { .aura-actionbar:not(.is-idle) { position: static; } }
2099
2103
  /* …and AppShell's top bar scrolls away with the page, so Shift+Tab never lands a field under it. */
2100
- @media (max-height: 480px) { .aura-shell__bar { position: static; } }
2104
+ @media (max-height: 30rem) { .aura-shell__bar { position: static; } }
2101
2105
  /* 5.48: wherever a BottomNav shows, a field scrolled into view (Tab) stops above it, not under it. */
2102
2106
  :root { scroll-padding-bottom: var(--aura-bottomnav-offset, 0px); }
2103
2107
  .aura-actionbar__inner { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2) var(--aura-space-3); min-height: 60px; box-sizing: border-box; padding-block: var(--aura-space-2); padding-inline: var(--aura-space-4) var(--aura-space-3); }
@@ -1111,6 +1111,8 @@ a.aura-tab { text-decoration: none; }
1111
1111
  --aura-shell-bar-height: 56px; /* 5.14 (Chamber-OS 104): the top bar's height, for sticky offsets under it */
1112
1112
  }
1113
1113
  .aura-shell--no-bar { --aura-shell-bar-height: 0px; }
1114
+ /* 5.49 (Chamber-OS 155): AppShell watches this for changes of the browser's text size (see the 30rem queries). */
1115
+ .aura-shell__probe { position: absolute; top: 0; inset-inline-start: 0; font-size: medium; width: 1em; height: 0; overflow: hidden; visibility: hidden; pointer-events: none; }
1114
1116
  /* 5.35 (DxT Monitor 13): headerHideOnScroll — below lg the bar slides up out of view while the page scrolls down (its
1115
1117
  * shadow too); AppShell sets the bar-height token to 0 meanwhile. */
1116
1118
  .aura-shell__bar--hides { transition: transform var(--aura-duration-base) var(--aura-ease); }
@@ -1210,14 +1212,14 @@ a.aura-tab { text-decoration: none; }
1210
1212
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1211
1213
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; } /* 5.45 (Chamber-OS addendum 52): centred on a taller button */
1212
1214
  }
1213
- /* 5.48 (Chamber-OS 154): only on a screen taller than 480px — on a short one (400% zoom, a phone held sideways) the
1215
+ /* 5.48 (Chamber-OS 154): only on a screen taller than 30rem (5.49: 480px at the default text size) — on a short one (400% zoom, a phone held sideways) the
1214
1216
  * actions stay in the header's own row and the page keeps its full height.
1215
1217
  * 5.48 (Chamber-OS 153): the bar is ActionBar's edge strip (full width, on the bottom edge, top border, the safe area
1216
1218
  * inside); actionsBarLook="floating" keeps 5.45's inset card.
1217
1219
  * 5.45 (Chamber-OS 150): actionsBarBelow — the same actions become a fixed bar with a status line; the page gains its
1218
1220
  * height (--aura-page-actions-height, measured on the client) so its end and a focused field scroll clear. */
1219
1221
  .aura-page-header__status { display: none; }
1220
- @media (max-width: 639.98px) and (min-height: 480.02px) {
1222
+ @media (max-width: 639.98px) and (min-height: 30.00125rem) {
1221
1223
  .aura-page-header--actions-bar-below-sm > .aura-page-header__actions { position: fixed; z-index: var(--aura-z-bar); left: 0; right: 0; bottom: var(--aura-bottomnav-offset, 0px); box-sizing: border-box; min-height: 60px; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin: 0; padding: var(--aura-space-2) var(--aura-space-3) calc(var(--aura-space-2) + max(0px, env(safe-area-inset-bottom, 0px) - var(--aura-bottomnav-offset, 0px))) var(--aura-space-4); background: var(--aura-bg-surface); color: var(--aura-fg-primary); border: 0; border-top: 1px solid var(--aura-border-default); border-radius: 0; box-shadow: none; transition: bottom var(--aura-duration-base) var(--aura-ease); }
1222
1224
  .aura-page-header--actions-bar-below-sm.aura-page-header--actions-bar-floating > .aura-page-header__actions { left: var(--aura-space-4); right: var(--aura-space-4); bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px))); padding-bottom: var(--aura-space-2); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay); }
1223
1225
  .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > .aura-page-header__status { display: block; flex: 1 1 100%; min-width: 0; font-size: max(14px, .875rem); line-height: 1.5; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
@@ -1235,7 +1237,7 @@ a.aura-tab { text-decoration: none; }
1235
1237
  :root:has(.aura-page-header--actions-bar-below-sm) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-page-actions-space)); }
1236
1238
  :root:has(.aura-page-header--actions-bar-below-sm):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-page-actions-space); }
1237
1239
  }
1238
- @media (max-width: 767.98px) and (min-height: 480.02px) {
1240
+ @media (max-width: 767.98px) and (min-height: 30.00125rem) {
1239
1241
  .aura-page-header--actions-bar-below-md > .aura-page-header__actions { position: fixed; z-index: var(--aura-z-bar); left: 0; right: 0; bottom: var(--aura-bottomnav-offset, 0px); box-sizing: border-box; min-height: 60px; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin: 0; padding: var(--aura-space-2) var(--aura-space-3) calc(var(--aura-space-2) + max(0px, env(safe-area-inset-bottom, 0px) - var(--aura-bottomnav-offset, 0px))) var(--aura-space-4); background: var(--aura-bg-surface); color: var(--aura-fg-primary); border: 0; border-top: 1px solid var(--aura-border-default); border-radius: 0; box-shadow: none; transition: bottom var(--aura-duration-base) var(--aura-ease); }
1240
1242
  .aura-page-header--actions-bar-below-md.aura-page-header--actions-bar-floating > .aura-page-header__actions { left: var(--aura-space-4); right: var(--aura-space-4); bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px))); padding-bottom: var(--aura-space-2); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay); }
1241
1243
  .aura-page-header--actions-bar-below-md > .aura-page-header__actions > .aura-page-header__status { display: block; flex: 1 1 100%; min-width: 0; font-size: max(14px, .875rem); line-height: 1.5; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
@@ -2095,11 +2097,13 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
2095
2097
  border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay);
2096
2098
  }
2097
2099
  .aura-actionbar--container { bottom: 0; border-top: 1px solid var(--aura-border-default); }
2098
- /* 5.48 (Chamber-OS 154): on a short screen (480px or less: 400% zoom, a phone held sideways) the bar stops sticking —
2100
+ /* 5.48 (Chamber-OS 154): on a short screen (30rem or less: 400% zoom, a phone held sideways) the bar stops sticking —
2099
2101
  * it stays at the end of its container, in the flow, so it never covers a focused field (WCAG 2.4.11, 1.4.10). */
2100
- @media (max-height: 480px) { .aura-actionbar:not(.is-idle) { position: static; } }
2102
+ /* 5.49 (Chamber-OS 155): the threshold is 30rem, which in a media query is the browser's text size, not the page's:
2103
+ * 480px at the default 16px, 960px at 32px, so large text counts lines of text, not pixels. */
2104
+ @media (max-height: 30rem) { .aura-actionbar:not(.is-idle) { position: static; } }
2101
2105
  /* …and AppShell's top bar scrolls away with the page, so Shift+Tab never lands a field under it. */
2102
- @media (max-height: 480px) { .aura-shell__bar { position: static; } }
2106
+ @media (max-height: 30rem) { .aura-shell__bar { position: static; } }
2103
2107
  /* 5.48: wherever a BottomNav shows, a field scrolled into view (Tab) stops above it, not under it. */
2104
2108
  :root { scroll-padding-bottom: var(--aura-bottomnav-offset, 0px); }
2105
2109
  .aura-actionbar__inner { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2) var(--aura-space-3); min-height: 60px; box-sizing: border-box; padding-block: var(--aura-space-2); padding-inline: var(--aura-space-4) var(--aura-space-3); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.48.0",
3
+ "version": "5.49.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",