@jirawatpyk/aura-react 5.40.0 → 5.41.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,13 @@ 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.41 — DxT Monitor requests 19–22
190
+
191
+ - **No menu button on a page with a back arrow** (request 19): put `data-aura-hide-menubutton` on any element of the page (as with `data-aura-hide-bottomnav`) and AppShell's phone bar drops its menu button, giving the title its room (a shell with no `header` then has no bar on phones). The drawer stays reachable from pages without the mark. A browser without `:has()` keeps the button.
192
+ - **PageHeader `titleHideBelow`** (request 20): `'sm' | 'md' | 'lg'` — below that width the title is visually hidden but stays the page's heading for screen readers, and the breadcrumb and eyebrow are hidden; the meta line then starts the header, or the actions when there is no meta (with neither, the header takes no room). For phone layouts that show the title in the top bar. Stateless, `/server` too.
193
+ - **Menu links that open a new tab say so** (request 21): a Menu or DropdownMenu item with `href` and `target="_blank"` is named "Visit site (opens in a new tab)" — the words are visually hidden, after the label, in the locale's language (`opensInNewTab` in the strings: เปิดในแท็บใหม่, öppnas i en ny flik). A custom `strings` pack without the key falls back to the built-in words. Other links you give a `target` (Breadcrumb, Tabs, DataTable rows) don't add it yet; give their label the words yourself.
194
+ - **Menu triggers look open while their menu shows** (request 22): an IconButton, secondary or ghost Button with `aria-haspopup` and `aria-expanded="true"` (DropdownMenu, Popover and Dialog triggers) keeps its hover fill. A disclosure button of your own (`aria-expanded` without `aria-haspopup`) keeps its plain look.
195
+
189
196
  ## 5.40 — Chamber-OS addendum 48
190
197
 
191
198
  - **Type follows the browser's default font size** (#145, WCAG 1.4.4). Every font size and px line height in `styles.css`, the `.aura-text-*` classes and `--aura-input-font-size` is now `max(<px>, <rem>)` — for example `max(13px, .8125rem)`. At the default 16px root nothing changes. When someone raises the browser's default font size (Settings → Font size, not page zoom), AURA's text grows with the app's own: at 32px a card's description, a Switch's description and a table cell are twice the size. Spacing, borders and control heights stay in px; boxes that hold text grow where they already could (fields, cards, rows with `rowHeight="auto"`), and one-line controls keep their height with larger text inside.
@@ -950,6 +950,7 @@ window.Aura = (() => {
950
950
  statusMaintenance: "\u0E1B\u0E34\u0E14\u0E1B\u0E23\u0E31\u0E1A\u0E1B\u0E23\u0E38\u0E07",
951
951
  statusOk: "\u0E1B\u0E01\u0E15\u0E34",
952
952
  statusUnknown: "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
953
+ opensInNewTab: "\u0E40\u0E1B\u0E34\u0E14\u0E43\u0E19\u0E41\u0E17\u0E47\u0E1A\u0E43\u0E2B\u0E21\u0E48",
953
954
  accepts: function(list, max) {
954
955
  return [list, max && "\u0E44\u0E21\u0E48\u0E40\u0E01\u0E34\u0E19 " + max + " \u0E15\u0E48\u0E2D\u0E44\u0E1F\u0E25\u0E4C"].filter(Boolean).join(" \xB7 ");
955
956
  }
@@ -1086,6 +1087,7 @@ window.Aura = (() => {
1086
1087
  statusMaintenance: "Underh\xE5ll",
1087
1088
  statusOk: "OK",
1088
1089
  statusUnknown: "Ingen data",
1090
+ opensInNewTab: "\xF6ppnas i en ny flik",
1089
1091
  accepts: function(list, max) {
1090
1092
  return [list, max && "h\xF6gst " + max + " per fil"].filter(Boolean).join(", ");
1091
1093
  }
@@ -1223,6 +1225,7 @@ window.Aura = (() => {
1223
1225
  statusMaintenance: "Maintenance",
1224
1226
  statusOk: "OK",
1225
1227
  statusUnknown: "No data",
1228
+ opensInNewTab: "opens in a new tab",
1226
1229
  accepts: function(list, max) {
1227
1230
  return [list, max && "up to " + max + " each"].filter(Boolean).join(", ");
1228
1231
  }
@@ -1624,6 +1627,7 @@ window.Aura = (() => {
1624
1627
  const headerId = uid(), itemId = uid();
1625
1628
  const hasHeader = props.header != null && props.header !== false && props.header !== "";
1626
1629
  const Link = useLinkComponent(props.linkComponent);
1630
+ const t = useStrings();
1627
1631
  function place2() {
1628
1632
  const a = props.anchor, m = own.current;
1629
1633
  if (!a || !m) return;
@@ -1750,6 +1754,8 @@ window.Aura = (() => {
1750
1754
  if (reasonId)
1751
1755
  body[2] = /* Hidden from the name (it would be read twice); aria-describedby still reads it. */
1752
1756
  /* @__PURE__ */ React9.createElement("span", { key: "h", id: reasonId, className: "aura-menu__hint aura-menu__reason", "aria-hidden": true }, it.disabledReason);
1757
+ if (it.href && !it.disabled && it.target === "_blank")
1758
+ body[1] = /* @__PURE__ */ React9.createElement("span", { key: "t", className: "aura-menu__label" }, it.label, /* @__PURE__ */ React9.createElement("span", { className: "aura-sr-only" }, " (" + t.opensInNewTab + ")"));
1753
1759
  if (it.href && !it.disabled)
1754
1760
  return /* @__PURE__ */ React9.createElement(
1755
1761
  Link,
@@ -7698,6 +7704,8 @@ window.Aura = (() => {
7698
7704
  });
7699
7705
  const level = props.headingLevel || 1;
7700
7706
  const below2 = props.actionsFullWidthBelow;
7707
+ const hide2 = props.titleHideBelow;
7708
+ const hasMeta = props.meta != null && props.meta !== false;
7701
7709
  return h8(
7702
7710
  "div",
7703
7711
  Object.assign(attrs2, {
@@ -7705,6 +7713,8 @@ window.Aura = (() => {
7705
7713
  className: cx(
7706
7714
  "aura-page-header",
7707
7715
  (below2 === "sm" || below2 === "md" || below2 === "lg") && "aura-page-header--actions-full-below-" + below2,
7716
+ (hide2 === "sm" || hide2 === "md" || hide2 === "lg") && "aura-page-header--title-hide-below-" + hide2,
7717
+ (hide2 === "sm" || hide2 === "md" || hide2 === "lg") && !hasMeta && "has-no-meta",
7708
7718
  props.className
7709
7719
  ),
7710
7720
  style: props.style
@@ -8183,6 +8193,7 @@ window.Aura = (() => {
8183
8193
  className: cx(
8184
8194
  "aura-shell__bar",
8185
8195
  (!props.header || props.headerHideFrom === "lg") && "aura-shell__bar--menu-only",
8196
+ !props.header && "aura-shell__bar--no-header",
8186
8197
  props.headerHideOnScroll && "aura-shell__bar--hides",
8187
8198
  away && "is-away"
8188
8199
  )
@@ -932,6 +932,7 @@ var th = {
932
932
  statusMaintenance: "\u0E1B\u0E34\u0E14\u0E1B\u0E23\u0E31\u0E1A\u0E1B\u0E23\u0E38\u0E07",
933
933
  statusOk: "\u0E1B\u0E01\u0E15\u0E34",
934
934
  statusUnknown: "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
935
+ opensInNewTab: "\u0E40\u0E1B\u0E34\u0E14\u0E43\u0E19\u0E41\u0E17\u0E47\u0E1A\u0E43\u0E2B\u0E21\u0E48",
935
936
  accepts: function(list, max) {
936
937
  return [list, max && "\u0E44\u0E21\u0E48\u0E40\u0E01\u0E34\u0E19 " + max + " \u0E15\u0E48\u0E2D\u0E44\u0E1F\u0E25\u0E4C"].filter(Boolean).join(" \xB7 ");
937
938
  }
@@ -1068,6 +1069,7 @@ var sv = {
1068
1069
  statusMaintenance: "Underh\xE5ll",
1069
1070
  statusOk: "OK",
1070
1071
  statusUnknown: "Ingen data",
1072
+ opensInNewTab: "\xF6ppnas i en ny flik",
1071
1073
  accepts: function(list, max) {
1072
1074
  return [list, max && "h\xF6gst " + max + " per fil"].filter(Boolean).join(", ");
1073
1075
  }
@@ -1205,6 +1207,7 @@ var STRINGS = {
1205
1207
  statusMaintenance: "Maintenance",
1206
1208
  statusOk: "OK",
1207
1209
  statusUnknown: "No data",
1210
+ opensInNewTab: "opens in a new tab",
1208
1211
  accepts: function(list, max) {
1209
1212
  return [list, max && "up to " + max + " each"].filter(Boolean).join(", ");
1210
1213
  }
@@ -1606,6 +1609,7 @@ var Menu = React9.forwardRef(function Menu2(props, ref) {
1606
1609
  const headerId = uid(), itemId = uid();
1607
1610
  const hasHeader = props.header != null && props.header !== false && props.header !== "";
1608
1611
  const Link = useLinkComponent(props.linkComponent);
1612
+ const t = useStrings();
1609
1613
  function place2() {
1610
1614
  const a = props.anchor, m = own.current;
1611
1615
  if (!a || !m) return;
@@ -1732,6 +1736,8 @@ var Menu = React9.forwardRef(function Menu2(props, ref) {
1732
1736
  if (reasonId)
1733
1737
  body[2] = /* Hidden from the name (it would be read twice); aria-describedby still reads it. */
1734
1738
  /* @__PURE__ */ React9.createElement("span", { key: "h", id: reasonId, className: "aura-menu__hint aura-menu__reason", "aria-hidden": true }, it.disabledReason);
1739
+ if (it.href && !it.disabled && it.target === "_blank")
1740
+ body[1] = /* @__PURE__ */ React9.createElement("span", { key: "t", className: "aura-menu__label" }, it.label, /* @__PURE__ */ React9.createElement("span", { className: "aura-sr-only" }, " (" + t.opensInNewTab + ")"));
1735
1741
  if (it.href && !it.disabled)
1736
1742
  return /* @__PURE__ */ React9.createElement(
1737
1743
  Link,
@@ -7680,6 +7686,8 @@ var PageHeader = React43.forwardRef(function PageHeader2(props, ref) {
7680
7686
  });
7681
7687
  const level = props.headingLevel || 1;
7682
7688
  const below2 = props.actionsFullWidthBelow;
7689
+ const hide2 = props.titleHideBelow;
7690
+ const hasMeta = props.meta != null && props.meta !== false;
7683
7691
  return h8(
7684
7692
  "div",
7685
7693
  Object.assign(attrs2, {
@@ -7687,6 +7695,8 @@ var PageHeader = React43.forwardRef(function PageHeader2(props, ref) {
7687
7695
  className: cx(
7688
7696
  "aura-page-header",
7689
7697
  (below2 === "sm" || below2 === "md" || below2 === "lg") && "aura-page-header--actions-full-below-" + below2,
7698
+ (hide2 === "sm" || hide2 === "md" || hide2 === "lg") && "aura-page-header--title-hide-below-" + hide2,
7699
+ (hide2 === "sm" || hide2 === "md" || hide2 === "lg") && !hasMeta && "has-no-meta",
7690
7700
  props.className
7691
7701
  ),
7692
7702
  style: props.style
@@ -8165,6 +8175,7 @@ var AppShell = React47.forwardRef(function AppShell2(props, ref) {
8165
8175
  className: cx(
8166
8176
  "aura-shell__bar",
8167
8177
  (!props.header || props.headerHideFrom === "lg") && "aura-shell__bar--menu-only",
8178
+ !props.header && "aura-shell__bar--no-header",
8168
8179
  props.headerHideOnScroll && "aura-shell__bar--hides",
8169
8180
  away && "is-away"
8170
8181
  )
@@ -116,6 +116,7 @@ const AppShell = React.forwardRef(function AppShell2(props, ref) {
116
116
  className: cx(
117
117
  "aura-shell__bar",
118
118
  (!props.header || props.headerHideFrom === "lg") && "aura-shell__bar--menu-only",
119
+ !props.header && "aura-shell__bar--no-header",
119
120
  props.headerHideOnScroll && "aura-shell__bar--hides",
120
121
  away && "is-away"
121
122
  )
package/dist/esm/Menu.js CHANGED
@@ -3,7 +3,7 @@ import * as React from "react";
3
3
  import { createPortal } from "react-dom";
4
4
  import { cx, uid, useIsoLayoutEffect, useMounted, useMergedRef } from "./internal.js";
5
5
  import { Icon } from "./Icon.js";
6
- import { useLinkComponent } from "./locale.js";
6
+ import { useLinkComponent, useStrings } from "./locale.js";
7
7
  import { IconCheck } from "./icons.js";
8
8
  const ITEMS = '[role^="menuitem"]';
9
9
  function makesBlock(s) {
@@ -48,6 +48,7 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
48
48
  const headerId = uid(), itemId = uid();
49
49
  const hasHeader = props.header != null && props.header !== false && props.header !== "";
50
50
  const Link = useLinkComponent(props.linkComponent);
51
+ const t = useStrings();
51
52
  function place() {
52
53
  const a = props.anchor, m = own.current;
53
54
  if (!a || !m) return;
@@ -174,6 +175,8 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
174
175
  if (reasonId)
175
176
  body[2] = /* Hidden from the name (it would be read twice); aria-describedby still reads it. */
176
177
  /* @__PURE__ */ React.createElement("span", { key: "h", id: reasonId, className: "aura-menu__hint aura-menu__reason", "aria-hidden": true }, it.disabledReason);
178
+ if (it.href && !it.disabled && it.target === "_blank")
179
+ body[1] = /* @__PURE__ */ React.createElement("span", { key: "t", className: "aura-menu__label" }, it.label, /* @__PURE__ */ React.createElement("span", { className: "aura-sr-only" }, " (" + t.opensInNewTab + ")"));
177
180
  if (it.href && !it.disabled)
178
181
  return /* @__PURE__ */ React.createElement(
179
182
  Link,
@@ -10,6 +10,8 @@ const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
10
10
  });
11
11
  const level = props.headingLevel || 1;
12
12
  const below = props.actionsFullWidthBelow;
13
+ const hide = props.titleHideBelow;
14
+ const hasMeta = props.meta != null && props.meta !== false;
13
15
  return h(
14
16
  "div",
15
17
  Object.assign(attrs, {
@@ -17,6 +19,8 @@ const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
17
19
  className: cx(
18
20
  "aura-page-header",
19
21
  (below === "sm" || below === "md" || below === "lg") && "aura-page-header--actions-full-below-" + below,
22
+ (hide === "sm" || hide === "md" || hide === "lg") && "aura-page-header--title-hide-below-" + hide,
23
+ (hide === "sm" || hide === "md" || hide === "lg") && !hasMeta && "has-no-meta",
20
24
  props.className
21
25
  ),
22
26
  style: props.style
@@ -132,6 +132,7 @@ const STRINGS = {
132
132
  statusMaintenance: "Maintenance",
133
133
  statusOk: "OK",
134
134
  statusUnknown: "No data",
135
+ opensInNewTab: "opens in a new tab",
135
136
  accepts: function(list, max) {
136
137
  return [list, max && "up to " + max + " each"].filter(Boolean).join(", ");
137
138
  }
@@ -128,6 +128,7 @@ const sv = {
128
128
  statusMaintenance: "Underh\xE5ll",
129
129
  statusOk: "OK",
130
130
  statusUnknown: "Ingen data",
131
+ opensInNewTab: "\xF6ppnas i en ny flik",
131
132
  accepts: function(list, max) {
132
133
  return [list, max && "h\xF6gst " + max + " per fil"].filter(Boolean).join(", ");
133
134
  }
@@ -128,6 +128,7 @@ const th = {
128
128
  statusMaintenance: "\u0E1B\u0E34\u0E14\u0E1B\u0E23\u0E31\u0E1A\u0E1B\u0E23\u0E38\u0E07",
129
129
  statusOk: "\u0E1B\u0E01\u0E15\u0E34",
130
130
  statusUnknown: "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
131
+ opensInNewTab: "\u0E40\u0E1B\u0E34\u0E14\u0E43\u0E19\u0E41\u0E17\u0E47\u0E1A\u0E43\u0E2B\u0E21\u0E48",
131
132
  accepts: function(list, max) {
132
133
  return [list, max && "\u0E44\u0E21\u0E48\u0E40\u0E01\u0E34\u0E19 " + max + " \u0E15\u0E48\u0E2D\u0E44\u0E1F\u0E25\u0E4C"].filter(Boolean).join(" \xB7 ");
133
134
  }
package/dist/index.d.cts CHANGED
@@ -1936,6 +1936,10 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
1936
1936
  * Tooltip or Popover too; IconButtons keep their size) — a single Button or your own grid spans the row. Wider
1937
1937
  * than that, the actions hug their content at the end as before. */
1938
1938
  actionsFullWidthBelow?: "sm" | "md" | "lg" | undefined;
1939
+ /** 5.41 (DxT Monitor #20): below this breakpoint the title moves out of sight — still the page's heading for screen
1940
+ * readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
1941
+ * meta line and actions stay; with no meta, the actions start the header. */
1942
+ titleHideBelow?: "sm" | "md" | "lg" | undefined;
1939
1943
  /** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
1940
1944
  headingLevel?: 1 | 2 | 3 | undefined;
1941
1945
  /** The heading's id, for `aria-labelledby` on the page's region. */
@@ -2044,6 +2048,8 @@ export interface AuraStrings {
2044
2048
  statusOk: string;
2045
2049
  /** StatusTile `unknown` (5.35). */
2046
2050
  statusUnknown: string;
2051
+ /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
2052
+ opensInNewTab: string;
2047
2053
  }
2048
2054
  /** Built-in strings by locale. th and sv also ship as packs (`@jirawatpyk/aura-react/locales/th`, `/sv`, 5.9); in 6.0
2049
2055
  * only en stays built in and a Thai or Swedish app passes its pack to AuraProvider `strings`. */
package/dist/index.d.ts CHANGED
@@ -1936,6 +1936,10 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
1936
1936
  * Tooltip or Popover too; IconButtons keep their size) — a single Button or your own grid spans the row. Wider
1937
1937
  * than that, the actions hug their content at the end as before. */
1938
1938
  actionsFullWidthBelow?: "sm" | "md" | "lg" | undefined;
1939
+ /** 5.41 (DxT Monitor #20): below this breakpoint the title moves out of sight — still the page's heading for screen
1940
+ * readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
1941
+ * meta line and actions stay; with no meta, the actions start the header. */
1942
+ titleHideBelow?: "sm" | "md" | "lg" | undefined;
1939
1943
  /** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
1940
1944
  headingLevel?: 1 | 2 | 3 | undefined;
1941
1945
  /** The heading's id, for `aria-labelledby` on the page's region. */
@@ -2044,6 +2048,8 @@ export interface AuraStrings {
2044
2048
  statusOk: string;
2045
2049
  /** StatusTile `unknown` (5.35). */
2046
2050
  statusUnknown: string;
2051
+ /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
2052
+ opensInNewTab: string;
2047
2053
  }
2048
2054
  /** Built-in strings by locale. th and sv also ship as packs (`@jirawatpyk/aura-react/locales/th`, `/sv`, 5.9); in 6.0
2049
2055
  * only en stays built in and a Thai or Swedish app passes its pack to AuraProvider `strings`. */
@@ -153,6 +153,7 @@ var sv = {
153
153
  statusMaintenance: "Underh\xE5ll",
154
154
  statusOk: "OK",
155
155
  statusUnknown: "Ingen data",
156
+ opensInNewTab: "\xF6ppnas i en ny flik",
156
157
  accepts: function(list, max) {
157
158
  return [list, max && "h\xF6gst " + max + " per fil"].filter(Boolean).join(", ");
158
159
  }
@@ -96,6 +96,8 @@ export interface AuraStrings {
96
96
  statusOk: string;
97
97
  /** StatusTile `unknown` (5.35). */
98
98
  statusUnknown: string;
99
+ /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
100
+ opensInNewTab: string;
99
101
  }
100
102
  /** Built-in strings by locale. th and sv also ship as packs (`@jirawatpyk/aura-react/locales/th`, `/sv`, 5.9); in 6.0
101
103
  * only en stays built in and a Thai or Swedish app passes its pack to AuraProvider `strings`. */
@@ -96,6 +96,8 @@ export interface AuraStrings {
96
96
  statusOk: string;
97
97
  /** StatusTile `unknown` (5.35). */
98
98
  statusUnknown: string;
99
+ /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
100
+ opensInNewTab: string;
99
101
  }
100
102
  /** Built-in strings by locale. th and sv also ship as packs (`@jirawatpyk/aura-react/locales/th`, `/sv`, 5.9); in 6.0
101
103
  * only en stays built in and a Thai or Swedish app passes its pack to AuraProvider `strings`. */
@@ -153,6 +153,7 @@ var th = {
153
153
  statusMaintenance: "\u0E1B\u0E34\u0E14\u0E1B\u0E23\u0E31\u0E1A\u0E1B\u0E23\u0E38\u0E07",
154
154
  statusOk: "\u0E1B\u0E01\u0E15\u0E34",
155
155
  statusUnknown: "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
156
+ opensInNewTab: "\u0E40\u0E1B\u0E34\u0E14\u0E43\u0E19\u0E41\u0E17\u0E47\u0E1A\u0E43\u0E2B\u0E21\u0E48",
156
157
  accepts: function(list, max) {
157
158
  return [list, max && "\u0E44\u0E21\u0E48\u0E40\u0E01\u0E34\u0E19 " + max + " \u0E15\u0E48\u0E2D\u0E44\u0E1F\u0E25\u0E4C"].filter(Boolean).join(" \xB7 ");
158
159
  }
@@ -96,6 +96,8 @@ export interface AuraStrings {
96
96
  statusOk: string;
97
97
  /** StatusTile `unknown` (5.35). */
98
98
  statusUnknown: string;
99
+ /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
100
+ opensInNewTab: string;
99
101
  }
100
102
  /** Built-in strings by locale. th and sv also ship as packs (`@jirawatpyk/aura-react/locales/th`, `/sv`, 5.9); in 6.0
101
103
  * only en stays built in and a Thai or Swedish app passes its pack to AuraProvider `strings`. */
@@ -96,6 +96,8 @@ export interface AuraStrings {
96
96
  statusOk: string;
97
97
  /** StatusTile `unknown` (5.35). */
98
98
  statusUnknown: string;
99
+ /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
100
+ opensInNewTab: string;
99
101
  }
100
102
  /** Built-in strings by locale. th and sv also ship as packs (`@jirawatpyk/aura-react/locales/th`, `/sv`, 5.9); in 6.0
101
103
  * only en stays built in and a Thai or Swedish app passes its pack to AuraProvider `strings`. */
@@ -342,6 +342,7 @@ var th = {
342
342
  statusMaintenance: "\u0E1B\u0E34\u0E14\u0E1B\u0E23\u0E31\u0E1A\u0E1B\u0E23\u0E38\u0E07",
343
343
  statusOk: "\u0E1B\u0E01\u0E15\u0E34",
344
344
  statusUnknown: "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
345
+ opensInNewTab: "\u0E40\u0E1B\u0E34\u0E14\u0E43\u0E19\u0E41\u0E17\u0E47\u0E1A\u0E43\u0E2B\u0E21\u0E48",
345
346
  accepts: function(list, max) {
346
347
  return [list, max && "\u0E44\u0E21\u0E48\u0E40\u0E01\u0E34\u0E19 " + max + " \u0E15\u0E48\u0E2D\u0E44\u0E1F\u0E25\u0E4C"].filter(Boolean).join(" \xB7 ");
347
348
  }
@@ -478,6 +479,7 @@ var sv = {
478
479
  statusMaintenance: "Underh\xE5ll",
479
480
  statusOk: "OK",
480
481
  statusUnknown: "Ingen data",
482
+ opensInNewTab: "\xF6ppnas i en ny flik",
481
483
  accepts: function(list, max) {
482
484
  return [list, max && "h\xF6gst " + max + " per fil"].filter(Boolean).join(", ");
483
485
  }
@@ -615,6 +617,7 @@ var STRINGS = {
615
617
  statusMaintenance: "Maintenance",
616
618
  statusOk: "OK",
617
619
  statusUnknown: "No data",
620
+ opensInNewTab: "opens in a new tab",
618
621
  accepts: function(list, max) {
619
622
  return [list, max && "up to " + max + " each"].filter(Boolean).join(", ");
620
623
  }
@@ -1426,6 +1429,8 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1426
1429
  });
1427
1430
  const level = props.headingLevel || 1;
1428
1431
  const below = props.actionsFullWidthBelow;
1432
+ const hide = props.titleHideBelow;
1433
+ const hasMeta = props.meta != null && props.meta !== false;
1429
1434
  return h4(
1430
1435
  "div",
1431
1436
  Object.assign(attrs2, {
@@ -1433,6 +1438,8 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1433
1438
  className: cx(
1434
1439
  "aura-page-header",
1435
1440
  (below === "sm" || below === "md" || below === "lg") && "aura-page-header--actions-full-below-" + below,
1441
+ (hide === "sm" || hide === "md" || hide === "lg") && "aura-page-header--title-hide-below-" + hide,
1442
+ (hide === "sm" || hide === "md" || hide === "lg") && !hasMeta && "has-no-meta",
1436
1443
  props.className
1437
1444
  ),
1438
1445
  style: props.style
@@ -383,6 +383,8 @@ export interface AuraStrings {
383
383
  statusOk: string;
384
384
  /** StatusTile `unknown` (5.35). */
385
385
  statusUnknown: string;
386
+ /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
387
+ opensInNewTab: string;
386
388
  }
387
389
  /** Built-in strings by locale. th and sv also ship as packs (`@jirawatpyk/aura-react/locales/th`, `/sv`, 5.9); in 6.0
388
390
  * only en stays built in and a Thai or Swedish app passes its pack to AuraProvider `strings`. */
@@ -501,6 +503,10 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
501
503
  * Tooltip or Popover too; IconButtons keep their size) — a single Button or your own grid spans the row. Wider
502
504
  * than that, the actions hug their content at the end as before. */
503
505
  actionsFullWidthBelow?: "sm" | "md" | "lg" | undefined;
506
+ /** 5.41 (DxT Monitor #20): below this breakpoint the title moves out of sight — still the page's heading for screen
507
+ * readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
508
+ * meta line and actions stay; with no meta, the actions start the header. */
509
+ titleHideBelow?: "sm" | "md" | "lg" | undefined;
504
510
  /** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
505
511
  headingLevel?: 1 | 2 | 3 | undefined;
506
512
  /** The heading's id, for `aria-labelledby` on the page's region. */
@@ -383,6 +383,8 @@ export interface AuraStrings {
383
383
  statusOk: string;
384
384
  /** StatusTile `unknown` (5.35). */
385
385
  statusUnknown: string;
386
+ /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
387
+ opensInNewTab: string;
386
388
  }
387
389
  /** Built-in strings by locale. th and sv also ship as packs (`@jirawatpyk/aura-react/locales/th`, `/sv`, 5.9); in 6.0
388
390
  * only en stays built in and a Thai or Swedish app passes its pack to AuraProvider `strings`. */
@@ -501,6 +503,10 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
501
503
  * Tooltip or Popover too; IconButtons keep their size) — a single Button or your own grid spans the row. Wider
502
504
  * than that, the actions hug their content at the end as before. */
503
505
  actionsFullWidthBelow?: "sm" | "md" | "lg" | undefined;
506
+ /** 5.41 (DxT Monitor #20): below this breakpoint the title moves out of sight — still the page's heading for screen
507
+ * readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
508
+ * meta line and actions stay; with no meta, the actions start the header. */
509
+ titleHideBelow?: "sm" | "md" | "lg" | undefined;
504
510
  /** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
505
511
  headingLevel?: 1 | 2 | 3 | undefined;
506
512
  /** The heading's id, for `aria-labelledby` on the page's region. */
@@ -278,6 +278,7 @@ var th = {
278
278
  statusMaintenance: "\u0E1B\u0E34\u0E14\u0E1B\u0E23\u0E31\u0E1A\u0E1B\u0E23\u0E38\u0E07",
279
279
  statusOk: "\u0E1B\u0E01\u0E15\u0E34",
280
280
  statusUnknown: "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
281
+ opensInNewTab: "\u0E40\u0E1B\u0E34\u0E14\u0E43\u0E19\u0E41\u0E17\u0E47\u0E1A\u0E43\u0E2B\u0E21\u0E48",
281
282
  accepts: function(list, max) {
282
283
  return [list, max && "\u0E44\u0E21\u0E48\u0E40\u0E01\u0E34\u0E19 " + max + " \u0E15\u0E48\u0E2D\u0E44\u0E1F\u0E25\u0E4C"].filter(Boolean).join(" \xB7 ");
283
284
  }
@@ -414,6 +415,7 @@ var sv = {
414
415
  statusMaintenance: "Underh\xE5ll",
415
416
  statusOk: "OK",
416
417
  statusUnknown: "Ingen data",
418
+ opensInNewTab: "\xF6ppnas i en ny flik",
417
419
  accepts: function(list, max) {
418
420
  return [list, max && "h\xF6gst " + max + " per fil"].filter(Boolean).join(", ");
419
421
  }
@@ -551,6 +553,7 @@ var STRINGS = {
551
553
  statusMaintenance: "Maintenance",
552
554
  statusOk: "OK",
553
555
  statusUnknown: "No data",
556
+ opensInNewTab: "opens in a new tab",
554
557
  accepts: function(list, max) {
555
558
  return [list, max && "up to " + max + " each"].filter(Boolean).join(", ");
556
559
  }
@@ -1362,6 +1365,8 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1362
1365
  });
1363
1366
  const level = props.headingLevel || 1;
1364
1367
  const below = props.actionsFullWidthBelow;
1368
+ const hide = props.titleHideBelow;
1369
+ const hasMeta = props.meta != null && props.meta !== false;
1365
1370
  return h4(
1366
1371
  "div",
1367
1372
  Object.assign(attrs2, {
@@ -1369,6 +1374,8 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1369
1374
  className: cx(
1370
1375
  "aura-page-header",
1371
1376
  (below === "sm" || below === "md" || below === "lg") && "aura-page-header--actions-full-below-" + below,
1377
+ (hide === "sm" || hide === "md" || hide === "lg") && "aura-page-header--title-hide-below-" + hide,
1378
+ (hide === "sm" || hide === "md" || hide === "lg") && !hasMeta && "has-no-meta",
1372
1379
  props.className
1373
1380
  ),
1374
1381
  style: props.style
package/dist/styles.css CHANGED
@@ -70,10 +70,10 @@ button.aura-btn--creative[aria-disabled='true']:hover { box-shadow: var(--aura-s
70
70
  .aura-btn--primary:hover { background: var(--aura-button-primary-bg-hover); }
71
71
 
72
72
  .aura-btn--secondary { border: 1px solid var(--aura-button-secondary-border); color: var(--aura-fg-primary); }
73
- .aura-btn--secondary:hover { background: var(--aura-hover, var(--aura-bg-surface-hover)); }
73
+ .aura-btn--secondary:hover, .aura-btn--secondary[aria-haspopup][aria-expanded="true"] { background: var(--aura-hover, var(--aura-bg-surface-hover)); }
74
74
  /* Destructive: filled for the confirm step, outline beside other actions. Loading keeps the colour (busy, not unavailable). */
75
75
  .aura-btn--ghost { color: var(--aura-fg-primary); }
76
- .aura-btn--ghost:hover { background: var(--aura-hover, var(--aura-bg-surface-hover)); }
76
+ .aura-btn--ghost:hover, .aura-btn--ghost[aria-haspopup][aria-expanded="true"] { background: var(--aura-hover, var(--aura-bg-surface-hover)); }
77
77
  /* size="sm" (4.16): 32px for toolbars, table rows and card footers. On touch the pill stays 32px and a transparent
78
78
  * ::after grows the hit area to 44px, as IconButton does. */
79
79
  .aura-btn--sm { height: var(--aura-button-height-sm); padding: 0 var(--aura-space-3); gap: 6px; }
@@ -344,7 +344,7 @@ a.aura-icon-btn { text-decoration: none; }
344
344
  border: 0; border-radius: var(--aura-radius-full); background: transparent; color: var(--aura-fg-primary);
345
345
  cursor: pointer; transition: background var(--aura-duration-fast) var(--aura-ease);
346
346
  }
347
- .aura-icon-btn:hover { background: var(--aura-hover, var(--aura-bg-surface-hover)); }
347
+ .aura-icon-btn:hover, .aura-icon-btn[aria-haspopup][aria-expanded="true"] { background: var(--aura-hover, var(--aura-bg-surface-hover)); } /* 5.41 (DxT #22): looks open while its menu shows */
348
348
  .aura-icon-btn--danger { color: var(--aura-fg-danger); }
349
349
  .aura-icon-btn--danger:hover { background: var(--aura-alert-danger-bg); }
350
350
  .aura-icon-btn:disabled { opacity: var(--aura-disabled-opacity); pointer-events: none; }
@@ -1124,6 +1124,9 @@ a.aura-tab { text-decoration: none; }
1124
1124
  .aura-shell__bar--menu-only { display: none; }
1125
1125
  }
1126
1126
  .aura-shell__bar-content { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--aura-space-3); }
1127
+ /* 5.41 (DxT Monitor #19): a page with its own back arrow marks itself with data-aura-hide-menubutton (on any element)
1128
+ * and the bar drops the menu button, as BottomNav does for data-aura-hide-bottomnav. */
1129
+ :root:has([data-aura-hide-menubutton]) :is(.aura-shell__menu, .aura-shell__bar--no-header) { display: none; } /* with no header the bar would be empty */
1127
1130
  .aura-shell__content { flex: 1; min-width: 0; padding: var(--aura-space-6) var(--aura-space-4); }
1128
1131
  /* 5.7: <main> takes focus (tabIndex -1) for skip links and "the row you acted on is gone"; a landmark gets no ring. */
1129
1132
  .aura-shell__content:focus { outline: none; }
@@ -1144,6 +1147,20 @@ a.aura-tab { text-decoration: none; }
1144
1147
  .aura-page-header__breadcrumb { min-width: 0; } /* 5.33 (DxT Monitor #7): Breadcrumb keeps its own type */
1145
1148
  .aura-page-header__meta { min-width: 0; font-size: max(13px, .8125rem); line-height: 1.5; color: var(--aura-fg-secondary); overflow-wrap: anywhere; }
1146
1149
  .aura-page-header__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); }
1150
+ /* 5.41 (DxT Monitor #20): titleHideBelow — the title is visually hidden (still the heading), the breadcrumb and eyebrow
1151
+ * are gone; with no meta line the text block takes no room, so the actions start the header. */
1152
+ @media (max-width: 639.98px) {
1153
+ .aura-page-header--title-hide-below-sm .aura-page-header__title, .aura-page-header--title-hide-below-sm.has-no-meta > .aura-page-header__text { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1154
+ .aura-page-header--title-hide-below-sm :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow) { display: none; }
1155
+ }
1156
+ @media (max-width: 767.98px) {
1157
+ .aura-page-header--title-hide-below-md .aura-page-header__title, .aura-page-header--title-hide-below-md.has-no-meta > .aura-page-header__text { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1158
+ .aura-page-header--title-hide-below-md :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow) { display: none; }
1159
+ }
1160
+ @media (max-width: 1023.98px) {
1161
+ .aura-page-header--title-hide-below-lg .aura-page-header__title, .aura-page-header--title-hide-below-lg.has-no-meta > .aura-page-header__text { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1162
+ .aura-page-header--title-hide-below-lg :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow) { display: none; }
1163
+ }
1147
1164
  /* 5.37 (DxT Monitor #17): actionsFullWidthBelow — the actions take the row under the text; their children share
1148
1165
  * each line equally (wrapping when a label won't fit), a trigger inside a DropdownMenu, Tooltip or Popover wrapper
1149
1166
  * fills it, and icon buttons keep their size. The :has rule is alone so older browsers drop only it. */
@@ -72,10 +72,10 @@ button.aura-btn--creative[aria-disabled='true']:hover { box-shadow: var(--aura-s
72
72
  .aura-btn--primary:hover { background: var(--aura-button-primary-bg-hover); }
73
73
 
74
74
  .aura-btn--secondary { border: 1px solid var(--aura-button-secondary-border); color: var(--aura-fg-primary); }
75
- .aura-btn--secondary:hover { background: var(--aura-hover, var(--aura-bg-surface-hover)); }
75
+ .aura-btn--secondary:hover, .aura-btn--secondary[aria-haspopup][aria-expanded="true"] { background: var(--aura-hover, var(--aura-bg-surface-hover)); }
76
76
  /* Destructive: filled for the confirm step, outline beside other actions. Loading keeps the colour (busy, not unavailable). */
77
77
  .aura-btn--ghost { color: var(--aura-fg-primary); }
78
- .aura-btn--ghost:hover { background: var(--aura-hover, var(--aura-bg-surface-hover)); }
78
+ .aura-btn--ghost:hover, .aura-btn--ghost[aria-haspopup][aria-expanded="true"] { background: var(--aura-hover, var(--aura-bg-surface-hover)); }
79
79
  /* size="sm" (4.16): 32px for toolbars, table rows and card footers. On touch the pill stays 32px and a transparent
80
80
  * ::after grows the hit area to 44px, as IconButton does. */
81
81
  .aura-btn--sm { height: var(--aura-button-height-sm); padding: 0 var(--aura-space-3); gap: 6px; }
@@ -346,7 +346,7 @@ a.aura-icon-btn { text-decoration: none; }
346
346
  border: 0; border-radius: var(--aura-radius-full); background: transparent; color: var(--aura-fg-primary);
347
347
  cursor: pointer; transition: background var(--aura-duration-fast) var(--aura-ease);
348
348
  }
349
- .aura-icon-btn:hover { background: var(--aura-hover, var(--aura-bg-surface-hover)); }
349
+ .aura-icon-btn:hover, .aura-icon-btn[aria-haspopup][aria-expanded="true"] { background: var(--aura-hover, var(--aura-bg-surface-hover)); } /* 5.41 (DxT #22): looks open while its menu shows */
350
350
  .aura-icon-btn--danger { color: var(--aura-fg-danger); }
351
351
  .aura-icon-btn--danger:hover { background: var(--aura-alert-danger-bg); }
352
352
  .aura-icon-btn:disabled { opacity: var(--aura-disabled-opacity); pointer-events: none; }
@@ -1126,6 +1126,9 @@ a.aura-tab { text-decoration: none; }
1126
1126
  .aura-shell__bar--menu-only { display: none; }
1127
1127
  }
1128
1128
  .aura-shell__bar-content { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--aura-space-3); }
1129
+ /* 5.41 (DxT Monitor #19): a page with its own back arrow marks itself with data-aura-hide-menubutton (on any element)
1130
+ * and the bar drops the menu button, as BottomNav does for data-aura-hide-bottomnav. */
1131
+ :root:has([data-aura-hide-menubutton]) :is(.aura-shell__menu, .aura-shell__bar--no-header) { display: none; } /* with no header the bar would be empty */
1129
1132
  .aura-shell__content { flex: 1; min-width: 0; padding: var(--aura-space-6) var(--aura-space-4); }
1130
1133
  /* 5.7: <main> takes focus (tabIndex -1) for skip links and "the row you acted on is gone"; a landmark gets no ring. */
1131
1134
  .aura-shell__content:focus { outline: none; }
@@ -1146,6 +1149,20 @@ a.aura-tab { text-decoration: none; }
1146
1149
  .aura-page-header__breadcrumb { min-width: 0; } /* 5.33 (DxT Monitor #7): Breadcrumb keeps its own type */
1147
1150
  .aura-page-header__meta { min-width: 0; font-size: max(13px, .8125rem); line-height: 1.5; color: var(--aura-fg-secondary); overflow-wrap: anywhere; }
1148
1151
  .aura-page-header__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); }
1152
+ /* 5.41 (DxT Monitor #20): titleHideBelow — the title is visually hidden (still the heading), the breadcrumb and eyebrow
1153
+ * are gone; with no meta line the text block takes no room, so the actions start the header. */
1154
+ @media (max-width: 639.98px) {
1155
+ .aura-page-header--title-hide-below-sm .aura-page-header__title, .aura-page-header--title-hide-below-sm.has-no-meta > .aura-page-header__text { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1156
+ .aura-page-header--title-hide-below-sm :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow) { display: none; }
1157
+ }
1158
+ @media (max-width: 767.98px) {
1159
+ .aura-page-header--title-hide-below-md .aura-page-header__title, .aura-page-header--title-hide-below-md.has-no-meta > .aura-page-header__text { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1160
+ .aura-page-header--title-hide-below-md :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow) { display: none; }
1161
+ }
1162
+ @media (max-width: 1023.98px) {
1163
+ .aura-page-header--title-hide-below-lg .aura-page-header__title, .aura-page-header--title-hide-below-lg.has-no-meta > .aura-page-header__text { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1164
+ .aura-page-header--title-hide-below-lg :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow) { display: none; }
1165
+ }
1149
1166
  /* 5.37 (DxT Monitor #17): actionsFullWidthBelow — the actions take the row under the text; their children share
1150
1167
  * each line equally (wrapping when a label won't fit), a trigger inside a DropdownMenu, Tooltip or Popover wrapper
1151
1168
  * fills it, and icon buttons keep their size. The :has rule is alone so older browsers drop only it. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.40.0",
3
+ "version": "5.41.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",