banhaten 0.1.3 → 0.3.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/CHANGELOG.md +73 -0
- package/CONTRIBUTING.md +44 -0
- package/README.md +65 -13
- package/SECURITY.md +15 -0
- package/banhaten.config.example.json +0 -2
- package/docs/design-system/README.md +9 -0
- package/docs/design-system/adoption-quality-remediation.md +87 -0
- package/docs/design-system/agent-usage.md +13 -0
- package/docs/design-system/appearance-presets.md +6 -1
- package/docs/design-system/component-docs-pattern.md +81 -0
- package/docs/design-system/component-implementation-ownership-audit.md +244 -0
- package/docs/design-system/component-quality-audit-2026-08-20.md +223 -0
- package/docs/design-system/component-showcase-consistency-report.md +2 -0
- package/docs/design-system/component-token-consistency-audit.md +13 -3
- package/docs/design-system/components/README.md +4 -2
- package/docs/design-system/components/accordion.md +16 -0
- package/docs/design-system/components/activity-feed.md +17 -1
- package/docs/design-system/components/activity-heatmap.md +73 -0
- package/docs/design-system/components/alert-dialog.md +17 -0
- package/docs/design-system/components/alert.md +46 -14
- package/docs/design-system/components/aspect-ratio.md +15 -0
- package/docs/design-system/components/attribute.md +16 -0
- package/docs/design-system/components/autocomplete.md +19 -0
- package/docs/design-system/components/avatar.md +18 -0
- package/docs/design-system/components/badge.md +19 -0
- package/docs/design-system/components/banner.md +19 -1
- package/docs/design-system/components/breadcrumbs.md +17 -0
- package/docs/design-system/components/button-group.md +35 -0
- package/docs/design-system/components/button.md +18 -0
- package/docs/design-system/components/card.md +26 -1
- package/docs/design-system/components/carousel.md +20 -3
- package/docs/design-system/components/catalog-components.md +18 -1
- package/docs/design-system/components/chart.md +15 -0
- package/docs/design-system/components/checkbox.md +16 -0
- package/docs/design-system/components/collapsible.md +15 -0
- package/docs/design-system/components/command.md +15 -0
- package/docs/design-system/components/context-menu.md +15 -0
- package/docs/design-system/components/date-picker.md +21 -1
- package/docs/design-system/components/divider.md +16 -0
- package/docs/design-system/components/empty-state.md +17 -0
- package/docs/design-system/components/field.md +17 -0
- package/docs/design-system/components/file-upload.md +18 -0
- package/docs/design-system/components/hover-card.md +15 -0
- package/docs/design-system/components/input-group.md +17 -0
- package/docs/design-system/components/input-otp.md +18 -0
- package/docs/design-system/components/input.md +43 -7
- package/docs/design-system/components/item.md +72 -0
- package/docs/design-system/components/kbd.md +18 -0
- package/docs/design-system/components/label.md +16 -0
- package/docs/design-system/components/menu.md +17 -0
- package/docs/design-system/components/menubar.md +15 -0
- package/docs/design-system/components/modal.md +25 -4
- package/docs/design-system/components/native-select.md +18 -0
- package/docs/design-system/components/navigation-menu.md +15 -0
- package/docs/design-system/components/onboarding-step-list-item.md +16 -1
- package/docs/design-system/components/page-header.md +17 -1
- package/docs/design-system/components/pagination.md +31 -8
- package/docs/design-system/components/popover.md +19 -0
- package/docs/design-system/components/progress-slider.md +18 -0
- package/docs/design-system/components/progress.md +17 -0
- package/docs/design-system/components/radio-card.md +16 -0
- package/docs/design-system/components/radio-group.md +17 -0
- package/docs/design-system/components/resizable.md +15 -0
- package/docs/design-system/components/scroll-area.md +20 -1
- package/docs/design-system/components/segmented-control.md +71 -0
- package/docs/design-system/components/select.md +44 -7
- package/docs/design-system/components/sheet.md +17 -0
- package/docs/design-system/components/sidebar.md +17 -0
- package/docs/design-system/components/skeleton.md +18 -0
- package/docs/design-system/components/slideout.md +17 -0
- package/docs/design-system/components/slider.md +20 -0
- package/docs/design-system/components/social-button.md +21 -3
- package/docs/design-system/components/spinner.md +16 -0
- package/docs/design-system/components/steps.md +19 -0
- package/docs/design-system/components/table.md +36 -4
- package/docs/design-system/components/tabs.md +17 -0
- package/docs/design-system/components/tag.md +17 -0
- package/docs/design-system/components/textarea.md +16 -0
- package/docs/design-system/components/timeline.md +17 -0
- package/docs/design-system/components/toast.md +17 -0
- package/docs/design-system/components/toggle.md +17 -0
- package/docs/design-system/components/toolbar.md +21 -1
- package/docs/design-system/components/tooltip.md +18 -1
- package/docs/design-system/density-and-elevation.md +61 -0
- package/docs/design-system/direction-and-localization.md +23 -0
- package/docs/design-system/form-recipes.md +73 -0
- package/docs/design-system/gap-promotion-policy.md +21 -0
- package/docs/design-system/gap-promotion-report.md +100 -0
- package/docs/design-system/installation.md +68 -0
- package/docs/design-system/launch-comparison-shadcn.md +98 -0
- package/docs/design-system/registry-and-cli.md +30 -7
- package/docs/design-system/release-policy.md +30 -0
- package/docs/design-system/roadmap.md +14 -0
- package/docs/design-system/support-matrix.md +23 -0
- package/docs/design-system/tabs.md +1 -1
- package/docs/design-system/token-governance.md +23 -1
- package/package.json +30 -15
- package/registry/component-contract.json +40 -0
- package/registry/components/alert-dialog.tsx +2 -2
- package/registry/components/alert.tsx +101 -76
- package/registry/components/autocomplete.tsx +23 -9
- package/registry/components/avatar.tsx +14 -10
- package/registry/components/badge.tsx +18 -18
- package/registry/components/button-group.tsx +324 -5
- package/registry/components/button.tsx +38 -17
- package/registry/components/card.tsx +87 -62
- package/registry/components/carousel.tsx +67 -5
- package/registry/components/chart.tsx +36 -3
- package/registry/components/checkbox.tsx +3 -3
- package/registry/components/collapsible.tsx +1 -1
- package/registry/components/command.tsx +38 -4
- package/registry/components/context-menu.tsx +1 -1
- package/registry/components/date-picker.tsx +312 -135
- package/registry/components/expanded/ActivityFeed.tsx +9 -22
- package/registry/components/expanded/ActivityHeatmap.tsx +64 -0
- package/registry/components/expanded/Banner.tsx +3 -4
- package/registry/components/expanded/Breadcrumbs.tsx +8 -5
- package/registry/components/expanded/CatalogComponentsShowcase.tsx +16 -17
- package/registry/components/expanded/CatalogDivider.tsx +4 -3
- package/registry/components/expanded/EmptyState.tsx +1 -1
- package/registry/components/expanded/FileUpload.tsx +16 -7
- package/registry/components/expanded/OnboardingStepListItem.tsx +2 -6
- package/registry/components/expanded/PageHeader.tsx +47 -56
- package/registry/components/expanded/Slideout.tsx +29 -424
- package/registry/components/expanded/Steps.tsx +151 -13
- package/registry/components/expanded/Table.tsx +161 -82
- package/registry/components/expanded/Timeline.tsx +14 -27
- package/registry/components/expanded/activityFeed.css +9 -9
- package/registry/components/expanded/activityHeatmap.css +66 -0
- package/registry/components/expanded/banner.css +21 -11
- package/registry/components/expanded/breadcrumbs.css +2 -2
- package/registry/components/expanded/divider.css +1 -1
- package/registry/components/expanded/emptyState.css +1 -1
- package/registry/components/expanded/fileUpload.css +7 -7
- package/registry/components/expanded/onboardingStepListItem.css +2 -2
- package/registry/components/expanded/pageHeader.css +14 -11
- package/registry/components/expanded/slideout.css +10 -690
- package/registry/components/expanded/steps.css +78 -15
- package/registry/components/expanded/table.css +60 -69
- package/registry/components/expanded/timeline.css +19 -18
- package/registry/components/field.tsx +61 -8
- package/registry/components/input-content.ts +1 -0
- package/registry/components/input-otp.tsx +13 -3
- package/registry/components/input.tsx +68 -43
- package/registry/components/item.tsx +189 -0
- package/registry/components/kbd.tsx +111 -4
- package/registry/components/menu.tsx +87 -251
- package/registry/components/menubar.tsx +1 -1
- package/registry/components/modal.tsx +143 -103
- package/registry/components/native-select.tsx +2 -2
- package/registry/components/navigation-menu.tsx +1 -1
- package/registry/components/pagination.css +36 -0
- package/registry/components/pagination.tsx +88 -64
- package/registry/components/popover.tsx +162 -664
- package/registry/components/progress-slider.tsx +1 -1
- package/registry/components/radio-card.tsx +116 -87
- package/registry/components/resizable.tsx +36 -2
- package/registry/components/scroll-area.tsx +30 -6
- package/registry/components/segmented-control.tsx +87 -0
- package/registry/components/select-content.tsx +2 -2
- package/registry/components/select.tsx +86 -27
- package/registry/components/sheet.tsx +1 -1
- package/registry/components/sidebar.tsx +12 -6
- package/registry/components/skeleton.css +0 -3
- package/registry/components/social-button.tsx +59 -30
- package/registry/components/spinner.tsx +18 -55
- package/registry/components/table-elements.tsx +128 -0
- package/registry/components/tabs.css +1 -1
- package/registry/components/tabs.tsx +13 -14
- package/registry/components/tag.tsx +3 -3
- package/registry/components/textarea.tsx +3 -3
- package/registry/components/toast.tsx +16 -11
- package/registry/components/toggle.tsx +4 -4
- package/registry/components/toolbar.tsx +94 -22
- package/registry/components/tooltip.tsx +2 -2
- package/registry/examples/alert-demo.tsx +25 -5
- package/registry/examples/attribute-demo.tsx +1 -1
- package/registry/examples/autocomplete-demo.tsx +3 -3
- package/registry/examples/avatar-demo.tsx +14 -11
- package/registry/examples/badge-demo.tsx +1 -1
- package/registry/examples/button-demo.tsx +6 -6
- package/registry/examples/button-group-demo.tsx +23 -2
- package/registry/examples/card-demo.tsx +46 -8
- package/registry/examples/carousel-demo.tsx +20 -2
- package/registry/examples/chart-demo.tsx +1 -1
- package/registry/examples/checkbox-demo.tsx +5 -5
- package/registry/examples/collection-filter-bar-demo.tsx +135 -0
- package/registry/examples/command-demo.tsx +3 -3
- package/registry/examples/{expanded/command-bar-demo.tsx → command-palette-demo.tsx} +5 -15
- package/registry/examples/context-menu-demo.tsx +1 -1
- package/registry/examples/control-density-contract-demo.tsx +61 -0
- package/registry/examples/date-picker-demo.tsx +12 -12
- package/registry/examples/divider-demo.tsx +3 -3
- package/registry/examples/expanded/activity-heatmap-demo.tsx +29 -0
- package/registry/examples/expanded/banner-demo.tsx +1 -1
- package/registry/examples/expanded/breadcrumbs-demo.tsx +4 -4
- package/registry/examples/expanded/empty-state-demo.tsx +1 -1
- package/registry/examples/expanded/file-upload-demo.tsx +1 -1
- package/registry/examples/expanded/onboarding-step-demo.tsx +1 -1
- package/registry/examples/expanded/slideout-demo.tsx +2 -2
- package/registry/examples/expanded/steps-demo.tsx +1 -1
- package/registry/examples/expanded/tabs-demo.tsx +1 -1
- package/registry/examples/expanded/timeline-demo.tsx +1 -1
- package/registry/examples/hover-card-demo.tsx +2 -2
- package/registry/examples/input-demo.tsx +6 -6
- package/registry/examples/input-otp-demo.tsx +4 -4
- package/registry/examples/item-demo.tsx +46 -0
- package/registry/examples/kbd-demo.tsx +1 -1
- package/registry/examples/label-demo.tsx +1 -1
- package/registry/examples/menu-demo.tsx +1 -1
- package/registry/examples/modal-demo.tsx +67 -9
- package/registry/examples/navigation-menu-demo.tsx +1 -1
- package/registry/examples/pagination-demo.tsx +10 -7
- package/registry/examples/popover-demo.tsx +19 -19
- package/registry/examples/progress-demo.tsx +1 -1
- package/registry/examples/progress-slider-demo.tsx +1 -1
- package/registry/examples/radio-card-demo.tsx +4 -4
- package/registry/examples/radio-group-demo.tsx +2 -2
- package/registry/examples/resizable-demo.tsx +1 -1
- package/registry/examples/results-toolbar-demo.tsx +44 -0
- package/registry/examples/scroll-area-demo.tsx +3 -3
- package/registry/examples/segmented-control-demo.tsx +39 -0
- package/registry/examples/select-demo.tsx +1 -1
- package/registry/examples/sidebar-demo.tsx +5 -3
- package/registry/examples/slider-demo.tsx +3 -3
- package/registry/examples/social-button-demo.tsx +18 -8
- package/registry/examples/spinner-demo.tsx +13 -13
- package/registry/examples/tabs-demo.tsx +1 -1
- package/registry/examples/tag-demo.tsx +1 -1
- package/registry/examples/textarea-demo.tsx +4 -4
- package/registry/examples/toast-demo.tsx +1 -1
- package/registry/examples/toggle-demo.tsx +6 -6
- package/registry/examples/tooltip-demo.tsx +4 -4
- package/registry/guidance/USAGE.md +27 -0
- package/registry/hooks/use-direction.ts +193 -13
- package/registry/index.json +5668 -375
- package/registry/styles/globals.css +2404 -3999
- package/registry.json +156 -149
- package/schema/config.schema.json +11 -8
- package/schema/registry.schema.json +150 -45
- package/schema/tokens.schema.json +134 -34
- package/src/cli/command-line.js +194 -0
- package/src/cli/config-editors.js +9 -0
- package/src/cli/doctor.js +399 -0
- package/src/cli/file-transaction.js +295 -0
- package/src/cli/global-css.js +153 -0
- package/src/cli/index.js +567 -1613
- package/src/cli/install-plan.js +592 -0
- package/src/cli/install-receipt.js +171 -0
- package/src/cli/jsonc.js +203 -0
- package/src/cli/package-install-state.js +254 -0
- package/src/cli/package-manager.js +238 -0
- package/src/cli/package-plan.js +185 -0
- package/src/cli/package-version.js +97 -0
- package/src/cli/registry-query.js +207 -0
- package/src/cli/reporting.js +55 -0
- package/src/cli/schema-validation.js +19 -0
- package/src/cli/source-scanner.js +686 -0
- package/src/cli/vite-config.js +478 -0
- package/tokens/banhaten.tokens.json +4444 -331
- package/docs/design-system/components/command-bar.md +0 -57
- package/registry/components/expanded/BannerBoard.tsx +0 -225
- package/registry/components/expanded/CatalogTag.tsx +0 -85
- package/registry/components/expanded/CommandBar.tsx +0 -386
- package/registry/components/expanded/IconExplorer.tsx +0 -612
- package/registry/components/expanded/TimelineShowcase.tsx +0 -158
- package/registry/components/expanded/commandBar.css +0 -470
- package/registry/components/expanded/iconExplorer.css +0 -764
- package/registry/components/expanded/iconPacks.ts +0 -866
- package/registry/components/expanded/tag.css +0 -148
- package/registry/examples/expanded/icons-demo.tsx +0 -5
- package/tokens/Color mode.zip +0 -0
- package/tokens/Numbers.zip +0 -0
- package/tokens/Radius.zip +0 -0
- package/tokens/Theme.zip +0 -0
|
@@ -54,8 +54,8 @@ function classes(...names: Array<string | false | undefined>) {
|
|
|
54
54
|
|
|
55
55
|
function StatusDot() {
|
|
56
56
|
return (
|
|
57
|
-
<span className="ds-activity-feed-item__status" aria-hidden="true"
|
|
58
|
-
<span
|
|
57
|
+
<span className="ds-activity-feed-item__status" aria-hidden="true">
|
|
58
|
+
<span />
|
|
59
59
|
</span>
|
|
60
60
|
);
|
|
61
61
|
}
|
|
@@ -63,21 +63,15 @@ function StatusDot() {
|
|
|
63
63
|
function Indicator({
|
|
64
64
|
avatarAlt,
|
|
65
65
|
avatarSrc,
|
|
66
|
-
rtl,
|
|
67
66
|
showLine,
|
|
68
|
-
type,
|
|
69
67
|
}: {
|
|
70
68
|
avatarAlt: string;
|
|
71
69
|
avatarSrc: string;
|
|
72
|
-
rtl: boolean;
|
|
73
70
|
showLine: boolean;
|
|
74
|
-
type: ActivityFeedItemType;
|
|
75
71
|
}) {
|
|
76
|
-
const avatarNodeId = rtl ? (type === "caption" ? "587:18722" : "587:18703") : type === "caption" ? "584:18593" : "584:10955";
|
|
77
|
-
|
|
78
72
|
return (
|
|
79
73
|
<span className="ds-activity-feed-item__indicator" aria-hidden={avatarAlt ? undefined : "true"}>
|
|
80
|
-
<span className="ds-activity-feed-item__avatar"
|
|
74
|
+
<span className="ds-activity-feed-item__avatar">
|
|
81
75
|
<img alt={avatarAlt} src={avatarSrc} />
|
|
82
76
|
</span>
|
|
83
77
|
{showLine && <span className="ds-activity-feed-item__line" />}
|
|
@@ -146,7 +140,7 @@ export function ActivityFeedItem({
|
|
|
146
140
|
hasTwoActionButtons = true,
|
|
147
141
|
label,
|
|
148
142
|
link,
|
|
149
|
-
dir
|
|
143
|
+
dir,
|
|
150
144
|
showLine = true,
|
|
151
145
|
showPaddingBottom = true,
|
|
152
146
|
slotContent,
|
|
@@ -155,8 +149,6 @@ export function ActivityFeedItem({
|
|
|
155
149
|
type = "caption",
|
|
156
150
|
}: ActivityFeedItemProps) {
|
|
157
151
|
const actionItems = actions === false || !hasActionButtons ? [] : (actions ?? []).slice(0, hasTwoActionButtons ? 2 : 1);
|
|
158
|
-
const rtl = dir === "rtl";
|
|
159
|
-
const nodeId = rtl ? (type === "caption" ? "587:18720" : "587:18701") : type === "caption" ? "584:18591" : "584:10411";
|
|
160
152
|
|
|
161
153
|
const textParts = [
|
|
162
154
|
label && <strong key="label">{label}</strong>,
|
|
@@ -169,13 +161,11 @@ export function ActivityFeedItem({
|
|
|
169
161
|
className={classes(
|
|
170
162
|
"ds-activity-feed-item",
|
|
171
163
|
`ds-activity-feed-item--${type}`,
|
|
172
|
-
rtl ? "ds-activity-feed-item--rtl" : "ds-activity-feed-item--ltr",
|
|
173
164
|
className,
|
|
174
165
|
)}
|
|
175
|
-
|
|
176
|
-
dir={rtl ? "rtl" : "ltr"}
|
|
166
|
+
dir={dir}
|
|
177
167
|
>
|
|
178
|
-
<Indicator avatarAlt={avatarAlt} avatarSrc={avatarSrc}
|
|
168
|
+
<Indicator avatarAlt={avatarAlt} avatarSrc={avatarSrc} showLine={showLine} />
|
|
179
169
|
|
|
180
170
|
<div className="ds-activity-feed-item__content">
|
|
181
171
|
<div className="ds-activity-feed-item__container">
|
|
@@ -215,17 +205,14 @@ export function ActivityFeed({
|
|
|
215
205
|
ariaLabel,
|
|
216
206
|
avatarSrc = defaultAvatarSrc,
|
|
217
207
|
className,
|
|
218
|
-
dir
|
|
208
|
+
dir,
|
|
219
209
|
items = [],
|
|
220
210
|
}: ActivityFeedProps) {
|
|
221
|
-
const rtl = dir === "rtl";
|
|
222
|
-
|
|
223
211
|
return (
|
|
224
212
|
<section
|
|
225
213
|
aria-label={ariaLabel}
|
|
226
|
-
className={classes("ds-activity-feed",
|
|
227
|
-
|
|
228
|
-
dir={rtl ? "rtl" : "ltr"}
|
|
214
|
+
className={classes("ds-activity-feed", className)}
|
|
215
|
+
dir={dir}
|
|
229
216
|
>
|
|
230
217
|
{items.map((item, index) => (
|
|
231
218
|
<ActivityFeedItem
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
+
import "./activityHeatmap.css";
|
|
3
|
+
|
|
4
|
+
export type ActivityHeatmapLevel = 0 | 1 | 2 | 3 | 4;
|
|
5
|
+
|
|
6
|
+
export type ActivityHeatmapItem = {
|
|
7
|
+
id?: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
level: ActivityHeatmapLevel;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type ActivityHeatmapProps = Omit<
|
|
13
|
+
ComponentPropsWithoutRef<"div">,
|
|
14
|
+
"children" | "dir"
|
|
15
|
+
> & {
|
|
16
|
+
ariaLabel?: string;
|
|
17
|
+
dir?: "ltr" | "rtl";
|
|
18
|
+
items?: readonly ActivityHeatmapItem[];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function classes(...names: Array<string | false | undefined>) {
|
|
22
|
+
return names.filter(Boolean).join(" ");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function normalizeLevel(level: ActivityHeatmapLevel): ActivityHeatmapLevel {
|
|
26
|
+
return Math.max(0, Math.min(4, Math.round(level))) as ActivityHeatmapLevel;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function ActivityHeatmap({
|
|
30
|
+
ariaLabel = "Activity heatmap",
|
|
31
|
+
className,
|
|
32
|
+
dir,
|
|
33
|
+
items = [],
|
|
34
|
+
tabIndex = 0,
|
|
35
|
+
...props
|
|
36
|
+
}: ActivityHeatmapProps) {
|
|
37
|
+
return (
|
|
38
|
+
<div
|
|
39
|
+
{...props}
|
|
40
|
+
aria-label={ariaLabel}
|
|
41
|
+
className={classes("ds-activity-heatmap", className)}
|
|
42
|
+
data-slot="activity-heatmap"
|
|
43
|
+
dir={dir}
|
|
44
|
+
role="img"
|
|
45
|
+
tabIndex={tabIndex}
|
|
46
|
+
>
|
|
47
|
+
<span
|
|
48
|
+
aria-hidden="true"
|
|
49
|
+
className="ds-activity-heatmap__grid"
|
|
50
|
+
data-slot="activity-heatmap-grid"
|
|
51
|
+
>
|
|
52
|
+
{items.map((item, index) => (
|
|
53
|
+
<span
|
|
54
|
+
className="ds-activity-heatmap__cell"
|
|
55
|
+
data-level={normalizeLevel(item.level)}
|
|
56
|
+
data-slot="activity-heatmap-cell"
|
|
57
|
+
key={item.id ?? index}
|
|
58
|
+
title={item.label}
|
|
59
|
+
/>
|
|
60
|
+
))}
|
|
61
|
+
</span>
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
@@ -35,11 +35,11 @@ export type BannerProps = {
|
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
function MegaphoneIcon() {
|
|
38
|
-
return <LucideMegaphoneIcon aria-hidden="true" className="ds-banner__icon" strokeWidth=
|
|
38
|
+
return <LucideMegaphoneIcon aria-hidden="true" className="ds-banner__icon" strokeWidth="var(--bh-icon-stroke-210)" />;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
function CloseIcon() {
|
|
42
|
-
return <XIcon aria-hidden="true" className="ds-banner__close-icon" strokeWidth=
|
|
42
|
+
return <XIcon aria-hidden="true" className="ds-banner__close-icon" strokeWidth="var(--bh-icon-stroke-225)" />;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
function getBannerActionVariant(color: BannerColor): ButtonProps["variant"] {
|
|
@@ -60,7 +60,7 @@ export function Banner({
|
|
|
60
60
|
color = "brand",
|
|
61
61
|
content = "title",
|
|
62
62
|
description,
|
|
63
|
-
dir
|
|
63
|
+
dir,
|
|
64
64
|
icon,
|
|
65
65
|
inputAriaLabel,
|
|
66
66
|
inputPlaceholder,
|
|
@@ -101,7 +101,6 @@ export function Banner({
|
|
|
101
101
|
`ds-banner--${size}`,
|
|
102
102
|
`ds-banner--${color}`,
|
|
103
103
|
`ds-banner--${content}`,
|
|
104
|
-
dir === "rtl" && "ds-banner--rtl",
|
|
105
104
|
className,
|
|
106
105
|
)}
|
|
107
106
|
dir={dir}
|
|
@@ -19,6 +19,7 @@ export type BreadcrumbItem = {
|
|
|
19
19
|
|
|
20
20
|
export type BreadcrumbsProps = {
|
|
21
21
|
"aria-label"?: string;
|
|
22
|
+
className?: string;
|
|
22
23
|
dir?: "ltr" | "rtl" | "auto";
|
|
23
24
|
iconOnly?: boolean;
|
|
24
25
|
items: BreadcrumbItem[];
|
|
@@ -49,7 +50,8 @@ function visibleItems(
|
|
|
49
50
|
|
|
50
51
|
export function Breadcrumbs({
|
|
51
52
|
"aria-label": ariaLabel,
|
|
52
|
-
|
|
53
|
+
className,
|
|
54
|
+
dir,
|
|
53
55
|
iconOnly = false,
|
|
54
56
|
items,
|
|
55
57
|
maxItems,
|
|
@@ -67,6 +69,7 @@ export function Breadcrumbs({
|
|
|
67
69
|
`ds-breadcrumbs--${surfaceStyle}`,
|
|
68
70
|
`ds-breadcrumbs--${separator}`,
|
|
69
71
|
iconOnly && "ds-breadcrumbs--icon-only",
|
|
72
|
+
className,
|
|
70
73
|
)}
|
|
71
74
|
dir={dir}
|
|
72
75
|
>
|
|
@@ -112,17 +115,17 @@ function Separator({ separator }: { separator: BreadcrumbSeparator }) {
|
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
export function BreadcrumbHomeIcon() {
|
|
115
|
-
return <HomeIcon aria-hidden="true" strokeWidth=
|
|
118
|
+
return <HomeIcon aria-hidden="true" strokeWidth="var(--bh-icon-stroke-190)" />;
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
export function BreadcrumbFolderIcon() {
|
|
119
|
-
return <FolderIcon aria-hidden="true" strokeWidth=
|
|
122
|
+
return <FolderIcon aria-hidden="true" strokeWidth="var(--bh-icon-stroke-190)" />;
|
|
120
123
|
}
|
|
121
124
|
|
|
122
125
|
function ChevronIcon() {
|
|
123
|
-
return <ChevronRightIcon aria-hidden="true" strokeWidth=
|
|
126
|
+
return <ChevronRightIcon aria-hidden="true" strokeWidth="var(--bh-icon-stroke-200)" />;
|
|
124
127
|
}
|
|
125
128
|
|
|
126
129
|
function OverflowIcon() {
|
|
127
|
-
return <EllipsisIcon aria-hidden="true" strokeWidth=
|
|
130
|
+
return <EllipsisIcon aria-hidden="true" strokeWidth="var(--bh-icon-stroke-225)" />;
|
|
128
131
|
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { CatalogContentDivider, CatalogDivider } from "./CatalogDivider";
|
|
9
9
|
import { FileUpload, type FileUploadFile } from "./FileUpload";
|
|
10
10
|
import { Table, type TableColumn, type TableRowBase } from "./Table";
|
|
11
|
-
import {
|
|
11
|
+
import { Tag, type TagState, type TagType } from "@/components/ui/tag";
|
|
12
12
|
import "./catalogComponentsShowcase.css";
|
|
13
13
|
|
|
14
14
|
type ProjectRow = TableRowBase & {
|
|
@@ -32,7 +32,6 @@ const rtlBreadcrumbItems: BreadcrumbItem[] = [
|
|
|
32
32
|
{ label: "\u0627\u0644\u0645\u0643\u0648\u0646\u0627\u062a", current: true },
|
|
33
33
|
];
|
|
34
34
|
|
|
35
|
-
const breadcrumbAriaLabel = "Catalog breadcrumbs";
|
|
36
35
|
const rtlBreadcrumbAriaLabel = "\u0627\u0644\u0645\u0633\u0627\u0631";
|
|
37
36
|
|
|
38
37
|
const uploadFiles: FileUploadFile[] = [
|
|
@@ -99,8 +98,8 @@ const columns: TableColumn<ProjectRow>[] = [
|
|
|
99
98
|
{ id: "actions", width: 44, kind: "actions", item: () => ({ type: "action", icon: "more", label: "Open row actions" }) },
|
|
100
99
|
];
|
|
101
100
|
|
|
102
|
-
const tagTypes:
|
|
103
|
-
const tagStates:
|
|
101
|
+
const tagTypes: TagType[] = ["simple", "dot", "flag", "avatar", "icon"];
|
|
102
|
+
const tagStates: TagState[] = ["default", "active", "disabled"];
|
|
104
103
|
|
|
105
104
|
export function CatalogComponentsShowcase() {
|
|
106
105
|
const [selectedRows, setSelectedRows] = useState(["1", "2"]);
|
|
@@ -109,9 +108,9 @@ export function CatalogComponentsShowcase() {
|
|
|
109
108
|
<div className="catalog-showcase">
|
|
110
109
|
<ShowcaseCard title="Breadcrumbs" description="Default, raised, icon-only, separator, and RTL variants.">
|
|
111
110
|
<div className="catalog-showcase__stack">
|
|
112
|
-
<Breadcrumbs aria-label=
|
|
113
|
-
<Breadcrumbs aria-label=
|
|
114
|
-
<Breadcrumbs aria-label=
|
|
111
|
+
<Breadcrumbs aria-label="Default catalog breadcrumbs" items={breadcrumbItems} overflowLabel="More" />
|
|
112
|
+
<Breadcrumbs aria-label="Raised catalog breadcrumbs" items={breadcrumbItems} overflowLabel="More" separator="chevron" style="raised" />
|
|
113
|
+
<Breadcrumbs aria-label="Icon-only catalog breadcrumbs" iconOnly items={breadcrumbItems} overflowLabel="More" separator="chevron" style="raised" />
|
|
115
114
|
<Breadcrumbs
|
|
116
115
|
aria-label={rtlBreadcrumbAriaLabel}
|
|
117
116
|
dir="rtl"
|
|
@@ -136,7 +135,7 @@ export function CatalogComponentsShowcase() {
|
|
|
136
135
|
<ShowcaseCard title="Tags" description="Type, state, size, close button, and RTL coverage.">
|
|
137
136
|
<div className="catalog-showcase__tag-grid">
|
|
138
137
|
{tagTypes.map((type) => (
|
|
139
|
-
<
|
|
138
|
+
<Tag
|
|
140
139
|
closeLabel="Remove tag"
|
|
141
140
|
key={type}
|
|
142
141
|
showCloseButton={type === "simple"}
|
|
@@ -144,19 +143,19 @@ export function CatalogComponentsShowcase() {
|
|
|
144
143
|
avatar={type === "avatar" ? "A" : undefined}
|
|
145
144
|
>
|
|
146
145
|
{type}
|
|
147
|
-
</
|
|
146
|
+
</Tag>
|
|
148
147
|
))}
|
|
149
148
|
{tagStates.map((state) => (
|
|
150
|
-
<
|
|
149
|
+
<Tag key={state} state={state} type="dot">
|
|
151
150
|
{state}
|
|
152
|
-
</
|
|
151
|
+
</Tag>
|
|
153
152
|
))}
|
|
154
|
-
<
|
|
155
|
-
<
|
|
156
|
-
<
|
|
153
|
+
<Tag size="xs">xs</Tag>
|
|
154
|
+
<Tag size="md">md</Tag>
|
|
155
|
+
<Tag closeLabel="Remove tag" size="lg" showCloseButton>
|
|
157
156
|
large
|
|
158
|
-
</
|
|
159
|
-
<
|
|
157
|
+
</Tag>
|
|
158
|
+
<Tag
|
|
160
159
|
avatar={"\u0645"}
|
|
161
160
|
closeLabel={"\u0625\u0632\u0627\u0644\u0629 \u0648\u0633\u0645"}
|
|
162
161
|
dir="rtl"
|
|
@@ -164,7 +163,7 @@ export function CatalogComponentsShowcase() {
|
|
|
164
163
|
showCloseButton
|
|
165
164
|
>
|
|
166
165
|
{"\u0645\u0644\u0635\u0642"}
|
|
167
|
-
</
|
|
166
|
+
</Tag>
|
|
168
167
|
</div>
|
|
169
168
|
</ShowcaseCard>
|
|
170
169
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Button } from "@/components/ui/button";
|
|
1
2
|
import "./divider.css";
|
|
2
3
|
|
|
3
4
|
export type DividerBorderStyle = "solid" | "dotted";
|
|
@@ -27,7 +28,7 @@ export function CatalogDivider({ borderStyle = "solid" }: CatalogDividerProps) {
|
|
|
27
28
|
export function CatalogContentDivider({
|
|
28
29
|
actionLabel,
|
|
29
30
|
borderStyle = "solid",
|
|
30
|
-
dir
|
|
31
|
+
dir,
|
|
31
32
|
disabled = false,
|
|
32
33
|
label,
|
|
33
34
|
onAction,
|
|
@@ -36,9 +37,9 @@ export function CatalogContentDivider({
|
|
|
36
37
|
<div className={`ds-content-divider ds-content-divider--${borderStyle}`} dir={dir}>
|
|
37
38
|
<span aria-hidden="true" className="ds-content-divider__rule" />
|
|
38
39
|
{actionLabel && onAction ? (
|
|
39
|
-
<
|
|
40
|
+
<Button className="ds-content-divider__button" disabled={disabled} onClick={onAction} size="sm" type="button" variant="soft">
|
|
40
41
|
{actionLabel}
|
|
41
|
-
</
|
|
42
|
+
</Button>
|
|
42
43
|
) : label ? (
|
|
43
44
|
<span className="ds-content-divider__label">{label}</span>
|
|
44
45
|
) : null}
|
|
@@ -52,7 +52,7 @@ export function FileUpload({
|
|
|
52
52
|
accept,
|
|
53
53
|
browseLabel,
|
|
54
54
|
cancelLabel = "Cancel upload",
|
|
55
|
-
dir
|
|
55
|
+
dir,
|
|
56
56
|
disabled = false,
|
|
57
57
|
dropzoneState = "default",
|
|
58
58
|
files = [],
|
|
@@ -154,9 +154,9 @@ export function FileUpload({
|
|
|
154
154
|
<p className="ds-file-upload__title">
|
|
155
155
|
{resolvedPrompt}{" "}
|
|
156
156
|
{resolvedBrowseLabel && (
|
|
157
|
-
<
|
|
157
|
+
<Button className="ds-file-upload__browse" disabled={disabled} onClick={browse} size="xs" type="button" variant="link">
|
|
158
158
|
{resolvedBrowseLabel}
|
|
159
|
-
</
|
|
159
|
+
</Button>
|
|
160
160
|
)}
|
|
161
161
|
</p>
|
|
162
162
|
)}
|
|
@@ -251,7 +251,14 @@ function FileUploadRow({
|
|
|
251
251
|
)}
|
|
252
252
|
|
|
253
253
|
{isProgress && (
|
|
254
|
-
<div
|
|
254
|
+
<div
|
|
255
|
+
aria-label={`Upload progress ${progressLabel}`}
|
|
256
|
+
aria-valuemax={100}
|
|
257
|
+
aria-valuemin={0}
|
|
258
|
+
aria-valuenow={progressValue}
|
|
259
|
+
className="ds-file-upload-row__progress"
|
|
260
|
+
role="progressbar"
|
|
261
|
+
>
|
|
255
262
|
<span className="ds-file-upload-row__progress-track">
|
|
256
263
|
<span className="ds-file-upload-row__progress-fill" style={{ width: `${progressValue}%` }} />
|
|
257
264
|
</span>
|
|
@@ -260,9 +267,9 @@ function FileUploadRow({
|
|
|
260
267
|
)}
|
|
261
268
|
|
|
262
269
|
{!isSmall && file.status === "error" && (
|
|
263
|
-
<
|
|
270
|
+
<Button className="ds-file-upload-row__retry" onClick={() => onRetry?.(file.id)} size="xs" type="button" variant="link">
|
|
264
271
|
{retryLabel}
|
|
265
|
-
</
|
|
272
|
+
</Button>
|
|
266
273
|
)}
|
|
267
274
|
</div>
|
|
268
275
|
</div>
|
|
@@ -397,12 +404,14 @@ function StatusIcon({
|
|
|
397
404
|
}) {
|
|
398
405
|
return (
|
|
399
406
|
<span
|
|
407
|
+
aria-hidden={standalone ? undefined : "true"}
|
|
408
|
+
aria-label={standalone ? getStatusLabel(status) : undefined}
|
|
400
409
|
className={cx(
|
|
401
410
|
"ds-file-upload-row__status",
|
|
402
411
|
standalone && "ds-file-upload-row__status--standalone",
|
|
403
412
|
`ds-file-upload-row__status--${status}`
|
|
404
413
|
)}
|
|
405
|
-
|
|
414
|
+
role={standalone ? "img" : undefined}
|
|
406
415
|
>
|
|
407
416
|
{status === "uploaded" && <CheckboxCircleFillIcon />}
|
|
408
417
|
{status === "uploading" && <Loader2LineIcon />}
|
|
@@ -15,13 +15,12 @@ export type OnboardingStepListItemProps = {
|
|
|
15
15
|
|
|
16
16
|
export function OnboardingStepListItem({
|
|
17
17
|
className = "",
|
|
18
|
-
dir
|
|
18
|
+
dir,
|
|
19
19
|
label,
|
|
20
20
|
showLeadingLine = true,
|
|
21
21
|
showTrailingLine = true,
|
|
22
22
|
state = "finished",
|
|
23
23
|
}: OnboardingStepListItemProps) {
|
|
24
|
-
const rtl = dir === "rtl";
|
|
25
24
|
const isFinished = state === "finished";
|
|
26
25
|
const isActive = state === "active";
|
|
27
26
|
const isInactive = state === "inactive";
|
|
@@ -31,7 +30,6 @@ export function OnboardingStepListItem({
|
|
|
31
30
|
className={[
|
|
32
31
|
"ds-onboarding-step",
|
|
33
32
|
`ds-onboarding-step--${state}`,
|
|
34
|
-
rtl ? "ds-onboarding-step--rtl" : "ds-onboarding-step--ltr",
|
|
35
33
|
className,
|
|
36
34
|
]
|
|
37
35
|
.filter(Boolean)
|
|
@@ -55,9 +53,7 @@ function CheckCircleIcon() {
|
|
|
55
53
|
<CircleCheckIcon
|
|
56
54
|
aria-hidden="true"
|
|
57
55
|
className="ds-onboarding-step__check"
|
|
58
|
-
|
|
59
|
-
strokeWidth={2.25}
|
|
60
|
-
width="20"
|
|
56
|
+
strokeWidth="var(--bh-icon-stroke-225)"
|
|
61
57
|
/>
|
|
62
58
|
);
|
|
63
59
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
1
|
+
import type { ElementType, ReactNode } from "react";
|
|
2
2
|
import { HomeIcon as LucideHomeIcon } from "lucide-react";
|
|
3
|
+
import { Button } from "@/components/ui/button";
|
|
4
|
+
import { Breadcrumbs as OwnedBreadcrumbs } from "./Breadcrumbs";
|
|
3
5
|
import { Tabs, type TabsProps } from "../tabs";
|
|
4
6
|
import "./pageHeader.css";
|
|
5
7
|
|
|
@@ -31,6 +33,7 @@ export type PageHeaderProps = {
|
|
|
31
33
|
description?: string;
|
|
32
34
|
dir?: "ltr" | "rtl";
|
|
33
35
|
icon?: ReactNode | false;
|
|
36
|
+
headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
34
37
|
metaInfo?: string;
|
|
35
38
|
tabs?: PageHeaderTabs | false;
|
|
36
39
|
title?: string;
|
|
@@ -41,43 +44,7 @@ function classes(...names: Array<string | false | undefined>) {
|
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
function HomeIcon() {
|
|
44
|
-
return <LucideHomeIcon aria-hidden="true" className="ds-page-header__home-icon" strokeWidth=
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function Breadcrumbs({ items, label }: { items: PageHeaderBreadcrumb[]; label?: string }) {
|
|
48
|
-
return (
|
|
49
|
-
<nav aria-label={label} className="ds-page-header__breadcrumbs" data-node-id="1134:39921">
|
|
50
|
-
<ol>
|
|
51
|
-
{items.map((item, index) => {
|
|
52
|
-
const isLast = index === items.length - 1;
|
|
53
|
-
const isCurrent = item.current === true;
|
|
54
|
-
const content = (
|
|
55
|
-
<>
|
|
56
|
-
{item.icon && <span className="ds-page-header__breadcrumb-icon">{item.icon}</span>}
|
|
57
|
-
<span className="ds-page-header__breadcrumb-label">{item.label}</span>
|
|
58
|
-
</>
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
return (
|
|
62
|
-
<li key={`${item.label}-${index}`}>
|
|
63
|
-
{item.href && !isCurrent ? (
|
|
64
|
-
<a href={item.href}>{content}</a>
|
|
65
|
-
) : (
|
|
66
|
-
<span aria-current={isCurrent ? "page" : undefined} className={isCurrent ? "is-current" : undefined}>
|
|
67
|
-
{content}
|
|
68
|
-
</span>
|
|
69
|
-
)}
|
|
70
|
-
{!isLast && (
|
|
71
|
-
<span aria-hidden="true" className="ds-page-header__breadcrumb-separator">
|
|
72
|
-
/
|
|
73
|
-
</span>
|
|
74
|
-
)}
|
|
75
|
-
</li>
|
|
76
|
-
);
|
|
77
|
-
})}
|
|
78
|
-
</ol>
|
|
79
|
-
</nav>
|
|
80
|
-
);
|
|
47
|
+
return <LucideHomeIcon aria-hidden="true" className="ds-page-header__home-icon" strokeWidth="var(--bh-icon-stroke-190)" />;
|
|
81
48
|
}
|
|
82
49
|
|
|
83
50
|
function Action({ action }: { action: PageHeaderAction }) {
|
|
@@ -86,22 +53,37 @@ function Action({ action }: { action: PageHeaderAction }) {
|
|
|
86
53
|
|
|
87
54
|
if (action.href) {
|
|
88
55
|
return (
|
|
89
|
-
<
|
|
90
|
-
|
|
91
|
-
|
|
56
|
+
<Button asChild className={className} variant="secondary">
|
|
57
|
+
<a
|
|
58
|
+
aria-disabled={action.disabled || undefined}
|
|
59
|
+
aria-label={action.ariaLabel}
|
|
60
|
+
href={action.disabled ? undefined : action.href}
|
|
61
|
+
onClick={(event) => {
|
|
62
|
+
if (action.disabled) {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
action.onClick?.();
|
|
67
|
+
}}
|
|
68
|
+
tabIndex={action.disabled ? -1 : undefined}
|
|
69
|
+
>
|
|
70
|
+
{label}
|
|
71
|
+
</a>
|
|
72
|
+
</Button>
|
|
92
73
|
);
|
|
93
74
|
}
|
|
94
75
|
|
|
95
76
|
return (
|
|
96
|
-
<
|
|
77
|
+
<Button
|
|
97
78
|
aria-label={action.ariaLabel}
|
|
98
79
|
className={className}
|
|
99
80
|
disabled={action.disabled}
|
|
100
81
|
onClick={action.onClick}
|
|
101
82
|
type="button"
|
|
83
|
+
variant="secondary"
|
|
102
84
|
>
|
|
103
85
|
{label}
|
|
104
|
-
</
|
|
86
|
+
</Button>
|
|
105
87
|
);
|
|
106
88
|
}
|
|
107
89
|
|
|
@@ -111,7 +93,8 @@ export function PageHeader({
|
|
|
111
93
|
breadcrumbs = [],
|
|
112
94
|
className,
|
|
113
95
|
description,
|
|
114
|
-
dir
|
|
96
|
+
dir,
|
|
97
|
+
headingLevel = 1,
|
|
115
98
|
icon,
|
|
116
99
|
metaInfo,
|
|
117
100
|
tabs = {},
|
|
@@ -120,34 +103,42 @@ export function PageHeader({
|
|
|
120
103
|
const breadcrumbItems = breadcrumbs === false ? [] : breadcrumbs;
|
|
121
104
|
const actionItems = actions === false ? [] : actions;
|
|
122
105
|
const showIcon = icon !== false;
|
|
106
|
+
const Heading = `h${headingLevel}` as ElementType;
|
|
123
107
|
|
|
124
108
|
return (
|
|
125
|
-
<header className={classes("ds-page-header", className)}
|
|
126
|
-
{breadcrumbItems.length > 0 &&
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
109
|
+
<header className={classes("ds-page-header", className)} dir={dir}>
|
|
110
|
+
{breadcrumbItems.length > 0 && (
|
|
111
|
+
<OwnedBreadcrumbs
|
|
112
|
+
aria-label={breadcrumbLabel ?? "Breadcrumb"}
|
|
113
|
+
className="ds-page-header__breadcrumbs"
|
|
114
|
+
dir={dir}
|
|
115
|
+
items={breadcrumbItems}
|
|
116
|
+
/>
|
|
117
|
+
)}
|
|
118
|
+
|
|
119
|
+
<div className="ds-page-header__section">
|
|
120
|
+
<div className="ds-page-header__topline">
|
|
121
|
+
<div className="ds-page-header__copy">
|
|
122
|
+
<div className="ds-page-header__heading-row">
|
|
123
|
+
<div className="ds-page-header__heading-main">
|
|
133
124
|
{showIcon && <span className="ds-page-header__icon">{icon ?? <HomeIcon />}</span>}
|
|
134
|
-
{title && <
|
|
125
|
+
{title && <Heading className="ds-page-header__title">{title}</Heading>}
|
|
135
126
|
</div>
|
|
136
127
|
{metaInfo && (
|
|
137
|
-
<span className="ds-page-header__meta"
|
|
128
|
+
<span className="ds-page-header__meta">
|
|
138
129
|
{metaInfo}
|
|
139
130
|
</span>
|
|
140
131
|
)}
|
|
141
132
|
</div>
|
|
142
133
|
{description && (
|
|
143
|
-
<p className="ds-page-header__description"
|
|
134
|
+
<p className="ds-page-header__description">
|
|
144
135
|
{description}
|
|
145
136
|
</p>
|
|
146
137
|
)}
|
|
147
138
|
</div>
|
|
148
139
|
|
|
149
140
|
{actionItems.length > 0 && (
|
|
150
|
-
<div className="ds-page-header__actions"
|
|
141
|
+
<div className="ds-page-header__actions">
|
|
151
142
|
{actionItems.map((action, index) => (
|
|
152
143
|
<Action action={action} key={`${action.label}-${index}`} />
|
|
153
144
|
))}
|