@aggc/ui 0.4.1 → 0.5.1
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/package.json +4 -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,145 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import { UiButton } from "../../components";
|
|
4
|
+
import StoryThemeFrame from "../support/StoryThemeFrame.vue";
|
|
5
|
+
import {
|
|
6
|
+
storyCaptionClass,
|
|
7
|
+
storySectionLabelClass,
|
|
8
|
+
storySurfaceClass,
|
|
9
|
+
storySurfaceCompactClass,
|
|
10
|
+
} from "../support/storyStyles";
|
|
11
|
+
import {
|
|
12
|
+
uiButtonLoadingSource,
|
|
13
|
+
uiButtonOutlineSource,
|
|
14
|
+
uiButtonSolidSource,
|
|
15
|
+
uiButtonSubtleSource,
|
|
16
|
+
} from "../support/sources";
|
|
17
|
+
|
|
18
|
+
const meta = {
|
|
19
|
+
title: "Primitives/UiButton",
|
|
20
|
+
id: "ui-button",
|
|
21
|
+
component: UiButton,
|
|
22
|
+
tags: ["autodocs"],
|
|
23
|
+
parameters: {
|
|
24
|
+
docs: {
|
|
25
|
+
description: {
|
|
26
|
+
component: "Action primitive for high-emphasis, secondary and low-emphasis actions.",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
} satisfies Meta<typeof UiButton>;
|
|
31
|
+
|
|
32
|
+
export default meta;
|
|
33
|
+
type Story = StoryObj<typeof meta>;
|
|
34
|
+
|
|
35
|
+
export const Solid: Story = {
|
|
36
|
+
parameters: {
|
|
37
|
+
docs: { source: { code: uiButtonSolidSource } },
|
|
38
|
+
},
|
|
39
|
+
render: () => ({
|
|
40
|
+
components: { StoryThemeFrame, UiButton },
|
|
41
|
+
setup() {
|
|
42
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
43
|
+
return {
|
|
44
|
+
previewTheme,
|
|
45
|
+
storyCaptionClass,
|
|
46
|
+
storySectionLabelClass,
|
|
47
|
+
storySurfaceClass,
|
|
48
|
+
storySurfaceCompactClass,
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
template: `
|
|
52
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="solid">
|
|
53
|
+
<div :class="[storySurfaceClass, storySurfaceCompactClass]">
|
|
54
|
+
<p :class="storySectionLabelClass">Primary</p>
|
|
55
|
+
<UiButton>Primary action</UiButton>
|
|
56
|
+
<p :class="storyCaptionClass">Default high-emphasis action for the most important choice in a surface.</p>
|
|
57
|
+
</div>
|
|
58
|
+
</StoryThemeFrame>
|
|
59
|
+
`,
|
|
60
|
+
}),
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const Outline: Story = {
|
|
64
|
+
parameters: {
|
|
65
|
+
docs: { source: { code: uiButtonOutlineSource } },
|
|
66
|
+
},
|
|
67
|
+
render: () => ({
|
|
68
|
+
components: { StoryThemeFrame, UiButton },
|
|
69
|
+
setup() {
|
|
70
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
71
|
+
return {
|
|
72
|
+
previewTheme,
|
|
73
|
+
storyCaptionClass,
|
|
74
|
+
storySectionLabelClass,
|
|
75
|
+
storySurfaceClass,
|
|
76
|
+
storySurfaceCompactClass,
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
template: `
|
|
80
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="outline">
|
|
81
|
+
<div :class="[storySurfaceClass, storySurfaceCompactClass]">
|
|
82
|
+
<p :class="storySectionLabelClass">Secondary</p>
|
|
83
|
+
<UiButton variant="outline">Secondary action</UiButton>
|
|
84
|
+
<p :class="storyCaptionClass">Use when the action is important but should not dominate the surface.</p>
|
|
85
|
+
</div>
|
|
86
|
+
</StoryThemeFrame>
|
|
87
|
+
`,
|
|
88
|
+
}),
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const Loading: Story = {
|
|
92
|
+
parameters: {
|
|
93
|
+
docs: { source: { code: uiButtonLoadingSource } },
|
|
94
|
+
},
|
|
95
|
+
render: () => ({
|
|
96
|
+
components: { StoryThemeFrame, UiButton },
|
|
97
|
+
setup() {
|
|
98
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
99
|
+
return {
|
|
100
|
+
previewTheme,
|
|
101
|
+
storyCaptionClass,
|
|
102
|
+
storySectionLabelClass,
|
|
103
|
+
storySurfaceClass,
|
|
104
|
+
storySurfaceCompactClass,
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
template: `
|
|
108
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="loading">
|
|
109
|
+
<div :class="[storySurfaceClass, storySurfaceCompactClass]">
|
|
110
|
+
<p :class="storySectionLabelClass">Async state</p>
|
|
111
|
+
<UiButton variant="subtle" loading loading-label="Loading">Async action</UiButton>
|
|
112
|
+
<p :class="storyCaptionClass">The component sets busy state and blocks interaction while work is running.</p>
|
|
113
|
+
</div>
|
|
114
|
+
</StoryThemeFrame>
|
|
115
|
+
`,
|
|
116
|
+
}),
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export const Subtle: Story = {
|
|
120
|
+
parameters: {
|
|
121
|
+
docs: { source: { code: uiButtonSubtleSource } },
|
|
122
|
+
},
|
|
123
|
+
render: () => ({
|
|
124
|
+
components: { StoryThemeFrame, UiButton },
|
|
125
|
+
setup() {
|
|
126
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
127
|
+
return {
|
|
128
|
+
previewTheme,
|
|
129
|
+
storyCaptionClass,
|
|
130
|
+
storySectionLabelClass,
|
|
131
|
+
storySurfaceClass,
|
|
132
|
+
storySurfaceCompactClass,
|
|
133
|
+
};
|
|
134
|
+
},
|
|
135
|
+
template: `
|
|
136
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="subtle">
|
|
137
|
+
<div :class="[storySurfaceClass, storySurfaceCompactClass]">
|
|
138
|
+
<p :class="storySectionLabelClass">Supportive action</p>
|
|
139
|
+
<UiButton variant="subtle">Preview state</UiButton>
|
|
140
|
+
<p :class="storyCaptionClass">Use subtle actions for preview, inspect and other lower-emphasis flows.</p>
|
|
141
|
+
</div>
|
|
142
|
+
</StoryThemeFrame>
|
|
143
|
+
`,
|
|
144
|
+
}),
|
|
145
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import { UiSegmentedControl } from "../../components";
|
|
4
|
+
import StoryThemeFrame from "../support/StoryThemeFrame.vue";
|
|
5
|
+
import { storyCaptionClass, storySectionLabelClass, storySurfaceClass, storySurfaceCompactClass } from "../support/storyStyles";
|
|
6
|
+
import { uiSegmentedControlSource } from "../support/sources";
|
|
7
|
+
|
|
8
|
+
const meta = {
|
|
9
|
+
title: "Primitives/UiSegmentedControl",
|
|
10
|
+
id: "ui-segmented-control",
|
|
11
|
+
component: UiSegmentedControl,
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
args: {
|
|
14
|
+
modelValue: "components",
|
|
15
|
+
options: [
|
|
16
|
+
{ label: "Components", value: "components" },
|
|
17
|
+
{ label: "Tokens", value: "tokens" },
|
|
18
|
+
{ label: "Patterns", value: "patterns" },
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
parameters: {
|
|
22
|
+
docs: {
|
|
23
|
+
description: {
|
|
24
|
+
component: "Compact option switcher for short mutually exclusive views.",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
} satisfies Meta<typeof UiSegmentedControl>;
|
|
29
|
+
|
|
30
|
+
export default meta;
|
|
31
|
+
type Story = StoryObj<typeof meta>;
|
|
32
|
+
|
|
33
|
+
export const Overview: Story = {
|
|
34
|
+
parameters: {
|
|
35
|
+
docs: { source: { code: uiSegmentedControlSource } },
|
|
36
|
+
},
|
|
37
|
+
render: () => ({
|
|
38
|
+
components: { StoryThemeFrame, UiSegmentedControl },
|
|
39
|
+
setup() {
|
|
40
|
+
const previewTheme = ref<"light" | "dark">("dark");
|
|
41
|
+
const value = ref("components");
|
|
42
|
+
const options = [
|
|
43
|
+
{ label: "Components", value: "components" },
|
|
44
|
+
{ label: "Tokens", value: "tokens" },
|
|
45
|
+
{ label: "Patterns", value: "patterns" },
|
|
46
|
+
];
|
|
47
|
+
return {
|
|
48
|
+
options,
|
|
49
|
+
previewTheme,
|
|
50
|
+
storyCaptionClass,
|
|
51
|
+
storySectionLabelClass,
|
|
52
|
+
storySurfaceClass,
|
|
53
|
+
storySurfaceCompactClass,
|
|
54
|
+
value,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
template: `
|
|
58
|
+
<StoryThemeFrame v-model:theme="previewTheme" preview-id="overview">
|
|
59
|
+
<div :class="[storySurfaceClass, storySurfaceCompactClass]">
|
|
60
|
+
<p :class="storySectionLabelClass">Shared navigation</p>
|
|
61
|
+
<UiSegmentedControl v-model="value" :options="options" />
|
|
62
|
+
<p :class="storyCaptionClass">Use for short mutually exclusive views where tabs would be visually heavier than needed.</p>
|
|
63
|
+
</div>
|
|
64
|
+
</StoryThemeFrame>
|
|
65
|
+
`,
|
|
66
|
+
}),
|
|
67
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from "vue";
|
|
3
|
+
import { colorTokens } from "../../tokens/colors";
|
|
4
|
+
import {
|
|
5
|
+
storyPreviewActionsClass,
|
|
6
|
+
storyPreviewHeaderClass,
|
|
7
|
+
storyPreviewRootClass,
|
|
8
|
+
storyPreviewThemeButtonClass,
|
|
9
|
+
storyPreviewThemeGroupClass,
|
|
10
|
+
} from "./storyStyles";
|
|
11
|
+
|
|
12
|
+
type PreviewTheme = "light" | "dark";
|
|
13
|
+
|
|
14
|
+
const props = defineProps<{
|
|
15
|
+
theme: PreviewTheme;
|
|
16
|
+
previewId?: string;
|
|
17
|
+
}>();
|
|
18
|
+
|
|
19
|
+
const emit = defineEmits<{
|
|
20
|
+
"update:theme": [value: PreviewTheme];
|
|
21
|
+
}>();
|
|
22
|
+
|
|
23
|
+
const themeLabel = computed(() => (props.theme === "dark" ? "Dark" : "Light"));
|
|
24
|
+
const themeVars = computed<Record<string, string>>(() => buildThemeVars(props.theme));
|
|
25
|
+
|
|
26
|
+
function setTheme(nextTheme: PreviewTheme) {
|
|
27
|
+
emit("update:theme", nextTheme);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function buildThemeVars(theme: PreviewTheme) {
|
|
31
|
+
const vars: Record<string, string> = {};
|
|
32
|
+
|
|
33
|
+
walkTokens(colorTokens, [], vars, theme);
|
|
34
|
+
|
|
35
|
+
return vars;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function walkTokens(
|
|
39
|
+
node: Record<string, unknown>,
|
|
40
|
+
path: string[],
|
|
41
|
+
vars: Record<string, string>,
|
|
42
|
+
theme: PreviewTheme
|
|
43
|
+
) {
|
|
44
|
+
for (const [key, value] of Object.entries(node)) {
|
|
45
|
+
if (value && typeof value === "object" && "value" in value) {
|
|
46
|
+
const tokenValue = (value as { value: { base: string; _dark?: string } }).value;
|
|
47
|
+
vars[`--colors-${toKebabCase([...path, key].join("-"))}`] =
|
|
48
|
+
theme === "dark" ? (tokenValue._dark ?? tokenValue.base) : tokenValue.base;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (value && typeof value === "object") {
|
|
53
|
+
walkTokens(value as Record<string, unknown>, [...path, key], vars, theme);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function toKebabCase(value: string) {
|
|
59
|
+
return value.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<template>
|
|
65
|
+
<div
|
|
66
|
+
:class="[storyPreviewRootClass, props.theme === 'dark' ? 'dark' : '']"
|
|
67
|
+
:data-story-preview-root="props.previewId ?? ''"
|
|
68
|
+
:data-theme="props.theme"
|
|
69
|
+
:style="themeVars"
|
|
70
|
+
>
|
|
71
|
+
<div :class="storyPreviewHeaderClass">
|
|
72
|
+
<div :class="storyPreviewActionsClass">
|
|
73
|
+
<span>Preview theme</span>
|
|
74
|
+
<strong>{{ themeLabel }}</strong>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div :class="storyPreviewThemeGroupClass" role="group" aria-label="Preview theme">
|
|
78
|
+
<button
|
|
79
|
+
type="button"
|
|
80
|
+
:class="storyPreviewThemeButtonClass({ active: props.theme === 'dark' })"
|
|
81
|
+
data-testid="story-theme-dark"
|
|
82
|
+
:aria-pressed="props.theme === 'dark'"
|
|
83
|
+
@click="setTheme('dark')"
|
|
84
|
+
>
|
|
85
|
+
Dark
|
|
86
|
+
</button>
|
|
87
|
+
<button
|
|
88
|
+
type="button"
|
|
89
|
+
:class="storyPreviewThemeButtonClass({ active: props.theme === 'light' })"
|
|
90
|
+
data-testid="story-theme-light"
|
|
91
|
+
:aria-pressed="props.theme === 'light'"
|
|
92
|
+
@click="setTheme('light')"
|
|
93
|
+
>
|
|
94
|
+
Light
|
|
95
|
+
</button>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<slot />
|
|
100
|
+
</div>
|
|
101
|
+
</template>
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
export const uiButtonSolidSource = `<script setup lang="ts">
|
|
2
|
+
import { UiButton } from "@aggc/ui";
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<template>
|
|
6
|
+
<UiButton>Primary action</UiButton>
|
|
7
|
+
</template>`;
|
|
8
|
+
|
|
9
|
+
export const uiButtonOutlineSource = `<script setup lang="ts">
|
|
10
|
+
import { UiButton } from "@aggc/ui";
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<UiButton variant="outline">Secondary action</UiButton>
|
|
15
|
+
</template>`;
|
|
16
|
+
|
|
17
|
+
export const uiButtonLoadingSource = `<script setup lang="ts">
|
|
18
|
+
import { UiButton } from "@aggc/ui";
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<UiButton variant="subtle" loading loading-label="Loading">
|
|
23
|
+
Async action
|
|
24
|
+
</UiButton>
|
|
25
|
+
</template>`;
|
|
26
|
+
|
|
27
|
+
export const uiButtonSubtleSource = `<script setup lang="ts">
|
|
28
|
+
import { UiButton } from "@aggc/ui";
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<UiButton variant="subtle">
|
|
33
|
+
Preview state
|
|
34
|
+
</UiButton>
|
|
35
|
+
</template>`;
|
|
36
|
+
|
|
37
|
+
export const uiCheckboxUncheckedSource = `<script setup lang="ts">
|
|
38
|
+
import { ref } from "vue";
|
|
39
|
+
import { UiCheckbox } from "@aggc/ui";
|
|
40
|
+
|
|
41
|
+
const enabled = ref(false);
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<template>
|
|
45
|
+
<UiCheckbox
|
|
46
|
+
v-model="enabled"
|
|
47
|
+
label="Enable feature flag"
|
|
48
|
+
description="Unchecked baseline state."
|
|
49
|
+
/>
|
|
50
|
+
</template>`;
|
|
51
|
+
|
|
52
|
+
export const uiCheckboxCheckedSource = `<script setup lang="ts">
|
|
53
|
+
import { ref } from "vue";
|
|
54
|
+
import { UiCheckbox } from "@aggc/ui";
|
|
55
|
+
|
|
56
|
+
const enabled = ref(true);
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<template>
|
|
60
|
+
<UiCheckbox
|
|
61
|
+
v-model="enabled"
|
|
62
|
+
label="Enable feature flag"
|
|
63
|
+
description="Checked baseline state."
|
|
64
|
+
/>
|
|
65
|
+
</template>`;
|
|
66
|
+
|
|
67
|
+
export const uiCheckboxDisabledSource = `<script setup lang="ts">
|
|
68
|
+
import { ref } from "vue";
|
|
69
|
+
import { UiCheckbox } from "@aggc/ui";
|
|
70
|
+
|
|
71
|
+
const enabled = ref(true);
|
|
72
|
+
</script>
|
|
73
|
+
|
|
74
|
+
<template>
|
|
75
|
+
<UiCheckbox
|
|
76
|
+
v-model="enabled"
|
|
77
|
+
label="Protected setting"
|
|
78
|
+
description="Disabled state keeps the same layout and copy."
|
|
79
|
+
disabled
|
|
80
|
+
/>
|
|
81
|
+
</template>`;
|
|
82
|
+
|
|
83
|
+
export const uiFieldSource = `<script setup lang="ts">
|
|
84
|
+
import { ref } from "vue";
|
|
85
|
+
import { UiField, UiSelect } from "@aggc/ui";
|
|
86
|
+
|
|
87
|
+
const target = ref("desktop");
|
|
88
|
+
const options = [
|
|
89
|
+
{ label: "Desktop app", value: "desktop" },
|
|
90
|
+
{ label: "Public web", value: "web" },
|
|
91
|
+
];
|
|
92
|
+
</script>
|
|
93
|
+
|
|
94
|
+
<template>
|
|
95
|
+
<UiField
|
|
96
|
+
id="consumer-target-hint"
|
|
97
|
+
for-id="consumer-target"
|
|
98
|
+
label="Consumer target"
|
|
99
|
+
hint="The same component works in desktop and public web."
|
|
100
|
+
>
|
|
101
|
+
<UiSelect
|
|
102
|
+
id="consumer-target"
|
|
103
|
+
v-model="target"
|
|
104
|
+
:options="options"
|
|
105
|
+
aria-describedby="consumer-target-hint"
|
|
106
|
+
/>
|
|
107
|
+
</UiField>
|
|
108
|
+
</template>`;
|
|
109
|
+
|
|
110
|
+
export const uiFieldMetaSource = `<script setup lang="ts">
|
|
111
|
+
import { ref } from "vue";
|
|
112
|
+
import { StatusBadge, UiField, UiSelect } from "@aggc/ui";
|
|
113
|
+
|
|
114
|
+
const target = ref("web");
|
|
115
|
+
const options = [
|
|
116
|
+
{ label: "Desktop app", value: "desktop" },
|
|
117
|
+
{ label: "Public web", value: "web" },
|
|
118
|
+
];
|
|
119
|
+
</script>
|
|
120
|
+
|
|
121
|
+
<template>
|
|
122
|
+
<UiField
|
|
123
|
+
id="consumer-target-meta-hint"
|
|
124
|
+
for-id="consumer-target-meta"
|
|
125
|
+
eyebrow="Shared system"
|
|
126
|
+
label="Release target"
|
|
127
|
+
hint="Use the meta slot for compact status context."
|
|
128
|
+
>
|
|
129
|
+
<template #meta>
|
|
130
|
+
<StatusBadge tone="info">Required</StatusBadge>
|
|
131
|
+
</template>
|
|
132
|
+
|
|
133
|
+
<UiSelect
|
|
134
|
+
id="consumer-target-meta"
|
|
135
|
+
v-model="target"
|
|
136
|
+
:options="options"
|
|
137
|
+
aria-describedby="consumer-target-meta-hint"
|
|
138
|
+
/>
|
|
139
|
+
</UiField>
|
|
140
|
+
</template>`;
|
|
141
|
+
|
|
142
|
+
export const uiSelectClosedSource = `<script setup lang="ts">
|
|
143
|
+
import { ref } from "vue";
|
|
144
|
+
import { UiField, UiSelect } from "@aggc/ui";
|
|
145
|
+
|
|
146
|
+
const target = ref("desktop");
|
|
147
|
+
const options = [
|
|
148
|
+
{ label: "Desktop app", value: "desktop", description: "Product shell and authenticated workflows." },
|
|
149
|
+
{ label: "Public web", value: "web", description: "Marketing site and reusable presentation sections." },
|
|
150
|
+
];
|
|
151
|
+
</script>
|
|
152
|
+
|
|
153
|
+
<template>
|
|
154
|
+
<UiField
|
|
155
|
+
id="consumer-target-hint"
|
|
156
|
+
for-id="consumer-target"
|
|
157
|
+
label="Consumer target"
|
|
158
|
+
hint="The same component works in desktop and public web."
|
|
159
|
+
>
|
|
160
|
+
<UiSelect
|
|
161
|
+
id="consumer-target"
|
|
162
|
+
v-model="target"
|
|
163
|
+
:options="options"
|
|
164
|
+
aria-describedby="consumer-target-hint"
|
|
165
|
+
/>
|
|
166
|
+
</UiField>
|
|
167
|
+
</template>`;
|
|
168
|
+
|
|
169
|
+
export const uiSelectOpenSource = `<script setup lang="ts">
|
|
170
|
+
import { ref } from "vue";
|
|
171
|
+
import { UiField, UiSelect } from "@aggc/ui";
|
|
172
|
+
|
|
173
|
+
const target = ref("desktop");
|
|
174
|
+
const options = [
|
|
175
|
+
{ label: "Desktop app", value: "desktop", description: "Product shell and authenticated workflows." },
|
|
176
|
+
{ label: "Public web", value: "web", description: "Marketing site and reusable presentation sections." },
|
|
177
|
+
];
|
|
178
|
+
</script>
|
|
179
|
+
|
|
180
|
+
<template>
|
|
181
|
+
<UiField
|
|
182
|
+
id="consumer-target-open-hint"
|
|
183
|
+
for-id="consumer-target-open"
|
|
184
|
+
label="Consumer target"
|
|
185
|
+
hint="The same component works in desktop and public web."
|
|
186
|
+
>
|
|
187
|
+
<UiSelect
|
|
188
|
+
id="consumer-target-open"
|
|
189
|
+
v-model="target"
|
|
190
|
+
:options="options"
|
|
191
|
+
aria-describedby="consumer-target-open-hint"
|
|
192
|
+
/>
|
|
193
|
+
</UiField>
|
|
194
|
+
</template>`;
|
|
195
|
+
|
|
196
|
+
export const uiSelectSmallSource = `<script setup lang="ts">
|
|
197
|
+
import { ref } from "vue";
|
|
198
|
+
import { UiField, UiSelect } from "@aggc/ui";
|
|
199
|
+
|
|
200
|
+
const target = ref("web");
|
|
201
|
+
const options = [
|
|
202
|
+
{ label: "Desktop app", value: "desktop" },
|
|
203
|
+
{ label: "Public web", value: "web" },
|
|
204
|
+
];
|
|
205
|
+
</script>
|
|
206
|
+
|
|
207
|
+
<template>
|
|
208
|
+
<UiField
|
|
209
|
+
id="consumer-target-small-hint"
|
|
210
|
+
for-id="consumer-target-small"
|
|
211
|
+
label="Compact selector"
|
|
212
|
+
hint="Use the small size in dense toolbars or secondary controls."
|
|
213
|
+
>
|
|
214
|
+
<UiSelect
|
|
215
|
+
id="consumer-target-small"
|
|
216
|
+
v-model="target"
|
|
217
|
+
size="sm"
|
|
218
|
+
:options="options"
|
|
219
|
+
aria-describedby="consumer-target-small-hint"
|
|
220
|
+
/>
|
|
221
|
+
</UiField>
|
|
222
|
+
</template>`;
|
|
223
|
+
|
|
224
|
+
export const statusBadgeTonesSource = `<script setup lang="ts">
|
|
225
|
+
import { StatusBadge } from "@aggc/ui";
|
|
226
|
+
</script>
|
|
227
|
+
|
|
228
|
+
<template>
|
|
229
|
+
<StatusBadge tone="success">Ready</StatusBadge>
|
|
230
|
+
<StatusBadge tone="warning">Needs review</StatusBadge>
|
|
231
|
+
<StatusBadge tone="info">Preview</StatusBadge>
|
|
232
|
+
<StatusBadge tone="neutral">Draft</StatusBadge>
|
|
233
|
+
</template>`;
|
|
234
|
+
|
|
235
|
+
export const uiLoadingStateSource = `<script setup lang="ts">
|
|
236
|
+
import { UiLoadingState } from "@aggc/ui";
|
|
237
|
+
</script>
|
|
238
|
+
|
|
239
|
+
<template>
|
|
240
|
+
<UiLoadingState
|
|
241
|
+
title="Preparing release artifacts"
|
|
242
|
+
description="Generating CSS, declarations and export map."
|
|
243
|
+
/>
|
|
244
|
+
</template>`;
|
|
245
|
+
|
|
246
|
+
export const uiSkeletonStackSource = `<script setup lang="ts">
|
|
247
|
+
import { UiSkeleton } from "@aggc/ui";
|
|
248
|
+
</script>
|
|
249
|
+
|
|
250
|
+
<template>
|
|
251
|
+
<UiSkeleton variant="title" />
|
|
252
|
+
<UiSkeleton variant="text" />
|
|
253
|
+
<UiSkeleton variant="rect" height="120px" />
|
|
254
|
+
</template>`;
|
|
255
|
+
|
|
256
|
+
export const uiSkeletonVariantsSource = `<script setup lang="ts">
|
|
257
|
+
import { UiSkeleton } from "@aggc/ui";
|
|
258
|
+
</script>
|
|
259
|
+
|
|
260
|
+
<template>
|
|
261
|
+
<UiSkeleton variant="title" />
|
|
262
|
+
<UiSkeleton variant="text" />
|
|
263
|
+
<UiSkeleton variant="pill" />
|
|
264
|
+
<UiSkeleton variant="circle" />
|
|
265
|
+
<UiSkeleton variant="stat" />
|
|
266
|
+
<UiSkeleton variant="action" />
|
|
267
|
+
</template>`;
|
|
268
|
+
|
|
269
|
+
export const resultPanelSuccessSource = `<script setup lang="ts">
|
|
270
|
+
import { ResultPanel } from "@aggc/ui";
|
|
271
|
+
</script>
|
|
272
|
+
|
|
273
|
+
<template>
|
|
274
|
+
<ResultPanel
|
|
275
|
+
ok
|
|
276
|
+
summary="Package validation passed"
|
|
277
|
+
:messages="['Typecheck passed', 'Tests passed', 'Build passed']"
|
|
278
|
+
/>
|
|
279
|
+
</template>`;
|
|
280
|
+
|
|
281
|
+
export const resultPanelFailureSource = `<script setup lang="ts">
|
|
282
|
+
import { ResultPanel } from "@aggc/ui";
|
|
283
|
+
</script>
|
|
284
|
+
|
|
285
|
+
<template>
|
|
286
|
+
<ResultPanel
|
|
287
|
+
:ok="false"
|
|
288
|
+
summary="Package validation failed"
|
|
289
|
+
:warnings="['One component needs contrast review']"
|
|
290
|
+
:errors="['Visual regression diff detected']"
|
|
291
|
+
/>
|
|
292
|
+
</template>`;
|
|
293
|
+
|
|
294
|
+
export const sectionCardDefaultSource = `<script setup lang="ts">
|
|
295
|
+
import { SectionCard, StatusBadge, UiButton } from "@aggc/ui";
|
|
296
|
+
</script>
|
|
297
|
+
|
|
298
|
+
<template>
|
|
299
|
+
<SectionCard
|
|
300
|
+
title="AGGC UI Playground"
|
|
301
|
+
eyebrow="Shared system"
|
|
302
|
+
description="Visual reference for reusable components and patterns."
|
|
303
|
+
>
|
|
304
|
+
<template #actions>
|
|
305
|
+
<StatusBadge tone="info">v0.1.0</StatusBadge>
|
|
306
|
+
</template>
|
|
307
|
+
|
|
308
|
+
<p>Shared components should render consistently in desktop and public web.</p>
|
|
309
|
+
|
|
310
|
+
<UiButton variant="outline">Open docs</UiButton>
|
|
311
|
+
</SectionCard>
|
|
312
|
+
</template>`;
|
|
313
|
+
|
|
314
|
+
export const sectionCardScrollSource = `<script setup lang="ts">
|
|
315
|
+
import { SectionCard, StatusBadge } from "@aggc/ui";
|
|
316
|
+
</script>
|
|
317
|
+
|
|
318
|
+
<template>
|
|
319
|
+
<SectionCard
|
|
320
|
+
title="Changelog"
|
|
321
|
+
eyebrow="Scrollable region"
|
|
322
|
+
description="Longer bodies can scroll without breaking the card header."
|
|
323
|
+
scroll-body
|
|
324
|
+
>
|
|
325
|
+
<template #actions>
|
|
326
|
+
<StatusBadge tone="neutral">14 entries</StatusBadge>
|
|
327
|
+
</template>
|
|
328
|
+
|
|
329
|
+
<p>Release note 1. Shared surfaces keep spacing stable across dense content.</p>
|
|
330
|
+
<p>Release note 2. Shared surfaces keep spacing stable across dense content.</p>
|
|
331
|
+
<p>Release note 3. Shared surfaces keep spacing stable across dense content.</p>
|
|
332
|
+
</SectionCard>
|
|
333
|
+
</template>`;
|
|
334
|
+
|
|
335
|
+
export const uiSegmentedControlSource = `<script setup lang="ts">
|
|
336
|
+
import { ref } from "vue";
|
|
337
|
+
import { UiSegmentedControl } from "@aggc/ui";
|
|
338
|
+
|
|
339
|
+
const view = ref("components");
|
|
340
|
+
const options = [
|
|
341
|
+
{ label: "Components", value: "components" },
|
|
342
|
+
{ label: "Tokens", value: "tokens" },
|
|
343
|
+
{ label: "Patterns", value: "patterns" },
|
|
344
|
+
];
|
|
345
|
+
</script>
|
|
346
|
+
|
|
347
|
+
<template>
|
|
348
|
+
<UiSegmentedControl
|
|
349
|
+
v-model="view"
|
|
350
|
+
:options="options"
|
|
351
|
+
/>
|
|
352
|
+
</template>`;
|
|
353
|
+
|
|
354
|
+
export const pageSurfaceSource = `<script setup lang="ts">
|
|
355
|
+
import { PageSurface, SectionCard, StatusBadge, UiButton } from "@aggc/ui";
|
|
356
|
+
</script>
|
|
357
|
+
|
|
358
|
+
<template>
|
|
359
|
+
<PageSurface>
|
|
360
|
+
<SectionCard
|
|
361
|
+
title="Release summary"
|
|
362
|
+
eyebrow="Shared shell"
|
|
363
|
+
description="Use PageSurface as the main scroll-aware wrapper for top-level screens."
|
|
364
|
+
>
|
|
365
|
+
<template #actions>
|
|
366
|
+
<StatusBadge tone="info">Desktop + Web</StatusBadge>
|
|
367
|
+
</template>
|
|
368
|
+
|
|
369
|
+
<p>PageSurface gives top-level views a predictable outer rhythm and width behavior.</p>
|
|
370
|
+
|
|
371
|
+
<UiButton>Primary action</UiButton>
|
|
372
|
+
</SectionCard>
|
|
373
|
+
</PageSurface>
|
|
374
|
+
</template>`;
|