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>