Standards

    Success stories pattern

    Narrative/story-first pattern for happy tails and adopted-pet outcomes — full context and CTA on a dedicated stories page, or a compact card grid for a home-page preview.

    Example

    Recent happy tails

    Tan rescue dog resting comfortably after adoption
    Forever Loved

    Remi's Journey

    Dog • Mixed Breed

    From abandoned stray to forever loved family member.

    Remi arrived underweight and fearful, then stabilized in foster care before adoption.

    After intake, Remi received veterinary care, nutrition support, and confidence-building routines.

    Once matched with an adopter, the transition plan focused on structure, decompression, and ongoing support.

    Adopted: 2025-10-12

    Smiling black rescue dog outdoors
    Adopted

    Nova

    Dog • Labrador Mix

    Medical recovery followed by a successful family placement.

    Nova needed post-op foster support and a low-stress home match.

    Adopted: 2025-08-03

    Small rescue dog with pink harness
    Happy Tail

    Peaches

    Dog • Terrier Mix

    Shy intake that became a confident companion at home.

    Peaches needed a quieter placement and did well with slow introductions and consistency.

    Adopted: 2025-06-21

    Compact variant (home-page preview)

    Same stories data, with context/content/CTAs turned off and maxItems capping the grid — the settings a home page uses instead of a separate card component.

    Tan rescue dog resting comfortably after adoption
    Forever Loved

    Remi's Journey

    Dog • Mixed Breed

    From abandoned stray to forever loved family member.

    Adopted: 2025-10-12

    Smiling black rescue dog outdoors
    Adopted

    Nova

    Dog • Labrador Mix

    Medical recovery followed by a successful family placement.

    Adopted: 2025-08-03

    Splitting by status (e.g. available vs. adopted)

    A site-owned status field — not part of SuccessStoryItem — decides which bucket a story falls into. Call this component twice with two filtered arrays instead of rendering one mixed grid. Buddy's card below also shows ctaLinks: an available dog can carry a direct "Apply to Adopt" button, not just a link through to the full story.

    Available Now

    Energetic tan and white dog mid-run in a grassy park
    Available Now

    Buddy

    Dog • Terrier Mix

    High-energy and people-focused — does best with an active family and a fenced yard.

    Happy Tails

    Tan rescue dog resting comfortably after adoption
    Forever Loved

    Remi's Journey

    Dog • Mixed Breed

    From abandoned stray to forever loved family member.

    Adopted: 2025-10-12

    Smiling black rescue dog outdoors
    Adopted

    Nova

    Dog • Labrador Mix

    Medical recovery followed by a successful family placement.

    Adopted: 2025-08-03

    Small rescue dog with pink harness
    Happy Tail

    Peaches

    Dog • Terrier Mix

    Shy intake that became a confident companion at home.

    Adopted: 2025-06-21

    Auto-rotating teaser (home-page carousel)

    Built directly on components/ui/carousel.tsx's autoPlay prop, not a mode on this component — pauses on hover/focus and respects prefers-reduced-motion. Hover to pause, or use the arrows.

    Tan rescue dog resting comfortably after adoption
    Forever Loved

    Remi

    Smiling black rescue dog outdoors
    Adopted

    Nova

    Small rescue dog with pink harness
    Happy Tail

    Peaches

    Energetic tan and white dog mid-run in a grassy park
    Available Now

    Buddy

    Idea: badge-driven detail-page CTAs (illustrative, not governance)

    Seen on a real rescue-client site: instead of free-text badge labels, give each story a badge key into a small dictionary — the same dictionary then decides which CTA button(s) that dog's own detail page shows, in order. No fragile string-matching on translated badge text, and no component change: this lives entirely in a site's own data/page files. Not a standardized part of SuccessStoriesSection — just a pattern worth reusing if it fits.

    type StoryCtaAction = "adopt" | "foster" | "volunteer" | "contact" | "donate";
    
    const STORY_STATUS_BADGES = {
      availableForAdoption: {
        label: { en: "Available for Adoption", es: "Disponible para Adopción" },
        ctaActions: ["adopt"],
      },
      needsFosterHome: {
        label: { en: "Needs a Foster Home", es: "Necesita un Hogar de Acogida" },
        ctaActions: ["foster"],
      },
      inFosterCare: {
        label: { en: "In Foster Care", es: "En Hogar de Acogida" },
        // Already has a foster — point people at other ways to help instead.
        ctaActions: ["contact", "foster", "volunteer"],
      },
      adopted: {
        label: { en: "Found Their Forever Home", es: "Encontró Su Hogar Para Siempre" },
        // Ask shifts from "help this one" to "help the next one".
        ctaActions: ["adopt", "donate", "volunteer"],
      },
    } satisfies Record<string, { label: LocalizedText; ctaActions?: StoryCtaAction[] }>;
    
    // Detail page: look up STORY_STATUS_BADGES[story.badge] once — same object drives
    // both the badge pill text and which CTA button(s) to render, in order.

    Standard

    - Use `SuccessStoriesSection` for adoption outcomes and happy-tail story collections.

    - Store stories as normalized `SuccessStoryItem` objects and pass them through `stories`.

    - Use module toggles (`showSummary`, `showStoryContext`, `showStoryContent`, `showStoryCtas`) instead of page-local branching.

    - For home-page previews, use compact settings (`maxItems`, `columns`, and content toggles) rather than a separate card implementation — see the variant above.

    - Cards are no-JS readable; the portrait image and the optional story link (`storyHref`) both render as plain anchors — internal routes use `Link`, external URLs get `target="_blank" rel="noreferrer"`.

    - `contentWidth="contained"` narrows the section to a centered column; default is `"full"` width.

    - `labels` overrides section copy (`adoptedLabel`, `readStoryLabel`, `adoptedPrefix`) for i18n/site customization.

    - `ctaLinks` (optional, on `SuccessStoryItem`) renders extra button(s) before the "read story" link — e.g. a badge-driven "Apply to Adopt"/"Apply to Foster" so an index card can offer the actual next step, not just a link through to the detail page. See Buddy's card in the "splitting by status" example above. Piloted on `the-comeback-pack`'s `/pack-journeys` index.

    - Composing a rescue-journeys page: pair this with `JourneyTimeline` (see that pattern's page) and a site-owned `status` field (e.g. `"in_care" | "adopted"`) on your own story type — call this component twice with two filtered arrays for an in-care/adopted split, and derive impact-stat counts from the same field. No component change needed; `status` lives on your site's own extended type. See the live "splitting by status" example above; piloted on `the-comeback-pack`'s `/pack-journeys`.

    - A home-page teaser that needs to auto-rotate once it outgrows one row: build it from `components/ui/carousel.tsx`'s `autoPlay` prop directly rather than adding a carousel mode here — keeps this component's grid simple and the rotation behavior reusable outside this pattern too. See the live "auto-rotating teaser" example above, or `the-comeback-pack`'s real homepage teaser.

    - Component: `template/src/components/patterns/SuccessStoriesSection.tsx`