Skip to content

UI Design System

Luara edited this page Jul 5, 2026 · 2 revisions

UI Design System

Color values confirmed against app/globals.css at time of writing.

Overview

Felines uses an editorial design system with alternating light and dark sections, Inter typography, a palette derived from the logo cat, and subtle animations that make the product feel alive without being distracting.


Color Tokens

See Visual Identity for the full palette table — implemented as CSS custom properties in app/globals.css's @theme block (Tailwind v4, no JS config file).


Components

Buttons

Variant Background Text Border Use
Primary #B66119 #FFFFFF Main action
Secondary transparent #B66119 1.5px #B66119 Secondary action
Ghost transparent #6B6B6B 1px #E8E4DF Tertiary actions
Danger #C0392B #FFFFFF Destructive actions
White #FFFFFF #2D1810 On dark sections

Border radius 10px, padding 12px 24px, hover translateY(-1px) + subtle shadow, press scale(0.97).

Cards

Background #FFFFFF, 1px #E8E4DF border, 16px radius, 24px padding, 0 2px 8px rgba(0,0,0,0.05) shadow. Hover: translateY(-3px) + larger shadow.

Inputs

48px height, 1px #E8E4DF border, 8px radius. Focus: border #B66119, 2px rgba(182,97,25,0.2) outline.

Badges

Pill shape (20px radius), 4px 12px padding, 12px semibold. Neutered: golden bg. Verified: success bg. Read: neutral bg. Emergency: emergency bg/white text.

Modals

rgba(0,0,0,0.5) backdrop with 4px blur, 20px radius container, 32px padding, max-width 560px, slide-up animation (250ms cubic-bezier(0.16, 1, 0.3, 1)). Focus is trapped and Escape closes — implemented via a shared hook reused across all modals after 15 were found missing it during the WCAG audit.

Tabs

Active: 2px #B66119 underline, #B66119 text. Inactive: #6B6B6B text. The underline slides horizontally between tabs (200ms ease).


Animations

All respect prefers-reduced-motion.

Page load fade-up: staggered — hero 0ms, subheadline 100ms, CTAs 200ms.

Scroll reveal: Intersection Observer (not a scroll listener), fade + translateY(16px→0), 400ms ease-out, 80ms stagger between items.

Count-up: numbers on /impact and home count from 0 to their final value via requestAnimationFrame, 800ms ease-out, triggered by Intersection Observer.

Map pin hover: spring scale 1→1.3x with overshoot, cubic-bezier(0.34, 1.56, 0.64, 1). Emergency pins pulse with a 2s infinite ripple.

Skeletons: shimmer keyframe animation for loading states.


Layout

Grid: desktop max-width 1200px with 48px horizontal padding; mobile 20px horizontal padding. Sections use 80px vertical padding (desktop), 60px (mobile).

Visual rhythm: alternating light/dark sections create editorial pacing — hero (light) → stats strip (dark) → entry cards (light) → cat assistant video (light) → quick facts (dark) → final CTA (light).


Accessibility (WCAG 2.2)

Criterion Implementation
Normal text contrast Minimum 4.5:1 — verified and corrected (a success-state color was 3.3:1)
Large text contrast Minimum 3:1 — verified
Focus ring 2px #B66119 (light backgrounds), 2px #F2AE72 (dark backgrounds)
Modal focus trap Shared hook — 15 modals fixed
ARIA roles Tabs, modals, progress bars, dropdowns
aria-live Notifications, confirmations, report counters
Alt text All colony and cat images
Labels Every input has a real <label>, not just a placeholder (2 forms fixed)
Touch targets Minimum 44×44px on every interactive element
lang attribute Updated dynamically with the PT/EN toggle
Reduced motion All animations disabled via media query

UI Principles

  1. No purely decorative elements — everything exists for a functional reason
  2. Empty states as an invitation — never an error, always with a CTA
  3. Hierarchy through size, not color — structure stays clear without depending on color alone
  4. Immediate feedback — every action gets a visual response in under 200ms
  5. Mobile first — every component is designed for 375px before desktop

Clone this wiki locally