picocrank 1.25.1 → 1.26.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 (44) hide show
  1. package/eslint.config.js +68 -0
  2. package/package.json +13 -3
  3. package/router.js +74 -0
  4. package/styles/dark-theme.css +21 -9
  5. package/styles/picocrank-extensions.css +131 -2
  6. package/supplemental-themes/catppuccin-latte-frappe/theme.css +12 -22
  7. package/supplemental-themes/dracula-alucard/theme.css +12 -22
  8. package/supplemental-themes/gruvbox-dark-light/theme.css +12 -22
  9. package/supplemental-themes/waffles/theme.css +2 -12
  10. package/vue/components/Breadcrumbs.vue +192 -45
  11. package/vue/components/Calendar.vue +93 -180
  12. package/vue/components/DangerZone.vue +186 -0
  13. package/vue/components/Header.vue +22 -6
  14. package/vue/components/Login.vue +6 -7
  15. package/vue/components/NavigationGrid.vue +26 -204
  16. package/vue/components/NotificationBlock.vue +120 -0
  17. package/vue/components/NotificationPopup.vue +44 -41
  18. package/vue/components/QuickSearch.vue +21 -47
  19. package/vue/components/RadioGroup.vue +4 -4
  20. package/vue/components/ReadOnlyTextArea.vue +1 -1
  21. package/vue/components/SidebarNavLink.vue +3 -3
  22. package/vue/components/Table.vue +109 -81
  23. package/vue/components/TableColumnFilterPopover.vue +7 -17
  24. package/vue/components/TableColumnOptionsPopover.vue +22 -27
  25. package/vue/components/Tabs.vue +366 -82
  26. package/vue/components/TopBar.vue +2 -2
  27. package/vue/composables/tableColumnPriorities.js +33 -0
  28. package/vue/composables/tableFilters.js +1 -1
  29. package/vue/data/navSectionHubs.js +196 -0
  30. package/vue/data/routeBreadcrumbs.js +90 -0
  31. package/vue/examples/Admin.vue +12 -12
  32. package/vue/examples/App.vue +27 -36
  33. package/vue/examples/CalendarExample.vue +32 -22
  34. package/vue/examples/ExampleHeaderThemeSwitcher.vue +1 -1
  35. package/vue/examples/Login.vue +0 -3
  36. package/vue/examples/LoginExample.vue +2 -14
  37. package/vue/examples/NavSectionHub.vue +36 -0
  38. package/vue/examples/PageStructure.vue +6 -3
  39. package/vue/examples/StatusExample.vue +248 -129
  40. package/vue/examples/TableExample.vue +68 -67
  41. package/vue/examples/TabsExample.vue +200 -255
  42. package/vue/examples/ThemePreview.vue +21 -23
  43. package/vue/examples/ViewItem.vue +32 -5
  44. package/vue/examples/Welcome.vue +3 -112
@@ -1,145 +1,216 @@
1
1
  <template>
2
- <Section title="Tabs Example" subtitle="A flexible tabbed control component with support for multiple tab panes">
2
+ <Section
3
+ title="Horizontal Tabs"
4
+ subtitle="A flexible tabbed control component with support for multiple tab panes"
5
+ :padding="horizontalTabsSectionPadding"
6
+ >
3
7
  <template #toolbar>
4
- <button @click="addRandomTab" class="good">Add Tab</button>
5
- <button @click="removeLastTab" class="bad" :disabled="tabs.length <= 1">Remove Tab</button>
8
+ <label class="tabs-padding-toggle">
9
+ <input v-model="horizontalTabsSectionPadding" type="checkbox" />
10
+ Section padding
11
+ </label>
12
+ <label class="tabs-padding-toggle">
13
+ <input v-model="horizontalTabsPadding" type="checkbox" />
14
+ Tab padding
15
+ </label>
6
16
  </template>
7
17
 
8
- <div class="tabs-example-container">
9
- <h3>Basic Tabs</h3>
10
- <Tabs :tabs="basicTabs" @tab-change="onTabChange">
11
- <template #tab-0>
12
- <div class="tab-content">
13
- <h4>Overview</h4>
14
- <p>
15
- This is the Overview tab. It contains general information about the current topic.
16
- You can place any content here, including forms, tables, images, or other components.
17
- </p>
18
- <ul>
19
- <li>First item in the overview</li>
20
- <li>Second item with more details</li>
21
- <li>Third item explaining features</li>
22
- </ul>
23
- </div>
24
- </template>
25
- <template #tab-1>
26
- <div class="tab-content">
27
- <h4>Details</h4>
28
- <p>
29
- The Details tab provides in-depth information. This section can be used to display
30
- comprehensive data, specifications, or detailed descriptions.
31
- </p>
32
- <div class="details-grid">
33
- <div class="detail-item">
34
- <strong>Property 1:</strong> Value 1
35
- </div>
36
- <div class="detail-item">
37
- <strong>Property 2:</strong> Value 2
38
- </div>
39
- <div class="detail-item">
40
- <strong>Property 3:</strong> Value 3
41
- </div>
42
- <div class="detail-item">
43
- <strong>Property 4:</strong> Value 4
44
- </div>
45
- </div>
46
- </div>
47
- </template>
48
- <template #tab-2>
49
- <div class="tab-content">
50
- <h4>Settings</h4>
51
- <p>Configure your preferences and settings in this tab.</p>
52
- <form class="settings-form">
53
- <div class="form-group">
54
- <label for="setting1">Setting 1:</label>
55
- <input id="setting1" type="text" v-model="settings.setting1" placeholder="Enter value" />
56
- </div>
57
- <div class="form-group">
58
- <label for="setting2">Setting 2:</label>
59
- <select id="setting2" v-model="settings.setting2">
60
- <option value="option1">Option 1</option>
61
- <option value="option2">Option 2</option>
62
- <option value="option3">Option 3</option>
63
- </select>
64
- </div>
65
- <div class="form-group">
66
- <label>
67
- <input type="checkbox" v-model="settings.enabled" />
68
- Enable feature
69
- </label>
70
- </div>
71
- <button type="button" class="good" @click="saveSettings">Save Settings</button>
72
- </form>
73
- </div>
74
- </template>
75
- </Tabs>
18
+ <Tabs
19
+ :tabs="basicTabs"
20
+ :padding="horizontalTabsPadding"
21
+ @tab-change="onTabChange"
22
+ >
23
+ <template #tab-0>
24
+ <div class="tab-content">
25
+ <h4>Overview</h4>
26
+ <p>
27
+ This is the Overview tab. It contains general information about the current topic.
28
+ You can place any content here, including forms, tables, images, or other components.
29
+ </p>
30
+ <ul>
31
+ <li>First item in the overview</li>
32
+ <li>Second item with more details</li>
33
+ <li>Third item explaining features</li>
34
+ </ul>
35
+ </div>
36
+ </template>
37
+ <template #tab-1>
38
+ <div class="tab-content">
39
+ <h4>Details</h4>
40
+ <p>
41
+ The Details tab provides in-depth information. This section can be used to display
42
+ comprehensive data, specifications, or detailed descriptions.
43
+ </p>
44
+ <dl>
45
+ <dt>Property 1</dt>
46
+ <dd>Value 1</dd>
47
+
48
+ <dt>Property 2</dt>
49
+ <dd>Value 2</dd>
50
+
51
+ <dt>Property 3</dt>
52
+ <dd>Value 3</dd>
53
+
54
+ <dt>Property 4</dt>
55
+ <dd>Value 4</dd>
56
+ </dl>
57
+ </div>
58
+ </template>
59
+ <template #tab-2>
60
+ <div class="tab-content">
61
+ <h4>Settings</h4>
62
+ <p>Configure your preferences and settings in this tab.</p>
63
+ <FormLayout @submit.prevent="saveSettings">
64
+ <FormField label="Setting 1" for="tabs-setting1">
65
+ <input
66
+ id="tabs-setting1"
67
+ v-model="settings.setting1"
68
+ type="text"
69
+ placeholder="Enter value"
70
+ />
71
+ </FormField>
72
+
73
+ <FormField label="Setting 2" for="tabs-setting2">
74
+ <select id="tabs-setting2" v-model="settings.setting2">
75
+ <option value="option1">Option 1</option>
76
+ <option value="option2">Option 2</option>
77
+ <option value="option3">Option 3</option>
78
+ </select>
79
+ </FormField>
80
+
81
+ <FormField label="Enable feature" for="tabs-setting-enabled">
82
+ <input
83
+ id="tabs-setting-enabled"
84
+ v-model="settings.enabled"
85
+ type="checkbox"
86
+ />
87
+ </FormField>
88
+
89
+ <template #actions>
90
+ <button type="submit" class="good">Save Settings</button>
91
+ </template>
92
+ </FormLayout>
93
+ </div>
94
+ </template>
95
+ </Tabs>
96
+ </Section>
76
97
 
77
- <h3>Dynamic Tabs</h3>
78
- <Tabs :tabs="tabs" :default-tab="0" @tab-change="onDynamicTabChange">
79
- <template v-for="(tab, index) in tabs" :key="tab.id" #[`tab-${index}`]>
80
- <div class="tab-content">
81
- <h4>{{ tab.label }}</h4>
82
- <p>{{ tab.content }}</p>
83
- <div class="tab-info">
84
- <p><strong>Tab ID:</strong> {{ tab.id }}</p>
85
- <p><strong>Created:</strong> {{ tab.created }}</p>
86
- </div>
87
- </div>
88
- </template>
89
- </Tabs>
98
+ <Section
99
+ title="Vertical Tabs"
100
+ subtitle="Side tab strip with arrow-key navigation up and down"
101
+ :padding="verticalTabsSectionPadding"
102
+ >
103
+ <template #toolbar>
104
+ <label class="tabs-padding-toggle">
105
+ <input v-model="verticalTabsSectionPadding" type="checkbox" />
106
+ Section padding
107
+ </label>
108
+ <label class="tabs-padding-toggle">
109
+ <input v-model="verticalTabsPadding" type="checkbox" />
110
+ Tab padding
111
+ </label>
112
+ </template>
90
113
 
91
- <h3>Tabs with Icons</h3>
92
- <Tabs :tabs="iconTabs" @tab-change="onTabChange">
93
- <template #tab-home>
94
- <div class="tab-content">
95
- <h4>Home</h4>
96
- <p>Welcome to the home section. This tab demonstrates the use of icons in tab labels.</p>
97
- </div>
98
- </template>
99
- <template #tab-profile>
100
- <div class="tab-content">
101
- <h4>Profile</h4>
102
- <p>View and edit your profile information here.</p>
103
- <div class="profile-card">
104
- <div class="profile-avatar">JD</div>
105
- <div class="profile-info">
106
- <h5>John Doe</h5>
107
- <p>john.doe@example.com</p>
108
- </div>
109
- </div>
110
- </div>
111
- </template>
112
- <template #tab-settings>
113
- <div class="tab-content">
114
- <h4>Settings</h4>
115
- <p>Manage your application settings and preferences.</p>
114
+ <Tabs
115
+ :tabs="verticalTabs"
116
+ orientation="vertical"
117
+ :padding="verticalTabsPadding"
118
+ @tab-change="onTabChange"
119
+ >
120
+ <template #tab-general>
121
+ <div class="tab-content">
122
+ <h4>General</h4>
123
+ <p>
124
+ Vertical tabs place the tab list beside the panel. Use them when labels are
125
+ longer or when the layout mirrors a settings sidebar.
126
+ </p>
127
+ </div>
128
+ </template>
129
+ <template #tab-appearance>
130
+ <div class="tab-content">
131
+ <h4>Appearance</h4>
132
+ <p>Theme and display options would live in this pane.</p>
133
+ <FormLayout>
134
+ <FormField label="Theme" for="vertical-tab-theme">
135
+ <select id="vertical-tab-theme">
136
+ <option>System</option>
137
+ <option>Light</option>
138
+ <option>Dark</option>
139
+ </select>
140
+ </FormField>
141
+ </FormLayout>
142
+ </div>
143
+ </template>
144
+ <template #tab-notifications>
145
+ <div class="tab-content">
146
+ <h4>Notifications</h4>
147
+ <p>Configure alerts and delivery preferences here.</p>
148
+ <ul>
149
+ <li>Email digests</li>
150
+ <li>Push notifications</li>
151
+ <li>In-app badges</li>
152
+ </ul>
153
+ </div>
154
+ </template>
155
+ <template #tab-advanced>
156
+ <div class="tab-content">
157
+ <h4>Advanced</h4>
158
+ <p>Less common options grouped at the bottom of the strip.</p>
159
+ </div>
160
+ </template>
161
+ </Tabs>
162
+ </Section>
163
+
164
+ <Section
165
+ title="Dynamic Tabs"
166
+ subtitle="Add and remove tab panes programmatically"
167
+ >
168
+ <template #toolbar>
169
+ <button @click="addRandomTab" class="good">Add Tab</button>
170
+ <button @click="removeLastTab" class="bad" :disabled="tabs.length <= 1">Remove Tab</button>
171
+ </template>
172
+
173
+ <Tabs :tabs="tabs" :default-tab="0" @tab-change="onDynamicTabChange">
174
+ <template v-for="(tab, index) in tabs" :key="tab.id" #[`tab-${index}`]>
175
+ <div class="tab-content">
176
+ <h4>{{ tab.label }}</h4>
177
+ <p>{{ tab.content }}</p>
178
+ <div class="tab-info">
179
+ <p><strong>Tab ID:</strong> {{ tab.id }}</p>
180
+ <p><strong>Created:</strong> {{ tab.created }}</p>
116
181
  </div>
117
- </template>
118
- </Tabs>
119
- </div>
182
+ </div>
183
+ </template>
184
+ </Tabs>
120
185
  </Section>
121
186
  </template>
122
187
 
123
188
  <script setup>
124
189
  import { ref, reactive } from 'vue';
190
+ import { HomeIcon, Settings01Icon, UserIcon, ViewIcon } from '@hugeicons/core-free-icons';
125
191
  import Section from '../components/Section.vue';
126
192
  import Tabs from '../components/Tabs.vue';
127
- // Icons are optional - set to null if not available
128
- // You can import specific icons from @hugeicons/core-free-icons if available
129
- // Example: import { HomeIcon, UserIcon, SettingsIcon } from '@hugeicons/core-free-icons';
193
+ import FormLayout from '../components/FormLayout.vue';
194
+ import FormField from '../components/FormField.vue';
130
195
 
131
196
  const basicTabs = ref([
132
- { id: 0, label: 'Overview' },
133
- { id: 1, label: 'Details' },
134
- { id: 2, label: 'Settings' }
197
+ { id: 0, label: 'Overview', icon: HomeIcon },
198
+ { id: 1, label: 'Details', icon: ViewIcon },
199
+ { id: 2, label: 'Settings', icon: Settings01Icon },
135
200
  ]);
136
201
 
137
- const iconTabs = ref([
138
- { id: 'home', label: 'Home', icon: null }, // Add icon from @hugeicons/core-free-icons if available
139
- { id: 'profile', label: 'Profile', icon: null }, // Add icon from @hugeicons/core-free-icons if available
140
- { id: 'settings', label: 'Settings', icon: null } // Add icon from @hugeicons/core-free-icons if available
202
+ const verticalTabs = ref([
203
+ { id: 'general', label: 'General', icon: HomeIcon },
204
+ { id: 'appearance', label: 'Appearance', icon: Settings01Icon },
205
+ { id: 'notifications', label: 'Notifications', icon: UserIcon },
206
+ { id: 'advanced', label: 'Advanced', icon: Settings01Icon },
141
207
  ]);
142
208
 
209
+ const horizontalTabsSectionPadding = ref(true);
210
+ const horizontalTabsPadding = ref(false);
211
+ const verticalTabsSectionPadding = ref(true);
212
+ const verticalTabsPadding = ref(false);
213
+
143
214
  const tabs = ref([
144
215
  {
145
216
  id: 0,
@@ -196,142 +267,16 @@ function saveSettings() {
196
267
  </script>
197
268
 
198
269
  <style scoped>
199
- .tabs-example-container {
200
- display: flex;
201
- flex-direction: column;
202
- gap: 2rem;
203
- }
204
-
205
- .tabs-example-container h3 {
206
- margin: 0 0 1rem 0;
207
- font-size: 1.3em;
208
- font-weight: 600;
209
- border-bottom: 1px solid var(--border-color, #e1e5e9);
210
- padding-bottom: 0.5rem;
211
- }
212
-
213
- .tab-content {
214
- display: flex;
215
- flex-direction: column;
216
- gap: 1rem;
217
- }
218
-
219
- .tab-content h4 {
220
- margin: 0 0 0.5rem 0;
221
- font-size: 1.2em;
222
- font-weight: 600;
223
- }
224
-
225
- .tab-content p {
226
- margin: 0;
227
- line-height: 1.6;
228
- }
229
-
230
- .tab-content ul {
231
- margin: 0.5rem 0;
232
- padding-left: 1.5rem;
233
- }
234
-
235
- .tab-content li {
236
- margin: 0.5rem 0;
237
- }
238
-
239
- .details-grid {
240
- display: grid;
241
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
242
- gap: 1rem;
243
- margin-top: 1rem;
244
- }
245
-
246
- .detail-item {
247
- padding: 0.75rem;
248
- background-color: var(--hover-background-color, #f5f5f5);
249
- border-radius: 4px;
250
- }
251
-
252
- .settings-form {
253
- display: flex;
254
- flex-direction: column;
255
- gap: 1rem;
256
- margin-top: 1rem;
257
- }
258
-
259
- .form-group {
260
- display: flex;
261
- flex-direction: column;
262
- gap: 0.5rem;
263
- }
264
-
265
- .form-group label {
266
- font-weight: 500;
267
- }
268
-
269
- .form-group input[type="text"],
270
- .form-group select {
271
- padding: 0.5rem;
272
- border: 1px solid var(--border-color, #ccc);
273
- border-radius: 4px;
274
- font-size: 1em;
275
- }
276
-
277
- .form-group input[type="checkbox"] {
278
- margin-right: 0.5rem;
270
+ .tabs-padding-toggle {
271
+ display: inline-flex;
272
+ align-items: center;
273
+ gap: 0.4em;
274
+ margin-right: 0.75em;
279
275
  }
280
276
 
281
277
  .tab-info {
282
- margin-top: 1rem;
283
- padding: 1rem;
284
- background-color: var(--hover-background-color, #f5f5f5);
285
- border-radius: 4px;
286
- }
287
-
288
- .tab-info p {
289
- margin: 0.5rem 0;
290
- }
291
-
292
- .profile-card {
293
- display: flex;
294
- align-items: center;
295
- gap: 1rem;
296
278
  padding: 1rem;
297
- background-color: var(--hover-background-color, #f5f5f5);
298
- border-radius: 8px;
299
- margin-top: 1rem;
300
- }
301
-
302
- .profile-avatar {
303
- width: 60px;
304
- height: 60px;
305
- border-radius: 50%;
306
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
307
- display: flex;
308
- align-items: center;
309
- justify-content: center;
310
- color: white;
311
- font-size: 1.5em;
312
- font-weight: bold;
313
- }
314
-
315
- .profile-info h5 {
316
- margin: 0 0 0.25rem 0;
317
- font-size: 1.1em;
318
- }
319
-
320
- .profile-info p {
321
- margin: 0;
322
- color: var(--text-muted, #666);
323
- }
324
-
325
- html[data-theme="dark"] {
326
- .detail-item,
327
- .tab-info,
328
- .profile-card {
329
- background-color: var(--hover-background-color, #333);
330
- }
331
-
332
- .detail-item strong,
333
- .tab-info strong {
334
- color: var(--text-color, #fff);
335
- }
279
+ background-color: var(--standout-bg-color);
280
+ border-radius: 0.4em;
336
281
  }
337
282
  </style>
@@ -40,21 +40,26 @@
40
40
  </Section>
41
41
 
42
42
  <Section title="Notifications" subtitle="Block-level karma status">
43
- <div class="notification show good" role="status">
44
- <strong>GOOD:</strong> Theme tokens are applying to karma backgrounds.
45
- </div>
46
- <div class="notification show bad" role="status">
47
- <strong>BAD:</strong> Check contrast on error surfaces.
48
- </div>
49
- <div class="notification show warning" role="status">
50
- <strong>WARNING:</strong> Accent and border colors should stay readable.
51
- </div>
52
- <p class="fg-success show inline-notification">
53
- <strong>SUCCESS:</strong> Inline notification with foreground karma.
54
- </p>
55
- <p class="fg-warning show inline-notification">
56
- <strong>WARNING:</strong> Another inline status line.
57
- </p>
43
+ <NotificationBlock
44
+ type="success"
45
+ message="Theme tokens are applying to karma backgrounds."
46
+ />
47
+ <NotificationBlock
48
+ type="critical"
49
+ message="Check contrast on error surfaces."
50
+ />
51
+ <NotificationBlock
52
+ type="warning"
53
+ message="Accent and border colors should stay readable."
54
+ />
55
+ <span class="annotation good">
56
+ <span class="annotation-key">success</span>
57
+ <span class="annotation-val">Inline annotation with karma tint.</span>
58
+ </span>
59
+ <span class="annotation warning">
60
+ <span class="annotation-key">warning</span>
61
+ <span class="annotation-val">Another inline status chip.</span>
62
+ </span>
58
63
  </Section>
59
64
 
60
65
  <Section title="Form controls" subtitle="Inputs inherit theme variables">
@@ -132,6 +137,7 @@ import { inject } from 'vue'
132
137
  import Section from '../components/Section.vue'
133
138
  import FormLayout from '../components/FormLayout.vue'
134
139
  import FormField from '../components/FormField.vue'
140
+ import NotificationBlock from '../components/NotificationBlock.vue'
135
141
  import { HEADER_THEME_SWITCHER_SELECT_ID } from '../components/ThemeSwitcher.vue'
136
142
 
137
143
  const themeSwitcherEnabled = inject('themeSwitcherEnabled')
@@ -168,12 +174,4 @@ function openThemeSwitcher() {
168
174
  padding: 0.5rem 0.75rem;
169
175
  border-bottom: 1px solid var(--border-color, #d7d7d7);
170
176
  }
171
-
172
- .notification {
173
- margin-bottom: 0.5rem;
174
- }
175
-
176
- .inline-notification {
177
- margin: 0.5rem 0;
178
- }
179
177
  </style>
@@ -5,7 +5,6 @@
5
5
  <h2 :title="item.subtitle">{{ item.title }}</h2>
6
6
  </div>
7
7
  <div role="toolbar">
8
- <router-link :to="{ name: 'TableExample' }" class="button neutral">Back to table</router-link>
9
8
  <button type="button" class="good">Edit</button>
10
9
  </div>
11
10
  </div>
@@ -83,10 +82,23 @@
83
82
  </ul>
84
83
  </div>
85
84
  </section>
85
+
86
+ <DangerZone
87
+ title="Danger zone"
88
+ subtitle="Destructive actions for this record"
89
+ description="Show destructive actions"
90
+ >
91
+ <div role="toolbar" class="danger-zone-actions">
92
+ <button type="button" class="bad" @click="deleteItem">
93
+ Delete {{ item.name }}
94
+ </button>
95
+ </div>
96
+ </DangerZone>
86
97
  </template>
87
98
 
88
99
  <script setup>
89
100
  import { computed } from 'vue'
101
+ import DangerZone from '../components/DangerZone.vue'
90
102
 
91
103
  const props = defineProps({
92
104
  id: {
@@ -102,7 +114,7 @@ const itemsById = {
102
114
  summary: 'Read-only detail view for a single record, using Femtocrank definition lists and section subheaders.',
103
115
  name: 'Acme deployment',
104
116
  status: 'Active',
105
- statusClass: 'fg-good',
117
+ statusClass: 'good',
106
118
  role: 'Release',
107
119
  location: 'us-east-1',
108
120
  email: 'releases@example.com',
@@ -124,7 +136,7 @@ const itemsById = {
124
136
  summary: 'Example person record linked from the table example.',
125
137
  name: 'Alice',
126
138
  status: 'Active',
127
- statusClass: 'fg-good',
139
+ statusClass: 'good',
128
140
  role: 'Senior analyst',
129
141
  location: 'New York',
130
142
  email: 'alice@example.com',
@@ -145,7 +157,7 @@ const itemsById = {
145
157
  summary: 'Example person record linked from the table example.',
146
158
  name: 'Bob',
147
159
  status: 'Away',
148
- statusClass: 'fg-warning',
160
+ statusClass: 'warning',
149
161
  role: 'Support specialist',
150
162
  location: 'Los Angeles',
151
163
  email: 'bob@example.com',
@@ -175,7 +187,7 @@ const item = computed(() => {
175
187
  summary: 'Generic detail view for records opened from the table or navigation.',
176
188
  name: label,
177
189
  status: 'Unknown',
178
- statusClass: 'fg-note',
190
+ statusClass: 'note',
179
191
  role: '—',
180
192
  location: '—',
181
193
  email: `${key.toLowerCase()}@example.com`,
@@ -188,4 +200,19 @@ const item = computed(() => {
188
200
  activity: [{ when: '—', text: 'No activity recorded for this item.' }],
189
201
  }
190
202
  })
203
+
204
+ function deleteItem() {
205
+ const name = item.value.name
206
+ if (window.confirm(`Delete “${name}”? This action cannot be undone.`)) {
207
+ window.alert(`“${name}” would be deleted. (Demo only — no request was sent.)`)
208
+ }
209
+ }
191
210
  </script>
211
+
212
+ <style scoped>
213
+ .danger-zone-actions {
214
+ display: flex;
215
+ flex-wrap: wrap;
216
+ gap: 0.5rem;
217
+ }
218
+ </style>