feat (ui): add radix vue components library

This commit is contained in:
Abizrh
2025-08-07 14:45:37 +07:00
parent f3dc250944
commit 645383e5cb
341 changed files with 8563 additions and 1 deletions

No files matched your search

+36
View File
@@ -0,0 +1,36 @@
<script setup lang="ts">
import type { MenubarRootEmits, MenubarRootProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import {
MenubarRoot,
useForwardPropsEmits,
} from 'radix-vue'
import { computed } from 'vue'
const props = defineProps<MenubarRootProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<MenubarRootEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<MenubarRoot
v-bind="forwarded"
:class="
cn(
'flex h-9 items-center space-x-1 rounded-md border bg-background p-1 shadow-sm',
props.class,
)
"
>
<slot />
</MenubarRoot>
</template>
@@ -0,0 +1,40 @@
<script setup lang="ts">
import type { MenubarCheckboxItemEmits, MenubarCheckboxItemProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import {
MenubarCheckboxItem,
MenubarItemIndicator,
useForwardPropsEmits,
} from 'radix-vue'
import { computed } from 'vue'
const props = defineProps<MenubarCheckboxItemProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<MenubarCheckboxItemEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<MenubarCheckboxItem
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-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
props.class,
)"
>
<span class="absolute left-2 h-3.5 w-3.5 flex items-center justify-center">
<MenubarItemIndicator>
<Icon name="i-radix-icons-check" class="h-4 w-4" />
</MenubarItemIndicator>
</span>
<slot />
</MenubarCheckboxItem>
</template>
@@ -0,0 +1,45 @@
<script setup lang="ts">
import type { MenubarContentProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import {
MenubarContent,
MenubarPortal,
useForwardProps,
} from 'radix-vue'
import { computed } from 'vue'
const props = withDefaults(
defineProps<MenubarContentProps & { class?: HTMLAttributes['class'] }>(),
{
align: 'start',
alignOffset: -4,
sideOffset: 8,
},
)
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<MenubarPortal>
<MenubarContent
v-bind="forwardedProps"
:class="
cn(
'z-50 min-w-48 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
props.class,
)
"
>
<slot />
</MenubarContent>
</MenubarPortal>
</template>
@@ -0,0 +1,12 @@
<script setup lang="ts">
import type { MenubarGroupProps } from 'radix-vue'
import { MenubarGroup } from 'radix-vue'
const props = defineProps<MenubarGroupProps>()
</script>
<template>
<MenubarGroup v-bind="props">
<slot />
</MenubarGroup>
</template>
@@ -0,0 +1,36 @@
<script setup lang="ts">
import type { MenubarItemEmits, MenubarItemProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import {
MenubarItem,
useForwardPropsEmits,
} from 'radix-vue'
import { computed } from 'vue'
const props = defineProps<MenubarItemProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
const emits = defineEmits<MenubarItemEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<MenubarItem
v-bind="forwarded"
:class="cn(
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
inset && 'pl-8',
props.class,
)"
>
<slot />
</MenubarItem>
</template>
@@ -0,0 +1,14 @@
<script setup lang="ts">
import type { MenubarLabelProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import { MenubarLabel } from 'radix-vue'
const props = defineProps<MenubarLabelProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
</script>
<template>
<MenubarLabel :class="cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', props.class)">
<slot />
</MenubarLabel>
</template>
@@ -0,0 +1,12 @@
<script setup lang="ts">
import type { MenubarMenuProps } from 'radix-vue'
import { MenubarMenu } from 'radix-vue'
const props = defineProps<MenubarMenuProps>()
</script>
<template>
<MenubarMenu v-bind="props">
<slot />
</MenubarMenu>
</template>
@@ -0,0 +1,20 @@
<script setup lang="ts">
import type { MenubarRadioGroupEmits, MenubarRadioGroupProps } from 'radix-vue'
import {
MenubarRadioGroup,
useForwardPropsEmits,
} from 'radix-vue'
const props = defineProps<MenubarRadioGroupProps>()
const emits = defineEmits<MenubarRadioGroupEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<MenubarRadioGroup v-bind="forwarded">
<slot />
</MenubarRadioGroup>
</template>
@@ -0,0 +1,40 @@
<script setup lang="ts">
import type { MenubarRadioItemEmits, MenubarRadioItemProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import {
MenubarItemIndicator,
MenubarRadioItem,
useForwardPropsEmits,
} from 'radix-vue'
import { computed } from 'vue'
const props = defineProps<MenubarRadioItemProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<MenubarRadioItemEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<MenubarRadioItem
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-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
props.class,
)"
>
<span class="absolute left-2 h-3.5 w-3.5 flex items-center justify-center">
<MenubarItemIndicator>
<Icon name="i-radix-icons-dot-filled" class="h-4 w-4 fill-current" />
</MenubarItemIndicator>
</span>
<slot />
</MenubarRadioItem>
</template>
@@ -0,0 +1,21 @@
<script setup lang="ts">
import type { MenubarSeparatorProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import { MenubarSeparator, useForwardProps } from 'radix-vue'
import { computed } from 'vue'
const props = defineProps<MenubarSeparatorProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<MenubarSeparator :class=" cn('-mx-1 my-1 h-px bg-muted', props.class)" v-bind="forwardedProps" />
</template>
@@ -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 text-muted-foreground', props.class)">
<slot />
</span>
</template>
@@ -0,0 +1,20 @@
<script setup lang="ts">
import type { MenubarSubEmits } from 'radix-vue'
import { MenubarSub, useForwardPropsEmits } from 'radix-vue'
interface MenubarSubRootProps {
defaultOpen?: boolean
open?: boolean
}
const props = defineProps<MenubarSubRootProps>()
const emits = defineEmits<MenubarSubEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<MenubarSub v-bind="forwarded">
<slot />
</MenubarSub>
</template>
@@ -0,0 +1,40 @@
<script setup lang="ts">
import type { MenubarSubContentEmits, MenubarSubContentProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import {
MenubarPortal,
MenubarSubContent,
useForwardPropsEmits,
} from 'radix-vue'
import { computed } from 'vue'
const props = defineProps<MenubarSubContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<MenubarSubContentEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<MenubarPortal>
<MenubarSubContent
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 />
</MenubarSubContent>
</MenubarPortal>
</template>
@@ -0,0 +1,31 @@
<script setup lang="ts">
import type { MenubarSubTriggerProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import { MenubarSubTrigger, useForwardProps } from 'radix-vue'
import { computed } from 'vue'
const props = defineProps<MenubarSubTriggerProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<MenubarSubTrigger
v-bind="forwardedProps"
:class="cn(
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
inset && 'pl-8',
props.class,
)"
>
<slot />
<Icon name="i-radix-icons-chevron-right" class="ml-auto h-4 w-4" />
</MenubarSubTrigger>
</template>
@@ -0,0 +1,31 @@
<script setup lang="ts">
import type { MenubarTriggerProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
import { MenubarTrigger, useForwardProps } from 'radix-vue'
import { computed } from 'vue'
const props = defineProps<MenubarTriggerProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<MenubarTrigger
v-bind="forwardedProps"
:class="
cn(
'flex cursor-default select-none items-center rounded-sm px-3 py-1 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
props.class,
)
"
>
<slot />
</MenubarTrigger>
</template>
+15
View File
@@ -0,0 +1,15 @@
export { default as Menubar } from './Menubar.vue'
export { default as MenubarCheckboxItem } from './MenubarCheckboxItem.vue'
export { default as MenubarContent } from './MenubarContent.vue'
export { default as MenubarGroup } from './MenubarGroup.vue'
export { default as MenubarItem } from './MenubarItem.vue'
export { default as MenubarLabel } from './MenubarLabel.vue'
export { default as MenubarMenu } from './MenubarMenu.vue'
export { default as MenubarRadioGroup } from './MenubarRadioGroup.vue'
export { default as MenubarRadioItem } from './MenubarRadioItem.vue'
export { default as MenubarSeparator } from './MenubarSeparator.vue'
export { default as MenubarShortcut } from './MenubarShortcut.vue'
export { default as MenubarSub } from './MenubarSub.vue'
export { default as MenubarSubContent } from './MenubarSubContent.vue'
export { default as MenubarSubTrigger } from './MenubarSubTrigger.vue'
export { default as MenubarTrigger } from './MenubarTrigger.vue'