{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "team-section",
  "title": "Team Section",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-svelte/blocks/team-section/TeamSection.svelte",
      "content": "<script lang=\"ts\" module>\n  export interface TeamMember {\n    name: string\n    role: string\n    bio?: string\n    /** When any member has a department, the grid groups under uppercase headers. */\n    department?: string\n    twitter?: string\n    github?: string\n    linkedin?: string\n  }\n\n  export interface TeamSectionProps {\n    eyebrow?: string\n    title?: string\n    description?: string\n    members?: TeamMember[]\n    /** 'grid' shows full cards with bios; 'compact' tightens cards and drops them. */\n    variant?: 'grid' | 'compact'\n    class?: string\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n  import { Avatar, AvatarFallback } from '$lib/components/ui/avatar'\n  import { Badge } from '$lib/components/ui/badge'\n  import { Button } from '$lib/components/ui/button'\n  import { Card, CardContent } from '$lib/components/ui/card'\n\n  /**\n   * Marketing team section. The roster below is stub data — swap\n   * DEFAULT_MEMBERS for your data source after installing, or pass `members`.\n   */\n  const DEFAULT_MEMBERS: TeamMember[] = [\n    {\n      name: 'Amara Okafor',\n      role: 'Co-founder & CEO',\n      bio: 'Sets the vision and still reviews every release note before it ships.',\n      twitter: 'https://x.com/amaraokafor',\n      linkedin: 'https://linkedin.com/in/amaraokafor',\n    },\n    {\n      name: 'Jonas Lindqvist',\n      role: 'Co-founder & CTO',\n      bio: 'Owns architecture and keeps p95 latency under 80ms in every region.',\n      github: 'https://github.com/jonaslindqvist',\n      linkedin: 'https://linkedin.com/in/jonaslindqvist',\n    },\n    {\n      name: 'Priya Raghavan',\n      role: 'Staff Engineer',\n      bio: 'Leads the platform team and maintains our public REST and GraphQL APIs.',\n      github: 'https://github.com/priyaraghavan',\n    },\n    {\n      name: 'Marco Deluca',\n      role: 'Product Designer',\n      bio: 'Turns messy workflows into calm interfaces and runs our weekly design critique.',\n      twitter: 'https://x.com/marcodeluca',\n      github: 'https://github.com/marcodeluca',\n      linkedin: 'https://linkedin.com/in/marcodeluca',\n    },\n    {\n      name: 'Tomoko Saito',\n      role: 'Head of People',\n      bio: 'Builds hiring loops that respect candidates and onboarding that actually sticks.',\n      linkedin: 'https://linkedin.com/in/tomokosaito',\n    },\n    {\n      name: 'Felix Adeyemi',\n      role: 'Growth Engineer',\n      bio: 'Experiments across onboarding and pricing pages; ships behind flags daily.',\n      twitter: 'https://x.com/felixadeyemi',\n    },\n  ]\n\n  let {\n    eyebrow,\n    title,\n    description,\n    members,\n    variant = 'grid',\n    class: className,\n  }: TeamSectionProps = $props()\n\n  const compact = $derived(variant === 'compact')\n  const showHeader = $derived(Boolean(eyebrow || title || description))\n\n  interface MemberSection {\n    department?: string\n    members: TeamMember[]\n  }\n\n  const sections = $derived.by((): MemberSection[] => {\n    const roster = members ?? DEFAULT_MEMBERS\n    if (!roster.some((member) => member.department)) return [{ members: roster }]\n    const grouped = new Map<string, TeamMember[]>()\n    for (const member of roster) {\n      const key = member.department ?? ''\n      if (!grouped.has(key)) grouped.set(key, [])\n      grouped.get(key)!.push(member)\n    }\n    return Array.from(grouped.entries()).map(([department, groupedMembers]) => ({\n      department: department || undefined,\n      members: groupedMembers,\n    }))\n  })\n\n  function initialsFor(name: string): string {\n    return name\n      .split(/\\s+/)\n      .filter(Boolean)\n      .slice(0, 2)\n      .map((part) => part.charAt(0).toUpperCase())\n      .join('')\n  }\n</script>\n\n<section data-slot=\"team-section\" class={cn('bg-background', className)}>\n  <div class=\"mx-auto max-w-6xl px-6 py-24\">\n    {#if showHeader}\n      <div data-slot=\"team-section-header\" class=\"mx-auto max-w-2xl text-center\">\n        {#if eyebrow}\n          <p class=\"text-primary text-sm font-medium tracking-widest uppercase\">{eyebrow}</p>\n        {/if}\n        {#if title}\n          <h2 class=\"mt-2 text-3xl font-semibold tracking-tight sm:text-4xl\">{title}</h2>\n        {/if}\n        {#if description}\n          <p class=\"text-muted-foreground mt-3 text-lg leading-relaxed\">{description}</p>\n        {/if}\n      </div>\n    {/if}\n\n    {#each sections as section, i (section.department ?? 'team')}\n      <div data-slot=\"team-section-group\" class={i > 0 || showHeader ? 'mt-12' : undefined}>\n        {#if section.department}\n          <h3 class=\"text-muted-foreground text-xs font-semibold tracking-widest uppercase\">\n            {section.department}\n          </h3>\n        {/if}\n        <div\n          data-slot=\"team-section-grid\"\n          class={cn('grid gap-6 sm:grid-cols-2 lg:grid-cols-3', compact && 'gap-4', section.department && 'mt-6')}\n        >\n          {#each section.members as member (member.name)}\n            <Card class=\"text-center\">\n              <CardContent class={cn('flex flex-col items-center', compact ? 'gap-3 p-4' : 'gap-4 p-6')}>\n                <Avatar class={compact ? 'size-10' : 'size-16'}>\n                  <AvatarFallback class={compact ? 'text-sm' : 'text-lg'}>\n                    {initialsFor(member.name)}\n                  </AvatarFallback>\n                </Avatar>\n                <div class=\"space-y-1\">\n                  <p class=\"text-sm font-semibold\">{member.name}</p>\n                  <Badge variant=\"secondary\">{member.role}</Badge>\n                  {#if !compact && member.bio}\n                    <p class=\"text-muted-foreground line-clamp-2 text-xs leading-relaxed\">\n                      {member.bio}\n                    </p>\n                  {/if}\n                </div>\n                {#if member.twitter || member.github || member.linkedin}\n                  <div class=\"flex items-center gap-0.5\">\n                    {#if member.twitter}\n                      <Button variant=\"ghost\" size=\"icon-sm\">\n                        {#snippet child({ props })}\n                          <a\n                            href={member.twitter}\n                            target=\"_blank\"\n                            rel=\"noreferrer\"\n                            aria-label={`${member.name} on X (Twitter)`}\n                            {...props}\n                          >\n                            <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"size-4\" aria-hidden=\"true\">\n                              <path\n                                d=\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\"\n                              />\n                            </svg>\n                          </a>\n                        {/snippet}\n                      </Button>\n                    {/if}\n                    {#if member.github}\n                      <Button variant=\"ghost\" size=\"icon-sm\">\n                        {#snippet child({ props })}\n                          <a\n                            href={member.github}\n                            target=\"_blank\"\n                            rel=\"noreferrer\"\n                            aria-label={`${member.name} on GitHub`}\n                            {...props}\n                          >\n                            <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"size-4\" aria-hidden=\"true\">\n                              <path\n                                d=\"M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.58.11.79-.25.79-.55v-2.15c-3.2.69-3.87-1.36-3.87-1.36-.52-1.33-1.28-1.68-1.28-1.68-1.04-.71.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.02 1.76 2.69 1.25 3.35.96.1-.75.4-1.25.72-1.54-2.55-.29-5.24-1.28-5.24-5.68 0-1.26.45-2.28 1.19-3.09-.12-.29-.52-1.46.11-3.05 0 0 .97-.31 3.18 1.18a11.1 11.1 0 0 1 5.78 0c2.21-1.49 3.18-1.18 3.18-1.18.63 1.59.23 2.76.11 3.05.74.81 1.19 1.83 1.19 3.09 0 4.41-2.69 5.38-5.26 5.66.41.35.78 1.05.78 2.12v3.14c0 .31.21.67.8.55A11.51 11.51 0 0 0 23.5 12C23.5 5.65 18.35.5 12 .5z\"\n                              />\n                            </svg>\n                          </a>\n                        {/snippet}\n                      </Button>\n                    {/if}\n                    {#if member.linkedin}\n                      <Button variant=\"ghost\" size=\"icon-sm\">\n                        {#snippet child({ props })}\n                          <a\n                            href={member.linkedin}\n                            target=\"_blank\"\n                            rel=\"noreferrer\"\n                            aria-label={`${member.name} on LinkedIn`}\n                            {...props}\n                          >\n                            <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"size-4\" aria-hidden=\"true\">\n                              <path\n                                d=\"M20.45 20.45h-3.55v-5.57c0-1.33-.03-3.04-1.85-3.04-1.85 0-2.14 1.45-2.14 2.94v5.67H9.36V9h3.41v1.56h.05c.47-.9 1.63-1.85 3.36-1.85 3.6 0 4.27 2.37 4.27 5.46zM5.34 7.43a2.06 2.06 0 1 1 0-4.12 2.06 2.06 0 0 1 0 4.12zM7.12 20.45H3.56V9h3.56zM22.22 0H1.77C.79 0 0 .77 0 1.72v20.55C0 23.23.79 24 1.77 24h20.45c.98 0 1.78-.77 1.78-1.73V1.72C24 .77 23.2 0 22.22 0z\"\n                              />\n                            </svg>\n                          </a>\n                        {/snippet}\n                      </Button>\n                    {/if}\n                  </div>\n                {/if}\n              </CardContent>\n            </Card>\n          {/each}\n        </div>\n      </div>\n    {/each}\n  </div>\n</section>\n",
      "type": "registry:block",
      "target": "~/src/lib/components/blocks/team-section/TeamSection.svelte"
    },
    {
      "path": "packages/registry-svelte/blocks/team-section/page.svelte",
      "content": "<script lang=\"ts\">\n  // Demo page wired by `npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/team-section.json`.\n  // Visit /team-section-demo after install.\n  import TeamSection from '$lib/components/blocks/team-section/TeamSection.svelte'\n</script>\n\n<div class=\"bg-background min-h-svh\">\n  <header class=\"border-border border-b px-8 py-4\">\n    <h1 class=\"text-muted-foreground font-mono text-sm tracking-widest break-all uppercase\">team-section demo</h1>\n  </header>\n  <main class=\"p-8\">\n    <TeamSection />\n  </main>\n</div>\n",
      "type": "registry:block",
      "target": "~/src/routes/team-section-demo/+page.svelte"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/svelte/avatar.json",
    "https://uipkge.dev/r/svelte/badge.json",
    "https://uipkge.dev/r/svelte/button.json",
    "https://uipkge.dev/r/svelte/card.json"
  ],
  "description": "Centered marketing team section. Eyebrow + headline + lede over a responsive member card grid (initials avatar, role badge, one-line bio, ghost social buttons). Members with a department field group under uppercase headers; variant=\"compact\" drops bios for tighter cards. Roster is stub data — edit DEFAULT_MEMBERS or pass members.",
  "categories": [
    "marketing"
  ]
}