docs: add vertical Tabs example (#739)

* feat(docs): add vertical Tabs example and components for account/password management

* fix(TabsTrigger): wrap slot content in a span with truncate class for better text handling

* chore: build:registry
This commit is contained in:
Roman Hrynevych 2024-08-30 20:21:17 +03:00 committed by GitHub
parent 85b10641c2
commit f73e1ddaaf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 186 additions and 6 deletions

View File

@ -1053,6 +1053,13 @@ export const Index = {
component: () => import("../src/lib/registry/default/example/TabsDemo.vue").then((m) => m.default), component: () => import("../src/lib/registry/default/example/TabsDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/TabsDemo.vue"], files: ["../src/lib/registry/default/example/TabsDemo.vue"],
}, },
"TabsVerticalDemo": {
name: "TabsVerticalDemo",
type: "components:example",
registryDependencies: [],
component: () => import("../src/lib/registry/default/example/TabsVerticalDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/TabsVerticalDemo.vue"],
},
"TagsInputComboboxDemo": { "TagsInputComboboxDemo": {
name: "TagsInputComboboxDemo", name: "TagsInputComboboxDemo",
type: "components:example", type: "components:example",
@ -2538,6 +2545,13 @@ export const Index = {
component: () => import("../src/lib/registry/new-york/example/TabsDemo.vue").then((m) => m.default), component: () => import("../src/lib/registry/new-york/example/TabsDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/TabsDemo.vue"], files: ["../src/lib/registry/new-york/example/TabsDemo.vue"],
}, },
"TabsVerticalDemo": {
name: "TabsVerticalDemo",
type: "components:example",
registryDependencies: [],
component: () => import("../src/lib/registry/new-york/example/TabsVerticalDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/TabsVerticalDemo.vue"],
},
"TagsInputComboboxDemo": { "TagsInputComboboxDemo": {
name: "TagsInputComboboxDemo", name: "TagsInputComboboxDemo",
type: "components:example", type: "components:example",

View File

@ -39,3 +39,9 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
</Tabs> </Tabs>
</template> </template>
``` ```
## Examples
### Vertical
<ComponentPreview name="TabsVerticalDemo" />

View File

@ -0,0 +1,78 @@
<script setup lang="ts">
import { Button } from '@/lib/registry/default/ui/button'
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/lib/registry/default/ui/card'
import { Input } from '@/lib/registry/default/ui/input'
import { Label } from '@/lib/registry/default/ui/label'
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from '@/lib/registry/default/ui/tabs'
</script>
<template>
<Tabs default-value="account" class="w-[400px]" orientation="vertical">
<TabsList class="grid w-full grid-cols-1">
<TabsTrigger value="account">
Accounts
</TabsTrigger>
<TabsTrigger value="password">
Password
</TabsTrigger>
</TabsList>
<TabsContent value="account">
<Card>
<CardHeader>
<CardTitle>Account</CardTitle>
<CardDescription>
Make changes to your account here. Click save when you're done.
</CardDescription>
</CardHeader>
<CardContent class="space-y-2">
<div class="space-y-1">
<Label for="name">Name</Label>
<Input id="name" default-value="Pedro Duarte" />
</div>
<div class="space-y-1">
<Label for="username">Username</Label>
<Input id="username" default-value="@peduarte" />
</div>
</CardContent>
<CardFooter>
<Button>Save changes</Button>
</CardFooter>
</Card>
</TabsContent>
<TabsContent value="password">
<Card>
<CardHeader>
<CardTitle>Password</CardTitle>
<CardDescription>
Change your password here. After saving, you'll be logged out.
</CardDescription>
</CardHeader>
<CardContent class="space-y-2">
<div class="space-y-1">
<Label for="current">Current password</Label>
<Input id="current" type="password" />
</div>
<div class="space-y-1">
<Label for="new">New password</Label>
<Input id="new" type="password" />
</div>
</CardContent>
<CardFooter>
<Button>Save password</Button>
</CardFooter>
</Card>
</TabsContent>
</Tabs>
</template>

View File

@ -16,7 +16,7 @@ const delegatedProps = computed(() => {
<TabsList <TabsList
v-bind="delegatedProps" v-bind="delegatedProps"
:class="cn( :class="cn(
'inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground', 'inline-flex items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',
props.class, props.class,
)" )"
> >

View File

@ -22,6 +22,8 @@ const forwardedProps = useForwardProps(delegatedProps)
props.class, props.class,
)" )"
> >
<span class="truncate">
<slot /> <slot />
</span>
</TabsTrigger> </TabsTrigger>
</template> </template>

View File

@ -0,0 +1,78 @@
<script setup lang="ts">
import { Button } from '@/lib/registry/new-york/ui/button'
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/lib/registry/new-york/ui/card'
import { Input } from '@/lib/registry/new-york/ui/input'
import { Label } from '@/lib/registry/new-york/ui/label'
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from '@/lib/registry/new-york/ui/tabs'
</script>
<template>
<Tabs default-value="account" class="w-[400px]" orientation="vertical">
<TabsList class="grid w-full grid-cols-1">
<TabsTrigger value="account">
Account
</TabsTrigger>
<TabsTrigger value="password">
Password
</TabsTrigger>
</TabsList>
<TabsContent value="account">
<Card>
<CardHeader>
<CardTitle>Account</CardTitle>
<CardDescription>
Make changes to your account here. Click save when you're done.
</CardDescription>
</CardHeader>
<CardContent class="space-y-2">
<div class="space-y-1">
<Label for="name">Name</Label>
<Input id="name" default-value="Pedro Duarte" />
</div>
<div class="space-y-1">
<Label for="username">Username</Label>
<Input id="username" default-value="@peduarte" />
</div>
</CardContent>
<CardFooter>
<Button>Save changes</Button>
</CardFooter>
</Card>
</TabsContent>
<TabsContent value="password">
<Card>
<CardHeader>
<CardTitle>Password</CardTitle>
<CardDescription>
Change your password here. After saving, you'll be logged out.
</CardDescription>
</CardHeader>
<CardContent class="space-y-2">
<div class="space-y-1">
<Label for="current">Current password</Label>
<Input id="current" type="password" />
</div>
<div class="space-y-1">
<Label for="new">New password</Label>
<Input id="new" type="password" />
</div>
</CardContent>
<CardFooter>
<Button>Save password</Button>
</CardFooter>
</Card>
</TabsContent>
</Tabs>
</template>

View File

@ -16,7 +16,7 @@ const delegatedProps = computed(() => {
<TabsList <TabsList
v-bind="delegatedProps" v-bind="delegatedProps"
:class="cn( :class="cn(
'inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground', 'inline-flex items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground',
props.class, props.class,
)" )"
> >

View File

@ -22,6 +22,8 @@ const forwardedProps = useForwardProps(delegatedProps)
props.class, props.class,
)" )"
> >
<span class="truncate">
<slot /> <slot />
</span>
</TabsTrigger> </TabsTrigger>
</template> </template>

View File

@ -43,7 +43,7 @@
}, },
{ {
"name": "SelectTrigger.vue", "name": "SelectTrigger.vue",
"content": "<script setup lang=\"ts\">\nimport { type HTMLAttributes, computed } from 'vue'\nimport { SelectIcon, SelectTrigger, type SelectTriggerProps, useForwardProps } from 'radix-vue'\nimport { ChevronDown } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<SelectTriggerProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwardedProps = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <SelectTrigger\n v-bind=\"forwardedProps\"\n :class=\"cn(\n 'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',\n props.class,\n )\"\n >\n <slot />\n <SelectIcon as-child>\n <ChevronDown class=\"w-4 h-4 opacity-50\" />\n </SelectIcon>\n </SelectTrigger>\n</template>\n" "content": "<script setup lang=\"ts\">\nimport { type HTMLAttributes, computed } from 'vue'\nimport { SelectIcon, SelectTrigger, type SelectTriggerProps, useForwardProps } from 'radix-vue'\nimport { ChevronDown } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<SelectTriggerProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwardedProps = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <SelectTrigger\n v-bind=\"forwardedProps\"\n :class=\"cn(\n 'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:truncate text-start',\n props.class,\n )\"\n >\n <slot />\n <SelectIcon as-child>\n <ChevronDown class=\"w-4 h-4 opacity-50 shrink-0\" />\n </SelectIcon>\n </SelectTrigger>\n</template>\n"
}, },
{ {
"name": "SelectValue.vue", "name": "SelectValue.vue",

View File

@ -43,7 +43,7 @@
}, },
{ {
"name": "SelectTrigger.vue", "name": "SelectTrigger.vue",
"content": "<script setup lang=\"ts\">\nimport { type HTMLAttributes, computed } from 'vue'\nimport { SelectIcon, SelectTrigger, type SelectTriggerProps, useForwardProps } from 'radix-vue'\nimport { CaretSortIcon } from '@radix-icons/vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<SelectTriggerProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwardedProps = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <SelectTrigger\n v-bind=\"forwardedProps\"\n :class=\"cn(\n 'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',\n props.class,\n )\"\n >\n <slot />\n <SelectIcon as-child>\n <CaretSortIcon class=\"w-4 h-4 opacity-50\" />\n </SelectIcon>\n </SelectTrigger>\n</template>\n" "content": "<script setup lang=\"ts\">\nimport { type HTMLAttributes, computed } from 'vue'\nimport { SelectIcon, SelectTrigger, type SelectTriggerProps, useForwardProps } from 'radix-vue'\nimport { CaretSortIcon } from '@radix-icons/vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<SelectTriggerProps & { class?: HTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n\nconst forwardedProps = useForwardProps(delegatedProps)\n</script>\n\n<template>\n <SelectTrigger\n v-bind=\"forwardedProps\"\n :class=\"cn(\n 'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:truncate text-start',\n props.class,\n )\"\n >\n <slot />\n <SelectIcon as-child>\n <CaretSortIcon class=\"w-4 h-4 opacity-50 shrink-0\" />\n </SelectIcon>\n </SelectTrigger>\n</template>\n"
}, },
{ {
"name": "SelectValue.vue", "name": "SelectValue.vue",