fix tailwind
This commit is contained in:
parent
00f4bfa583
commit
f2a3f5e53e
63 changed files with 807 additions and 562 deletions
|
|
@ -1,314 +1,146 @@
|
||||||
@import "tailwindcss";
|
@import 'tailwindcss';
|
||||||
@config "../../tailwind.config.js";
|
|
||||||
|
@plugin 'tailwindcss-animate';
|
||||||
|
|
||||||
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--radius-lg: var(--radius);
|
||||||
|
--radius-md: calc(var(--radius) - 2px);
|
||||||
|
--radius-sm: calc(var(--radius) - 4px);
|
||||||
|
|
||||||
|
--color-background: oklch(var(--background));
|
||||||
|
--color-foreground: oklch(var(--foreground));
|
||||||
|
|
||||||
|
--color-card: oklch(var(--card));
|
||||||
|
--color-card-foreground: oklch(var(--card-foreground));
|
||||||
|
|
||||||
|
--color-popover: oklch(var(--popover));
|
||||||
|
--color-popover-foreground: oklch(var(--popover-foreground));
|
||||||
|
|
||||||
|
--color-primary: oklch(var(--primary));
|
||||||
|
--color-primary-foreground: oklch(var(--primary-foreground));
|
||||||
|
|
||||||
|
--color-secondary: oklch(var(--secondary));
|
||||||
|
--color-secondary-foreground: oklch(var(--secondary-foreground));
|
||||||
|
|
||||||
|
--color-muted: oklch(var(--muted));
|
||||||
|
--color-muted-foreground: oklch(var(--muted-foreground));
|
||||||
|
|
||||||
|
--color-accent: oklch(var(--accent));
|
||||||
|
--color-accent-foreground: oklch(var(--accent-foreground));
|
||||||
|
|
||||||
|
--color-destructive: oklch(var(--destructive));
|
||||||
|
--color-destructive-foreground: oklch(var(--destructive-foreground));
|
||||||
|
|
||||||
|
--color-border: oklch(var(--border));
|
||||||
|
--color-input: oklch(var(--input));
|
||||||
|
--color-ring: oklch(var(--ring));
|
||||||
|
|
||||||
|
--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));
|
||||||
|
|
||||||
|
--animate-accordion-down: accordion-down 0.2s ease-out;
|
||||||
|
--animate-accordion-up: accordion-up 0.2s ease-out;
|
||||||
|
|
||||||
|
@keyframes accordion-down {
|
||||||
|
from {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
height: var(--reka-accordion-content-height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes accordion-up {
|
||||||
|
from {
|
||||||
|
height: var(--reka-accordion-content-height);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
/* Light theme */
|
/* Catppuccin Latte */
|
||||||
--background: 0 0% 100%;
|
--background: 0.97 0.005 235; /* base */
|
||||||
--background: oklch(0.97 0.02 250);
|
--foreground: 0.30 0.02 235; /* text */
|
||||||
--foreground: 222.2 84% 4.9%;
|
--card: 0.97 0.005 235;
|
||||||
--foreground: oklch(0.40 0.03 265);
|
--card-foreground: 0.30 0.02 235;
|
||||||
|
--popover: 0.97 0.005 235;
|
||||||
--card: 0 0% 100%;
|
--popover-foreground: 0.30 0.02 235;
|
||||||
--card: oklch(0.92 0.02 260);
|
--primary: 0.55 0.15 250; /* lavender */
|
||||||
--card-foreground: 222.2 84% 4.9%;
|
--primary-foreground: 0.97 0.005 235;
|
||||||
--card-foreground: oklch(0.40 0.03 265);
|
--secondary: 0.90 0.03 235; /* surface1 */
|
||||||
|
--secondary-foreground: 0.30 0.02 235;
|
||||||
--popover: 0 0% 100%;
|
--muted: 0.93 0.02 235; /* surface0 */
|
||||||
--popover: oklch(0.92 0.02 260);
|
--muted-foreground: 0.50 0.02 235; /* subtext0 */
|
||||||
--popover-foreground: 222.2 84% 4.9%;
|
--accent: 0.65 0.15 290; /* mauve */
|
||||||
--popover-foreground: oklch(0.40 0.03 265);
|
--accent-foreground: 0.30 0.02 235;
|
||||||
|
--destructive: 0.65 0.25 0; /* red */
|
||||||
--primary: 222.2 47.4% 11.2%;
|
--destructive-foreground: 0.97 0.005 235;
|
||||||
--primary: oklch(0.60 0.20 260);
|
--border: 0.90 0.03 235; /* surface1 */
|
||||||
--primary-foreground: 210 40% 98%;
|
--input: 0.90 0.03 235;
|
||||||
--primary-foreground: oklch(0.97 0.02 250);
|
--ring: 0.55 0.15 250; /* lavender */
|
||||||
|
--chart-1: 0.65 0.25 0; /* red */
|
||||||
--secondary: 210 40% 96.1%;
|
--chart-2: 0.75 0.20 30; /* peach */
|
||||||
--secondary: oklch(0.87 0.03 255);
|
--chart-3: 0.80 0.15 90; /* yellow */
|
||||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
--chart-4: 0.70 0.15 150; /* green */
|
||||||
--secondary-foreground: oklch(0.40 0.03 265);
|
--chart-5: 0.60 0.15 180; /* blue */
|
||||||
|
|
||||||
--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);
|
|
||||||
|
|
||||||
--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);
|
|
||||||
|
|
||||||
--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);
|
|
||||||
|
|
||||||
--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);
|
|
||||||
|
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
|
|
||||||
--chart-1: 12 76% 61%;
|
|
||||||
|
|
||||||
--chart-2: 173 58% 39%;
|
|
||||||
|
|
||||||
--chart-3: 197 37% 24%;
|
|
||||||
|
|
||||||
--chart-4: 43 74% 66%;
|
|
||||||
|
|
||||||
--chart-5: 27 87% 67%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
/* Dark theme */
|
/* Catppuccin Mocha */
|
||||||
--background: 222.2 84% 4.9%;
|
--background: 0.20 0.02 235; /* base */
|
||||||
--background: oklch(0.25 0.05 265);
|
--foreground: 0.90 0.02 235; /* text */
|
||||||
--foreground: 210 40% 98%;
|
--card: 0.20 0.02 235;
|
||||||
--foreground: oklch(0.90 0.03 260);
|
--card-foreground: 0.90 0.02 235;
|
||||||
|
--popover: 0.20 0.02 235;
|
||||||
--card: 222.2 84% 4.9%;
|
--popover-foreground: 0.90 0.02 235;
|
||||||
--card: oklch(0.20 0.05 265);
|
--primary: 0.55 0.15 250; /* lavender */
|
||||||
--card-foreground: 210 40% 98%;
|
--primary-foreground: 0.20 0.02 235;
|
||||||
--card-foreground: oklch(0.90 0.03 260);
|
--secondary: 0.25 0.02 235; /* surface1 */
|
||||||
|
--secondary-foreground: 0.90 0.02 235;
|
||||||
--popover: 222.2 84% 4.9%;
|
--muted: 0.23 0.02 235; /* surface0 */
|
||||||
--popover: oklch(0.20 0.05 265);
|
--muted-foreground: 0.70 0.02 235; /* subtext0 */
|
||||||
--popover-foreground: 210 40% 98%;
|
--accent: 0.65 0.15 290; /* mauve */
|
||||||
--popover-foreground: oklch(0.90 0.03 260);
|
--accent-foreground: 0.90 0.02 235;
|
||||||
|
--destructive: 0.65 0.25 0; /* red */
|
||||||
--primary: 210 40% 98%;
|
--destructive-foreground: 0.90 0.02 235;
|
||||||
--primary: oklch(0.75 0.15 260);
|
--border: 0.25 0.02 235; /* surface1 */
|
||||||
--primary-foreground: 222.2 47.4% 11.2%;
|
--input: 0.25 0.02 235;
|
||||||
--primary-foreground: oklch(0.25 0.05 265);
|
--ring: 0.55 0.15 250; /* lavender */
|
||||||
|
--chart-1: 0.65 0.25 0; /* red */
|
||||||
--secondary: 217.2 32.6% 17.5%;
|
--chart-2: 0.75 0.20 30; /* peach */
|
||||||
--secondary: oklch(0.30 0.06 265);
|
--chart-3: 0.80 0.15 90; /* yellow */
|
||||||
--secondary-foreground: 210 40% 98%;
|
--chart-4: 0.70 0.15 150; /* green */
|
||||||
--secondary-foreground: oklch(0.90 0.03 260);
|
--chart-5: 0.60 0.15 180; /* blue */
|
||||||
|
|
||||||
--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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add support for border colors */
|
|
||||||
@layer utilities {
|
|
||||||
.border {
|
|
||||||
border-color: var(--border);
|
|
||||||
}
|
|
||||||
.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
@apply border-border;
|
@apply border-border;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import {
|
||||||
type AccordionRootEmits,
|
type AccordionRootEmits,
|
||||||
type AccordionRootProps,
|
type AccordionRootProps,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'reka-ui'
|
||||||
|
|
||||||
const props = defineProps<AccordionRootProps>()
|
const props = defineProps<AccordionRootProps>()
|
||||||
const emits = defineEmits<AccordionRootEmits>()
|
const emits = defineEmits<AccordionRootEmits>()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
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'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<AccordionContentProps & { class?: HTMLAttributes['class'] }>()
|
const props = defineProps<AccordionContentProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
@ -15,7 +15,7 @@ const delegatedProps = computed(() => {
|
||||||
<template>
|
<template>
|
||||||
<AccordionContent
|
<AccordionContent
|
||||||
v-bind="delegatedProps"
|
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)">
|
<div :class="cn('pb-4 pt-0', props.class)">
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
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'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<AccordionItemProps & { class?: HTMLAttributes['class'] }>()
|
const props = defineProps<AccordionItemProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import {
|
||||||
AccordionHeader,
|
AccordionHeader,
|
||||||
AccordionTrigger,
|
AccordionTrigger,
|
||||||
type AccordionTriggerProps,
|
type AccordionTriggerProps,
|
||||||
} from 'radix-vue'
|
} from 'reka-ui'
|
||||||
import { computed, type HTMLAttributes } from 'vue'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<AccordionTriggerProps & { class?: HTMLAttributes['class'] }>()
|
const props = defineProps<AccordionTriggerProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
@ -23,7 +23,7 @@ const delegatedProps = computed(() => {
|
||||||
v-bind="delegatedProps"
|
v-bind="delegatedProps"
|
||||||
:class="
|
:class="
|
||||||
cn(
|
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,
|
props.class,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
|
@ -31,7 +31,7 @@ const delegatedProps = computed(() => {
|
||||||
<slot />
|
<slot />
|
||||||
<slot name="icon">
|
<slot name="icon">
|
||||||
<ChevronDown
|
<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>
|
</slot>
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,21 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { HTMLAttributes } from 'vue'
|
import type { HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
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']
|
class?: HTMLAttributes['class']
|
||||||
}>()
|
size?: AvatarVariants['size']
|
||||||
|
shape?: AvatarVariants['shape']
|
||||||
|
}>(), {
|
||||||
|
size: 'sm',
|
||||||
|
shape: 'circle',
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<AvatarRoot :class="cn(avatarVariant({ size, shape }), props.class)">
|
||||||
:class="cn('relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full', props.class)"
|
|
||||||
>
|
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</AvatarRoot>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { HTMLAttributes } from 'vue'
|
import { AvatarFallback, type AvatarFallbackProps } from 'reka-ui'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<AvatarFallbackProps>()
|
||||||
class?: HTMLAttributes['class']
|
|
||||||
}>()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<AvatarFallback v-bind="props">
|
||||||
:class="cn('flex h-full w-full items-center justify-center rounded-full bg-muted', props.class)"
|
|
||||||
>
|
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</AvatarFallback>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,18 +1,12 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { HTMLAttributes } from 'vue'
|
import type { AvatarImageProps } from 'reka-ui'
|
||||||
import { cn } from '@/lib/utils'
|
import { AvatarImage } from 'reka-ui'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<AvatarImageProps>()
|
||||||
src?: string
|
|
||||||
alt?: string
|
|
||||||
class?: HTMLAttributes['class']
|
|
||||||
}>()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<img
|
<AvatarImage v-bind="props" class="h-full w-full object-cover">
|
||||||
:src="src"
|
<slot />
|
||||||
:alt="alt"
|
</AvatarImage>
|
||||||
:class="cn('aspect-square h-full w-full', props.class)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,3 +1,24 @@
|
||||||
|
import { cva, type VariantProps } from 'class-variance-authority'
|
||||||
|
|
||||||
export { default as Avatar } from './Avatar.vue'
|
export { default as Avatar } from './Avatar.vue'
|
||||||
export { default as AvatarImage } from './AvatarImage.vue'
|
|
||||||
export { default as AvatarFallback } from './AvatarFallback.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>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ const props = defineProps<{
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<span :class="cn(badgeVariants({ variant: props.variant }), props.class)">
|
<div :class="cn(badgeVariants({ variant }), props.class)">
|
||||||
<slot />
|
<slot />
|
||||||
</span>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,17 @@ import { cva, type VariantProps } from 'class-variance-authority'
|
||||||
export { default as Badge } from './Badge.vue'
|
export { default as Badge } from './Badge.vue'
|
||||||
|
|
||||||
export const badgeVariants = cva(
|
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: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default:
|
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:
|
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:
|
destructive:
|
||||||
'border-transparent bg-destructive/10 text-destructive hover:bg-destructive/20',
|
'border-transparent bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/80',
|
||||||
success:
|
outline: 'text-foreground',
|
||||||
'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',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { HTMLAttributes } from 'vue'
|
import type { HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { Primitive, type PrimitiveProps } from 'radix-vue'
|
import { Primitive, type PrimitiveProps } from 'reka-ui'
|
||||||
import { type ButtonVariants, buttonVariants } from '.'
|
import { type ButtonVariants, buttonVariants } from '.'
|
||||||
|
|
||||||
interface Props extends PrimitiveProps {
|
interface Props extends PrimitiveProps {
|
||||||
|
|
@ -16,7 +16,11 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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 />
|
<slot />
|
||||||
</Primitive>
|
</Primitive>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -3,23 +3,23 @@ import { cva, type VariantProps } from 'class-variance-authority'
|
||||||
export { default as Button } from './Button.vue'
|
export { default as Button } from './Button.vue'
|
||||||
|
|
||||||
export const buttonVariants = cva(
|
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: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default:
|
default: 'bg-primary text-primary-foreground shadow-sm hover:bg-primary/90',
|
||||||
'bg-primary text-primary-foreground shadow hover:bg-primary/90',
|
|
||||||
destructive:
|
destructive:
|
||||||
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
|
'bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90',
|
||||||
outline:
|
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:
|
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',
|
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||||
link: 'text-primary underline-offset-4 hover:underline',
|
link: 'text-primary underline-offset-4 hover:underline',
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: 'h-9 px-4 py-2',
|
default: 'h-9 px-4 py-2',
|
||||||
|
xs: 'h-7 rounded px-2',
|
||||||
sm: 'h-8 rounded-md px-3 text-xs',
|
sm: 'h-8 rounded-md px-3 text-xs',
|
||||||
lg: 'h-10 rounded-md px-8',
|
lg: 'h-10 rounded-md px-8',
|
||||||
icon: 'h-9 w-9',
|
icon: 'h-9 w-9',
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,12 @@ const props = defineProps<{
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<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 />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,7 @@ const props = defineProps<{
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div :class="cn('p-6 pt-0', props.class)">
|
||||||
:class="
|
|
||||||
cn('p-6 pt-0', props.class)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,7 @@ const props = defineProps<{
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<p
|
<p :class="cn('text-sm text-muted-foreground', props.class)">
|
||||||
:class="
|
|
||||||
cn('text-sm text-muted-foreground', props.class)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<slot />
|
<slot />
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,7 @@ const props = defineProps<{
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div :class="cn('flex items-center p-6 pt-0', props.class)">
|
||||||
:class="
|
|
||||||
cn('flex items-center p-6 pt-0', props.class)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,7 @@ const props = defineProps<{
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div :class="cn('flex flex-col gap-y-1.5 p-6', props.class)">
|
||||||
:class="
|
|
||||||
cn('flex flex-col space-y-1.5 p-6', props.class)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ const props = defineProps<{
|
||||||
<template>
|
<template>
|
||||||
<h3
|
<h3
|
||||||
:class="
|
:class="
|
||||||
cn('text-2xl font-semibold leading-none tracking-tight', props.class)
|
cn('font-semibold leading-none tracking-tight', props.class)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,14 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DialogRoot } from 'radix-vue'
|
import { DialogRoot, type DialogRootEmits, type DialogRootProps, useForwardPropsEmits } from 'reka-ui'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<DialogRootProps>()
|
||||||
open?: boolean
|
const emits = defineEmits<DialogRootEmits>()
|
||||||
defaultOpen?: boolean
|
|
||||||
modal?: boolean
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const emits = defineEmits<{
|
const forwarded = useForwardPropsEmits(props, emits)
|
||||||
'update:open': [value: boolean]
|
|
||||||
}>()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DialogRoot v-bind="props" @update:open="emits('update:open', $event)">
|
<DialogRoot v-bind="forwarded">
|
||||||
<slot />
|
<slot />
|
||||||
</DialogRoot>
|
</DialogRoot>
|
||||||
</template>
|
</template>
|
||||||
11
src/components/ui/dialog/DialogClose.vue
Normal file
11
src/components/ui/dialog/DialogClose.vue
Normal 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>
|
||||||
|
|
@ -1,12 +1,27 @@
|
||||||
<script setup lang="ts">
|
<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 { 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<{
|
const props = defineProps<DialogContentProps & { class?: HTMLAttributes['class'] }>()
|
||||||
class?: HTMLAttributes['class']
|
const emits = defineEmits<DialogContentEmits>()
|
||||||
}>()
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -14,19 +29,22 @@ const props = defineProps<{
|
||||||
<DialogOverlay
|
<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
|
<DialogContent
|
||||||
:class="cn(
|
v-bind="forwarded"
|
||||||
'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',
|
:class="
|
||||||
props.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 />
|
<slot />
|
||||||
|
|
||||||
<DialogClose
|
<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>
|
<span class="sr-only">Close</span>
|
||||||
</DialogClose>
|
</DialogClose>
|
||||||
</DialogContentPrimitive>
|
</DialogContent>
|
||||||
</DialogPortal>
|
</DialogPortal>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,15 +1,24 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DialogDescription as DialogDescriptionPrimitive } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
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<{
|
const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes['class'] }>()
|
||||||
class?: HTMLAttributes['class']
|
|
||||||
}>()
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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 />
|
<slot />
|
||||||
</DialogDescriptionPrimitive>
|
</DialogDescription>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
import type { HTMLAttributes } from 'vue'
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{ class?: HTMLAttributes['class'] }>()
|
||||||
class?: HTMLAttributes['class']
|
|
||||||
}>()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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 />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
import type { HTMLAttributes } from 'vue'
|
import type { HTMLAttributes } from 'vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
class?: HTMLAttributes['class']
|
class?: HTMLAttributes['class']
|
||||||
|
|
@ -8,7 +8,9 @@ const props = defineProps<{
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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 />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
59
src/components/ui/dialog/DialogScrollContent.vue
Normal file
59
src/components/ui/dialog/DialogScrollContent.vue
Normal 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>
|
||||||
|
|
@ -1,15 +1,29 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DialogTitle as DialogTitlePrimitive } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
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<{
|
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes['class'] }>()
|
||||||
class?: HTMLAttributes['class']
|
|
||||||
}>()
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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 />
|
<slot />
|
||||||
</DialogTitlePrimitive>
|
</DialogTitle>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DialogTrigger as DialogTriggerPrimitive } from 'radix-vue'
|
import { DialogTrigger, type DialogTriggerProps } from 'reka-ui'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
import type { HTMLAttributes } from 'vue'
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<DialogTriggerProps>()
|
||||||
class?: HTMLAttributes['class']
|
|
||||||
asChild?: boolean
|
|
||||||
}>()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DialogTriggerPrimitive v-bind="props" :class="cn(props.class)">
|
<DialogTrigger v-bind="props">
|
||||||
<slot />
|
<slot />
|
||||||
</DialogTriggerPrimitive>
|
</DialogTrigger>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,17 +1,9 @@
|
||||||
export { default as Dialog } from './Dialog.vue'
|
export { default as Dialog } from './Dialog.vue'
|
||||||
|
export { default as DialogClose } from './DialogClose.vue'
|
||||||
export { default as DialogContent } from './DialogContent.vue'
|
export { default as DialogContent } from './DialogContent.vue'
|
||||||
export { default as DialogDescription } from './DialogDescription.vue'
|
export { default as DialogDescription } from './DialogDescription.vue'
|
||||||
export { default as DialogFooter } from './DialogFooter.vue'
|
export { default as DialogFooter } from './DialogFooter.vue'
|
||||||
export { default as DialogHeader } from './DialogHeader.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 DialogTitle } from './DialogTitle.vue'
|
||||||
export { default as DialogTrigger } from './DialogTrigger.vue'
|
export { default as DialogTrigger } from './DialogTrigger.vue'
|
||||||
|
|
||||||
export type {
|
|
||||||
DialogRootEmits,
|
|
||||||
DialogRootProps,
|
|
||||||
DialogOverlayProps,
|
|
||||||
DialogPortalProps,
|
|
||||||
DialogContentProps,
|
|
||||||
DialogTitleProps,
|
|
||||||
DialogTriggerProps,
|
|
||||||
} from 'radix-vue'
|
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DropdownMenuRoot } from 'radix-vue'
|
import { DropdownMenuRoot, type DropdownMenuRootEmits, type DropdownMenuRootProps, useForwardPropsEmits } from 'reka-ui'
|
||||||
|
|
||||||
defineOptions({
|
const props = defineProps<DropdownMenuRootProps>()
|
||||||
name: 'DropdownMenu'
|
const emits = defineEmits<DropdownMenuRootEmits>()
|
||||||
})
|
|
||||||
|
|
||||||
defineSlots<{
|
const forwarded = useForwardPropsEmits(props, emits)
|
||||||
default?: (props: {}) => any
|
|
||||||
}>()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DropdownMenuRoot v-bind="$attrs">
|
<DropdownMenuRoot v-bind="forwarded">
|
||||||
<slot />
|
<slot />
|
||||||
</DropdownMenuRoot>
|
</DropdownMenuRoot>
|
||||||
</template>
|
</template>
|
||||||
40
src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue
Normal file
40
src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue
Normal 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>
|
||||||
|
|
@ -1,31 +1,38 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DropdownMenuContent, type DropdownMenuContentProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import {
|
||||||
defineOptions({
|
DropdownMenuContent,
|
||||||
name: 'DropdownMenuContent'
|
type DropdownMenuContentEmits,
|
||||||
})
|
type DropdownMenuContentProps,
|
||||||
|
DropdownMenuPortal,
|
||||||
|
useForwardPropsEmits,
|
||||||
|
} from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<DropdownMenuContentProps & {
|
defineProps<DropdownMenuContentProps & { class?: HTMLAttributes['class'] }>(),
|
||||||
class?: string
|
|
||||||
}>(),
|
|
||||||
{
|
{
|
||||||
sideOffset: 4,
|
sideOffset: 4,
|
||||||
align: 'start',
|
},
|
||||||
class: ''
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
const emits = defineEmits<DropdownMenuContentEmits>()
|
||||||
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
|
})
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<DropdownMenuPortal>
|
||||||
<DropdownMenuContent
|
<DropdownMenuContent
|
||||||
:class="cn(
|
v-bind="forwarded"
|
||||||
'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',
|
: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)"
|
||||||
props.class
|
|
||||||
)"
|
|
||||||
v-bind="{ ...props, ...$attrs }"
|
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenuPortal>
|
||||||
</template>
|
</template>
|
||||||
11
src/components/ui/dropdown-menu/DropdownMenuGroup.vue
Normal file
11
src/components/ui/dropdown-menu/DropdownMenuGroup.vue
Normal 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>
|
||||||
|
|
@ -1,33 +1,27 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DropdownMenuItem, type DropdownMenuItemProps } from 'radix-vue'
|
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { DropdownMenuItem, type DropdownMenuItemProps, useForwardProps } from 'reka-ui'
|
||||||
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
defineOptions({
|
const props = defineProps<DropdownMenuItemProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
|
||||||
name: 'DropdownMenuItem'
|
|
||||||
|
const delegatedProps = computed(() => {
|
||||||
|
const { class: _, ...delegated } = props
|
||||||
|
|
||||||
|
return delegated
|
||||||
})
|
})
|
||||||
|
|
||||||
const props = withDefaults(
|
const forwardedProps = useForwardProps(delegatedProps)
|
||||||
defineProps<
|
|
||||||
DropdownMenuItemProps & {
|
|
||||||
class?: string
|
|
||||||
inset?: boolean
|
|
||||||
}
|
|
||||||
>(),
|
|
||||||
{
|
|
||||||
class: '',
|
|
||||||
inset: false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
|
v-bind="forwardedProps"
|
||||||
:class="cn(
|
: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',
|
inset && 'pl-8',
|
||||||
props.class
|
props.class,
|
||||||
)"
|
)"
|
||||||
v-bind="{ ...props, ...$attrs }"
|
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
|
|
||||||
24
src/components/ui/dropdown-menu/DropdownMenuLabel.vue
Normal file
24
src/components/ui/dropdown-menu/DropdownMenuLabel.vue
Normal 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>
|
||||||
19
src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue
Normal file
19
src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue
Normal 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>
|
||||||
41
src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue
Normal file
41
src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue
Normal 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>
|
||||||
22
src/components/ui/dropdown-menu/DropdownMenuSeparator.vue
Normal file
22
src/components/ui/dropdown-menu/DropdownMenuSeparator.vue
Normal 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>
|
||||||
14
src/components/ui/dropdown-menu/DropdownMenuShortcut.vue
Normal file
14
src/components/ui/dropdown-menu/DropdownMenuShortcut.vue
Normal 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>
|
||||||
19
src/components/ui/dropdown-menu/DropdownMenuSub.vue
Normal file
19
src/components/ui/dropdown-menu/DropdownMenuSub.vue
Normal 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>
|
||||||
30
src/components/ui/dropdown-menu/DropdownMenuSubContent.vue
Normal file
30
src/components/ui/dropdown-menu/DropdownMenuSubContent.vue
Normal 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>
|
||||||
33
src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue
Normal file
33
src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue
Normal 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>
|
||||||
|
|
@ -1,22 +1,13 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DropdownMenuTrigger } from 'radix-vue'
|
import { DropdownMenuTrigger, type DropdownMenuTriggerProps, useForwardProps } from 'reka-ui'
|
||||||
|
|
||||||
defineOptions({
|
const props = defineProps<DropdownMenuTriggerProps>()
|
||||||
name: 'DropdownMenuTrigger'
|
|
||||||
})
|
|
||||||
|
|
||||||
const props = withDefaults(
|
const forwardedProps = useForwardProps(props)
|
||||||
defineProps<{
|
|
||||||
asChild?: boolean
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
asChild: false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DropdownMenuTrigger v-bind="{ ...props, ...$attrs }">
|
<DropdownMenuTrigger class="outline-hidden" v-bind="forwardedProps">
|
||||||
<slot />
|
<slot />
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1,4 +1,16 @@
|
||||||
export { default as DropdownMenu } from './DropdownMenu.vue'
|
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 DropdownMenuContent } from './DropdownMenuContent.vue'
|
||||||
|
export { default as DropdownMenuGroup } from './DropdownMenuGroup.vue'
|
||||||
export { default as DropdownMenuItem } from './DropdownMenuItem.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'
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,5 @@ const modelValue = useVModel(props, 'modelValue', emits, {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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>
|
</template>
|
||||||
|
|
|
||||||
27
src/components/ui/label/Label.vue
Normal file
27
src/components/ui/label/Label.vue
Normal 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>
|
||||||
|
|
@ -1,8 +1 @@
|
||||||
import { Label as LabelPrimitive } from 'radix-vue'
|
export { default as Label } from './Label.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
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import {
|
||||||
ScrollAreaRoot,
|
ScrollAreaRoot,
|
||||||
type ScrollAreaRootProps,
|
type ScrollAreaRootProps,
|
||||||
ScrollAreaViewport,
|
ScrollAreaViewport,
|
||||||
} from 'radix-vue'
|
} from 'reka-ui'
|
||||||
import { computed, type HTMLAttributes } from 'vue'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import ScrollBar from './ScrollBar.vue'
|
import ScrollBar from './ScrollBar.vue'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import { ScrollAreaScrollbar, type ScrollAreaScrollbarProps, ScrollAreaThumb } from 'reka-ui'
|
||||||
ScrollAreaScrollbar,
|
|
||||||
ScrollAreaThumb,
|
|
||||||
type ScrollAreaScrollbarProps,
|
|
||||||
} from 'radix-vue'
|
|
||||||
import { computed, type HTMLAttributes } from 'vue'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<
|
const props = withDefaults(defineProps<ScrollAreaScrollbarProps & { class?: HTMLAttributes['class'] }>(), {
|
||||||
ScrollAreaScrollbarProps & {
|
orientation: 'vertical',
|
||||||
class?: HTMLAttributes['class']
|
})
|
||||||
}
|
|
||||||
>()
|
|
||||||
|
|
||||||
const delegatedProps = computed(() => {
|
const delegatedProps = computed(() => {
|
||||||
const { class: _, ...delegated } = props
|
const { class: _, ...delegated } = props
|
||||||
|
|
@ -23,20 +17,14 @@ const delegatedProps = computed(() => {
|
||||||
<template>
|
<template>
|
||||||
<ScrollAreaScrollbar
|
<ScrollAreaScrollbar
|
||||||
v-bind="delegatedProps"
|
v-bind="delegatedProps"
|
||||||
:class="cn(
|
:class="
|
||||||
'flex touch-none select-none transition-colors',
|
cn('flex touch-none select-none transition-colors',
|
||||||
props.orientation === 'vertical' &&
|
orientation === 'vertical'
|
||||||
'h-full w-2.5 border-l border-l-transparent p-[1px]',
|
&& 'h-full w-2.5 border-l border-l-transparent p-px',
|
||||||
props.orientation === 'horizontal' &&
|
orientation === 'horizontal'
|
||||||
'h-2.5 border-t border-t-transparent p-[1px]',
|
&& 'h-2.5 flex-col border-t border-t-transparent p-px',
|
||||||
props.class
|
props.class)"
|
||||||
)"
|
|
||||||
>
|
>
|
||||||
<ScrollAreaThumb
|
<ScrollAreaThumb class="relative flex-1 rounded-full bg-border" />
|
||||||
:class="cn(
|
|
||||||
'relative rounded-full bg-border',
|
|
||||||
props.orientation === 'vertical' && 'flex-1'
|
|
||||||
)"
|
|
||||||
/>
|
|
||||||
</ScrollAreaScrollbar>
|
</ScrollAreaScrollbar>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
export { default as ScrollArea } from './ScrollArea.vue'
|
export { default as ScrollArea } from './ScrollArea.vue'
|
||||||
|
export { default as ScrollBar } from './ScrollBar.vue'
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { SelectRootEmits, SelectRootProps } from 'radix-vue'
|
import type { SelectRootEmits, SelectRootProps } from 'reka-ui'
|
||||||
import { SelectRoot, useForwardPropsEmits } from 'radix-vue'
|
import { SelectRoot, useForwardPropsEmits } from 'reka-ui'
|
||||||
|
|
||||||
const props = defineProps<SelectRootProps>()
|
const props = defineProps<SelectRootProps>()
|
||||||
const emits = defineEmits<SelectRootEmits>()
|
const emits = defineEmits<SelectRootEmits>()
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {
|
||||||
SelectPortal,
|
SelectPortal,
|
||||||
SelectViewport,
|
SelectViewport,
|
||||||
useForwardPropsEmits,
|
useForwardPropsEmits,
|
||||||
} from 'radix-vue'
|
} from 'reka-ui'
|
||||||
import { computed, type HTMLAttributes } from 'vue'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
import { SelectScrollDownButton, SelectScrollUpButton } from '.'
|
import { SelectScrollDownButton, SelectScrollUpButton } from '.'
|
||||||
|
|
||||||
|
|
@ -37,9 +37,6 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
<SelectContent
|
<SelectContent
|
||||||
v-bind="{ ...forwarded, ...$attrs }" :class="cn(
|
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',
|
'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'
|
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',
|
&& '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,
|
props.class,
|
||||||
|
|
@ -47,7 +44,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<SelectScrollUpButton />
|
<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 />
|
<slot />
|
||||||
</SelectViewport>
|
</SelectViewport>
|
||||||
<SelectScrollDownButton />
|
<SelectScrollDownButton />
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
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'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<SelectGroupProps & { class?: HTMLAttributes['class'] }>()
|
const props = defineProps<SelectGroupProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {
|
||||||
type SelectItemProps,
|
type SelectItemProps,
|
||||||
SelectItemText,
|
SelectItemText,
|
||||||
useForwardProps,
|
useForwardProps,
|
||||||
} from 'radix-vue'
|
} from 'reka-ui'
|
||||||
import { computed, type HTMLAttributes } from 'vue'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<SelectItemProps & { class?: HTMLAttributes['class'] }>()
|
const props = defineProps<SelectItemProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
@ -26,14 +26,12 @@ const forwardedProps = useForwardProps(delegatedProps)
|
||||||
v-bind="forwardedProps"
|
v-bind="forwardedProps"
|
||||||
:class="
|
:class="
|
||||||
cn(
|
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',
|
'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',
|
||||||
'hover:bg-accent/50',
|
|
||||||
'active:bg-accent/70',
|
|
||||||
props.class,
|
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>
|
<SelectItemIndicator>
|
||||||
<Check class="h-4 w-4" />
|
<Check class="h-4 w-4" />
|
||||||
</SelectItemIndicator>
|
</SelectItemIndicator>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SelectItemText, type SelectItemTextProps } from 'radix-vue'
|
import { SelectItemText, type SelectItemTextProps } from 'reka-ui'
|
||||||
|
|
||||||
const props = defineProps<SelectItemTextProps>()
|
const props = defineProps<SelectItemTextProps>()
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { HTMLAttributes } from 'vue'
|
import type { HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
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'] }>()
|
const props = defineProps<SelectLabelProps & { class?: HTMLAttributes['class'] }>()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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 />
|
<slot />
|
||||||
</SelectLabel>
|
</SelectLabel>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { ChevronDown } from 'lucide-vue-next'
|
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'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<SelectScrollDownButtonProps & { class?: HTMLAttributes['class'] }>()
|
const props = defineProps<SelectScrollDownButtonProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
@ -18,7 +18,7 @@ const forwardedProps = useForwardProps(delegatedProps)
|
||||||
<template>
|
<template>
|
||||||
<SelectScrollDownButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
|
<SelectScrollDownButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
|
||||||
<slot>
|
<slot>
|
||||||
<ChevronDown class="h-4 w-4" />
|
<ChevronDown />
|
||||||
</slot>
|
</slot>
|
||||||
</SelectScrollDownButton>
|
</SelectScrollDownButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { ChevronUp } from 'lucide-vue-next'
|
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'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<SelectScrollUpButtonProps & { class?: HTMLAttributes['class'] }>()
|
const props = defineProps<SelectScrollUpButtonProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
@ -18,7 +18,7 @@ const forwardedProps = useForwardProps(delegatedProps)
|
||||||
<template>
|
<template>
|
||||||
<SelectScrollUpButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
|
<SelectScrollUpButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
|
||||||
<slot>
|
<slot>
|
||||||
<ChevronUp class="h-4 w-4" />
|
<ChevronUp />
|
||||||
</slot>
|
</slot>
|
||||||
</SelectScrollUpButton>
|
</SelectScrollUpButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
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'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<SelectSeparatorProps & { class?: HTMLAttributes['class'] }>()
|
const props = defineProps<SelectSeparatorProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { ChevronDown } from 'lucide-vue-next'
|
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'
|
import { computed, type HTMLAttributes } from 'vue'
|
||||||
|
|
||||||
const props = defineProps<SelectTriggerProps & { class?: HTMLAttributes['class'] }>()
|
const props = defineProps<SelectTriggerProps & { class?: HTMLAttributes['class'] }>()
|
||||||
|
|
@ -19,7 +19,7 @@ const forwardedProps = useForwardProps(delegatedProps)
|
||||||
<SelectTrigger
|
<SelectTrigger
|
||||||
v-bind="forwardedProps"
|
v-bind="forwardedProps"
|
||||||
:class="cn(
|
: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,
|
props.class,
|
||||||
)"
|
)"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SelectValue, type SelectValueProps } from 'radix-vue'
|
import { SelectValue, type SelectValueProps } from 'reka-ui'
|
||||||
|
|
||||||
const props = defineProps<SelectValueProps>()
|
const props = defineProps<SelectValueProps>()
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
22
src/components/ui/tabs/TabsContent.vue
Normal file
22
src/components/ui/tabs/TabsContent.vue
Normal 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>
|
||||||
29
src/components/ui/tabs/TabsTrigger.vue
Normal file
29
src/components/ui/tabs/TabsTrigger.vue
Normal 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>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue