@jirawatpyk/aura-react 5.44.0 → 5.46.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 +33 -0
- package/dist/aura.bundle.js +326 -228
- package/dist/cjs/index.cjs +326 -228
- package/dist/esm/PageHeader.js +36 -4
- package/dist/esm/PageHeaderClient.js +68 -0
- package/dist/esm/index.js +1 -1
- package/dist/index.d.cts +32 -1
- package/dist/index.d.ts +32 -1
- package/dist/server/index.cjs +36 -4
- package/dist/server/index.d.cts +32 -1
- package/dist/server/index.d.ts +32 -1
- package/dist/server/index.js +36 -4
- package/dist/styles.css +56 -5
- package/dist/styles.layer.css +56 -5
- package/package.json +1 -1
package/dist/esm/PageHeader.js
CHANGED
|
@@ -11,7 +11,25 @@ const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
|
|
|
11
11
|
const level = props.headingLevel || 1;
|
|
12
12
|
const below = props.actionsFullWidthBelow;
|
|
13
13
|
const hide = props.titleHideBelow;
|
|
14
|
-
const
|
|
14
|
+
const shown = function(n) {
|
|
15
|
+
return n != null && n !== false && n !== "";
|
|
16
|
+
};
|
|
17
|
+
const hasMeta = shown(props.meta) || shown(props.subtitle) || shown(props.titleAddon);
|
|
18
|
+
const size = props.size === "hero" || props.size === "hero-lg" ? props.size : null;
|
|
19
|
+
const eyebrow = props.eyebrow;
|
|
20
|
+
const plainEyebrow = typeof eyebrow === "string" || typeof eyebrow === "number";
|
|
21
|
+
const heading = h(
|
|
22
|
+
"h" + level,
|
|
23
|
+
{
|
|
24
|
+
className: "aura-page-header__title",
|
|
25
|
+
id: props.titleId,
|
|
26
|
+
tabIndex: props.focusTitleOnMount ? -1 : void 0,
|
|
27
|
+
"data-aura-focus-on-mount": props.focusTitleOnMount ? "" : void 0
|
|
28
|
+
},
|
|
29
|
+
props.title
|
|
30
|
+
);
|
|
31
|
+
const hasActions = props.actions != null && props.actions !== false;
|
|
32
|
+
const bar = hasActions && (props.actionsBarBelow === "sm" || props.actionsBarBelow === "md") ? props.actionsBarBelow : null;
|
|
15
33
|
return h(
|
|
16
34
|
"div",
|
|
17
35
|
Object.assign(attrs, {
|
|
@@ -21,6 +39,9 @@ const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
|
|
|
21
39
|
(below === "sm" || below === "md" || below === "lg") && "aura-page-header--actions-full-below-" + below,
|
|
22
40
|
(hide === "sm" || hide === "md" || hide === "lg") && "aura-page-header--title-hide-below-" + hide,
|
|
23
41
|
(hide === "sm" || hide === "md" || hide === "lg") && !hasMeta && "has-no-meta",
|
|
42
|
+
bar && "aura-page-header--actions-bar-below-" + bar,
|
|
43
|
+
size && "aura-page-header--" + size,
|
|
44
|
+
props.actionsAlign === "start" && "aura-page-header--actions-start",
|
|
24
45
|
props.className
|
|
25
46
|
),
|
|
26
47
|
style: props.style
|
|
@@ -29,11 +50,22 @@ const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
|
|
|
29
50
|
"div",
|
|
30
51
|
{ className: "aura-page-header__text" },
|
|
31
52
|
props.breadcrumb != null && props.breadcrumb !== false ? h("div", { className: "aura-page-header__breadcrumb" }, props.breadcrumb) : null,
|
|
32
|
-
|
|
33
|
-
|
|
53
|
+
shown(eyebrow) ? plainEyebrow ? h("p", { className: "aura-page-header__eyebrow" }, eyebrow) : h("div", { className: "aura-page-header__eyebrow aura-page-header__eyebrow--rich" }, eyebrow) : null,
|
|
54
|
+
shown(props.titleAddon) ? h(
|
|
55
|
+
"div",
|
|
56
|
+
{ className: "aura-page-header__title-row" },
|
|
57
|
+
heading,
|
|
58
|
+
h("div", { className: "aura-page-header__title-addon" }, props.titleAddon)
|
|
59
|
+
) : heading,
|
|
60
|
+
shown(props.subtitle) ? h("div", { className: "aura-page-header__subtitle" }, props.subtitle) : null,
|
|
34
61
|
props.meta != null && props.meta !== false ? h("div", { className: "aura-page-header__meta" }, props.meta) : null
|
|
35
62
|
),
|
|
36
|
-
props.actions != null && props.actions !== false ? h(
|
|
63
|
+
props.actions != null && props.actions !== false ? h(
|
|
64
|
+
"div",
|
|
65
|
+
{ className: "aura-page-header__actions" },
|
|
66
|
+
bar && props.actionsStatus != null && props.actionsStatus !== false ? h("div", { className: "aura-page-header__status", role: "status" }, props.actionsStatus) : null,
|
|
67
|
+
props.actions
|
|
68
|
+
) : null
|
|
37
69
|
);
|
|
38
70
|
});
|
|
39
71
|
export {
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { PageHeader as StaticPageHeader } from "./PageHeader.js";
|
|
4
|
+
import { devWarnOnce, useMergedRef } from "./internal.js";
|
|
5
|
+
const NAME = "--aura-page-actions-height";
|
|
6
|
+
const bars = [];
|
|
7
|
+
function trapped(el) {
|
|
8
|
+
for (let p = el.parentElement; p && p !== document.documentElement; p = p.parentElement) {
|
|
9
|
+
const s = getComputedStyle(p);
|
|
10
|
+
if (s.transform !== "none" || s.filter !== "none" || (s.backdropFilter || "none") !== "none" || s.contentVisibility === "auto" || s.perspective !== "none" || /transform|filter|perspective/.test(s.willChange) || /paint|layout|strict|content/.test(s.contain))
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
|
|
16
|
+
const own = React.useRef(null);
|
|
17
|
+
const merged = useMergedRef(ref, own);
|
|
18
|
+
const bar = props.actionsBarBelow;
|
|
19
|
+
const hasActions = props.actions != null && props.actions !== false;
|
|
20
|
+
React.useEffect(
|
|
21
|
+
function() {
|
|
22
|
+
if (bar !== "sm" && bar !== "md" || !hasActions || !own.current) return;
|
|
23
|
+
const el = own.current.querySelector(":scope > .aura-page-header__actions");
|
|
24
|
+
if (!el) return;
|
|
25
|
+
const root = document.documentElement;
|
|
26
|
+
let checked = false;
|
|
27
|
+
function sync() {
|
|
28
|
+
if (bars[bars.length - 1] !== sync) return;
|
|
29
|
+
if (getComputedStyle(el).position === "fixed") {
|
|
30
|
+
root.style.setProperty(NAME, el.offsetHeight + "px");
|
|
31
|
+
if (!checked && (checked = true, trapped(el)))
|
|
32
|
+
devWarnOnce(
|
|
33
|
+
"pageheader-bar-trapped",
|
|
34
|
+
"PageHeader actionsBarBelow: an ancestor has a transform, filter, will-change or paint containment, so the fixed bar is placed against it instead of the screen. Remove it from the page header's ancestors."
|
|
35
|
+
);
|
|
36
|
+
} else root.style.removeProperty(NAME);
|
|
37
|
+
}
|
|
38
|
+
if (bars.length)
|
|
39
|
+
devWarnOnce(
|
|
40
|
+
"pageheader-bar-twice",
|
|
41
|
+
"PageHeader actionsBarBelow: two bars on one page overlap at the bottom of the screen. Give it to one PageHeader per page."
|
|
42
|
+
);
|
|
43
|
+
bars.push(sync);
|
|
44
|
+
const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(sync);
|
|
45
|
+
if (ro) ro.observe(el);
|
|
46
|
+
window.addEventListener("resize", sync);
|
|
47
|
+
sync();
|
|
48
|
+
return function() {
|
|
49
|
+
if (ro) ro.disconnect();
|
|
50
|
+
window.removeEventListener("resize", sync);
|
|
51
|
+
bars.splice(bars.indexOf(sync), 1);
|
|
52
|
+
if (bars.length) bars[bars.length - 1]();
|
|
53
|
+
else root.style.removeProperty(NAME);
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
[bar, hasActions]
|
|
57
|
+
);
|
|
58
|
+
const focusTitle = !!props.focusTitleOnMount;
|
|
59
|
+
React.useEffect(function() {
|
|
60
|
+
if (!focusTitle || !own.current) return;
|
|
61
|
+
const t = own.current.querySelector(".aura-page-header__title");
|
|
62
|
+
if (t) t.focus({ preventScroll: true });
|
|
63
|
+
}, []);
|
|
64
|
+
return /* @__PURE__ */ React.createElement(StaticPageHeader, { ...props, ref: merged });
|
|
65
|
+
});
|
|
66
|
+
export {
|
|
67
|
+
PageHeader
|
|
68
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import { Avatar } from "./Avatar.js";
|
|
|
35
35
|
import { Stack } from "./Stack.js";
|
|
36
36
|
import { Grid } from "./Grid.js";
|
|
37
37
|
import { Container } from "./Container.js";
|
|
38
|
-
import { PageHeader } from "./
|
|
38
|
+
import { PageHeader } from "./PageHeaderClient.js";
|
|
39
39
|
import { StatusTile } from "./StatusTile.js";
|
|
40
40
|
import { TileGrid, Sparkline } from "./tiles.js";
|
|
41
41
|
import { AppShell } from "./AppShell.js";
|
package/dist/index.d.cts
CHANGED
|
@@ -1932,7 +1932,8 @@ export declare const Container: React$1.ForwardRefExoticComponent<ContainerProps
|
|
|
1932
1932
|
* `/server`. It renders a plain `div`: to name a region by its title, put `aria-labelledby={titleId}` on your own
|
|
1933
1933
|
* `<section>`, or pass `role="region"` with it. */
|
|
1934
1934
|
export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "lang" | "dir" | "role">, React$1.AriaAttributes, DataAttributes {
|
|
1935
|
-
/** Small mono line above the title — a section or breadcrumb-like context ("Monitor / Sites").
|
|
1935
|
+
/** Small mono line above the title — a section or breadcrumb-like context ("Monitor / Sites"). 5.46 (Chamber-OS
|
|
1936
|
+
* 151): anything but text (chips: a status, a member number, badges) is a wrapping row in a `div`, 8px apart. */
|
|
1936
1937
|
eyebrow?: React$1.ReactNode | undefined;
|
|
1937
1938
|
/** 5.33 (DxT Monitor #7): a `<Breadcrumb>` above the title, 4px from it like the eyebrow, in its own `div` (a `nav`
|
|
1938
1939
|
* can't sit in the eyebrow's `p`) and its own 13px sans. Detail pages show a breadcrumb or an eyebrow; with both,
|
|
@@ -1940,6 +1941,23 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
|
|
|
1940
1941
|
breadcrumb?: React$1.ReactNode | undefined;
|
|
1941
1942
|
/** The page's heading. */
|
|
1942
1943
|
title: React$1.ReactNode;
|
|
1944
|
+
/** 5.46 (Chamber-OS 151): a sentence under the title at body size (14px/1.7, secondary colour) — "Members, plans
|
|
1945
|
+
* and renewals for SweCham" — before `meta`. A `div`, so a loading skeleton's blocks are valid inside. */
|
|
1946
|
+
subtitle?: React$1.ReactNode | undefined;
|
|
1947
|
+
/** 5.46: a chip or badge on the title's line (a role, an invoice's status, "Archived"). Title and addon share a
|
|
1948
|
+
* wrapping row, 8px apart vertically and 12px across; on a narrow screen the addon wraps under the title. */
|
|
1949
|
+
titleAddon?: React$1.ReactNode | undefined;
|
|
1950
|
+
/** 5.46: the title's size. `default` 28px below 640px, 36px from 640px; `hero` 30px on a 36px line with 16px more
|
|
1951
|
+
* room above; `hero-lg` 26px below 1024px and 36px from 1024px, with the same room. Per page, the custom
|
|
1952
|
+
* properties `--aura-page-header-title-size` and `--aura-page-header-title-line-height` override any of them. */
|
|
1953
|
+
size?: "default" | "hero" | "hero-lg" | undefined;
|
|
1954
|
+
/** 5.46: focus the heading when the header mounts (`tabIndex={-1}`, `preventScroll`, no visible ring) — a page
|
|
1955
|
+
* reached by a server redirect (renewal done, back from a payment page), so a screen reader starts there (WCAG
|
|
1956
|
+
* 2.4.3). The main entry's PageHeader does it; from `/server` the heading is focusable but not focused. */
|
|
1957
|
+
focusTitleOnMount?: boolean | undefined;
|
|
1958
|
+
/** 5.46: `end` (default) lines the actions up with the bottom of the text; `start` with its top (the title, when
|
|
1959
|
+
* there is no breadcrumb or eyebrow). */
|
|
1960
|
+
actionsAlign?: "end" | "start" | undefined;
|
|
1943
1961
|
/** A line under the title — counts, last update, owner. */
|
|
1944
1962
|
meta?: React$1.ReactNode | undefined;
|
|
1945
1963
|
/** Buttons for the page, bottom-aligned at the end; they wrap below the text on a narrow screen. */
|
|
@@ -1953,6 +1971,19 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
|
|
|
1953
1971
|
* readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
|
|
1954
1972
|
* meta line and actions stay; with no meta, the actions start the header. */
|
|
1955
1973
|
titleHideBelow?: "sm" | "md" | "lg" | undefined;
|
|
1974
|
+
/** 5.45 (Chamber-OS 150): below this breakpoint (`sm` 640px, `md` 768px) the same `actions` — rendered once, so a
|
|
1975
|
+
* dialog trigger or test id is never doubled — become a bar fixed to the bottom of the screen with ActionBar's look:
|
|
1976
|
+
* above a BottomNav, clear of the home indicator, `actionsStatus` as its status line. The page's end and a focused
|
|
1977
|
+
* field scroll clear of it (AppShell's content, or the body, gains the bar's height). With an IconButton among them
|
|
1978
|
+
* the actions share one row, labels wrapping inside the buttons (as `actionsFullWidthBelow`, Chamber-OS 149); with only icon
|
|
1979
|
+
* buttons the status and the icons share one row. From the breakpoint up nothing changes. Use it for a detail page's
|
|
1980
|
+
* own actions (Issue credit note…, ⋯) — one per page. The bar is `position: fixed`: no ancestor of the header may
|
|
1981
|
+
* have a transform, filter, backdrop-filter, will-change, paint/layout containment or `content-visibility: auto`, or it is placed
|
|
1982
|
+
* against that ancestor instead of the screen — the main entry warns in development. */
|
|
1983
|
+
actionsBarBelow?: "sm" | "md" | undefined;
|
|
1984
|
+
/** 5.45: the bar's status line ("Total 10,700.00 THB incl. VAT · due 22 Oct 2026"), shown only while the actions are
|
|
1985
|
+
* a bar, in a polite live region. */
|
|
1986
|
+
actionsStatus?: React$1.ReactNode | undefined;
|
|
1956
1987
|
/** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
|
|
1957
1988
|
headingLevel?: 1 | 2 | 3 | undefined;
|
|
1958
1989
|
/** The heading's id, for `aria-labelledby` on the page's region. */
|
package/dist/index.d.ts
CHANGED
|
@@ -1932,7 +1932,8 @@ export declare const Container: React$1.ForwardRefExoticComponent<ContainerProps
|
|
|
1932
1932
|
* `/server`. It renders a plain `div`: to name a region by its title, put `aria-labelledby={titleId}` on your own
|
|
1933
1933
|
* `<section>`, or pass `role="region"` with it. */
|
|
1934
1934
|
export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "lang" | "dir" | "role">, React$1.AriaAttributes, DataAttributes {
|
|
1935
|
-
/** Small mono line above the title — a section or breadcrumb-like context ("Monitor / Sites").
|
|
1935
|
+
/** Small mono line above the title — a section or breadcrumb-like context ("Monitor / Sites"). 5.46 (Chamber-OS
|
|
1936
|
+
* 151): anything but text (chips: a status, a member number, badges) is a wrapping row in a `div`, 8px apart. */
|
|
1936
1937
|
eyebrow?: React$1.ReactNode | undefined;
|
|
1937
1938
|
/** 5.33 (DxT Monitor #7): a `<Breadcrumb>` above the title, 4px from it like the eyebrow, in its own `div` (a `nav`
|
|
1938
1939
|
* can't sit in the eyebrow's `p`) and its own 13px sans. Detail pages show a breadcrumb or an eyebrow; with both,
|
|
@@ -1940,6 +1941,23 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
|
|
|
1940
1941
|
breadcrumb?: React$1.ReactNode | undefined;
|
|
1941
1942
|
/** The page's heading. */
|
|
1942
1943
|
title: React$1.ReactNode;
|
|
1944
|
+
/** 5.46 (Chamber-OS 151): a sentence under the title at body size (14px/1.7, secondary colour) — "Members, plans
|
|
1945
|
+
* and renewals for SweCham" — before `meta`. A `div`, so a loading skeleton's blocks are valid inside. */
|
|
1946
|
+
subtitle?: React$1.ReactNode | undefined;
|
|
1947
|
+
/** 5.46: a chip or badge on the title's line (a role, an invoice's status, "Archived"). Title and addon share a
|
|
1948
|
+
* wrapping row, 8px apart vertically and 12px across; on a narrow screen the addon wraps under the title. */
|
|
1949
|
+
titleAddon?: React$1.ReactNode | undefined;
|
|
1950
|
+
/** 5.46: the title's size. `default` 28px below 640px, 36px from 640px; `hero` 30px on a 36px line with 16px more
|
|
1951
|
+
* room above; `hero-lg` 26px below 1024px and 36px from 1024px, with the same room. Per page, the custom
|
|
1952
|
+
* properties `--aura-page-header-title-size` and `--aura-page-header-title-line-height` override any of them. */
|
|
1953
|
+
size?: "default" | "hero" | "hero-lg" | undefined;
|
|
1954
|
+
/** 5.46: focus the heading when the header mounts (`tabIndex={-1}`, `preventScroll`, no visible ring) — a page
|
|
1955
|
+
* reached by a server redirect (renewal done, back from a payment page), so a screen reader starts there (WCAG
|
|
1956
|
+
* 2.4.3). The main entry's PageHeader does it; from `/server` the heading is focusable but not focused. */
|
|
1957
|
+
focusTitleOnMount?: boolean | undefined;
|
|
1958
|
+
/** 5.46: `end` (default) lines the actions up with the bottom of the text; `start` with its top (the title, when
|
|
1959
|
+
* there is no breadcrumb or eyebrow). */
|
|
1960
|
+
actionsAlign?: "end" | "start" | undefined;
|
|
1943
1961
|
/** A line under the title — counts, last update, owner. */
|
|
1944
1962
|
meta?: React$1.ReactNode | undefined;
|
|
1945
1963
|
/** Buttons for the page, bottom-aligned at the end; they wrap below the text on a narrow screen. */
|
|
@@ -1953,6 +1971,19 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
|
|
|
1953
1971
|
* readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
|
|
1954
1972
|
* meta line and actions stay; with no meta, the actions start the header. */
|
|
1955
1973
|
titleHideBelow?: "sm" | "md" | "lg" | undefined;
|
|
1974
|
+
/** 5.45 (Chamber-OS 150): below this breakpoint (`sm` 640px, `md` 768px) the same `actions` — rendered once, so a
|
|
1975
|
+
* dialog trigger or test id is never doubled — become a bar fixed to the bottom of the screen with ActionBar's look:
|
|
1976
|
+
* above a BottomNav, clear of the home indicator, `actionsStatus` as its status line. The page's end and a focused
|
|
1977
|
+
* field scroll clear of it (AppShell's content, or the body, gains the bar's height). With an IconButton among them
|
|
1978
|
+
* the actions share one row, labels wrapping inside the buttons (as `actionsFullWidthBelow`, Chamber-OS 149); with only icon
|
|
1979
|
+
* buttons the status and the icons share one row. From the breakpoint up nothing changes. Use it for a detail page's
|
|
1980
|
+
* own actions (Issue credit note…, ⋯) — one per page. The bar is `position: fixed`: no ancestor of the header may
|
|
1981
|
+
* have a transform, filter, backdrop-filter, will-change, paint/layout containment or `content-visibility: auto`, or it is placed
|
|
1982
|
+
* against that ancestor instead of the screen — the main entry warns in development. */
|
|
1983
|
+
actionsBarBelow?: "sm" | "md" | undefined;
|
|
1984
|
+
/** 5.45: the bar's status line ("Total 10,700.00 THB incl. VAT · due 22 Oct 2026"), shown only while the actions are
|
|
1985
|
+
* a bar, in a polite live region. */
|
|
1986
|
+
actionsStatus?: React$1.ReactNode | undefined;
|
|
1956
1987
|
/** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
|
|
1957
1988
|
headingLevel?: 1 | 2 | 3 | undefined;
|
|
1958
1989
|
/** The heading's id, for `aria-labelledby` on the page's region. */
|
package/dist/server/index.cjs
CHANGED
|
@@ -1442,7 +1442,25 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
|
|
|
1442
1442
|
const level = props.headingLevel || 1;
|
|
1443
1443
|
const below = props.actionsFullWidthBelow;
|
|
1444
1444
|
const hide = props.titleHideBelow;
|
|
1445
|
-
const
|
|
1445
|
+
const shown = function(n3) {
|
|
1446
|
+
return n3 != null && n3 !== false && n3 !== "";
|
|
1447
|
+
};
|
|
1448
|
+
const hasMeta = shown(props.meta) || shown(props.subtitle) || shown(props.titleAddon);
|
|
1449
|
+
const size = props.size === "hero" || props.size === "hero-lg" ? props.size : null;
|
|
1450
|
+
const eyebrow = props.eyebrow;
|
|
1451
|
+
const plainEyebrow = typeof eyebrow === "string" || typeof eyebrow === "number";
|
|
1452
|
+
const heading = h4(
|
|
1453
|
+
"h" + level,
|
|
1454
|
+
{
|
|
1455
|
+
className: "aura-page-header__title",
|
|
1456
|
+
id: props.titleId,
|
|
1457
|
+
tabIndex: props.focusTitleOnMount ? -1 : void 0,
|
|
1458
|
+
"data-aura-focus-on-mount": props.focusTitleOnMount ? "" : void 0
|
|
1459
|
+
},
|
|
1460
|
+
props.title
|
|
1461
|
+
);
|
|
1462
|
+
const hasActions = props.actions != null && props.actions !== false;
|
|
1463
|
+
const bar = hasActions && (props.actionsBarBelow === "sm" || props.actionsBarBelow === "md") ? props.actionsBarBelow : null;
|
|
1446
1464
|
return h4(
|
|
1447
1465
|
"div",
|
|
1448
1466
|
Object.assign(attrs2, {
|
|
@@ -1452,6 +1470,9 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
|
|
|
1452
1470
|
(below === "sm" || below === "md" || below === "lg") && "aura-page-header--actions-full-below-" + below,
|
|
1453
1471
|
(hide === "sm" || hide === "md" || hide === "lg") && "aura-page-header--title-hide-below-" + hide,
|
|
1454
1472
|
(hide === "sm" || hide === "md" || hide === "lg") && !hasMeta && "has-no-meta",
|
|
1473
|
+
bar && "aura-page-header--actions-bar-below-" + bar,
|
|
1474
|
+
size && "aura-page-header--" + size,
|
|
1475
|
+
props.actionsAlign === "start" && "aura-page-header--actions-start",
|
|
1455
1476
|
props.className
|
|
1456
1477
|
),
|
|
1457
1478
|
style: props.style
|
|
@@ -1460,11 +1481,22 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
|
|
|
1460
1481
|
"div",
|
|
1461
1482
|
{ className: "aura-page-header__text" },
|
|
1462
1483
|
props.breadcrumb != null && props.breadcrumb !== false ? h4("div", { className: "aura-page-header__breadcrumb" }, props.breadcrumb) : null,
|
|
1463
|
-
|
|
1464
|
-
|
|
1484
|
+
shown(eyebrow) ? plainEyebrow ? h4("p", { className: "aura-page-header__eyebrow" }, eyebrow) : h4("div", { className: "aura-page-header__eyebrow aura-page-header__eyebrow--rich" }, eyebrow) : null,
|
|
1485
|
+
shown(props.titleAddon) ? h4(
|
|
1486
|
+
"div",
|
|
1487
|
+
{ className: "aura-page-header__title-row" },
|
|
1488
|
+
heading,
|
|
1489
|
+
h4("div", { className: "aura-page-header__title-addon" }, props.titleAddon)
|
|
1490
|
+
) : heading,
|
|
1491
|
+
shown(props.subtitle) ? h4("div", { className: "aura-page-header__subtitle" }, props.subtitle) : null,
|
|
1465
1492
|
props.meta != null && props.meta !== false ? h4("div", { className: "aura-page-header__meta" }, props.meta) : null
|
|
1466
1493
|
),
|
|
1467
|
-
props.actions != null && props.actions !== false ? h4(
|
|
1494
|
+
props.actions != null && props.actions !== false ? h4(
|
|
1495
|
+
"div",
|
|
1496
|
+
{ className: "aura-page-header__actions" },
|
|
1497
|
+
bar && props.actionsStatus != null && props.actionsStatus !== false ? h4("div", { className: "aura-page-header__status", role: "status" }, props.actionsStatus) : null,
|
|
1498
|
+
props.actions
|
|
1499
|
+
) : null
|
|
1468
1500
|
);
|
|
1469
1501
|
});
|
|
1470
1502
|
|
package/dist/server/index.d.cts
CHANGED
|
@@ -490,7 +490,8 @@ export declare const Container: React$1.ForwardRefExoticComponent<ContainerProps
|
|
|
490
490
|
* `/server`. It renders a plain `div`: to name a region by its title, put `aria-labelledby={titleId}` on your own
|
|
491
491
|
* `<section>`, or pass `role="region"` with it. */
|
|
492
492
|
export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "lang" | "dir" | "role">, React$1.AriaAttributes, DataAttributes {
|
|
493
|
-
/** Small mono line above the title — a section or breadcrumb-like context ("Monitor / Sites").
|
|
493
|
+
/** Small mono line above the title — a section or breadcrumb-like context ("Monitor / Sites"). 5.46 (Chamber-OS
|
|
494
|
+
* 151): anything but text (chips: a status, a member number, badges) is a wrapping row in a `div`, 8px apart. */
|
|
494
495
|
eyebrow?: React$1.ReactNode | undefined;
|
|
495
496
|
/** 5.33 (DxT Monitor #7): a `<Breadcrumb>` above the title, 4px from it like the eyebrow, in its own `div` (a `nav`
|
|
496
497
|
* can't sit in the eyebrow's `p`) and its own 13px sans. Detail pages show a breadcrumb or an eyebrow; with both,
|
|
@@ -498,6 +499,23 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
|
|
|
498
499
|
breadcrumb?: React$1.ReactNode | undefined;
|
|
499
500
|
/** The page's heading. */
|
|
500
501
|
title: React$1.ReactNode;
|
|
502
|
+
/** 5.46 (Chamber-OS 151): a sentence under the title at body size (14px/1.7, secondary colour) — "Members, plans
|
|
503
|
+
* and renewals for SweCham" — before `meta`. A `div`, so a loading skeleton's blocks are valid inside. */
|
|
504
|
+
subtitle?: React$1.ReactNode | undefined;
|
|
505
|
+
/** 5.46: a chip or badge on the title's line (a role, an invoice's status, "Archived"). Title and addon share a
|
|
506
|
+
* wrapping row, 8px apart vertically and 12px across; on a narrow screen the addon wraps under the title. */
|
|
507
|
+
titleAddon?: React$1.ReactNode | undefined;
|
|
508
|
+
/** 5.46: the title's size. `default` 28px below 640px, 36px from 640px; `hero` 30px on a 36px line with 16px more
|
|
509
|
+
* room above; `hero-lg` 26px below 1024px and 36px from 1024px, with the same room. Per page, the custom
|
|
510
|
+
* properties `--aura-page-header-title-size` and `--aura-page-header-title-line-height` override any of them. */
|
|
511
|
+
size?: "default" | "hero" | "hero-lg" | undefined;
|
|
512
|
+
/** 5.46: focus the heading when the header mounts (`tabIndex={-1}`, `preventScroll`, no visible ring) — a page
|
|
513
|
+
* reached by a server redirect (renewal done, back from a payment page), so a screen reader starts there (WCAG
|
|
514
|
+
* 2.4.3). The main entry's PageHeader does it; from `/server` the heading is focusable but not focused. */
|
|
515
|
+
focusTitleOnMount?: boolean | undefined;
|
|
516
|
+
/** 5.46: `end` (default) lines the actions up with the bottom of the text; `start` with its top (the title, when
|
|
517
|
+
* there is no breadcrumb or eyebrow). */
|
|
518
|
+
actionsAlign?: "end" | "start" | undefined;
|
|
501
519
|
/** A line under the title — counts, last update, owner. */
|
|
502
520
|
meta?: React$1.ReactNode | undefined;
|
|
503
521
|
/** Buttons for the page, bottom-aligned at the end; they wrap below the text on a narrow screen. */
|
|
@@ -511,6 +529,19 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
|
|
|
511
529
|
* readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
|
|
512
530
|
* meta line and actions stay; with no meta, the actions start the header. */
|
|
513
531
|
titleHideBelow?: "sm" | "md" | "lg" | undefined;
|
|
532
|
+
/** 5.45 (Chamber-OS 150): below this breakpoint (`sm` 640px, `md` 768px) the same `actions` — rendered once, so a
|
|
533
|
+
* dialog trigger or test id is never doubled — become a bar fixed to the bottom of the screen with ActionBar's look:
|
|
534
|
+
* above a BottomNav, clear of the home indicator, `actionsStatus` as its status line. The page's end and a focused
|
|
535
|
+
* field scroll clear of it (AppShell's content, or the body, gains the bar's height). With an IconButton among them
|
|
536
|
+
* the actions share one row, labels wrapping inside the buttons (as `actionsFullWidthBelow`, Chamber-OS 149); with only icon
|
|
537
|
+
* buttons the status and the icons share one row. From the breakpoint up nothing changes. Use it for a detail page's
|
|
538
|
+
* own actions (Issue credit note…, ⋯) — one per page. The bar is `position: fixed`: no ancestor of the header may
|
|
539
|
+
* have a transform, filter, backdrop-filter, will-change, paint/layout containment or `content-visibility: auto`, or it is placed
|
|
540
|
+
* against that ancestor instead of the screen — the main entry warns in development. */
|
|
541
|
+
actionsBarBelow?: "sm" | "md" | undefined;
|
|
542
|
+
/** 5.45: the bar's status line ("Total 10,700.00 THB incl. VAT · due 22 Oct 2026"), shown only while the actions are
|
|
543
|
+
* a bar, in a polite live region. */
|
|
544
|
+
actionsStatus?: React$1.ReactNode | undefined;
|
|
514
545
|
/** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
|
|
515
546
|
headingLevel?: 1 | 2 | 3 | undefined;
|
|
516
547
|
/** The heading's id, for `aria-labelledby` on the page's region. */
|
package/dist/server/index.d.ts
CHANGED
|
@@ -490,7 +490,8 @@ export declare const Container: React$1.ForwardRefExoticComponent<ContainerProps
|
|
|
490
490
|
* `/server`. It renders a plain `div`: to name a region by its title, put `aria-labelledby={titleId}` on your own
|
|
491
491
|
* `<section>`, or pass `role="region"` with it. */
|
|
492
492
|
export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "lang" | "dir" | "role">, React$1.AriaAttributes, DataAttributes {
|
|
493
|
-
/** Small mono line above the title — a section or breadcrumb-like context ("Monitor / Sites").
|
|
493
|
+
/** Small mono line above the title — a section or breadcrumb-like context ("Monitor / Sites"). 5.46 (Chamber-OS
|
|
494
|
+
* 151): anything but text (chips: a status, a member number, badges) is a wrapping row in a `div`, 8px apart. */
|
|
494
495
|
eyebrow?: React$1.ReactNode | undefined;
|
|
495
496
|
/** 5.33 (DxT Monitor #7): a `<Breadcrumb>` above the title, 4px from it like the eyebrow, in its own `div` (a `nav`
|
|
496
497
|
* can't sit in the eyebrow's `p`) and its own 13px sans. Detail pages show a breadcrumb or an eyebrow; with both,
|
|
@@ -498,6 +499,23 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
|
|
|
498
499
|
breadcrumb?: React$1.ReactNode | undefined;
|
|
499
500
|
/** The page's heading. */
|
|
500
501
|
title: React$1.ReactNode;
|
|
502
|
+
/** 5.46 (Chamber-OS 151): a sentence under the title at body size (14px/1.7, secondary colour) — "Members, plans
|
|
503
|
+
* and renewals for SweCham" — before `meta`. A `div`, so a loading skeleton's blocks are valid inside. */
|
|
504
|
+
subtitle?: React$1.ReactNode | undefined;
|
|
505
|
+
/** 5.46: a chip or badge on the title's line (a role, an invoice's status, "Archived"). Title and addon share a
|
|
506
|
+
* wrapping row, 8px apart vertically and 12px across; on a narrow screen the addon wraps under the title. */
|
|
507
|
+
titleAddon?: React$1.ReactNode | undefined;
|
|
508
|
+
/** 5.46: the title's size. `default` 28px below 640px, 36px from 640px; `hero` 30px on a 36px line with 16px more
|
|
509
|
+
* room above; `hero-lg` 26px below 1024px and 36px from 1024px, with the same room. Per page, the custom
|
|
510
|
+
* properties `--aura-page-header-title-size` and `--aura-page-header-title-line-height` override any of them. */
|
|
511
|
+
size?: "default" | "hero" | "hero-lg" | undefined;
|
|
512
|
+
/** 5.46: focus the heading when the header mounts (`tabIndex={-1}`, `preventScroll`, no visible ring) — a page
|
|
513
|
+
* reached by a server redirect (renewal done, back from a payment page), so a screen reader starts there (WCAG
|
|
514
|
+
* 2.4.3). The main entry's PageHeader does it; from `/server` the heading is focusable but not focused. */
|
|
515
|
+
focusTitleOnMount?: boolean | undefined;
|
|
516
|
+
/** 5.46: `end` (default) lines the actions up with the bottom of the text; `start` with its top (the title, when
|
|
517
|
+
* there is no breadcrumb or eyebrow). */
|
|
518
|
+
actionsAlign?: "end" | "start" | undefined;
|
|
501
519
|
/** A line under the title — counts, last update, owner. */
|
|
502
520
|
meta?: React$1.ReactNode | undefined;
|
|
503
521
|
/** Buttons for the page, bottom-aligned at the end; they wrap below the text on a narrow screen. */
|
|
@@ -511,6 +529,19 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
|
|
|
511
529
|
* readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
|
|
512
530
|
* meta line and actions stay; with no meta, the actions start the header. */
|
|
513
531
|
titleHideBelow?: "sm" | "md" | "lg" | undefined;
|
|
532
|
+
/** 5.45 (Chamber-OS 150): below this breakpoint (`sm` 640px, `md` 768px) the same `actions` — rendered once, so a
|
|
533
|
+
* dialog trigger or test id is never doubled — become a bar fixed to the bottom of the screen with ActionBar's look:
|
|
534
|
+
* above a BottomNav, clear of the home indicator, `actionsStatus` as its status line. The page's end and a focused
|
|
535
|
+
* field scroll clear of it (AppShell's content, or the body, gains the bar's height). With an IconButton among them
|
|
536
|
+
* the actions share one row, labels wrapping inside the buttons (as `actionsFullWidthBelow`, Chamber-OS 149); with only icon
|
|
537
|
+
* buttons the status and the icons share one row. From the breakpoint up nothing changes. Use it for a detail page's
|
|
538
|
+
* own actions (Issue credit note…, ⋯) — one per page. The bar is `position: fixed`: no ancestor of the header may
|
|
539
|
+
* have a transform, filter, backdrop-filter, will-change, paint/layout containment or `content-visibility: auto`, or it is placed
|
|
540
|
+
* against that ancestor instead of the screen — the main entry warns in development. */
|
|
541
|
+
actionsBarBelow?: "sm" | "md" | undefined;
|
|
542
|
+
/** 5.45: the bar's status line ("Total 10,700.00 THB incl. VAT · due 22 Oct 2026"), shown only while the actions are
|
|
543
|
+
* a bar, in a polite live region. */
|
|
544
|
+
actionsStatus?: React$1.ReactNode | undefined;
|
|
514
545
|
/** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
|
|
515
546
|
headingLevel?: 1 | 2 | 3 | undefined;
|
|
516
547
|
/** The heading's id, for `aria-labelledby` on the page's region. */
|
package/dist/server/index.js
CHANGED
|
@@ -1378,7 +1378,25 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
|
|
|
1378
1378
|
const level = props.headingLevel || 1;
|
|
1379
1379
|
const below = props.actionsFullWidthBelow;
|
|
1380
1380
|
const hide = props.titleHideBelow;
|
|
1381
|
-
const
|
|
1381
|
+
const shown = function(n3) {
|
|
1382
|
+
return n3 != null && n3 !== false && n3 !== "";
|
|
1383
|
+
};
|
|
1384
|
+
const hasMeta = shown(props.meta) || shown(props.subtitle) || shown(props.titleAddon);
|
|
1385
|
+
const size = props.size === "hero" || props.size === "hero-lg" ? props.size : null;
|
|
1386
|
+
const eyebrow = props.eyebrow;
|
|
1387
|
+
const plainEyebrow = typeof eyebrow === "string" || typeof eyebrow === "number";
|
|
1388
|
+
const heading = h4(
|
|
1389
|
+
"h" + level,
|
|
1390
|
+
{
|
|
1391
|
+
className: "aura-page-header__title",
|
|
1392
|
+
id: props.titleId,
|
|
1393
|
+
tabIndex: props.focusTitleOnMount ? -1 : void 0,
|
|
1394
|
+
"data-aura-focus-on-mount": props.focusTitleOnMount ? "" : void 0
|
|
1395
|
+
},
|
|
1396
|
+
props.title
|
|
1397
|
+
);
|
|
1398
|
+
const hasActions = props.actions != null && props.actions !== false;
|
|
1399
|
+
const bar = hasActions && (props.actionsBarBelow === "sm" || props.actionsBarBelow === "md") ? props.actionsBarBelow : null;
|
|
1382
1400
|
return h4(
|
|
1383
1401
|
"div",
|
|
1384
1402
|
Object.assign(attrs2, {
|
|
@@ -1388,6 +1406,9 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
|
|
|
1388
1406
|
(below === "sm" || below === "md" || below === "lg") && "aura-page-header--actions-full-below-" + below,
|
|
1389
1407
|
(hide === "sm" || hide === "md" || hide === "lg") && "aura-page-header--title-hide-below-" + hide,
|
|
1390
1408
|
(hide === "sm" || hide === "md" || hide === "lg") && !hasMeta && "has-no-meta",
|
|
1409
|
+
bar && "aura-page-header--actions-bar-below-" + bar,
|
|
1410
|
+
size && "aura-page-header--" + size,
|
|
1411
|
+
props.actionsAlign === "start" && "aura-page-header--actions-start",
|
|
1391
1412
|
props.className
|
|
1392
1413
|
),
|
|
1393
1414
|
style: props.style
|
|
@@ -1396,11 +1417,22 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
|
|
|
1396
1417
|
"div",
|
|
1397
1418
|
{ className: "aura-page-header__text" },
|
|
1398
1419
|
props.breadcrumb != null && props.breadcrumb !== false ? h4("div", { className: "aura-page-header__breadcrumb" }, props.breadcrumb) : null,
|
|
1399
|
-
|
|
1400
|
-
|
|
1420
|
+
shown(eyebrow) ? plainEyebrow ? h4("p", { className: "aura-page-header__eyebrow" }, eyebrow) : h4("div", { className: "aura-page-header__eyebrow aura-page-header__eyebrow--rich" }, eyebrow) : null,
|
|
1421
|
+
shown(props.titleAddon) ? h4(
|
|
1422
|
+
"div",
|
|
1423
|
+
{ className: "aura-page-header__title-row" },
|
|
1424
|
+
heading,
|
|
1425
|
+
h4("div", { className: "aura-page-header__title-addon" }, props.titleAddon)
|
|
1426
|
+
) : heading,
|
|
1427
|
+
shown(props.subtitle) ? h4("div", { className: "aura-page-header__subtitle" }, props.subtitle) : null,
|
|
1401
1428
|
props.meta != null && props.meta !== false ? h4("div", { className: "aura-page-header__meta" }, props.meta) : null
|
|
1402
1429
|
),
|
|
1403
|
-
props.actions != null && props.actions !== false ? h4(
|
|
1430
|
+
props.actions != null && props.actions !== false ? h4(
|
|
1431
|
+
"div",
|
|
1432
|
+
{ className: "aura-page-header__actions" },
|
|
1433
|
+
bar && props.actionsStatus != null && props.actionsStatus !== false ? h4("div", { className: "aura-page-header__status", role: "status" }, props.actionsStatus) : null,
|
|
1434
|
+
props.actions
|
|
1435
|
+
) : null
|
|
1404
1436
|
);
|
|
1405
1437
|
});
|
|
1406
1438
|
|
package/dist/styles.css
CHANGED
|
@@ -1152,7 +1152,7 @@ a.aura-tab { text-decoration: none; }
|
|
|
1152
1152
|
.aura-page-header { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--aura-space-4) var(--aura-space-6); min-width: 0; font-family: var(--font-sans); }
|
|
1153
1153
|
.aura-page-header__text { display: flex; flex-direction: column; gap: var(--aura-space-1); flex: 1 1 320px; min-width: 0; }
|
|
1154
1154
|
.aura-page-header__eyebrow { margin: 0; font-family: var(--font-mono); font-size: max(12px, .75rem); line-height: 1.7; color: var(--aura-fg-secondary); overflow-wrap: anywhere; }
|
|
1155
|
-
.aura-page-header__title { margin: 0; font-family: var(--font-display); font-size: max(28px, 1.75rem); line-height: 1.15; font-weight: 600; letter-spacing: -0.01em; color: var(--aura-fg-primary); overflow-wrap: anywhere; }
|
|
1155
|
+
.aura-page-header__title { margin: 0; font-family: var(--font-display); font-size: var(--aura-page-header-title-size, max(28px, 1.75rem)); line-height: var(--aura-page-header-title-line-height, 1.15); font-weight: 600; letter-spacing: -0.01em; color: var(--aura-fg-primary); overflow-wrap: anywhere; }
|
|
1156
1156
|
.aura-page-header__breadcrumb { min-width: 0; } /* 5.33 (DxT Monitor #7): Breadcrumb keeps its own type */
|
|
1157
1157
|
.aura-page-header__meta { min-width: 0; font-size: max(13px, .8125rem); line-height: 1.5; color: var(--aura-fg-secondary); overflow-wrap: anywhere; }
|
|
1158
1158
|
.aura-page-header__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); }
|
|
@@ -1160,15 +1160,15 @@ a.aura-tab { text-decoration: none; }
|
|
|
1160
1160
|
* are gone; with no meta line the text block takes no room, so the actions start the header. */
|
|
1161
1161
|
@media (max-width: 639.98px) {
|
|
1162
1162
|
.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; }
|
|
1163
|
-
.aura-page-header--title-hide-below-sm :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow) { display: none; }
|
|
1163
|
+
.aura-page-header--title-hide-below-sm :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow, .aura-page-header__title-addon) { display: none; }
|
|
1164
1164
|
}
|
|
1165
1165
|
@media (max-width: 767.98px) {
|
|
1166
1166
|
.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; }
|
|
1167
|
-
.aura-page-header--title-hide-below-md :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow) { display: none; }
|
|
1167
|
+
.aura-page-header--title-hide-below-md :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow, .aura-page-header__title-addon) { display: none; }
|
|
1168
1168
|
}
|
|
1169
1169
|
@media (max-width: 1023.98px) {
|
|
1170
1170
|
.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; }
|
|
1171
|
-
.aura-page-header--title-hide-below-lg :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow) { display: none; }
|
|
1171
|
+
.aura-page-header--title-hide-below-lg :is(.aura-page-header__breadcrumb, .aura-page-header__eyebrow, .aura-page-header__title-addon) { display: none; }
|
|
1172
1172
|
}
|
|
1173
1173
|
/* 5.37 (DxT Monitor #17): actionsFullWidthBelow — the actions take the row under the text; their children share
|
|
1174
1174
|
* each line equally (wrapping when a label won't fit), a trigger inside a DropdownMenu, Tooltip or Popover wrapper
|
|
@@ -1184,6 +1184,7 @@ a.aura-tab { text-decoration: none; }
|
|
|
1184
1184
|
.aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: nowrap; align-items: stretch; }
|
|
1185
1185
|
.aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > * { min-width: 0; }
|
|
1186
1186
|
.aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
|
|
1187
|
+
.aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; } /* 5.45 (Chamber-OS addendum 52): centred on a taller button */
|
|
1187
1188
|
}
|
|
1188
1189
|
@media (max-width: 767.98px) {
|
|
1189
1190
|
.aura-page-header--actions-full-below-md > .aura-page-header__actions { flex: 1 1 100%; gap: var(--aura-space-3); }
|
|
@@ -1194,6 +1195,7 @@ a.aura-tab { text-decoration: none; }
|
|
|
1194
1195
|
.aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: nowrap; align-items: stretch; }
|
|
1195
1196
|
.aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > * { min-width: 0; }
|
|
1196
1197
|
.aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
|
|
1198
|
+
.aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; } /* 5.45 (Chamber-OS addendum 52): centred on a taller button */
|
|
1197
1199
|
}
|
|
1198
1200
|
@media (max-width: 1023.98px) {
|
|
1199
1201
|
.aura-page-header--actions-full-below-lg > .aura-page-header__actions { flex: 1 1 100%; gap: var(--aura-space-3); }
|
|
@@ -1204,8 +1206,57 @@ a.aura-tab { text-decoration: none; }
|
|
|
1204
1206
|
.aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: nowrap; align-items: stretch; }
|
|
1205
1207
|
.aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > * { min-width: 0; }
|
|
1206
1208
|
.aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
|
|
1209
|
+
.aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; } /* 5.45 (Chamber-OS addendum 52): centred on a taller button */
|
|
1207
1210
|
}
|
|
1208
|
-
|
|
1211
|
+
/* 5.45 (Chamber-OS 150): actionsBarBelow — the same actions become a fixed bar with a status line; the page gains its
|
|
1212
|
+
* height (--aura-page-actions-height, measured on the client) so its end and a focused field scroll clear. */
|
|
1213
|
+
.aura-page-header__status { display: none; }
|
|
1214
|
+
@media (max-width: 639.98px) {
|
|
1215
|
+
.aura-page-header--actions-bar-below-sm > .aura-page-header__actions { position: fixed; z-index: var(--aura-z-bar); left: var(--aura-space-4); right: var(--aura-space-4); bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px))); box-sizing: border-box; min-height: 60px; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin: 0; padding: var(--aura-space-2) var(--aura-space-3) var(--aura-space-2) var(--aura-space-4); background: var(--aura-bg-surface); color: var(--aura-fg-primary); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay); transition: bottom var(--aura-duration-base) var(--aura-ease); }
|
|
1216
|
+
.aura-page-header--actions-bar-below-sm > .aura-page-header__actions > .aura-page-header__status { display: block; flex: 1 1 100%; min-width: 0; font-size: max(14px, .875rem); line-height: 1.5; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
|
|
1217
|
+
.aura-page-header--actions-bar-below-sm > .aura-page-header__actions > :not(.aura-page-header__status) { flex: 1 1 0; min-width: max-content; }
|
|
1218
|
+
.aura-page-header--actions-bar-below-sm > .aura-page-header__actions > :is(.aura-dropdown, .aura-tooltip-anchor, .aura-popover-anchor) > * { flex: 1 1 auto; }
|
|
1219
|
+
.aura-page-header--actions-bar-below-sm > .aura-page-header__actions > .aura-icon-btn { flex: none; }
|
|
1220
|
+
.aura-page-header--actions-bar-below-sm > .aura-page-header__actions > :has(> .aura-icon-btn) { flex: none; }
|
|
1221
|
+
.aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: wrap; align-items: stretch; }
|
|
1222
|
+
.aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :not(.aura-page-header__status) { min-width: 0; }
|
|
1223
|
+
.aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; }
|
|
1224
|
+
.aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
|
|
1225
|
+
.aura-page-header--actions-bar-below-sm > .aura-page-header__actions:not(:has(> .aura-btn, > * > .aura-btn)) > .aura-page-header__status { flex: 1 1 0; align-self: center; }
|
|
1226
|
+
:root:has(.aura-page-header--actions-bar-below-sm) { --aura-page-actions-space: calc(var(--aura-page-actions-height, 7rem) + var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px)) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-page-actions-space); }
|
|
1227
|
+
:root:has(.aura-page-header--actions-bar-below-sm) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-page-actions-space)); }
|
|
1228
|
+
:root:has(.aura-page-header--actions-bar-below-sm):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-page-actions-space); }
|
|
1229
|
+
}
|
|
1230
|
+
@media (max-width: 767.98px) {
|
|
1231
|
+
.aura-page-header--actions-bar-below-md > .aura-page-header__actions { position: fixed; z-index: var(--aura-z-bar); left: var(--aura-space-4); right: var(--aura-space-4); bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px))); box-sizing: border-box; min-height: 60px; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin: 0; padding: var(--aura-space-2) var(--aura-space-3) var(--aura-space-2) var(--aura-space-4); background: var(--aura-bg-surface); color: var(--aura-fg-primary); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay); transition: bottom var(--aura-duration-base) var(--aura-ease); }
|
|
1232
|
+
.aura-page-header--actions-bar-below-md > .aura-page-header__actions > .aura-page-header__status { display: block; flex: 1 1 100%; min-width: 0; font-size: max(14px, .875rem); line-height: 1.5; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
|
|
1233
|
+
.aura-page-header--actions-bar-below-md > .aura-page-header__actions > :not(.aura-page-header__status) { flex: 1 1 0; min-width: max-content; }
|
|
1234
|
+
.aura-page-header--actions-bar-below-md > .aura-page-header__actions > :is(.aura-dropdown, .aura-tooltip-anchor, .aura-popover-anchor) > * { flex: 1 1 auto; }
|
|
1235
|
+
.aura-page-header--actions-bar-below-md > .aura-page-header__actions > .aura-icon-btn { flex: none; }
|
|
1236
|
+
.aura-page-header--actions-bar-below-md > .aura-page-header__actions > :has(> .aura-icon-btn) { flex: none; }
|
|
1237
|
+
.aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: wrap; align-items: stretch; }
|
|
1238
|
+
.aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :not(.aura-page-header__status) { min-width: 0; }
|
|
1239
|
+
.aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; }
|
|
1240
|
+
.aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
|
|
1241
|
+
.aura-page-header--actions-bar-below-md > .aura-page-header__actions:not(:has(> .aura-btn, > * > .aura-btn)) > .aura-page-header__status { flex: 1 1 0; align-self: center; }
|
|
1242
|
+
:root:has(.aura-page-header--actions-bar-below-md) { --aura-page-actions-space: calc(var(--aura-page-actions-height, 7rem) + var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px)) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-page-actions-space); }
|
|
1243
|
+
:root:has(.aura-page-header--actions-bar-below-md) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-page-actions-space)); }
|
|
1244
|
+
:root:has(.aura-page-header--actions-bar-below-md):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-page-actions-space); }
|
|
1245
|
+
}
|
|
1246
|
+
@media (prefers-reduced-motion: reduce) { .aura-page-header__actions { transition: none; } }
|
|
1247
|
+
@media (min-width: 640px) { .aura-page-header__title { font-size: var(--aura-page-header-title-size, max(36px, 2.25rem)); } }
|
|
1248
|
+
/* 5.46 (Chamber-OS 151): subtitle, a title addon, a chip eyebrow, hero sizes, a focusable heading, top-aligned actions. */
|
|
1249
|
+
.aura-page-header__subtitle { min-width: 0; font-size: max(14px, .875rem); line-height: 1.7; color: var(--aura-fg-secondary); overflow-wrap: anywhere; }
|
|
1250
|
+
.aura-page-header__title-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2) var(--aura-space-3); min-width: 0; }
|
|
1251
|
+
.aura-page-header__title-row > .aura-page-header__title { min-width: 0; }
|
|
1252
|
+
.aura-page-header__title-addon { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); min-width: 0; }
|
|
1253
|
+
.aura-page-header__eyebrow--rich { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); font-family: var(--font-sans); line-height: 1.5; }
|
|
1254
|
+
.aura-page-header--hero, .aura-page-header--hero-lg { padding-top: var(--aura-space-4); }
|
|
1255
|
+
.aura-page-header--hero .aura-page-header__title { font-size: var(--aura-page-header-title-size, max(30px, 1.875rem)); line-height: var(--aura-page-header-title-line-height, 1.2); }
|
|
1256
|
+
.aura-page-header--hero-lg .aura-page-header__title { font-size: var(--aura-page-header-title-size, max(26px, 1.625rem)); line-height: var(--aura-page-header-title-line-height, 1.25); }
|
|
1257
|
+
@media (min-width: 1024px) { .aura-page-header--hero-lg .aura-page-header__title { font-size: var(--aura-page-header-title-size, max(36px, 2.25rem)); line-height: var(--aura-page-header-title-line-height, 1.2); } }
|
|
1258
|
+
.aura-page-header__title[tabindex="-1"]:focus { outline: none; }
|
|
1259
|
+
.aura-page-header--actions-start { align-items: flex-start; }
|
|
1209
1260
|
/* Thai marks need the room a 1.15 line takes away. */
|
|
1210
1261
|
.aura-page-header__title:lang(th) { line-height: 1.4; letter-spacing: 0; }
|
|
1211
1262
|
.aura-page-header__meta:lang(th) { line-height: 1.6; }
|