본문으로 건너뛰기
cccskills
무료GitHub에 공개

reka-ui

Skill for direct usage of Reka UI v2 headless primitives (the foundation of shadcn-vue). Use when you need to compose custom components beyond those available in shadcn-vue, understand asChild/as, controlled state, portals, or migrate from Radix Vue.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(1)

  • SKILL.md7.4 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Skill: Reka UI v2

Reka UI is the successor to Radix Vue. Foundation of all shadcn-vue@latest components. Current version: v2.7.0 (March 2026)

Installation

# Via shadcn-vue (recommended — includes styles)
npx shadcn-vue@latest add [component]

# Direct (for unstyled primitives)
npm install reka-ui

# Nuxt — auto-imports
# nuxt.config.ts
export default defineNuxtConfig({
  modules: ['reka-ui/nuxt']
})

# Vite — auto-import resolver
# vite.config.ts
import { RekaResolver } from 'reka-ui/resolver'
import Components from 'unplugin-vue-components/vite'
export default defineConfig({
  plugins: [
    vue(),
    Components({ resolvers: [RekaResolver()] })
  ]
})

Fundamental pattern: Root + Parts

Every Reka UI component follows the Root + sub-parts pattern:

<script setup lang="ts">
import {
  AccordionRoot,
  AccordionItem,
  AccordionHeader,
  AccordionTrigger,
  AccordionContent,
} from 'reka-ui'

const value = ref(['item-1'])
</script>

<template>
  <!-- Root: manages state -->
  <AccordionRoot v-model="value" type="multiple">
    <!-- Item: context for each entry -->
    <AccordionItem value="item-1">
      <!-- Header + Trigger: accessible clickable element -->
      <AccordionHeader>
        <AccordionTrigger>Title</AccordionTrigger>
      </AccordionHeader>
      <!-- Content: expandable panel -->
      <AccordionContent>Item content</AccordionContent>
    </AccordionItem>
  </AccordionRoot>
</template>

Controlled vs Uncontrolled state

<!-- Controlled: you control the state -->
<DialogRoot v-model:open="isOpen">
  <DialogTrigger>Open</DialogTrigger>
  <DialogPortal>
    <DialogContent>...</DialogContent>
  </DialogPortal>
</DialogRoot>

<!-- Uncontrolled: Reka UI manages internally -->
<DialogRoot :default-open="false">
  <DialogTrigger>Open</DialogTrigger>
  <DialogPortal>
    <DialogContent>...</DialogContent>
  </DialogPortal>
</DialogRoot>

Convention: default* prefix for initial values (uncontrolled). v-model:open, v-model:value, v-model:checked for controlled.


asChild — element composition

asChild allows the Reka UI component to apply its behavior to the child element:

<!-- WITHOUT asChild: Reka renders an extra <button> -->
<DialogTrigger>
  <Button>Open</Button>  <!-- Button inside button = invalid HTML -->
</DialogTrigger>

<!-- WITH asChild: Reka applies handlers to Button directly -->
<DialogTrigger as-child>
  <Button>Open</Button>  <!-- Correct: only one interactive element -->
</DialogTrigger>

<!-- Navigation with RouterLink -->
<NavigationMenuLink as-child>
  <RouterLink to="/dashboard">Dashboard</RouterLink>
</NavigationMenuLink>

as — swap the rendered element

<!-- Primitive: swap div for section -->
<Primitive as="section" class="container">
  <slot />
</Primitive>

<!-- Create reusable base component -->
<script setup lang="ts">
import type { PrimitiveProps } from 'reka-ui'
import { Primitive } from 'reka-ui'

const props = withDefaults(defineProps<PrimitiveProps>(), {
  as: 'div'
})
</script>
<template>
  <Primitive v-bind="props">
    <slot />
  </Primitive>
</template>

Portal — render outside the current DOM

<!-- Dialogs, Tooltips, Popovers need Portal -->
<DialogRoot v-model:open="open">
  <DialogTrigger>Open</DialogTrigger>
  <DialogPortal>
    <!-- Rendered in <body> — avoids z-index and overflow issues -->
    <DialogOverlay class="fixed inset-0 bg-black/50" />
    <DialogContent class="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
      <DialogTitle>Title</DialogTitle>
      <DialogClose>Close</DialogClose>
    </DialogContent>
  </DialogPortal>
</DialogRoot>

forceMount — keep in DOM for animations

<!-- Keep content in DOM even when closed (for CSS transitions) -->
<DialogContent force-mount v-show="open" class="data-[state=open]:animate-in">
  <!-- Content always mounted, visibility controlled by data-state -->
</DialogContent>

Components by category

Form inputs

CheckboxRoot, RadioGroupRoot + RadioGroupItem, SwitchRoot, SliderRoot, NumberFieldRoot, PinInputRoot, TagsInputRoot

Overlay

DialogRoot, AlertDialogRoot, PopoverRoot, TooltipRoot, HoverCardRoot, SheetRoot (via DrawerRoot)

Navigation

NavigationMenuRoot, MenubarRoot, ContextMenuRoot, DropdownMenuRoot, TabsRoot

Selection / Search

SelectRoot, ComboboxRoot, ListboxRoot

Disclosure

AccordionRoot, CollapsibleRoot

Data display

ScrollAreaRoot, SeparatorRoot, AvatarRoot, AspectRatioRoot

Date / Time

CalendarRoot, RangeCalendarRoot (uses @internationalized/date)


Virtualization — large lists

<script setup lang="ts">
import { ComboboxRoot, ComboboxVirtualizer, ComboboxItem } from 'reka-ui'

const items = ref(Array.from({ length: 10000 }, (_, i) => `Item ${i}`))
</script>

<template>
  <ComboboxRoot>
    <ComboboxContent>
      <!-- Automatic virtualization for performance -->
      <ComboboxVirtualizer
        :options="items"
        :estimate-size="32"
        v-slot="{ option }"
      >
        <ComboboxItem :value="option">{{ option }}</ComboboxItem>
      </ComboboxVirtualizer>
    </ComboboxContent>
  </ComboboxRoot>
</template>

Supported in: ComboboxRoot, ListboxRoot, TreeRoot


useLocale and useDirection (v2.6+)

<script setup lang="ts">
import { useLocale, useDirection } from 'reka-ui'

// Global locale for date components
const { locale } = useLocale()
locale.value = 'pt-BR'

// RTL support
const { dir } = useDirection()
dir.value = 'ltr' // or 'rtl'
</script>

Date/Calendar with @internationalized/date

<script setup lang="ts">
import { CalendarRoot, CalendarGrid, CalendarCell } from 'reka-ui'
import { CalendarDate, today, getLocalTimeZone } from '@internationalized/date'
import { ref } from 'vue'

const value = ref(today(getLocalTimeZone()))
</script>

<template>
  <CalendarRoot v-model="value" locale="pt-BR">
    <CalendarGrid>
      <CalendarCell v-for="date in dates" :date="date" />
    </CalendarGrid>
  </CalendarRoot>
</template>

Radix Vue → Reka UI Migration

# Via shadcn-vue CLI (reinstalls all components with Reka)
npx shadcn-vue@latest add --all

# Manual: swap imports
# Before: import { Dialog } from 'radix-vue'
# After: import { DialogRoot } from 'reka-ui'
# or: import { Dialog } from '@/components/ui/dialog'  ← preferred

Main name changes:

Radix VueReka UI
RadixDialogDialogRoot
import from 'radix-vue'import from 'reka-ui'
Same API patternSame API pattern

Reka UI v2 Gotchas

  • asChild + slot: do not add elements between the Reka component and the direct child
  • v-model:open is reactive by reference — do not destroy and recreate the component
  • forceMount + v-show works; forceMount + v-if does not (defeats the purpose)
  • Portal teleports to <body> — scoped CSS may not reach the content
  • ComboboxVirtualizer: estimateSize can be a function for variable heights (v2.7+)
  • Calendar: @internationalized/date is a peer dependency — install separately: npm i @internationalized/date

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Accessibility auditing and remediation skill for Vue 3 + Reka UI. Use when reviewing components, verifying WCAG 2.1 AA, fixing ARIA issues, or validating keyboard navigation in Reka UI components.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

pwdev-solucoes/pwdev-claude-marketplace32026년 10월 15일 업데이트

ai-infra

무료

Infraestrutura para IA — GPU, servidores MCP, gateway de LLM, pipeline de inferência, custo de token, cache semântico e observabilidade de modelo. Use quando o usuário disser "GPU", "MCP server", "LLM", "inferência", "modelo", "gateway de IA", "custo de token", "rate limit da API de IA", "self-host de modelo".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

pwdev-solucoes/pwdev-claude-marketplace32026년 10월 15일 업데이트

alt-text

무료

Escreve texto alternativo e descrição de imagem para peças de rede social. Use quando o usuário disser "alt text", "texto alternativo", "descrição da imagem", "acessibilidade da peça", "descrever para leitor de tela", ou automaticamente antes de qualquer publicação. Obrigatório em todas as peças — em carrossel, um por slide.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

pwdev-solucoes/pwdev-claude-marketplace32026년 10월 15일 업데이트

Organiza, compara e seleciona entre as variações geradas, e publica a grade de comparação como Artifact para aprovação do time. Use quando o usuário disser "qual dessas", "comparar as variações", "escolher a melhor", "mostrar as opções", "montar grade de aprovação", ou após qualquer lote de geração. Selecionar é trabalho, não detalhe.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

pwdev-solucoes/pwdev-claude-marketplace32026년 10월 15일 업데이트

Aumenta resolução e qualidade de imagem via Freepik/Magnific, ou orienta o processo manual quando não há chave. Use quando o usuário disser "upscale", "melhorar a resolução", "a imagem está pixelada", "Magnific", "Freepik", "aumentar a imagem", "imagem pequena demais". Gasta crédito — exige confirmação.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

pwdev-solucoes/pwdev-claude-marketplace32026년 10월 15일 업데이트

CI/CD e automação — GitHub Actions, Terraform, OpenTofu, Ansible, n8n. Use quando o usuário disser "pipeline", "CI/CD", "GitHub Actions", "workflow", "terraform", "ansible", "n8n", "automatizar", "deploy automático", "IaC".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

pwdev-solucoes/pwdev-claude-marketplace32026년 10월 15일 업데이트

pwdev-solucoes의 스킬 모두 보기

이 스킬의 문제 신고