@aggc/ui 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/dist/chunks/UiSkeleton.vue_vue_type_script_setup_true_lang-Lghyrtms.js +1201 -0
- package/dist/chunks/pageHeader-CcJrPX_8.js +522 -0
- package/dist/components/PageSurface.styles.d.ts +1 -0
- package/dist/components/PageSurface.vue.d.ts +13 -0
- package/dist/components/ResultPanel.styles.d.ts +64 -0
- package/dist/components/ResultPanel.vue.d.ts +16 -0
- package/dist/components/SectionCard.styles.d.ts +13 -0
- package/dist/components/SectionCard.vue.d.ts +27 -0
- package/dist/components/StatusBadge.styles.d.ts +24 -0
- package/dist/components/StatusBadge.vue.d.ts +18 -0
- package/dist/components/UiButton.styles.d.ts +54 -0
- package/dist/components/UiButton.vue.d.ts +28 -0
- package/dist/components/UiCheckbox.styles.d.ts +42 -0
- package/dist/components/UiCheckbox.vue.d.ts +37 -0
- package/dist/components/UiField.styles.d.ts +7 -0
- package/dist/components/UiField.vue.d.ts +22 -0
- package/dist/components/UiLoadingState.styles.d.ts +4 -0
- package/dist/components/UiLoadingState.vue.d.ts +10 -0
- package/dist/components/UiSegmentedControl.styles.d.ts +23 -0
- package/dist/components/UiSegmentedControl.vue.d.ts +14 -0
- package/dist/components/UiSelect.styles.d.ts +104 -0
- package/dist/components/UiSelect.vue.d.ts +35 -0
- package/dist/components/UiSkeleton.styles.d.ts +67 -0
- package/dist/components/UiSkeleton.vue.d.ts +12 -0
- package/dist/components/index.d.ts +11 -0
- package/dist/components.d.ts +1 -0
- package/dist/components.js +14 -0
- package/dist/css.d.ts +2 -0
- package/dist/css.js +1 -0
- package/dist/fonts.css +6 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +65 -0
- package/dist/styles/index.d.ts +20 -0
- package/dist/styles/layouts/cluster.d.ts +27 -0
- package/dist/styles/layouts/page.d.ts +2 -0
- package/dist/styles/layouts/split.d.ts +22 -0
- package/dist/styles/layouts/stack.d.ts +19 -0
- package/dist/styles/patterns/actionToolbar.d.ts +1 -0
- package/dist/styles/patterns/emptyState.d.ts +2 -0
- package/dist/styles/patterns/infoPanel.d.ts +2 -0
- package/dist/styles/patterns/metricGrid.d.ts +22 -0
- package/dist/styles/patterns/pageHeader.d.ts +3 -0
- package/dist/styles/patterns/resultRegion.d.ts +1 -0
- package/dist/styles/patterns/selectableListDetail.d.ts +3 -0
- package/dist/styles/primitives/feedback.d.ts +4 -0
- package/dist/styles/primitives/fields.d.ts +3 -0
- package/dist/styles/primitives/surfaces.d.ts +3 -0
- package/dist/styles/primitives/typography.d.ts +6 -0
- package/dist/styles/recipes/badge.recipe.d.ts +32 -0
- package/dist/styles/recipes/button.recipe.d.ts +51 -0
- package/dist/styles/recipes/card.recipe.d.ts +59 -0
- package/dist/styles/recipes/dropdown.recipe.d.ts +25 -0
- package/dist/styles/recipes/input.recipe.d.ts +32 -0
- package/dist/styles.d.ts +1 -0
- package/dist/styles.js +429 -0
- package/dist/tokens/colors.d.ts +360 -0
- package/dist/tokens/core-colors.d.ts +238 -0
- package/dist/tokens/desktop-colors.d.ts +132 -0
- package/dist/tokens/index.d.ts +7 -0
- package/dist/tokens/motion.d.ts +10 -0
- package/dist/tokens/radius.d.ts +5 -0
- package/dist/tokens/spacing.d.ts +8 -0
- package/dist/tokens/typography.d.ts +10 -0
- package/dist/tokens-core.d.ts +5 -0
- package/dist/tokens-core.js +69 -0
- package/dist/tokens-desktop.d.ts +1 -0
- package/dist/tokens-desktop.js +30 -0
- package/dist/tokens.d.ts +1 -0
- package/dist/tokens.js +16 -0
- package/dist/ui.css +2026 -0
- package/package.json +3 -2
- package/src/components/PageSurface.styles.ts +3 -0
- package/src/components/PageSurface.vue +9 -0
- package/src/components/ResultPanel.styles.ts +108 -0
- package/src/components/ResultPanel.test.ts +22 -0
- package/src/components/ResultPanel.vue +70 -0
- package/src/components/SectionCard.styles.ts +65 -0
- package/src/components/SectionCard.test.ts +22 -0
- package/src/components/SectionCard.vue +51 -0
- package/src/components/StatusBadge.styles.ts +49 -0
- package/src/components/StatusBadge.test.ts +18 -0
- package/src/components/StatusBadge.vue +18 -0
- package/src/components/UiButton.styles.ts +29 -0
- package/src/components/UiButton.test.ts +21 -0
- package/src/components/UiButton.vue +46 -0
- package/src/components/UiCheckbox.styles.ts +118 -0
- package/src/components/UiCheckbox.test.ts +18 -0
- package/src/components/UiCheckbox.vue +72 -0
- package/src/components/UiField.styles.ts +35 -0
- package/src/components/UiField.test.ts +22 -0
- package/src/components/UiField.vue +36 -0
- package/src/components/UiLoadingState.styles.ts +36 -0
- package/src/components/UiLoadingState.vue +34 -0
- package/src/components/UiSegmentedControl.styles.ts +49 -0
- package/src/components/UiSegmentedControl.vue +30 -0
- package/src/components/UiSelect.styles.ts +214 -0
- package/src/components/UiSelect.test.ts +49 -0
- package/src/components/UiSelect.vue +256 -0
- package/src/components/UiSkeleton.styles.ts +93 -0
- package/src/components/UiSkeleton.vue +48 -0
- package/src/components/index.ts +11 -0
- package/src/components.ts +1 -0
- package/src/css/base.css +62 -0
- package/src/css/fonts.css +6 -0
- package/src/css/index.css +2 -0
- package/src/css/storybook.css +15 -0
- package/src/env.d.ts +1 -0
- package/src/index.ts +3 -0
- package/src/stories/feedback/ResultPanel.stories.ts +76 -0
- package/src/stories/feedback/StatusBadge.stories.ts +50 -0
- package/src/stories/feedback/UiLoadingState.stories.ts +52 -0
- package/src/stories/feedback/UiSkeleton.stories.ts +85 -0
- package/src/stories/forms/UiCheckbox.stories.ts +104 -0
- package/src/stories/forms/UiField.stories.ts +87 -0
- package/src/stories/forms/UiSelect.stories.ts +134 -0
- package/src/stories/layout/PageSurface.stories.ts +53 -0
- package/src/stories/layout/SectionCard.stories.ts +85 -0
- package/src/stories/primitives/UiButton.stories.ts +145 -0
- package/src/stories/primitives/UiSegmentedControl.stories.ts +67 -0
- package/src/stories/support/StoryThemeFrame.vue +101 -0
- package/src/stories/support/sources.ts +374 -0
- package/src/stories/support/storyStyles.ts +150 -0
- package/src/styles/README.md +23 -0
- package/src/styles/index.ts +20 -0
- package/src/styles/layouts/cluster.ts +27 -0
- package/src/styles/layouts/page.ts +22 -0
- package/src/styles/layouts/split.ts +26 -0
- package/src/styles/layouts/stack.ts +21 -0
- package/src/styles/patterns/actionToolbar.ts +8 -0
- package/src/styles/patterns/emptyState.ts +23 -0
- package/src/styles/patterns/infoPanel.ts +22 -0
- package/src/styles/patterns/metricGrid.ts +19 -0
- package/src/styles/patterns/pageHeader.ts +19 -0
- package/src/styles/patterns/resultRegion.ts +7 -0
- package/src/styles/patterns/selectableListDetail.ts +21 -0
- package/src/styles/primitives/feedback.ts +23 -0
- package/src/styles/primitives/fields.ts +76 -0
- package/src/styles/primitives/surfaces.ts +52 -0
- package/src/styles/primitives/typography.ts +42 -0
- package/src/styles/recipes/badge.recipe.ts +54 -0
- package/src/styles/recipes/button.recipe.ts +115 -0
- package/src/styles/recipes/card.recipe.ts +64 -0
- package/src/styles/recipes/dropdown.recipe.ts +40 -0
- package/src/styles/recipes/input.recipe.ts +59 -0
- package/src/styles.ts +1 -0
- package/src/test/setup.ts +1 -0
- package/src/tokens/colors.ts +16 -0
- package/src/tokens/core-colors.ts +53 -0
- package/src/tokens/desktop-colors.ts +37 -0
- package/src/tokens/index.ts +8 -0
- package/src/tokens/motion.ts +6 -0
- package/src/tokens/radius.ts +3 -0
- package/src/tokens/spacing.ts +4 -0
- package/src/tokens/typography.ts +6 -0
- package/src/tokens-core.ts +5 -0
- package/src/tokens-desktop.ts +1 -0
- package/src/tokens.ts +1 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import { UiSkeleton } from "../../components";
|
|
4
|
+
import StoryThemeFrame from "../support/StoryThemeFrame.vue";
|
|
5
|
+
import {
|
|
6
|
+
storyCaptionClass,
|
|
7
|
+
storyGridClass,
|
|
8
|
+
storySectionLabelClass,
|
|
9
|
+
storyStackClass,
|
|
10
|
+
storySurfaceClass,
|
|
11
|
+
storySurfaceWideClass,
|
|
12
|
+
} from "../support/storyStyles";
|
|
13
|
+
import { uiSkeletonStackSource, uiSkeletonVariantsSource } from "../support/sources";
|
|
14
|
+
|
|
15
|
+
const meta = {
|
|
16
|
+
title: "Feedback/UiSkeleton",
|
|
17
|
+
id: "ui-skeleton",
|
|
18
|
+
component: UiSkeleton,
|
|
19
|
+
tags: ["autodocs"],
|
|
20
|
+
parameters: {
|
|
21
|
+
docs: {
|
|
22
|
+
description: {
|
|
23
|
+
component: "Shared skeleton primitives for text, stat and action placeholders.",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
} satisfies Meta<typeof UiSkeleton>;
|
|
28
|
+
|
|
29
|
+
export default meta;
|
|
30
|
+
type Story = StoryObj<typeof meta>;
|
|
31
|
+
|
|
32
|
+
export const Stack: Story = {
|
|
33
|
+
parameters: {
|
|
34
|
+
docs: { source: { code: uiSkeletonStackSource } },
|
|
35
|
+
},
|
|
36
|
+
render: () => ({
|
|
37
|
+
components: { StoryThemeFrame, UiSkeleton },
|
|
38
|
+
setup() {
|
|
39
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
40
|
+
return { previewTheme, storyCaptionClass, storySectionLabelClass, storyStackClass, storySurfaceClass, storySurfaceWideClass };
|
|
41
|
+
},
|
|
42
|
+
template: `
|
|
43
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="stack">
|
|
44
|
+
<div :class="[storySurfaceClass, storySurfaceWideClass]">
|
|
45
|
+
<p :class="storySectionLabelClass">Content stack</p>
|
|
46
|
+
<div :class="storyStackClass">
|
|
47
|
+
<UiSkeleton variant="title" />
|
|
48
|
+
<UiSkeleton variant="text" />
|
|
49
|
+
<UiSkeleton variant="rect" height="120px" />
|
|
50
|
+
</div>
|
|
51
|
+
<p :class="storyCaptionClass">Use the stack composition for page bodies and list sections while data is still loading.</p>
|
|
52
|
+
</div>
|
|
53
|
+
</StoryThemeFrame>
|
|
54
|
+
`,
|
|
55
|
+
}),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const Variants: Story = {
|
|
59
|
+
parameters: {
|
|
60
|
+
docs: { source: { code: uiSkeletonVariantsSource } },
|
|
61
|
+
},
|
|
62
|
+
render: () => ({
|
|
63
|
+
components: { StoryThemeFrame, UiSkeleton },
|
|
64
|
+
setup() {
|
|
65
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
66
|
+
return { previewTheme, storyCaptionClass, storyGridClass, storySectionLabelClass, storySurfaceClass, storySurfaceWideClass };
|
|
67
|
+
},
|
|
68
|
+
template: `
|
|
69
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="variants">
|
|
70
|
+
<div :class="[storySurfaceClass, storySurfaceWideClass]">
|
|
71
|
+
<p :class="storySectionLabelClass">Available shapes</p>
|
|
72
|
+
<div :class="storyGridClass">
|
|
73
|
+
<UiSkeleton variant="title" />
|
|
74
|
+
<UiSkeleton variant="text" />
|
|
75
|
+
<UiSkeleton variant="pill" />
|
|
76
|
+
<UiSkeleton variant="circle" />
|
|
77
|
+
<UiSkeleton variant="stat" />
|
|
78
|
+
<UiSkeleton variant="action" />
|
|
79
|
+
</div>
|
|
80
|
+
<p :class="storyCaptionClass">Keep skeleton shapes close to the final layout so loading does not create reflow surprises.</p>
|
|
81
|
+
</div>
|
|
82
|
+
</StoryThemeFrame>
|
|
83
|
+
`,
|
|
84
|
+
}),
|
|
85
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import { UiCheckbox } from "../../components";
|
|
4
|
+
import StoryThemeFrame from "../support/StoryThemeFrame.vue";
|
|
5
|
+
import { storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceCompactClass } from "../support/storyStyles";
|
|
6
|
+
import {
|
|
7
|
+
uiCheckboxCheckedSource,
|
|
8
|
+
uiCheckboxDisabledSource,
|
|
9
|
+
uiCheckboxUncheckedSource,
|
|
10
|
+
} from "../support/sources";
|
|
11
|
+
|
|
12
|
+
const meta = {
|
|
13
|
+
title: "Forms/UiCheckbox",
|
|
14
|
+
id: "ui-checkbox",
|
|
15
|
+
component: UiCheckbox,
|
|
16
|
+
tags: ["autodocs"],
|
|
17
|
+
args: {
|
|
18
|
+
modelValue: false,
|
|
19
|
+
},
|
|
20
|
+
parameters: {
|
|
21
|
+
docs: {
|
|
22
|
+
description: {
|
|
23
|
+
component: "Checkbox control with shared label, description and invalid states.",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
} satisfies Meta<typeof UiCheckbox>;
|
|
28
|
+
|
|
29
|
+
export default meta;
|
|
30
|
+
type Story = StoryObj<typeof meta>;
|
|
31
|
+
|
|
32
|
+
export const Unchecked: Story = {
|
|
33
|
+
parameters: {
|
|
34
|
+
docs: { source: { code: uiCheckboxUncheckedSource } },
|
|
35
|
+
},
|
|
36
|
+
render: () => ({
|
|
37
|
+
components: { StoryThemeFrame, UiCheckbox },
|
|
38
|
+
setup() {
|
|
39
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
40
|
+
const enabled = ref(false);
|
|
41
|
+
return { enabled, previewTheme, storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceCompactClass };
|
|
42
|
+
},
|
|
43
|
+
template: `
|
|
44
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="unchecked">
|
|
45
|
+
<div :class="[storySurfaceClass, storySurfaceCompactClass]">
|
|
46
|
+
<p :class="storySectionLabelClass">Unchecked</p>
|
|
47
|
+
<UiCheckbox v-model="enabled" label="Enable feature flag" description="Unchecked baseline state." />
|
|
48
|
+
<p :class="storyCaptionClass">Baseline checkbox state with label and supporting description.</p>
|
|
49
|
+
</div>
|
|
50
|
+
</StoryThemeFrame>
|
|
51
|
+
`,
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const Checked: Story = {
|
|
56
|
+
parameters: {
|
|
57
|
+
docs: { source: { code: uiCheckboxCheckedSource } },
|
|
58
|
+
},
|
|
59
|
+
render: () => ({
|
|
60
|
+
components: { StoryThemeFrame, UiCheckbox },
|
|
61
|
+
setup() {
|
|
62
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
63
|
+
const enabled = ref(true);
|
|
64
|
+
return { enabled, previewTheme, storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceCompactClass };
|
|
65
|
+
},
|
|
66
|
+
template: `
|
|
67
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="checked">
|
|
68
|
+
<div :class="[storySurfaceClass, storySurfaceCompactClass]">
|
|
69
|
+
<p :class="storySectionLabelClass">Checked</p>
|
|
70
|
+
<UiCheckbox v-model="enabled" label="Enable feature flag" description="Checked baseline state." />
|
|
71
|
+
<p :class="storyCaptionClass">The checked state keeps the same layout and emphasis as the baseline control.</p>
|
|
72
|
+
</div>
|
|
73
|
+
</StoryThemeFrame>
|
|
74
|
+
`,
|
|
75
|
+
}),
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const Disabled: Story = {
|
|
79
|
+
parameters: {
|
|
80
|
+
docs: { source: { code: uiCheckboxDisabledSource } },
|
|
81
|
+
},
|
|
82
|
+
render: () => ({
|
|
83
|
+
components: { StoryThemeFrame, UiCheckbox },
|
|
84
|
+
setup() {
|
|
85
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
86
|
+
const enabled = ref(true);
|
|
87
|
+
return { enabled, previewTheme, storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceCompactClass };
|
|
88
|
+
},
|
|
89
|
+
template: `
|
|
90
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="disabled">
|
|
91
|
+
<div :class="[storySurfaceClass, storySurfaceCompactClass]">
|
|
92
|
+
<p :class="storySectionLabelClass">Disabled</p>
|
|
93
|
+
<UiCheckbox
|
|
94
|
+
v-model="enabled"
|
|
95
|
+
label="Protected setting"
|
|
96
|
+
description="Disabled state keeps the same layout and copy."
|
|
97
|
+
disabled
|
|
98
|
+
/>
|
|
99
|
+
<p :class="storyCaptionClass">Use disabled controls sparingly and keep the label explicit about why the setting cannot be changed.</p>
|
|
100
|
+
</div>
|
|
101
|
+
</StoryThemeFrame>
|
|
102
|
+
`,
|
|
103
|
+
}),
|
|
104
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import { StatusBadge, UiField, UiSelect } from "../../components";
|
|
4
|
+
import StoryThemeFrame from "../support/StoryThemeFrame.vue";
|
|
5
|
+
import { storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceWideClass } from "../support/storyStyles";
|
|
6
|
+
import { uiFieldMetaSource, uiFieldSource } from "../support/sources";
|
|
7
|
+
|
|
8
|
+
const meta = {
|
|
9
|
+
title: "Forms/UiField",
|
|
10
|
+
id: "ui-field",
|
|
11
|
+
component: UiField,
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
parameters: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component: "Labeling wrapper for form controls that need shared copy and field-level status.",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
} satisfies Meta<typeof UiField>;
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
type Story = StoryObj<typeof meta>;
|
|
24
|
+
|
|
25
|
+
const options = [
|
|
26
|
+
{ label: "Desktop app", value: "desktop" },
|
|
27
|
+
{ label: "Public web", value: "web" },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
export const Basic: Story = {
|
|
31
|
+
parameters: {
|
|
32
|
+
docs: { source: { code: uiFieldSource } },
|
|
33
|
+
},
|
|
34
|
+
render: () => ({
|
|
35
|
+
components: { StoryThemeFrame, UiField, UiSelect },
|
|
36
|
+
setup() {
|
|
37
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
38
|
+
const target = ref("desktop");
|
|
39
|
+
return { options, previewTheme, storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceWideClass, target };
|
|
40
|
+
},
|
|
41
|
+
template: `
|
|
42
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="basic">
|
|
43
|
+
<div :class="[storySurfaceClass, storySurfaceWideClass]">
|
|
44
|
+
<p :class="storySectionLabelClass">Baseline field</p>
|
|
45
|
+
<UiField id="consumer-target-hint" for-id="consumer-target" label="Consumer target" hint="The same component works in desktop and public web.">
|
|
46
|
+
<UiSelect id="consumer-target" v-model="target" :options="options" aria-describedby="consumer-target-hint" />
|
|
47
|
+
</UiField>
|
|
48
|
+
<p :class="storyCaptionClass">UiField handles label, hint and field rhythm so controls stay visually consistent.</p>
|
|
49
|
+
</div>
|
|
50
|
+
</StoryThemeFrame>
|
|
51
|
+
`,
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const WithMeta: Story = {
|
|
56
|
+
parameters: {
|
|
57
|
+
docs: { source: { code: uiFieldMetaSource } },
|
|
58
|
+
},
|
|
59
|
+
render: () => ({
|
|
60
|
+
components: { StatusBadge, StoryThemeFrame, UiField, UiSelect },
|
|
61
|
+
setup() {
|
|
62
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
63
|
+
const target = ref("web");
|
|
64
|
+
return { options, previewTheme, storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceWideClass, target };
|
|
65
|
+
},
|
|
66
|
+
template: `
|
|
67
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="with-meta">
|
|
68
|
+
<div :class="[storySurfaceClass, storySurfaceWideClass]">
|
|
69
|
+
<p :class="storySectionLabelClass">Field metadata</p>
|
|
70
|
+
<UiField
|
|
71
|
+
id="consumer-target-meta-hint"
|
|
72
|
+
for-id="consumer-target-meta"
|
|
73
|
+
eyebrow="Shared system"
|
|
74
|
+
label="Release target"
|
|
75
|
+
hint="Use the meta slot for compact status context."
|
|
76
|
+
>
|
|
77
|
+
<template #meta>
|
|
78
|
+
<StatusBadge tone="info">Required</StatusBadge>
|
|
79
|
+
</template>
|
|
80
|
+
<UiSelect id="consumer-target-meta" v-model="target" :options="options" aria-describedby="consumer-target-meta-hint" />
|
|
81
|
+
</UiField>
|
|
82
|
+
<p :class="storyCaptionClass">The meta slot is useful for compact status or requirement markers without crowding the main label copy.</p>
|
|
83
|
+
</div>
|
|
84
|
+
</StoryThemeFrame>
|
|
85
|
+
`,
|
|
86
|
+
}),
|
|
87
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { defineComponent, onMounted, ref } from "vue";
|
|
3
|
+
import { UiField, UiSelect } from "../../components";
|
|
4
|
+
import StoryThemeFrame from "../support/StoryThemeFrame.vue";
|
|
5
|
+
import { storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceWideClass } from "../support/storyStyles";
|
|
6
|
+
import { uiSelectClosedSource, uiSelectOpenSource, uiSelectSmallSource } from "../support/sources";
|
|
7
|
+
|
|
8
|
+
const options = [
|
|
9
|
+
{ label: "Desktop app", value: "desktop", description: "Product shell and authenticated workflows." },
|
|
10
|
+
{ label: "Public web", value: "web", description: "Marketing site and reusable presentation sections." },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const meta = {
|
|
14
|
+
title: "Forms/UiSelect",
|
|
15
|
+
id: "ui-select",
|
|
16
|
+
component: UiSelect,
|
|
17
|
+
tags: ["autodocs"],
|
|
18
|
+
args: {
|
|
19
|
+
modelValue: "desktop",
|
|
20
|
+
options,
|
|
21
|
+
},
|
|
22
|
+
parameters: {
|
|
23
|
+
docs: {
|
|
24
|
+
description: {
|
|
25
|
+
component: "Shared select control with deterministic open state for docs and visual testing.",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
} satisfies Meta<typeof UiSelect>;
|
|
30
|
+
|
|
31
|
+
export default meta;
|
|
32
|
+
type Story = StoryObj<typeof meta>;
|
|
33
|
+
|
|
34
|
+
const OpenSelectDemo = defineComponent({
|
|
35
|
+
name: "OpenSelectDemo",
|
|
36
|
+
components: { UiField, UiSelect },
|
|
37
|
+
setup() {
|
|
38
|
+
const value = ref("desktop");
|
|
39
|
+
onMounted(() => {
|
|
40
|
+
requestAnimationFrame(() => {
|
|
41
|
+
document.querySelector<HTMLButtonElement>("#docs-select-open")?.click();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return { options, value };
|
|
46
|
+
},
|
|
47
|
+
template: `
|
|
48
|
+
<UiField
|
|
49
|
+
id="docs-select-open-hint"
|
|
50
|
+
for-id="docs-select-open"
|
|
51
|
+
label="Consumer target"
|
|
52
|
+
hint="Open state of the shared select component."
|
|
53
|
+
>
|
|
54
|
+
<UiSelect
|
|
55
|
+
id="docs-select-open"
|
|
56
|
+
v-model="value"
|
|
57
|
+
:options="options"
|
|
58
|
+
aria-describedby="docs-select-open-hint"
|
|
59
|
+
/>
|
|
60
|
+
</UiField>
|
|
61
|
+
`,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export const Closed: Story = {
|
|
65
|
+
parameters: {
|
|
66
|
+
docs: { source: { code: uiSelectClosedSource } },
|
|
67
|
+
},
|
|
68
|
+
render: () => ({
|
|
69
|
+
components: { StoryThemeFrame, UiField, UiSelect },
|
|
70
|
+
setup() {
|
|
71
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
72
|
+
const value = ref("desktop");
|
|
73
|
+
return { options, previewTheme, storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceWideClass, value };
|
|
74
|
+
},
|
|
75
|
+
template: `
|
|
76
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="closed">
|
|
77
|
+
<div :class="[storySurfaceClass, storySurfaceWideClass]">
|
|
78
|
+
<p :class="storySectionLabelClass">Baseline</p>
|
|
79
|
+
<UiField id="consumer-target-hint" for-id="consumer-target" label="Consumer target" hint="The same component works in desktop and public web.">
|
|
80
|
+
<UiSelect id="consumer-target" v-model="value" :options="options" aria-describedby="consumer-target-hint" />
|
|
81
|
+
</UiField>
|
|
82
|
+
<p :class="storyCaptionClass">Closed state keeps label, selected value and icon alignment stable across themes.</p>
|
|
83
|
+
</div>
|
|
84
|
+
</StoryThemeFrame>
|
|
85
|
+
`,
|
|
86
|
+
}),
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const Open: Story = {
|
|
90
|
+
parameters: {
|
|
91
|
+
docs: { source: { code: uiSelectOpenSource } },
|
|
92
|
+
},
|
|
93
|
+
render: () => ({
|
|
94
|
+
components: { OpenSelectDemo, StoryThemeFrame },
|
|
95
|
+
setup() {
|
|
96
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
97
|
+
return { previewTheme, storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceWideClass };
|
|
98
|
+
},
|
|
99
|
+
template: `
|
|
100
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="open">
|
|
101
|
+
<div :class="[storySurfaceClass, storySurfaceWideClass]">
|
|
102
|
+
<p :class="storySectionLabelClass">Open listbox</p>
|
|
103
|
+
<OpenSelectDemo />
|
|
104
|
+
<p :class="storyCaptionClass">The open state is deterministic so it can be documented and captured in visual tests.</p>
|
|
105
|
+
</div>
|
|
106
|
+
</StoryThemeFrame>
|
|
107
|
+
`,
|
|
108
|
+
}),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const Small: Story = {
|
|
112
|
+
parameters: {
|
|
113
|
+
docs: { source: { code: uiSelectSmallSource } },
|
|
114
|
+
},
|
|
115
|
+
render: () => ({
|
|
116
|
+
components: { StoryThemeFrame, UiField, UiSelect },
|
|
117
|
+
setup() {
|
|
118
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
119
|
+
const value = ref("web");
|
|
120
|
+
return { options, previewTheme, storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceWideClass, value };
|
|
121
|
+
},
|
|
122
|
+
template: `
|
|
123
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="small">
|
|
124
|
+
<div :class="[storySurfaceClass, storySurfaceWideClass]">
|
|
125
|
+
<p :class="storySectionLabelClass">Compact control</p>
|
|
126
|
+
<UiField id="consumer-target-small-hint" for-id="consumer-target-small" label="Compact selector" hint="Use the small size in dense toolbars or secondary controls.">
|
|
127
|
+
<UiSelect id="consumer-target-small" v-model="value" size="sm" :options="options" aria-describedby="consumer-target-small-hint" />
|
|
128
|
+
</UiField>
|
|
129
|
+
<p :class="storyCaptionClass">The small variant keeps the same semantics and dropdown behavior while reducing vertical footprint.</p>
|
|
130
|
+
</div>
|
|
131
|
+
</StoryThemeFrame>
|
|
132
|
+
`,
|
|
133
|
+
}),
|
|
134
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import { PageSurface, SectionCard, StatusBadge, UiButton } from "../../components";
|
|
4
|
+
import StoryThemeFrame from "../support/StoryThemeFrame.vue";
|
|
5
|
+
import { storyCaptionClass, storySectionLabelClass, storySurfaceWideClass } from "../support/storyStyles";
|
|
6
|
+
import { pageSurfaceSource } from "../support/sources";
|
|
7
|
+
|
|
8
|
+
const meta = {
|
|
9
|
+
title: "Layout/PageSurface",
|
|
10
|
+
id: "page-surface",
|
|
11
|
+
component: PageSurface,
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
parameters: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component: "Top-level scroll-aware wrapper for page-sized views and workspace surfaces.",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
} satisfies Meta<typeof PageSurface>;
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
type Story = StoryObj<typeof meta>;
|
|
24
|
+
|
|
25
|
+
export const Overview: Story = {
|
|
26
|
+
parameters: {
|
|
27
|
+
docs: { source: { code: pageSurfaceSource } },
|
|
28
|
+
},
|
|
29
|
+
render: () => ({
|
|
30
|
+
components: { PageSurface, SectionCard, StatusBadge, StoryThemeFrame, UiButton },
|
|
31
|
+
setup() {
|
|
32
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
33
|
+
return { previewTheme, storyCaptionClass, storySectionLabelClass, storySurfaceWideClass };
|
|
34
|
+
},
|
|
35
|
+
template: `
|
|
36
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="overview">
|
|
37
|
+
<div :class="storySurfaceWideClass">
|
|
38
|
+
<p :class="storySectionLabelClass">Page wrapper</p>
|
|
39
|
+
<PageSurface>
|
|
40
|
+
<SectionCard title="Release summary" eyebrow="Shared shell" description="Use PageSurface as the main scroll-aware wrapper for top-level screens.">
|
|
41
|
+
<template #actions>
|
|
42
|
+
<StatusBadge tone="info">Desktop + Web</StatusBadge>
|
|
43
|
+
</template>
|
|
44
|
+
<p>PageSurface gives top-level views a predictable outer rhythm and width behavior.</p>
|
|
45
|
+
<UiButton>Primary action</UiButton>
|
|
46
|
+
</SectionCard>
|
|
47
|
+
</PageSurface>
|
|
48
|
+
<p :class="storyCaptionClass">Use PageSurface at the page level, not for nested cards or inline sub-sections.</p>
|
|
49
|
+
</div>
|
|
50
|
+
</StoryThemeFrame>
|
|
51
|
+
`,
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { StatusBadge, SectionCard, UiButton } from "../../components";
|
|
3
|
+
import StoryThemeFrame from "../support/StoryThemeFrame.vue";
|
|
4
|
+
import { ref } from "vue";
|
|
5
|
+
import { storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceWideClass } from "../support/storyStyles";
|
|
6
|
+
import { sectionCardDefaultSource, sectionCardScrollSource } from "../support/sources";
|
|
7
|
+
|
|
8
|
+
const meta = {
|
|
9
|
+
title: "Layout/SectionCard",
|
|
10
|
+
id: "section-card",
|
|
11
|
+
component: SectionCard,
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
args: {
|
|
14
|
+
title: "Section title",
|
|
15
|
+
},
|
|
16
|
+
parameters: {
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component: "Reusable section surface for grouped content with optional actions.",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
} satisfies Meta<typeof SectionCard>;
|
|
24
|
+
|
|
25
|
+
export default meta;
|
|
26
|
+
type Story = StoryObj<typeof meta>;
|
|
27
|
+
|
|
28
|
+
export const Default: Story = {
|
|
29
|
+
parameters: {
|
|
30
|
+
docs: { source: { code: sectionCardDefaultSource } },
|
|
31
|
+
},
|
|
32
|
+
render: () => ({
|
|
33
|
+
components: { SectionCard, StatusBadge, StoryThemeFrame, UiButton },
|
|
34
|
+
setup() {
|
|
35
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
36
|
+
return { previewTheme, storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceWideClass };
|
|
37
|
+
},
|
|
38
|
+
template: `
|
|
39
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="default">
|
|
40
|
+
<div :class="[storySurfaceClass, storySurfaceWideClass]">
|
|
41
|
+
<p :class="storySectionLabelClass">Base surface</p>
|
|
42
|
+
<SectionCard title="AGGC UI Playground" eyebrow="Shared system" description="Visual reference for reusable components and patterns.">
|
|
43
|
+
<template #actions>
|
|
44
|
+
<StatusBadge tone="info">v0.1.0</StatusBadge>
|
|
45
|
+
</template>
|
|
46
|
+
<p>Shared components should render consistently in desktop and public web.</p>
|
|
47
|
+
<UiButton variant="outline">Open docs</UiButton>
|
|
48
|
+
</SectionCard>
|
|
49
|
+
<p :class="storyCaptionClass">Use SectionCard for focused regions with a strong header and optional header actions.</p>
|
|
50
|
+
</div>
|
|
51
|
+
</StoryThemeFrame>
|
|
52
|
+
`,
|
|
53
|
+
}),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const ScrollBody: Story = {
|
|
57
|
+
parameters: {
|
|
58
|
+
docs: { source: { code: sectionCardScrollSource } },
|
|
59
|
+
},
|
|
60
|
+
render: () => ({
|
|
61
|
+
components: { SectionCard, StatusBadge, StoryThemeFrame },
|
|
62
|
+
setup() {
|
|
63
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
64
|
+
return { previewTheme, storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceWideClass };
|
|
65
|
+
},
|
|
66
|
+
template: `
|
|
67
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="scroll-body">
|
|
68
|
+
<div :class="[storySurfaceClass, storySurfaceWideClass]">
|
|
69
|
+
<p :class="storySectionLabelClass">Scrollable body</p>
|
|
70
|
+
<SectionCard title="Changelog" eyebrow="Scrollable region" description="Longer bodies can scroll without breaking the card header." scroll-body>
|
|
71
|
+
<template #actions>
|
|
72
|
+
<StatusBadge tone="neutral">14 entries</StatusBadge>
|
|
73
|
+
</template>
|
|
74
|
+
<p>Release note 1. Shared surfaces keep spacing stable across dense content.</p>
|
|
75
|
+
<p>Release note 2. Shared surfaces keep spacing stable across dense content.</p>
|
|
76
|
+
<p>Release note 3. Shared surfaces keep spacing stable across dense content.</p>
|
|
77
|
+
<p>Release note 4. Shared surfaces keep spacing stable across dense content.</p>
|
|
78
|
+
<p>Release note 5. Shared surfaces keep spacing stable across dense content.</p>
|
|
79
|
+
</SectionCard>
|
|
80
|
+
<p :class="storyCaptionClass">Use scrollBody when long detail lists should stay within a bounded panel.</p>
|
|
81
|
+
</div>
|
|
82
|
+
</StoryThemeFrame>
|
|
83
|
+
`,
|
|
84
|
+
}),
|
|
85
|
+
};
|