import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; import { Sparkles, Palette, Type, Shapes, MousePointerClick, FileEdit, LayoutGrid, SlidersHorizontal, Compass, Home, Mail, Phone, User, Users, Bell, TrendingUp, Rocket, Search, ChevronsUpDown, } from 'lucide-react'; import { useBrandColors } from '../../../contexts/BrandColorsContext'; import { useOptionalLayout } from '../../../contexts/LayoutContext'; import { cn } from '../../shared/utils'; import { Header } from '../../layout/header'; import { PageHeader } from '../../ui/page-header'; import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, } from '../../ui/card'; import { Separator } from '../../ui/separator'; import { Badge } from '../../ui/badge'; import { Button } from '../../ui/button'; import { Input } from '../../ui/input'; import { Label } from '../../ui/label'; import { Textarea } from '../../ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../ui/select'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '../../ui/tabs'; import { Alert, AlertTitle, AlertDescription } from '../../ui/alert'; import { Progress } from '../../ui/progress'; import { Skeleton } from '../../ui/skeleton'; import { Empty, EmptyIcon, EmptyTitle, EmptyDescription, EmptyAction } from '../../ui/empty'; import { Avatar, AvatarImage, AvatarFallback } from '../../ui/avatar'; import { StatsCard } from '../../ui/stats-card'; import { Timeline, TimelineItem, TimelineDot, TimelineContent, TimelineHeading, TimelineTime, TimelineDescription, } from '../../ui/timeline'; import { Checkbox } from '../../ui/checkbox'; import { RadioGroup, RadioGroupItem } from '../../ui/radio-group'; import { Switch } from '../../ui/switch'; import { Slider } from '../../ui/slider'; import { ToggleGroup, ToggleGroupItem } from '../../ui/toggle-group'; import { InputOTP, InputOTPGroup, InputOTPSlot } from '../../ui/input-otp'; import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '../../ui/dialog'; import { Popover, PopoverTrigger, PopoverContent } from '../../ui/popover'; import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '../../ui/tooltip'; import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, } from '../../ui/dropdown-menu'; import { HoverCard, HoverCardTrigger, HoverCardContent } from '../../ui/hover-card'; import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '../../ui/accordion'; import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '../../ui/collapsible'; import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationPrevious, PaginationNext, } from '../../ui/pagination'; import { FeatureCard, QuickActionCard, ActivityCard, NotificationCard, ProfileCard, ProjectCard, type ActivityItem, type NotificationItem, } from '../../blocks/card-patterns'; import { ThemeToggle } from '../../brand/theme-toggle'; import { LanguageSelector } from '../../brand/language-selector'; import { Isotipo, Mosaico, Cuadrados } from '../../brand/isotype'; import { XerticaLogo } from '../../brand/xertica-logo'; import { XerticaXLogo } from '../../brand/xertica-xlogo'; export interface ShowcaseContentProps { /** * Brand theme id to switch to on mount (e.g. `"xertica"`). Left undefined * by default so embedding this content inside a host app never hijacks its * active theme — only the standalone `ShowcasePage` opts into this. */ defaultThemeId?: string; } const TYPOGRAPHY_SCALE = [ { key: 'hero', family: 'heading', weight: 'Heavy 900', size: '60px', lineHeight: '105%', tracking: '-2px', }, { key: 'h1', family: 'heading', weight: 'Bold 700', size: '44px', lineHeight: '120%', tracking: '-1.5px', }, { key: 'h2', family: 'heading', weight: 'Bold 700', size: '32px', lineHeight: '125%', tracking: '-1px', }, { key: 'h3', family: 'heading', weight: 'Bold 700', size: '24px', lineHeight: '130%', tracking: '-0.5px', }, { key: 'body', family: 'body', weight: 'Regular 400', size: '18px', lineHeight: '165%', tracking: 'normal', }, { key: 'eyebrow', family: 'body', weight: 'Medium 500', size: '13px', lineHeight: '150%', tracking: '1.5px', }, { key: 'nav', family: 'body', weight: 'Regular/Medium', size: '15–16px', lineHeight: '150%', tracking: 'normal', }, { key: 'button', family: 'body', weight: 'Semibold/Bold 600–700', size: '15–16px', lineHeight: '120%', tracking: '-0.2px', }, ] as const; const TYPOGRAPHY_FONT_SIZE: Record<(typeof TYPOGRAPHY_SCALE)[number]['key'], string> = { hero: '60px', h1: '44px', h2: '32px', h3: '24px', body: '18px', eyebrow: '13px', nav: '16px', button: '16px', }; const ACCENT_PALETTE = [ { name: 'Negro Xertica', hex: '#1E1E1E' }, { name: 'Azul', hex: '#3D63AC' }, { name: 'Celeste', hex: '#1899AF' }, { name: 'Magenta', hex: '#C45BAA' }, { name: 'Rojo Coral', hex: '#DE5B48' }, { name: 'Rosado', hex: '#E2B8D2' }, { name: 'Amarillo', hex: '#FAF338' }, { name: 'Naranja', hex: '#E37744' }, { name: 'Verde', hex: '#2E8B5A' }, { name: 'Verde azulado', hex: '#39C6AE' }, ]; const SURFACE_PALETTE = [ { name: 'Marfil', hex: '#FFFEF8' }, { name: 'Crema / Papel', hex: '#F2EDD8' }, { name: 'Fondo Slides', hex: '#F5F0E8' }, { name: 'Off-white cálido', hex: '#E9E6DC' }, ]; const APPROVED_COMBINATIONS = [ ['#1899AF', '#DE5B48'], ['#DE5B48', '#3D63AC', '#E2B8D2'], ['#DE5B48', '#2E8B5A', '#E2B8D2'], ['#FAF338', '#DE5B48'], ['#C45BAA', '#1899AF'], ]; const INTERSECTIONS = [ { a: '#1899AF', b: '#C45BAA', result: '#5A4A96', obligatory: true }, { a: '#2E8B5A', b: '#DE5B48', result: '#2A2415', obligatory: true }, { a: '#1899AF', b: '#FAF338', result: '#2E9A3A', obligatory: false }, ]; const SAMPLE_ACTIVITY_ITEMS: ActivityItem[] = [ { id: 'a1', user: { name: 'Alex Rivera', initials: 'AR' }, action: 'updated', target: 'Showcase Page', time: '2m', type: 'update', }, { id: 'a2', user: { name: 'Mia Chen', initials: 'MC' }, action: 'deployed', target: 'v3.1.0', time: '1h', type: 'deploy', }, { id: 'a3', user: { name: 'Diego Torres', initials: 'DT' }, action: 'commented on', target: 'Brand tokens', time: '3h', type: 'comment', }, ]; const SAMPLE_NOTIFICATION_ITEMS: NotificationItem[] = [ { id: 'n1', title: 'New theme available', message: 'The xertica brand theme is ready to use.', time: '5m', read: false, type: 'success', }, { id: 'n2', title: 'Token update', message: '--card-hover-shadow now resolves to none.', time: '1h', read: false, type: 'info', }, { id: 'n3', title: 'Review requested', message: 'Please review the button press-shift spec.', time: '1d', read: true, type: 'default', }, ]; function SectionHeading({ icon, title, description, }: { icon: React.ReactNode; title: string; description?: string; }) { return (
{icon}

{title}

{description &&

{description}

}
); } function StaticSwatch({ name, hex }: { name: string; hex: string }) { return (

{name}

{hex}

); } export function ShowcaseContent({ defaultThemeId }: ShowcaseContentProps) { const { t } = useTranslation(); const { currentTheme, themes, setTheme } = useBrandColors(); const layout = useOptionalLayout(); const sidebarExpanded = layout?.sidebarExpanded ?? false; const sidebarWidth = layout?.sidebarWidth ?? 280; useEffect(() => { if (defaultThemeId) { setTheme(defaultThemeId); } // Only ever applied once, on mount — never re-forced if the visitor picks a different theme. // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const [progress, setProgress] = useState(64); const [otpValue, setOtpValue] = useState(''); const [radioValue, setRadioValue] = useState('starter'); const [checked, setChecked] = useState(true); const [switchOn, setSwitchOn] = useState(true); const [paginationPage, setPaginationPage] = useState(2); const orderedThemes = [ ...themes.filter(theme => theme.id === 'xertica'), ...themes.filter(theme => theme.id === 'xertica-original'), ...themes.filter(theme => theme.id !== 'xertica' && theme.id !== 'xertica-original'), ]; return (
}, { label: t('showcase.breadcrumb') }, ]} renderLink={(href, props) => } />
{/* 0. Theme switcher */} {t('showcase.themeSwitcher.label')} {t('showcase.themeSwitcher.hint')}
{orderedThemes.map(theme => ( ))}
{/* 1. Typography */}
} title={t('showcase.sections.typography')} description={t('showcase.typography.description')} /> {TYPOGRAPHY_SCALE.map(row => (

{t(`showcase.typography.samples.${row.key}`)}

{t(`showcase.typography.labels.${row.key}`)} — {row.weight} · {row.size} ·{' '} {row.lineHeight} lh · {row.tracking} tracking

))}

{t('showcase.typography.footnote')}

{/* 2. Colors & surfaces */}
} title={t('showcase.sections.colors')} description={t('showcase.colors.description')} /> {t('showcase.colors.staticBadge')} {t('showcase.colors.accentPalette')} {ACCENT_PALETTE.map(color => ( ))}
{t('showcase.colors.surfaces')} {SURFACE_PALETTE.map(surface => ( ))} {t('showcase.colors.intersections')} {t('showcase.colors.intersectionsHint')} {INTERSECTIONS.map(pair => (
+ = {pair.result} {pair.obligatory && ( {t('showcase.colors.obligatory')} )}
))}
{t('showcase.colors.combinations')} {APPROVED_COMBINATIONS.map((combo, index) => (
{combo.map((hex, hexIndex) => ( ))}
))}
{/* 3. Isotypes & logo */}
} title={t('showcase.sections.brandMarks')} description={t('showcase.brandMarks.description')} />

Mosaico

{(['blue-magenta', 'blue-yellow', 'green-red'] as const).map(variant => (

Cuadrados · {variant}

))} {(['magenta-blue', 'blue-red', 'green-red'] as const).map(variant => (

Isotipo · {variant}

))}

XerticaLogo · default

XerticaLogo · white

XerticaXLogo

{t('showcase.brandMarks.neverTitle')}
  • {t('showcase.brandMarks.never.gradients')}
  • {t('showcase.brandMarks.never.metallic')}
  • {t('showcase.brandMarks.never.decorativeFonts')}
  • {t('showcase.brandMarks.never.textOverShapes')}
  • {t('showcase.brandMarks.never.floatingShapes')}
  • {t('showcase.brandMarks.never.logoAbuse')}
{/* 4. Buttons */}
} title={t('showcase.sections.buttons')} description={t('showcase.buttons.description')} />
{t('showcase.buttons.segmentedA')} {t('showcase.buttons.segmentedB')} {t('showcase.buttons.segmentedC')}

{t('showcase.buttons.footnote')}

{/* 5. Forms */}
} title={t('showcase.sections.forms')} description={t('showcase.forms.description')} />
event.preventDefault()} >