fix tailwind

This commit is contained in:
padreug 2025-03-11 01:52:56 +01:00
parent 00f4bfa583
commit f2a3f5e53e
63 changed files with 807 additions and 562 deletions

View file

@ -1,314 +1,146 @@
@import "tailwindcss";
@config "../../tailwind.config.js";
@import 'tailwindcss';
@layer base {
:root {
/* Light theme */
--background: 0 0% 100%;
--background: oklch(0.97 0.02 250);
--foreground: 222.2 84% 4.9%;
--foreground: oklch(0.40 0.03 265);
@plugin 'tailwindcss-animate';
--card: 0 0% 100%;
--card: oklch(0.92 0.02 260);
--card-foreground: 222.2 84% 4.9%;
--card-foreground: oklch(0.40 0.03 265);
@custom-variant dark (&:is(.dark *));
--popover: 0 0% 100%;
--popover: oklch(0.92 0.02 260);
--popover-foreground: 222.2 84% 4.9%;
--popover-foreground: oklch(0.40 0.03 265);
@theme {
--radius-lg: var(--radius);
--radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px);
--primary: 222.2 47.4% 11.2%;
--primary: oklch(0.60 0.20 260);
--primary-foreground: 210 40% 98%;
--primary-foreground: oklch(0.97 0.02 250);
--color-background: oklch(var(--background));
--color-foreground: oklch(var(--foreground));
--secondary: 210 40% 96.1%;
--secondary: oklch(0.87 0.03 255);
--secondary-foreground: 222.2 47.4% 11.2%;
--secondary-foreground: oklch(0.40 0.03 265);
--color-card: oklch(var(--card));
--color-card-foreground: oklch(var(--card-foreground));
--muted: 210 40% 96.1%;
--muted: oklch(0.87 0.03 255);
--muted-foreground: 215.4 16.3% 46.9%;
--muted-foreground: oklch(0.55 0.03 265);
--color-popover: oklch(var(--popover));
--color-popover-foreground: oklch(var(--popover-foreground));
--accent: 210 40% 96.1%;
--accent: oklch(0.70 0.15 30);
--accent-foreground: 222.2 47.4% 11.2%;
--accent-foreground: oklch(0.97 0.02 250);
--color-primary: oklch(var(--primary));
--color-primary-foreground: oklch(var(--primary-foreground));
--destructive: 0 84.2% 60.2%;
--destructive: oklch(0.50 0.28 15);
--destructive-foreground: 210 40% 98%;
--destructive-foreground: oklch(0.97 0.02 250);
--color-secondary: oklch(var(--secondary));
--color-secondary-foreground: oklch(var(--secondary-foreground));
--border: 214.3 31.8% 91.4%;
--border: oklch(0.83 0.02 265);
--input: 214.3 31.8% 91.4%;
--input: oklch(0.83 0.02 265);
--ring: 222.2 84% 4.9%;
--ring: oklch(0.60 0.20 260);
--color-muted: oklch(var(--muted));
--color-muted-foreground: oklch(var(--muted-foreground));
--radius: 0.5rem;
--color-accent: oklch(var(--accent));
--color-accent-foreground: oklch(var(--accent-foreground));
--chart-1: 12 76% 61%;
--color-destructive: oklch(var(--destructive));
--color-destructive-foreground: oklch(var(--destructive-foreground));
--chart-2: 173 58% 39%;
--color-border: oklch(var(--border));
--color-input: oklch(var(--input));
--color-ring: oklch(var(--ring));
--chart-3: 197 37% 24%;
--color-chart-1: oklch(var(--chart-1));
--color-chart-2: oklch(var(--chart-2));
--color-chart-3: oklch(var(--chart-3));
--color-chart-4: oklch(var(--chart-4));
--color-chart-5: oklch(var(--chart-5));
--chart-4: 43 74% 66%;
--animate-accordion-down: accordion-down 0.2s ease-out;
--animate-accordion-up: accordion-up 0.2s ease-out;
--chart-5: 27 87% 67%;
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(--reka-accordion-content-height);
}
}
.dark {
/* Dark theme */
--background: 222.2 84% 4.9%;
--background: oklch(0.25 0.05 265);
--foreground: 210 40% 98%;
--foreground: oklch(0.90 0.03 260);
--card: 222.2 84% 4.9%;
--card: oklch(0.20 0.05 265);
--card-foreground: 210 40% 98%;
--card-foreground: oklch(0.90 0.03 260);
--popover: 222.2 84% 4.9%;
--popover: oklch(0.20 0.05 265);
--popover-foreground: 210 40% 98%;
--popover-foreground: oklch(0.90 0.03 260);
--primary: 210 40% 98%;
--primary: oklch(0.75 0.15 260);
--primary-foreground: 222.2 47.4% 11.2%;
--primary-foreground: oklch(0.25 0.05 265);
--secondary: 217.2 32.6% 17.5%;
--secondary: oklch(0.30 0.06 265);
--secondary-foreground: 210 40% 98%;
--secondary-foreground: oklch(0.90 0.03 260);
--muted: 217.2 32.6% 17.5%;
--muted: oklch(0.30 0.06 265);
--muted-foreground: 215 20.2% 65.1%;
--muted-foreground: oklch(0.78 0.06 265);
--accent: 217.2 32.6% 17.5%;
--accent: oklch(0.83 0.12 30);
--accent-foreground: 210 40% 98%;
--accent-foreground: oklch(0.25 0.05 265);
--destructive: 0 62.8% 30.6%;
--destructive: oklch(0.75 0.18 15);
--destructive-foreground: 210 40% 98%;
--destructive-foreground: oklch(0.25 0.05 265);
--border: 217.2 32.6% 17.5%;
--border: oklch(0.30 0.06 265);
--input: 217.2 32.6% 17.5%;
--input: oklch(0.30 0.06 265);
--ring: 212.7 26.8% 83.9%;
--ring: oklch(0.75 0.15 260);
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}
@layer base {
* {
@apply box-border;
}
body {
@apply bg-background text-foreground;
font-feature-settings: "rlig" 1, "calt" 1;
}
}
@layer utilities {
.bg-background {
background-color: var(--background);
}
.bg-foreground {
background-color: var(--foreground);
}
.bg-card {
background-color: var(--card);
}
.bg-card-foreground {
background-color: var(--card-foreground);
}
.bg-popover {
background-color: var(--popover);
}
.bg-popover-foreground {
background-color: var(--popover-foreground);
}
.bg-primary {
background-color: var(--primary);
}
.bg-primary-foreground {
background-color: var(--primary-foreground);
}
.bg-secondary {
background-color: var(--secondary);
}
.bg-secondary-foreground {
background-color: var(--secondary-foreground);
}
.bg-muted {
background-color: var(--muted);
}
.bg-muted-foreground {
background-color: var(--muted-foreground);
}
.bg-accent {
background-color: var(--accent);
}
.bg-accent-foreground {
background-color: var(--accent-foreground);
}
.bg-destructive {
background-color: var(--destructive);
}
.bg-destructive-foreground {
background-color: var(--destructive-foreground);
}
.text-background {
color: var(--background);
}
.text-foreground {
color: var(--foreground);
}
.text-card {
color: var(--card);
}
.text-card-foreground {
color: var(--card-foreground);
}
.text-popover {
color: var(--popover);
}
.text-popover-foreground {
color: var(--popover-foreground);
}
.text-primary {
color: var(--primary);
}
.text-primary-foreground {
color: var(--primary-foreground);
}
.text-secondary {
color: var(--secondary);
}
.text-secondary-foreground {
color: var(--secondary-foreground);
}
.text-muted {
color: var(--muted);
}
.text-muted-foreground {
color: var(--muted-foreground);
}
.text-accent {
color: var(--accent);
}
.text-accent-foreground {
color: var(--accent-foreground);
}
.text-destructive {
color: var(--destructive);
}
.text-destructive-foreground {
color: var(--destructive-foreground);
}
@supports not (backdrop-filter: blur(1px)) {
.select-content {
background-color: var(--background);
@keyframes accordion-up {
from {
height: var(--reka-accordion-content-height);
}
to {
height: 0;
}
}
}
/* Add support for ring colors */
@layer utilities {
.ring-border {
--tw-ring-color: var(--border);
}
.ring-primary {
--tw-ring-color: var(--primary);
}
.ring-background {
--tw-ring-color: var(--background);
/*
The default border color has changed to `currentColor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
/* Add support for border colors */
@layer utilities {
.border {
border-color: var(--border);
@layer base {
:root {
/* Catppuccin Latte */
--background: 0.97 0.005 235; /* base */
--foreground: 0.30 0.02 235; /* text */
--card: 0.97 0.005 235;
--card-foreground: 0.30 0.02 235;
--popover: 0.97 0.005 235;
--popover-foreground: 0.30 0.02 235;
--primary: 0.55 0.15 250; /* lavender */
--primary-foreground: 0.97 0.005 235;
--secondary: 0.90 0.03 235; /* surface1 */
--secondary-foreground: 0.30 0.02 235;
--muted: 0.93 0.02 235; /* surface0 */
--muted-foreground: 0.50 0.02 235; /* subtext0 */
--accent: 0.65 0.15 290; /* mauve */
--accent-foreground: 0.30 0.02 235;
--destructive: 0.65 0.25 0; /* red */
--destructive-foreground: 0.97 0.005 235;
--border: 0.90 0.03 235; /* surface1 */
--input: 0.90 0.03 235;
--ring: 0.55 0.15 250; /* lavender */
--chart-1: 0.65 0.25 0; /* red */
--chart-2: 0.75 0.20 30; /* peach */
--chart-3: 0.80 0.15 90; /* yellow */
--chart-4: 0.70 0.15 150; /* green */
--chart-5: 0.60 0.15 180; /* blue */
--radius: 0.5rem;
}
.border-x {
border-left-color: var(--border);
border-right-color: var(--border);
}
.border-y {
border-top-color: var(--border);
border-bottom-color: var(--border);
}
.border-t {
border-top-color: var(--border);
}
.border-r {
border-right-color: var(--border);
}
.border-b {
border-bottom-color: var(--border);
}
.border-l {
border-left-color: var(--border);
}
.border-primary {
border-color: var(--primary);
}
.border-background {
border-color: var(--background);
}
.border-foreground {
border-color: var(--foreground);
}
.border-card {
border-color: var(--card);
}
.border-card-foreground {
border-color: var(--card-foreground);
}
.border-muted {
border-color: var(--muted);
}
.border-muted-foreground {
border-color: var(--muted-foreground);
}
.border-accent {
border-color: var(--accent);
}
.border-accent-foreground {
border-color: var(--accent-foreground);
}
.border-destructive {
border-color: var(--destructive);
}
.border-destructive-foreground {
border-color: var(--destructive-foreground);
.dark {
/* Catppuccin Mocha */
--background: 0.20 0.02 235; /* base */
--foreground: 0.90 0.02 235; /* text */
--card: 0.20 0.02 235;
--card-foreground: 0.90 0.02 235;
--popover: 0.20 0.02 235;
--popover-foreground: 0.90 0.02 235;
--primary: 0.55 0.15 250; /* lavender */
--primary-foreground: 0.20 0.02 235;
--secondary: 0.25 0.02 235; /* surface1 */
--secondary-foreground: 0.90 0.02 235;
--muted: 0.23 0.02 235; /* surface0 */
--muted-foreground: 0.70 0.02 235; /* subtext0 */
--accent: 0.65 0.15 290; /* mauve */
--accent-foreground: 0.90 0.02 235;
--destructive: 0.65 0.25 0; /* red */
--destructive-foreground: 0.90 0.02 235;
--border: 0.25 0.02 235; /* surface1 */
--input: 0.25 0.02 235;
--ring: 0.55 0.15 250; /* lavender */
--chart-1: 0.65 0.25 0; /* red */
--chart-2: 0.75 0.20 30; /* peach */
--chart-3: 0.80 0.15 90; /* yellow */
--chart-4: 0.70 0.15 150; /* green */
--chart-5: 0.60 0.15 180; /* blue */
}
}
@layer base {
* {
@apply border-border;

View file

@ -4,7 +4,7 @@ import {
type AccordionRootEmits,
type AccordionRootProps,
useForwardPropsEmits,
} from 'radix-vue'
} from 'reka-ui'
const props = defineProps<AccordionRootProps>()
const emits = defineEmits<AccordionRootEmits>()

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { AccordionContent, type AccordionContentProps } from 'radix-vue'
import { AccordionContent, type AccordionContentProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<AccordionContentProps & { class?: HTMLAttributes['class'] }>()
@ -15,7 +15,7 @@ const delegatedProps = computed(() => {
<template>
<AccordionContent
v-bind="delegatedProps"
class="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
class="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
>
<div :class="cn('pb-4 pt-0', props.class)">
<slot />

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { AccordionItem, type AccordionItemProps, useForwardProps } from 'radix-vue'
import { AccordionItem, type AccordionItemProps, useForwardProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<AccordionItemProps & { class?: HTMLAttributes['class'] }>()

View file

@ -5,7 +5,7 @@ import {
AccordionHeader,
AccordionTrigger,
type AccordionTriggerProps,
} from 'radix-vue'
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<AccordionTriggerProps & { class?: HTMLAttributes['class'] }>()
@ -23,7 +23,7 @@ const delegatedProps = computed(() => {
v-bind="delegatedProps"
:class="
cn(
'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
'flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
props.class,
)
"
@ -31,7 +31,7 @@ const delegatedProps = computed(() => {
<slot />
<slot name="icon">
<ChevronDown
class="h-4 w-4 shrink-0 transition-transform duration-200"
class="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200"
/>
</slot>
</AccordionTrigger>

View file

@ -1,16 +1,21 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import { AvatarRoot } from 'reka-ui'
import { avatarVariant, type AvatarVariants } from '.'
const props = defineProps<{
const props = withDefaults(defineProps<{
class?: HTMLAttributes['class']
}>()
size?: AvatarVariants['size']
shape?: AvatarVariants['shape']
}>(), {
size: 'sm',
shape: 'circle',
})
</script>
<template>
<div
:class="cn('relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full', props.class)"
>
<AvatarRoot :class="cn(avatarVariant({ size, shape }), props.class)">
<slot />
</div>
</AvatarRoot>
</template>

View file

@ -1,16 +1,11 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import { AvatarFallback, type AvatarFallbackProps } from 'reka-ui'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
const props = defineProps<AvatarFallbackProps>()
</script>
<template>
<div
:class="cn('flex h-full w-full items-center justify-center rounded-full bg-muted', props.class)"
>
<AvatarFallback v-bind="props">
<slot />
</div>
</AvatarFallback>
</template>

View file

@ -1,18 +1,12 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import type { AvatarImageProps } from 'reka-ui'
import { AvatarImage } from 'reka-ui'
const props = defineProps<{
src?: string
alt?: string
class?: HTMLAttributes['class']
}>()
const props = defineProps<AvatarImageProps>()
</script>
<template>
<img
:src="src"
:alt="alt"
:class="cn('aspect-square h-full w-full', props.class)"
/>
<AvatarImage v-bind="props" class="h-full w-full object-cover">
<slot />
</AvatarImage>
</template>

View file

@ -1,3 +1,24 @@
import { cva, type VariantProps } from 'class-variance-authority'
export { default as Avatar } from './Avatar.vue'
export { default as AvatarImage } from './AvatarImage.vue'
export { default as AvatarFallback } from './AvatarFallback.vue'
export { default as AvatarImage } from './AvatarImage.vue'
export const avatarVariant = cva(
'inline-flex items-center justify-center font-normal text-foreground select-none shrink-0 bg-secondary overflow-hidden',
{
variants: {
size: {
sm: 'h-10 w-10 text-xs',
base: 'h-16 w-16 text-2xl',
lg: 'h-32 w-32 text-5xl',
},
shape: {
circle: 'rounded-full',
square: 'rounded-md',
},
},
},
)
export type AvatarVariants = VariantProps<typeof avatarVariant>

View file

@ -10,7 +10,7 @@ const props = defineProps<{
</script>
<template>
<span :class="cn(badgeVariants({ variant: props.variant }), props.class)">
<div :class="cn(badgeVariants({ variant }), props.class)">
<slot />
</span>
</div>
</template>

View file

@ -3,21 +3,17 @@ import { cva, type VariantProps } from 'class-variance-authority'
export { default as Badge } from './Badge.vue'
export const badgeVariants = cva(
'inline-flex items-center whitespace-nowrap rounded-full border px-1.5 py-0.5 text-[10px] font-medium transition-colors',
'inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2',
{
variants: {
variant: {
default:
'border-transparent bg-primary/10 text-primary hover:bg-primary/20',
'border-transparent bg-primary text-primary-foreground shadow-sm hover:bg-primary/80',
secondary:
'border-transparent bg-secondary/10 text-secondary-foreground hover:bg-secondary/20',
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
destructive:
'border-transparent bg-destructive/10 text-destructive hover:bg-destructive/20',
success:
'border-transparent bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400',
warning:
'border-transparent bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400',
outline: 'border-border text-foreground hover:bg-accent hover:text-accent-foreground',
'border-transparent bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/80',
outline: 'text-foreground',
},
},
defaultVariants: {

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import { Primitive, type PrimitiveProps } from 'radix-vue'
import { Primitive, type PrimitiveProps } from 'reka-ui'
import { type ButtonVariants, buttonVariants } from '.'
interface Props extends PrimitiveProps {
@ -16,7 +16,11 @@ const props = withDefaults(defineProps<Props>(), {
</script>
<template>
<Primitive :as="as" :as-child="asChild" :class="cn(buttonVariants({ variant, size }), props.class)">
<Primitive
:as="as"
:as-child="asChild"
:class="cn(buttonVariants({ variant, size }), props.class)"
>
<slot />
</Primitive>
</template>

View file

@ -3,23 +3,23 @@ import { cva, type VariantProps } from 'class-variance-authority'
export { default as Button } from './Button.vue'
export const buttonVariants = cva(
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium 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 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
{
variants: {
variant: {
default:
'bg-primary text-primary-foreground shadow hover:bg-primary/90',
default: 'bg-primary text-primary-foreground shadow-sm hover:bg-primary/90',
destructive:
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
'bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90',
outline:
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
'border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground',
secondary:
'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
default: 'h-9 px-4 py-2',
xs: 'h-7 rounded px-2',
sm: 'h-8 rounded-md px-3 text-xs',
lg: 'h-10 rounded-md px-8',
icon: 'h-9 w-9',

View file

@ -9,7 +9,12 @@ const props = defineProps<{
<template>
<div
:class="cn('rounded-lg border bg-card text-card-foreground shadow-sm', props.class)"
:class="
cn(
'rounded-xl border bg-card text-card-foreground shadow-sm',
props.class,
)
"
>
<slot />
</div>

View file

@ -8,11 +8,7 @@ const props = defineProps<{
</script>
<template>
<div
:class="
cn('p-6 pt-0', props.class)
"
>
<div :class="cn('p-6 pt-0', props.class)">
<slot />
</div>
</template>

View file

@ -8,11 +8,7 @@ const props = defineProps<{
</script>
<template>
<p
:class="
cn('text-sm text-muted-foreground', props.class)
"
>
<p :class="cn('text-sm text-muted-foreground', props.class)">
<slot />
</p>
</template>

View file

@ -8,11 +8,7 @@ const props = defineProps<{
</script>
<template>
<div
:class="
cn('flex items-center p-6 pt-0', props.class)
"
>
<div :class="cn('flex items-center p-6 pt-0', props.class)">
<slot />
</div>
</template>

View file

@ -8,11 +8,7 @@ const props = defineProps<{
</script>
<template>
<div
:class="
cn('flex flex-col space-y-1.5 p-6', props.class)
"
>
<div :class="cn('flex flex-col gap-y-1.5 p-6', props.class)">
<slot />
</div>
</template>

View file

@ -10,7 +10,7 @@ const props = defineProps<{
<template>
<h3
:class="
cn('text-2xl font-semibold leading-none tracking-tight', props.class)
cn('font-semibold leading-none tracking-tight', props.class)
"
>
<slot />

View file

@ -1,19 +1,14 @@
<script setup lang="ts">
import { DialogRoot } from 'radix-vue'
import { DialogRoot, type DialogRootEmits, type DialogRootProps, useForwardPropsEmits } from 'reka-ui'
const props = defineProps<{
open?: boolean
defaultOpen?: boolean
modal?: boolean
}>()
const props = defineProps<DialogRootProps>()
const emits = defineEmits<DialogRootEmits>()
const emits = defineEmits<{
'update:open': [value: boolean]
}>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<DialogRoot v-bind="props" @update:open="emits('update:open', $event)">
<DialogRoot v-bind="forwarded">
<slot />
</DialogRoot>
</template>

View file

@ -0,0 +1,11 @@
<script setup lang="ts">
import { DialogClose, type DialogCloseProps } from 'reka-ui'
const props = defineProps<DialogCloseProps>()
</script>
<template>
<DialogClose v-bind="props">
<slot />
</DialogClose>
</template>

View file

@ -1,32 +1,50 @@
<script setup lang="ts">
import { DialogPortal, DialogOverlay, DialogContent as DialogContentPrimitive, DialogClose } from 'radix-vue'
import { X } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
import type { HTMLAttributes } from 'vue'
import { X } from 'lucide-vue-next'
import {
DialogClose,
DialogContent,
type DialogContentEmits,
type DialogContentProps,
DialogOverlay,
DialogPortal,
useForwardPropsEmits,
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
const props = defineProps<DialogContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DialogContentEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<DialogPortal>
<DialogOverlay
class="fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
class="fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
/>
<DialogContentPrimitive
:class="cn(
'fixed left-[50%] top-[50%] z-50 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg mx-auto',
props.class
)"
<DialogContent
v-bind="forwarded"
:class="
cn(
'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
props.class,
)"
>
<slot />
<DialogClose
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
>
<X class="h-4 w-4" />
<X class="w-4 h-4" />
<span class="sr-only">Close</span>
</DialogClose>
</DialogContentPrimitive>
</DialogContent>
</DialogPortal>
</template>

View file

@ -1,15 +1,24 @@
<script setup lang="ts">
import { DialogDescription as DialogDescriptionPrimitive } from 'radix-vue'
import { cn } from '@/lib/utils'
import type { HTMLAttributes } from 'vue'
import { DialogDescription, type DialogDescriptionProps, useForwardProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<DialogDescriptionPrimitive :class="cn('text-sm text-muted-foreground', props.class)">
<DialogDescription
v-bind="forwardedProps"
:class="cn('text-sm text-muted-foreground', props.class)"
>
<slot />
</DialogDescriptionPrimitive>
</DialogDescription>
</template>

View file

@ -1,14 +1,19 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
const props = defineProps<{ class?: HTMLAttributes['class'] }>()
</script>
<template>
<div :class="cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', props.class)">
<div
:class="
cn(
'flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-x-2',
props.class,
)
"
>
<slot />
</div>
</template>

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
@ -8,7 +8,9 @@ const props = defineProps<{
</script>
<template>
<div :class="cn('flex flex-col space-y-1.5 text-center sm:text-left', props.class)">
<div
:class="cn('flex flex-col gap-y-1.5 text-center sm:text-left', props.class)"
>
<slot />
</div>
</template>

View file

@ -0,0 +1,59 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { X } from 'lucide-vue-next'
import {
DialogClose,
DialogContent,
type DialogContentEmits,
type DialogContentProps,
DialogOverlay,
DialogPortal,
useForwardPropsEmits,
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<DialogContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DialogContentEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<DialogPortal>
<DialogOverlay
class="fixed inset-0 z-50 grid place-items-center overflow-y-auto bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
>
<DialogContent
:class="
cn(
'relative z-50 grid w-full max-w-lg my-8 gap-4 border border-border bg-background p-6 shadow-lg duration-200 sm:rounded-lg md:w-full',
props.class,
)
"
v-bind="forwarded"
@pointer-down-outside="(event) => {
const originalEvent = event.detail.originalEvent;
const target = originalEvent.target as HTMLElement;
if (originalEvent.offsetX > target.clientWidth || originalEvent.offsetY > target.clientHeight) {
event.preventDefault();
}
}"
>
<slot />
<DialogClose
class="absolute top-4 right-4 p-0.5 transition-colors rounded-md hover:bg-secondary"
>
<X class="w-4 h-4" />
<span class="sr-only">Close</span>
</DialogClose>
</DialogContent>
</DialogOverlay>
</DialogPortal>
</template>

View file

@ -1,15 +1,29 @@
<script setup lang="ts">
import { DialogTitle as DialogTitlePrimitive } from 'radix-vue'
import { cn } from '@/lib/utils'
import type { HTMLAttributes } from 'vue'
import { DialogTitle, type DialogTitleProps, useForwardProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<DialogTitlePrimitive :class="cn('text-lg font-semibold leading-none tracking-tight', props.class)">
<DialogTitle
v-bind="forwardedProps"
:class="
cn(
'text-lg font-semibold leading-none tracking-tight',
props.class,
)
"
>
<slot />
</DialogTitlePrimitive>
</DialogTitle>
</template>

View file

@ -1,16 +1,11 @@
<script setup lang="ts">
import { DialogTrigger as DialogTriggerPrimitive } from 'radix-vue'
import { cn } from '@/lib/utils'
import type { HTMLAttributes } from 'vue'
import { DialogTrigger, type DialogTriggerProps } from 'reka-ui'
const props = defineProps<{
class?: HTMLAttributes['class']
asChild?: boolean
}>()
const props = defineProps<DialogTriggerProps>()
</script>
<template>
<DialogTriggerPrimitive v-bind="props" :class="cn(props.class)">
<DialogTrigger v-bind="props">
<slot />
</DialogTriggerPrimitive>
</DialogTrigger>
</template>

View file

@ -1,17 +1,9 @@
export { default as Dialog } from './Dialog.vue'
export { default as DialogClose } from './DialogClose.vue'
export { default as DialogContent } from './DialogContent.vue'
export { default as DialogDescription } from './DialogDescription.vue'
export { default as DialogFooter } from './DialogFooter.vue'
export { default as DialogHeader } from './DialogHeader.vue'
export { default as DialogScrollContent } from './DialogScrollContent.vue'
export { default as DialogTitle } from './DialogTitle.vue'
export { default as DialogTrigger } from './DialogTrigger.vue'
export type {
DialogRootEmits,
DialogRootProps,
DialogOverlayProps,
DialogPortalProps,
DialogContentProps,
DialogTitleProps,
DialogTriggerProps,
} from 'radix-vue'

View file

@ -1,17 +1,14 @@
<script setup lang="ts">
import { DropdownMenuRoot } from 'radix-vue'
import { DropdownMenuRoot, type DropdownMenuRootEmits, type DropdownMenuRootProps, useForwardPropsEmits } from 'reka-ui'
defineOptions({
name: 'DropdownMenu'
})
const props = defineProps<DropdownMenuRootProps>()
const emits = defineEmits<DropdownMenuRootEmits>()
defineSlots<{
default?: (props: {}) => any
}>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<DropdownMenuRoot v-bind="$attrs">
<DropdownMenuRoot v-bind="forwarded">
<slot />
</DropdownMenuRoot>
</template>

View file

@ -0,0 +1,40 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { Check } from 'lucide-vue-next'
import {
DropdownMenuCheckboxItem,
type DropdownMenuCheckboxItemEmits,
type DropdownMenuCheckboxItemProps,
DropdownMenuItemIndicator,
useForwardPropsEmits,
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<DropdownMenuCheckboxItemProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DropdownMenuCheckboxItemEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<DropdownMenuCheckboxItem
v-bind="forwarded"
:class=" cn(
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50',
props.class,
)"
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuItemIndicator>
<Check class="w-4 h-4" />
</DropdownMenuItemIndicator>
</span>
<slot />
</DropdownMenuCheckboxItem>
</template>

View file

@ -1,31 +1,38 @@
<script setup lang="ts">
import { DropdownMenuContent, type DropdownMenuContentProps } from 'radix-vue'
import { cn } from '@/lib/utils'
defineOptions({
name: 'DropdownMenuContent'
})
import {
DropdownMenuContent,
type DropdownMenuContentEmits,
type DropdownMenuContentProps,
DropdownMenuPortal,
useForwardPropsEmits,
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = withDefaults(
defineProps<DropdownMenuContentProps & {
class?: string
}>(),
defineProps<DropdownMenuContentProps & { class?: HTMLAttributes['class'] }>(),
{
sideOffset: 4,
align: 'start',
class: ''
}
},
)
const emits = defineEmits<DropdownMenuContentEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<DropdownMenuContent
:class="cn(
'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground 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',
props.class
)"
v-bind="{ ...props, ...$attrs }"
>
<slot />
</DropdownMenuContent>
<DropdownMenuPortal>
<DropdownMenuContent
v-bind="forwarded"
:class="cn('z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground 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', props.class)"
>
<slot />
</DropdownMenuContent>
</DropdownMenuPortal>
</template>

View file

@ -0,0 +1,11 @@
<script setup lang="ts">
import { DropdownMenuGroup, type DropdownMenuGroupProps } from 'reka-ui'
const props = defineProps<DropdownMenuGroupProps>()
</script>
<template>
<DropdownMenuGroup v-bind="props">
<slot />
</DropdownMenuGroup>
</template>

View file

@ -1,33 +1,27 @@
<script setup lang="ts">
import { DropdownMenuItem, type DropdownMenuItemProps } from 'radix-vue'
import { cn } from '@/lib/utils'
import { DropdownMenuItem, type DropdownMenuItemProps, useForwardProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
defineOptions({
name: 'DropdownMenuItem'
const props = defineProps<DropdownMenuItemProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const props = withDefaults(
defineProps<
DropdownMenuItemProps & {
class?: string
inset?: boolean
}
>(),
{
class: '',
inset: false
}
)
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<DropdownMenuItem
v-bind="forwardedProps"
:class="cn(
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
'relative flex cursor-default select-none items-center rounded-sm gap-2 px-2 py-1.5 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0',
inset && 'pl-8',
props.class
props.class,
)"
v-bind="{ ...props, ...$attrs }"
>
<slot />
</DropdownMenuItem>

View file

@ -0,0 +1,24 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { DropdownMenuLabel, type DropdownMenuLabelProps, useForwardProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<DropdownMenuLabelProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<DropdownMenuLabel
v-bind="forwardedProps"
:class="cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', props.class)"
>
<slot />
</DropdownMenuLabel>
</template>

View file

@ -0,0 +1,19 @@
<script setup lang="ts">
import {
DropdownMenuRadioGroup,
type DropdownMenuRadioGroupEmits,
type DropdownMenuRadioGroupProps,
useForwardPropsEmits,
} from 'reka-ui'
const props = defineProps<DropdownMenuRadioGroupProps>()
const emits = defineEmits<DropdownMenuRadioGroupEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<DropdownMenuRadioGroup v-bind="forwarded">
<slot />
</DropdownMenuRadioGroup>
</template>

View file

@ -0,0 +1,41 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { Circle } from 'lucide-vue-next'
import {
DropdownMenuItemIndicator,
DropdownMenuRadioItem,
type DropdownMenuRadioItemEmits,
type DropdownMenuRadioItemProps,
useForwardPropsEmits,
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<DropdownMenuRadioItemProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DropdownMenuRadioItemEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<DropdownMenuRadioItem
v-bind="forwarded"
:class="cn(
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50',
props.class,
)"
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuItemIndicator>
<Circle class="h-4 w-4 fill-current" />
</DropdownMenuItemIndicator>
</span>
<slot />
</DropdownMenuRadioItem>
</template>

View file

@ -0,0 +1,22 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import {
DropdownMenuSeparator,
type DropdownMenuSeparatorProps,
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<DropdownMenuSeparatorProps & {
class?: HTMLAttributes['class']
}>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<DropdownMenuSeparator v-bind="delegatedProps" :class="cn('-mx-1 my-1 h-px bg-muted', props.class)" />
</template>

View file

@ -0,0 +1,14 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<span :class="cn('ml-auto text-xs tracking-widest opacity-60', props.class)">
<slot />
</span>
</template>

View file

@ -0,0 +1,19 @@
<script setup lang="ts">
import {
DropdownMenuSub,
type DropdownMenuSubEmits,
type DropdownMenuSubProps,
useForwardPropsEmits,
} from 'reka-ui'
const props = defineProps<DropdownMenuSubProps>()
const emits = defineEmits<DropdownMenuSubEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<DropdownMenuSub v-bind="forwarded">
<slot />
</DropdownMenuSub>
</template>

View file

@ -0,0 +1,30 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import {
DropdownMenuSubContent,
type DropdownMenuSubContentEmits,
type DropdownMenuSubContentProps,
useForwardPropsEmits,
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<DropdownMenuSubContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DropdownMenuSubContentEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<DropdownMenuSubContent
v-bind="forwarded"
:class="cn('z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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)"
>
<slot />
</DropdownMenuSubContent>
</template>

View file

@ -0,0 +1,33 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { ChevronRight } from 'lucide-vue-next'
import {
DropdownMenuSubTrigger,
type DropdownMenuSubTriggerProps,
useForwardProps,
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<DropdownMenuSubTriggerProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<DropdownMenuSubTrigger
v-bind="forwardedProps"
:class="cn(
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent data-[state=open]:bg-accent',
props.class,
)"
>
<slot />
<ChevronRight class="ml-auto h-4 w-4" />
</DropdownMenuSubTrigger>
</template>

View file

@ -1,22 +1,13 @@
<script setup lang="ts">
import { DropdownMenuTrigger } from 'radix-vue'
import { DropdownMenuTrigger, type DropdownMenuTriggerProps, useForwardProps } from 'reka-ui'
defineOptions({
name: 'DropdownMenuTrigger'
})
const props = defineProps<DropdownMenuTriggerProps>()
const props = withDefaults(
defineProps<{
asChild?: boolean
}>(),
{
asChild: false
}
)
const forwardedProps = useForwardProps(props)
</script>
<template>
<DropdownMenuTrigger v-bind="{ ...props, ...$attrs }">
<DropdownMenuTrigger class="outline-hidden" v-bind="forwardedProps">
<slot />
</DropdownMenuTrigger>
</template>

View file

@ -1,4 +1,16 @@
export { default as DropdownMenu } from './DropdownMenu.vue'
export { default as DropdownMenuTrigger } from './DropdownMenuTrigger.vue'
export { default as DropdownMenuCheckboxItem } from './DropdownMenuCheckboxItem.vue'
export { default as DropdownMenuContent } from './DropdownMenuContent.vue'
export { default as DropdownMenuGroup } from './DropdownMenuGroup.vue'
export { default as DropdownMenuItem } from './DropdownMenuItem.vue'
export { default as DropdownMenuLabel } from './DropdownMenuLabel.vue'
export { default as DropdownMenuRadioGroup } from './DropdownMenuRadioGroup.vue'
export { default as DropdownMenuRadioItem } from './DropdownMenuRadioItem.vue'
export { default as DropdownMenuSeparator } from './DropdownMenuSeparator.vue'
export { default as DropdownMenuShortcut } from './DropdownMenuShortcut.vue'
export { default as DropdownMenuSub } from './DropdownMenuSub.vue'
export { default as DropdownMenuSubContent } from './DropdownMenuSubContent.vue'
export { default as DropdownMenuSubTrigger } from './DropdownMenuSubTrigger.vue'
export { default as DropdownMenuTrigger } from './DropdownMenuTrigger.vue'
export { DropdownMenuPortal } from 'reka-ui'

View file

@ -20,5 +20,5 @@ const modelValue = useVModel(props, 'modelValue', emits, {
</script>
<template>
<input v-model="modelValue" :class="cn('flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium 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', props.class)">
<input v-model="modelValue" :class="cn('flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50', props.class)">
</template>

View file

@ -0,0 +1,27 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { Label, type LabelProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<LabelProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<Label
v-bind="delegatedProps"
:class="
cn(
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
props.class,
)
"
>
<slot />
</Label>
</template>

View file

@ -1,8 +1 @@
import { Label as LabelPrimitive } from 'radix-vue'
import { tv } from 'tailwind-variants'
export const labelVariants = tv({
base: 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'
})
export const Label = LabelPrimitive.Root
export { default as Label } from './Label.vue'

View file

@ -5,7 +5,7 @@ import {
ScrollAreaRoot,
type ScrollAreaRootProps,
ScrollAreaViewport,
} from 'radix-vue'
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
import ScrollBar from './ScrollBar.vue'

View file

@ -1,17 +1,11 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import {
ScrollAreaScrollbar,
ScrollAreaThumb,
type ScrollAreaScrollbarProps,
} from 'radix-vue'
import { ScrollAreaScrollbar, type ScrollAreaScrollbarProps, ScrollAreaThumb } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<
ScrollAreaScrollbarProps & {
class?: HTMLAttributes['class']
}
>()
const props = withDefaults(defineProps<ScrollAreaScrollbarProps & { class?: HTMLAttributes['class'] }>(), {
orientation: 'vertical',
})
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
@ -23,20 +17,14 @@ const delegatedProps = computed(() => {
<template>
<ScrollAreaScrollbar
v-bind="delegatedProps"
:class="cn(
'flex touch-none select-none transition-colors',
props.orientation === 'vertical' &&
'h-full w-2.5 border-l border-l-transparent p-[1px]',
props.orientation === 'horizontal' &&
'h-2.5 border-t border-t-transparent p-[1px]',
props.class
)"
:class="
cn('flex touch-none select-none transition-colors',
orientation === 'vertical'
&& 'h-full w-2.5 border-l border-l-transparent p-px',
orientation === 'horizontal'
&& 'h-2.5 flex-col border-t border-t-transparent p-px',
props.class)"
>
<ScrollAreaThumb
:class="cn(
'relative rounded-full bg-border',
props.orientation === 'vertical' && 'flex-1'
)"
/>
<ScrollAreaThumb class="relative flex-1 rounded-full bg-border" />
</ScrollAreaScrollbar>
</template>

View file

@ -1 +1,2 @@
export { default as ScrollArea } from './ScrollArea.vue'
export { default as ScrollBar } from './ScrollBar.vue'

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import type { SelectRootEmits, SelectRootProps } from 'radix-vue'
import { SelectRoot, useForwardPropsEmits } from 'radix-vue'
import type { SelectRootEmits, SelectRootProps } from 'reka-ui'
import { SelectRoot, useForwardPropsEmits } from 'reka-ui'
const props = defineProps<SelectRootProps>()
const emits = defineEmits<SelectRootEmits>()

View file

@ -7,7 +7,7 @@ import {
SelectPortal,
SelectViewport,
useForwardPropsEmits,
} from 'radix-vue'
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
import { SelectScrollDownButton, SelectScrollUpButton } from '.'
@ -37,9 +37,6 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
<SelectContent
v-bind="{ ...forwarded, ...$attrs }" :class="cn(
'relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground 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',
'bg-background dark:bg-background',
'backdrop-blur-sm backdrop-saturate-150 bg-opacity-90 dark:bg-opacity-90',
'[&>div]:bg-background [&>div]:dark:bg-background',
position === 'popper'
&& 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
props.class,
@ -47,7 +44,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
"
>
<SelectScrollUpButton />
<SelectViewport :class="cn('p-1', position === 'popper' && 'h-[--radix-select-trigger-height] w-full min-w-[--radix-select-trigger-width]')">
<SelectViewport :class="cn('p-1', position === 'popper' && 'h-(--reka-select-trigger-height) w-full min-w-(--reka-select-trigger-width)')">
<slot />
</SelectViewport>
<SelectScrollDownButton />

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { SelectGroup, type SelectGroupProps } from 'radix-vue'
import { SelectGroup, type SelectGroupProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<SelectGroupProps & { class?: HTMLAttributes['class'] }>()

View file

@ -7,7 +7,7 @@ import {
type SelectItemProps,
SelectItemText,
useForwardProps,
} from 'radix-vue'
} from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<SelectItemProps & { class?: HTMLAttributes['class'] }>()
@ -26,14 +26,12 @@ const forwardedProps = useForwardProps(delegatedProps)
v-bind="forwardedProps"
:class="
cn(
'relative flex w-full 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',
'hover:bg-accent/50',
'active:bg-accent/70',
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50',
props.class,
)
"
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<span class="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectItemIndicator>
<Check class="h-4 w-4" />
</SelectItemIndicator>

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { SelectItemText, type SelectItemTextProps } from 'radix-vue'
import { SelectItemText, type SelectItemTextProps } from 'reka-ui'
const props = defineProps<SelectItemTextProps>()
</script>

View file

@ -1,13 +1,13 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import { SelectLabel, type SelectLabelProps } from 'radix-vue'
import { SelectLabel, type SelectLabelProps } from 'reka-ui'
const props = defineProps<SelectLabelProps & { class?: HTMLAttributes['class'] }>()
</script>
<template>
<SelectLabel :class="cn('py-1.5 pl-8 pr-2 text-sm font-semibold', props.class)">
<SelectLabel :class="cn('px-2 py-1.5 text-sm font-semibold', props.class)">
<slot />
</SelectLabel>
</template>

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { ChevronDown } from 'lucide-vue-next'
import { SelectScrollDownButton, type SelectScrollDownButtonProps, useForwardProps } from 'radix-vue'
import { SelectScrollDownButton, type SelectScrollDownButtonProps, useForwardProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<SelectScrollDownButtonProps & { class?: HTMLAttributes['class'] }>()
@ -18,7 +18,7 @@ const forwardedProps = useForwardProps(delegatedProps)
<template>
<SelectScrollDownButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
<slot>
<ChevronDown class="h-4 w-4" />
<ChevronDown />
</slot>
</SelectScrollDownButton>
</template>

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { ChevronUp } from 'lucide-vue-next'
import { SelectScrollUpButton, type SelectScrollUpButtonProps, useForwardProps } from 'radix-vue'
import { SelectScrollUpButton, type SelectScrollUpButtonProps, useForwardProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<SelectScrollUpButtonProps & { class?: HTMLAttributes['class'] }>()
@ -18,7 +18,7 @@ const forwardedProps = useForwardProps(delegatedProps)
<template>
<SelectScrollUpButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
<slot>
<ChevronUp class="h-4 w-4" />
<ChevronUp />
</slot>
</SelectScrollUpButton>
</template>

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { SelectSeparator, type SelectSeparatorProps } from 'radix-vue'
import { SelectSeparator, type SelectSeparatorProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<SelectSeparatorProps & { class?: HTMLAttributes['class'] }>()

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { ChevronDown } from 'lucide-vue-next'
import { SelectIcon, SelectTrigger, type SelectTriggerProps, useForwardProps } from 'radix-vue'
import { SelectIcon, SelectTrigger, type SelectTriggerProps, useForwardProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<SelectTriggerProps & { class?: HTMLAttributes['class'] }>()
@ -19,7 +19,7 @@ const forwardedProps = useForwardProps(delegatedProps)
<SelectTrigger
v-bind="forwardedProps"
:class="cn(
'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 data-[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',
'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-xs ring-offset-background data-placeholder:text-muted-foreground focus:outline-hidden focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:truncate text-start',
props.class,
)"
>

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { SelectValue, type SelectValueProps } from 'radix-vue'
import { SelectValue, type SelectValueProps } from 'reka-ui'
const props = defineProps<SelectValueProps>()
</script>

View file

@ -0,0 +1,22 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { TabsContent, type TabsContentProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<TabsContentProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<TabsContent
:class="cn('mt-2 ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2', props.class)"
v-bind="delegatedProps"
>
<slot />
</TabsContent>
</template>

View file

@ -0,0 +1,29 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
import { TabsTrigger, type TabsTriggerProps, useForwardProps } from 'reka-ui'
import { computed, type HTMLAttributes } from 'vue'
const props = defineProps<TabsTriggerProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<TabsTrigger
v-bind="forwardedProps"
:class="cn(
'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm',
props.class,
)"
>
<span class="truncate">
<slot />
</span>
</TabsTrigger>
</template>