UIPackage

Toggle Group

Vue action
Edit on GitHub

Group of `Toggle` buttons that act as a single-select or multi-select control. Use for view-mode pickers (grid/list), text-format toolbars, and any "pick one of N" button bar.

Also available for React ->

Installation

$ npx shadcn-vue@latest add https://uipkge.dev/r/vue/toggle-group.json

Or with the named registry: npx shadcn-vue@latest add @uipkge/toggle-group

Examples

Props

Name Type / Values Default Required
class HTMLAttributes['class'] optional
variant
'default''outline'
optional
size
'default''sm''lg'
optional
spacing number 0 optional
asChild boolean optional
as string | object optional
type
'single''multiple'
optional
modelValue string | string[] optional
defaultValue string | string[] optional
disabled boolean optional
loop boolean optional
orientation
'horizontal''vertical'
optional
rovingFocus boolean optional
dir
'ltr''rtl'
optional

Schema

Type aliases from this item's source — use them to shape the data you pass in.

ToggleGroupContext
type ToggleGroupContext {
  variant?: 'default' | 'outline'
  size?: 'default' | 'sm' | 'lg'
  spacing?: number
}

Dependencies

Used by

Files (3)

  • app/components/ui/toggle-group/ToggleGroup.vue 1.8 kB
    <script setup lang="ts">
    import type { ToggleGroupRootEmits } from 'reka-ui'
    import type { HTMLAttributes } from 'vue'
    import { reactiveOmit } from '@vueuse/core'
    import { ToggleGroupRoot, useForwardPropsEmits } from 'reka-ui'
    import { provide } from 'vue'
    import { cn } from '@/lib/utils'
    
    // Inlined unions: SFC compiler can't extract runtime props from
    // `VariantProps<typeof toggleVariants>['...']`. Same for the
    // reka-ui `ToggleGroupRootProps` (no exports.types). Inline the
    // surface we expose.
    const props = withDefaults(
      defineProps<{
        class?: HTMLAttributes['class']
        variant?: 'default' | 'outline'
        size?: 'default' | 'sm' | 'lg'
        spacing?: number
        asChild?: boolean
        as?: string | object
        type?: 'single' | 'multiple'
        modelValue?: string | string[]
        defaultValue?: string | string[]
        disabled?: boolean
        loop?: boolean
        orientation?: 'horizontal' | 'vertical'
        rovingFocus?: boolean
        dir?: 'ltr' | 'rtl'
      }>(),
      {
        spacing: 0,
      },
    )
    
    const emits = defineEmits<ToggleGroupRootEmits>()
    
    provide('toggleGroup', {
      variant: props.variant,
      size: props.size,
      spacing: props.spacing,
    })
    
    const delegatedProps = reactiveOmit(props, 'class', 'size', 'variant')
    const forwarded = useForwardPropsEmits(delegatedProps, emits)
    </script>
    
    <template>
      <ToggleGroupRoot
        v-slot="slotProps"
        data-uipkge
        data-slot="toggle-group"
        :data-size="size"
        :data-variant="variant"
        :data-spacing="spacing"
        :style="{
          '--gap': spacing,
        }"
        v-bind="forwarded"
        :class="
          cn(
            'group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs',
            props.class,
          )
        "
      >
        <slot v-bind="slotProps" />
      </ToggleGroupRoot>
    </template>
  • app/components/ui/toggle-group/ToggleGroupItem.vue 1.7 kB
    <script setup lang="ts">
    import type { HTMLAttributes } from 'vue'
    import { reactiveOmit } from '@vueuse/core'
    import { ToggleGroupItem, useForwardProps } from 'reka-ui'
    import { inject } from 'vue'
    import { cn } from '@/lib/utils'
    import { toggleVariants } from '@/components/ui/toggle'
    
    type ToggleGroupContext = {
      variant?: 'default' | 'outline'
      size?: 'default' | 'sm' | 'lg'
      spacing?: number
    }
    
    // Inlined unions: SFC compiler can't extract runtime props from
    // indexed-access types. Same for reka-ui's ToggleGroupItemProps.
    const props = defineProps<{
      class?: HTMLAttributes['class']
      variant?: 'default' | 'outline'
      size?: 'default' | 'sm' | 'lg'
      asChild?: boolean
      as?: string | object
      value: string
      disabled?: boolean
    }>()
    
    const context = inject<ToggleGroupContext>('toggleGroup')
    
    const delegatedProps = reactiveOmit(props, 'class', 'size', 'variant')
    const forwardedProps = useForwardProps(delegatedProps)
    </script>
    
    <template>
      <ToggleGroupItem
        v-slot="slotProps"
        data-uipkge
        data-slot="toggle-group-item"
        :data-variant="context?.variant || variant"
        :data-size="context?.size || size"
        :data-spacing="context?.spacing"
        v-bind="forwardedProps"
        :class="
          cn(
            toggleVariants({
              variant: context?.variant || variant,
              size: context?.size || size,
            }),
            'w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10',
            'data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l',
            props.class,
          )
        "
      >
        <slot v-bind="slotProps" />
      </ToggleGroupItem>
    </template>
  • app/components/ui/toggle-group/index.ts 0.1 kB
    export { default as ToggleGroup } from './ToggleGroup.vue'
    export { default as ToggleGroupItem } from './ToggleGroupItem.vue'

Raw manifest: https://uipkge.dev/r/vue/toggle-group.json