@kcascend/liquid-ui 0.0.4 → 0.0.6
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 +66 -61
- package/dist/components/Checkbox/Checkbox.d.ts +2 -1
- package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/Checkbox.js +9 -0
- package/dist/components/DataTable/DataTable.d.ts +1 -1
- package/dist/components/DataTable/DataTable.d.ts.map +1 -1
- package/dist/components/DataTable/DataTable.js +12 -12
- package/dist/components/GridLayout/layoutPatterns.d.ts +8 -0
- package/dist/components/GridLayout/layoutPatterns.d.ts.map +1 -0
- package/dist/components/GridLayout/layoutPatterns.js +317 -0
- package/dist/components/HeaderShell/HeaderShell.d.ts +1 -1
- package/dist/components/HeaderShell/HeaderShell.d.ts.map +1 -1
- package/dist/components/HeaderShell/HeaderShell.js +46 -17
- package/dist/generated/tokens.d.ts +863 -65
- package/dist/generated/tokens.d.ts.map +1 -1
- package/dist/generated/tokens.js +863 -65
- package/dist/governance/checkboxGovernance.d.ts.map +1 -1
- package/dist/governance/checkboxGovernance.js +4 -3
- package/dist/governance/gridLayoutGovernance.d.ts.map +1 -1
- package/dist/governance/gridLayoutGovernance.js +6 -5
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/styles.css +3741 -3609
- package/dist/tokens/components.css +22 -7
- package/dist/tokens/primitives.css +1 -0
- package/dist/tokens/semantic.css +36 -5
- package/dist/types.d.ts +44 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +33 -33
package/README.md
CHANGED
|
@@ -1,61 +1,66 @@
|
|
|
1
|
-
# Liquid UI Package
|
|
2
|
-
|
|
3
|
-
`@kcascend/liquid-ui` is the reusable UI package for Liquid Design System consumers.
|
|
4
|
-
|
|
5
|
-
## Local development
|
|
6
|
-
|
|
7
|
-
1. Run `npm install` from the repository root to install the local file dependency.
|
|
8
|
-
2. Run `npm run build:ui` to rebuild the package outputs in `packages/liquid-ui/dist`.
|
|
9
|
-
3. Run `npm run storybook` to rebuild the package and launch Storybook against the package boundary.
|
|
10
|
-
|
|
11
|
-
## Grid usage
|
|
12
|
-
|
|
13
|
-
The package exposes a grid primitive through `GridLayout` and `GridColumn
|
|
14
|
-
|
|
15
|
-
```tsx
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<GridColumn
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
- `
|
|
41
|
-
- `
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
1
|
+
# Liquid UI Package
|
|
2
|
+
|
|
3
|
+
`@kcascend/liquid-ui` is the reusable UI package for Liquid Design System consumers.
|
|
4
|
+
|
|
5
|
+
## Local development
|
|
6
|
+
|
|
7
|
+
1. Run `npm install` from the repository root to install the local file dependency.
|
|
8
|
+
2. Run `npm run build:ui` to rebuild the package outputs in `packages/liquid-ui/dist`.
|
|
9
|
+
3. Run `npm run storybook` to rebuild the package and launch Storybook against the package boundary.
|
|
10
|
+
|
|
11
|
+
## Grid usage
|
|
12
|
+
|
|
13
|
+
The package exposes a grid primitive through `GridLayout` and `GridColumn`, plus an approved layout catalog for application shells and content regions.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import {
|
|
17
|
+
approvedContentLayoutPatterns,
|
|
18
|
+
GridColumn,
|
|
19
|
+
GridLayout,
|
|
20
|
+
} from '@kcascend/liquid-ui';
|
|
21
|
+
|
|
22
|
+
export function Example() {
|
|
23
|
+
const layout = approvedContentLayoutPatterns.sidebarEnd;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<GridLayout as="div">
|
|
27
|
+
<GridColumn {...layout.regions.primary}>Primary</GridColumn>
|
|
28
|
+
<GridColumn {...layout.regions.secondary}>Secondary</GridColumn>
|
|
29
|
+
</GridLayout>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Supported layout features:
|
|
35
|
+
|
|
36
|
+
- Responsive spans through `sm`, `md`, `lg`, `xlg`, and `max`.
|
|
37
|
+
- Offset columns with object values like `md={{ span: 4, offset: 2 }}`.
|
|
38
|
+
- Gutter modes with `narrow` and `condensed`.
|
|
39
|
+
- `withRowGap` to keep vertical spacing aligned with the active gutter.
|
|
40
|
+
- `fullWidth` for viewport-spanning layouts.
|
|
41
|
+
- `subgrid` for nested grids that inherit the parent column scaffold.
|
|
42
|
+
- Auto columns when a `GridColumn` is rendered without explicit breakpoint props.
|
|
43
|
+
|
|
44
|
+
Approved layout guidance:
|
|
45
|
+
|
|
46
|
+
- Start application shells from `approvedShellRows`.
|
|
47
|
+
- Start page content from `approvedContentLayoutPatterns`.
|
|
48
|
+
- Introduce a bespoke breakpoint map only when a screen cannot be expressed by the approved patterns and that exception is documented in a spec.
|
|
49
|
+
|
|
50
|
+
## Figma governance
|
|
51
|
+
|
|
52
|
+
Every reusable component must record an approved Figma reference in story metadata or component documentation before it is considered ready for review. The initial workflow example in this package uses the Liquid token source in Figma
|
|
53
|
+
|
|
54
|
+
Storybook now demonstrates both patterns:
|
|
55
|
+
|
|
56
|
+
- a package-consumed button component with Figma and accessibility metadata
|
|
57
|
+
- a token values reference story that reads directly from the generated `tokens` export
|
|
58
|
+
|
|
59
|
+
## Accessibility verification
|
|
60
|
+
|
|
61
|
+
Each component review must include:
|
|
62
|
+
|
|
63
|
+
- Keyboard interaction expectations when the component is interactive.
|
|
64
|
+
- Name, role, and state guidance for assistive technologies.
|
|
65
|
+
- Color contrast and focus treatment verification.
|
|
66
|
+
- Storybook documentation that explains any usage constraints needed to stay WCAG 2.1 aligned.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type { CheckboxProps } from '../../types';
|
|
1
|
+
import type { CheckboxGroupProps, CheckboxProps } from '../../types';
|
|
2
2
|
export declare function Checkbox({ className, id, indeterminate, label, hideLabel, style, disabled, ...props }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare function CheckboxGroup({ legend, helperText, errorText, warningText, className, style, children, }: CheckboxGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
3
4
|
//# sourceMappingURL=Checkbox.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../../src/components/Checkbox/Checkbox.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../../src/components/Checkbox/Checkbox.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMrE,wBAAgB,QAAQ,CAAC,EACvB,SAAS,EACT,EAAE,EACF,aAAqB,EACrB,KAAK,EACL,SAAiB,EACjB,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,aAAa,2CAkDf;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,UAAU,EACV,SAAS,EACT,WAAW,EACX,SAAS,EACT,KAAK,EACL,QAAQ,GACT,EAAE,kBAAkB,2CA0BpB"}
|
|
@@ -15,3 +15,12 @@ export function Checkbox({ className, id, indeterminate = false, label, hideLabe
|
|
|
15
15
|
}, [indeterminate]);
|
|
16
16
|
return (_jsxs("label", { className: getClassName(className), style: style, "data-disabled": disabled || undefined, children: [_jsx("input", { ...props, ref: inputRef, type: "checkbox", id: inputId, disabled: disabled, className: "liquid-checkbox__input" }), _jsxs("span", { className: "liquid-checkbox__box", "aria-hidden": "true", children: [_jsx(Icon, { className: "liquid-checkbox__check-icon", color: "var(--component-checkbox-icon-check, #ffffff)", name: "check", size: 14 }), _jsx(Icon, { className: "liquid-checkbox__dash-icon", color: "var(--component-checkbox-icon-check, #ffffff)", name: "dash", size: 14 })] }), label ? (_jsx("span", { className: hideLabel ? 'liquid-sr-only' : 'liquid-checkbox__label-text', children: label })) : null] }));
|
|
17
17
|
}
|
|
18
|
+
export function CheckboxGroup({ legend, helperText, errorText, warningText, className, style, children, }) {
|
|
19
|
+
const statusText = errorText ?? warningText ?? helperText;
|
|
20
|
+
const statusClass = errorText
|
|
21
|
+
? 'liquid-checkbox-group__status--error'
|
|
22
|
+
: warningText
|
|
23
|
+
? 'liquid-checkbox-group__status--warning'
|
|
24
|
+
: 'liquid-checkbox-group__status--helper';
|
|
25
|
+
return (_jsxs("fieldset", { className: ['liquid-checkbox-group', className].filter(Boolean).join(' '), style: style, children: [legend ? (_jsx("legend", { className: "liquid-checkbox-group__legend", children: legend })) : null, _jsxs("div", { className: "liquid-checkbox-group__options-helper", children: [_jsx("div", { className: "liquid-checkbox-group__items", children: children }), statusText ? (_jsx("span", { className: `liquid-checkbox-group__status ${statusClass}`, children: statusText })) : null] })] }));
|
|
26
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { DataTableProps } from
|
|
1
|
+
import type { DataTableProps } from "../../types";
|
|
2
2
|
export declare function DataTable({ captionDescription, captionTitle, className, columns, onRowSelectChange, onSelectAllChange, rowCheckboxLabel, rows, selectable, selectAllLabel, style, ...props }: DataTableProps): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
//# sourceMappingURL=DataTable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/DataTable.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMlD,wBAAgB,SAAS,CAAC,EACxB,kBAAmE,EACnE,YAA4B,EAC5B,SAAS,EACT,OAAO,EACP,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,IAAI,EACJ,UAAkB,EAClB,cAAkC,EAClC,KAAK,EACL,GAAG,KAAK,EACT,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/DataTable.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMlD,wBAAgB,SAAS,CAAC,EACxB,kBAAmE,EACnE,YAA4B,EAC5B,SAAS,EACT,OAAO,EACP,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,IAAI,EACJ,UAAkB,EAClB,cAAkC,EAClC,KAAK,EACL,GAAG,KAAK,EACT,EAAE,cAAc,2CAkGhB"}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Checkbox } from
|
|
2
|
+
import { Checkbox } from "../Checkbox/Checkbox";
|
|
3
3
|
function getClassName(className) {
|
|
4
|
-
return [
|
|
4
|
+
return ["liquid-data-table", className].filter(Boolean).join(" ");
|
|
5
5
|
}
|
|
6
|
-
export function DataTable({ captionDescription =
|
|
6
|
+
export function DataTable({ captionDescription = "Brief description of what the table contains", captionTitle = "Table title", className, columns, onRowSelectChange, onSelectAllChange, rowCheckboxLabel, rows, selectable = false, selectAllLabel = "Select all rows", style, ...props }) {
|
|
7
7
|
const selectableRows = rows.filter((row) => !row.selectionDisabled);
|
|
8
8
|
const selectedCount = selectableRows.filter((row) => row.selected).length;
|
|
9
9
|
const allSelected = selectableRows.length > 0 && selectedCount === selectableRows.length;
|
|
10
10
|
const partiallySelected = selectedCount > 0 && !allSelected;
|
|
11
|
-
return (_jsxs("section", { ...props, className: getClassName(className), style: style, children: [_jsxs("header", { className: "liquid-data-table__header", children: [_jsx("h2", { className: "liquid-data-table__title", children: captionTitle }), _jsx("p", { className: "liquid-data-table__description", children: captionDescription })] }), _jsxs("table", { className: "liquid-data-table__table", children: [_jsx("thead", { children: _jsxs("tr", { className: "liquid-data-table__column-row", children: [selectable ? (_jsx("th", { className: "liquid-data-table__column-header liquid-data-table__checkbox-column", scope: "col", children: _jsx(Checkbox, { checked: allSelected, indeterminate: partiallySelected, label: selectAllLabel, hideLabel: true, onChange: (event) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
return (_jsxs("section", { ...props, className: getClassName(className), style: style, children: [_jsxs("header", { className: "liquid-data-table__header", children: [_jsx("h2", { className: "liquid-data-table__title", children: captionTitle }), _jsx("p", { className: "liquid-data-table__description", children: captionDescription })] }), _jsx("div", { className: "liquid-data-table__scroll-container", children: _jsxs("table", { className: "liquid-data-table__table", children: [_jsx("thead", { children: _jsxs("tr", { className: "liquid-data-table__column-row", children: [selectable ? (_jsx("th", { className: "liquid-data-table__column-header liquid-data-table__checkbox-column", scope: "col", children: _jsx(Checkbox, { checked: allSelected, indeterminate: partiallySelected, label: selectAllLabel, hideLabel: true, onChange: (event) => {
|
|
12
|
+
onSelectAllChange?.(event.currentTarget.checked);
|
|
13
|
+
} }) })) : null, columns.map((column) => (_jsx("th", { className: "liquid-data-table__column-header", "data-align": column.align ?? "left", scope: "col", children: column.header }, column.id)))] }) }), _jsx("tbody", { children: rows.map((row, rowIndex) => {
|
|
14
|
+
const resolvedId = row.id ?? rowIndex;
|
|
15
|
+
return (_jsxs("tr", { className: "liquid-data-table__row", "data-selected": row.selected || undefined, children: [selectable ? (_jsx("td", { className: "liquid-data-table__cell liquid-data-table__checkbox-column", children: _jsx(Checkbox, { checked: Boolean(row.selected), disabled: row.selectionDisabled, hideLabel: true, label: rowCheckboxLabel?.(row, rowIndex) ??
|
|
16
|
+
`Select row ${rowIndex + 1}`, onChange: (event) => {
|
|
17
|
+
onRowSelectChange?.(resolvedId, event.currentTarget.checked);
|
|
18
|
+
} }) })) : null, columns.map((column, columnIndex) => (_jsx("td", { className: "liquid-data-table__cell", "data-align": column.align ?? "left", children: row.cells[columnIndex] ?? null }, `${String(resolvedId)}:${column.id}`)))] }, String(resolvedId)));
|
|
19
|
+
}) })] }) })] }));
|
|
20
20
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ApprovedLegacyContentLayoutPatternName, CanonicalLayoutPattern, CanonicalLayoutPatternName, GridColumnProps, ApprovedContentLayoutPattern, ApprovedShellRowConfig } from '../../types';
|
|
2
|
+
export declare const approvedShellRows: Record<'header' | 'search' | 'results' | 'footer', ApprovedShellRowConfig>;
|
|
3
|
+
export declare const approvedContentLayoutPatterns: Record<ApprovedLegacyContentLayoutPatternName, ApprovedContentLayoutPattern>;
|
|
4
|
+
export declare const canonicalModernizationLayoutPatterns: Record<CanonicalLayoutPatternName, CanonicalLayoutPattern>;
|
|
5
|
+
export declare const legacyToCanonicalLayoutPatternMap: Record<ApprovedLegacyContentLayoutPatternName, CanonicalLayoutPatternName[]>;
|
|
6
|
+
export declare function getCanonicalModernizationLayoutPattern(patternName: CanonicalLayoutPatternName): CanonicalLayoutPattern;
|
|
7
|
+
export declare function getApprovedContentLayoutColumns(patternName: keyof typeof approvedContentLayoutPatterns): Record<'primary' | 'secondary' | 'tertiary', GridColumnProps | undefined>;
|
|
8
|
+
//# sourceMappingURL=layoutPatterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layoutPatterns.d.ts","sourceRoot":"","sources":["../../../src/components/GridLayout/layoutPatterns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sCAAsC,EACtC,sBAAsB,EACtB,0BAA0B,EAC1B,eAAe,EAGf,4BAA4B,EAC5B,sBAAsB,EACvB,MAAM,aAAa,CAAC;AAoBrB,eAAO,MAAM,iBAAiB,EAAE,MAAM,CACpC,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,EAC1C,sBAAsB,CAqBvB,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAChD,sCAAsC,EACtC,4BAA4B,CA0D7B,CAAC;AAEF,eAAO,MAAM,oCAAoC,EAAE,MAAM,CACvD,0BAA0B,EAC1B,sBAAsB,CAoOvB,CAAC;AAEF,eAAO,MAAM,iCAAiC,EAAE,MAAM,CACpD,sCAAsC,EACtC,0BAA0B,EAAE,CAW7B,CAAC;AAEF,wBAAgB,sCAAsC,CACpD,WAAW,EAAE,0BAA0B,GACtC,sBAAsB,CAExB;AAED,wBAAgB,+BAA+B,CAC7C,WAAW,EAAE,MAAM,OAAO,6BAA6B,GACtD,MAAM,CAAC,SAAS,GAAG,WAAW,GAAG,UAAU,EAAE,eAAe,GAAG,SAAS,CAAC,CAY3E"}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
function pickResponsiveColumns(columns) {
|
|
2
|
+
return columns;
|
|
3
|
+
}
|
|
4
|
+
function pickLayoutProps(props) {
|
|
5
|
+
return props;
|
|
6
|
+
}
|
|
7
|
+
function toGridColumnProps(columns) {
|
|
8
|
+
return columns;
|
|
9
|
+
}
|
|
10
|
+
export const approvedShellRows = {
|
|
11
|
+
header: {
|
|
12
|
+
description: 'Full-width header row aligned to the global shell column map.',
|
|
13
|
+
layout: pickLayoutProps({ fullWidth: true, withRowGap: false }),
|
|
14
|
+
},
|
|
15
|
+
search: {
|
|
16
|
+
description: 'Standard-gutter search row for filters and query controls.',
|
|
17
|
+
layout: pickLayoutProps({ fullWidth: false, withRowGap: false }),
|
|
18
|
+
},
|
|
19
|
+
results: {
|
|
20
|
+
description: 'Standard-gutter results row. Start from an approved content pattern before introducing bespoke spans.',
|
|
21
|
+
layout: pickLayoutProps({ fullWidth: false, withRowGap: false }),
|
|
22
|
+
},
|
|
23
|
+
footer: {
|
|
24
|
+
description: 'Full-width footer row for meta content and secondary actions.',
|
|
25
|
+
layout: pickLayoutProps({ fullWidth: true, withRowGap: false }),
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
export const approvedContentLayoutPatterns = {
|
|
29
|
+
single: {
|
|
30
|
+
description: 'Single-column content for forms, detail views, and uninterrupted reading flows.',
|
|
31
|
+
guidance: 'Prefer this when secondary content is optional or can move below the primary flow.',
|
|
32
|
+
regions: {
|
|
33
|
+
primary: pickResponsiveColumns({
|
|
34
|
+
sm: 4,
|
|
35
|
+
md: 8,
|
|
36
|
+
lg: 16,
|
|
37
|
+
xlg: 16,
|
|
38
|
+
max: 16,
|
|
39
|
+
}),
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
sidebarStart: {
|
|
43
|
+
description: 'Leading sidebar with primary content to the right.',
|
|
44
|
+
guidance: 'Use for filter, navigation, or status sidebars that should stack above content on smaller viewports.',
|
|
45
|
+
regions: {
|
|
46
|
+
primary: pickResponsiveColumns({
|
|
47
|
+
sm: 4,
|
|
48
|
+
md: 8,
|
|
49
|
+
lg: 12,
|
|
50
|
+
xlg: 12,
|
|
51
|
+
max: 12,
|
|
52
|
+
}),
|
|
53
|
+
secondary: pickResponsiveColumns({ sm: 4, md: 8, lg: 4, xlg: 4, max: 4 }),
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
sidebarEnd: {
|
|
57
|
+
description: 'Primary content first, with a trailing sidebar on wider breakpoints.',
|
|
58
|
+
guidance: 'Use for supporting context that should remain visible on desktop without preceding the main task.',
|
|
59
|
+
regions: {
|
|
60
|
+
primary: pickResponsiveColumns({
|
|
61
|
+
sm: 4,
|
|
62
|
+
md: 8,
|
|
63
|
+
lg: 12,
|
|
64
|
+
xlg: 12,
|
|
65
|
+
max: 12,
|
|
66
|
+
}),
|
|
67
|
+
secondary: pickResponsiveColumns({ sm: 4, md: 8, lg: 4, xlg: 4, max: 4 }),
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
splitEqual: {
|
|
71
|
+
description: 'Balanced two-up layout for peer content such as comparisons or dual work areas.',
|
|
72
|
+
guidance: 'Use when both regions have equal task weight. Avoid for filters or auxiliary status panels.',
|
|
73
|
+
regions: {
|
|
74
|
+
primary: pickResponsiveColumns({ sm: 4, md: 8, lg: 8, xlg: 8, max: 8 }),
|
|
75
|
+
secondary: pickResponsiveColumns({ sm: 4, md: 8, lg: 8, xlg: 8, max: 8 }),
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
export const canonicalModernizationLayoutPatterns = {
|
|
80
|
+
'single-column-task-flow': {
|
|
81
|
+
description: 'Single readable task flow where users complete one primary progression of work.',
|
|
82
|
+
bestFit: 'Forms, guided tasks, and simple detail experiences.',
|
|
83
|
+
avoidWhen: 'Dense side-by-side comparison or persistent tool panels are required.',
|
|
84
|
+
geometryMode: 'wide',
|
|
85
|
+
regions: [
|
|
86
|
+
{
|
|
87
|
+
label: 'primary-task-column',
|
|
88
|
+
spans: {
|
|
89
|
+
sm: '1-4',
|
|
90
|
+
md: '1-6',
|
|
91
|
+
lg: '1-8',
|
|
92
|
+
xlg: 'span-controlled',
|
|
93
|
+
max: 'span-controlled',
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
adaptiveBehaviors: ['stack'],
|
|
98
|
+
scrollOwner: 'page',
|
|
99
|
+
runtimeValidationNotes: [
|
|
100
|
+
'Meet reflow requirements at 320 CSS px with one-dimensional page scrolling.',
|
|
101
|
+
'Keep DOM and focus order aligned with task order across breakpoints.',
|
|
102
|
+
],
|
|
103
|
+
legacyCompatiblePatterns: ['single'],
|
|
104
|
+
},
|
|
105
|
+
'content-plus-aside': {
|
|
106
|
+
description: 'Primary content with a supporting aside that does not outrank the primary task.',
|
|
107
|
+
bestFit: 'Main workflow plus metadata, summary, or contextual help.',
|
|
108
|
+
avoidWhen: 'Users must complete aside content before understanding the primary task.',
|
|
109
|
+
geometryMode: 'wide',
|
|
110
|
+
regions: [
|
|
111
|
+
{
|
|
112
|
+
label: 'primary',
|
|
113
|
+
spans: { sm: 'full', md: '1-5', lg: '1-10', xlg: '1-10', max: '1-10' },
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
label: 'aside',
|
|
117
|
+
spans: {
|
|
118
|
+
sm: 'stack-below',
|
|
119
|
+
md: '6-8',
|
|
120
|
+
lg: '11-16',
|
|
121
|
+
xlg: '11-16',
|
|
122
|
+
max: '11-16',
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
adaptiveBehaviors: ['stack'],
|
|
127
|
+
scrollOwner: 'page',
|
|
128
|
+
runtimeValidationNotes: [
|
|
129
|
+
'Ensure focus order matches reading order when the aside stacks on smaller screens.',
|
|
130
|
+
'Do not trap keyboard users in supporting panes.',
|
|
131
|
+
],
|
|
132
|
+
legacyCompatiblePatterns: ['sidebarEnd'],
|
|
133
|
+
},
|
|
134
|
+
'search-results-index': {
|
|
135
|
+
description: 'Search and browse index where results remain the primary region across breakpoints.',
|
|
136
|
+
bestFit: 'Directories and filtered collections without persistent detail panes.',
|
|
137
|
+
avoidWhen: 'Selected record detail must remain persistently visible with the list.',
|
|
138
|
+
geometryMode: 'wide',
|
|
139
|
+
regions: [
|
|
140
|
+
{
|
|
141
|
+
label: 'filters',
|
|
142
|
+
spans: {
|
|
143
|
+
sm: 'disclosure',
|
|
144
|
+
md: 'disclosure',
|
|
145
|
+
lg: '1-4',
|
|
146
|
+
xlg: '1-4',
|
|
147
|
+
max: '1-4',
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
label: 'results',
|
|
152
|
+
spans: { sm: 'full', md: 'full', lg: '5-16', xlg: '5-16', max: '5-16' },
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
adaptiveBehaviors: ['disclosure', 'stack'],
|
|
156
|
+
scrollOwner: 'named-region',
|
|
157
|
+
runtimeValidationNotes: [
|
|
158
|
+
'Only the labeled data/table region may own horizontal overflow.',
|
|
159
|
+
'Retain result count, pagination, and empty state semantics at all breakpoints.',
|
|
160
|
+
],
|
|
161
|
+
legacyCompatiblePatterns: ['sidebarStart'],
|
|
162
|
+
},
|
|
163
|
+
'list-detail': {
|
|
164
|
+
description: 'Two-region list and selected-detail workflow with drill-in behavior on smaller screens.',
|
|
165
|
+
bestFit: 'Cases, records, and scan-then-inspect workflows.',
|
|
166
|
+
avoidWhen: 'Content groups are unrelated or many details must be compared at once.',
|
|
167
|
+
geometryMode: 'narrow',
|
|
168
|
+
regions: [
|
|
169
|
+
{
|
|
170
|
+
label: 'list',
|
|
171
|
+
spans: {
|
|
172
|
+
sm: 'list-first',
|
|
173
|
+
md: '1-3',
|
|
174
|
+
lg: '1-5',
|
|
175
|
+
xlg: '1-5',
|
|
176
|
+
max: '1-5',
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
label: 'detail',
|
|
181
|
+
spans: {
|
|
182
|
+
sm: 'after-selection',
|
|
183
|
+
md: '4-8',
|
|
184
|
+
lg: '6-16',
|
|
185
|
+
xlg: '6-16',
|
|
186
|
+
max: '6-16',
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
adaptiveBehaviors: ['drill-in', 'stack'],
|
|
191
|
+
scrollOwner: 'page',
|
|
192
|
+
runtimeValidationNotes: [
|
|
193
|
+
'Preserve selection state and return orientation when switching between list and detail.',
|
|
194
|
+
'Ensure truncated list labels expose full text through accessible naming.',
|
|
195
|
+
],
|
|
196
|
+
legacyCompatiblePatterns: ['sidebarStart', 'sidebarEnd'],
|
|
197
|
+
},
|
|
198
|
+
'dashboard-overview': {
|
|
199
|
+
description: 'Comparison-first operational overview with status tiles and queue snapshots.',
|
|
200
|
+
bestFit: 'Status cards, metrics, and operational queue overviews.',
|
|
201
|
+
avoidWhen: 'Long-form instructional reading is the dominant task.',
|
|
202
|
+
geometryMode: 'condensed',
|
|
203
|
+
regions: [
|
|
204
|
+
{
|
|
205
|
+
label: 'tile-grid',
|
|
206
|
+
spans: {
|
|
207
|
+
sm: 'stack-priority-order',
|
|
208
|
+
md: '2-up',
|
|
209
|
+
lg: 'nested-condensed',
|
|
210
|
+
xlg: 'nested-condensed',
|
|
211
|
+
max: 'nested-condensed',
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
adaptiveBehaviors: ['stack'],
|
|
216
|
+
scrollOwner: 'page',
|
|
217
|
+
runtimeValidationNotes: [
|
|
218
|
+
'Do not rely on position or color alone to convey tile state.',
|
|
219
|
+
'Keep text from hanging into condensed 1px gutters.',
|
|
220
|
+
],
|
|
221
|
+
legacyCompatiblePatterns: ['splitEqual'],
|
|
222
|
+
},
|
|
223
|
+
'high-density-workspace': {
|
|
224
|
+
description: 'Dense operational workspace with controls and a separately scrollable data region.',
|
|
225
|
+
bestFit: 'Data tables, filters, and bulk-action workflows.',
|
|
226
|
+
avoidWhen: 'Public-facing workflows prioritize comprehension over operator density.',
|
|
227
|
+
geometryMode: 'condensed',
|
|
228
|
+
regions: [
|
|
229
|
+
{
|
|
230
|
+
label: 'controls-wrapper',
|
|
231
|
+
spans: {
|
|
232
|
+
sm: 'full',
|
|
233
|
+
md: 'full',
|
|
234
|
+
lg: 'wide-wrapper',
|
|
235
|
+
xlg: 'wide-wrapper',
|
|
236
|
+
max: 'wide-wrapper',
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
label: 'dense-data-region',
|
|
241
|
+
spans: {
|
|
242
|
+
sm: 'local-overflow-region',
|
|
243
|
+
md: 'full',
|
|
244
|
+
lg: 'nested-condensed',
|
|
245
|
+
xlg: 'nested-condensed',
|
|
246
|
+
max: 'nested-condensed',
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
adaptiveBehaviors: ['stack', 'resize'],
|
|
251
|
+
scrollOwner: 'named-region',
|
|
252
|
+
runtimeValidationNotes: [
|
|
253
|
+
'Horizontal overflow must be constrained to the labeled data region only.',
|
|
254
|
+
'Keep controls before the data region for keyboard traversal.',
|
|
255
|
+
],
|
|
256
|
+
legacyCompatiblePatterns: ['sidebarStart', 'splitEqual'],
|
|
257
|
+
},
|
|
258
|
+
'shell-influenced-layout': {
|
|
259
|
+
description: 'Main page layout that reflows within persistent shell chrome contexts.',
|
|
260
|
+
bestFit: 'Apps with persistent header, left navigation, and optional utility panels.',
|
|
261
|
+
avoidWhen: 'Shell chrome is treated as page content or IA labels change on collapse.',
|
|
262
|
+
geometryMode: 'wide',
|
|
263
|
+
regions: [
|
|
264
|
+
{
|
|
265
|
+
label: 'shell-chrome',
|
|
266
|
+
spans: {
|
|
267
|
+
sm: 'header-trigger-nav',
|
|
268
|
+
md: 'compact-rail',
|
|
269
|
+
lg: 'expanded-nav',
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
label: 'content-grid',
|
|
274
|
+
spans: {
|
|
275
|
+
sm: 'responsive',
|
|
276
|
+
md: 'responsive',
|
|
277
|
+
lg: 'responsive',
|
|
278
|
+
xlg: 'responsive',
|
|
279
|
+
max: 'responsive',
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
],
|
|
283
|
+
adaptiveBehaviors: ['overlay', 'push', 'resize'],
|
|
284
|
+
scrollOwner: 'page',
|
|
285
|
+
runtimeValidationNotes: [
|
|
286
|
+
'Keep skip links and route meaning stable as shell panels open and close.',
|
|
287
|
+
'Treat panel dimensions as provisional until component contracts are finalized.',
|
|
288
|
+
],
|
|
289
|
+
legacyCompatiblePatterns: ['single', 'sidebarStart', 'sidebarEnd'],
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
export const legacyToCanonicalLayoutPatternMap = {
|
|
293
|
+
single: ['single-column-task-flow', 'shell-influenced-layout'],
|
|
294
|
+
sidebarStart: [
|
|
295
|
+
'search-results-index',
|
|
296
|
+
'list-detail',
|
|
297
|
+
'high-density-workspace',
|
|
298
|
+
'shell-influenced-layout',
|
|
299
|
+
],
|
|
300
|
+
sidebarEnd: ['content-plus-aside', 'list-detail', 'shell-influenced-layout'],
|
|
301
|
+
splitEqual: ['dashboard-overview', 'high-density-workspace'],
|
|
302
|
+
};
|
|
303
|
+
export function getCanonicalModernizationLayoutPattern(patternName) {
|
|
304
|
+
return canonicalModernizationLayoutPatterns[patternName];
|
|
305
|
+
}
|
|
306
|
+
export function getApprovedContentLayoutColumns(patternName) {
|
|
307
|
+
const pattern = approvedContentLayoutPatterns[patternName];
|
|
308
|
+
return {
|
|
309
|
+
primary: toGridColumnProps(pattern.regions.primary),
|
|
310
|
+
secondary: pattern.regions.secondary
|
|
311
|
+
? toGridColumnProps(pattern.regions.secondary)
|
|
312
|
+
: undefined,
|
|
313
|
+
tertiary: pattern.regions.tertiary
|
|
314
|
+
? toGridColumnProps(pattern.regions.tertiary)
|
|
315
|
+
: undefined,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { HeaderShellProps } from
|
|
1
|
+
import type { HeaderShellProps } from "../../types";
|
|
2
2
|
export declare function HeaderShell({ activeNavigationItemId, actions, brand, className, defaultActiveNavigationItemId, menuTriggerLabel, navigationItems, navLabel, onAction, onMenuTriggerClick, onNavigationChange, showMenuTrigger, style, ...props }: HeaderShellProps): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
//# sourceMappingURL=HeaderShell.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeaderShell.d.ts","sourceRoot":"","sources":["../../../src/components/HeaderShell/HeaderShell.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAGjB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"HeaderShell.d.ts","sourceRoot":"","sources":["../../../src/components/HeaderShell/HeaderShell.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAGjB,MAAM,aAAa,CAAC;AA2HrB,wBAAgB,WAAW,CAAC,EAC1B,sBAAsB,EACtB,OAAO,EACP,KAAK,EACL,SAAS,EACT,6BAA6B,EAC7B,gBAA8B,EAC9B,eAAe,EACf,QAAoB,EACpB,QAAQ,EACR,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,KAAK,EACL,GAAG,KAAK,EACT,EAAE,gBAAgB,2CAgMlB"}
|