mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 09:19:51 +00:00
Introduce a light/dark MODE axis orthogonal to the existing accent themes. Neutral surface tokens now live in html[data-mode="light|dark"] blocks; accent tokens (--primary*, --ring, --chart-1, --sidebar-primary*) stay in html[data-theme] blocks, so any accent works in either mode. - globals.css: split neutrals (mode) from accent (theme); add light palette; dark values unchanged (dark stays the default). - lib/themes.ts: Mode type, DEFAULT_MODE=dark, MODE_STORAGE_KEY, isMode. - use-theme.tsx: provider owns mode/setMode/toggleMode + cross-tab sync. - layout.tsx: boot script applies persisted mode before first paint (no flash); colorScheme "dark light". - mode-toggle.tsx (header sun/moon) + themed-toaster.tsx (mode-aware). - appearance-panel.tsx: light/dark control + updated copy. - Tokenize hardcoded neutral colors (slate/white/gray) -> semantic tokens across the app so every surface flips with mode. Flow canvas and message-bubble timestamps made mode-aware too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
45 lines
1.9 KiB
TypeScript
45 lines
1.9 KiB
TypeScript
// ============================================================
|
|
// /join/[token] layout — minimal full-bleed dark shell.
|
|
//
|
|
// The route group sits outside both `(auth)` and `(dashboard)`
|
|
// because it's hybrid: the page must render for anonymous
|
|
// visitors (to show "Sign up to join Acme") *and* for signed-in
|
|
// users (to show "Accept invite"). Reusing `(auth)`'s layout
|
|
// would funnel signed-in users through the middleware's auth-
|
|
// page redirect; reusing `(dashboard)` would funnel anonymous
|
|
// visitors through its login redirect. A dedicated layout
|
|
// avoids both.
|
|
//
|
|
// Styling matches the login / signup pages — centered card on a
|
|
// slate-950 background — so the join experience feels like a
|
|
// natural step in the auth funnel rather than a foreign page.
|
|
//
|
|
// Referrer-Policy: no-referrer
|
|
// The plaintext invite token lives in the URL path. Without
|
|
// this header, any externally-loaded resource (third-party
|
|
// font, CDN script, image) would receive the full join URL in
|
|
// its `Referer` header. The /join page doesn't currently load
|
|
// anything external, but `Referrer-Policy: no-referrer` is a
|
|
// cheap belt-and-braces guard against future regressions
|
|
// accidentally leaking tokens. Per Next.js 16's `metadata`
|
|
// export, this surfaces as `<meta name="referrer" content="no-referrer">`.
|
|
// ============================================================
|
|
|
|
import type { Metadata } from 'next';
|
|
import type { ReactNode } from 'react';
|
|
|
|
export const metadata: Metadata = {
|
|
referrer: 'no-referrer',
|
|
// Belt-and-braces against an invite URL ending up in search
|
|
// results if a join page is ever crawled.
|
|
robots: { index: false, follow: false },
|
|
};
|
|
|
|
export default function JoinLayout({ children }: { children: ReactNode }) {
|
|
return (
|
|
<div className="flex min-h-screen items-center justify-center bg-background px-4">
|
|
{children}
|
|
</div>
|
|
);
|
|
}
|