@godxjp/ui 31.6.0 → 31.7.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/agent/START-HERE.md +4 -4
- package/agent/components/Breadcrumb.json +1 -1
- package/agent/components/PageContainer.json +1 -1
- package/agent/components/Progress.json +12 -1
- package/agent/components/Text.json +1 -1
- package/agent/components.json +15 -4
- package/agent/index.json +4 -4
- package/agent/llms.txt +5 -5
- package/agent/tokens.json +6 -0
- package/dist/components/data-display/progress.d.ts +16 -0
- package/dist/components/data-display/progress.js +17 -3
- package/dist/components/feedback/tooltip.d.ts +21 -0
- package/dist/components/feedback/tooltip.js +101 -0
- package/dist/components/general/typography.js +30 -11
- package/dist/components/layout/breadcrumb-ellipsis.d.ts +16 -0
- package/dist/components/layout/breadcrumb-ellipsis.js +28 -0
- package/dist/components/layout/breadcrumb.js +16 -7
- package/dist/components/layout/page-container.js +29 -20
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +2 -1
- package/dist/i18n/messages/ja.json +2 -1
- package/dist/i18n/messages/vi.json +2 -1
- package/dist/props/registry.d.ts +5 -0
- package/dist/props/registry.js +5 -0
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/props/vocabulary/navigation.prop.d.ts +14 -0
- package/dist/styles/layers.json +3 -2
- package/dist/styles/layout.css +22 -0
- package/dist/styles/table-layout.css +8 -0
- package/dist/tokens/components/navigation.css +2 -0
- package/docs/data-display/progress.tsx +24 -6
- package/docs/general/typography.tsx +84 -1
- package/docs/i18n/messages/en.json +29 -1
- package/docs/i18n/messages/ja.json +29 -1
- package/docs/i18n/messages/vi.json +29 -1
- package/docs/navigation/breadcrumb.tsx +24 -0
- package/package.json +2 -2
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { ChevronDown, ChevronRight } from "lucide-react";
|
|
4
4
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
5
|
+
import { BreadcrumbCrumbText, trailEllipsis } from "./breadcrumb-ellipsis.js";
|
|
5
6
|
import {
|
|
6
7
|
DropdownMenu,
|
|
7
8
|
DropdownMenuContent,
|
|
@@ -17,12 +18,20 @@ function Breadcrumb({
|
|
|
17
18
|
}) {
|
|
18
19
|
const { t } = useTranslation();
|
|
19
20
|
const separatorNode = separator === void 0 ? /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true" }) : separator;
|
|
20
|
-
return /* @__PURE__ */ jsx("nav", { "aria-label": ariaLabel ?? t("navigation.breadcrumb.ariaLabel"), className: "ui-breadcrumb", children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", children: items.map((item, index) => {
|
|
21
|
+
return /* @__PURE__ */ jsx("nav", { "aria-label": ariaLabel ?? t("navigation.breadcrumb.ariaLabel"), className: "ui-breadcrumb", children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", "data-ellipsis": trailEllipsis(items), children: items.map((item, index) => {
|
|
21
22
|
const isLast = index === items.length - 1;
|
|
22
|
-
return /* @__PURE__ */ jsxs(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
return /* @__PURE__ */ jsxs(
|
|
24
|
+
"li",
|
|
25
|
+
{
|
|
26
|
+
className: "ui-breadcrumb-item",
|
|
27
|
+
"data-ellipsis": item.ellipsis ? "" : void 0,
|
|
28
|
+
children: [
|
|
29
|
+
renderBreadcrumbSegment({ item, index, isLast, items, itemRender, LinkComponent }),
|
|
30
|
+
!isLast ? /* @__PURE__ */ jsx("span", { className: "ui-breadcrumb-separator", "aria-hidden": "true", children: separatorNode }) : null
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
item.to ?? index
|
|
34
|
+
);
|
|
26
35
|
}) }) });
|
|
27
36
|
}
|
|
28
37
|
function renderBreadcrumbSegment({
|
|
@@ -54,9 +63,9 @@ function renderBreadcrumbSegment({
|
|
|
54
63
|
] });
|
|
55
64
|
}
|
|
56
65
|
if (item.to && !isLast) {
|
|
57
|
-
return /* @__PURE__ */ jsx(LinkComponent, { href: item.to, to: item.to, className: "ui-breadcrumb-link", children: item.label });
|
|
66
|
+
return /* @__PURE__ */ jsx(BreadcrumbCrumbText, { item, children: /* @__PURE__ */ jsx(LinkComponent, { href: item.to, to: item.to, className: "ui-breadcrumb-link", children: item.label }) });
|
|
58
67
|
}
|
|
59
|
-
return /* @__PURE__ */ jsx("span", { className: "ui-breadcrumb-current", "aria-current": isLast ? "page" : void 0, children: item.label });
|
|
68
|
+
return /* @__PURE__ */ jsx(BreadcrumbCrumbText, { item, children: /* @__PURE__ */ jsx("span", { className: "ui-breadcrumb-current", "aria-current": isLast ? "page" : void 0, children: item.label }) });
|
|
60
69
|
}
|
|
61
70
|
export {
|
|
62
71
|
Breadcrumb
|
|
@@ -5,6 +5,7 @@ import { ChevronRight } from "lucide-react";
|
|
|
5
5
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
6
|
import { scrollParent, useInView } from "../../lib/hooks.js";
|
|
7
7
|
import { cn } from "../../lib/utils.js";
|
|
8
|
+
import { BreadcrumbCrumbText, trailEllipsis } from "./breadcrumb-ellipsis.js";
|
|
8
9
|
import { densityClass, pageContainerVariantClass, padStyle } from "../../lib/variants.js";
|
|
9
10
|
function useFooterReveal(enabled) {
|
|
10
11
|
const headerRef = useRef(null);
|
|
@@ -92,7 +93,7 @@ function PageContainerRoot({
|
|
|
92
93
|
{
|
|
93
94
|
"aria-label": breadcrumbLabel ?? breadcrumbAriaLabel ?? t("navigation.breadcrumb.ariaLabel"),
|
|
94
95
|
className: "ui-breadcrumb",
|
|
95
|
-
children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", children: breadcrumb.map((item, i) => {
|
|
96
|
+
children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", "data-ellipsis": trailEllipsis(breadcrumb), children: breadcrumb.map((item, i) => {
|
|
96
97
|
const isLast = i === breadcrumb.length - 1;
|
|
97
98
|
return (
|
|
98
99
|
// `--space-inline-xs` gap the previous `.ui-inline-xs` gave, and it brings
|
|
@@ -100,25 +101,33 @@ function PageContainerRoot({
|
|
|
100
101
|
// longer carries a `size-3` literal. It also drops `.ui-inline-xs`'s
|
|
101
102
|
// `flex-wrap: wrap` — a crumb must not break between its label and its
|
|
102
103
|
// chevron; the LIST wraps instead, exactly as <Breadcrumb> already behaves.
|
|
103
|
-
/* @__PURE__ */ jsxs(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
children:
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
104
|
+
/* @__PURE__ */ jsxs(
|
|
105
|
+
"li",
|
|
106
|
+
{
|
|
107
|
+
className: "ui-breadcrumb-item",
|
|
108
|
+
"data-ellipsis": item.ellipsis ? "" : void 0,
|
|
109
|
+
children: [
|
|
110
|
+
item.to && !isLast ? /* @__PURE__ */ jsx(BreadcrumbCrumbText, { item, children: /* @__PURE__ */ jsx(
|
|
111
|
+
LinkComponent,
|
|
112
|
+
{
|
|
113
|
+
href: item.to,
|
|
114
|
+
to: item.to,
|
|
115
|
+
className: "hover:text-foreground hover:underline",
|
|
116
|
+
children: item.label
|
|
117
|
+
}
|
|
118
|
+
) }) : /* @__PURE__ */ jsx(BreadcrumbCrumbText, { item, children: /* @__PURE__ */ jsx(
|
|
119
|
+
"span",
|
|
120
|
+
{
|
|
121
|
+
className: isLast ? "text-foreground" : "",
|
|
122
|
+
"aria-current": isLast ? "page" : void 0,
|
|
123
|
+
children: item.label
|
|
124
|
+
}
|
|
125
|
+
) }),
|
|
126
|
+
!isLast && /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true" })
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
i
|
|
130
|
+
)
|
|
122
131
|
);
|
|
123
132
|
}) })
|
|
124
133
|
}
|
|
@@ -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": "31.
|
|
3
|
+
"version": "31.7.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/props/registry.d.ts
CHANGED
|
@@ -604,6 +604,11 @@ export declare const VOCABULARY_REGISTRY: {
|
|
|
604
604
|
readonly category: "navigation";
|
|
605
605
|
readonly description: "Single breadcrumb segment";
|
|
606
606
|
};
|
|
607
|
+
readonly BreadcrumbItemEllipsisProp: {
|
|
608
|
+
readonly file: "vocabulary/navigation.prop.ts";
|
|
609
|
+
readonly category: "navigation";
|
|
610
|
+
readonly description: "One-line truncation of a breadcrumb segment, with the full label in a tooltip";
|
|
611
|
+
};
|
|
607
612
|
readonly BreadcrumbProp: {
|
|
608
613
|
readonly file: "vocabulary/navigation.prop.ts";
|
|
609
614
|
readonly category: "navigation";
|
package/dist/props/registry.js
CHANGED
|
@@ -604,6 +604,11 @@ const VOCABULARY_REGISTRY = {
|
|
|
604
604
|
category: "navigation",
|
|
605
605
|
description: "Single breadcrumb segment"
|
|
606
606
|
},
|
|
607
|
+
BreadcrumbItemEllipsisProp: {
|
|
608
|
+
file: "vocabulary/navigation.prop.ts",
|
|
609
|
+
category: "navigation",
|
|
610
|
+
description: "One-line truncation of a breadcrumb segment, with the full label in a tooltip"
|
|
611
|
+
},
|
|
607
612
|
BreadcrumbProp: {
|
|
608
613
|
file: "vocabulary/navigation.prop.ts",
|
|
609
614
|
category: "navigation",
|
|
@@ -3,5 +3,5 @@ export type { ClassNameProp, ChildrenProp, IdProp, OpenProp, DefaultOpenProp, On
|
|
|
3
3
|
export type { TitleProp, SubtitleProp, StatusProp, DescriptionProp, ExtraProp, FooterProp, ActionProp, IconProp, ConfirmLabelProp, CancelLabelProp, ActionsProp, EmptyMessageProp, } from "./content.prop.js";
|
|
4
4
|
export type { PageDensityProp, PageContainerVariantProp, CenteredShellWidthProp, CenteredShellAlignProp, CenteredShellPresetProp, ErrorSurfaceModeProp, ErrorSurfaceStatusProp, AuthShellPresetProp, MobileShellHeightProp, MobileShellWidthProp, OrientationProp, TableDensityProp, DensityProp, GapNameProp, PadProp, PadRawProp, PadSides, GapProp, GapStepProp, } from "./layout.prop.js";
|
|
5
5
|
export type { ButtonVariantProp, ButtonSizeProp, BadgeVariantProp, AppSettingPickerAppearanceProp, AppSettingToggleAppearanceProp, ShapeProp, AvatarShapeProp, TextSizeProp, TextToneProp, FontWeightProp, HeadingLevelProp, TextAlignProp, TextWhitespaceProp, TextBreakProp, TypographyTypeProp, TitleLevelProp, TypographyCopyConfigProp, TypographyEditConfigProp, TypographyEllipsisConfigProp, TypographyActionsConfigProp, SizeProp, ControlStatusProp, ControlVariantProp, FormLayoutProp, DescriptionsLayoutProp, BreakpointProp, ConfirmVariantProp, ToneProp, AlertVariantProp, CalloutKindProp, SortDirectionProp, ColumnAlignProp, SortStateProp, RevealDelayProp, RevealTriggerProp, InViewAmountProp, ActivityVariantProp, ActivityAnnounceProp, IconSizeProp, } from "./interaction.prop.js";
|
|
6
|
-
export type { BreadcrumbItemProp, BreadcrumbProp, BreadcrumbItemMenuProp, BreadcrumbItemMenuEntryProp, BreadcrumbSeparatorProp, BreadcrumbItemRenderProp, } from "./navigation.prop.js";
|
|
6
|
+
export type { BreadcrumbItemProp, BreadcrumbProp, BreadcrumbItemMenuProp, BreadcrumbItemEllipsisProp, BreadcrumbItemMenuEntryProp, BreadcrumbSeparatorProp, BreadcrumbItemRenderProp, } from "./navigation.prop.js";
|
|
7
7
|
export type { GetRowIdProp, GetRowLabelProp, OnRowClickProp, ColumnDefProp, TablePresetProp, TableColumnPriorityProp, TableCellIndentProp, SelectedIdsProp, OnSelectChangeProp, OnTableDensityChangeProp, TableRowToneProp, RowToneProp, OnSortChangeProp, OnSearchChangeProp, OnClearFiltersProp, HasActiveFiltersProp, StickyProp, ColumnFixedProp, ColumnFilterValueProp, ColumnFilterItemProp, ColumnFilterStateProp, OnColumnFilterChangeProp, ColumnCompareProp, ColumnSorterProp, TableSelectionItemProp, TableSelectionBuiltInProp, TableSelectAllMatchingProp, TableRowSelectionProp, TableExpandableProp, TableSummaryProp, TableScrollProp, TableStickyProp, OnRowProp, TablePaginationProp, TablePaginationPositionProp, DescriptionsColumnProp, DescriptionsSpanProp, DescriptionsItemsProp, } from "./data.prop.js";
|
|
@@ -33,6 +33,20 @@ export type BreadcrumbItemProp = {
|
|
|
33
33
|
to?: string;
|
|
34
34
|
/** Ant Design `menu` — a sibling dropdown on this segment. @see BreadcrumbItemMenuProp */
|
|
35
35
|
menu?: BreadcrumbItemMenuProp;
|
|
36
|
+
/**
|
|
37
|
+
* One line, a long label cut with "…" (gh#1046). antd's Breadcrumb has no per-item ellipsis;
|
|
38
|
+
* the name and shape are antd Typography's `ellipsis`. The full label shows in a tooltip on hover
|
|
39
|
+
* and on keyboard focus of the crumb link — `true` / `{}` use the label, `{ tooltip: node }`
|
|
40
|
+
* replaces it, `{ tooltip: false }` drops it. Applies to link and current crumbs, not to a
|
|
41
|
+
* `menu` segment or an `itemRender` body. The trail then stays on one line; a theme may cap
|
|
42
|
+
* each such crumb with `--breadcrumb-item-max-inline-size`.
|
|
43
|
+
* @see BreadcrumbItemEllipsisProp
|
|
44
|
+
*/
|
|
45
|
+
ellipsis?: BreadcrumbItemEllipsisProp;
|
|
46
|
+
};
|
|
47
|
+
/** `BreadcrumbItemProp.ellipsis` — on, or on with an explicit tooltip (gh#1046). */
|
|
48
|
+
export type BreadcrumbItemEllipsisProp = boolean | {
|
|
49
|
+
tooltip?: React.ReactNode;
|
|
36
50
|
};
|
|
37
51
|
/** Ordered breadcrumb trail above page title. */
|
|
38
52
|
export type BreadcrumbProp = BreadcrumbItemProp[];
|
package/dist/styles/layers.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "31.
|
|
2
|
+
"version": "31.7.0",
|
|
3
3
|
"generatedBy": "scripts/gen-style-layers.mjs — do not edit by hand; run `pnpm gen:style-layers`",
|
|
4
4
|
"base": "base.css",
|
|
5
5
|
"fonts": "fonts.css",
|
|
@@ -702,7 +702,8 @@
|
|
|
702
702
|
},
|
|
703
703
|
"PageContainer": {
|
|
704
704
|
"layers": [
|
|
705
|
-
"layout.css"
|
|
705
|
+
"layout.css",
|
|
706
|
+
"dialog-layout.css"
|
|
706
707
|
]
|
|
707
708
|
},
|
|
708
709
|
"Pagination": {
|
package/dist/styles/layout.css
CHANGED
|
@@ -1036,6 +1036,28 @@
|
|
|
1036
1036
|
color: hsl(var(--foreground));
|
|
1037
1037
|
}
|
|
1038
1038
|
|
|
1039
|
+
.ui-breadcrumb-list[data-ellipsis] {
|
|
1040
|
+
flex-wrap: nowrap;
|
|
1041
|
+
}
|
|
1042
|
+
.ui-breadcrumb-list[data-ellipsis] > .ui-breadcrumb-item:not([data-ellipsis]) {
|
|
1043
|
+
flex-shrink: 0;
|
|
1044
|
+
white-space: nowrap;
|
|
1045
|
+
}
|
|
1046
|
+
.ui-breadcrumb-item[data-ellipsis] {
|
|
1047
|
+
min-inline-size: 0;
|
|
1048
|
+
max-inline-size: var(--breadcrumb-item-max-inline-size);
|
|
1049
|
+
}
|
|
1050
|
+
.ui-breadcrumb-item[data-ellipsis] > svg,
|
|
1051
|
+
.ui-breadcrumb-item[data-ellipsis] > .ui-breadcrumb-separator {
|
|
1052
|
+
flex-shrink: 0;
|
|
1053
|
+
}
|
|
1054
|
+
.ui-breadcrumb-ellipsis {
|
|
1055
|
+
min-inline-size: 0;
|
|
1056
|
+
overflow: hidden;
|
|
1057
|
+
text-overflow: ellipsis;
|
|
1058
|
+
white-space: nowrap;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1039
1061
|
.ui-empty-state {
|
|
1040
1062
|
display: flex;
|
|
1041
1063
|
flex-direction: column;
|
|
@@ -212,6 +212,9 @@
|
|
|
212
212
|
font: inherit;
|
|
213
213
|
cursor: pointer;
|
|
214
214
|
outline: none;
|
|
215
|
+
|
|
216
|
+
max-inline-size: 100%;
|
|
217
|
+
min-inline-size: 0;
|
|
215
218
|
}
|
|
216
219
|
|
|
217
220
|
.ui-data-table-sort-button::after {
|
|
@@ -334,6 +337,11 @@
|
|
|
334
337
|
display: inline-flex;
|
|
335
338
|
align-items: center;
|
|
336
339
|
gap: var(--space-inline-xs);
|
|
340
|
+
min-inline-size: 0;
|
|
341
|
+
max-inline-size: 100%;
|
|
342
|
+
}
|
|
343
|
+
.ui-data-table-sort-label > .ui-data-table-sort-icon {
|
|
344
|
+
flex-shrink: 0;
|
|
337
345
|
}
|
|
338
346
|
|
|
339
347
|
:is(th, td).text-center > .ui-data-table-sort-button > .ui-data-table-sort-label {
|
|
@@ -46,6 +46,8 @@
|
|
|
46
46
|
--breadcrumb-font-size: var(--font-size-xs, calc(var(--font-size-base) / var(--font-size-ratio)));
|
|
47
47
|
|
|
48
48
|
--breadcrumb-menu-trigger-gap: var(--space-inline-xs);
|
|
49
|
+
|
|
50
|
+
--breadcrumb-item-max-inline-size: none;
|
|
49
51
|
--menu-shortcut-font-size: var(
|
|
50
52
|
--font-size-xs,
|
|
51
53
|
calc(var(--font-size-base) / var(--font-size-ratio))
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
CardTitle,
|
|
7
7
|
Progress,
|
|
8
8
|
} from "@godxjp/ui/data-display";
|
|
9
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
9
10
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -13,6 +14,7 @@ import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
|
13
14
|
* Composed only from real @godxjp/ui components.
|
|
14
15
|
*/
|
|
15
16
|
export default function Demo() {
|
|
17
|
+
const { t, locale } = useTranslation();
|
|
16
18
|
return (
|
|
17
19
|
<PageContainer title="Progress" subtitle="0–100 bar · optional label + semantic tone">
|
|
18
20
|
<Flex direction="col" gap="lg">
|
|
@@ -37,11 +39,10 @@ export default function Demo() {
|
|
|
37
39
|
<CardHeader>
|
|
38
40
|
<CardTitle level={2}>shape="ring"</CardTitle>
|
|
39
41
|
<CardDescription>
|
|
40
|
-
同じメーターを弧で描きます。バーと同じ value / tone / size / ARIA
|
|
41
|
-
|
|
42
|
-
件」を見出しの横に出したいとき、バー+キャプションの 2
|
|
43
|
-
|
|
44
|
-
場所が正方形のときに選びます。
|
|
42
|
+
同じメーターを弧で描きます。バーと同じ value / tone / size / ARIA のまま、label
|
|
43
|
+
がリングの内側に入ります。狭いアプリバーで「18 / 42
|
|
44
|
+
件」を見出しの横に出したいとき、バー+キャプションの 2 段ではなく 1
|
|
45
|
+
マスで済むのが理由です。数値が重要なときではなく、 場所が正方形のときに選びます。
|
|
45
46
|
</CardDescription>
|
|
46
47
|
</CardHeader>
|
|
47
48
|
<CardContent>
|
|
@@ -68,7 +69,10 @@ export default function Demo() {
|
|
|
68
69
|
1 つの合計を状態ごとに分割します。割合ではなく実数を渡すと、各スライスの比率は
|
|
69
70
|
コンポーネントが計算します。メーターより背の高いトラックになるのは、0.5rem の pill
|
|
70
71
|
上に 3 色を並べると比率が読めなくなるためです。role="img"
|
|
71
|
-
として、全スライスを 1 つの名前で読み上げます。
|
|
72
|
+
として、全スライスを 1 つの名前で読み上げます。total を渡すと全体は合計ではなく total
|
|
73
|
+
になり、残りはトラックのまま「残り」として読み上げます(antd の percent +
|
|
74
|
+
success.percent と同じく、未塗りのトラックが残り。antd の全体は常に 100
|
|
75
|
+
ですが、ここは実数の単位で total を指定します)。
|
|
72
76
|
</CardDescription>
|
|
73
77
|
</CardHeader>
|
|
74
78
|
<CardContent>
|
|
@@ -89,6 +93,20 @@ export default function Demo() {
|
|
|
89
93
|
]}
|
|
90
94
|
label="みどり農産株式会社(0 件のスライスは幅 0)"
|
|
91
95
|
/>
|
|
96
|
+
{/* total を渡すと、スライスは合計ではなく total に対して描かれ、残りはトラックのまま。
|
|
97
|
+
読み上げには残り(remainderLabel)が Intl 形式の数値で入ります。 */}
|
|
98
|
+
<Progress
|
|
99
|
+
segments={[
|
|
100
|
+
{ value: 3, tone: "success", label: t("progressDocs.testRun.passed") },
|
|
101
|
+
{ value: 1, tone: "destructive", label: t("progressDocs.testRun.failed") },
|
|
102
|
+
{ value: 2, tone: "warning", label: t("progressDocs.testRun.blocked") },
|
|
103
|
+
]}
|
|
104
|
+
total={400}
|
|
105
|
+
remainderLabel={t("progressDocs.testRun.notRun")}
|
|
106
|
+
label={t("progressDocs.testRun.caption", {
|
|
107
|
+
total: new Intl.NumberFormat(locale).format(400),
|
|
108
|
+
})}
|
|
109
|
+
/>
|
|
92
110
|
</Flex>
|
|
93
111
|
</CardContent>
|
|
94
112
|
</Card>
|
|
@@ -21,8 +21,10 @@ import {
|
|
|
21
21
|
TableHead,
|
|
22
22
|
TableHeader,
|
|
23
23
|
TableRow,
|
|
24
|
+
DataTable,
|
|
25
|
+
Tree,
|
|
24
26
|
} from "@godxjp/ui/data-display";
|
|
25
|
-
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
27
|
+
import { Breadcrumb, Flex, PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
30
|
* Text + Heading — the typographic primitives. Use these INSTEAD of a hand-rolled
|
|
@@ -46,8 +48,15 @@ const headingTones = [
|
|
|
46
48
|
{ tone: "info", title: "システムメンテナンスのお知らせ" },
|
|
47
49
|
] as const;
|
|
48
50
|
|
|
51
|
+
type SuiteRow = { id: string; title: string };
|
|
52
|
+
|
|
49
53
|
export default function Demo() {
|
|
50
54
|
const { t } = useTranslation();
|
|
55
|
+
const longTitle = t("textExamples.ellipsisLongTitle");
|
|
56
|
+
const suiteRows: SuiteRow[] = [
|
|
57
|
+
{ id: "TS-0412", title: longTitle },
|
|
58
|
+
{ id: "TS-0413", title: t("textExamples.ellipsisShortTitle") },
|
|
59
|
+
];
|
|
51
60
|
return (
|
|
52
61
|
<PageContainer
|
|
53
62
|
title="Typography"
|
|
@@ -388,6 +397,80 @@ export default function Demo() {
|
|
|
388
397
|
</Flex>
|
|
389
398
|
</CardContent>
|
|
390
399
|
</Card>
|
|
400
|
+
<Card>
|
|
401
|
+
<CardHeader>
|
|
402
|
+
<CardTitle level={2}>{t("textExamples.ellipsisTitle")}</CardTitle>
|
|
403
|
+
<CardDescription>{t("textExamples.ellipsisDescription")}</CardDescription>
|
|
404
|
+
</CardHeader>
|
|
405
|
+
<CardContent>
|
|
406
|
+
<Flex direction="col" gap="md">
|
|
407
|
+
<ResponsiveGrid columns={{ sm: 2, lg: 3 }}>
|
|
408
|
+
<Flex direction="col" gap="xs">
|
|
409
|
+
<Text size="xs" tone="muted">
|
|
410
|
+
{t("textExamples.ellipsisPlain")}
|
|
411
|
+
</Text>
|
|
412
|
+
<Text ellipsis={{ tooltip: true }}>{longTitle}</Text>
|
|
413
|
+
</Flex>
|
|
414
|
+
<Flex direction="col" gap="xs">
|
|
415
|
+
<Text size="xs" tone="muted">
|
|
416
|
+
{t("textExamples.ellipsisLink")}
|
|
417
|
+
</Text>
|
|
418
|
+
<Text asChild link ellipsis={{ tooltip: true }}>
|
|
419
|
+
<a href="#typography">{longTitle}</a>
|
|
420
|
+
</Text>
|
|
421
|
+
</Flex>
|
|
422
|
+
<Flex direction="col" gap="xs">
|
|
423
|
+
<Text size="xs" tone="muted">
|
|
424
|
+
{t("textExamples.ellipsisTree")}
|
|
425
|
+
</Text>
|
|
426
|
+
<Tree
|
|
427
|
+
aria-label={t("textExamples.ellipsisTree")}
|
|
428
|
+
treeData={[
|
|
429
|
+
{
|
|
430
|
+
value: "suite",
|
|
431
|
+
label: longTitle,
|
|
432
|
+
children: [
|
|
433
|
+
{ value: "case-1", label: t("textExamples.ellipsisShortTitle") },
|
|
434
|
+
],
|
|
435
|
+
},
|
|
436
|
+
]}
|
|
437
|
+
defaultExpandedValues={["suite"]}
|
|
438
|
+
titleRender={(node) => <Text ellipsis={{ tooltip: true }}>{node.label}</Text>}
|
|
439
|
+
/>
|
|
440
|
+
</Flex>
|
|
441
|
+
</ResponsiveGrid>
|
|
442
|
+
<DataTable<SuiteRow>
|
|
443
|
+
label={t("textExamples.ellipsisTable")}
|
|
444
|
+
data={suiteRows}
|
|
445
|
+
getRowId={(row) => row.id}
|
|
446
|
+
columns={[
|
|
447
|
+
{ key: "id", header: "ID", width: "7rem", render: (row) => row.id },
|
|
448
|
+
{
|
|
449
|
+
key: "title",
|
|
450
|
+
header: (
|
|
451
|
+
<Text ellipsis={{ tooltip: true }}>
|
|
452
|
+
{t("textExamples.ellipsisLongHeader")}
|
|
453
|
+
</Text>
|
|
454
|
+
),
|
|
455
|
+
width: "12rem",
|
|
456
|
+
ellipsis: true,
|
|
457
|
+
sortable: true,
|
|
458
|
+
sorter: (a, b) => a.title.localeCompare(b.title),
|
|
459
|
+
render: (row) => <Text ellipsis={{ tooltip: true }}>{row.title}</Text>,
|
|
460
|
+
},
|
|
461
|
+
]}
|
|
462
|
+
/>
|
|
463
|
+
<Breadcrumb
|
|
464
|
+
ariaLabel={t("textExamples.ellipsisBreadcrumb")}
|
|
465
|
+
items={[
|
|
466
|
+
{ label: t("textExamples.ellipsisCrumbHome"), to: "#typography" },
|
|
467
|
+
{ label: longTitle, to: "#typography", ellipsis: true },
|
|
468
|
+
{ label: longTitle, ellipsis: true },
|
|
469
|
+
]}
|
|
470
|
+
/>
|
|
471
|
+
</Flex>
|
|
472
|
+
</CardContent>
|
|
473
|
+
</Card>
|
|
391
474
|
<Card>
|
|
392
475
|
<CardHeader>
|
|
393
476
|
<CardTitle level={2}>copyable · editable · 装飾</CardTitle>
|
|
@@ -6,7 +6,18 @@
|
|
|
6
6
|
"breakDescription": "An identifier with nowhere to break — an email address, a coupon code, a login ID — takes break=\"anywhere\", and the column stays inside the viewport even in a table cell. whitespace=\"pre-wrap\" is for newlines a person typed; it cannot wrap an identifier in a table cell.",
|
|
7
7
|
"breakColumnOwner": "Owner",
|
|
8
8
|
"breakColumnEmail": "Email address",
|
|
9
|
-
"breakSampleName": "Sato"
|
|
9
|
+
"breakSampleName": "Sato",
|
|
10
|
+
"ellipsisTitle": "ellipsis · the full text in a tooltip while it is cut",
|
|
11
|
+
"ellipsisDescription": "ellipsis={{ tooltip: true }} keeps one line and shows the whole text on hover and on keyboard focus of the control it sits in (the link, the tree item, the sort button). A title that fits shows no tooltip, and the Text never becomes a tab stop of its own.",
|
|
12
|
+
"ellipsisPlain": "Plain Text",
|
|
13
|
+
"ellipsisLink": "Text asChild · link",
|
|
14
|
+
"ellipsisTree": "Tree titleRender",
|
|
15
|
+
"ellipsisTable": "Test suites",
|
|
16
|
+
"ellipsisBreadcrumb": "Truncated breadcrumb",
|
|
17
|
+
"ellipsisCrumbHome": "Home",
|
|
18
|
+
"ellipsisLongTitle": "Q3 integration test · payment module · invoice re-issue scenarios and acceptance criteria review",
|
|
19
|
+
"ellipsisShortTitle": "Login smoke test",
|
|
20
|
+
"ellipsisLongHeader": "Latest run name (release candidate 2026-09)"
|
|
10
21
|
},
|
|
11
22
|
"themeShowcase": {
|
|
12
23
|
"page": {
|
|
@@ -1469,5 +1480,22 @@
|
|
|
1469
1480
|
"other": "Load {count} more"
|
|
1470
1481
|
}
|
|
1471
1482
|
}
|
|
1483
|
+
},
|
|
1484
|
+
"progressDocs": {
|
|
1485
|
+
"testRun": {
|
|
1486
|
+
"passed": "Passed",
|
|
1487
|
+
"failed": "Failed",
|
|
1488
|
+
"blocked": "Blocked",
|
|
1489
|
+
"notRun": "Not run",
|
|
1490
|
+
"caption": "Regression suite — {total} cases"
|
|
1491
|
+
}
|
|
1492
|
+
},
|
|
1493
|
+
"breadcrumbExamples": {
|
|
1494
|
+
"ellipsisTitle": "ellipsis · a long segment on one line",
|
|
1495
|
+
"ellipsisDescription": "ellipsis on a segment keeps the trail on one line and cuts that label with \"…\"; the full label shows in a tooltip on hover and when the crumb link takes keyboard focus. antd Breadcrumb has no per-item ellipsis — the shape is Typography’s. PageContainer breadcrumb takes the same item field.",
|
|
1496
|
+
"ellipsisAria": "Truncated breadcrumb",
|
|
1497
|
+
"home": "Home",
|
|
1498
|
+
"longSuite": "Q3 integration test · payment module · invoice re-issue scenarios",
|
|
1499
|
+
"longSection": "Acceptance criteria review for the release candidate of September 2026"
|
|
1472
1500
|
}
|
|
1473
1501
|
}
|
|
@@ -6,7 +6,18 @@
|
|
|
6
6
|
"breakDescription": "メールアドレス・クーポンコード・ログイン ID のような区切りのない識別子は break=\"anywhere\"。表のセルでも列が画面幅に収まります。whitespace=\"pre-wrap\" は人が入力した改行のためのもので、表のセルでは識別子を折り返せません。",
|
|
7
7
|
"breakColumnOwner": "担当者",
|
|
8
8
|
"breakColumnEmail": "メールアドレス",
|
|
9
|
-
"breakSampleName": "佐藤"
|
|
9
|
+
"breakSampleName": "佐藤",
|
|
10
|
+
"ellipsisTitle": "ellipsis · 省略中は全文をツールチップで",
|
|
11
|
+
"ellipsisDescription": "ellipsis={{ tooltip: true }} は 1 行に収め、ホバーと、置かれたコントロール(リンク・ツリー項目・並べ替えボタン)へのキーボードフォーカスで全文を表示します。収まるタイトルにはツールチップを出さず、Text 自体はタブ移動先になりません。",
|
|
12
|
+
"ellipsisPlain": "通常の Text",
|
|
13
|
+
"ellipsisLink": "Text asChild · リンク",
|
|
14
|
+
"ellipsisTree": "Tree の titleRender",
|
|
15
|
+
"ellipsisTable": "テストスイート",
|
|
16
|
+
"ellipsisBreadcrumb": "省略付きパンくずリスト",
|
|
17
|
+
"ellipsisCrumbHome": "ホーム",
|
|
18
|
+
"ellipsisLongTitle": "第3四半期 結合テスト 決済モジュール 請求書再発行シナリオと受入基準のレビュー",
|
|
19
|
+
"ellipsisShortTitle": "ログインのスモークテスト",
|
|
20
|
+
"ellipsisLongHeader": "最新の実行名(2026年9月 リリース候補)"
|
|
10
21
|
},
|
|
11
22
|
"themeShowcase": {
|
|
12
23
|
"page": {
|
|
@@ -1462,5 +1473,22 @@
|
|
|
1462
1473
|
"other": "さらに {count} 件を読み込む"
|
|
1463
1474
|
}
|
|
1464
1475
|
}
|
|
1476
|
+
},
|
|
1477
|
+
"progressDocs": {
|
|
1478
|
+
"testRun": {
|
|
1479
|
+
"passed": "合格",
|
|
1480
|
+
"failed": "失敗",
|
|
1481
|
+
"blocked": "ブロック",
|
|
1482
|
+
"notRun": "未実施",
|
|
1483
|
+
"caption": "回帰テスト — 全 {total} 件"
|
|
1484
|
+
}
|
|
1485
|
+
},
|
|
1486
|
+
"breadcrumbExamples": {
|
|
1487
|
+
"ellipsisTitle": "ellipsis · 長いセグメントを 1 行に",
|
|
1488
|
+
"ellipsisDescription": "セグメントに ellipsis を付けるとパンくずは 1 行のまま、そのラベルを「…」で省略します。全文はホバーと、パンくずのリンクへのキーボードフォーカスでツールチップに出ます。antd の Breadcrumb に項目単位の省略はなく、形は Typography に合わせています。PageContainer の breadcrumb も同じ項目フィールドを受け付けます。",
|
|
1489
|
+
"ellipsisAria": "省略付きパンくずリスト",
|
|
1490
|
+
"home": "ホーム",
|
|
1491
|
+
"longSuite": "第3四半期 結合テスト 決済モジュール 請求書再発行シナリオ",
|
|
1492
|
+
"longSection": "2026年9月 リリース候補の受入基準レビュー"
|
|
1465
1493
|
}
|
|
1466
1494
|
}
|
|
@@ -6,7 +6,18 @@
|
|
|
6
6
|
"breakDescription": "Định danh không có chỗ ngắt — địa chỉ email, mã giảm giá, ID đăng nhập — dùng break=\"anywhere\", và cột vẫn nằm gọn trong bề ngang màn hình kể cả trong ô của bảng. whitespace=\"pre-wrap\" dành cho ký tự xuống dòng do người nhập; nó không ngắt được một định danh trong ô bảng.",
|
|
7
7
|
"breakColumnOwner": "Phụ trách",
|
|
8
8
|
"breakColumnEmail": "Địa chỉ email",
|
|
9
|
-
"breakSampleName": "Sato"
|
|
9
|
+
"breakSampleName": "Sato",
|
|
10
|
+
"ellipsisTitle": "ellipsis · toàn văn trong tooltip khi bị cắt",
|
|
11
|
+
"ellipsisDescription": "ellipsis={{ tooltip: true }} giữ một dòng và hiện toàn văn khi rê chuột và khi bàn phím đưa tiêu điểm tới điều khiển chứa nó (liên kết, mục cây, nút sắp xếp). Tiêu đề vừa chỗ thì không có tooltip, và Text không bao giờ tự thành một điểm dừng Tab.",
|
|
12
|
+
"ellipsisPlain": "Text thường",
|
|
13
|
+
"ellipsisLink": "Text asChild · liên kết",
|
|
14
|
+
"ellipsisTree": "titleRender của Tree",
|
|
15
|
+
"ellipsisTable": "Bộ kiểm thử",
|
|
16
|
+
"ellipsisBreadcrumb": "Breadcrumb có cắt chữ",
|
|
17
|
+
"ellipsisCrumbHome": "Trang chủ",
|
|
18
|
+
"ellipsisLongTitle": "Kiểm thử tích hợp quý 3 · mô-đun thanh toán · kịch bản xuất lại hoá đơn và rà soát tiêu chí nghiệm thu",
|
|
19
|
+
"ellipsisShortTitle": "Kiểm thử nhanh đăng nhập",
|
|
20
|
+
"ellipsisLongHeader": "Tên lần chạy gần nhất (bản ứng viên 2026-09)"
|
|
10
21
|
},
|
|
11
22
|
"themeShowcase": {
|
|
12
23
|
"page": {
|
|
@@ -1462,5 +1473,22 @@
|
|
|
1462
1473
|
"other": "Tải thêm {count} ca"
|
|
1463
1474
|
}
|
|
1464
1475
|
}
|
|
1476
|
+
},
|
|
1477
|
+
"progressDocs": {
|
|
1478
|
+
"testRun": {
|
|
1479
|
+
"passed": "Đạt",
|
|
1480
|
+
"failed": "Lỗi",
|
|
1481
|
+
"blocked": "Bị chặn",
|
|
1482
|
+
"notRun": "Chưa chạy",
|
|
1483
|
+
"caption": "Bộ kiểm thử hồi quy — {total} ca"
|
|
1484
|
+
}
|
|
1485
|
+
},
|
|
1486
|
+
"breadcrumbExamples": {
|
|
1487
|
+
"ellipsisTitle": "ellipsis · một đoạn dài trên một dòng",
|
|
1488
|
+
"ellipsisDescription": "ellipsis trên một đoạn giữ breadcrumb trên một dòng và cắt nhãn đó bằng \"…\"; toàn văn hiện trong tooltip khi rê chuột và khi liên kết của đoạn nhận tiêu điểm bàn phím. Breadcrumb của antd không có ellipsis theo từng mục — hình dạng lấy theo Typography. breadcrumb của PageContainer nhận cùng trường này.",
|
|
1489
|
+
"ellipsisAria": "Breadcrumb có cắt chữ",
|
|
1490
|
+
"home": "Trang chủ",
|
|
1491
|
+
"longSuite": "Kiểm thử tích hợp quý 3 · mô-đun thanh toán · kịch bản xuất lại hoá đơn",
|
|
1492
|
+
"longSection": "Rà soát tiêu chí nghiệm thu cho bản ứng viên tháng 9/2026"
|
|
1465
1493
|
}
|
|
1466
1494
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
CodeBlock,
|
|
10
10
|
} from "@godxjp/ui/data-display";
|
|
11
11
|
import { Text } from "@godxjp/ui/general";
|
|
12
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
12
13
|
import { Breadcrumb } from "@godxjp/ui/layout";
|
|
13
14
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
14
15
|
|
|
@@ -25,6 +26,9 @@ const RouterLink = forwardRef<
|
|
|
25
26
|
});
|
|
26
27
|
|
|
27
28
|
export default function Demo() {
|
|
29
|
+
const { t } = useTranslation();
|
|
30
|
+
const suite = t("breadcrumbExamples.longSuite");
|
|
31
|
+
const section = t("breadcrumbExamples.longSection");
|
|
28
32
|
return (
|
|
29
33
|
<PageContainer
|
|
30
34
|
title="Breadcrumb"
|
|
@@ -177,6 +181,26 @@ export default function Demo() {
|
|
|
177
181
|
</Flex>
|
|
178
182
|
</CardContent>
|
|
179
183
|
</Card>
|
|
184
|
+
|
|
185
|
+
{/* gh#1046 — a long segment cut to one line, the full label in a tooltip. */}
|
|
186
|
+
<Card>
|
|
187
|
+
<CardHeader>
|
|
188
|
+
<CardTitle level={2}>{t("breadcrumbExamples.ellipsisTitle")}</CardTitle>
|
|
189
|
+
<CardDescription>{t("breadcrumbExamples.ellipsisDescription")}</CardDescription>
|
|
190
|
+
</CardHeader>
|
|
191
|
+
<CardContent>
|
|
192
|
+
<div id="breadcrumb-ellipsis">
|
|
193
|
+
<Breadcrumb
|
|
194
|
+
ariaLabel={t("breadcrumbExamples.ellipsisAria")}
|
|
195
|
+
items={[
|
|
196
|
+
{ label: t("breadcrumbExamples.home"), to: "/" },
|
|
197
|
+
{ label: suite, to: "/suites/412", ellipsis: true },
|
|
198
|
+
{ label: section, ellipsis: true },
|
|
199
|
+
]}
|
|
200
|
+
/>
|
|
201
|
+
</div>
|
|
202
|
+
</CardContent>
|
|
203
|
+
</Card>
|
|
180
204
|
</Flex>
|
|
181
205
|
</PageContainer>
|
|
182
206
|
);
|