chore(components): improve props

This commit is contained in:
Benjamin Canac
2024-06-28 18:13:03 +02:00
parent c9f9a248b7
commit 673064dee5
38 changed files with 260 additions and 137 deletions

View File

@@ -31,7 +31,6 @@ const component = ({ name, primitive, pro, prose, content }) => {
? `
<script lang="ts">
import { tv } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/${path}/${prose ? 'prose/' : ''}${content ? 'content/' : ''}${kebabName}'
@@ -40,7 +39,12 @@ const appConfig = _appConfig as AppConfig & { ${key}: { ${prose ? 'prose: { ' :
const ${camelName} = tv({ extend: tv(theme), ...(appConfig.${key}?.${prose ? 'prose?.' : ''}${camelName} || {}) })
export interface ${upperName}Props extends Omit<PrimitiveProps, 'asChild'> {
export interface ${upperName}Props {
/**
* The element or component this component should render as.
* @defaultValue \`div\`
*/
as?: any
class?: any
ui?: Partial<typeof ${camelName}.slots>
}
@@ -80,7 +84,7 @@ const ${camelName} = tv({ extend: tv(theme), ...(appConfig.${key}?.${prose ? 'pr
type ${upperName}Variants = VariantProps<typeof ${camelName}>
export interface ${upperName}Props extends Omit<${upperName}RootProps, 'asChild'> {
export interface ${upperName}Props extends Pick<${upperName}RootProps> {
class?: any
ui?: Partial<typeof ${camelName}.slots>
}

View File

@@ -18,11 +18,16 @@ export interface AccordionItem extends Partial<Pick<AccordionItemProps, 'disable
content?: string
}
export interface AccordionProps<T> extends Omit<AccordionRootProps, 'asChild' | 'dir' | 'orientation'> {
export interface AccordionProps<T> extends Pick<AccordionRootProps, 'collapsible' | 'defaultValue' | 'modelValue' | 'type' | 'disabled'> {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
items?: T[]
/**
* The icon displayed on the right side of the trigger.
* @defaultValue `appConfig.ui.icons.chevronDown`
* @defaultValue appConfig.ui.icons.chevronDown
*/
trailingIcon?: string
/** The content of the accordion. */

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { tv, type VariantProps } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/ui/alert'
@@ -12,7 +11,12 @@ const alert = tv({ extend: tv(theme), ...(appConfig.ui?.alert || {}) })
type AlertVariants = VariantProps<typeof alert>
export interface AlertProps extends Omit<PrimitiveProps, 'asChild'> {
export interface AlertProps {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
title?: string
description?: string
icon?: string
@@ -28,12 +32,12 @@ export interface AlertProps extends Omit<PrimitiveProps, 'asChild'> {
/**
* Display a close button to dismiss the alert.
* @emits `close`
* @defaultValue `false` (`{ size: 'md', color: 'gray', variant: 'link' }`)
* @defaultValue false ({ size: 'md', color: 'gray', variant: 'link' })
*/
close?: ButtonProps | boolean
/**
* The icon displayed in the close button.
* @defaultValue `appConfig.ui.icons.close`
* @defaultValue appConfig.ui.icons.close
*/
closeIcon?: string
class?: any
@@ -59,7 +63,7 @@ import { Primitive } from 'radix-vue'
import { useAppConfig } from '#imports'
import { UIcon, UAvatar } from '#components'
const props = withDefaults(defineProps<AlertProps>(), { as: 'div' })
const props = defineProps<AlertProps>()
const emits = defineEmits<AlertEmits>()
const slots = defineSlots<AlertSlots>()

View File

@@ -11,7 +11,7 @@ const avatar = tv({ extend: tv(theme), ...(appConfig.ui?.avatar || {}) })
type AvatarVariants = VariantProps<typeof avatar>
export interface AvatarProps extends Omit<AvatarFallbackProps, 'as' | 'asChild'> {
export interface AvatarProps extends Pick<AvatarFallbackProps, 'delayMs'> {
as?: string | object
src?: string
alt?: string

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { tv, type VariantProps } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/ui/avatar-group'
@@ -11,7 +10,12 @@ const avatarGroup = tv({ extend: tv(theme), ...(appConfig.ui?.avatarGroup || {})
type AvatarGroupVariants = VariantProps<typeof avatarGroup>
export interface AvatarGroupProps extends Omit<PrimitiveProps, 'asChild'> {
export interface AvatarGroupProps {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
size?: AvatarGroupVariants['size']
/**
* The maximum number of avatars to display.

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { tv, type VariantProps } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/ui/badge'
@@ -11,7 +10,12 @@ const badge = tv({ extend: tv(theme), ...(appConfig.ui?.badge || {}) })
type BadgeVariants = VariantProps<typeof badge>
export interface BadgeProps extends Omit<PrimitiveProps, 'asChild'> {
export interface BadgeProps {
/**
* The element or component this component should render as.
* @defaultValue 'span'
*/
as?: any
label?: string | number
color?: BadgeVariants['color']
variant?: BadgeVariants['variant']
@@ -27,7 +31,9 @@ export interface BadgeSlots {
<script setup lang="ts">
import { Primitive } from 'radix-vue'
const props = withDefaults(defineProps<BadgeProps>(), { as: 'span' })
const props = withDefaults(defineProps<BadgeProps>(), {
as: 'span'
})
defineSlots<BadgeSlots>()
</script>

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { tv } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/ui/breadcrumb'
@@ -18,11 +17,16 @@ export interface BreadcrumbItem extends Omit<LinkProps, 'custom'> {
slot?: string
}
export interface BreadcrumbProps<T> extends Omit<PrimitiveProps, 'asChild'> {
export interface BreadcrumbProps<T> {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
items?: T[]
/**
* The icon to use as a separator.
* @defaultValue `appConfig.ui.icons.chevronRight`
* @defaultValue appConfig.ui.icons.chevronRight
*/
separatorIcon?: string
class?: any

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { tv, type VariantProps } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/ui/button-group'
@@ -12,11 +11,16 @@ const buttonGroup = tv({ extend: tv(theme), ...(appConfig.ui?.buttonGroup) })
type ButtonGroupVariants = VariantProps<typeof buttonGroup>
export interface ButtonGroupProps extends Omit<PrimitiveProps, 'asChild'> {
export interface ButtonGroupProps {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
size?: ButtonProps['size']
/**
* The orientation the buttons are laid out.
* @defaultValue `'horizontal'`
* @defaultValue 'horizontal'
*/
orientation?: ButtonGroupVariants['orientation']
class?: any
@@ -33,7 +37,6 @@ import { Primitive } from 'radix-vue'
import { buttonGroupInjectionKey } from '#imports'
const props = withDefaults(defineProps<ButtonGroupProps>(), {
as: 'div',
orientation: 'horizontal'
})
defineSlots<ButtonGroupSlots>()

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { tv } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/ui/card'
@@ -9,7 +8,12 @@ const appConfig = _appConfig as AppConfig & { ui: { card: Partial<typeof theme>
const card = tv({ extend: tv(theme), ...(appConfig.ui?.card || {}) })
export interface CardProps extends Omit<PrimitiveProps, 'asChild'> {
export interface CardProps {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
class?: any
ui?: Partial<typeof card.slots>
}
@@ -25,7 +29,7 @@ export interface CardSlots {
import { computed } from 'vue'
import { Primitive } from 'radix-vue'
const props = withDefaults(defineProps<CardProps>(), { as: 'div' })
const props = defineProps<CardProps>()
const slots = defineSlots<CardSlots>()
const ui = computed(() => tv({ extend: card, slots: props.ui })())

View File

@@ -12,20 +12,20 @@ const checkbox = tv({ extend: tv(theme), ...(appConfig.ui?.checkbox || {}) })
type CheckboxVariants = VariantProps<typeof checkbox>
export interface CheckboxProps extends Omit<CheckboxRootProps, 'asChild' | 'checked' | 'defaultChecked'> {
export interface CheckboxProps extends Pick<CheckboxRootProps, 'disabled' | 'required' | 'name' | 'value' | 'id'> {
label?: string
description?: string
color?: CheckboxVariants['color']
size?: CheckboxVariants['size']
/**
* The icon displayed when checked.
* @defaultValue `appConfig.ui.icons.check`
* @defaultValue appConfig.ui.icons.check
*/
icon?: string
indeterminate?: InputHTMLAttributes['indeterminate']
/**
* The icon displayed when the checkbox is indeterminate.
* @defaultValue `appConfig.ui.icons.minus`
* @defaultValue appConfig.ui.icons.minus
*/
indeterminateIcon?: string
/** The checked state of the checkbox when it is initially rendered. Use when you do not need to control its checked state. */
@@ -56,7 +56,7 @@ defineEmits<CheckboxEmits>()
const modelValue = defineModel<boolean | undefined>({ default: undefined })
const rootProps = useForwardProps(reactivePick(props, 'as', 'required', 'value'))
const rootProps = useForwardProps(reactivePick(props, 'required', 'value'))
const appConfig = useAppConfig()
const { id: _id, emitFormChange, size, color, name, disabled } = useFormField<CheckboxProps>(props)

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { tv, type VariantProps } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/ui/chip'
@@ -11,7 +10,12 @@ const chip = tv({ extend: tv(theme), ...(appConfig.ui?.chip || {}) })
type ChipVariants = VariantProps<typeof chip>
export interface ChipProps extends Omit<PrimitiveProps, 'asChild'> {
export interface ChipProps {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
/** Display some text inside the chip. */
text?: string | number
color?: ChipVariants['color']
@@ -40,7 +44,7 @@ import { computed } from 'vue'
import { Primitive } from 'radix-vue'
import { useAvatarGroup } from '#imports'
const props = withDefaults(defineProps<ChipProps>(), { as: 'div' })
const props = defineProps<ChipProps>()
defineSlots<ChipSlots>()
const show = defineModel<boolean>('show', { default: true })

View File

@@ -9,7 +9,12 @@ const appConfig = _appConfig as AppConfig & { ui: { collapsible: Partial<typeof
const collapsible = tv({ extend: tv(theme), ...(appConfig.ui?.collapsible || {}) })
export interface CollapsibleProps extends Omit<CollapsibleRootProps, 'asChild'> {
export interface CollapsibleProps extends Pick<CollapsibleRootProps, 'defaultOpen' | 'open' | 'disabled'> {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
class?: any
ui?: Partial<typeof collapsible.slots>
}

View File

@@ -39,33 +39,33 @@ export interface CommandPaletteGroup<T> {
export interface CommandPaletteProps<G, T> extends Pick<ComboboxRootProps, 'as' | 'multiple' | 'disabled' | 'modelValue' | 'defaultValue'>, Pick<UseComponentIconsProps, 'loading' | 'loadingIcon'> {
/**
* The icon displayed in the input.
* @defaultValue `appConfig.ui.icons.search`
* @defaultValue appConfig.ui.icons.search
*/
icon?: string
/**
* The icon displayed when an item is selected.
* @defaultValue `appConfig.ui.icons.check`
* @defaultValue appConfig.ui.icons.check
*/
selectedIcon?: string
/**
* The placeholder text for the input.
* @defaultValue `'Type a command or search...'`
* @defaultValue 'Type a command or search...'
*/
placeholder?: InputProps['placeholder']
/**
* Display a close button in the input (useful when inside a `UModal`).
* @defaultValue `false` (`{ size: 'md', color: 'gray', variant: 'ghost' }`)
* @defaultValue false ({ size: 'md', color: 'gray', variant: 'ghost' })
*/
close?: ButtonProps | boolean
/**
* The icon displayed in the close button.
* @defaultValue `appConfig.ui.icons.close`
* @defaultValue appConfig.ui.icons.close
*/
closeIcon?: string
groups?: G[]
/**
* Options for [useFuse](https://vueuse.org/integrations/useFuse).
* @defaultValue `{ ignoreLocation: true, threshold: 0.1, keys: ['label', 'suffix'], resultLimit: 12, matchAllWhenSearchEmpty: true }`
* @defaultValue { ignoreLocation: true, threshold: 0.1, keys: ['label', 'suffix'], resultLimit: 12, matchAllWhenSearchEmpty: true }
*/
fuse?: UseFuseOptions<T>
class?: any

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { tv } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/ui/container'
@@ -9,7 +8,12 @@ const appConfig = _appConfig as AppConfig & { ui: { container: Partial<typeof th
const container = tv({ extend: tv(theme), ...(appConfig.ui?.container || {}) })
export interface ContainerProps extends Omit<PrimitiveProps, 'asChild'> {
export interface ContainerProps {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
class?: any
}
@@ -21,7 +25,7 @@ export interface ContainerSlots {
<script setup lang="ts">
import { Primitive } from 'radix-vue'
const props = withDefaults(defineProps<ContainerProps>(), { as: 'div' })
const props = defineProps<ContainerProps>()
defineSlots<ContainerSlots>()
</script>

View File

@@ -19,7 +19,7 @@ export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'custom'>, Pic
kbds?: KbdProps['value'][] | KbdProps[]
/**
* The item type.
* @defaultValue `'link'`
* @defaultValue 'link'
*/
type?: 'label' | 'separator' | 'link'
slot?: string
@@ -35,7 +35,7 @@ export interface ContextMenuProps<T> extends Omit<ContextMenuRootProps, 'dir'>,
content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'>
/**
* Render the menu in a portal.
* @defaultValue `true`
* @defaultValue true
*/
portal?: boolean
class?: any

View File

@@ -10,7 +10,12 @@ const appConfig = _appConfig as AppConfig & { ui: { drawer: Partial<typeof theme
const drawer = tv({ extend: tv(theme), ...(appConfig.ui?.drawer || {}) })
export interface DrawerProps extends Omit<DrawerRootProps, 'asChild'> {
export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | 'closeThreshold' | 'defaultOpen' | 'direction' | 'dismissible' | 'fadeFromIndex' | 'fixed' | 'modal' | 'nested' | 'open' | 'scrollLockTimeout' | 'shouldScaleBackground' | 'snapPoints'> {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
title?: string
description?: string
/** The content of the drawer. */
@@ -18,7 +23,7 @@ export interface DrawerProps extends Omit<DrawerRootProps, 'asChild'> {
overlay?: boolean
/**
* Render the drawer in a portal.
* @defaultValue `true`
* @defaultValue true
*/
portal?: boolean
class?: any

View File

@@ -19,7 +19,7 @@ export interface DropdownMenuItem extends Omit<LinkProps, 'type' | 'custom'>, Pi
kbds?: KbdProps['value'][] | KbdProps[]
/**
* The item type.
* @defaultValue `'link'`
* @defaultValue 'link'
*/
type?: 'label' | 'separator' | 'link'
slot?: string
@@ -36,17 +36,17 @@ export interface DropdownMenuProps<T> extends Omit<DropdownMenuRootProps, 'dir'>
items?: T[] | T[][]
/**
* The content of the menu.
* @defaultValue `{ side: 'bottom', sideOffset: 8 }`
* @defaultValue { side: 'bottom', sideOffset: 8 }
*/
content?: Omit<DropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'>
/**
* Display an arrow alongside the menu.
* @defaultValue `false`
* @defaultValue false
*/
arrow?: boolean | Omit<DropdownMenuArrowProps, 'as' | 'asChild'>
/**
* Render the menu in a portal.
* @defaultValue `true`
* @defaultValue true
*/
portal?: boolean
class?: any

View File

@@ -20,14 +20,19 @@ export interface InputMenuItem extends Pick<ComboboxItemProps, 'disabled'> {
chip?: ChipProps
/**
* The item type.
* @defaultValue `'item'`
* @defaultValue 'item'
*/
type?: 'label' | 'separator' | 'item'
}
type InputMenuVariants = VariantProps<typeof inputMenu>
export interface InputMenuProps<T> extends Omit<ComboboxRootProps<T>, 'asChild' | 'dir' | 'filterFunction' | 'displayValue'>, UseComponentIconsProps {
export interface InputMenuProps<T> extends Pick<ComboboxRootProps<T>, 'modelValue' | 'defaultValue' | 'open' | 'defaultOpen' | 'searchTerm' | 'multiple' | 'disabled' | 'name' | 'resetSearchTermOnBlur'>, UseComponentIconsProps {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
id?: string
type?: InputHTMLAttributes['type']
/** The placeholder text when the input is empty. */
@@ -40,39 +45,39 @@ export interface InputMenuProps<T> extends Omit<ComboboxRootProps<T>, 'asChild'
autofocusDelay?: number
/**
* The icon displayed to open the menu.
* @defaultValue `appConfig.ui.icons.chevronDown`
* @defaultValue appConfig.ui.icons.chevronDown
*/
trailingIcon?: string
/**
* The icon displayed when an item is selected.
* @defaultValue `appConfig.ui.icons.check`
* @defaultValue appConfig.ui.icons.check
*/
selectedIcon?: string
/**
* The icon displayed to delete a tag.
* Works only when `multiple` is `true`.
* @defaultValue `appConfig.ui.icons.close`
* @defaultValue appConfig.ui.icons.close
*/
deleteIcon?: string
/**
* The content of the menu.
* @defaultValue `{ side: 'bottom', sideOffset: 8, position: 'popper' }`
* @defaultValue { side: 'bottom', sideOffset: 8, position: 'popper' }
*/
content?: Omit<ComboboxContentProps, 'as' | 'asChild' | 'forceMount'>
/**
* Display an arrow alongside the menu.
* @defaultValue `false`
* @defaultValue false
*/
arrow?: boolean | Omit<ComboboxArrowProps, 'as' | 'asChild'>
/**
* Render the menu in a portal.
* @defaultValue `true`
* @defaultValue true
*/
portal?: boolean
/**
* Whether to filter items or not, can be an array of fields to filter.
* When `false`, items will not be filtered which is useful for custom filtering.
* @defaultValue `['label']`
* @defaultValue ['label']
*/
filter?: boolean | string[]
items?: T[] | T[][]
@@ -120,7 +125,7 @@ const slots = defineSlots<InputMenuSlots<T>>()
const searchTerm = defineModel<string>('searchTerm', { default: '' })
const appConfig = useAppConfig()
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'multiple'), emits)
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'multiple', 'resetSearchTermOnBlur'), emits)
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as ComboboxContentProps)
const { emitFormBlur, emitFormChange, size: formGroupSize, color, id, name, disabled } = useFormField<InputProps>(props)
const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { tv, type VariantProps } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/ui/kbd'
@@ -12,7 +11,12 @@ const kbd = tv({ extend: tv(theme), ...(appConfig.ui?.kbd || {}) })
type KbdVariants = VariantProps<typeof kbd>
export interface KbdProps extends Omit<PrimitiveProps, 'asChild'> {
export interface KbdProps {
/**
* The element or component this component should render as.
* @defaultValue 'kbd'
*/
as?: any
value: KbdKey | string
color?: KbdVariants['color']
size?: KbdVariants['size']
@@ -28,7 +32,9 @@ export interface KbdSlots {
import { Primitive } from 'radix-vue'
import { useKbd } from '#imports'
const props = withDefaults(defineProps<KbdProps>(), { as: 'kbd' })
const props = withDefaults(defineProps<KbdProps>(), {
as: 'kbd'
})
defineSlots<KbdSlots>()
const { getKbdKey } = useKbd()

View File

@@ -1,7 +1,6 @@
<script lang="ts">
import type { ButtonHTMLAttributes } from 'vue'
import { tv } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/ui/link'
@@ -11,7 +10,16 @@ const appConfig = _appConfig as AppConfig & { ui: { link: Partial<typeof theme>
const link = tv({ extend: tv(theme), ...(appConfig.ui?.link || {}) })
export interface LinkProps extends NuxtLinkProps, Omit<PrimitiveProps, 'asChild'> {
export interface LinkProps extends NuxtLinkProps {
/**
* The element or component this component should render as when not a link.
* @defaultValue 'button'
*/
as?: any
/**
* The type of the button when not a link.
* @defaultValue 'button'
*/
type?: ButtonHTMLAttributes['type']
disabled?: boolean
active?: boolean

View File

@@ -20,17 +20,17 @@ export interface ModalProps extends DialogRootProps {
fullscreen?: boolean
/**
* Render the modal in a portal.
* @defaultValue `true`
* @defaultValue true
*/
portal?: boolean
/**
* Display a close button to dismiss the modal.
* @defaultValue `true` (`{ size: 'md', color: 'gray', variant: 'ghost' }`)
* @defaultValue true ({ size: 'md', color: 'gray', variant: 'ghost' })
*/
close?: ButtonProps | boolean
/**
* The icon displayed in the close button.
* @defaultValue `appConfig.ui.icons.close`
* @defaultValue appConfig.ui.icons.close
*/
closeIcon?: string
/** When `true`, the modal will not close when clicking outside. */

View File

@@ -31,10 +31,15 @@ export interface NavigationMenuItem extends Omit<LinkProps, 'custom'>, Pick<Navi
type NavigationMenuVariants = VariantProps<typeof navigationMenu>
export interface NavigationMenuProps<T> extends Omit<NavigationMenuRootProps, 'asChild' | 'dir' | 'orientation'> {
export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'defaultValue' | 'delayDuration' | 'disableClickTrigger' | 'disableHoverTrigger' | 'modelValue' | 'skipDelayDuration'> {
/**
* The element or component this component should render as.
* @defaultValue `div`
*/
as?: any
/**
* The icon displayed to open the menu.
* @defaultValue `appConfig.ui.icons.chevronDown`
* @defaultValue appConfig.ui.icons.chevronDown
*/
trailingIcon?: string
items?: T[] | T[][]
@@ -42,7 +47,7 @@ export interface NavigationMenuProps<T> extends Omit<NavigationMenuRootProps, 'a
variant?: NavigationMenuVariants['variant']
/**
* The orientation of the menu.
* @defaultValue `'horizontal'`
* @defaultValue 'horizontal'
*/
orientation?: NavigationMenuRootProps['orientation']
/** Display a line next to the active item. */
@@ -52,7 +57,7 @@ export interface NavigationMenuProps<T> extends Omit<NavigationMenuRootProps, 'a
content?: Omit<NavigationMenuContentProps, 'as' | 'asChild' | 'forceMount'>
/**
* Display an arrow alongside the menu.
* @defaultValue `false`
* @defaultValue false
*/
arrow?: boolean
class?: any

View File

@@ -11,55 +11,60 @@ const appConfig = _appConfig as AppConfig & { ui: { pagination: Partial<typeof t
const pagination = tv({ extend: tv(theme), ...(appConfig.ui?.pagination || {}) })
export interface PaginationProps extends Omit<PaginationRootProps, 'asChild'> {
export interface PaginationProps extends Pick<PaginationRootProps, 'defaultPage' | 'disabled' | 'itemsPerPage' | 'page' | 'showEdges' | 'siblingCount' | 'total'> {
/**
* The element or component this component should render as.
* @defaultValue `div`
*/
as?: any
/**
* The icon to use for the first page control.
* @defaultValue `appConfig.ui.icons.chevronDoubleLeft`
* @defaultValue appConfig.ui.icons.chevronDoubleLeft
*/
firstIcon?: string
/**
* The icon to use for the previous page control.
* @defaultValue `appConfig.ui.icons.chevronLeft`
* @defaultValue appConfig.ui.icons.chevronLeft
*/
prevIcon?: string
/**
* The icon to use for the next page control.
* @defaultValue `appConfig.ui.icons.chevronRight`
* @defaultValue appConfig.ui.icons.chevronRight
*/
nextIcon?: string
/**
* The icon to use for the last page control.
* @defaultValue `appConfig.ui.icons.chevronDoubleRight`
* @defaultValue appConfig.ui.icons.chevronDoubleRight
*/
lastIcon?: string
/**
* The icon to use for the ellipsis control.
* @defaultValue `appConfig.ui.icons.ellipsis`
* @defaultValue appConfig.ui.icons.ellipsis
*/
ellipsisIcon?: string
/**
* The color of the pagination controls.
* @defaultValue `'white'`
* @defaultValue 'white'
*/
color?: ButtonProps['color']
/**
* The variant of the pagination controls.
* @defaultValue `'solid'`
* @defaultValue 'solid'
*/
variant?: ButtonProps['variant']
/**
* The color of the active pagination control.
* @defaultValue `'black'`
* @defaultValue 'black'
*/
activeColor?: ButtonProps['color']
/**
* The variant of the active pagination control.
* @defaultValue `'solid'`
* @defaultValue 'solid'
*/
activeVariant?: ButtonProps['variant']
/**
* Whether to show the first, previous, next, and last controls.
* @defaultValue `true`
* @defaultValue true
*/
showControls?: boolean
size?: ButtonProps['size']

View File

@@ -12,22 +12,22 @@ const popover = tv({ extend: tv(theme), ...(appConfig.ui?.popover || {}) })
export interface PopoverProps extends PopoverRootProps, Pick<HoverCardRootProps, 'openDelay' | 'closeDelay'> {
/**
* The display mode of the popover.
* @defaultValue `"click"`
* @defaultValue 'click'
*/
mode?: 'click' | 'hover'
/**
* The content of the popover.
* @defaultValue `{ side: 'bottom', sideOffset: 8 }`
* @defaultValue { side: 'bottom', sideOffset: 8 }
*/
content?: Omit<PopoverContentProps, 'as' | 'asChild' | 'forceMount'>
/**
* Display an arrow alongside the popover.
* @defaultValue `false`
* @defaultValue false
*/
arrow?: boolean | Omit<PopoverArrowProps, 'as' | 'asChild'>
/**
* Render the popover in a portal.
* @defaultValue `true`
* @defaultValue true
*/
portal?: boolean
class?: any

View File

@@ -11,7 +11,12 @@ const progress = tv({ extend: tv(theme), ...(appConfig.ui?.progress || {}) })
type ProgressVariants = VariantProps<typeof progress>
export interface ProgressProps extends Omit<ProgressRootProps, 'asChild' | 'max'> {
export interface ProgressProps extends Pick<ProgressRootProps, 'getValueLabel' | 'modelValue'> {
/**
* The element or component this component should render as.
* @defaultValue `div`
*/
as?: any
max?: number | Array<any>
status?: boolean
inverted?: boolean
@@ -19,7 +24,7 @@ export interface ProgressProps extends Omit<ProgressRootProps, 'asChild' | 'max'
color?: ProgressVariants['color']
/**
* The orientation of the progress bar.
* @defaultValue `'horizontal'`
* @defaultValue 'horizontal'
*/
orientation?: ProgressVariants['orientation']
animation?: ProgressVariants['animation']

View File

@@ -17,14 +17,19 @@ export interface RadioGroupItem extends Pick<RadioGroupItemProps, 'disabled' | '
description?: string
}
export interface RadioGroupProps<T> extends Omit<RadioGroupRootProps, 'asChild' | 'dir' | 'orientation'> {
export interface RadioGroupProps<T> extends Pick<RadioGroupRootProps, 'defaultValue' | 'disabled' | 'loop' | 'modelValue' | 'name' | 'required'> {
/**
* The element or component this component should render as.
* @defaultValue `div`
*/
as?: any
legend?: string
items?: T[]
size?: RadioGroupVariants['size']
color?: RadioGroupVariants['color']
/**
* The orientation the radio buttons are laid out.
* @defaultValue `'vertical'`
* @defaultValue 'vertical'
*/
orientation?: RadioGroupRootProps['orientation']
class?: any

View File

@@ -19,14 +19,14 @@ export interface SelectItem extends Pick<SelectItemProps, 'disabled' | 'value'>
chip?: ChipProps
/**
* The item type.
* @defaultValue `'item'`
* @defaultValue 'item'
*/
type?: 'label' | 'separator' | 'item'
}
type SelectVariants = VariantProps<typeof select>
export interface SelectProps<T> extends Omit<SelectRootProps, 'asChild' | 'dir'>, UseComponentIconsProps {
export interface SelectProps<T> extends Omit<SelectRootProps, 'dir'>, UseComponentIconsProps {
id?: string
/** The placeholder text when the select is empty. */
placeholder?: string
@@ -35,27 +35,27 @@ export interface SelectProps<T> extends Omit<SelectRootProps, 'asChild' | 'dir'>
size?: SelectVariants['size']
/**
* The icon displayed to open the menu.
* @defaultValue `appConfig.ui.icons.chevronDown`
* @defaultValue appConfig.ui.icons.chevronDown
*/
trailingIcon?: string
/**
* The icon displayed when an item is selected.
* @defaultValue `appConfig.ui.icons.check`
* @defaultValue appConfig.ui.icons.check
*/
selectedIcon?: string
/**
* The content of the menu.
* @defaultValue `{ side: 'bottom', sideOffset: 8, position: 'popper' }`
* @defaultValue { side: 'bottom', sideOffset: 8, position: 'popper' }
*/
content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'>
/**
* Display an arrow alongside the menu.
* @defaultValue `false`
* @defaultValue false
*/
arrow?: boolean | Omit<SelectArrowProps, 'as' | 'asChild'>
/**
* Render the menu in a portal.
* @defaultValue `true`
* @defaultValue true
*/
portal?: boolean
items?: T[] | T[][]
@@ -92,7 +92,7 @@ const emits = defineEmits<SelectEmits>()
const slots = defineSlots<SelectSlots<T>>()
const appConfig = useAppConfig()
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'disabled', 'autocomplete', 'required'), emits)
const rootProps = useForwardPropsEmits(reactivePick(props, 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'disabled', 'autocomplete', 'required'), emits)
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as SelectContentProps)
const { emitFormChange, emitFormBlur, size: formGroupSize, color, id, name, disabled } = useFormField<InputProps>(props)

View File

@@ -19,14 +19,14 @@ export interface SelectMenuItem extends Pick<ComboboxItemProps, 'disabled'> {
chip?: ChipProps
/**
* The item type.
* @defaultValue `'item'`
* @defaultValue 'item'
*/
type?: 'label' | 'separator' | 'item'
}
type SelectMenuVariants = VariantProps<typeof selectMenu>
export interface SelectMenuProps<T> extends Omit<ComboboxRootProps<T>, 'asChild' | 'dir' | 'filterFunction' | 'displayValue'>, UseComponentIconsProps {
export interface SelectMenuProps<T> extends Pick<ComboboxRootProps<T>, 'modelValue' | 'defaultValue' | 'open' | 'defaultOpen' | 'searchTerm' | 'multiple' | 'disabled' | 'name' | 'resetSearchTermOnBlur'>, UseComponentIconsProps {
id?: string
/** The placeholder text when the select is empty. */
placeholder?: string
@@ -38,33 +38,33 @@ export interface SelectMenuProps<T> extends Omit<ComboboxRootProps<T>, 'asChild'
required?: boolean
/**
* The icon displayed to open the menu.
* @defaultValue `appConfig.ui.icons.chevronDown`
* @defaultValue appConfig.ui.icons.chevronDown
*/
trailingIcon?: string
/**
* The icon displayed when an item is selected.
* @defaultValue `appConfig.ui.icons.check`
* @defaultValue appConfig.ui.icons.check
*/
selectedIcon?: string
/**
* The content of the menu.
* @defaultValue `{ side: 'bottom', sideOffset: 8, position: 'popper' }`
* @defaultValue { side: 'bottom', sideOffset: 8, position: 'popper' }
*/
content?: Omit<ComboboxContentProps, 'as' | 'asChild' | 'forceMount'>
/**
* Display an arrow alongside the menu.
* @defaultValue `false`
* @defaultValue false
*/
arrow?: boolean | Omit<ComboboxArrowProps, 'as' | 'asChild'>
/**
* Render the menu in a portal.
* @defaultValue `true`
* @defaultValue true
*/
portal?: boolean
/**
* Whether to filter items or not, can be an array of fields to filter.
* When `false`, items will not be filtered which is useful for custom filtering.
* @defaultValue `['label']`
* @defaultValue ['label']
*/
filter?: boolean | string[]
items?: T[] | T[][]
@@ -109,7 +109,7 @@ const slots = defineSlots<SelectMenuSlots<T>>()
const searchTerm = defineModel<string>('searchTerm', { default: '' })
const appConfig = useAppConfig()
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'multiple'), emits)
const rootProps = useForwardPropsEmits(reactivePick(props, 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'multiple', 'resetSearchTermOnBlur'), emits)
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as ComboboxContentProps)
const { emitFormBlur, emitFormChange, size: formGroupSize, color, id, name, disabled } = useFormField<InputProps>(props)
const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)

View File

@@ -12,7 +12,12 @@ const separator = tv({ extend: tv(theme), ...(appConfig.ui?.separator || {}) })
type SeparatorVariants = VariantProps<typeof separator>
export interface SeparatorProps extends Omit<_SeparatorProps, 'asChild' | 'orientation'> {
export interface SeparatorProps extends Pick<_SeparatorProps, 'decorative'> {
/**
* The element or component this component should render as.
* @defaultValue `div`
*/
as?: any
/** Display a label in the middle. */
label?: string
/** Display an icon in the middle. */
@@ -24,7 +29,7 @@ export interface SeparatorProps extends Omit<_SeparatorProps, 'asChild' | 'orien
type?: SeparatorVariants['type']
/**
* The orientation of the separator.
* @defaultValue `'horizontal'`
* @defaultValue 'horizontal'
*/
orientation?: _SeparatorProps['orientation']
class?: any
@@ -43,7 +48,6 @@ import { reactivePick } from '@vueuse/core'
import { UAvatar, UIcon } from '#components'
const props = withDefaults(defineProps<SeparatorProps>(), {
as: 'div',
orientation: 'horizontal'
})
const slots = defineSlots<SeparatorSlots>()

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { tv } from 'tailwind-variants'
import type { PrimitiveProps } from 'radix-vue'
import type { AppConfig } from '@nuxt/schema'
import _appConfig from '#build/app.config'
import theme from '#build/ui/skeleton'
@@ -9,7 +8,12 @@ const appConfig = _appConfig as AppConfig & { ui: { skeleton: Partial<typeof the
const skeleton = tv({ extend: tv(theme), ...(appConfig.ui?.skeleton || {}) })
export interface SkeletonProps extends Omit<PrimitiveProps, 'asChild'> {
export interface SkeletonProps {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
class?: any
}
</script>
@@ -17,7 +21,7 @@ export interface SkeletonProps extends Omit<PrimitiveProps, 'asChild'> {
<script setup lang="ts">
import { Primitive } from 'radix-vue'
const props = withDefaults(defineProps<SkeletonProps>(), { as: 'div' })
const props = defineProps<SkeletonProps>()
</script>
<template>

View File

@@ -19,28 +19,28 @@ export interface SlideoverProps extends DialogRootProps {
content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'>
/**
* Display an overlay behind the slideover.
* @defaultValue `true`
* @defaultValue true
*/
overlay?: boolean
/**
* Open & close the slideover with a transition.
* @defaultValue `true`
* @defaultValue true
*/
transition?: boolean
side?: SlideoverVariants['side']
/**
* Render the slideover in a portal.
* @defaultValue `true`
* @defaultValue true
*/
portal?: boolean
/**
* Display a close button to dismiss the slideover.
* @defaultValue `true` (`{ size: 'md', color: 'gray', variant: 'ghost' }`)
* @defaultValue true ({ size: 'md', color: 'gray', variant: 'ghost' })
*/
close?: ButtonProps | boolean
/**
* The icon displayed in the close button.
* @defaultValue `appConfig.ui.icons.close`
* @defaultValue appConfig.ui.icons.close
*/
closeIcon?: string
/** When `true`, the slideover will not close when clicking outside. */

View File

@@ -11,12 +11,17 @@ const slider = tv({ extend: tv(theme), ...(appConfig.ui?.slider || {}) })
type SliderVariants = VariantProps<typeof slider>
export interface SliderProps extends Omit<SliderRootProps, 'asChild' | 'modelValue' | 'defaultValue' | 'dir' | 'orientation'> {
export interface SliderProps extends Pick<SliderRootProps, 'name' | 'disabled' | 'inverted' | 'min' | 'max' | 'step' | 'minStepsBetweenThumbs'> {
/**
* The element or component this component should render as.
* @defaultValue `div`
*/
as?: any
size?: SliderVariants['size']
color?: SliderVariants['color']
/**
* The orientation of the slider.
* @defaultValue `'horizontal'`
* @defaultValue 'horizontal'
*/
orientation?: SliderRootProps['orientation']
/** The value of the slider when initially rendered. Use when you do not need to control the state of the slider. */

View File

@@ -11,14 +11,19 @@ const switchTv = tv({ extend: tv(theme), ...(appConfig.ui?.switch || {}) })
type SwitchVariants = VariantProps<typeof switchTv>
export interface SwitchProps extends Omit<SwitchRootProps, 'asChild' | 'checked' | 'defaultChecked'> {
export interface SwitchProps extends Pick<SwitchRootProps, 'disabled' | 'id' | 'name' | 'required' | 'value'> {
/**
* The element or component this component should render as.
* @defaultValue `div`
*/
as?: any
color?: SwitchVariants['color']
size?: SwitchVariants['size']
/** When `true`, the loading icon will be displayed. */
loading?: boolean
/**
* The icon when the `loading` prop is `true`.
* @defaultValue `appConfig.ui.icons.loading`
* @defaultValue appConfig.ui.icons.loading
*/
loadingIcon?: string
/** Display an icon when the switch is checked. */

View File

@@ -21,19 +21,24 @@ export interface TabsItem extends Partial<Pick<TabsTriggerProps, 'disabled' | 'v
type TabsVariants = VariantProps<typeof tabs>
export interface TabsProps<T> extends Omit<TabsRootProps, 'asChild' | 'orientation'> {
export interface TabsProps<T> extends Pick<TabsRootProps, 'defaultValue' | 'modelValue' | 'activationMode'> {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
items?: T[]
color?: TabsVariants['color']
variant?: TabsVariants['variant']
size?: TabsVariants['size']
/**
* The orientation of the tabs.
* @defaultValue `'horizontal'`
* @defaultValue 'horizontal'
*/
orientation?: TabsRootProps['orientation']
/**
* The content of the tabs, can be disabled to prevent rendering the content.
* @defaultValue `true`
* @defaultValue true
*/
content?: boolean | Omit<TabsContentProps, 'as' | 'asChild' | 'value'>
class?: any

View File

@@ -12,7 +12,12 @@ const toast = tv({ extend: tv(theme), ...(appConfig.ui?.toast || {}) })
type ToastVariants = VariantProps<typeof toast>
export interface ToastProps extends Omit<ToastRootProps, 'asChild' | 'forceMount'> {
export interface ToastProps extends Pick<ToastRootProps, 'defaultOpen' | 'open' | 'type' | 'duration'> {
/**
* The element or component this component should render as.
* @defaultValue 'div'
*/
as?: any
title?: string
description?: string
icon?: string
@@ -26,12 +31,12 @@ export interface ToastProps extends Omit<ToastRootProps, 'asChild' | 'forceMount
actions?: ButtonProps[]
/**
* Display a close button to dismiss the toast.
* @defaultValue `true` (`{ size: 'md', color: 'gray', variant: 'link' }`)
* @defaultValue true ({ size: 'md', color: 'gray', variant: 'link' })
*/
close?: ButtonProps | boolean
/**
* The icon displayed in the close button.
* @defaultValue `appConfig.ui.icons.close`
* @defaultValue appConfig.ui.icons.close
*/
closeIcon?: string
class?: any
@@ -56,7 +61,9 @@ import { reactivePick } from '@vueuse/core'
import { useAppConfig } from '#imports'
import { UIcon, UAvatar } from '#components'
const props = withDefaults(defineProps<ToastProps>(), { close: true })
const props = withDefaults(defineProps<ToastProps>(), {
close: true
})
const emits = defineEmits<ToastEmits>()
const slots = defineSlots<ToastSlots>()

View File

@@ -16,7 +16,7 @@ export interface ToasterProps extends Omit<ToastProviderProps, 'swipeDirection'>
position?: ToasterVariants['position']
/**
* Expand the toasts to show multiple toasts at once.
* @defaultValue `true`
* @defaultValue true
*/
expand?: boolean
class?: any

View File

@@ -17,17 +17,17 @@ export interface TooltipProps extends TooltipRootProps {
kbds?: KbdProps['value'][] | KbdProps[]
/**
* The content of the tooltip.
* @defaultValue `{ side: 'bottom', sideOffset: 8 }`
* @defaultValue { side: 'bottom', sideOffset: 8 }
*/
content?: Omit<TooltipContentProps, 'as' | 'asChild'>
/**
* Display an arrow alongside the tooltip.
* @defaultValue `false`
* @defaultValue false
*/
arrow?: boolean | Omit<TooltipArrowProps, 'as' | 'asChild'>
/**
* Render the tooltip in a portal.
* @defaultValue `true`
* @defaultValue true
*/
portal?: boolean
class?: any
@@ -49,7 +49,9 @@ import { TooltipRoot, TooltipTrigger, TooltipPortal, TooltipContent, TooltipArro
import { reactivePick } from '@vueuse/core'
import { UKbd } from '#components'
const props = withDefaults(defineProps<TooltipProps>(), { portal: true })
const props = withDefaults(defineProps<TooltipProps>(), {
portal: true
})
const emits = defineEmits<TooltipEmits>()
const slots = defineSlots<TooltipSlots>()

View File

@@ -16,7 +16,7 @@ export interface UseComponentIconsProps {
loading?: boolean
/**
* The icon when the `loading` prop is `true`.
* @defaultValue `appConfig.ui.icons.loading`
* @defaultValue appConfig.ui.icons.loading
*/
loadingIcon?: string
}