@jirawatpyk/aura-react 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/README.md +13 -0
- package/dist/aura.bundle.js +76 -31
- package/dist/cjs/index.cjs +76 -31
- package/dist/esm/AppShell.js +1 -1
- package/dist/esm/BottomNav.js +4 -1
- package/dist/esm/Breadcrumb.js +4 -1
- package/dist/esm/Dialog.js +24 -2
- package/dist/esm/DropdownMenu.js +1 -0
- package/dist/esm/Menu.js +43 -27
- package/dist/index.d.cts +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/styles.css +19 -2
- package/dist/styles.layer.css +19 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -186,6 +186,19 @@ 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.7.1 — SideNav labels wrap
|
|
190
|
+
|
|
191
|
+
- **SideNav** (item 63): a long label wraps to a second line instead of ending in an ellipsis, so Thai and Swedish names read in full in the 240px nav and the phone drawer. One-line rows stay 36px (44px on touch); a two-line row grows to 44px with its icon centred. Past two lines the label clamps; the accessible name is always complete. The collapsed rail is unchanged.
|
|
192
|
+
|
|
193
|
+
## 5.7 — Chamber-OS addendum 5 (shell details)
|
|
194
|
+
|
|
195
|
+
- **DropdownMenu `header`**: content above the items, e.g. name, email and role in an account menu. It sits outside `role="menu"` (arrow keys, Home/End skip it; clicking it keeps focus on the item) and is the menu's accessible description (`aria-describedby`). Screen readers differ in whether they speak a menu's description on open; keep the essentials (who is signed in) in the trigger's name too if they must be heard. With a header, the menu's `ref` and `.aura-menu` are the outer box and `role="menu"` is `.aura-menu__list` inside it.
|
|
196
|
+
- **Breadcrumb**: an item with neither `href` nor `onClick` is plain text (`.aura-crumbs__text`), not a button that does nothing.
|
|
197
|
+
- **AppShell** `<main>` has `tabIndex={-1}`, so a skip link or `document.getElementById(mainId)?.focus({ preventScroll: true })` moves focus there when the row you acted on leaves the list. No ring is drawn on the landmark.
|
|
198
|
+
- **Dialog / Drawer `dismissOnScrim`**: `false` keeps it open on a scrim click; Escape and the close button still close it, and focus stays inside. **`role="alertdialog"` now defaults to `false`**, so a stray click outside a confirmation doesn't throw away a typed reason; pass `dismissOnScrim` to get the old behaviour.
|
|
199
|
+
- **BottomNav item `ariaLabel`**: the full name when the visible label is shortened (`label="Konto"`, `ariaLabel="Mitt konto"`); the count or badge words still follow. Include the visible text in it (WCAG 2.5.3).
|
|
200
|
+
- **SideNav** rows are 44px on touch screens (AppShell's phone drawer); 36px with a mouse.
|
|
201
|
+
|
|
189
202
|
## 5.6 — Chamber-OS addendum 4 (selectable rows, richer toasts)
|
|
190
203
|
|
|
191
204
|
- **DataTable** `isRowSelectable={(r) => r.status === 'Awaiting review'}`: a row it rejects shows no checkbox (the cell stays, so columns line up), and select-all, Space, the "N selected" count and `onSelectionChange` skip it. A rejected key passed in through `selected` is never shown as selected and is dropped from your state with one `onSelectionChange` call. `rowSelectDisabledLabel={(r) => …}` names the empty cell for screen readers. Server HTML has no checkbox for those rows.
|
package/dist/aura.bundle.js
CHANGED
|
@@ -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
|
|
889
|
+
const list2 = Array.prototype.slice.call(
|
|
875
890
|
own.current.querySelectorAll('[role^="menuitem"]:not([disabled])')
|
|
876
891
|
);
|
|
877
|
-
const i =
|
|
892
|
+
const i = list2.indexOf(document.activeElement);
|
|
878
893
|
if (e.key === "ArrowDown") {
|
|
879
894
|
e.preventDefault();
|
|
880
|
-
|
|
895
|
+
list2[(i + 1) % list2.length].focus();
|
|
881
896
|
} else if (e.key === "ArrowUp") {
|
|
882
897
|
e.preventDefault();
|
|
883
|
-
|
|
898
|
+
list2[(i - 1 + list2.length) % list2.length].focus();
|
|
884
899
|
} else if (e.key === "Home") {
|
|
885
900
|
e.preventDefault();
|
|
886
|
-
|
|
901
|
+
list2[0].focus();
|
|
887
902
|
} else if (e.key === "End") {
|
|
888
903
|
e.preventDefault();
|
|
889
|
-
|
|
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(
|
|
916
|
+
function groupItems(list2) {
|
|
902
917
|
const out = [];
|
|
903
|
-
|
|
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
|
|
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
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
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
|
-
|
|
973
|
-
|
|
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(
|
|
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(
|
|
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)
|
|
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
|
-
|
|
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
|
}))
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -810,6 +810,8 @@ var Menu = React6.forwardRef(function Menu2(props, ref) {
|
|
|
810
810
|
const pos = posState[0], setPos = posState[1];
|
|
811
811
|
const items2 = props.items || [];
|
|
812
812
|
const mounted = useMounted();
|
|
813
|
+
const headerId = uid();
|
|
814
|
+
const hasHeader = props.header != null && props.header !== false && props.header !== "";
|
|
813
815
|
const Link = useLinkComponent(props.linkComponent);
|
|
814
816
|
useIsoLayoutEffect(
|
|
815
817
|
function() {
|
|
@@ -827,7 +829,20 @@ var Menu = React6.forwardRef(function Menu2(props, ref) {
|
|
|
827
829
|
const left = Math.max(8, Math.min(r.right - mw, window.innerWidth - mw - 8));
|
|
828
830
|
setPos({ top, left, maxHeight });
|
|
829
831
|
},
|
|
830
|
-
[props.anchor, mounted]
|
|
832
|
+
[props.anchor, mounted, hasHeader]
|
|
833
|
+
);
|
|
834
|
+
const hadHeader = React6.useRef(hasHeader);
|
|
835
|
+
React6.useEffect(
|
|
836
|
+
function() {
|
|
837
|
+
if (hadHeader.current === hasHeader) return;
|
|
838
|
+
hadHeader.current = hasHeader;
|
|
839
|
+
const a = document.activeElement;
|
|
840
|
+
if (own.current && (!a || a === document.body)) {
|
|
841
|
+
const first = own.current.querySelector('[role^="menuitem"]:not([disabled])');
|
|
842
|
+
if (first) first.focus();
|
|
843
|
+
}
|
|
844
|
+
},
|
|
845
|
+
[hasHeader]
|
|
831
846
|
);
|
|
832
847
|
React6.useEffect(
|
|
833
848
|
function() {
|
|
@@ -853,22 +868,22 @@ var Menu = React6.forwardRef(function Menu2(props, ref) {
|
|
|
853
868
|
[mounted]
|
|
854
869
|
);
|
|
855
870
|
function onKeyDown(e) {
|
|
856
|
-
const
|
|
871
|
+
const list2 = Array.prototype.slice.call(
|
|
857
872
|
own.current.querySelectorAll('[role^="menuitem"]:not([disabled])')
|
|
858
873
|
);
|
|
859
|
-
const i =
|
|
874
|
+
const i = list2.indexOf(document.activeElement);
|
|
860
875
|
if (e.key === "ArrowDown") {
|
|
861
876
|
e.preventDefault();
|
|
862
|
-
|
|
877
|
+
list2[(i + 1) % list2.length].focus();
|
|
863
878
|
} else if (e.key === "ArrowUp") {
|
|
864
879
|
e.preventDefault();
|
|
865
|
-
|
|
880
|
+
list2[(i - 1 + list2.length) % list2.length].focus();
|
|
866
881
|
} else if (e.key === "Home") {
|
|
867
882
|
e.preventDefault();
|
|
868
|
-
|
|
883
|
+
list2[0].focus();
|
|
869
884
|
} else if (e.key === "End") {
|
|
870
885
|
e.preventDefault();
|
|
871
|
-
|
|
886
|
+
list2[list2.length - 1].focus();
|
|
872
887
|
} else if (e.key === " " && document.activeElement && document.activeElement.tagName === "A") {
|
|
873
888
|
e.preventDefault();
|
|
874
889
|
document.activeElement.click();
|
|
@@ -880,9 +895,9 @@ var Menu = React6.forwardRef(function Menu2(props, ref) {
|
|
|
880
895
|
}
|
|
881
896
|
e.stopPropagation();
|
|
882
897
|
}
|
|
883
|
-
function groupItems(
|
|
898
|
+
function groupItems(list2) {
|
|
884
899
|
const out = [];
|
|
885
|
-
|
|
900
|
+
list2.forEach(function(it, i) {
|
|
886
901
|
const g = it.type === "radio" && it.group ? it.group : null;
|
|
887
902
|
const last = out[out.length - 1];
|
|
888
903
|
if (last && last.group === g && g !== null) last.items.push({ it, i });
|
|
@@ -937,27 +952,28 @@ var Menu = React6.forwardRef(function Menu2(props, ref) {
|
|
|
937
952
|
body
|
|
938
953
|
);
|
|
939
954
|
}
|
|
940
|
-
const
|
|
955
|
+
const style = {
|
|
956
|
+
top: pos ? pos.top : -9999,
|
|
957
|
+
left: pos ? pos.left : -9999,
|
|
958
|
+
maxHeight: pos && pos.maxHeight ? pos.maxHeight : void 0
|
|
959
|
+
};
|
|
960
|
+
const list = groupItems(items2).map(function(block, bi) {
|
|
961
|
+
const rendered = block.items.map(function(x) {
|
|
962
|
+
return renderItem(x.it, x.i);
|
|
963
|
+
});
|
|
964
|
+
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);
|
|
965
|
+
});
|
|
966
|
+
const el = hasHeader ? /* @__PURE__ */ React6.createElement("div", { ref: merged, className: "aura-menu has-header", onKeyDown, style }, /* @__PURE__ */ React6.createElement(
|
|
941
967
|
"div",
|
|
942
968
|
{
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
onKeyDown,
|
|
948
|
-
style: {
|
|
949
|
-
top: pos ? pos.top : -9999,
|
|
950
|
-
left: pos ? pos.left : -9999,
|
|
951
|
-
maxHeight: pos && pos.maxHeight ? pos.maxHeight : void 0
|
|
969
|
+
className: "aura-menu__header",
|
|
970
|
+
id: headerId,
|
|
971
|
+
onMouseDown: function(e) {
|
|
972
|
+
e.preventDefault();
|
|
952
973
|
}
|
|
953
974
|
},
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
return renderItem(x.it, x.i);
|
|
957
|
-
});
|
|
958
|
-
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);
|
|
959
|
-
})
|
|
960
|
-
);
|
|
975
|
+
props.header
|
|
976
|
+
), /* @__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);
|
|
961
977
|
return mounted ? (0, import_react_dom.createPortal)(el, document.body) : null;
|
|
962
978
|
});
|
|
963
979
|
|
|
@@ -997,6 +1013,7 @@ var DropdownMenu = React7.forwardRef(function DropdownMenu2(props, ref) {
|
|
|
997
1013
|
label: props.label,
|
|
998
1014
|
items: props.items,
|
|
999
1015
|
linkComponent: props.linkComponent,
|
|
1016
|
+
header: props.header,
|
|
1000
1017
|
onClose: function(restore) {
|
|
1001
1018
|
setAnchor(null);
|
|
1002
1019
|
if (restore && typeof anchor.focus === "function") anchor.focus();
|
|
@@ -3996,6 +4013,7 @@ var Dialog = React27.forwardRef(function Dialog2(props, ref) {
|
|
|
3996
4013
|
function close() {
|
|
3997
4014
|
if (props.dismissible !== false && props.onClose) props.onClose();
|
|
3998
4015
|
}
|
|
4016
|
+
const scrimCloses = props.dismissible !== false && (props.dismissOnScrim !== void 0 ? props.dismissOnScrim : props.role !== "alertdialog");
|
|
3999
4017
|
const modal = useModal(props.open, own, {
|
|
4000
4018
|
autoFocus: props.autoFocus,
|
|
4001
4019
|
onEscape: close,
|
|
@@ -4004,7 +4022,17 @@ var Dialog = React27.forwardRef(function Dialog2(props, ref) {
|
|
|
4004
4022
|
});
|
|
4005
4023
|
if (!modal.ready) return null;
|
|
4006
4024
|
return (0, import_react_dom8.createPortal)(
|
|
4007
|
-
/* @__PURE__ */ React27.createElement("div", { className: "aura-dialog-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React27.createElement(
|
|
4025
|
+
/* @__PURE__ */ React27.createElement("div", { className: "aura-dialog-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React27.createElement(
|
|
4026
|
+
"div",
|
|
4027
|
+
{
|
|
4028
|
+
className: "aura-scrim",
|
|
4029
|
+
onClick: scrimCloses ? close : void 0,
|
|
4030
|
+
onMouseDown: scrimCloses ? void 0 : function(e) {
|
|
4031
|
+
e.preventDefault();
|
|
4032
|
+
},
|
|
4033
|
+
"aria-hidden": true
|
|
4034
|
+
}
|
|
4035
|
+
), /* @__PURE__ */ React27.createElement(
|
|
4008
4036
|
"div",
|
|
4009
4037
|
{
|
|
4010
4038
|
ref: merged,
|
|
@@ -4038,8 +4066,19 @@ var Drawer = React27.forwardRef(function Drawer2(props, ref) {
|
|
|
4038
4066
|
});
|
|
4039
4067
|
if (!modal.ready) return null;
|
|
4040
4068
|
const side = props.side === "left" ? "left" : "right";
|
|
4069
|
+
const drawerScrimCloses = props.dismissible !== false && props.dismissOnScrim !== false;
|
|
4041
4070
|
return (0, import_react_dom8.createPortal)(
|
|
4042
|
-
/* @__PURE__ */ React27.createElement("div", { className: "aura-dialog-layer aura-drawer-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React27.createElement(
|
|
4071
|
+
/* @__PURE__ */ React27.createElement("div", { className: "aura-dialog-layer aura-drawer-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React27.createElement(
|
|
4072
|
+
"div",
|
|
4073
|
+
{
|
|
4074
|
+
className: "aura-scrim",
|
|
4075
|
+
onClick: drawerScrimCloses ? close : void 0,
|
|
4076
|
+
onMouseDown: !drawerScrimCloses ? function(e) {
|
|
4077
|
+
e.preventDefault();
|
|
4078
|
+
} : void 0,
|
|
4079
|
+
"aria-hidden": true
|
|
4080
|
+
}
|
|
4081
|
+
), /* @__PURE__ */ React27.createElement(
|
|
4043
4082
|
"div",
|
|
4044
4083
|
{
|
|
4045
4084
|
ref: merged,
|
|
@@ -5708,7 +5747,10 @@ var Breadcrumb = React32.forwardRef(function Breadcrumb2(props, ref) {
|
|
|
5708
5747
|
const items2 = props.items || [];
|
|
5709
5748
|
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) {
|
|
5710
5749
|
const last = i === items2.length - 1;
|
|
5711
|
-
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)
|
|
5750
|
+
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) : (
|
|
5751
|
+
/* 5.7: a segment with no page and no action is text, not a button that does nothing. */
|
|
5752
|
+
/* @__PURE__ */ React32.createElement("span", { className: "aura-crumbs__text" }, it.label)
|
|
5753
|
+
), last ? null : /* @__PURE__ */ React32.createElement(Icon, { name: "chevron-right", size: 12, className: "aura-crumbs__sep" }));
|
|
5712
5754
|
})));
|
|
5713
5755
|
});
|
|
5714
5756
|
|
|
@@ -5903,7 +5945,7 @@ var AppShell = React38.forwardRef(function AppShell2(props, ref) {
|
|
|
5903
5945
|
},
|
|
5904
5946
|
"aria-expanded": open
|
|
5905
5947
|
}
|
|
5906
|
-
) : 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));
|
|
5948
|
+
) : 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));
|
|
5907
5949
|
});
|
|
5908
5950
|
|
|
5909
5951
|
// src/ActionBar.tsx
|
|
@@ -6058,8 +6100,11 @@ var BottomNav = React42.forwardRef(function BottomNav2(props, ref) {
|
|
|
6058
6100
|
/* @__PURE__ */ React42.createElement("ul", { className: "aura-bottomnav__list" }, props.items.map(function(it) {
|
|
6059
6101
|
const on = active === it.id;
|
|
6060
6102
|
const count = it.count != null && it.count > 0 ? it.count > 99 ? "99+" : String(it.count) : null;
|
|
6103
|
+
const suffix = count || it.badge && it.badgeLabel ? " (" + (count || it.badgeLabel) + ")" : "";
|
|
6061
6104
|
const common = {
|
|
6062
6105
|
className: cx("aura-bottomnav__item", on && "is-active"),
|
|
6106
|
+
/* 5.7: a full name when the label is shortened; the count / badge words still follow. */
|
|
6107
|
+
"aria-label": it.ariaLabel ? it.ariaLabel + suffix : void 0,
|
|
6063
6108
|
"aria-current": on ? "page" : void 0,
|
|
6064
6109
|
onClick: function(e) {
|
|
6065
6110
|
if (!it.href) e.preventDefault();
|
|
@@ -6070,7 +6115,7 @@ var BottomNav = React42.forwardRef(function BottomNav2(props, ref) {
|
|
|
6070
6115
|
const inner = [
|
|
6071
6116
|
/* @__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),
|
|
6072
6117
|
/* @__PURE__ */ React42.createElement("span", { key: "l", className: "aura-bottomnav__label" }, it.label),
|
|
6073
|
-
|
|
6118
|
+
suffix && !it.ariaLabel ? /* @__PURE__ */ React42.createElement("span", { key: "s", className: "aura-sr-only" }, suffix) : null
|
|
6074
6119
|
];
|
|
6075
6120
|
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));
|
|
6076
6121
|
}))
|
package/dist/esm/AppShell.js
CHANGED
|
@@ -59,7 +59,7 @@ const AppShell = React.forwardRef(function AppShell2(props, ref) {
|
|
|
59
59
|
},
|
|
60
60
|
"aria-expanded": open
|
|
61
61
|
}
|
|
62
|
-
) : null, /* @__PURE__ */ React.createElement("div", { className: "aura-shell__bar-content" }, props.header)) : null, /* @__PURE__ */ React.createElement("main", { className: "aura-shell__content", id: props.mainId || "main" }, props.children), props.bottomNav || null));
|
|
62
|
+
) : null, /* @__PURE__ */ React.createElement("div", { className: "aura-shell__bar-content" }, props.header)) : null, /* @__PURE__ */ React.createElement("main", { className: "aura-shell__content", id: props.mainId || "main", tabIndex: -1 }, props.children), props.bottomNav || null));
|
|
63
63
|
});
|
|
64
64
|
export {
|
|
65
65
|
AppShell
|
package/dist/esm/BottomNav.js
CHANGED
|
@@ -23,8 +23,11 @@ const BottomNav = React.forwardRef(function BottomNav2(props, ref) {
|
|
|
23
23
|
/* @__PURE__ */ React.createElement("ul", { className: "aura-bottomnav__list" }, props.items.map(function(it) {
|
|
24
24
|
const on = active === it.id;
|
|
25
25
|
const count = it.count != null && it.count > 0 ? it.count > 99 ? "99+" : String(it.count) : null;
|
|
26
|
+
const suffix = count || it.badge && it.badgeLabel ? " (" + (count || it.badgeLabel) + ")" : "";
|
|
26
27
|
const common = {
|
|
27
28
|
className: cx("aura-bottomnav__item", on && "is-active"),
|
|
29
|
+
/* 5.7: a full name when the label is shortened; the count / badge words still follow. */
|
|
30
|
+
"aria-label": it.ariaLabel ? it.ariaLabel + suffix : void 0,
|
|
28
31
|
"aria-current": on ? "page" : void 0,
|
|
29
32
|
onClick: function(e) {
|
|
30
33
|
if (!it.href) e.preventDefault();
|
|
@@ -35,7 +38,7 @@ const BottomNav = React.forwardRef(function BottomNav2(props, ref) {
|
|
|
35
38
|
const inner = [
|
|
36
39
|
/* @__PURE__ */ React.createElement("span", { key: "i", className: "aura-bottomnav__icon" }, /* @__PURE__ */ React.createElement(Icon, { name: it.icon, size: "md" }), count ? /* @__PURE__ */ React.createElement("span", { className: "aura-bottomnav__count", "aria-hidden": "true" }, count) : it.badge ? /* @__PURE__ */ React.createElement("span", { className: "aura-bottomnav__dot", "aria-hidden": "true" }) : null),
|
|
37
40
|
/* @__PURE__ */ React.createElement("span", { key: "l", className: "aura-bottomnav__label" }, it.label),
|
|
38
|
-
|
|
41
|
+
suffix && !it.ariaLabel ? /* @__PURE__ */ React.createElement("span", { key: "s", className: "aura-sr-only" }, suffix) : null
|
|
39
42
|
];
|
|
40
43
|
return /* @__PURE__ */ React.createElement("li", { key: it.id, className: "aura-bottomnav__cell" }, it.href ? /* @__PURE__ */ React.createElement(Link, { href: it.href, ...common }, inner) : /* @__PURE__ */ React.createElement("button", { type: "button", ...common }, inner));
|
|
41
44
|
}))
|
package/dist/esm/Breadcrumb.js
CHANGED
|
@@ -9,7 +9,10 @@ const Breadcrumb = React.forwardRef(function Breadcrumb2(props, ref) {
|
|
|
9
9
|
const items = props.items || [];
|
|
10
10
|
return /* @__PURE__ */ React.createElement("nav", { ref, "aria-label": props.label || t.breadcrumb, className: cx("aura-crumbs", props.className) }, /* @__PURE__ */ React.createElement("ol", null, items.map(function(it, i) {
|
|
11
11
|
const last = i === items.length - 1;
|
|
12
|
-
return /* @__PURE__ */ React.createElement("li", { key: i }, last ? /* @__PURE__ */ React.createElement("span", { "aria-current": "page", className: "aura-crumbs__current" }, it.label) : it.href ? /* @__PURE__ */ React.createElement(Link, { href: it.href, onClick: it.onClick }, it.label) : /* @__PURE__ */ React.createElement("button", { type: "button", onClick: it.onClick }, it.label)
|
|
12
|
+
return /* @__PURE__ */ React.createElement("li", { key: i }, last ? /* @__PURE__ */ React.createElement("span", { "aria-current": "page", className: "aura-crumbs__current" }, it.label) : it.href ? /* @__PURE__ */ React.createElement(Link, { href: it.href, onClick: it.onClick }, it.label) : it.onClick ? /* @__PURE__ */ React.createElement("button", { type: "button", onClick: it.onClick }, it.label) : (
|
|
13
|
+
/* 5.7: a segment with no page and no action is text, not a button that does nothing. */
|
|
14
|
+
/* @__PURE__ */ React.createElement("span", { className: "aura-crumbs__text" }, it.label)
|
|
15
|
+
), last ? null : /* @__PURE__ */ React.createElement(Icon, { name: "chevron-right", size: 12, className: "aura-crumbs__sep" }));
|
|
13
16
|
})));
|
|
14
17
|
});
|
|
15
18
|
export {
|
package/dist/esm/Dialog.js
CHANGED
|
@@ -12,6 +12,7 @@ const Dialog = React.forwardRef(function Dialog2(props, ref) {
|
|
|
12
12
|
function close() {
|
|
13
13
|
if (props.dismissible !== false && props.onClose) props.onClose();
|
|
14
14
|
}
|
|
15
|
+
const scrimCloses = props.dismissible !== false && (props.dismissOnScrim !== void 0 ? props.dismissOnScrim : props.role !== "alertdialog");
|
|
15
16
|
const modal = useModal(props.open, own, {
|
|
16
17
|
autoFocus: props.autoFocus,
|
|
17
18
|
onEscape: close,
|
|
@@ -20,7 +21,17 @@ const Dialog = React.forwardRef(function Dialog2(props, ref) {
|
|
|
20
21
|
});
|
|
21
22
|
if (!modal.ready) return null;
|
|
22
23
|
return createPortal(
|
|
23
|
-
/* @__PURE__ */ React.createElement("div", { className: "aura-dialog-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React.createElement(
|
|
24
|
+
/* @__PURE__ */ React.createElement("div", { className: "aura-dialog-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React.createElement(
|
|
25
|
+
"div",
|
|
26
|
+
{
|
|
27
|
+
className: "aura-scrim",
|
|
28
|
+
onClick: scrimCloses ? close : void 0,
|
|
29
|
+
onMouseDown: scrimCloses ? void 0 : function(e) {
|
|
30
|
+
e.preventDefault();
|
|
31
|
+
},
|
|
32
|
+
"aria-hidden": true
|
|
33
|
+
}
|
|
34
|
+
), /* @__PURE__ */ React.createElement(
|
|
24
35
|
"div",
|
|
25
36
|
{
|
|
26
37
|
ref: merged,
|
|
@@ -54,8 +65,19 @@ const Drawer = React.forwardRef(function Drawer2(props, ref) {
|
|
|
54
65
|
});
|
|
55
66
|
if (!modal.ready) return null;
|
|
56
67
|
const side = props.side === "left" ? "left" : "right";
|
|
68
|
+
const drawerScrimCloses = props.dismissible !== false && props.dismissOnScrim !== false;
|
|
57
69
|
return createPortal(
|
|
58
|
-
/* @__PURE__ */ React.createElement("div", { className: "aura-dialog-layer aura-drawer-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React.createElement(
|
|
70
|
+
/* @__PURE__ */ React.createElement("div", { className: "aura-dialog-layer aura-drawer-layer", "data-density": density, onKeyDown: modal.onKeyDown }, /* @__PURE__ */ React.createElement(
|
|
71
|
+
"div",
|
|
72
|
+
{
|
|
73
|
+
className: "aura-scrim",
|
|
74
|
+
onClick: drawerScrimCloses ? close : void 0,
|
|
75
|
+
onMouseDown: !drawerScrimCloses ? function(e) {
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
} : void 0,
|
|
78
|
+
"aria-hidden": true
|
|
79
|
+
}
|
|
80
|
+
), /* @__PURE__ */ React.createElement(
|
|
59
81
|
"div",
|
|
60
82
|
{
|
|
61
83
|
ref: merged,
|
package/dist/esm/DropdownMenu.js
CHANGED
|
@@ -36,6 +36,7 @@ const DropdownMenu = React.forwardRef(function DropdownMenu2(props, ref) {
|
|
|
36
36
|
label: props.label,
|
|
37
37
|
items: props.items,
|
|
38
38
|
linkComponent: props.linkComponent,
|
|
39
|
+
header: props.header,
|
|
39
40
|
onClose: function(restore) {
|
|
40
41
|
setAnchor(null);
|
|
41
42
|
if (restore && typeof anchor.focus === "function") anchor.focus();
|
package/dist/esm/Menu.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
|
-
import { cx, useIsoLayoutEffect, useMounted, useMergedRef } from "./internal.js";
|
|
4
|
+
import { cx, uid, useIsoLayoutEffect, useMounted, useMergedRef } from "./internal.js";
|
|
5
5
|
import { Icon } from "./Icon.js";
|
|
6
6
|
import { useLinkComponent } from "./locale.js";
|
|
7
7
|
const Menu = React.forwardRef(function Menu2(props, ref) {
|
|
@@ -10,6 +10,8 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
|
|
|
10
10
|
const pos = posState[0], setPos = posState[1];
|
|
11
11
|
const items = props.items || [];
|
|
12
12
|
const mounted = useMounted();
|
|
13
|
+
const headerId = uid();
|
|
14
|
+
const hasHeader = props.header != null && props.header !== false && props.header !== "";
|
|
13
15
|
const Link = useLinkComponent(props.linkComponent);
|
|
14
16
|
useIsoLayoutEffect(
|
|
15
17
|
function() {
|
|
@@ -27,7 +29,20 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
|
|
|
27
29
|
const left = Math.max(8, Math.min(r.right - mw, window.innerWidth - mw - 8));
|
|
28
30
|
setPos({ top, left, maxHeight });
|
|
29
31
|
},
|
|
30
|
-
[props.anchor, mounted]
|
|
32
|
+
[props.anchor, mounted, hasHeader]
|
|
33
|
+
);
|
|
34
|
+
const hadHeader = React.useRef(hasHeader);
|
|
35
|
+
React.useEffect(
|
|
36
|
+
function() {
|
|
37
|
+
if (hadHeader.current === hasHeader) return;
|
|
38
|
+
hadHeader.current = hasHeader;
|
|
39
|
+
const a = document.activeElement;
|
|
40
|
+
if (own.current && (!a || a === document.body)) {
|
|
41
|
+
const first = own.current.querySelector('[role^="menuitem"]:not([disabled])');
|
|
42
|
+
if (first) first.focus();
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
[hasHeader]
|
|
31
46
|
);
|
|
32
47
|
React.useEffect(
|
|
33
48
|
function() {
|
|
@@ -53,22 +68,22 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
|
|
|
53
68
|
[mounted]
|
|
54
69
|
);
|
|
55
70
|
function onKeyDown(e) {
|
|
56
|
-
const
|
|
71
|
+
const list2 = Array.prototype.slice.call(
|
|
57
72
|
own.current.querySelectorAll('[role^="menuitem"]:not([disabled])')
|
|
58
73
|
);
|
|
59
|
-
const i =
|
|
74
|
+
const i = list2.indexOf(document.activeElement);
|
|
60
75
|
if (e.key === "ArrowDown") {
|
|
61
76
|
e.preventDefault();
|
|
62
|
-
|
|
77
|
+
list2[(i + 1) % list2.length].focus();
|
|
63
78
|
} else if (e.key === "ArrowUp") {
|
|
64
79
|
e.preventDefault();
|
|
65
|
-
|
|
80
|
+
list2[(i - 1 + list2.length) % list2.length].focus();
|
|
66
81
|
} else if (e.key === "Home") {
|
|
67
82
|
e.preventDefault();
|
|
68
|
-
|
|
83
|
+
list2[0].focus();
|
|
69
84
|
} else if (e.key === "End") {
|
|
70
85
|
e.preventDefault();
|
|
71
|
-
|
|
86
|
+
list2[list2.length - 1].focus();
|
|
72
87
|
} else if (e.key === " " && document.activeElement && document.activeElement.tagName === "A") {
|
|
73
88
|
e.preventDefault();
|
|
74
89
|
document.activeElement.click();
|
|
@@ -80,9 +95,9 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
|
|
|
80
95
|
}
|
|
81
96
|
e.stopPropagation();
|
|
82
97
|
}
|
|
83
|
-
function groupItems(
|
|
98
|
+
function groupItems(list2) {
|
|
84
99
|
const out = [];
|
|
85
|
-
|
|
100
|
+
list2.forEach(function(it, i) {
|
|
86
101
|
const g = it.type === "radio" && it.group ? it.group : null;
|
|
87
102
|
const last = out[out.length - 1];
|
|
88
103
|
if (last && last.group === g && g !== null) last.items.push({ it, i });
|
|
@@ -137,27 +152,28 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
|
|
|
137
152
|
body
|
|
138
153
|
);
|
|
139
154
|
}
|
|
140
|
-
const
|
|
155
|
+
const style = {
|
|
156
|
+
top: pos ? pos.top : -9999,
|
|
157
|
+
left: pos ? pos.left : -9999,
|
|
158
|
+
maxHeight: pos && pos.maxHeight ? pos.maxHeight : void 0
|
|
159
|
+
};
|
|
160
|
+
const list = groupItems(items).map(function(block, bi) {
|
|
161
|
+
const rendered = block.items.map(function(x) {
|
|
162
|
+
return renderItem(x.it, x.i);
|
|
163
|
+
});
|
|
164
|
+
return block.group ? /* @__PURE__ */ React.createElement("div", { key: "g" + bi, role: "group", "aria-label": block.group, className: "aura-menu__group" }, rendered) : /* @__PURE__ */ React.createElement(React.Fragment, { key: "f" + bi }, rendered);
|
|
165
|
+
});
|
|
166
|
+
const el = hasHeader ? /* @__PURE__ */ React.createElement("div", { ref: merged, className: "aura-menu has-header", onKeyDown, style }, /* @__PURE__ */ React.createElement(
|
|
141
167
|
"div",
|
|
142
168
|
{
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
onKeyDown,
|
|
148
|
-
style: {
|
|
149
|
-
top: pos ? pos.top : -9999,
|
|
150
|
-
left: pos ? pos.left : -9999,
|
|
151
|
-
maxHeight: pos && pos.maxHeight ? pos.maxHeight : void 0
|
|
169
|
+
className: "aura-menu__header",
|
|
170
|
+
id: headerId,
|
|
171
|
+
onMouseDown: function(e) {
|
|
172
|
+
e.preventDefault();
|
|
152
173
|
}
|
|
153
174
|
},
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return renderItem(x.it, x.i);
|
|
157
|
-
});
|
|
158
|
-
return block.group ? /* @__PURE__ */ React.createElement("div", { key: "g" + bi, role: "group", "aria-label": block.group, className: "aura-menu__group" }, rendered) : /* @__PURE__ */ React.createElement(React.Fragment, { key: "f" + bi }, rendered);
|
|
159
|
-
})
|
|
160
|
-
);
|
|
175
|
+
props.header
|
|
176
|
+
), /* @__PURE__ */ React.createElement("div", { role: "menu", "aria-label": props.label, "aria-describedby": headerId, className: "aura-menu__list" }, list)) : /* @__PURE__ */ React.createElement("div", { ref: merged, role: "menu", "aria-label": props.label, className: "aura-menu", onKeyDown, style }, list);
|
|
161
177
|
return mounted ? createPortal(el, document.body) : null;
|
|
162
178
|
});
|
|
163
179
|
export {
|
package/dist/index.d.cts
CHANGED
|
@@ -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/dist/index.d.ts
CHANGED
|
@@ -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/dist/styles.css
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
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. */
|
package/dist/styles.layer.css
CHANGED
|
@@ -249,6 +249,12 @@ a.aura-menu__item { text-decoration: none; box-sizing: border-box; }
|
|
|
249
249
|
}
|
|
250
250
|
.aura-menu__radio.is-on { border-color: var(--aura-button-primary-bg); }
|
|
251
251
|
.aura-menu__radio.is-on::after { content: ''; width: 8px; height: 8px; border-radius: var(--aura-radius-full); background: var(--aura-button-primary-bg); }
|
|
252
|
+
/* 5.7: a header above the items (who is signed in), set off by a hairline like a separator. */
|
|
253
|
+
.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; }
|
|
254
|
+
.aura-menu__header > * { margin: 0; }
|
|
255
|
+
/* Stays in view when a long menu scrolls. */
|
|
256
|
+
.aura-menu.has-header .aura-menu__header { position: sticky; top: calc(-1 * var(--aura-space-1)); z-index: 1; background: var(--aura-bg-surface); }
|
|
257
|
+
.aura-menu__header strong, .aura-menu__header b { color: var(--aura-fg-primary); font-weight: 500; font-size: 13px; }
|
|
252
258
|
.aura-menu__sep { height: 1px; margin: var(--aura-space-1) calc(-1 * var(--aura-space-1)); background: var(--aura-border-default); }
|
|
253
259
|
|
|
254
260
|
/* Footer + pager */
|
|
@@ -637,7 +643,7 @@ a.aura-tab { text-decoration: none; }
|
|
|
637
643
|
.aura-nav__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
638
644
|
.aura-nav__item {
|
|
639
645
|
box-sizing: border-box; display: flex; align-items: center; gap: var(--aura-space-3); width: 100%;
|
|
640
|
-
height: 36px; padding:
|
|
646
|
+
min-height: 36px; padding: var(--aura-space-1) var(--aura-space-3); border: 0; border-radius: var(--aura-radius-sm);
|
|
641
647
|
background: transparent; color: var(--aura-fg-secondary); font: inherit; font-size: 13px; font-weight: 500;
|
|
642
648
|
text-decoration: none; text-align: left; cursor: pointer;
|
|
643
649
|
transition: background var(--aura-duration-fast) var(--aura-ease), color var(--aura-duration-fast) var(--aura-ease);
|
|
@@ -646,7 +652,14 @@ a.aura-tab { text-decoration: none; }
|
|
|
646
652
|
.aura-nav__item.is-active { background: var(--aura-bg-selected); color: var(--aura-fg-primary); }
|
|
647
653
|
.aura-nav__item.is-active .aura-icon { color: var(--aura-fg-accent); }
|
|
648
654
|
.aura-nav__item:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: -2px; }
|
|
649
|
-
|
|
655
|
+
/* Touch (5.7): rows are 44px on coarse pointers (AppShell's phone drawer); desktop keeps 36px. */
|
|
656
|
+
@media (pointer: coarse) { .aura-nav__item { min-height: var(--aura-touch-target); } }
|
|
657
|
+
/* 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
|
|
658
|
+
* way to read the rest — Thai and Swedish names in a 240px nav or the phone drawer. Beyond two lines it clamps. */
|
|
659
|
+
.aura-nav__label {
|
|
660
|
+
flex: 1; min-width: 0; line-height: 18px; overflow: hidden; overflow-wrap: anywhere;
|
|
661
|
+
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
|
|
662
|
+
}
|
|
650
663
|
.aura-nav__count { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--aura-fg-secondary); }
|
|
651
664
|
.aura-nav__badge { display: inline-flex; align-items: center; flex: none; }
|
|
652
665
|
/* Groups: a disclosure button, its items indented one step per level. */
|
|
@@ -691,6 +704,8 @@ a.aura-tab { text-decoration: none; }
|
|
|
691
704
|
.aura-crumbs a:hover, .aura-crumbs button:hover { color: var(--aura-fg-primary); text-decoration: underline; text-underline-offset: 3px; }
|
|
692
705
|
.aura-crumbs a:focus-visible, .aura-crumbs button:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 2px; }
|
|
693
706
|
.aura-crumbs__current { color: var(--aura-fg-primary); font-weight: 500; }
|
|
707
|
+
/* 5.7: a segment with no page of its own — the links' colour, not interactive. */
|
|
708
|
+
.aura-crumbs__text { color: var(--aura-fg-secondary); }
|
|
694
709
|
.aura-crumbs__sep { color: var(--aura-fg-tertiary); }
|
|
695
710
|
|
|
696
711
|
/* ---------- Avatar ---------- */
|
|
@@ -886,6 +901,8 @@ a.aura-tab { text-decoration: none; }
|
|
|
886
901
|
}
|
|
887
902
|
.aura-shell__bar-content { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--aura-space-3); }
|
|
888
903
|
.aura-shell__content { flex: 1; min-width: 0; padding: var(--aura-space-6) var(--aura-space-4); }
|
|
904
|
+
/* 5.7: <main> takes focus (tabIndex -1) for skip links and "the row you acted on is gone"; a landmark gets no ring. */
|
|
905
|
+
.aura-shell__content:focus { outline: none; }
|
|
889
906
|
@media (min-width: 640px) { .aura-shell__content { padding: var(--aura-space-6); } }
|
|
890
907
|
@media (min-width: 1024px) { .aura-shell__content { padding: var(--aura-space-8); } }
|
|
891
908
|
/* The shell already pads its content: a Container directly inside only caps the width. */
|
package/package.json
CHANGED