Skip to content

feat(playground): formatter pages, Intl explorer, Settings, 404 (follow-up to #2084)#2337

Draft
Adebesin-Cell wants to merge 61 commits into
amannn:mainfrom
Adebesin-Cell:docs/playground-extras
Draft

feat(playground): formatter pages, Intl explorer, Settings, 404 (follow-up to #2084)#2337
Adebesin-Cell wants to merge 61 commits into
amannn:mainfrom
Adebesin-Cell:docs/playground-extras

Conversation

@Adebesin-Cell

@Adebesin-Cell Adebesin-Cell commented May 25, 2026

Copy link
Copy Markdown

Draft follow-up to #2084.

What's here:

  • Formatting → Dates, Numbers, Explorer (useFormatter playground covering all 5 methods + named formats + Code Hike snippet)
  • Routing → Mixed routing
  • Patterns → Locale switcher, Browser language, Cache components (placeholder)
  • Settings dialog — reduce motion, announce output, accent color
  • Localized /not-found with a tiny useFormatter/useTranslations playground
  • Root-layout refactor so the 404 renders
  • a11y pass (aria-pressed, aria-live, aria-current)

amannn and others added 30 commits August 29, 2025 13:48
…hadcn UI, a11y

New pages (each following the Demo MDX + dotgrid Output pattern, all using next-intl APIs only — never raw Intl.*):

- /[locale]/formatting/dates — useFormatter + useNow with dateStyle/timeStyle controls
- /[locale]/formatting/numbers — format.number with style/currency controls
- /[locale]/formatting/explorer — full useFormatter explorer covering all 5 methods (number, dateTime, dateTimeRange, relativeTime, list) with options grid, per-locale preview (each cell wrapped in NextIntlClientProvider), inline-vs-named-format toggle, generated next-intl snippet panel rendered via Code Hike, copy button with clearTimeout
- /[locale]/routing/mixed-routing — table comparing localePrefix: always | as-needed | never for the active locale
- /[locale]/patterns/locale-switcher — typed Link from @/i18n/navigation with locale prop, wrapped in Button asChild variant="outline"

Named formats registry:
- New src/i18n/formats.ts registers number (precise, currency, percent), dateTime (short, long, shortTime), list (or, and)
- Wired into getRequestConfig + NextIntlClientProvider

UI migration to shadcn/ui:
- Installed shadcn select, input, checkbox, label, tabs (used as primitives across Dates, Numbers, Explorer, Locale switcher)
- New CodeBlock client component uses codehike highlight() so the Explorer's generated snippet gets the same syntax theme as MDX code blocks

Landing & layout polish:
- Fix empty-cell skeleton on landing when a category has a single item (grid drops to 1 col)
- Bigger card padding (px-6 py-5) and softer hover bg-card/40 so the hover state breathes inside the EXAMPLES boundary
- Output sections across all demo pages: result is the hero (3xl/4xl tabular-nums), controls in a compact pill row underneath

Accessibility:
- aria-label + aria-expanded + aria-controls on the mobile menu toggle
- aria-label on the header locale switcher trigger ("Language: …. Change language."), aria-current on the active menu item
- Theme toggle aria-label announces the destination state
- Explorer chips use aria-pressed; locale picker has role="group" with an aria-label
- Explorer Output section is aria-labelledby its h2, with aria-live="polite" + aria-atomic="true" so screen readers announce format changes
…nouncements, accent palette

New gear button in the sidebar header opens a shadcn Dialog with three preferences persisted to localStorage:

- Reduce motion: nukes transitions/animations across the playground via [data-reduce-motion="true"] on <html>. Independent of the system prefers-reduced-motion: reduce media query (also honoured separately), so users can opt in or out explicitly.
- Announce output to screen readers: toggles the Explorer Output panel's aria-live between "polite" and "off" for users who find live announcements noisy.
- Accent color: blue (default), teal, violet, amber — driven by [data-accent] on <html> overriding --primary / --ring / --sidebar-primary / --sidebar-ring in globals.css. Flows through every shadcn primitive automatically.

Infrastructure:
- New src/lib/settings.tsx Context provider, hydrates from localStorage on mount, writes through on change, applies dataset attributes to <html>
- src/components/playground/settings-dialog.tsx renders the Dialog with proper role="radiogroup"/aria-checked on the accent picker, aria-labelled Switches, focus trap from Radix Dialog
- Installed shadcn dialog + switch primitives
… markers, ghost-button hover

The accent palette setting was only flipping a handful of obscure surfaces. Brand and hover surfaces stayed hardcoded so the chosen accent was invisible on most pages. Fixed by routing the standard shadcn tokens (--primary, --accent, --sidebar-primary, --sidebar-accent, --ring) per palette and dropping the hardcoded color refs:

- Logo: text-blue-700 dark:text-blue-300 → text-primary
- Sidebar active nav item: text-foreground → text-primary; left indicator bg-foreground → bg-primary
- MDX bullet markers (.mdx-content li::marker): hardcoded --blue-300 → --primary
- globals.css per-accent block now also overrides --accent and --sidebar-accent so dropdown menu items, ghost-button hover, and other shadcn surfaces that key off --accent (not --primary) follow the palette too
- ThemeToggle + SettingsDialog: removed the explicit hover:bg-transparent / focus:ring-0 overrides that were nuking the shared ghost-button hover state — they now show the accent tint on hover in both themes
…attributes

Switch the locale-switcher demo, Explorer chips, Explorer option cards, and the Explorer Options grid disabled state from template-literal conditional classNames to constant classNames keyed off data-* attributes:

- locale-switcher-example: data-active on each locale Button → CSS via data-[active]: modifiers
- PickerChip: data-active replaces the active ternary
- OptToggle: data-checked on the card and data-disabled on the inner control wrapper
- Options grid: data-disabled on the grid container

Constant className strings: no per-render concatenation, no allocation; React diffs a single data-* attribute when state flips. Also aligns with the shadcn/Radix data-state convention.
…calized 404, root-level shell

New pages:
- /[locale]/patterns/browser-language — server component reads Accept-Language via next/headers, parses q-values, matches against routing.locales (exact → language-only → fallback), renders the chain and the resolved locale
- /[locale]/patterns/cache-components — coming-soon placeholder describing what the page will demo ('use cache' on getTranslations, cacheLife profiles, cacheTag for surgical revalidation)
- /not-found — fun localized 404 with a "while you're here" mini-playground (live name + score formatted via useFormatter/useTranslations) and quick-jump suggestions

Layout / routing refactor:
- Move <html>/<body>, fonts, NextIntlClientProvider, and ClientProviders up to app/layout.tsx using getLocale/getMessages so root-level not-found can render correctly (previously broke with "Missing root layout tags")
- Extract PlaygroundShell (sidebar + content frame) and reuse it from [locale]/layout.tsx and the root not-found
- localePrefix: 'as-needed' so the default locale (en) is unprefixed

Nav i18n:
- NavItem/NavSection types switch from hardcoded title/description strings to titleKey/descriptionKey translation keys, plus a comingSoon boolean
- Sidebar, landing page, and not-found resolve all titles/descriptions via the Nav.* messages namespace
- "soon" badge is localized; new sections + items pick up translations in en + de

Other:
- New CacheComponents.* messages namespace; NotFound.* messages already present picked up via root not-found
@vercel

vercel Bot commented May 25, 2026

Copy link
Copy Markdown

@Adebesin-Cell is attempting to deploy a commit to the next-intl Team on Vercel.

A member of the Team first needs to authorize it.

@Adebesin-Cell Adebesin-Cell changed the base branch from main to docs/refactor-playground May 25, 2026 20:18
@Adebesin-Cell Adebesin-Cell changed the base branch from docs/refactor-playground to main May 25, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants