@godxjp/ui 26.0.0 → 26.1.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/dist/components/data-entry/select.d.ts +4 -1
- package/dist/components/layout/page-container.js +7 -1
- package/dist/contracts/measurement.json +1 -1
- package/dist/styles/layout.css +15 -0
- package/dist/styles/shell-layout.css +4 -0
- package/docs/layout/app-shell-states.tsx +15 -5
- package/package.json +2 -2
|
@@ -26,7 +26,10 @@ export type SelectCompoundProp = FieldA11yProps & {
|
|
|
26
26
|
form?: string;
|
|
27
27
|
children?: React.ReactNode;
|
|
28
28
|
};
|
|
29
|
-
export type SelectProp = SelectDataProp | SelectCompoundProp
|
|
29
|
+
export type SelectProp = SelectDataProp | (SelectCompoundProp & {
|
|
30
|
+
mode?: undefined;
|
|
31
|
+
labelInValue?: undefined;
|
|
32
|
+
});
|
|
30
33
|
/**
|
|
31
34
|
* Select — one component for every single-select. Use the compound API for full control
|
|
32
35
|
* (`<Select><SelectTrigger/><SelectContent><SelectItem/></SelectContent></Select>`), OR the
|
|
@@ -33,6 +33,12 @@ function useFooterReveal(enabled) {
|
|
|
33
33
|
function PageContainerInset({ className, children, ...props }) {
|
|
34
34
|
return /* @__PURE__ */ jsx("div", { className: cn("ui-page-container-inset", className), ...props, children });
|
|
35
35
|
}
|
|
36
|
+
function footerPadStyle(footerPad) {
|
|
37
|
+
const style = padStyle(footerPad, void 0);
|
|
38
|
+
const end = style?.paddingInlineEnd ?? style?.padding;
|
|
39
|
+
if (end === void 0) return style;
|
|
40
|
+
return { ...style, paddingInlineEnd: `calc(${end} + var(--page-footer-content-slack))` };
|
|
41
|
+
}
|
|
36
42
|
function PageContainerRoot({
|
|
37
43
|
title,
|
|
38
44
|
subtitle,
|
|
@@ -150,7 +156,7 @@ function PageContainerRoot({
|
|
|
150
156
|
),
|
|
151
157
|
toolbar != null && /* @__PURE__ */ jsx("div", { className: "ui-page-toolbar", style: padStyle(toolbarPad, void 0), children: toolbar }),
|
|
152
158
|
children != null && /* @__PURE__ */ jsx("div", { className: "ui-page-body", children }),
|
|
153
|
-
footer && /* @__PURE__ */ jsx("footer", { className: "ui-page-footer", style:
|
|
159
|
+
footer && /* @__PURE__ */ jsx("footer", { className: "ui-page-footer", style: footerPadStyle(footerPad), children: footer })
|
|
154
160
|
]
|
|
155
161
|
}
|
|
156
162
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
|
|
3
|
-
"version": "26.
|
|
3
|
+
"version": "26.1.0",
|
|
4
4
|
"targetSize": {
|
|
5
5
|
"standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
|
|
6
6
|
"min": 24,
|
package/dist/styles/layout.css
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
@property --page-footer-content-slack {
|
|
4
|
+
syntax: "<length-percentage>";
|
|
5
|
+
inherits: false;
|
|
6
|
+
initial-value: 0px;
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
@layer components {
|
|
4
10
|
|
|
5
11
|
.ui-separator {
|
|
@@ -616,6 +622,14 @@
|
|
|
616
622
|
max-inline-size: var(--page-measure-medium);
|
|
617
623
|
}
|
|
618
624
|
|
|
625
|
+
.ui-page-container[data-measure="narrow"] .ui-page-footer {
|
|
626
|
+
--page-footer-content-slack: max(0px, 100% - var(--page-measure-narrow));
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
.ui-page-container[data-measure="medium"] .ui-page-footer {
|
|
630
|
+
--page-footer-content-slack: max(0px, 100% - var(--page-measure-medium));
|
|
631
|
+
}
|
|
632
|
+
|
|
619
633
|
.ui-page-container--flush .ui-page-toolbar,
|
|
620
634
|
.ui-page-container--flush .ui-page-body {
|
|
621
635
|
padding-inline-start: 0;
|
|
@@ -867,6 +881,7 @@
|
|
|
867
881
|
align-items: stretch;
|
|
868
882
|
gap: var(--space-inline-sm);
|
|
869
883
|
padding-top: var(--space-stack-md);
|
|
884
|
+
padding-inline-end: calc(var(--space-page-active-x) + var(--page-footer-content-slack));
|
|
870
885
|
border-top: var(--page-footer-divider, 1px solid hsl(var(--border)));
|
|
871
886
|
}
|
|
872
887
|
|
|
@@ -291,6 +291,10 @@
|
|
|
291
291
|
max-inline-size: var(--app-shell-page-max-width);
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
+
.app-main :where(.ui-page-footer) {
|
|
295
|
+
--page-footer-content-slack: max(0px, 100% - var(--app-shell-page-max-width));
|
|
296
|
+
}
|
|
297
|
+
|
|
294
298
|
.ui-auth-shell {
|
|
295
299
|
--control-height: var(--auth-shell-control-height);
|
|
296
300
|
--heading-h1: var(--auth-shell-heading-size);
|
|
@@ -3,6 +3,7 @@ import { AppShell, Flex, PageContainer, Sidebar, Topbar } from "@godxjp/ui/layou
|
|
|
3
3
|
import type { SidebarSectionProp } from "@godxjp/ui/layout";
|
|
4
4
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display";
|
|
5
5
|
import { Button, Text } from "@godxjp/ui/general";
|
|
6
|
+
import { Input } from "@godxjp/ui/data-entry";
|
|
6
7
|
import {
|
|
7
8
|
Bell,
|
|
8
9
|
Building2,
|
|
@@ -24,11 +25,13 @@ import {
|
|
|
24
25
|
* single page:
|
|
25
26
|
*
|
|
26
27
|
* ?topbarSpan=content|full ?navRail=start|end|top|bottom ?collapsed=1 ?sidebar=none
|
|
27
|
-
* ?responsive=docked ?measure=narrow|medium ?footer=1
|
|
28
|
+
* ?responsive=docked ?measure=narrow|medium ?footer=1|row
|
|
28
29
|
*
|
|
29
30
|
* `measure` and `footer` feed `scripts/check-app-shell-page-width.mjs` (gh#672): the page is fluid
|
|
30
31
|
* in the main column at every sidebar state, and a sticky footer band always spans `.app-main`,
|
|
31
32
|
* even when a service caps content with `--app-shell-page-max-width` or the page sets `measure`.
|
|
33
|
+
* The footer's CONTENT sits in the same column as the body (gh#682), so the two shapes a footer
|
|
34
|
+
* takes are both rendered: `footer=1` an end-aligned action group, `footer=row` a full-row composer.
|
|
32
35
|
*
|
|
33
36
|
* With no query it is `topbarSpan="full"` without a rail — the state gh#474 found collapsing
|
|
34
37
|
* `main` into a 170px implicit track below 900px, with the page actions laid out past the edge.
|
|
@@ -66,12 +69,12 @@ function readState() {
|
|
|
66
69
|
responsiveNavigation:
|
|
67
70
|
params.get("responsive") === "docked" ? ("docked" as const) : ("drawer" as const),
|
|
68
71
|
measure: (["narrow", "medium"] as const).find((m) => m === params.get("measure")),
|
|
69
|
-
|
|
72
|
+
footer: (["1", "row"] as const).find((f) => f === params.get("footer")),
|
|
70
73
|
};
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
export default function Demo() {
|
|
74
|
-
const [{ topbarSpan, navRail, collapsed, hasSidebar, responsiveNavigation, measure,
|
|
77
|
+
const [{ topbarSpan, navRail, collapsed, hasSidebar, responsiveNavigation, measure, footer }] =
|
|
75
78
|
useState(readState);
|
|
76
79
|
const [activeId, setActiveId] = useState("dashboard");
|
|
77
80
|
const strip = navRail === "top" || navRail === "bottom";
|
|
@@ -121,16 +124,23 @@ export default function Demo() {
|
|
|
121
124
|
subtitle="株式会社アクメ · 2026年5月"
|
|
122
125
|
measure={measure}
|
|
123
126
|
footer={
|
|
124
|
-
|
|
127
|
+
footer === "1" ? (
|
|
125
128
|
<Flex gap="sm" align="center" justify="end">
|
|
126
129
|
<Button size="sm" variant="outline">
|
|
127
130
|
下書き保存
|
|
128
131
|
</Button>
|
|
129
132
|
<Button size="sm">コメントを送信する</Button>
|
|
130
133
|
</Flex>
|
|
134
|
+
) : footer === "row" ? (
|
|
135
|
+
<Flex grow gap="sm" align="center">
|
|
136
|
+
<Flex grow>
|
|
137
|
+
<Input aria-label="コメント" placeholder="コメントを入力" />
|
|
138
|
+
</Flex>
|
|
139
|
+
<Button size="sm">送信</Button>
|
|
140
|
+
</Flex>
|
|
131
141
|
) : undefined
|
|
132
142
|
}
|
|
133
|
-
stickyFooter={
|
|
143
|
+
stickyFooter={footer !== undefined}
|
|
134
144
|
extra={
|
|
135
145
|
<Flex gap="sm" wrap>
|
|
136
146
|
<Button size="sm" variant="outline">
|