primitives

Button Group

Button Group — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).

Загрузка превью…

src/ui/button-group/ButtonGroup.vue

<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/lib/utils"
import { buttonGroupVariants, type ButtonGroupVariants } from "./variants"

const props = defineProps<{
  /** Доп. классы. Имя `class` — соглашение shadcn-vue (не `className`). */
  class?: HTMLAttributes["class"]
  orientation?: ButtonGroupVariants["orientation"]
}>()
</script>

<template>
  <div
    role="group"
    data-slot="button-group"
    :data-orientation="props.orientation"
    :class="cn(buttonGroupVariants({ orientation: props.orientation }), props.class)"
  >
    <slot />
  </div>
</template>

src/ui/button-group/ButtonGroupSeparator.vue

<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import type { SeparatorProps } from "reka-ui"
import { Separator } from "@/components/ui/separator"
import { cn } from "@/lib/utils"

const props = withDefaults(
  defineProps<
    SeparatorProps & {
      /** Доп. классы. Имя `class` — соглашение shadcn-vue (не `className`). */
      class?: HTMLAttributes["class"]
    }
  >(),
  {
    orientation: "vertical",
  }
)
</script>

<template>
  <Separator
    data-slot="button-group-separator"
    :orientation="props.orientation"
    :class="
      cn(
        'cn-button-group-separator relative self-stretch data-horizontal:mx-px data-horizontal:w-auto data-vertical:my-px data-vertical:h-auto',
        props.class
      )
    "
  />
</template>

src/ui/button-group/ButtonGroupText.vue

<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { Primitive } from "reka-ui"
import { cn } from "@/lib/utils"

const props = withDefaults(
  defineProps<{
    /** Доп. классы. Имя `class` — соглашение shadcn-vue (не `className`). */
    class?: HTMLAttributes["class"]
    /** Соответствие Radix `asChild`: Reka UI `Primitive` с `as-child`. */
    asChild?: boolean
  }>(),
  {
    asChild: false,
  }
)
</script>

<template>
  <Primitive
    as="div"
    :as-child="props.asChild"
    :class="cn('cn-button-group-text flex items-center [&_svg]:pointer-events-none', props.class)"
  >
    <slot />
  </Primitive>
</template>

src/ui/button-group/index.ts

export { default as ButtonGroup } from "./ButtonGroup.vue"
export { default as ButtonGroupText } from "./ButtonGroupText.vue"
export { default as ButtonGroupSeparator } from "./ButtonGroupSeparator.vue"
export { buttonGroupVariants, type ButtonGroupVariants } from "./variants"

src/ui/button-group/variants.ts

import { cva, type VariantProps } from "class-variance-authority"

/**
 * Перенесено дословно из shadcn (registry/bases/radix/ui/button-group.tsx, MIT).
 *
 * cva-блоки — чистые JS-объекты и переносятся между React и Vue без единой
 * правки. Вся визуальная семантика живёт здесь, а фреймворк-специфичной
 * остаётся только разметка.
 */
export const buttonGroupVariants = cva(
  "cn-button-group group/button-group flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
  {
    variants: {
      orientation: {
        horizontal:
          "cn-button-group-orientation-horizontal [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
        vertical:
          "cn-button-group-orientation-vertical flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
      },
    },
    defaultVariants: {
      orientation: "horizontal",
    },
  }
)

export type ButtonGroupVariants = VariantProps<typeof buttonGroupVariants>

Установка

npx shadcn-vue@latest add https://revueui.rootapi.dev/r/button-group.json

Зависимости реестра

npm-зависимости

  • class-variance-authority
  • reka-ui

Источник: порт из ReUI (Keenthemes, MIT)