@jirawatpyk/aura-tokens 5.6.0 → 5.7.1

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/aura-tailwind.css CHANGED
@@ -1,4 +1,4 @@
1
- /* AURA v5.6.0 — Tailwind v4 theme. GENERATED by scripts/build-tokens.mts from tokens.json. Do not edit by hand.
1
+ /* AURA v5.7.1 — Tailwind v4 theme. GENERATED by scripts/build-tokens.mts from tokens.json. Do not edit by hand.
2
2
  * @import "tailwindcss";
3
3
  * @import "@jirawatpyk/aura-tokens/tailwind.css";
4
4
  * Gives bg-bg-surface, text-fg-primary, border-border-strong, p-aura-6, rounded-aura-xl, shadow-aura-overlay,
@@ -1,4 +1,4 @@
1
- /* AURA v5.6.0 — Tailwind v4 theme with aura- prefixed names. GENERATED by scripts/build-tokens.mts. Do not edit by hand.
1
+ /* AURA v5.7.1 — Tailwind v4 theme with aura- prefixed names. GENERATED by scripts/build-tokens.mts. Do not edit by hand.
2
2
  * For apps that already have a Tailwind theme (shadcn): nothing here redefines an existing name.
3
3
  * @layer aura-tokens, theme, base, aura, components, utilities;
4
4
  * @import "tailwindcss";
package/aura.css CHANGED
@@ -1,4 +1,4 @@
1
- /* AURA v5.6.0 — GENERATED by scripts/build-tokens.mts from tokens.json. Do not edit by hand. */
1
+ /* AURA v5.7.1 — GENERATED by scripts/build-tokens.mts from tokens.json. Do not edit by hand. */
2
2
  /* Fonts: load aura-fonts.css (or the <link> tags in README) separately, so a blocked Google Fonts never breaks this file. */
3
3
 
4
4
  :root, [data-theme="light"] {
@@ -828,6 +828,8 @@ window.Aura = (() => {
828
828
  const pos = posState[0], setPos = posState[1];
829
829
  const items2 = props.items || [];
830
830
  const mounted = useMounted();
831
+ const headerId = uid();
832
+ const hasHeader = props.header != null && props.header !== false && props.header !== "";
831
833
  const Link = useLinkComponent(props.linkComponent);
832
834
  useIsoLayoutEffect(
833
835
  function() {
@@ -845,7 +847,20 @@ window.Aura = (() => {
845
847
  const left = Math.max(8, Math.min(r.right - mw, window.innerWidth - mw - 8));
846
848
  setPos({ top, left, maxHeight });
847
849
  },
848
- [props.anchor, mounted]
850
+ [props.anchor, mounted, hasHeader]
851
+ );
852
+ const hadHeader = React6.useRef(hasHeader);
853
+ React6.useEffect(
854
+ function() {
855
+ if (hadHeader.current === hasHeader) return;
856
+ hadHeader.current = hasHeader;
857
+ const a = document.activeElement;
858
+ if (own.current && (!a || a === document.body)) {
859
+ const first = own.current.querySelector('[role^="menuitem"]:not([disabled])');
860
+ if (first) first.focus();
861
+ }
862
+ },
863
+ [hasHeader]
849
864
  );
850
865
  React6.useEffect(
851
866
  function() {
@@ -871,22 +886,22 @@ window.Aura = (() => {
871
886
  [mounted]
872
887
  );
873
888
  function onKeyDown(e) {
874
- const list = Array.prototype.slice.call(
889
+ const list2 = Array.prototype.slice.call(
875
890
  own.current.querySelectorAll('[role^="menuitem"]:not([disabled])')
876
891
  );
877
- const i = list.indexOf(document.activeElement);
892
+ const i = list2.indexOf(document.activeElement);
878
893
  if (e.key === "ArrowDown") {
879
894
  e.preventDefault();
880
- list[(i + 1) % list.length].focus();
895
+ list2[(i + 1) % list2.length].focus();
881
896
  } else if (e.key === "ArrowUp") {
882
897
  e.preventDefault();
883
- list[(i - 1 + list.length) % list.length].focus();
898
+ list2[(i - 1 + list2.length) % list2.length].focus();
884
899
  } else if (e.key === "Home") {
885
900
  e.preventDefault();
886
- list[0].focus();
901
+ list2[0].focus();
887
902
  } else if (e.key === "End") {
888
903
  e.preventDefault();
889
- list[list.length - 1].focus();
904
+ list2[list2.length - 1].focus();
890
905
  } else if (e.key === " " && document.activeElement && document.activeElement.tagName === "A") {
891
906
  e.preventDefault();
892
907
  document.activeElement.click();
@@ -898,9 +913,9 @@ window.Aura = (() => {
898
913
  }
899
914
  e.stopPropagation();
900
915
  }
901
- function groupItems(list) {
916
+ function groupItems(list2) {
902
917
  const out = [];
903
- list.forEach(function(it, i) {
918
+ list2.forEach(function(it, i) {
904
919
  const g = it.type === "radio" && it.group ? it.group : null;
905
920
  const last = out[out.length - 1];
906
921
  if (last && last.group === g && g !== null) last.items.push({ it, i });
@@ -955,27 +970,28 @@ window.Aura = (() => {
955
970
  body
956
971
  );
957
972
  }
958
- const el = /* @__PURE__ */ React6.createElement(
973
+ const style = {
974
+ top: pos ? pos.top : -9999,
975
+ left: pos ? pos.left : -9999,
976
+ maxHeight: pos && pos.maxHeight ? pos.maxHeight : void 0
977
+ };
978
+ const list = groupItems(items2).map(function(block, bi) {
979
+ const rendered = block.items.map(function(x) {
980
+ return renderItem(x.it, x.i);
981
+ });
982
+ return block.group ? /* @__PURE__ */ React6.createElement("div", { key: "g" + bi, role: "group", "aria-label": block.group, className: "aura-menu__group" }, rendered) : /* @__PURE__ */ React6.createElement(React6.Fragment, { key: "f" + bi }, rendered);
983
+ });
984
+ const el = hasHeader ? /* @__PURE__ */ React6.createElement("div", { ref: merged, className: "aura-menu has-header", onKeyDown, style }, /* @__PURE__ */ React6.createElement(
959
985
  "div",
960
986
  {
961
- ref: merged,
962
- role: "menu",
963
- "aria-label": props.label,
964
- className: "aura-menu",
965
- onKeyDown,
966
- style: {
967
- top: pos ? pos.top : -9999,
968
- left: pos ? pos.left : -9999,
969
- maxHeight: pos && pos.maxHeight ? pos.maxHeight : void 0
987
+ className: "aura-menu__header",
988
+ id: headerId,
989
+ onMouseDown: function(e) {
990
+ e.preventDefault();
970
991
  }
971
992
  },
972
- groupItems(items2).map(function(block, bi) {
973
- const rendered = block.items.map(function(x) {
974
- return renderItem(x.it, x.i);
975
- });
976
- return block.group ? /* @__PURE__ */ React6.createElement("div", { key: "g" + bi, role: "group", "aria-label": block.group, className: "aura-menu__group" }, rendered) : /* @__PURE__ */ React6.createElement(React6.Fragment, { key: "f" + bi }, rendered);
977
- })
978
- );
993
+ props.header
994
+ ), /* @__PURE__ */ React6.createElement("div", { role: "menu", "aria-label": props.label, "aria-describedby": headerId, className: "aura-menu__list" }, list)) : /* @__PURE__ */ React6.createElement("div", { ref: merged, role: "menu", "aria-label": props.label, className: "aura-menu", onKeyDown, style }, list);
979
995
  return mounted ? (0, import_react_dom.createPortal)(el, document.body) : null;
980
996
  });
981
997
 
@@ -1015,6 +1031,7 @@ window.Aura = (() => {
1015
1031
  label: props.label,
1016
1032
  items: props.items,
1017
1033
  linkComponent: props.linkComponent,
1034
+ header: props.header,
1018
1035
  onClose: function(restore) {
1019
1036
  setAnchor(null);
1020
1037
  if (restore && typeof anchor.focus === "function") anchor.focus();
@@ -4014,6 +4031,7 @@ window.Aura = (() => {
4014
4031
  function close() {
4015
4032
  if (props.dismissible !== false && props.onClose) props.onClose();
4016
4033
  }
4034
+ const scrimCloses = props.dismissible !== false && (props.dismissOnScrim !== void 0 ? props.dismissOnScrim : props.role !== "alertdialog");
4017
4035
  const modal = useModal(props.open, own, {
4018
4036
  autoFocus: props.autoFocus,
4019
4037
  onEscape: close,
@@ -4022,7 +4040,17 @@ window.Aura = (() => {
4022
4040
  });
4023
4041
  if (!modal.ready) return null;
4024
4042
  return (0, import_react_dom8.createPortal)(
4025
- /* @__PURE__ */ React27.createElement("div", { className: "aura-dialog-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React27.createElement("div", { className: "aura-scrim", onClick: close, "aria-hidden": true }), /* @__PURE__ */ React27.createElement(
4043
+ /* @__PURE__ */ React27.createElement("div", { className: "aura-dialog-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React27.createElement(
4044
+ "div",
4045
+ {
4046
+ className: "aura-scrim",
4047
+ onClick: scrimCloses ? close : void 0,
4048
+ onMouseDown: scrimCloses ? void 0 : function(e) {
4049
+ e.preventDefault();
4050
+ },
4051
+ "aria-hidden": true
4052
+ }
4053
+ ), /* @__PURE__ */ React27.createElement(
4026
4054
  "div",
4027
4055
  {
4028
4056
  ref: merged,
@@ -4056,8 +4084,19 @@ window.Aura = (() => {
4056
4084
  });
4057
4085
  if (!modal.ready) return null;
4058
4086
  const side = props.side === "left" ? "left" : "right";
4087
+ const drawerScrimCloses = props.dismissible !== false && props.dismissOnScrim !== false;
4059
4088
  return (0, import_react_dom8.createPortal)(
4060
- /* @__PURE__ */ React27.createElement("div", { className: "aura-dialog-layer aura-drawer-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React27.createElement("div", { className: "aura-scrim", onClick: close, "aria-hidden": true }), /* @__PURE__ */ React27.createElement(
4089
+ /* @__PURE__ */ React27.createElement("div", { className: "aura-dialog-layer aura-drawer-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React27.createElement(
4090
+ "div",
4091
+ {
4092
+ className: "aura-scrim",
4093
+ onClick: drawerScrimCloses ? close : void 0,
4094
+ onMouseDown: !drawerScrimCloses ? function(e) {
4095
+ e.preventDefault();
4096
+ } : void 0,
4097
+ "aria-hidden": true
4098
+ }
4099
+ ), /* @__PURE__ */ React27.createElement(
4061
4100
  "div",
4062
4101
  {
4063
4102
  ref: merged,
@@ -5726,7 +5765,10 @@ window.Aura = (() => {
5726
5765
  const items2 = props.items || [];
5727
5766
  return /* @__PURE__ */ React32.createElement("nav", { ref, "aria-label": props.label || t.breadcrumb, className: cx("aura-crumbs", props.className) }, /* @__PURE__ */ React32.createElement("ol", null, items2.map(function(it, i) {
5728
5767
  const last = i === items2.length - 1;
5729
- return /* @__PURE__ */ React32.createElement("li", { key: i }, last ? /* @__PURE__ */ React32.createElement("span", { "aria-current": "page", className: "aura-crumbs__current" }, it.label) : it.href ? /* @__PURE__ */ React32.createElement(Link, { href: it.href, onClick: it.onClick }, it.label) : /* @__PURE__ */ React32.createElement("button", { type: "button", onClick: it.onClick }, it.label), last ? null : /* @__PURE__ */ React32.createElement(Icon, { name: "chevron-right", size: 12, className: "aura-crumbs__sep" }));
5768
+ return /* @__PURE__ */ React32.createElement("li", { key: i }, last ? /* @__PURE__ */ React32.createElement("span", { "aria-current": "page", className: "aura-crumbs__current" }, it.label) : it.href ? /* @__PURE__ */ React32.createElement(Link, { href: it.href, onClick: it.onClick }, it.label) : it.onClick ? /* @__PURE__ */ React32.createElement("button", { type: "button", onClick: it.onClick }, it.label) : (
5769
+ /* 5.7: a segment with no page and no action is text, not a button that does nothing. */
5770
+ /* @__PURE__ */ React32.createElement("span", { className: "aura-crumbs__text" }, it.label)
5771
+ ), last ? null : /* @__PURE__ */ React32.createElement(Icon, { name: "chevron-right", size: 12, className: "aura-crumbs__sep" }));
5730
5772
  })));
5731
5773
  });
5732
5774
 
@@ -5921,7 +5963,7 @@ window.Aura = (() => {
5921
5963
  },
5922
5964
  "aria-expanded": open
5923
5965
  }
5924
- ) : null, /* @__PURE__ */ React38.createElement("div", { className: "aura-shell__bar-content" }, props.header)) : null, /* @__PURE__ */ React38.createElement("main", { className: "aura-shell__content", id: props.mainId || "main" }, props.children), props.bottomNav || null));
5966
+ ) : null, /* @__PURE__ */ React38.createElement("div", { className: "aura-shell__bar-content" }, props.header)) : null, /* @__PURE__ */ React38.createElement("main", { className: "aura-shell__content", id: props.mainId || "main", tabIndex: -1 }, props.children), props.bottomNav || null));
5925
5967
  });
5926
5968
 
5927
5969
  // src/ActionBar.tsx
@@ -6076,8 +6118,11 @@ window.Aura = (() => {
6076
6118
  /* @__PURE__ */ React42.createElement("ul", { className: "aura-bottomnav__list" }, props.items.map(function(it) {
6077
6119
  const on = active === it.id;
6078
6120
  const count = it.count != null && it.count > 0 ? it.count > 99 ? "99+" : String(it.count) : null;
6121
+ const suffix = count || it.badge && it.badgeLabel ? " (" + (count || it.badgeLabel) + ")" : "";
6079
6122
  const common = {
6080
6123
  className: cx("aura-bottomnav__item", on && "is-active"),
6124
+ /* 5.7: a full name when the label is shortened; the count / badge words still follow. */
6125
+ "aria-label": it.ariaLabel ? it.ariaLabel + suffix : void 0,
6081
6126
  "aria-current": on ? "page" : void 0,
6082
6127
  onClick: function(e) {
6083
6128
  if (!it.href) e.preventDefault();
@@ -6088,7 +6133,7 @@ window.Aura = (() => {
6088
6133
  const inner = [
6089
6134
  /* @__PURE__ */ React42.createElement("span", { key: "i", className: "aura-bottomnav__icon" }, /* @__PURE__ */ React42.createElement(Icon, { name: it.icon, size: "md" }), count ? /* @__PURE__ */ React42.createElement("span", { className: "aura-bottomnav__count", "aria-hidden": "true" }, count) : it.badge ? /* @__PURE__ */ React42.createElement("span", { className: "aura-bottomnav__dot", "aria-hidden": "true" }) : null),
6090
6135
  /* @__PURE__ */ React42.createElement("span", { key: "l", className: "aura-bottomnav__label" }, it.label),
6091
- count || it.badge && it.badgeLabel ? /* @__PURE__ */ React42.createElement("span", { key: "s", className: "aura-sr-only" }, " (" + (count || it.badgeLabel) + ")") : null
6136
+ suffix && !it.ariaLabel ? /* @__PURE__ */ React42.createElement("span", { key: "s", className: "aura-sr-only" }, suffix) : null
6092
6137
  ];
6093
6138
  return /* @__PURE__ */ React42.createElement("li", { key: it.id, className: "aura-bottomnav__cell" }, it.href ? /* @__PURE__ */ React42.createElement(Link, { href: it.href, ...common }, inner) : /* @__PURE__ */ React42.createElement("button", { type: "button", ...common }, inner));
6094
6139
  }))
@@ -247,6 +247,12 @@ a.aura-menu__item { text-decoration: none; box-sizing: border-box; }
247
247
  }
248
248
  .aura-menu__radio.is-on { border-color: var(--aura-button-primary-bg); }
249
249
  .aura-menu__radio.is-on::after { content: ''; width: 8px; height: 8px; border-radius: var(--aura-radius-full); background: var(--aura-button-primary-bg); }
250
+ /* 5.7: a header above the items (who is signed in), set off by a hairline like a separator. */
251
+ .aura-menu__header { margin: calc(-1 * var(--aura-space-1)) calc(-1 * var(--aura-space-1)) var(--aura-space-1); padding: var(--aura-space-3); border-bottom: 1px solid var(--aura-border-default); color: var(--aura-fg-secondary); font-size: 12px; line-height: 18px; overflow-wrap: anywhere; }
252
+ .aura-menu__header > * { margin: 0; }
253
+ /* Stays in view when a long menu scrolls. */
254
+ .aura-menu.has-header .aura-menu__header { position: sticky; top: calc(-1 * var(--aura-space-1)); z-index: 1; background: var(--aura-bg-surface); }
255
+ .aura-menu__header strong, .aura-menu__header b { color: var(--aura-fg-primary); font-weight: 500; font-size: 13px; }
250
256
  .aura-menu__sep { height: 1px; margin: var(--aura-space-1) calc(-1 * var(--aura-space-1)); background: var(--aura-border-default); }
251
257
 
252
258
  /* Footer + pager */
@@ -635,7 +641,7 @@ a.aura-tab { text-decoration: none; }
635
641
  .aura-nav__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
636
642
  .aura-nav__item {
637
643
  box-sizing: border-box; display: flex; align-items: center; gap: var(--aura-space-3); width: 100%;
638
- height: 36px; padding: 0 var(--aura-space-3); border: 0; border-radius: var(--aura-radius-sm);
644
+ min-height: 36px; padding: var(--aura-space-1) var(--aura-space-3); border: 0; border-radius: var(--aura-radius-sm);
639
645
  background: transparent; color: var(--aura-fg-secondary); font: inherit; font-size: 13px; font-weight: 500;
640
646
  text-decoration: none; text-align: left; cursor: pointer;
641
647
  transition: background var(--aura-duration-fast) var(--aura-ease), color var(--aura-duration-fast) var(--aura-ease);
@@ -644,7 +650,14 @@ a.aura-tab { text-decoration: none; }
644
650
  .aura-nav__item.is-active { background: var(--aura-bg-selected); color: var(--aura-fg-primary); }
645
651
  .aura-nav__item.is-active .aura-icon { color: var(--aura-fg-accent); }
646
652
  .aura-nav__item:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: -2px; }
647
- .aura-nav__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
653
+ /* Touch (5.7): rows are 44px on coarse pointers (AppShell's phone drawer); desktop keeps 36px. */
654
+ @media (pointer: coarse) { .aura-nav__item { min-height: var(--aura-touch-target); } }
655
+ /* 5.7.1: a long label wraps to a second line (the row grows; one-line rows stay 36px) instead of an ellipsis with no
656
+ * way to read the rest — Thai and Swedish names in a 240px nav or the phone drawer. Beyond two lines it clamps. */
657
+ .aura-nav__label {
658
+ flex: 1; min-width: 0; line-height: 18px; overflow: hidden; overflow-wrap: anywhere;
659
+ display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
660
+ }
648
661
  .aura-nav__count { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--aura-fg-secondary); }
649
662
  .aura-nav__badge { display: inline-flex; align-items: center; flex: none; }
650
663
  /* Groups: a disclosure button, its items indented one step per level. */
@@ -689,6 +702,8 @@ a.aura-tab { text-decoration: none; }
689
702
  .aura-crumbs a:hover, .aura-crumbs button:hover { color: var(--aura-fg-primary); text-decoration: underline; text-underline-offset: 3px; }
690
703
  .aura-crumbs a:focus-visible, .aura-crumbs button:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 2px; }
691
704
  .aura-crumbs__current { color: var(--aura-fg-primary); font-weight: 500; }
705
+ /* 5.7: a segment with no page of its own — the links' colour, not interactive. */
706
+ .aura-crumbs__text { color: var(--aura-fg-secondary); }
692
707
  .aura-crumbs__sep { color: var(--aura-fg-tertiary); }
693
708
 
694
709
  /* ---------- Avatar ---------- */
@@ -884,6 +899,8 @@ a.aura-tab { text-decoration: none; }
884
899
  }
885
900
  .aura-shell__bar-content { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--aura-space-3); }
886
901
  .aura-shell__content { flex: 1; min-width: 0; padding: var(--aura-space-6) var(--aura-space-4); }
902
+ /* 5.7: <main> takes focus (tabIndex -1) for skip links and "the row you acted on is gone"; a landmark gets no ring. */
903
+ .aura-shell__content:focus { outline: none; }
887
904
  @media (min-width: 640px) { .aura-shell__content { padding: var(--aura-space-6); } }
888
905
  @media (min-width: 1024px) { .aura-shell__content { padding: var(--aura-space-8); } }
889
906
  /* The shell already pads its content: a Container directly inside only caps the width. */
@@ -310,6 +310,9 @@ export interface MenuProps {
310
310
  autoFocus?: boolean | undefined;
311
311
  /** Router link for items with `href`; defaults to AuraProvider's `linkComponent`, then `<a>`. (4.19) */
312
312
  linkComponent?: React$1.ElementType | undefined;
313
+ /** Content above the items (5.7), e.g. who is signed in. Not an item: arrow keys skip it; it is the menu's
314
+ * accessible description, read once when the menu opens. */
315
+ header?: React$1.ReactNode | undefined;
313
316
  }
314
317
  export interface FieldProps {
315
318
  /** Visible label; also the accessible name. */
@@ -547,6 +550,9 @@ export interface DialogProps {
547
550
  size?: "sm" | "md" | "lg" | undefined;
548
551
  /** Default true. False hides the close button and ignores Escape and scrim clicks. */
549
552
  dismissible?: boolean | undefined;
553
+ /** Whether a click on the scrim closes it (5.7). Default true, false for `role="alertdialog"`: a stray click
554
+ * outside shouldn't throw away a typed reason. Escape and the close button still close it. */
555
+ dismissOnScrim?: boolean | undefined;
550
556
  /** Use `alertdialog` for destructive confirmations. */
551
557
  role?: "dialog" | "alertdialog" | undefined;
552
558
  /** Default true. Turn off only for static demos. */
@@ -638,6 +644,7 @@ export interface SideNavProps {
638
644
  }
639
645
  export interface BreadcrumbProps {
640
646
  /** Root first; the last item is the current page. */
647
+ /** An item with neither `href` nor `onClick` is plain text (5.7), for a segment with no page of its own. */
641
648
  items: Array<{
642
649
  label: string;
643
650
  href?: string | undefined;
@@ -665,6 +672,9 @@ export interface DropdownMenuProps {
665
672
  label?: string | undefined;
666
673
  /** Router link for items with `href`. (4.19) */
667
674
  linkComponent?: React$1.ElementType | undefined;
675
+ /** Content above the items (5.7), e.g. name, email and role in an account menu. Not an item: arrow keys skip
676
+ * it; it is the menu's accessible description (`aria-describedby`). */
677
+ header?: React$1.ReactNode | undefined;
668
678
  }
669
679
  export interface ComboboxOption {
670
680
  value: string;
@@ -865,6 +875,8 @@ export interface DrawerProps {
865
875
  footer?: React$1.ReactNode | undefined;
866
876
  /** Scrim click and Escape close it. Default true. */
867
877
  dismissible?: boolean | undefined;
878
+ /** Whether a click on the scrim closes it (5.7). Default true; Escape and the close button still close it. */
879
+ dismissOnScrim?: boolean | undefined;
868
880
  /** Default true: focus moves to the element with `data-autofocus`, else the first control in the body. False only for static demos. */
869
881
  autoFocus?: boolean | undefined;
870
882
  /** Needed when there is no title. */
@@ -905,7 +917,8 @@ export interface AppShellProps {
905
917
  children?: React$1.ReactNode | undefined;
906
918
  navLabel?: string | undefined;
907
919
  menuLabel?: string | undefined;
908
- /** id of `<main>`, for a skip link. Default `main`. */
920
+ /** id of `<main>`, for a skip link. Default `main`. `<main>` has `tabIndex={-1}` (5.7), so a skip link or
921
+ * `document.getElementById(mainId).focus()` moves focus there (no ring is drawn on it). */
909
922
  mainId?: string | undefined;
910
923
  /** A BottomNav for phones (4.19). Shown below its `hideFrom` breakpoint; the content keeps room for it, and a
911
924
  * viewport ActionBar sits on top of it. With a `bottomNav` and no `nav`, there is no menu button. */
@@ -979,6 +992,9 @@ export interface BottomNavItem {
979
992
  badge?: boolean | undefined;
980
993
  /** Read after the label when `badge` is set, e.g. "new". */
981
994
  badgeLabel?: string | undefined;
995
+ /** The full name for screen readers when `label` is shortened to fit (5.7), e.g. label "Konto", ariaLabel
996
+ * "Mitt konto". Include the visible label in it (WCAG 2.5.3). The count or badge is still appended. */
997
+ ariaLabel?: string | undefined;
982
998
  }
983
999
  export interface BottomNavProps {
984
1000
  /** 2–5 items. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-tokens",
3
- "version": "5.6.0",
3
+ "version": "5.7.1",
4
4
  "description": "AURA Design System — tokens (CSS variables, Tailwind preset, Figma variables), theme contrast checks and token lint.",
5
5
  "main": "tailwind.tokens.cjs",
6
6
  "types": "components/index.d.ts",
package/tokens.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.6.0",
2
+ "version": "5.7.1",
3
3
  "meta": {
4
4
  "name": "AURA Design System",
5
5
  "tier": "3-tier",