@aggc/ui 0.4.1 → 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.
Files changed (88) hide show
  1. package/README.md +19 -0
  2. package/package.json +3 -2
  3. package/src/components/PageSurface.styles.ts +3 -0
  4. package/src/components/PageSurface.vue +9 -0
  5. package/src/components/ResultPanel.styles.ts +108 -0
  6. package/src/components/ResultPanel.test.ts +22 -0
  7. package/src/components/ResultPanel.vue +70 -0
  8. package/src/components/SectionCard.styles.ts +65 -0
  9. package/src/components/SectionCard.test.ts +22 -0
  10. package/src/components/SectionCard.vue +51 -0
  11. package/src/components/StatusBadge.styles.ts +49 -0
  12. package/src/components/StatusBadge.test.ts +18 -0
  13. package/src/components/StatusBadge.vue +18 -0
  14. package/src/components/UiButton.styles.ts +29 -0
  15. package/src/components/UiButton.test.ts +21 -0
  16. package/src/components/UiButton.vue +46 -0
  17. package/src/components/UiCheckbox.styles.ts +118 -0
  18. package/src/components/UiCheckbox.test.ts +18 -0
  19. package/src/components/UiCheckbox.vue +72 -0
  20. package/src/components/UiField.styles.ts +35 -0
  21. package/src/components/UiField.test.ts +22 -0
  22. package/src/components/UiField.vue +36 -0
  23. package/src/components/UiLoadingState.styles.ts +36 -0
  24. package/src/components/UiLoadingState.vue +34 -0
  25. package/src/components/UiSegmentedControl.styles.ts +49 -0
  26. package/src/components/UiSegmentedControl.vue +30 -0
  27. package/src/components/UiSelect.styles.ts +214 -0
  28. package/src/components/UiSelect.test.ts +49 -0
  29. package/src/components/UiSelect.vue +256 -0
  30. package/src/components/UiSkeleton.styles.ts +93 -0
  31. package/src/components/UiSkeleton.vue +48 -0
  32. package/src/components/index.ts +11 -0
  33. package/src/components.ts +1 -0
  34. package/src/css/base.css +62 -0
  35. package/src/css/fonts.css +6 -0
  36. package/src/css/index.css +2 -0
  37. package/src/css/storybook.css +15 -0
  38. package/src/env.d.ts +1 -0
  39. package/src/index.ts +3 -0
  40. package/src/stories/feedback/ResultPanel.stories.ts +76 -0
  41. package/src/stories/feedback/StatusBadge.stories.ts +50 -0
  42. package/src/stories/feedback/UiLoadingState.stories.ts +52 -0
  43. package/src/stories/feedback/UiSkeleton.stories.ts +85 -0
  44. package/src/stories/forms/UiCheckbox.stories.ts +104 -0
  45. package/src/stories/forms/UiField.stories.ts +87 -0
  46. package/src/stories/forms/UiSelect.stories.ts +134 -0
  47. package/src/stories/layout/PageSurface.stories.ts +53 -0
  48. package/src/stories/layout/SectionCard.stories.ts +85 -0
  49. package/src/stories/primitives/UiButton.stories.ts +145 -0
  50. package/src/stories/primitives/UiSegmentedControl.stories.ts +67 -0
  51. package/src/stories/support/StoryThemeFrame.vue +101 -0
  52. package/src/stories/support/sources.ts +374 -0
  53. package/src/stories/support/storyStyles.ts +150 -0
  54. package/src/styles/README.md +23 -0
  55. package/src/styles/index.ts +20 -0
  56. package/src/styles/layouts/cluster.ts +27 -0
  57. package/src/styles/layouts/page.ts +22 -0
  58. package/src/styles/layouts/split.ts +26 -0
  59. package/src/styles/layouts/stack.ts +21 -0
  60. package/src/styles/patterns/actionToolbar.ts +8 -0
  61. package/src/styles/patterns/emptyState.ts +23 -0
  62. package/src/styles/patterns/infoPanel.ts +22 -0
  63. package/src/styles/patterns/metricGrid.ts +19 -0
  64. package/src/styles/patterns/pageHeader.ts +19 -0
  65. package/src/styles/patterns/resultRegion.ts +7 -0
  66. package/src/styles/patterns/selectableListDetail.ts +21 -0
  67. package/src/styles/primitives/feedback.ts +23 -0
  68. package/src/styles/primitives/fields.ts +76 -0
  69. package/src/styles/primitives/surfaces.ts +52 -0
  70. package/src/styles/primitives/typography.ts +42 -0
  71. package/src/styles/recipes/badge.recipe.ts +54 -0
  72. package/src/styles/recipes/button.recipe.ts +115 -0
  73. package/src/styles/recipes/card.recipe.ts +64 -0
  74. package/src/styles/recipes/dropdown.recipe.ts +40 -0
  75. package/src/styles/recipes/input.recipe.ts +59 -0
  76. package/src/styles.ts +1 -0
  77. package/src/test/setup.ts +1 -0
  78. package/src/tokens/colors.ts +16 -0
  79. package/src/tokens/core-colors.ts +53 -0
  80. package/src/tokens/desktop-colors.ts +37 -0
  81. package/src/tokens/index.ts +8 -0
  82. package/src/tokens/motion.ts +6 -0
  83. package/src/tokens/radius.ts +3 -0
  84. package/src/tokens/spacing.ts +4 -0
  85. package/src/tokens/typography.ts +6 -0
  86. package/src/tokens-core.ts +5 -0
  87. package/src/tokens-desktop.ts +1 -0
  88. 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>`;