@brumaombra/ui-vintage 0.7.6 → 0.7.8
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/package.json +2 -1
- package/src/components/blog/BlogFAQSection.vue +8 -44
- package/src/components/blog/TableOfContents.vue +12 -50
- package/src/components/dashboard-shell/DashboardShell.vue +10 -5
- package/src/components/landing/landing-footer/LandingFooter.vue +4 -2
- package/src/components/theme-selector/ThemeSelector.vue +4 -4
- package/src/components/ui/accordion/Accordion.vue +61 -0
- package/src/components/ui/accordion/index.ts +1 -0
- package/src/components/ui/select/SelectContent.vue +1 -1
- package/src/components/ui/sidebar/SidebarProvider.vue +1 -1
- package/src/components/ui/sidebar/index.ts +2 -2
- package/src/components/ui/tabs/TabsTrigger.vue +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brumaombra/ui-vintage",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "Source-published Nuxt UI runtime with shared theme tokens and built-in Nuxt integrations.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Mauro Brambilla",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"./style.css": "./src/styles.css",
|
|
38
38
|
"./alert": "./src/components/ui/alert/index.ts",
|
|
39
39
|
"./alert-dialog": "./src/components/ui/alert-dialog/index.ts",
|
|
40
|
+
"./accordion": "./src/components/ui/accordion/index.ts",
|
|
40
41
|
"./background-grid": "./src/components/background-grid/index.ts",
|
|
41
42
|
"./badge": "./src/components/ui/badge/index.ts",
|
|
42
43
|
"./blog": "./src/components/blog/index.ts",
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import {
|
|
2
|
+
import { computed } from 'vue';
|
|
3
3
|
import { useI18n } from 'vue-i18n';
|
|
4
|
-
import {
|
|
5
|
-
import { HugeiconsIcon } from '@hugeicons/vue';
|
|
6
|
-
import { Card, CardContent } from '../ui/card';
|
|
4
|
+
import { Accordion } from '@brumaombra/ui-vintage/accordion';
|
|
7
5
|
import BlogSectionTitle from './BlogSectionTitle.vue';
|
|
8
6
|
|
|
9
7
|
// Props
|
|
@@ -12,23 +10,7 @@ const props = defineProps({
|
|
|
12
10
|
});
|
|
13
11
|
|
|
14
12
|
const { t } = useI18n();
|
|
15
|
-
const expandedItems = ref({});
|
|
16
13
|
const hasValidFAQs = computed(() => props.faqs && props.faqs.length > 0);
|
|
17
|
-
|
|
18
|
-
// Toggle expanded state
|
|
19
|
-
const toggleItem = index => {
|
|
20
|
-
expandedItems.value[index] = !expandedItems.value[index];
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
// Check if item is expanded
|
|
24
|
-
const isExpanded = index => {
|
|
25
|
-
return expandedItems.value[index] || false;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// Auto-open first FAQ for better UX
|
|
29
|
-
if (hasValidFAQs.value) {
|
|
30
|
-
expandedItems.value[0] = true;
|
|
31
|
-
}
|
|
32
14
|
</script>
|
|
33
15
|
|
|
34
16
|
<template>
|
|
@@ -37,35 +19,17 @@ if (hasValidFAQs.value) {
|
|
|
37
19
|
<BlogSectionTitle :title="t('uiVintage.blog.faq.title')" />
|
|
38
20
|
|
|
39
21
|
<!-- Description -->
|
|
40
|
-
<p class="text-base md:text-lg text-
|
|
22
|
+
<p class="text-base md:text-lg text-(--text-secondary-light) dark:text-(--text-secondary-dark) mb-8">
|
|
41
23
|
{{ t('uiVintage.blog.faq.description') }}
|
|
42
24
|
</p>
|
|
43
25
|
|
|
44
26
|
<!-- FAQ Items -->
|
|
45
27
|
<div class="space-y-4">
|
|
46
|
-
<
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<h3 class="text-sm md:!text-base font-semibold text-[var(--text-primary-light)] dark:text-[var(--text-primary-dark)] text-left">
|
|
52
|
-
{{ faq.question }}
|
|
53
|
-
</h3>
|
|
54
|
-
|
|
55
|
-
<!-- Toggle icon -->
|
|
56
|
-
<div class="flex-shrink-0 w-8 h-8 flex items-center justify-center rounded bg-[var(--bg-card-light)] dark:bg-[var(--bg-card-dark)] border border-[var(--border-light)] dark:border-[var(--border-dark)] transition-transform duration-300" :class="{ 'rotate-180': isExpanded(index) }">
|
|
57
|
-
<HugeiconsIcon :icon="ArrowDown01Icon" class="size-4 text-[var(--text-secondary-light)] dark:text-[var(--text-secondary-dark)]" />
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
|
|
61
|
-
<!-- Answer -->
|
|
62
|
-
<div class="overflow-hidden transition-all duration-300 ease-in-out" :class="isExpanded(index) ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'">
|
|
63
|
-
<p class="px-5 pb-5 text-xs md:text-sm text-[var(--text-secondary-light)] dark:text-[var(--text-secondary-dark)] leading-relaxed">
|
|
64
|
-
{{ faq.answer }}
|
|
65
|
-
</p>
|
|
66
|
-
</div>
|
|
67
|
-
</CardContent>
|
|
68
|
-
</Card>
|
|
28
|
+
<Accordion v-for="(faq, index) in props.faqs" :key="index" :title="faq.question" :initially-expanded="index === 0">
|
|
29
|
+
<p class="text-xs md:text-sm text-(--text-secondary-light) dark:text-(--text-secondary-dark) leading-relaxed">
|
|
30
|
+
{{ faq.answer }}
|
|
31
|
+
</p>
|
|
32
|
+
</Accordion>
|
|
69
33
|
</div>
|
|
70
34
|
</div>
|
|
71
35
|
</template>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { computed
|
|
2
|
+
import { computed } from 'vue';
|
|
3
3
|
import { useI18n } from 'vue-i18n';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { Card, CardContent } from '../ui/card';
|
|
4
|
+
import { Bookmark01Icon } from '@hugeicons/core-free-icons';
|
|
5
|
+
import { Accordion } from '../ui/accordion';
|
|
7
6
|
|
|
8
7
|
// Props
|
|
9
8
|
const props = defineProps({
|
|
@@ -11,8 +10,6 @@ const props = defineProps({
|
|
|
11
10
|
});
|
|
12
11
|
|
|
13
12
|
const { t } = useI18n();
|
|
14
|
-
const isExpanded = ref(false);
|
|
15
|
-
const contentBodyRef = ref(null);
|
|
16
13
|
|
|
17
14
|
// Create the headings list
|
|
18
15
|
const headings = computed(() => {
|
|
@@ -50,27 +47,17 @@ const scrollToHeading = id => {
|
|
|
50
47
|
}
|
|
51
48
|
};
|
|
52
49
|
|
|
53
|
-
// Toggle expanded state
|
|
54
|
-
const toggleExpanded = () => {
|
|
55
|
-
isExpanded.value = !isExpanded.value;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// Get the current content height for the expand/collapse animation
|
|
59
|
-
const contentHeight = computed(() => {
|
|
60
|
-
return contentBodyRef.value?.scrollHeight ?? 0;
|
|
61
|
-
});
|
|
62
|
-
|
|
63
50
|
// Get classes for heading button
|
|
64
51
|
const getHeadingButtonClasses = heading => {
|
|
65
52
|
// Base classes for all titles
|
|
66
|
-
const baseClasses = 'block w-full text-left px-0 py-2 md:px-3 md:py-2 rounded transition-all duration-200 hover:bg-
|
|
53
|
+
const baseClasses = 'block w-full text-left px-0 py-2 md:px-3 md:py-2 rounded transition-all duration-200 hover:bg-(--bg-selected-light) dark:hover:bg-(--bg-selected-dark) cursor-pointer';
|
|
67
54
|
|
|
68
55
|
// Add classes based on heading level
|
|
69
56
|
let levelClasses = '';
|
|
70
57
|
if (heading.level === 2) {
|
|
71
|
-
levelClasses = 'text-
|
|
58
|
+
levelClasses = 'text-(--text-primary-light) dark:text-(--text-primary-dark) font-semibold text-xs md:text-sm';
|
|
72
59
|
} else {
|
|
73
|
-
levelClasses = 'text-
|
|
60
|
+
levelClasses = 'text-(--text-secondary-light) dark:text-(--text-secondary-dark) !pl-6 text-xs md:text-sm';
|
|
74
61
|
}
|
|
75
62
|
|
|
76
63
|
// Return combined classes
|
|
@@ -79,36 +66,11 @@ const getHeadingButtonClasses = heading => {
|
|
|
79
66
|
</script>
|
|
80
67
|
|
|
81
68
|
<template>
|
|
82
|
-
<
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
<div class="flex items-center gap-3 min-w-0">
|
|
87
|
-
<!-- Icon -->
|
|
88
|
-
<div class="flex items-center justify-center w-8 h-8 md:!w-10 md:!h-10 bg-[var(--bg-card-light)] dark:bg-[var(--bg-card-dark)] border border-[var(--border-light)] dark:border-[var(--border-dark)] rounded-none flex-shrink-0">
|
|
89
|
-
<HugeiconsIcon :icon="Bookmark01Icon" class="size-4 text-[var(--text-secondary-light)] dark:text-[var(--text-secondary-dark)]" />
|
|
90
|
-
</div>
|
|
91
|
-
|
|
92
|
-
<!-- Title -->
|
|
93
|
-
<span class="text-sm md:!text-base font-semibold text-[var(--text-primary-light)] dark:text-[var(--text-primary-dark)]">
|
|
94
|
-
{{ t('uiVintage.blog.tableOfContents') }}
|
|
95
|
-
</span>
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
<!-- Expand/Collapse icon -->
|
|
99
|
-
<div class="flex-shrink-0 w-8 h-8 flex items-center justify-center rounded bg-[var(--bg-card-light)] dark:bg-[var(--bg-card-dark)] border border-[var(--border-light)] dark:border-[var(--border-dark)] transition-transform duration-300" :class="{ 'rotate-180': isExpanded }">
|
|
100
|
-
<HugeiconsIcon :icon="ArrowDown01Icon" class="size-4 text-[var(--text-secondary-light)] dark:text-[var(--text-secondary-dark)]" />
|
|
101
|
-
</div>
|
|
69
|
+
<Accordion v-if="headings.length > 0" :title="t('uiVintage.blog.tableOfContents')" :icon="Bookmark01Icon">
|
|
70
|
+
<nav class="space-y-1">
|
|
71
|
+
<button v-for="heading in headings" :key="heading.id" @click="scrollToHeading(heading.id)" :class="getHeadingButtonClasses(heading)">
|
|
72
|
+
{{ heading.text }}
|
|
102
73
|
</button>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
<div class="overflow-hidden transition-[height,opacity] duration-300 ease-in-out" :style="{ height: isExpanded ? `${contentHeight}px` : '0px' }" :class="isExpanded ? 'opacity-100' : 'opacity-0'">
|
|
106
|
-
<nav ref="contentBodyRef" class="px-5 pb-5 space-y-1">
|
|
107
|
-
<button v-for="heading in headings" :key="heading.id" @click="scrollToHeading(heading.id)" :class="getHeadingButtonClasses(heading)">
|
|
108
|
-
{{ heading.text }}
|
|
109
|
-
</button>
|
|
110
|
-
</nav>
|
|
111
|
-
</div>
|
|
112
|
-
</CardContent>
|
|
113
|
-
</Card>
|
|
74
|
+
</nav>
|
|
75
|
+
</Accordion>
|
|
114
76
|
</template>
|
|
@@ -3,6 +3,7 @@ import { NuxtImg } from "#components";
|
|
|
3
3
|
import type { Component, HTMLAttributes } from "vue";
|
|
4
4
|
import { HugeiconsIcon } from "@hugeicons/vue";
|
|
5
5
|
import BackgroundGrid from "../background-grid/BackgroundGrid.vue";
|
|
6
|
+
import { ThemeSelector } from "../theme-selector";
|
|
6
7
|
import { Separator } from "../ui/separator";
|
|
7
8
|
import {
|
|
8
9
|
Sidebar,
|
|
@@ -117,7 +118,7 @@ const getSidebarItemLinkProps = (item: DashboardSidebarItem) => {
|
|
|
117
118
|
|
|
118
119
|
<!-- Sidebar sections -->
|
|
119
120
|
<SidebarContent v-if="props.sidebarSections.length">
|
|
120
|
-
<SidebarGroup v-for="section in props.sidebarSections" :key="section.id">
|
|
121
|
+
<SidebarGroup v-for="section in props.sidebarSections" :key="section.id" class="space-y-1">
|
|
121
122
|
<!-- Section label -->
|
|
122
123
|
<SidebarGroupLabel v-if="section.label">
|
|
123
124
|
{{ section.label }}
|
|
@@ -125,9 +126,9 @@ const getSidebarItemLinkProps = (item: DashboardSidebarItem) => {
|
|
|
125
126
|
|
|
126
127
|
<!-- Section content -->
|
|
127
128
|
<SidebarGroupContent>
|
|
128
|
-
<SidebarMenu class="gap-3">
|
|
129
|
+
<SidebarMenu :class="cn('gap-3', props.compact && 'gap-2')">
|
|
129
130
|
<SidebarMenuItem v-for="item in section.items" :key="item.id">
|
|
130
|
-
<SidebarMenuButton as-child :is-active="item.active" :class="cn('group h-auto min-h-12 rounded border border-
|
|
131
|
+
<SidebarMenuButton as-child :is-active="item.active" :class="cn('group h-auto min-h-12 rounded border border-(--border-light) px-3 py-2.5 text-(--text-secondary-light) transition-all duration-200 hover:border-(--border-hover-light) hover:bg-(--bg-selected-light) hover:text-(--text-primary-light) data-[active=true]:border-(--border-hover-light) data-[active=true]:bg-(--bg-selected-light) data-[active=true]:text-(--text-primary-light) dark:border-(--border-dark) dark:text-(--text-secondary-dark) dark:hover:border-(--border-hover-dark) dark:hover:bg-(--bg-selected-dark) dark:hover:text-(--text-primary-dark) dark:data-[active=true]:border-(--border-hover-dark) dark:data-[active=true]:bg-(--bg-selected-dark) dark:data-[active=true]:text-(--text-primary-dark) sm:px-4 sm:py-3', item.description ? 'items-start' : 'items-center')">
|
|
131
132
|
<component :is="props.sidebarLinkComponent" v-bind="getSidebarItemLinkProps(item)">
|
|
132
133
|
<!-- Icon -->
|
|
133
134
|
<HugeiconsIcon v-if="item.icon" :icon="item.icon" :stroke-width="1.8" :class="cn('shrink-0 opacity-90 transition-opacity duration-200 group-hover:opacity-100', item.description ? 'mt-0.5 size-5 sm:h-5 sm:w-5' : 'size-5 self-center sm:h-6 sm:w-6')" />
|
|
@@ -151,8 +152,12 @@ const getSidebarItemLinkProps = (item: DashboardSidebarItem) => {
|
|
|
151
152
|
</SidebarContent>
|
|
152
153
|
|
|
153
154
|
<!-- Sidebar footer -->
|
|
154
|
-
<SidebarFooter
|
|
155
|
-
<slot name="sidebar-footer"
|
|
155
|
+
<SidebarFooter class="border-t border-sidebar-border">
|
|
156
|
+
<slot name="sidebar-footer">
|
|
157
|
+
<div class="flex items-center gap-2">
|
|
158
|
+
<ThemeSelector />
|
|
159
|
+
</div>
|
|
160
|
+
</slot>
|
|
156
161
|
</SidebarFooter>
|
|
157
162
|
</Sidebar>
|
|
158
163
|
|
|
@@ -24,6 +24,7 @@ export interface LandingFooterSection {
|
|
|
24
24
|
interface LandingFooterProps {
|
|
25
25
|
appName: string;
|
|
26
26
|
appLogo?: string;
|
|
27
|
+
appLinkTo?: string;
|
|
27
28
|
appDescription?: string;
|
|
28
29
|
sections?: LandingFooterSection[];
|
|
29
30
|
linkComponent?: Component | string;
|
|
@@ -40,6 +41,7 @@ interface LandingFooterProps {
|
|
|
40
41
|
|
|
41
42
|
// Props
|
|
42
43
|
const props = withDefaults(defineProps<LandingFooterProps>(), {
|
|
44
|
+
appLinkTo: "/",
|
|
43
45
|
appDescription: "",
|
|
44
46
|
sections: () => [],
|
|
45
47
|
linkComponent: "a",
|
|
@@ -79,10 +81,10 @@ const getLinkProps = (link: LandingFooterLink) => {
|
|
|
79
81
|
<!-- Brand section -->
|
|
80
82
|
<div :class="cn('max-w-md flex-1', props.brandClass)">
|
|
81
83
|
<!-- App logo and name -->
|
|
82
|
-
<
|
|
84
|
+
<a :href="props.appLinkTo" class="mb-4 inline-flex items-center gap-2 text-lg font-semibold tracking-tight text-foreground transition-opacity hover:opacity-80">
|
|
83
85
|
<NuxtImg v-if="props.appLogo" :src="props.appLogo" :alt="`${props.appName} logo`" width="32" height="32" :sizes="{ 320: '32px', 1280: '32px' }" loading="lazy" decoding="async" class="size-8 shrink-0 object-contain" />
|
|
84
86
|
<span>{{ props.appName }}</span>
|
|
85
|
-
</
|
|
87
|
+
</a>
|
|
86
88
|
|
|
87
89
|
<!-- App description -->
|
|
88
90
|
<p v-if="props.appDescription" class="max-w-sm text-xs md:text-sm leading-relaxed text-muted-foreground">
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
|
3
3
|
import { useI18n } from 'vue-i18n';
|
|
4
|
-
import {
|
|
4
|
+
import { LaptopIcon, Moon01Icon, Sun01Icon, Tick02Icon } from '@hugeicons/core-free-icons';
|
|
5
5
|
import { HugeiconsIcon } from '@hugeicons/vue';
|
|
6
6
|
import { Button } from '../ui/button';
|
|
7
7
|
import { Command, CommandGroup, CommandItem, CommandList } from '../ui/command';
|
|
@@ -18,9 +18,9 @@ const getThemeIcon = (theme: string) => {
|
|
|
18
18
|
if (theme === 'light') {
|
|
19
19
|
return Sun01Icon;
|
|
20
20
|
} else if (theme === 'dark') {
|
|
21
|
-
return
|
|
21
|
+
return Moon01Icon;
|
|
22
22
|
} else {
|
|
23
|
-
return
|
|
23
|
+
return LaptopIcon;
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
|
|
@@ -112,7 +112,7 @@ onUnmounted(() => {
|
|
|
112
112
|
</PopoverTrigger>
|
|
113
113
|
|
|
114
114
|
<!-- Theme options -->
|
|
115
|
-
<PopoverContent side="bottom" align="end" :side-offset="8" class="w-44
|
|
115
|
+
<PopoverContent side="bottom" align="end" :side-offset="8" class="w-44 p-0!">
|
|
116
116
|
<Command :model-value="currentTheme">
|
|
117
117
|
<CommandList>
|
|
118
118
|
<CommandGroup :heading="t('uiVintage.theme.title')">
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "vue";
|
|
3
|
+
import { ref } from "vue";
|
|
4
|
+
import { ArrowDown01Icon } from "@hugeicons/core-free-icons";
|
|
5
|
+
import { HugeiconsIcon } from "@hugeicons/vue";
|
|
6
|
+
import { Card, CardContent } from "@brumaombra/ui-vintage/card";
|
|
7
|
+
|
|
8
|
+
type HugeiconsIconDefinition = readonly (readonly [string, { readonly [key: string]: string | number }])[];
|
|
9
|
+
|
|
10
|
+
interface AccordionProps {
|
|
11
|
+
title: string;
|
|
12
|
+
initiallyExpanded?: boolean;
|
|
13
|
+
icon?: HugeiconsIconDefinition | null;
|
|
14
|
+
iconClass?: HTMLAttributes["class"];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Props
|
|
18
|
+
const props = withDefaults(defineProps<AccordionProps>(), {
|
|
19
|
+
initiallyExpanded: false
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const expanded = ref(props.initiallyExpanded);
|
|
23
|
+
|
|
24
|
+
// Toggle expanded state
|
|
25
|
+
const toggleExpanded = () => {
|
|
26
|
+
expanded.value = !expanded.value;
|
|
27
|
+
};
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<template>
|
|
31
|
+
<Card class="p-0! overflow-hidden">
|
|
32
|
+
<CardContent class="p-0! gap-0">
|
|
33
|
+
<!-- Header -->
|
|
34
|
+
<div class="flex items-center justify-between p-5 gap-4 text-left cursor-pointer" @click="toggleExpanded">
|
|
35
|
+
<div class="flex items-center gap-3 min-w-0">
|
|
36
|
+
<!-- Icon -->
|
|
37
|
+
<div v-if="props.icon" class="flex h-8 w-8 shrink-0 items-center justify-center rounded bg-(--bg-card-light) border border-(--border-light) dark:bg-(--bg-card-dark) dark:border-(--border-dark) md:h-10 md:w-10">
|
|
38
|
+
<HugeiconsIcon :icon="props.icon" :class="['size-4 text-(--text-secondary-light) dark:text-(--text-secondary-dark)', props.iconClass]" />
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<!-- Title -->
|
|
42
|
+
<div class="text-sm md:text-base! font-semibold text-(--text-primary-light) dark:text-(--text-primary-dark) text-left">
|
|
43
|
+
{{ props.title }}
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<!-- Toggle icon -->
|
|
48
|
+
<div class="shrink-0 w-8 h-8 flex items-center justify-center rounded bg-(--bg-card-light) dark:bg-(--bg-card-dark) border border-(--border-light) dark:border-(--border-dark) transition-transform duration-300 cursor-pointer" :class="{ 'rotate-180': expanded }">
|
|
49
|
+
<HugeiconsIcon :icon="ArrowDown01Icon" class="size-4 text-(--text-secondary-light) dark:text-(--text-secondary-dark)" />
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<!-- Content -->
|
|
54
|
+
<div :class="['grid transition-all duration-300 ease-in-out', expanded ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0']">
|
|
55
|
+
<div :class="['overflow-hidden px-5 transition-[padding] duration-300 ease-in-out', expanded ? 'pb-5' : 'pb-0']">
|
|
56
|
+
<slot />
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</CardContent>
|
|
60
|
+
</Card>
|
|
61
|
+
</template>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Accordion } from "./Accordion.vue"
|
|
@@ -34,7 +34,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
|
34
34
|
<template>
|
|
35
35
|
<SelectPortal>
|
|
36
36
|
<SelectContent data-slot="select-content" v-bind="{ ...$attrs, ...forwarded }" :class="cn(
|
|
37
|
-
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--reka-select-content-available-height) min-w-
|
|
37
|
+
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--reka-select-content-available-height) min-w-32 overflow-x-hidden overflow-y-auto rounded border border-border transition-colors duration-300 ease-in-out max-sm:w-(--reka-select-trigger-width) max-sm:min-w-(--reka-select-trigger-width)',
|
|
38
38
|
position === 'popper'
|
|
39
39
|
&& 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
|
|
40
40
|
props.class,
|
|
@@ -72,7 +72,7 @@ provideSidebarContext({
|
|
|
72
72
|
<div data-slot="sidebar-wrapper" :style="{
|
|
73
73
|
'--sidebar-width': SIDEBAR_WIDTH,
|
|
74
74
|
'--sidebar-width-icon': SIDEBAR_WIDTH_ICON,
|
|
75
|
-
}" :class="cn('group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full', props.class)" v-bind="$attrs">
|
|
75
|
+
}" :data-compact="props.compact ? 'true' : 'false'" :class="cn('group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full', props.class)" v-bind="$attrs">
|
|
76
76
|
<slot />
|
|
77
77
|
</div>
|
|
78
78
|
</TooltipProvider>
|
|
@@ -51,8 +51,8 @@ export const sidebarMenuButtonVariants: (props?: SidebarMenuButtonVariants & Cla
|
|
|
51
51
|
"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]",
|
|
52
52
|
},
|
|
53
53
|
size: {
|
|
54
|
-
default: "min-h-8 text-sm group-data-[compact=true]/sidebar-wrapper:min-h-7 group-data-[compact=true]/sidebar-wrapper:text-xs",
|
|
55
|
-
sm: "min-h-7 text-xs group-data-[compact=true]/sidebar-wrapper:min-h-6",
|
|
54
|
+
default: "min-h-8 text-sm group-data-[compact=true]/sidebar-wrapper:min-h-7 group-data-[compact=true]/sidebar-wrapper:text-xs group-data-[compact=true]/sidebar-wrapper:py-3",
|
|
55
|
+
sm: "min-h-7 text-xs group-data-[compact=true]/sidebar-wrapper:min-h-6 group-data-[compact=true]/sidebar-wrapper:py-2.5",
|
|
56
56
|
lg: "min-h-12 text-sm group-data-[compact=true]/sidebar-wrapper:min-h-10 group-data-[collapsible=icon]:p-0!",
|
|
57
57
|
},
|
|
58
58
|
},
|
|
@@ -16,7 +16,7 @@ const forwardedProps = useForwardProps(delegatedProps)
|
|
|
16
16
|
<TabsTrigger
|
|
17
17
|
data-slot="tabs-trigger"
|
|
18
18
|
:class="cn(
|
|
19
|
-
'text-muted-foreground hover:text-foreground focus-visible:outline-none inline-flex min-h-9 flex-1 cursor-pointer items-center justify-center gap-1.5 rounded
|
|
19
|
+
'text-muted-foreground hover:text-foreground focus-visible:outline-none inline-flex min-h-9 flex-1 cursor-pointer items-center justify-center gap-1.5 rounded border border-transparent bg-transparent px-4 py-2 text-sm font-semibold whitespace-nowrap transition-colors duration-300 ease-in-out disabled:pointer-events-none disabled:opacity-50 data-[state=active]:cursor-pointer data-[state=active]:border-(--button-primary-light) data-[state=active]:bg-gray-50 data-[state=active]:text-(--button-primary-light) data-[state=active]:font-semibold data-[state=active]:outline-1 data-[state=active]:outline-border data-[state=active]:outline-offset-0 data-[state=active]:shadow-none dark:data-[state=active]:border-(--button-primary-dark) dark:data-[state=active]:bg-(--bg-card-dark) dark:data-[state=active]:text-(--button-primary-dark) [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4',
|
|
20
20
|
props.class,
|
|
21
21
|
)"
|
|
22
22
|
v-bind="forwardedProps"
|