@brumaombra/ui-vintage 0.7.13 → 0.8.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/COMPONENTS.md +3602 -0
- package/README.md +49 -9
- package/package.json +29 -8
- package/skills/ui-vintage/SKILL.md +42 -0
- package/src/components/blog/BlogFAQSection.vue +2 -2
- package/src/components/blog/BlogHeaderSection.vue +2 -2
- package/src/components/blog/BlogInfoSection.vue +3 -3
- package/src/components/blog/BlogProgressBar.vue +7 -6
- package/src/components/blog/BlogSectionTitle.vue +1 -1
- package/src/components/blog/BlogTagsSection.vue +22 -0
- package/src/components/blog/CategoryCard.vue +1 -1
- package/src/components/blog/HeaderCarousel.vue +6 -6
- package/src/components/blog/PostCard.vue +2 -2
- package/src/components/blog/SocialShareSidebar.vue +1 -1
- package/src/components/blog/TableOfContents.vue +6 -6
- package/src/components/blog/index.ts +1 -0
- package/src/components/busy-indicator/busy-indicator-state.ts +3 -2
- package/src/components/chip/Chip.vue +9 -5
- package/src/components/confirm-dialog/ConfirmDialog.vue +17 -6
- package/src/components/confirm-dialog/confirm-dialog-state.ts +4 -3
- package/src/components/content/BlogList.vue +3 -3
- package/src/components/content/BlogTable.vue +7 -7
- package/src/components/content/CodeBlock.vue +4 -4
- package/src/components/content/Flow.vue +3 -3
- package/src/components/content/ProseHr.vue +2 -2
- package/src/components/content/Terminal.vue +4 -4
- package/src/components/dashboard-shell/DashboardShell.vue +3 -3
- package/src/components/empty-state-card/EmptyStateCard.vue +4 -4
- package/src/components/error-page/ErrorPage.vue +16 -14
- package/src/components/info-card/InfoCard.vue +1 -1
- package/src/components/landing/landing-navbar/LandingNavbar.vue +2 -1
- package/src/components/load-more-button/LoadMoreButton.vue +2 -2
- package/src/components/loading-state-card/LoadingStateCard.vue +4 -4
- package/src/components/message-dialog/MessageDialog.vue +4 -4
- package/src/components/message-toast/MessageToast.vue +222 -50
- package/src/components/message-toast/index.ts +2 -2
- package/src/components/message-toast/message-toast-state.ts +107 -81
- package/src/components/page-header/PageHeader.vue +1 -1
- package/src/components/progress-component/ProgressComponent.vue +4 -4
- package/src/components/single-value-card/SingleValueCard.vue +47 -11
- package/src/components/theme-selector/ThemeSelector.vue +20 -36
- package/src/components/theme-selector/index.ts +3 -1
- package/src/components/theme-selector/theme-transition.ts +86 -0
- package/src/components/ui/accordion/Accordion.vue +41 -26
- package/src/components/ui/alert-dialog/AlertDialogContent.vue +2 -2
- package/src/components/ui/alert-dialog/AlertDialogFooter.vue +1 -1
- package/src/components/ui/animated-number/AnimatedNumber.vue +88 -0
- package/src/components/ui/animated-number/index.ts +1 -0
- package/src/components/ui/avatar/Avatar.vue +66 -0
- package/src/components/ui/avatar/AvatarFallback.vue +31 -0
- package/src/components/ui/avatar/AvatarGroup.vue +75 -0
- package/src/components/ui/avatar/AvatarImage.vue +23 -0
- package/src/components/ui/avatar/index.ts +47 -0
- package/src/components/ui/badge/Badge.vue +13 -2
- package/src/components/ui/breadcrumb/Breadcrumb.vue +4 -1
- package/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +7 -1
- package/src/components/ui/busy/Busy.vue +45 -20
- package/src/components/ui/button/Button.vue +20 -3
- package/src/components/ui/button/index.ts +12 -2
- package/src/components/ui/card/Card.vue +21 -8
- package/src/components/ui/card/CardText.vue +1 -1
- package/src/components/ui/checkbox/Checkbox.vue +48 -0
- package/src/components/ui/checkbox/index.ts +1 -0
- package/src/components/ui/collapsible/Collapsible.vue +22 -0
- package/src/components/ui/collapsible/CollapsibleContent.vue +22 -0
- package/src/components/ui/collapsible/CollapsibleTrigger.vue +19 -0
- package/src/components/ui/collapsible/index.ts +3 -0
- package/src/components/ui/combobox/Combobox.vue +24 -0
- package/src/components/ui/combobox/ComboboxAnchor.vue +39 -0
- package/src/components/ui/combobox/ComboboxEmpty.vue +21 -0
- package/src/components/ui/combobox/ComboboxGroup.vue +26 -0
- package/src/components/ui/combobox/ComboboxInput.vue +28 -0
- package/src/components/ui/combobox/ComboboxItem.vue +39 -0
- package/src/components/ui/combobox/ComboboxList.vue +43 -0
- package/src/components/ui/combobox/ComboboxSelect.vue +162 -0
- package/src/components/ui/combobox/ComboboxSeparator.vue +16 -0
- package/src/components/ui/combobox/ComboboxTrigger.vue +28 -0
- package/src/components/ui/combobox/index.ts +11 -0
- package/src/components/ui/combobox/types.ts +16 -0
- package/src/components/ui/command/CommandDialog.vue +18 -16
- package/src/components/ui/command/CommandGroup.vue +1 -1
- package/src/components/ui/command/CommandInput.vue +2 -2
- package/src/components/ui/command/CommandItem.vue +7 -5
- package/src/components/ui/data-table/DataTable.vue +230 -0
- package/src/components/ui/data-table/index.ts +20 -0
- package/src/components/ui/date-picker/DatePicker.vue +11 -15
- package/src/components/ui/date-time-picker/DateTimePicker.vue +2 -7
- package/src/components/ui/dialog/DialogContent.vue +9 -4
- package/src/components/ui/dialog/DialogOverlay.vue +1 -1
- package/src/components/ui/dialog/DialogScrollContent.vue +10 -5
- package/src/components/ui/dropdown-menu/DropdownMenu.vue +18 -0
- package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +34 -0
- package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +39 -0
- package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +13 -0
- package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +34 -0
- package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +26 -0
- package/src/components/ui/dropdown-menu/DropdownMenuPortal.vue +13 -0
- package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +18 -0
- package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +32 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +16 -0
- package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +15 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +18 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +39 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +36 -0
- package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +15 -0
- package/src/components/ui/dropdown-menu/classes.ts +24 -0
- package/src/components/ui/dropdown-menu/index.ts +15 -0
- package/src/components/ui/field/FieldDescription.vue +1 -1
- package/src/components/ui/field/FieldError.vue +4 -1
- package/src/components/ui/file-dropzone/FileDropzone.vue +250 -0
- package/src/components/ui/file-dropzone/index.ts +35 -0
- package/src/components/ui/hover-card/HoverCard.vue +21 -0
- package/src/components/ui/hover-card/HoverCardContent.vue +33 -0
- package/src/components/ui/hover-card/HoverCardTrigger.vue +13 -0
- package/src/components/ui/hover-card/index.ts +3 -0
- package/src/components/ui/input/Input.vue +5 -5
- package/src/components/ui/kbd/Kbd.vue +21 -0
- package/src/components/ui/kbd/KbdGroup.vue +72 -0
- package/src/components/ui/kbd/index.ts +2 -0
- package/src/components/ui/number-field/NumberField.vue +130 -0
- package/src/components/ui/number-field/index.ts +1 -0
- package/src/components/ui/pagination/Pagination.vue +27 -0
- package/src/components/ui/pagination/PaginationContent.vue +20 -0
- package/src/components/ui/pagination/PaginationEllipsis.vue +31 -0
- package/src/components/ui/pagination/PaginationFirst.vue +32 -0
- package/src/components/ui/pagination/PaginationItem.vue +41 -0
- package/src/components/ui/pagination/PaginationLast.vue +32 -0
- package/src/components/ui/pagination/PaginationNext.vue +32 -0
- package/src/components/ui/pagination/PaginationPrevious.vue +32 -0
- package/src/components/ui/pagination/SimplePagination.vue +49 -0
- package/src/components/ui/pagination/index.ts +9 -0
- package/src/components/ui/pin-input/PinInput.vue +48 -0
- package/src/components/ui/pin-input/PinInputInput.vue +49 -0
- package/src/components/ui/pin-input/context.ts +8 -0
- package/src/components/ui/pin-input/index.ts +2 -0
- package/src/components/ui/popover/PopoverContent.vue +1 -1
- package/src/components/ui/progress/Progress.vue +22 -7
- package/src/components/ui/radio-group/RadioGroup.vue +27 -0
- package/src/components/ui/radio-group/RadioGroupCard.vue +56 -0
- package/src/components/ui/radio-group/RadioGroupItem.vue +40 -0
- package/src/components/ui/radio-group/index.ts +3 -0
- package/src/components/ui/select/SelectContent.vue +1 -1
- package/src/components/ui/select/SelectItem.vue +2 -2
- package/src/components/ui/select/SelectItemContent.vue +1 -1
- package/src/components/ui/select/SelectTrigger.vue +6 -6
- package/src/components/ui/select/SelectValueContent.vue +1 -1
- package/src/components/ui/sheet/SheetContent.vue +5 -5
- package/src/components/ui/sheet/SheetOverlay.vue +1 -1
- package/src/components/ui/sidebar/Sidebar.vue +7 -5
- package/src/components/ui/sidebar/SidebarRail.vue +3 -1
- package/src/components/ui/sidebar/SidebarTrigger.vue +3 -1
- package/src/components/ui/skeleton/Skeleton.vue +4 -4
- package/src/components/ui/slider/Slider.vue +8 -6
- package/src/components/ui/spinner/Spinner.vue +47 -0
- package/src/components/ui/spinner/index.ts +1 -0
- package/src/components/ui/stepper/SimpleStepper.vue +56 -0
- package/src/components/ui/stepper/Stepper.vue +30 -0
- package/src/components/ui/stepper/StepperDescription.vue +20 -0
- package/src/components/ui/stepper/StepperIndicator.vue +41 -0
- package/src/components/ui/stepper/StepperItem.vue +21 -0
- package/src/components/ui/stepper/StepperSeparator.vue +34 -0
- package/src/components/ui/stepper/StepperTitle.vue +20 -0
- package/src/components/ui/stepper/StepperTrigger.vue +20 -0
- package/src/components/ui/stepper/index.ts +17 -0
- package/src/components/ui/switch/Switch.vue +8 -6
- package/src/components/ui/tabs/TabsContent.vue +1 -1
- package/src/components/ui/tabs/TabsList.vue +13 -5
- package/src/components/ui/tabs/TabsTrigger.vue +5 -3
- package/src/components/ui/tags-input/TagsInput.vue +49 -0
- package/src/components/ui/tags-input/TagsInputInput.vue +23 -0
- package/src/components/ui/tags-input/TagsInputItem.vue +35 -0
- package/src/components/ui/tags-input/TagsInputItemDelete.vue +31 -0
- package/src/components/ui/tags-input/TagsInputItemText.vue +21 -0
- package/src/components/ui/tags-input/index.ts +5 -0
- package/src/components/ui/textarea/Textarea.vue +4 -5
- package/src/components/ui/toggle-group/Toggle.vue +33 -0
- package/src/components/ui/toggle-group/ToggleGroup.vue +93 -0
- package/src/components/ui/toggle-group/ToggleGroupItem.vue +34 -0
- package/src/components/ui/toggle-group/index.ts +69 -0
- package/src/components/ui/tooltip/TooltipContent.vue +1 -1
- package/src/i18n/de.json +76 -0
- package/src/i18n/en.json +76 -0
- package/src/i18n/es.json +76 -0
- package/src/i18n/fr.json +76 -0
- package/src/i18n/it.json +76 -0
- package/src/i18n/ja.json +76 -0
- package/src/i18n/pt.json +76 -0
- package/src/i18n/ru.json +76 -0
- package/src/i18n/zh.json +76 -0
- package/src/lib/color-tokens.ts +14 -14
- package/src/styles.css +289 -5
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { HugeiconsIcon } from '@hugeicons/vue';
|
|
3
|
-
import { computed } from 'vue';
|
|
3
|
+
import { computed, ref } from 'vue';
|
|
4
4
|
import { InformationCircleIcon } from '@hugeicons/core-free-icons';
|
|
5
5
|
import { AlertDialog, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '../ui/alert-dialog';
|
|
6
6
|
import { Button } from '../ui/button';
|
|
7
7
|
import { cancelActiveConfirmDialog, closeConfirmDialog, confirmActiveDialog, confirmDialogState } from './confirm-dialog-state';
|
|
8
8
|
|
|
9
9
|
const currentDialog = computed(() => confirmDialogState.current);
|
|
10
|
+
const pendingAction = ref<'confirm' | 'cancel' | null>(null);
|
|
11
|
+
|
|
12
|
+
// Run an action while showing a spinner on the button that triggered it
|
|
13
|
+
const runAction = async (action: 'confirm' | 'cancel') => {
|
|
14
|
+
pendingAction.value = action;
|
|
15
|
+
try {
|
|
16
|
+
await (action === 'confirm' ? confirmActiveDialog() : cancelActiveConfirmDialog());
|
|
17
|
+
} finally {
|
|
18
|
+
pendingAction.value = null;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
10
21
|
|
|
11
22
|
// Close the dialog when the shell requests it
|
|
12
23
|
const handleOpenChange = (open: boolean) => {
|
|
@@ -24,9 +35,9 @@ const handleOpenChange = (open: boolean) => {
|
|
|
24
35
|
<div class="px-5 pb-5 pt-5 sm:px-6 sm:pb-4 sm:pt-6">
|
|
25
36
|
<div class="flex flex-col gap-4 sm:flex-row sm:items-start">
|
|
26
37
|
<!-- Dialog icon -->
|
|
27
|
-
<div class="flex size-12 shrink-0 self-center items-center justify-center rounded border border-
|
|
28
|
-
<HugeiconsIcon v-if="currentDialog.options.icon" :icon="currentDialog.options.icon" :stroke-width="1.8" class="size-6
|
|
29
|
-
<HugeiconsIcon v-else :icon="InformationCircleIcon" :stroke-width="1.8" class="size-6
|
|
38
|
+
<div class="flex size-12 shrink-0 self-center items-center justify-center rounded border border-primary/30 bg-primary/10 sm:size-10 sm:self-start">
|
|
39
|
+
<HugeiconsIcon v-if="currentDialog.options.icon" :icon="currentDialog.options.icon" :stroke-width="1.8" class="size-6 animate-uv-pop text-primary [animation-delay:140ms]" />
|
|
40
|
+
<HugeiconsIcon v-else :icon="InformationCircleIcon" :stroke-width="1.8" class="size-6 animate-uv-pop text-primary [animation-delay:140ms]" />
|
|
30
41
|
</div>
|
|
31
42
|
|
|
32
43
|
<!-- Dialog header -->
|
|
@@ -44,13 +55,13 @@ const handleOpenChange = (open: boolean) => {
|
|
|
44
55
|
<!-- Dialog actions -->
|
|
45
56
|
<AlertDialogFooter>
|
|
46
57
|
<!-- Cancel button -->
|
|
47
|
-
<Button :variant="currentDialog.options.cancelButtonType" :disabled="confirmDialogState.busy" @click="
|
|
58
|
+
<Button :variant="currentDialog.options.cancelButtonType" :disabled="confirmDialogState.busy && pendingAction !== 'cancel'" :loading="pendingAction === 'cancel'" @click="runAction('cancel')">
|
|
48
59
|
<HugeiconsIcon v-if="currentDialog.options.cancelButtonIcon" :icon="currentDialog.options.cancelButtonIcon" class="size-4" />
|
|
49
60
|
{{ currentDialog.options.cancelText }}
|
|
50
61
|
</Button>
|
|
51
62
|
|
|
52
63
|
<!-- Confirm button -->
|
|
53
|
-
<Button :variant="currentDialog.options.confirmButtonType" :disabled="confirmDialogState.busy" @click="
|
|
64
|
+
<Button :variant="currentDialog.options.confirmButtonType" :disabled="confirmDialogState.busy && pendingAction !== 'confirm'" :loading="pendingAction === 'confirm'" @click="runAction('confirm')">
|
|
54
65
|
<HugeiconsIcon v-if="currentDialog.options.confirmButtonIcon" :icon="currentDialog.options.confirmButtonIcon" class="size-4" />
|
|
55
66
|
{{ currentDialog.options.confirmText }}
|
|
56
67
|
</Button>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { h, markRaw, reactive, render } from 'vue';
|
|
2
2
|
import type { ButtonVariants } from '../ui/button';
|
|
3
3
|
import type { HugeiconsIconDefinition } from '../../lib/common-types';
|
|
4
|
+
import { getUiVintageRuntimeMessage } from '../../lib/i18n';
|
|
4
5
|
|
|
5
6
|
export type DialogButtonVariant = NonNullable<ButtonVariants['variant']>;
|
|
6
7
|
export type { HugeiconsIconDefinition };
|
|
@@ -183,10 +184,10 @@ export const showConfirmDialog = (options: ShowConfirmDialogOptions) => {
|
|
|
183
184
|
enqueueConfirmDialog({
|
|
184
185
|
id: nextConfirmDialogId += 1,
|
|
185
186
|
options: {
|
|
186
|
-
title: options.title ?? 'Confirm',
|
|
187
|
+
title: options.title ?? getUiVintageRuntimeMessage('uiVintage.messageDialog.confirm', 'Confirm'),
|
|
187
188
|
message: options.message,
|
|
188
|
-
confirmText: options.confirmText ?? 'Confirm',
|
|
189
|
-
cancelText: options.cancelText ?? 'Cancel',
|
|
189
|
+
confirmText: options.confirmText ?? getUiVintageRuntimeMessage('uiVintage.buttons.confirm', 'Confirm'),
|
|
190
|
+
cancelText: options.cancelText ?? getUiVintageRuntimeMessage('uiVintage.buttons.cancel', 'Cancel'),
|
|
190
191
|
confirmButtonType: options.confirmButtonType ?? 'primary',
|
|
191
192
|
cancelButtonType: options.cancelButtonType ?? 'secondary',
|
|
192
193
|
icon: markIcon(options.icon),
|
|
@@ -14,12 +14,12 @@ const props = withDefaults(defineProps<{
|
|
|
14
14
|
|
|
15
15
|
// Icon container classes
|
|
16
16
|
const getIconContainerClasses = () => {
|
|
17
|
-
return 'flex items-center justify-center w-8 h-8 bg-
|
|
17
|
+
return 'flex items-center justify-center w-8 h-8 bg-card border border-border rounded mr-4 shrink-0';
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
// Icon color classes
|
|
21
21
|
const getIconClasses = () => {
|
|
22
|
-
return 'text-
|
|
22
|
+
return 'text-muted-foreground text-xs';
|
|
23
23
|
};
|
|
24
24
|
</script>
|
|
25
25
|
|
|
@@ -51,7 +51,7 @@ const getIconClasses = () => {
|
|
|
51
51
|
|
|
52
52
|
<!-- Content -->
|
|
53
53
|
<div class="flex-1">
|
|
54
|
-
<div class="text-
|
|
54
|
+
<div class="text-foreground leading-relaxed">
|
|
55
55
|
{{ item }}
|
|
56
56
|
</div>
|
|
57
57
|
</div>
|
|
@@ -15,16 +15,16 @@ const props = withDefaults(defineProps<{
|
|
|
15
15
|
|
|
16
16
|
// Header cell classes
|
|
17
17
|
const getHeaderClasses = (colIndex: number) => {
|
|
18
|
-
const baseClasses = 'text-left font-semibold text-
|
|
19
|
-
const highlightClass = props.highlightCol === colIndex ? 'bg-
|
|
18
|
+
const baseClasses = 'text-left font-semibold text-foreground';
|
|
19
|
+
const highlightClass = props.highlightCol === colIndex ? 'bg-accent' : '';
|
|
20
20
|
return [baseClasses, highlightClass];
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
// Body cell classes
|
|
24
24
|
const getCellClasses = (colIndex: number) => {
|
|
25
|
-
const baseClasses = 'align-top text-
|
|
26
|
-
const firstColClass = colIndex === 0 ? 'font-semibold text-
|
|
27
|
-
const highlightClass = props.highlightCol === colIndex ? 'bg-
|
|
25
|
+
const baseClasses = 'align-top text-foreground leading-relaxed whitespace-normal';
|
|
26
|
+
const firstColClass = colIndex === 0 ? 'font-semibold text-muted-foreground' : '';
|
|
27
|
+
const highlightClass = props.highlightCol === colIndex ? 'bg-accent' : '';
|
|
28
28
|
return [baseClasses, firstColClass, highlightClass];
|
|
29
29
|
};
|
|
30
30
|
</script>
|
|
@@ -37,7 +37,7 @@ const getCellClasses = (colIndex: number) => {
|
|
|
37
37
|
<Table class="w-full text-sm text-left">
|
|
38
38
|
<!-- Table header -->
|
|
39
39
|
<TableHeader>
|
|
40
|
-
<TableRow class="bg-transparent text-sm text-
|
|
40
|
+
<TableRow class="bg-transparent text-sm text-muted-foreground hover:bg-transparent">
|
|
41
41
|
<TableHead v-for="(header, colIndex) in props.headers" :key="colIndex" :class="getHeaderClasses(colIndex)">
|
|
42
42
|
{{ header }}
|
|
43
43
|
</TableHead>
|
|
@@ -46,7 +46,7 @@ const getCellClasses = (colIndex: number) => {
|
|
|
46
46
|
|
|
47
47
|
<!-- Table body -->
|
|
48
48
|
<TableBody>
|
|
49
|
-
<TableRow v-for="(row, rowIndex) in props.rows" :key="rowIndex" class="text-
|
|
49
|
+
<TableRow v-for="(row, rowIndex) in props.rows" :key="rowIndex" class="text-muted-foreground hover:bg-transparent">
|
|
50
50
|
<TableCell v-for="(cell, colIndex) in row" :key="colIndex" :class="getCellClasses(colIndex)">
|
|
51
51
|
{{ cell }}
|
|
52
52
|
</TableCell>
|
|
@@ -76,12 +76,12 @@ const copyCode = async () => {
|
|
|
76
76
|
|
|
77
77
|
<template>
|
|
78
78
|
<div class="not-prose my-6 sm:my-8">
|
|
79
|
-
<Card class="gap-0! sm:gap-0! overflow-hidden p-0! text-
|
|
79
|
+
<Card class="gap-0! sm:gap-0! overflow-hidden p-0! text-foreground">
|
|
80
80
|
<!-- Code header -->
|
|
81
81
|
<div class="flex items-center justify-between gap-3 border-b border-(--border-light) bg-(--bg-card-light) px-3 py-2 sm:px-4 dark:border-(--border-dark) dark:bg-(--bg-card-dark)">
|
|
82
82
|
<div class="flex min-w-0 items-center gap-2">
|
|
83
|
-
<HugeiconsIcon :icon="CodeIcon" class="size-4 shrink-0 text-
|
|
84
|
-
<span class="truncate text-xs font-semibold text-
|
|
83
|
+
<HugeiconsIcon :icon="CodeIcon" class="size-4 shrink-0 text-muted-foreground" />
|
|
84
|
+
<span class="truncate text-xs font-semibold text-muted-foreground">{{ resolvedTitle }}</span>
|
|
85
85
|
</div>
|
|
86
86
|
|
|
87
87
|
<!-- Copy code button -->
|
|
@@ -98,7 +98,7 @@ const copyCode = async () => {
|
|
|
98
98
|
</div>
|
|
99
99
|
|
|
100
100
|
<!-- Code content -->
|
|
101
|
-
<div v-if="highlightedCode" class="code-block-content overflow-x-auto bg-
|
|
101
|
+
<div v-if="highlightedCode" class="code-block-content overflow-x-auto bg-surface" v-html="highlightedCode" />
|
|
102
102
|
<pre v-else class="code-block-content overflow-x-auto bg-(--bg-surface-light) px-4 py-3 text-xs leading-6 dark:bg-(--bg-surface-dark) sm:px-5 sm:py-4 sm:text-sm"><code>{{ displayedCode }}</code></pre>
|
|
103
103
|
</Card>
|
|
104
104
|
</div>
|
|
@@ -65,7 +65,7 @@ const isVertical = () => {
|
|
|
65
65
|
<Card class="flex-1 overflow-hidden md:flex md:items-center">
|
|
66
66
|
<CardContent class="w-full gap-3 md:justify-center">
|
|
67
67
|
<!-- Flow item header -->
|
|
68
|
-
<div class="inline-flex items-center gap-3 text-xs font-semibold text-
|
|
68
|
+
<div class="inline-flex items-center gap-3 text-xs font-semibold text-foreground">
|
|
69
69
|
<!-- Flow item number -->
|
|
70
70
|
<span class="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded border border-(--border-light) bg-(--bg-card-light) text-xs font-semibold text-(--text-secondary-light) dark:border-(--border-dark) dark:bg-(--bg-card-dark) dark:text-(--text-secondary-dark)">
|
|
71
71
|
{{ index + 1 }}
|
|
@@ -76,14 +76,14 @@ const isVertical = () => {
|
|
|
76
76
|
</div>
|
|
77
77
|
|
|
78
78
|
<!-- Flow item description -->
|
|
79
|
-
<p v-if="getItemDescription(item)" class="text-xs leading-6 text-
|
|
79
|
+
<p v-if="getItemDescription(item)" class="text-xs leading-6 text-muted-foreground md:leading-5">
|
|
80
80
|
{{ getItemDescription(item) }}
|
|
81
81
|
</p>
|
|
82
82
|
</CardContent>
|
|
83
83
|
</Card>
|
|
84
84
|
|
|
85
85
|
<!-- Flow item separator -->
|
|
86
|
-
<div v-if="index < props.items.length - 1" class="flex items-center justify-center text-
|
|
86
|
+
<div v-if="index < props.items.length - 1" class="flex items-center justify-center text-muted-foreground">
|
|
87
87
|
<!-- Flow item separator for vertical orientation -->
|
|
88
88
|
<HugeiconsIcon v-if="isVertical()" :icon="ArrowDown01Icon" class="size-5 shrink-0" />
|
|
89
89
|
|
|
@@ -18,8 +18,8 @@ const props = withDefaults(defineProps<{
|
|
|
18
18
|
<div class="h-px flex-1 bg-linear-to-r from-transparent via-(--border-light) to-(--border-light) dark:via-(--border-dark) dark:to-(--border-dark)" />
|
|
19
19
|
|
|
20
20
|
<!-- Icon in the middle -->
|
|
21
|
-
<div class="flex h-9 w-9 items-center justify-center rounded bg-
|
|
22
|
-
<HugeiconsIcon :icon="props.icon" class="size-4 text-
|
|
21
|
+
<div class="flex h-9 w-9 items-center justify-center rounded bg-card border border-border">
|
|
22
|
+
<HugeiconsIcon :icon="props.icon" class="size-4 text-muted-foreground" />
|
|
23
23
|
</div>
|
|
24
24
|
|
|
25
25
|
<!-- Right line -->
|
|
@@ -42,12 +42,12 @@ const copyCommands = async () => {
|
|
|
42
42
|
|
|
43
43
|
<template>
|
|
44
44
|
<div class="not-prose my-6 sm:my-8">
|
|
45
|
-
<Card class="gap-0! sm:gap-0! overflow-hidden p-0! text-
|
|
45
|
+
<Card class="gap-0! sm:gap-0! overflow-hidden p-0! text-foreground">
|
|
46
46
|
<!-- Terminal header -->
|
|
47
47
|
<div class="flex items-center justify-between gap-3 border-b border-(--border-light) bg-(--bg-card-light) px-3 py-2 sm:px-4 dark:border-(--border-dark) dark:bg-(--bg-card-dark)">
|
|
48
48
|
<div class="flex min-w-0 items-center gap-2">
|
|
49
|
-
<HugeiconsIcon :icon="TerminalIcon" class="size-4 shrink-0 text-
|
|
50
|
-
<span class="truncate text-xs font-semibold text-
|
|
49
|
+
<HugeiconsIcon :icon="TerminalIcon" class="size-4 shrink-0 text-muted-foreground" />
|
|
50
|
+
<span class="truncate text-xs font-semibold text-muted-foreground">{{ resolvedTitle }}</span>
|
|
51
51
|
</div>
|
|
52
52
|
|
|
53
53
|
<!-- Copy command button -->
|
|
@@ -64,7 +64,7 @@ const copyCommands = async () => {
|
|
|
64
64
|
</div>
|
|
65
65
|
|
|
66
66
|
<!-- Terminal commands -->
|
|
67
|
-
<pre class="overflow-x-auto bg-(--bg-surface-light) px-4 py-3 text-xs leading-6 dark:bg-(--bg-surface-dark) sm:px-5 sm:py-4 sm:text-sm"><code><span v-for="(command, index) in props.commands" :key="`${command}-${index}`" class="flex min-w-max"><span class="mr-3 select-none text-
|
|
67
|
+
<pre class="overflow-x-auto bg-(--bg-surface-light) px-4 py-3 text-xs leading-6 dark:bg-(--bg-surface-dark) sm:px-5 sm:py-4 sm:text-sm"><code><span v-for="(command, index) in props.commands" :key="`${command}-${index}`" class="flex min-w-max"><span class="mr-3 select-none text-muted-foreground" aria-hidden="true">{{ props.prompt }}</span><span>{{ command }}</span></span></code></pre>
|
|
68
68
|
</Card>
|
|
69
69
|
</div>
|
|
70
70
|
</template>
|
|
@@ -107,10 +107,10 @@ const getSidebarItemLinkProps = (item: NonNullable<typeof props.sidebarSections>
|
|
|
107
107
|
<SidebarGroupContent>
|
|
108
108
|
<SidebarMenu :class="cn('gap-3', props.compact && 'gap-2')">
|
|
109
109
|
<SidebarMenuItem v-for="item in section.items" :key="item.id">
|
|
110
|
-
<SidebarMenuButton as-child :is-active="item.active" :class="cn('group h-auto min-h-12 rounded border border-
|
|
110
|
+
<SidebarMenuButton as-child :is-active="item.active" :class="cn('group/nav relative h-auto min-h-12 overflow-hidden rounded border border-border px-3 py-2.5 text-muted-foreground [transition:color_150ms,background-color_150ms,border-color_150ms,scale_300ms_var(--ease-spring)] hover:border-border-strong hover:bg-accent hover:text-foreground active:scale-[0.98] data-[active=true]:border-border-strong data-[active=true]:bg-accent data-[active=true]:text-foreground sm:px-4 sm:py-3', 'before:absolute before:inset-y-2 before:left-0 before:w-[3px] before:origin-center before:scale-y-0 before:rounded-r-full before:bg-primary before:transition-transform before:duration-[420ms] before:ease-spring data-[active=true]:before:scale-y-100', item.description ? 'items-start' : 'items-center')">
|
|
111
111
|
<component :is="props.sidebarLinkComponent" v-bind="getSidebarItemLinkProps(item)">
|
|
112
112
|
<!-- Icon -->
|
|
113
|
-
<HugeiconsIcon v-if="item.icon" :icon="item.icon" :stroke-width="1.8" :class="cn('shrink-0 opacity-90 transition-opacity duration-
|
|
113
|
+
<HugeiconsIcon v-if="item.icon" :icon="item.icon" :stroke-width="1.8" :class="cn('shrink-0 opacity-90 transition-[opacity,translate,color] duration-300 ease-spring group-hover/nav:translate-x-0.5 group-hover/nav:opacity-100 group-data-[active=true]/nav:text-primary', item.description ? 'mt-0.5 size-5 sm:h-5 sm:w-5' : 'size-5 self-center sm:h-6 sm:w-6')" />
|
|
114
114
|
|
|
115
115
|
<!-- Label and optional description -->
|
|
116
116
|
<div :class="cn('min-w-0 flex-1 text-left leading-tight', item.description ? 'grid' : 'flex items-center')">
|
|
@@ -146,7 +146,7 @@ const getSidebarItemLinkProps = (item: NonNullable<typeof props.sidebarSections>
|
|
|
146
146
|
<BackgroundGrid v-if="props.showBackground" />
|
|
147
147
|
|
|
148
148
|
<!-- Topbar -->
|
|
149
|
-
<header :class="cn('sticky top-0 z-20 flex h-16 shrink-0 items-center gap-2 border-b border-sidebar-border bg-sidebar px-4 backdrop-blur', props.topbarClass)">
|
|
149
|
+
<header :class="cn('sticky top-0 z-20 flex h-16 shrink-0 items-center gap-2 border-b border-sidebar-border bg-sidebar/80 px-4 backdrop-blur-md backdrop-saturate-150', props.topbarClass)">
|
|
150
150
|
<!-- Sidebar trigger -->
|
|
151
151
|
<SidebarTrigger class="-ml-1" />
|
|
152
152
|
|
|
@@ -43,19 +43,19 @@ const resolvedDescription = computed(() => props.description
|
|
|
43
43
|
<Card class="flex flex-col items-center justify-center px-4 py-8 text-center md:py-12">
|
|
44
44
|
<CardContent class="flex flex-col items-center justify-center p-0! text-center">
|
|
45
45
|
<!-- Icon -->
|
|
46
|
-
<div class="flex items-center justify-center text-4xl text-
|
|
47
|
-
<HugeiconsIcon :icon="props.icon" class="size-10" />
|
|
46
|
+
<div class="flex items-center justify-center text-4xl text-muted-foreground opacity-40">
|
|
47
|
+
<HugeiconsIcon :icon="props.icon" class="size-10 animate-uv-float" />
|
|
48
48
|
</div>
|
|
49
49
|
|
|
50
50
|
<!-- Title -->
|
|
51
51
|
<component :is="`h${props.level}`"
|
|
52
52
|
v-if="resolvedTitle"
|
|
53
|
-
class="text-sm font-bold text-
|
|
53
|
+
class="text-sm font-bold text-foreground md:text-lg">
|
|
54
54
|
{{ resolvedTitle }}
|
|
55
55
|
</component>
|
|
56
56
|
|
|
57
57
|
<!-- Description -->
|
|
58
|
-
<p v-if="resolvedDescription" class="max-w-md text-xs text-
|
|
58
|
+
<p v-if="resolvedDescription" class="max-w-md text-xs text-muted-foreground md:text-sm">
|
|
59
59
|
{{ resolvedDescription }}
|
|
60
60
|
</p>
|
|
61
61
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { ArrowLeft01Icon } from '@hugeicons/core-free-icons';
|
|
3
3
|
import { HugeiconsIcon } from '@hugeicons/vue';
|
|
4
4
|
import { computed, type HTMLAttributes } from 'vue';
|
|
5
|
+
import { useI18n } from 'vue-i18n';
|
|
5
6
|
import BackgroundGrid from '../background-grid/BackgroundGrid.vue';
|
|
6
7
|
import { Button } from '../ui/button';
|
|
7
8
|
import { Card, CardContent, CardFooter } from '../ui/card';
|
|
@@ -22,10 +23,8 @@ const props = withDefaults(defineProps<{
|
|
|
22
23
|
footerClass?: HTMLAttributes['class'];
|
|
23
24
|
}>(), {
|
|
24
25
|
statusCode: 500,
|
|
25
|
-
label: 'Error',
|
|
26
26
|
title: undefined,
|
|
27
27
|
message: undefined,
|
|
28
|
-
actionLabel: 'Go back',
|
|
29
28
|
showBackground: true,
|
|
30
29
|
showDefaultAction: true,
|
|
31
30
|
class: undefined,
|
|
@@ -39,23 +38,26 @@ const emit = defineEmits<{
|
|
|
39
38
|
action: [];
|
|
40
39
|
}>();
|
|
41
40
|
|
|
42
|
-
const
|
|
41
|
+
const { t } = useI18n();
|
|
42
|
+
const resolvedStatusCode = computed(() => String(props.statusCode || 500));
|
|
43
|
+
const resolvedLabel = computed(() => props.label || t('uiVintage.messageDialog.error'));
|
|
44
|
+
const resolvedActionLabel = computed(() => props.actionLabel || t('uiVintage.buttons.goBack'));
|
|
43
45
|
|
|
44
|
-
// Resolve the heading copy
|
|
46
|
+
// Resolve the heading copy
|
|
45
47
|
const resolvedTitle = computed(() => {
|
|
46
48
|
if (props.title) return props.title;
|
|
47
|
-
if (resolvedStatusCode.value === '404') return '
|
|
48
|
-
return '
|
|
49
|
+
if (resolvedStatusCode.value === '404') return t('uiVintage.errorPage.notFound.title');
|
|
50
|
+
return t('uiVintage.errorPage.unexpected.title');
|
|
49
51
|
});
|
|
50
52
|
|
|
51
|
-
// Resolve the supporting message
|
|
53
|
+
// Resolve the supporting message
|
|
52
54
|
const resolvedMessage = computed(() => {
|
|
53
55
|
if (props.message) return props.message;
|
|
54
|
-
if (resolvedStatusCode.value === '404') return '
|
|
55
|
-
return '
|
|
56
|
+
if (resolvedStatusCode.value === '404') return t('uiVintage.errorPage.notFound.message');
|
|
57
|
+
return t('uiVintage.errorPage.unexpected.message');
|
|
56
58
|
});
|
|
57
59
|
|
|
58
|
-
// Emit the default action
|
|
60
|
+
// Emit the default action
|
|
59
61
|
const handleAction = () => {
|
|
60
62
|
emit('action');
|
|
61
63
|
};
|
|
@@ -83,8 +85,8 @@ const handleAction = () => {
|
|
|
83
85
|
<!-- Error copy -->
|
|
84
86
|
<div>
|
|
85
87
|
<!-- Status code -->
|
|
86
|
-
<div class="text-sm font-semibold uppercase tracking-[0.24em] text-
|
|
87
|
-
{{
|
|
88
|
+
<div class="text-sm font-semibold uppercase tracking-[0.24em] text-primary">
|
|
89
|
+
{{ resolvedLabel }} {{ resolvedStatusCode }}
|
|
88
90
|
</div>
|
|
89
91
|
|
|
90
92
|
<!-- Title -->
|
|
@@ -93,7 +95,7 @@ const handleAction = () => {
|
|
|
93
95
|
</h1>
|
|
94
96
|
|
|
95
97
|
<!-- Message -->
|
|
96
|
-
<p class="text-sm leading-7 text-
|
|
98
|
+
<p class="text-sm leading-7 text-muted-foreground sm:text-base mt-4">
|
|
97
99
|
{{ resolvedMessage }}
|
|
98
100
|
</p>
|
|
99
101
|
</div>
|
|
@@ -104,7 +106,7 @@ const handleAction = () => {
|
|
|
104
106
|
<slot name="actions" :on-action="handleAction">
|
|
105
107
|
<Button v-if="props.showDefaultAction" variant="primary" @click="handleAction">
|
|
106
108
|
<HugeiconsIcon :icon="ArrowLeft01Icon" :stroke-width="1.8" class="size-4" />
|
|
107
|
-
{{
|
|
109
|
+
{{ resolvedActionLabel }}
|
|
108
110
|
</Button>
|
|
109
111
|
</slot>
|
|
110
112
|
</CardFooter>
|
|
@@ -28,7 +28,7 @@ const props = withDefaults(defineProps<{
|
|
|
28
28
|
<div class="flex w-full flex-1 items-center justify-between text-center sm:w-auto sm:text-left">
|
|
29
29
|
<div class="flex flex-col w-full gap-2 sm:gap-1">
|
|
30
30
|
<!-- Title -->
|
|
31
|
-
<span class="text-base font-bold text-
|
|
31
|
+
<span class="text-base font-bold text-foreground">
|
|
32
32
|
{{ props.title }}
|
|
33
33
|
</span>
|
|
34
34
|
|
|
@@ -47,8 +47,9 @@ const props = withDefaults(defineProps<{
|
|
|
47
47
|
</div>
|
|
48
48
|
</nav>
|
|
49
49
|
|
|
50
|
+
<!-- Progress bar -->
|
|
50
51
|
<div v-if="props.showProgress" class="absolute inset-x-0 bottom-0 translate-y-full">
|
|
51
|
-
<BlogProgressBar
|
|
52
|
+
<BlogProgressBar />
|
|
52
53
|
</div>
|
|
53
54
|
</header>
|
|
54
55
|
</template>
|
|
@@ -22,8 +22,8 @@ const emits = defineEmits<{
|
|
|
22
22
|
}>();
|
|
23
23
|
|
|
24
24
|
const { t } = useI18n();
|
|
25
|
-
const resolvedText = computed(() => props.text || t('uiVintage.buttons.loadMore')
|
|
26
|
-
const resolvedLoadingText = computed(() => props.loadingText || t('uiVintage.buttons.loading')
|
|
25
|
+
const resolvedText = computed(() => props.text || t('uiVintage.buttons.loadMore'));
|
|
26
|
+
const resolvedLoadingText = computed(() => props.loadingText || t('uiVintage.buttons.loading'));
|
|
27
27
|
|
|
28
28
|
// Handle click event
|
|
29
29
|
const handleClick = () => {
|
|
@@ -20,8 +20,8 @@ const props = withDefaults(defineProps<{
|
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
const { t } = useI18n();
|
|
23
|
-
const resolvedTitle = computed(() => props.title || t('uiVintage.common.loading.title')
|
|
24
|
-
const resolvedDescription = computed(() => props.description || t('uiVintage.common.loading.description')
|
|
23
|
+
const resolvedTitle = computed(() => props.title || t('uiVintage.common.loading.title'));
|
|
24
|
+
const resolvedDescription = computed(() => props.description || t('uiVintage.common.loading.description'));
|
|
25
25
|
</script>
|
|
26
26
|
|
|
27
27
|
<template>
|
|
@@ -35,12 +35,12 @@ const resolvedDescription = computed(() => props.description || t('uiVintage.com
|
|
|
35
35
|
<!-- Title -->
|
|
36
36
|
<component :is="`h${props.level}`"
|
|
37
37
|
v-if="resolvedTitle"
|
|
38
|
-
class="text-sm font-bold text-
|
|
38
|
+
class="text-sm font-bold text-foreground md:text-lg">
|
|
39
39
|
{{ resolvedTitle }}
|
|
40
40
|
</component>
|
|
41
41
|
|
|
42
42
|
<!-- Description -->
|
|
43
|
-
<p v-if="resolvedDescription" class="max-w-md text-xs text-
|
|
43
|
+
<p v-if="resolvedDescription" class="max-w-md text-xs text-muted-foreground md:text-sm">
|
|
44
44
|
{{ resolvedDescription }}
|
|
45
45
|
</p>
|
|
46
46
|
|
|
@@ -36,11 +36,11 @@ const defaultMessageIcon = computed(() => {
|
|
|
36
36
|
// Resolved container classes for the message icon
|
|
37
37
|
const messageIconClasses = computed(() => {
|
|
38
38
|
const current = currentDialog.value;
|
|
39
|
-
if (!current) return 'border-(--border) bg-
|
|
39
|
+
if (!current) return 'border-(--border) bg-surface';
|
|
40
40
|
if (current.options.type === 'error') return 'border-red-200 bg-red-50 dark:border-red-900/50 dark:bg-red-950/30';
|
|
41
41
|
if (current.options.type === 'warning') return 'border-amber-200 bg-amber-50 dark:border-amber-900/50 dark:bg-amber-950/30';
|
|
42
42
|
if (current.options.type === 'success') return 'border-green-200 bg-green-50 dark:border-green-900/50 dark:bg-green-950/30';
|
|
43
|
-
return 'border-(--border) bg-
|
|
43
|
+
return 'border-(--border) bg-surface';
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
// Resolved glyph color classes
|
|
@@ -70,8 +70,8 @@ const handleOpenChange = (open: boolean) => {
|
|
|
70
70
|
<div class="flex flex-col gap-4 sm:flex-row sm:items-start">
|
|
71
71
|
<!-- Dialog icon -->
|
|
72
72
|
<div class="flex size-12 shrink-0 self-center items-center justify-center rounded border sm:size-10 sm:self-start" :class="messageIconClasses">
|
|
73
|
-
<HugeiconsIcon v-if="currentDialog.options.icon" :icon="currentDialog.options.icon" :stroke-width="1.8" class="size-6" :class="messageGlyphClasses" />
|
|
74
|
-
<HugeiconsIcon v-else :icon="defaultMessageIcon" :stroke-width="1.8" class="size-6" :class="messageGlyphClasses" />
|
|
73
|
+
<HugeiconsIcon v-if="currentDialog.options.icon" :icon="currentDialog.options.icon" :stroke-width="1.8" class="size-6 animate-uv-pop [animation-delay:140ms]" :class="messageGlyphClasses" />
|
|
74
|
+
<HugeiconsIcon v-else :icon="defaultMessageIcon" :stroke-width="1.8" class="size-6 animate-uv-pop [animation-delay:140ms]" :class="messageGlyphClasses" />
|
|
75
75
|
</div>
|
|
76
76
|
|
|
77
77
|
<!-- Dialog header -->
|