unparty-app UI Standards

Centralized reference for fonts, colors, layouts, and code snippets. Use this doc to build consistent UI fast.

See also: styling-project.md (Tailwind architecture), src/app/theunpartytemplate/STYLE.md (iOS design system)

---

Table of Contents

---

Brand Colors

Defined in src/app/constants/colors.ts.

Core Brand Palette

NameHexUsage
unparty#F9C22ESignature yellow — primary brand accent, interactive highlights
unpartyblack#000605Deep black — backgrounds, cards on dark
unpartywhite#FFF1D6Warm off-white — light surface backgrounds
champion#E7B12ESlightly darker yellow — secondary/hover state for brand yellow
nextyellow#E4C014Alternate yellow — active/pressed state

Extended Palette

NameHexCharacter
electricPurple#3500D3Vivid purple accent
healpurple#884455Muted rose-purple
starblack#753062Deep magenta-black
astroblack#3D2D59Indigo-black
pushblack#371B70Dark purple
unpartypurple#29284EMidnight purple
pinkyblack#6C6BB4Lavender-black
electricBlue#00FFFFCyan accent
electricGreen#00FF66Neon green accent
neonYellow#FFF700Pure neon yellow

Usage in Code

ts
// Import all colors
import { colors, palette } from '@/app/constants/colors';

// Inline style (dynamic theming)
<div style={{ color: colors.unparty }}>...</div>

// Dynamic theme color via hook
import { useTheme } from '@/app/contexts/ThemeContext';
const { colorValue } = useTheme();
<div style={{ color: colorValue }}>...</div>

---

CSS Design Tokens

Defined in src/app/globals.css as CSS custom properties.

Base Colors (Light / Dark)

css
/* Light mode */
--background:            #ededed;
--foreground:            #171717;
--background-highlight:  rgba(0, 0, 0, 0.1);
--text-muted:            rgba(23, 23, 23, 0.8);

/* Dark mode (auto-applied via @media prefers-color-scheme: dark) */
--background:            #0a0a0a;
--foreground:            #ededed;
--background-highlight:  rgba(255, 255, 255, 0.1);
--text-muted:            rgba(237, 237, 237, 0.8);

Tailwind aliases (configured in tailwind.config.ts):

tsx
// These resolve to the CSS variables above
className="bg-background text-foreground bg-background-highlight"

Depth / Shadow System

Use these to create visual hierarchy — prefer CSS vars over custom box-shadow values.

css
--depth-raised:   0 2px 4px rgba(0, 0, 0, 0.1);    /* Slightly lifted element */
--depth-elevated: 0 4px 8px rgba(0, 0, 0, 0.12);   /* Hover state / card */
--depth-floating: 0 6px 12px rgba(0, 0, 0, 0.15);  /* Sticky elements */
--depth-modal:    0 8px 16px rgba(0, 0, 0, 0.15);  /* Modals / drawers */
--depth-overlay:  0 12px 24px rgba(0, 0, 0, 0.18); /* Dropdowns / overlays */
tsx
// Usage example
<div style={{ boxShadow: 'var(--depth-elevated)' }}>...</div>

Brand Shadow & Glow

css
--brand-shadow:        0 2px 4px rgba(249, 194, 46, 0.1);
--brand-shadow-strong: 0 4px 8px rgba(249, 194, 46, 0.15);
--brand-glow:          0 0 8px rgba(249, 194, 46, 0.2);
--brand-glow-strong:   0 0 12px rgba(249, 194, 46, 0.25);
--brand-accent:        rgba(249, 194, 46, 0.1);
--brand-accent-strong: rgba(249, 194, 46, 0.15);

Interactive State Tokens

css
--focus-ring:        0 0 0 3px rgba(249, 194, 46, 0.3);
--hover-lift:        translateY(-1px);
--hover-lift-strong: translateY(-2px);
--active-press:      translateY(0) scale(0.98);

---

Font System

All fonts are configured in src/app/fonts.ts, tailwind.config.ts, and src/app/globals.css.

Available Font Families

Tailwind ClassFontCSS VariableCharacterWeights
font-monoSystem monospacebuilt-inCode, data, statsany
font-roundedNunito--font-nunitoFriendly, rounded200–900
font-brandon-grotesqueBrandon Grotesquelocal .otfPremium grotesque300–900
font-space-groteskSpace Grotesk--font-space-groteskModern editorial300–700
font-vt323VT323--font-vt323Retro terminal400
font-major-monoMajor Mono Display--font-major-monoDisplay mono400
font-geist-mono-googleGeist Mono--font-geist-mono-googleClean mono100–900
font-datatypeDatatypeGoogle Fonts @importTech / data100–900
font-flow-roundedFlow RoundedGoogle Fonts @importPlayful cursive400
font-google-sans-codeGoogle Sans CodeGoogle Fonts @importCode-focused300–800

Local fonts (loaded in src/app/layout.tsx): GeistVF.woff--font-geist-sans, GeistMonoVF.woff--font-geist-mono

Font Usage Examples

tsx
// Most common: monospace for data, stats, labels
<span className="font-mono text-sm">30+</span>

// Rounded / friendly headings
<h1 className="font-rounded text-2xl font-bold">UNPARTY</h1>

// Retro / editorial accent
<span className="font-vt323 text-4xl">STATUS: LIVE</span>

// Modern editorial
<p className="font-space-grotesk text-base font-medium">Description text</p>

---

Layout Patterns

Standard Page Container

The primary page pattern — used across most pages:

tsx
<div className="mx-auto w-full max-w-5xl">
  <div className="flex flex-col gap-6">
    {/* Page content here */}
  </div>
</div>

Page Container with Padding

For pages that need horizontal padding on smaller screens:

tsx
<div className="mx-auto w-full max-w-5xl px-4 sm:px-6">
  <div className="flex flex-col gap-6">
    {/* Page content here */}
  </div>
</div>

Full-Width Section with Centered Content

tsx
<main className="flex flex-col items-center gap-4 pt-2">
  <div className="w-full flex flex-col gap-4 px-2 md:gap-6">
    {/* Full-width content */}
  </div>
</main>

Max-Width Reference

ClassWidthBest For
max-w-sm24rem / 384pxCompact forms, small cards
max-w-md28rem / 448pxForms, modals
max-w-2xl42rem / 672pxNarrow content, small modals
max-w-3xl48rem / 768pxArticle text, narrow pages
max-w-4xl56rem / 896pxArticles, forms with sidebars
max-w-5xl64rem / 1024pxStandard page container (most common)
max-w-6xl72rem / 1152pxWide layouts
max-w-7xl80rem / 1280pxFull content wrapper inside root layout
max-w-screen-lgscreen widthOuter layout grid (root layout.tsx)

Two-Column Grid

tsx
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
  <div>Left</div>
  <div>Right</div>
</div>

Three-Column Grid (responsive)

tsx
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
  {items.map(item => <Card key={item.id} {...item} />)}
</div>

Card / Panel

tsx
<div className="rounded-xl bg-gray-50 p-6 dark:bg-black/10">
  {/* Card content */}
</div>

Card with Brand Glow

tsx
<div
  className="rounded-xl bg-gray-50 p-6 dark:bg-black/10"
  style={{ boxShadow: 'var(--brand-glow)' }}
>
  {/* Card content */}
</div>

---

Typography Utilities

Text Size Scale

ClassSizeCommon Use
text-xs0.75remLabels, metadata, timestamps
text-sm0.875remSecondary text, captions
text-base1remBody text
text-lg1.125remSlightly larger body
text-xl1.25remSmall headings
text-2xl1.5remSection headings
text-3xl1.875remPage headings
text-4xl2.25remHero / large headings
text-6xl3.75remDisplay / oversized headings

Common Text Patterns

tsx
// Section label / category tag
<span className="font-mono text-xs font-bold uppercase tracking-wider opacity-60">
  CATEGORY
</span>

// Stat / number
<div className="font-mono text-lg font-bold" style={{ color: colorValue }}>
  42+
</div>

// Body paragraph
<p className="text-sm leading-relaxed opacity-80">
  Description text goes here.
</p>

// Prominent heading
<h2 className="font-rounded text-2xl font-bold">
  Section Title
</h2>

// Brand-colored inline highlight
<span className="font-bold" style={{ color: colors.unparty }}>
  highlighted term
</span>

// Keyword term (uses .keyword-term CSS class from globals.css)
<span className="keyword-term">clickable term</span>

---

Component Snippets

Scroll Row Section

Used to display a horizontally scrolling row with a title and optional "more" link:

tsx
import ScrollRow from '@/components/HorizontalRow';
import PageAsterisk from '@/app/components/PageAsterick';

<ScrollRow
  title="SECTION TITLE"
  items={[
    <PageAsterisk key="asterisk" />,
    // Add components here
  ]}
  moreLink="/more"
  maxItems={4}
/>

Stats Component

tsx
import Stats from '@/app/components/Stats';

// Default values
<Stats />

// Custom values
<Stats waitlistCount={275} vibeMood="HIGH." priorityCategory="HIGH" className="shadow-lg" />

Page with Standard Layout (full example)

tsx
import AboutComponent from '@/app/components/AboutComponent';

export default function MyPage() {
  return (
    <main className="flex flex-col items-center gap-4 pt-2">
      <div className="mx-auto w-full max-w-5xl">
        <div className="flex flex-col gap-6">
          <AboutComponent />
        </div>
      </div>
    </main>
  );
}

Theme-Colored Element

tsx
'use client';
import { useTheme } from '@/app/contexts/ThemeContext';

export default function MyComponent() {
  const { colorValue } = useTheme();
  return (
    <div style={{ borderColor: colorValue, color: colorValue }}>
      Dynamic themed content
    </div>
  );
}

Responsive Section with Gap Scaling

tsx
<section className="flex flex-col gap-4 md:gap-6 lg:gap-8">
  {/* Content */}
</section>

---

Animation & Transitions

Transition Speed Tokens

css
--transition-fast:     0.15s ease;   /* Button hover, micro-interactions */
--transition-standard: 0.2s ease;    /* Most interactive states */
--transition-slow:     0.3s ease;    /* Page transitions, modals */

Custom Easing

css
--easing-brand:  cubic-bezier(0.25, 0.46, 0.45, 0.94);  /* Smooth brand motion */
--easing-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55); /* Playful bounce */

CSS Utility Classes (from globals.css)

tsx
// Scrolling banner / chyron
<div className="animate-scroll">
  Scrolling text content
</div>

// Page enter animation (auto-applied inside .page-transition-wrapper)
<div className="page-transition-wrapper">
  {children}
</div>

Standard Hover Pattern (Tailwind)

tsx
// Lift on hover, press on active
<button className="transition-transform duration-150 hover:-translate-y-0.5 active:scale-[0.98]">
  Click me
</button>

---

Dark Mode

The app uses @media (prefers-color-scheme: dark) for automatic dark mode. All CSS variable tokens update automatically.

Patterns

tsx
// Background: light gray / near-black
<div className="bg-background">...</div>

// Text: dark / light
<p className="text-foreground">...</p>

// Overlay / tinted background
<div className="bg-background-highlight">...</div>

// Manual dark variant via Tailwind
<div className="bg-gray-50 dark:bg-black/10">...</div>
<p className="text-gray-900 dark:text-gray-100">...</p>

---

Theme System (Dynamic Colors)

The app includes a runtime color theme system that lets users (or pages) switch the primary accent color.

Using the Theme

tsx
'use client';
import { useTheme } from '@/app/contexts/ThemeContext';

export default function ThemedCard() {
  const { colorValue, colorPalette, selectedColor, setSelectedColor } = useTheme();

  return (
    <div style={{ borderLeft: `4px solid ${colorValue}` }}>
      <p style={{ color: colorValue }}>Themed accent text</p>
    </div>
  );
}

Available Theme Colors (palette)

ts
// src/app/constants/colors.ts
export const palette = {
  unparty:       "#F9C22E",  // Signature yellow (default)
  unpartyblack:  "#000605",
  unpartywhite:  "#FFF1D6",
  electricPurple:"#3500D3",
  neonYellow:    "#FFF700",
  astroblack:    "#3D2D59",
  pinkyblack:    "#6C6BB4",
  starblack:     "#753062",
  pushblack:     "#371B70",
  champion:      "#E7B12E",
  healpurple:    "#884455",
  electricGreen: "#00FF66",
  electricBlue:  "#00FFFF",
  anotherlove:   "#000108",
};

Theme Persistence

The selected theme color is persisted to localStorage under the key unpartySelectedColor automatically.

---

Last updated: 2025-03-21 — See styling-project.md for Tailwind architecture details and src/app/theunpartytemplate/STYLE.md for the iOS design system.

#ui#standards#design-system#brand

🧗🏾‍♂️ in progress

THOUGHTS.