Case Study Tabs
ruixen-ui/case-study-tabsFreeComponent
A tabbed customer-testimonial block with embossed stars, brand-logo tabs, an animated underline indicator that adopts each brand's accent color, a featured case-study paragraph with CTA, and a pull-quote with author.
Live preview
live · rendered by the registry
Rendered by ruixen-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ruixen.com/r/case-study-tabs.jsonSource
1"use client";23import * as React from "react";4import Link from "next/link";5import { ChevronRight, Star } from "lucide-react";6import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";7import { cn } from "@/lib/utils";89/* ── types ───────────────────────────────────────────────────── */1011export interface CaseStudyTabsBrand {12 /** Unique tab id. */13 id: string;14 /** Accessible label for screen readers. */15 name: string;16 /** Logo node — typically an inline SVG. */17 logo: React.ReactNode;18 /** CSS color string used for the animated underline indicator. Defaults to `currentColor`. */19 accentColor?: string;20}2122export interface CaseStudyAuthor {23 name: string;24 role: string;25 /** Image URL for the avatar. */26 avatarUrl?: string;27 /** Initials/letter fallback when `avatarUrl` is omitted. */28 avatarFallback?: string;29}3031export interface CaseStudy {32 brand: CaseStudyTabsBrand;33 /** Featured headline paragraph rendered in large type. Omit to render testimonial-only. */34 headline?: React.ReactNode;35 /** Optional "Read case study" CTA. */36 cta?: { label: string; href: string };37 /** Pull-quote rendered with curly-quote pseudo-elements. */38 quote: React.ReactNode;39 author: CaseStudyAuthor;40}4142export interface CaseStudyTabsProps {43 cases: CaseStudy[];44 defaultCaseId?: string;45 /** Decorative embossed stars rendered above the tab bar. Set to 0 to hide. */46 starCount?: number;47 className?: string;48}4950/* ── stars row ───────────────────────────────────────────────── */5152function StarsRow({ count }: { count: number }) {53 return (54 <div className="flex gap-1">55 {Array.from({ length: count }, (_, i) => (56 <Star57 key={i}58 className="size-5 fill-background stroke-background drop-shadow"59 />60 ))}61 </div>62 );63}6465/* ── avatar ──────────────────────────────────────────────────── */6667function AuthorAvatar({ author }: { author: CaseStudyAuthor }) {68 const frame =69 "aspect-square size-10 overflow-hidden rounded-lg border border-transparent shadow-md shadow-black/15 ring-1 ring-foreground/10";7071 if (author.avatarUrl) {72 return (73 <div className={frame}>74// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from ruixen-ui
All 417 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Editorial Accordionaccordion-editorial | ruixen-ui | Components | Free | no deps | |
| Indexed Accordionaccordion-indexed | ruixen-ui | Components | Free | 1 dep | |
| Account Menuaccount-menu | ruixen-ui | Components | Free | 1 dep | |
| Action Toolbaraction-toolbar | ruixen-ui | Components | Free | 1 dep | |
| Add Task Sheetadd-task-sheet | ruixen-ui | Components | Free | 1 dep | |
| Add To Cart Buttonadd-to-cart-button | ruixen-ui | Components | Free | 1 dep | |
| AI Chat Inputai-chat-input | ruixen-ui | Components | Free | 1 dep | |
| Animated Highlight Textanimated-highlight-text | ruixen-ui | Components | Free | 1 dep |
