feat: add docs for components

This commit is contained in:
zernonia 2023-09-03 01:38:53 +08:00
parent fa8bf4a21c
commit bb7663330f
64 changed files with 1572 additions and 244 deletions

View File

@ -165,7 +165,7 @@
* Table
* -------------------------------------------------------------------------- */
.vp-doc table {
/* .vp-doc table {
display: block;
border-collapse: collapse;
margin: 20px 0;
@ -197,7 +197,7 @@
.vp-doc td {
font-size: 14px;
}
} */
/**
* Decorational elements

View File

@ -0,0 +1,53 @@
---
title: Hover Card
description: For sighted users to preview content available behind a link.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/hover-card
primitive: https://www.radix-vue.com/components/hover-card.html
---
<ComponentPreview name="HoverCardDemo" >
<<< ../../../lib/registry/default/examples/HoverCardDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add hover-card
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from '@/lib/registry/default/ui/hover-card'
</script>
<template>
<HoverCard>
<HoverCardTrigger>Hover</HoverCardTrigger>
<HoverCardContent>
The React Framework created and maintained by @vercel.
</HoverCardContent>
</HoverCard>
</template>
```

View File

@ -0,0 +1,42 @@
---
title: Input
description: Displays a form input field or a component that looks like an input field.
---
<ComponentPreview name="InputDemo" class="[&_input]:max-w-xs" >
<<< ../../../lib/registry/default/examples/InputDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add input
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { Input } from '@/lib/registry/default/ui/input'
</script>
<template>
<Input />
</template>
```

View File

@ -0,0 +1,43 @@
---
title: Label
description: Renders an accessible label associated with controls.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/label
primitive: https://www.radix-vue.com/components/label.html
---
<ComponentPreview name="LabelDemo" >
<<< ../../../lib/registry/default/examples/LabelDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add input
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { Label } from '@/lib/registry/default/ui/label'
</script>
<template>
<Label for="email">Your email address</Label>
</template>
```

View File

@ -0,0 +1,65 @@
---
title: Menubar
description: A visually persistent menu common in desktop applications that provides quick access to a consistent set of commands.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/menubar
primitive: https://www.radix-vue.com/components/menubar.html
---
<ComponentPreview name="MenubarDemo" >
<<< ../../../lib/registry/default/examples/MenubarDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add menubar
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import {
Menubar,
MenubarContent,
MenubarItem,
MenubarMenu,
MenubarSeparator,
MenubarShortcut,
MenubarTrigger,
} from '@/lib/registry/default/ui/menubar'
</script>
<template>
<Menubar>
<MenubarMenu>
<MenubarTrigger>File</MenubarTrigger>
<MenubarContent>
<MenubarItem>
New Tab <MenubarShortcut>⌘T</MenubarShortcut>
</MenubarItem>
<MenubarItem>New Window</MenubarItem>
<MenubarSeparator />
<MenubarItem>Share</MenubarItem>
<MenubarSeparator />
<MenubarItem>Print</MenubarItem>
</MenubarContent>
</MenubarMenu>
</Menubar>
</template>
```

View File

@ -0,0 +1,43 @@
---
title: Progress
description: Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/progress
primitive: https://www.radix-vue.com/components/progress.html
---
<ComponentPreview name="ProgressDemo" >
<<< ../../../lib/registry/default/examples/ProgressDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add progress
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { Progress } from '@/lib/registry/default/ui/progress'
</script>
<template>
<Progress :model-value="33" />
</template>
```

View File

@ -0,0 +1,53 @@
---
title: Radio Group
description: A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/radio-group
primitive: https://www.radix-vue.com/components/radio-group.html
---
<ComponentPreview name="RadioGroupDemo" >
<<< ../../../lib/registry/default/examples/RadioGroupDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add radio-group
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { Label } from '@/lib/registry/default/ui/label'
import { RadioGroup, RadioGroupItem } from '@/lib/registry/default/ui/radio-group'
</script>
<template>
<RadioGroup default-value="option-one">
<div className="flex items-center space-x-2">
<RadioGroupItem id="option-one" value="option-one" />
<Label html-for="option-one">Option One</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem id="option-two" value="option-two" />
<Label html-for="option-two">Option Two</Label>
</div>
</RadioGroup>
</template>
```

View File

@ -0,0 +1,50 @@
---
title: Scroll-area
description: Augments native scroll functionality for custom, cross-browser styling.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/scroll-area
primitive: https://www.radix-vue.com/components/scroll-area.html
---
<ComponentPreview name="ScrollAreaDemo" >
<<< ../../../lib/registry/default/examples/ScrollAreaDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add scroll-area
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
</script>
<template>
<ScrollArea class="h-[200px] w-[350px] rounded-md border p-4">
Jokester began sneaking into the castle in the middle of the night and leaving
jokes all over the place: under the king's pillow, in his soup, even in the
royal toilet. The king was furious, but he couldn't seem to stop Jokester. And
then, one day, the people of the kingdom discovered that the jokes left by
Jokester were so funny that they couldn't help but laugh. And once they
started laughing, they couldn't stop.
</ScrollArea>
</template>
```

View File

@ -0,0 +1,43 @@
---
title: Separator
description: Visually or semantically separates content.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/separator
primitive: https://www.radix-vue.com/components/separator.html
---
<ComponentPreview name="SeparatorDemo" >
<<< ../../../lib/registry/default/examples/SeparatorDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add separator
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { Separator } from '@/lib/registry/default/ui/separator'
</script>
<template>
<Separator />
</template>
```

View File

@ -0,0 +1,61 @@
---
title: Sheet
description: Extends the Dialog component to display content that complements the main content of the screen.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/dialog
primitive: https://www.radix-vue.com/components/dialog.html
---
<ComponentPreview name="SheetDemo" >
<<< ../../../lib/registry/default/examples/SheetDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add sheet
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@/lib/registry/default/ui/sheet'
</script>
<template>
<Sheet>
<SheetTrigger>Open</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Are you sure absolutely sure?</SheetTitle>
<SheetDescription>
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>
</template>
```

View File

@ -0,0 +1,41 @@
---
title: Skeleton
description: Use to show a placeholder while content is loading.
---
<ComponentPreview name="SkeletonDemo" >
<<< ../../../lib/registry/default/examples/SkeletonDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add skeleton
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { Skeleton } from '@/lib/registry/default/ui/skeleton'
</script>
<template>
<Skeleton class="w-[100px] h-[20px] rounded-full" />
</template>
```

View File

@ -0,0 +1,45 @@
---
title: Slider
description: An input where the user selects a value from within a given range.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/slider
primitive: https://www.radix-vue.com/components/slider.html
---
<ComponentPreview name="SliderDemo" >
<<< ../../../lib/registry/default/examples/SliderDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add slider
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { Slider } from '@/lib/registry/default/ui/slider'
</script>
<template>
<Slider
:default-value="[33]" :max="100" :step="1"
/>
</template>
```

View File

@ -0,0 +1,43 @@
---
title: Switch
description: A control that allows the user to toggle between checked and not checked.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/switch
primitive: https://www.radix-vue.com/components/switch.html
---
<ComponentPreview name="SwitchDemo" >
<<< ../../../lib/registry/default/examples/SwitchDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add switch
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { Switch } from '@/lib/registry/default/ui/switch'
</script>
<template>
<Switch />
</template>
```

View File

@ -0,0 +1,75 @@
---
title: Table
description: A responsive table component.
---
<ComponentPreview name="TableDemo" >
<<< ../../../lib/registry/default/examples/TableDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add table
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/lib/registry/default/ui/table'
</script>
<template>
<Table>
<TableCaption>A list of your recent invoices.</TableCaption>
<TableHeader>
<TableRow>
<TableHead class="w-[100px]">
Invoice
</TableHead>
<TableHead>Status</TableHead>
<TableHead>Method</TableHead>
<TableHead class="text-right">
Amount
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell class="font-medium">
INV001
</TableCell>
<TableCell>Paid</TableCell>
<TableCell>Credit Card</TableCell>
<TableCell class="text-right">
$250.00
</TableCell>
</TableRow>
</TableBody>
</Table>
</template>
```

View File

@ -0,0 +1,58 @@
---
title: Tabs
description: A set of layered sections of content—known as tab panels—that are displayed one at a time.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/tabs
primitive: https://www.radix-vue.com/components/tabs.html
---
<ComponentPreview name="TabsDemo" >
<<< ../../../lib/registry/default/examples/TabsDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add tabs
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/lib/registry/default/ui/tabs'
</script>
<template>
<Tabs default-value="account" class="w-[400px]">
<TabsList>
<TabsTrigger value="account">
Account
</TabsTrigger>
<TabsTrigger value="password">
Password
</TabsTrigger>
</TabsList>
<TabsContent value="account">
Make changes to your account here.
</TabsContent>
<TabsContent value="password">
Change your password here.
</TabsContent>
</Tabs>
</template>
```

View File

@ -0,0 +1,41 @@
---
title: Textarea
description: Displays a form textarea or a component that looks like a textarea.
---
<ComponentPreview name="TextareaDemo" >
<<< ../../../lib/registry/default/examples/TextareaDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add textarea
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { Textarea } from '@/lib/registry/default/ui/textarea'
</script>
<template>
<Textarea />
</template>
```

View File

@ -0,0 +1,43 @@
---
title: Toggle
description: A two-state button that can be either on or off.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/toggle
primitive: https://www.radix-vue.com/components/toggle.html
---
<ComponentPreview name="ToggleDemo" >
<<< ../../../lib/registry/default/examples/ToggleDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add toggle
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import { Toggle } from '@/lib/registry/default/ui/toggle'
</script>
<template>
<Toggle>Toggle</Toggle>
</template>
```

View File

@ -0,0 +1,55 @@
---
title: Tooltip
description: A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.
source: https://github.com/radix-vue/shadcn-vue/tree/main/apps/www/src/lib/registry/default/ui/tooltip
primitive: https://www.radix-vue.com/components/tooltip.html
---
<ComponentPreview name="TooltipDemo" >
<<< ../../../lib/registry/default/examples/TooltipDemo.vue
</ComponentPreview>
## Installation
```bash
npx shadcn-vue@latest add tooltip
```
<ManualInstall>
1. Install `radix-vue`:
```bash
npm install radix-vue
```
2. Copy and paste the component source files linked at the top of this page into your project.
</ManualInstall>
## Usage
```vue
<script setup lang="ts">
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger
} from '@/lib/registry/default/ui/tooltip'
</script>
<template>
<TooltipProvider>
<Tooltip>
<TooltipTrigger>Hover</TooltipTrigger>
<TooltipContent>
<p>Add to library</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</template>
```

View File

@ -0,0 +1,47 @@
<script setup lang="ts">
import { CalendarDays } from 'lucide-vue-next'
import {
Avatar,
AvatarFallback,
AvatarImage,
} from '@/lib/registry/default/ui/avatar'
import { Button } from '@/lib/registry/default/ui/button'
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from '@/lib/registry/default/ui/hover-card'
</script>
<template>
<HoverCard>
<HoverCardTrigger as-child>
<Button variant="link">
@vuejs
</Button>
</HoverCardTrigger>
<HoverCardContent class="w-80">
<div class="flex justify-between space-x-4">
<Avatar>
<AvatarImage src="https://github.com/vuejs.png" />
<AvatarFallback>VC</AvatarFallback>
</Avatar>
<div class="space-y-1">
<h4 class="text-sm font-semibold">
@vuejs
</h4>
<p class="text-sm">
Progressive JavaScript framework for building modern web interfaces.
</p>
<div class="flex items-center pt-2">
<CalendarDays class="mr-2 h-4 w-4 opacity-70" />
<span class="text-xs text-muted-foreground">
Joined January 2014
</span>
</div>
</div>
</div>
</HoverCardContent>
</HoverCard>
</template>

View File

@ -0,0 +1,7 @@
<script setup lang="ts">
import { Input } from '@/lib/registry/default/ui/input'
</script>
<template>
<Input type="email" placeholder="Email" />
</template>

View File

@ -0,0 +1,13 @@
<script setup lang="ts">
import { Checkbox } from '@/lib/registry/default/ui/checkbox'
import { Label } from '@/lib/registry/default/ui/label'
</script>
<template>
<div>
<div className="flex items-center space-x-2">
<Checkbox id="terms" />
<Label for="terms">Accept terms and conditions</Label>
</div>
</div>
</template>

View File

@ -0,0 +1,123 @@
<script setup lang="ts">
import {
Menubar,
MenubarCheckboxItem,
MenubarContent,
MenubarItem,
MenubarMenu,
MenubarRadioGroup,
MenubarRadioItem,
MenubarSeparator,
MenubarShortcut,
MenubarSub,
MenubarSubContent,
MenubarSubTrigger,
MenubarTrigger,
} from '@/lib/registry/default/ui/menubar'
</script>
<template>
<Menubar>
<MenubarMenu>
<MenubarTrigger>File</MenubarTrigger>
<MenubarContent>
<MenubarItem>
New Tab <MenubarShortcut>T</MenubarShortcut>
</MenubarItem>
<MenubarItem>
New Window <MenubarShortcut>N</MenubarShortcut>
</MenubarItem>
<MenubarItem disabled>
New Incognito Window
</MenubarItem>
<MenubarSeparator />
<MenubarSub>
<MenubarSubTrigger>Share</MenubarSubTrigger>
<MenubarSubContent>
<MenubarItem>Email link</MenubarItem>
<MenubarItem>Messages</MenubarItem>
<MenubarItem>Notes</MenubarItem>
</MenubarSubContent>
</MenubarSub>
<MenubarSeparator />
<MenubarItem>
Print... <MenubarShortcut>P</MenubarShortcut>
</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>Edit</MenubarTrigger>
<MenubarContent>
<MenubarItem>
Undo <MenubarShortcut>Z</MenubarShortcut>
</MenubarItem>
<MenubarItem>
Redo <MenubarShortcut>Z</MenubarShortcut>
</MenubarItem>
<MenubarSeparator />
<MenubarSub>
<MenubarSubTrigger>Find</MenubarSubTrigger>
<MenubarSubContent>
<MenubarItem>Search the web</MenubarItem>
<MenubarSeparator />
<MenubarItem>Find...</MenubarItem>
<MenubarItem>Find Next</MenubarItem>
<MenubarItem>Find Previous</MenubarItem>
</MenubarSubContent>
</MenubarSub>
<MenubarSeparator />
<MenubarItem>Cut</MenubarItem>
<MenubarItem>Copy</MenubarItem>
<MenubarItem>Paste</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>View</MenubarTrigger>
<MenubarContent>
<MenubarCheckboxItem>Always Show Bookmarks Bar</MenubarCheckboxItem>
<MenubarCheckboxItem checked>
Always Show Full URLs
</MenubarCheckboxItem>
<MenubarSeparator />
<MenubarItem inset>
Reload <MenubarShortcut>R</MenubarShortcut>
</MenubarItem>
<MenubarItem disabled inset>
Force Reload <MenubarShortcut>R</MenubarShortcut>
</MenubarItem>
<MenubarSeparator />
<MenubarItem inset>
Toggle Fullscreen
</MenubarItem>
<MenubarSeparator />
<MenubarItem inset>
Hide Sidebar
</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>Profiles</MenubarTrigger>
<MenubarContent>
<MenubarRadioGroup value="benoit">
<MenubarRadioItem value="andy">
Andy
</MenubarRadioItem>
<MenubarRadioItem value="benoit">
Benoit
</MenubarRadioItem>
<MenubarRadioItem value="Luis">
Luis
</MenubarRadioItem>
</MenubarRadioGroup>
<MenubarSeparator />
<MenubarItem inset>
Edit...
</MenubarItem>
<MenubarSeparator />
<MenubarItem inset>
Add Profile...
</MenubarItem>
</MenubarContent>
</MenubarMenu>
</Menubar>
</template>

View File

@ -0,0 +1,15 @@
<script setup lang="ts">
import { ref, watchEffect } from 'vue'
import { Progress } from '@/lib/registry/default/ui/progress'
const progress = ref(13)
watchEffect((cleanupFn) => {
const timer = setTimeout(() => progress.value = 66, 500)
cleanupFn(() => clearTimeout(timer))
})
</script>
<template>
<Progress v-model="progress" class="w-[60%]" />
</template>

View File

@ -0,0 +1,21 @@
<script setup lang="ts">
import { Label } from '@/lib/registry/default/ui/label'
import { RadioGroup, RadioGroupItem } from '@/lib/registry/default/ui/radio-group'
</script>
<template>
<RadioGroup default-value="comfortable">
<div className="flex items-center space-x-2">
<RadioGroupItem id="r1" value="default" />
<Label html-for="r1">Default</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem id="r2" value="comfortable" />
<Label html-for="r2">Comfortable</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem id="r3" value="compact" />
<Label html-for="r3">Compact</Label>
</div>
</RadioGroup>
</template>

View File

@ -0,0 +1,25 @@
<script setup lang="ts">
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
import { Separator } from '@/lib/registry/default/ui/separator'
const tags = Array.from({ length: 50 }).map(
(_, i, a) => `v1.2.0-beta.${a.length - i}`,
)
</script>
<template>
<ScrollArea class="h-72 w-48 rounded-md border">
<div class="p-4">
<h4 class="mb-4 text-sm font-medium leading-none">
Tags
</h4>
<div v-for="tag in tags" :key="tag">
<div class="text-sm">
{{ tag }}
</div>
<Separator class="my-2" />
</div>
</div>
</ScrollArea>
</template>

View File

@ -0,0 +1,24 @@
<script setup lang="ts">
import { Separator } from '@/lib/registry/default/ui/separator'
</script>
<template>
<div>
<div class="space-y-1">
<h4 class="text-sm font-medium leading-none">
Radix Primitives
</h4>
<p class="text-sm text-muted-foreground">
An open-source UI component library.
</p>
</div>
<Separator class="my-4" />
<div class="flex h-5 items-center space-x-4 text-sm">
<div>Blog</div>
<Separator orientation="vertical" />
<div>Docs</div>
<Separator orientation="vertical" />
<div>Source</div>
</div>
</div>
</template>

View File

@ -0,0 +1,54 @@
<script setup lang="ts">
import { Button } from '@/lib/registry/default/ui/button'
import { Input } from '@/lib/registry/default/ui/input'
import { Label } from '@/lib/registry/default/ui/label'
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@/lib/registry/default/ui/sheet'
</script>
<template>
<Sheet>
<SheetTrigger as-child>
<Button variant="outline">
Open
</Button>
</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Edit profile</SheetTitle>
<SheetDescription>
Make changes to your profile here. Click save when you're done.
</SheetDescription>
</SheetHeader>
<div class="grid gap-4 py-4">
<div class="grid grid-cols-4 items-center gap-4">
<Label for="name" class="text-right">
Name
</Label>
<Input id="name" value="Pedro Duarte" class="col-span-3" />
</div>
<div class="grid grid-cols-4 items-center gap-4">
<Label for="username" class="text-right">
Username
</Label>
<Input id="username" value="@peduarte" class="col-span-3" />
</div>
</div>
<SheetFooter>
<SheetClose as-child>
<Button type="submit">
Save changes
</Button>
</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>
</template>

View File

@ -0,0 +1,13 @@
<script setup lang="ts">
import { Skeleton } from '@/lib/registry/default/ui/skeleton'
</script>
<template>
<div class="flex items-center space-x-4">
<Skeleton class="h-12 w-12 rounded-full" />
<div class="space-y-2">
<Skeleton class="h-4 w-[250px]" />
<Skeleton class="h-4 w-[200px]" />
</div>
</div>
</template>

View File

@ -0,0 +1,15 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { Slider } from '@/lib/registry/default/ui/slider'
const modelValue = [50]
</script>
<template>
<Slider
v-model="modelValue"
:max="100"
:step="1"
:class="cn('w-[60%]', $attrs.class ?? '')"
/>
</template>

View File

@ -0,0 +1,11 @@
<script setup lang="ts">
import { Label } from '@/lib/registry/default/ui/label'
import { Switch } from '@/lib/registry/default/ui/switch'
</script>
<template>
<div className="flex items-center space-x-2">
<Switch id="airplane-mode" />
<Label for="airplane-mode">Airplane Mode</Label>
</div>
</template>

View File

@ -0,0 +1,86 @@
<script setup lang="ts">
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/lib/registry/default/ui/table'
const invoices = [
{
invoice: 'INV001',
paymentStatus: 'Paid',
totalAmount: '$250.00',
paymentMethod: 'Credit Card',
},
{
invoice: 'INV002',
paymentStatus: 'Pending',
totalAmount: '$150.00',
paymentMethod: 'PayPal',
},
{
invoice: 'INV003',
paymentStatus: 'Unpaid',
totalAmount: '$350.00',
paymentMethod: 'Bank Transfer',
},
{
invoice: 'INV004',
paymentStatus: 'Paid',
totalAmount: '$450.00',
paymentMethod: 'Credit Card',
},
{
invoice: 'INV005',
paymentStatus: 'Paid',
totalAmount: '$550.00',
paymentMethod: 'PayPal',
},
{
invoice: 'INV006',
paymentStatus: 'Pending',
totalAmount: '$200.00',
paymentMethod: 'Bank Transfer',
},
{
invoice: 'INV007',
paymentStatus: 'Unpaid',
totalAmount: '$300.00',
paymentMethod: 'Credit Card',
},
]
</script>
<template>
<Table>
<TableCaption>A list of your recent invoices.</TableCaption>
<TableHeader>
<TableRow>
<TableHead class-name="w-[100px]">
Invoice
</TableHead>
<TableHead>Status</TableHead>
<TableHead>Method</TableHead>
<TableHead class-name="text-right">
Amount
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow v-for="invoice in invoices" :key="invoice.invoice">
<TableCell class="font-medium">
{{ invoice.invoice }}
</TableCell>
<TableCell>{{ invoice.paymentStatus }}</TableCell>
<TableCell>{{ invoice.paymentMethod }}</TableCell>
<TableCell class="text-right">
{{ invoice.totalAmount }}
</TableCell>
</TableRow>
</TableBody>
</Table>
</template>

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]">
<TabsList class="grid w-full grid-cols-2">
<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 className="space-y-1">
<Label html-for="name">Name</Label>
<Input id="name" default-value="Pedro Duarte" />
</div>
<div className="space-y-1">
<Label html-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 className="space-y-1">
<Label html-for="current">Current password</Label>
<Input id="current" type="password" />
</div>
<div className="space-y-1">
<Label html-for="new">New password</Label>
<Input id="new" type="password" />
</div>
</CardContent>
<CardFooter>
<Button>Save password</Button>
</CardFooter>
</Card>
</TabsContent>
</Tabs>
</template>

View File

@ -0,0 +1,7 @@
<script setup lang="ts">
import { Textarea } from '@/lib/registry/default/ui/textarea'
</script>
<template>
<Textarea placeholder="Type your message here." />
</template>

View File

@ -0,0 +1,11 @@
<script setup lang="ts">
import { Bold } from 'lucide-vue-next'
import { Toggle } from '@/lib/registry/default/ui/toggle'
</script>
<template>
<Toggle aria-label="Toggle italic">
<Bold class="h-4 w-4" />
</Toggle>
</template>

View File

@ -0,0 +1,24 @@
<script setup lang="ts">
import { Button } from '@/lib/registry/default/ui/button'
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@/lib/registry/default/ui/tooltip'
</script>
<template>
<TooltipProvider>
<Tooltip>
<TooltipTrigger as-child>
<Button variant="outline">
Hover
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Add to library</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</template>

View File

@ -18,7 +18,7 @@ const emit = defineEmits<MenubarCheckboxItemEmits>()
v-bind="props"
:class="[
cn(
'flex relative items-center rounded-md transition-colors data-[disabled]:opacity-50 data-[disabled]:pointer-events-none data-[highlighted]:bg-outline-hover pl-7 py-1.5 text-sm outline-none select-none cursor-default',
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
props.class,
),
]"
@ -26,9 +26,9 @@ const emit = defineEmits<MenubarCheckboxItemEmits>()
@select="emit('select', $event)"
>
<MenubarItemIndicator
class="absolute left-2 inline-flex w-3.5 h-3.5 items-center justify-center"
class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"
>
<RadixIconsCheck class="text-foreground" />
<RadixIconsCheck class="w-4 h-4" />
</MenubarItemIndicator>
<slot />
</MenubarCheckboxItem>

View File

@ -11,7 +11,7 @@ const props = withDefaults(
{
align: 'start',
alignOffset: -4,
sideOffset: 4,
sideOffset: 8,
},
)
</script>
@ -27,7 +27,7 @@ const props = withDefaults(
:align-offset="props.alignOffset"
:class="
cn(
'bg-background text-foreground mt-1.5 border border-border p-1 z-50 min-w-[12rem] rounded-md shadow-md 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',
'z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in 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',
props.class,
)
"

View File

@ -6,7 +6,7 @@ import {
} from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<MenubarItemProps & { class?: string }>()
const props = defineProps<MenubarItemProps & { inset?: boolean; class?: string }>()
const emits = defineEmits<MenubarItemEmits>()
</script>
@ -16,7 +16,8 @@ const emits = defineEmits<MenubarItemEmits>()
v-bind="props"
:class="[
cn(
'flex items-center rounded-md transition-colors data-[disabled]:opacity-50 data-[disabled]:pointer-events-none focus:bg-outline-hover px-2 py-1.5 text-sm outline-none select-none cursor-default',
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
inset && 'pl-8',
props.class,
),
]"

View File

@ -2,13 +2,11 @@
import { MenubarLabel, type MenubarLabelProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<MenubarLabelProps & { class?: string }>()
const props = defineProps<MenubarLabelProps & { inset?: boolean; class?: string }>()
</script>
<template>
<div :class="cn('px-2 py-1.5 text-sm font-semibold', props.class)">
<MenubarLabel>
<slot />
</MenubarLabel>
</div>
<MenubarLabel :class="cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', props.class)">
<slot />
</MenubarLabel>
</template>

View File

@ -18,19 +18,18 @@ const emits = defineEmits<MenubarRadioItemEmits>()
v-bind="props"
:class="[
cn(
'flex items-center rounded-md transition-colors data-[disabled]:opacity-50 data-[disabled]:pointer-events-none focus:bg-outline-hover px-2 py-1.5 text-sm outline-none select-none cursor-default',
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
props.class,
),
]"
@select="emits('select', $event)"
>
<MenubarItemIndicator
class="absolute left-3.5 inline-flex w-2 h-2 items-center justify-center"
class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"
>
<RiCheckboxBlankCircleFill class="text-foreground" />
<RiCheckboxBlankCircleFill class="h-2 w-2 fill-curren" />
</MenubarItemIndicator>
<span class="pl-6">
<slot />
</span>
<slot />
</MenubarRadioItem>
</template>

View File

@ -1,9 +1,10 @@
<script setup lang="ts">
import { MenubarSeparator, type MenubarSeparatorProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<MenubarSeparatorProps>()
</script>
<template>
<MenubarSeparator class="-mx-1 my-1 h-px bg-secondary" v-bind="props" />
<MenubarSeparator :class=" cn('-mx-1 my-1 h-px bg-secondary', $attrs.class ?? '')" v-bind="props" />
</template>

View File

@ -1,5 +1,9 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
</script>
<template>
<div class="text-xxs ml-auto tracking-widest opacity-50">
<span :class="cn('text-xxs ml-auto tracking-widest opacity-50', $attrs.class ?? '')">
<slot />
</div>
</span>
</template>

View File

@ -29,7 +29,7 @@ const emits = defineEmits<MenubarSubContentEmits>()
:align-offset="props.alignOffset"
:class="
cn(
'bg-background text-foreground border border-border p-1 z-50 min-w-[10rem] rounded-md shadow-md 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',
'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 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',
props.class,
)
"

View File

@ -2,7 +2,7 @@
import { MenubarSubTrigger, type MenubarSubTriggerProps } from 'radix-vue'
import { cn } from '@/lib/utils'
const props = defineProps<MenubarSubTriggerProps & { class?: string }>()
const props = defineProps<MenubarSubTriggerProps & { inset?: boolean; class?: string }>()
</script>
<template>
@ -10,7 +10,8 @@ const props = defineProps<MenubarSubTriggerProps & { class?: string }>()
v-bind="props"
:class="[
cn(
'flex items-center rounded-md transition-colors data-[disabled]:opacity-50 data-[disabled]:pointer-events-none focus:bg-outline-hover px-2 py-1.5 text-sm outline-none select-none cursor-default',
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
inset && 'pl-8',
props.class,
),
]"

View File

@ -10,7 +10,7 @@ const props = defineProps<MenubarTriggerProps & { class?: string }>()
v-bind="props"
:class="
cn(
'flex cursor-default select-none items-center rounded px-3 py-1.5 text-sm font-medium outline-none data-[highlighted]:bg-outline-hover focus:bg-outline-hover text-foreground',
'flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
props.class,
)
"

View File

@ -1,58 +1,23 @@
<script setup lang="ts">
import { computed } from 'vue'
import { cn } from '@/lib/utils'
import type { SliderRootEmits, SliderRootProps } from 'radix-vue'
import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from 'radix-vue'
import { cn, useEmitAsProps } from '@/lib/utils'
interface SliderProps {
modelValue: number
class?: string
step?: number | string
disabled?: boolean
min?: number
max?: number
}
const props = withDefaults(defineProps<SliderProps>(), {
step: 1,
disabled: false,
min: 0,
max: 100,
})
const emit = defineEmits(['update:modelValue'])
const progressStyle = computed(() => {
const { modelValue, min, max } = props
const clampedValue = Math.max(min, Math.min(modelValue, max))
const relativeValue = (clampedValue - min) / (max - min)
return {
width: `${relativeValue * 100}%`,
}
})
const props = defineProps<SliderRootProps>()
const emits = defineEmits<SliderRootEmits>()
</script>
<template>
<div :class="cn('w-full', props.class)">
<div class="relative w-full flex items-center h-2">
<input
type="range"
:step="props.step"
:disabled="props.disabled"
:min="props.min"
:max="props.max"
class="w-full absolute appearance-none cursor-default disabled:cursor-not-allowed disabled:bg-opacity-50 focus:outline-none peer group bg-transparent rounded-lg focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-gray-950 h-4 [&::-webkit-slider-thumb]:relative [&::-moz-range-thumb]:relative [&::-webkit-slider-thumb]:active:cursor-grabbing [&::-webkit-slider-thumb]:z-[1] [&::-webkit-slider-thumb]:cursor-grab [&::-moz-range-thumb]:cursor-grab [&::-moz-range-thumb]:active:cursor-grabbing [&::-moz-range-thumb]:z-[1] [&::-webkit-slider-thumb]:appearance-none [&::-moz-range-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-0 text-foreground [&::-webkit-slider-thumb]:ring-2 [&::-webkit-slider-thumb]:ring-primary [&::-webkit-slider-thumb]:bg-background [&::-moz-range-thumb]:bg-current [&::-webkit-slider-thumb]:h-3 [&::-moz-range-thumb]:h-3 [&::-webkit-slider-thumb]:w-3 [&::-moz-range-thumb]:w-3 [&::-webkit-slider-thumb]:-mt-[3px] [&::-moz-range-thumb]:-mt-[3px] [&::-webkit-slider-runnable-track]:group-disabled:bg-opacity-50 [&::-moz-slider-runnable-track]:group-disabled:bg-opacity-50 [&::-webkit-slider-runnable-track]:bg-secondary [&::-moz-slider-runnable-track]:bg-secondary [&::-webkit-slider-runnable-track]:rounded-lg [&::-moz-slider-runnable-track]:rounded-lg [&::-webkit-slider-runnable-track]:h-1.5 [&::-moz-slider-runnable-track]:h-1.5"
:value="props.modelValue"
@input="
($event) =>
emit(
'update:modelValue',
($event.target as HTMLInputElement).valueAsNumber,
)
"
>
<span
class="absolute pointer-events-none peer-disabled:bg-opacity-50 rounded-s-lg bg-primary h-2"
:style="progressStyle"
/>
</div>
</div>
<SliderRoot
:class="cn(
'relative flex w-full touch-none select-none items-center',
$attrs.class ?? '',
)"
v-bind="{ ...props, ...useEmitAsProps(emits) }"
>
<SliderTrack class="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary">
<SliderRange class="absolute h-full bg-primary" />
</SliderTrack>
<SliderThumb class="block h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" />
</SliderRoot>
</template>

View File

@ -17,7 +17,7 @@ const emits = defineEmits<SwitchRootEmits>()
v-bind="props"
:class="
cn(
'peer inline-flex h-[20px] w-[36px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent data-[disabled]:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-secondary',
'peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
props.class,
)
"
@ -26,8 +26,7 @@ const emits = defineEmits<SwitchRootEmits>()
<SwitchThumb
:class="
cn(
'pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0 ease-in-out duration-200',
props.class,
'pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0',
)
"
/>

View File

@ -1,14 +1,12 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
const props = defineProps({
class: String,
})
const props = defineProps<{ class?: string }>()
</script>
<template>
<div :class="cn('w-full overflow-auto', props.class)">
<table class="w-full caption-bottom">
<div class="w-full overflow-auto">
<table :class="cn('w-full caption-bottom text-sm', props.class)">
<slot />
</table>
</div>

View File

@ -1,5 +1,11 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
const props = defineProps<{ class?: string }>()
</script>
<template>
<tbody>
<tbody :class="cn('[&_tr:last-child]:border-0', props.class)">
<slot />
</tbody>
</template>

View File

@ -1,5 +1,11 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
const props = defineProps<{ class?: string }>()
</script>
<template>
<caption class="text-sm mt-4 text-muted">
<caption :class="cn('mt-4 text-sm text-muted-foreground', props.class)">
<slot />
</caption>
</template>

View File

@ -1,16 +1,14 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
const props = defineProps({
class: String,
})
const props = defineProps<{ class?: string }>()
</script>
<template>
<td
:class="
cn(
'p-4 whitespace-nowrap align-middle text-sm text-foreground',
'p-4 align-middle [&:has([role=checkbox])]:pr-0',
props.class,
)
"

View File

@ -0,0 +1,11 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
const props = defineProps<{ class?: string }>()
</script>
<template>
<tfoot :class="cn('bg-primary font-medium text-primary-foreground', props.class)">
<slot />
</tfoot>
</template>

View File

@ -1,20 +1,11 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
const props = defineProps({
class: String,
})
const props = defineProps<{ class?: string }>()
</script>
<template>
<th
:class="
cn(
'px-4 h-12 text-left font-medium text-sm whitespace-nowrap text-muted',
props.class,
)
"
>
<th :class="cn('h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0', props.class)">
<slot />
</th>
</template>

View File

@ -1,13 +1,11 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
const props = defineProps({
class: String,
})
const props = defineProps<{ class?: string }>()
</script>
<template>
<thead :class="cn('border-b border-border', props.class)">
<thead :class="cn('[&_tr]:border-b', props.class)">
<slot />
</thead>
</template>

View File

@ -1,13 +1,11 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
const props = defineProps({
class: String,
})
const props = defineProps<{ class?: string }>()
</script>
<template>
<tr :class="cn('border-b border-border last:border-none', props.class)">
<tr :class="cn('border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted', props.class)">
<slot />
</tr>
</template>

View File

@ -7,7 +7,7 @@ const props = defineProps<TabsContentProps & { class?: string }>()
<template>
<TabsContent
:class="cn('mt-2 focus-visible:outline-none', props.class)"
:class="cn('mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2', props.class)"
v-bind="props"
>
<slot />

View File

@ -10,7 +10,7 @@ const props = defineProps<TabsListProps & { class?: string }>()
v-bind="props"
:class="
cn(
'inline-flex h-10 items-center justify-center rounded-md bg-outline-hover p-1 text-muted',
'inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',
props.class,
)
"

View File

@ -1,68 +0,0 @@
<script setup lang="ts">
import { AlertTriangle } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
interface InputProps {
id?: string
value?: string
type?: string
placeholder?: string
required?: boolean
disabled?: boolean
invalid?: boolean
helperText?: string
class?: string
}
const props = withDefaults(defineProps<InputProps>(), {
id: '',
value: '',
type: 'text',
placeholder: '',
required: false,
disabled: false,
invalid: false,
helperText: '',
})
const emit = defineEmits(['update:value'])
function handleInput(event: Event) {
emit('update:value', (event.target as HTMLInputElement).value)
}
</script>
<template>
<div :class="cn('relative', props.class)">
<input
:id="props.id"
:value="props.value"
:type="props.type"
:required="props.required"
:placeholder="props.placeholder"
:disabled="props.disabled"
:class="[
props.invalid
? '!ring-destructive ring-2 placeholder:!text-destructive'
: '',
props.disabled ? 'cursor-not-allowed opacity-50' : '',
cn(
'px-3 h-9 bg-transparent block w-full outline-none focus:ring-2 focus:ring-accent ring-secondary placeholder:text-muted rounded-md text-sm ring-1 text-foreground',
props.class,
),
]"
@input="handleInput"
>
<div
class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none"
>
<AlertTriangle v-if="props.invalid" class="w-4 h-4 text-destructive" />
</div>
</div>
<p
v-if="props.helperText && !props.invalid"
class="gap-1 leading-5 text-[13px] text-muted"
>
{{ props.helperText }}
</p>
</template>

View File

@ -1,67 +1,7 @@
<script setup lang="ts">
import { AlertTriangle } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
interface InputProps {
id?: string
value?: string
placeholder?: string
rows?: number
required?: boolean
disabled?: boolean
invalid?: boolean
helperText?: string
class?: string
}
const props = withDefaults(defineProps<InputProps>(), {
id: '',
value: '',
rows: 3,
placeholder: '',
required: false,
disabled: false,
invalid: false,
helperText: '',
})
const emit = defineEmits(['update:value'])
function handleInput(event: Event) {
emit('update:value', (event.target as HTMLInputElement).value)
}
</script>
<template>
<div :class="cn('relative', props.class)">
<textarea
:id="props.id"
:value="props.value"
:rows="props.rows"
:required="props.required"
:placeholder="props.placeholder"
:disabled="props.disabled"
:class="[
props.invalid
? '!ring-destructive ring-2 placeholder:!text-destructive'
: '',
cn(
'py-3 px-4 block bg-transparent outline-none focus:ring-2 focus:ring-accent w-full ring-1 ring-secondary placeholder:text-muted rounded-md text-sm text-foreground',
props.class,
),
]"
@input="handleInput"
/>
<div
class="absolute inset-y-0 right-0 bottom-6 flex items-center pr-3 pointer-events-none"
>
<AlertTriangle v-if="props.invalid" class="w-4 h-4 text-destructive" />
</div>
</div>
<p
v-if="props.helperText && !props.invalid"
class="gap-1 leading-5 text-[13px] text-muted"
>
{{ props.helperText }}
</p>
<textarea :class="cn('flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', $attrs.class ?? '')" />
</template>

View File

@ -0,0 +1,13 @@
<script setup lang="ts">
import { TooltipRoot, type TooltipRootEmits, type TooltipRootProps } from 'radix-vue'
import { useEmitAsProps } from '@/lib/utils'
const props = defineProps<TooltipRootProps>()
const emits = defineEmits<TooltipRootEmits>()
</script>
<template>
<TooltipRoot v-bind="{ ...props, ...useEmitAsProps(emits) }">
<slot />
</TooltipRoot>
</template>

View File

@ -0,0 +1,15 @@
<script setup lang="ts">
import { TooltipContent, type TooltipContentEmits, type TooltipContentProps } from 'radix-vue'
import { cn, useEmitAsProps } from '@/lib/utils'
const props = withDefaults(defineProps<TooltipContentProps>(), {
sideOffset: 4,
})
const emits = defineEmits<TooltipContentEmits>()
</script>
<template>
<TooltipContent v-bind="{ ...props, ...useEmitAsProps(emits) }" :class="cn('z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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', $attrs.class ?? '')">
<slot />
</TooltipContent>
</template>

View File

@ -0,0 +1,11 @@
<script setup lang="ts">
import { TooltipProvider, type TooltipProviderProps } from 'radix-vue'
const props = defineProps<TooltipProviderProps>()
</script>
<template>
<TooltipProvider v-bind="props">
<slot />
</TooltipProvider>
</template>

View File

@ -0,0 +1,11 @@
<script setup lang="ts">
import { TooltipTrigger, type TooltipTriggerProps } from 'radix-vue'
const props = defineProps<TooltipTriggerProps>()
</script>
<template>
<TooltipTrigger v-bind="props">
<slot />
</TooltipTrigger>
</template>

View File

@ -0,0 +1,4 @@
export { default as Tooltip } from './Tooltip.vue'
export { default as TooltipContent } from './TooltipContent.vue'
export { default as TooltipTrigger } from './TooltipTrigger.vue'
export { default as TooltipProvider } from './TooltipProvider.vue'