FAQ — Categorized Tabs
blockmarketingQuestion set grouped behind category tabs, each panel holding its own accordion with a count badge, for support pages where one flat list would run past thirty entries.
Installation
$pnpm dlx shadcn-vue@latest add https://uipkge.dev/r/vue/faq-categorized-tabs.json$npx shadcn-vue@latest add https://uipkge.dev/r/vue/faq-categorized-tabs.json$yarn dlx shadcn-vue@latest add https://uipkge.dev/r/vue/faq-categorized-tabs.json$bunx shadcn-vue@latest add https://uipkge.dev/r/vue/faq-categorized-tabs.jsonNamed registry:
npx shadcn-vue@latest add @uipkge/faq-categorized-tabsInstalls to:app/components/blocks/Variants
Loading interactive previews…
Loading interactive previews…
Files installed (1)
app/components/blocks/FaqCategorizedTabs.vue3.3 kB
<script setup lang="ts"> import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' const categories = [ { id: 'security', label: 'Security', entries: [ { q: 'Where is our data stored?', a: 'Definitions and query metadata sit in your chosen region. Warehouse rows are never copied out.', }, { q: 'Are you SOC 2 audited?', a: 'Type II, audited annually. The report and the subprocessor list are on the trust centre.', }, { q: 'Can we bring our own keys?', a: 'Yes, on the enterprise plan, with rotation handled through your KMS.' }, ], }, { id: 'billing', label: 'Billing', entries: [ { q: 'How is usage counted?', a: 'By query, not by seat. Materialised reads are not billed twice within their freshness window.', }, { q: 'Can we cap spend?', a: 'Per-team query budgets are enforced at run time, so a runaway dashboard cannot outspend its ceiling.', }, { q: 'Do you offer annual terms?', a: 'Yes, with a discount and an invoiced option above a threshold.' }, ], }, { id: 'setup', label: 'Setup', entries: [ { q: 'What do you need from us?', a: 'A read-only role, your identity provider, and an hour with whoever owns the warehouse.', }, { q: 'How long until first value?', a: 'Most teams publish a first certified metric on day one and finish the rollout in five weeks.', }, ], }, ] </script> <template> <section data-slot="faq-categorized-tabs" class="bg-background"> <div class="mx-auto max-w-4xl px-6 py-20 lg:py-28"> <div class="max-w-2xl"> <Badge variant="secondary">Support</Badge> <h2 class="mt-4 text-3xl font-semibold tracking-tight sm:text-4xl">Answers by topic</h2> <p class="text-muted-foreground mt-3 text-lg"> Grouped rather than listed, because one flat list of thirty questions is a list nobody reads. </p> </div> <Tabs :default-value="categories[0].id" class="mt-10"> <TabsList variant="pill" class="flex-nowrap overflow-x-auto"> <TabsTrigger v-for="category in categories" :key="category.id" :value="category.id" variant="pill"> {{ category.label }} <span class="text-muted-foreground ml-1.5 font-mono text-xs">{{ category.entries.length }}</span> </TabsTrigger> </TabsList> <TabsContent v-for="category in categories" :key="category.id" :value="category.id" class="mt-6"> <Accordion type="single" collapsible class="w-full"> <AccordionItem v-for="entry in category.entries" :key="entry.q" :value="entry.q"> <AccordionTrigger class="text-left font-medium">{{ entry.q }}</AccordionTrigger> <AccordionContent class="text-muted-foreground leading-relaxed">{{ entry.a }}</AccordionContent> </AccordionItem> </Accordion> </TabsContent> </Tabs> <Button variant="ghost" class="mt-8">Browse the full help centre</Button> </div> </section> </template>
Raw manifest:https://uipkge.dev/r/vue/faq-categorized-tabs.json