Theme the sign-in UI
Synq’s default <SignIn> and <SignInSheet> are designed to look
correct in 90% of apps with zero customization — but you almost
certainly want them to look like your app, not Synq’s. This guide
walks through the four levels of theming from least to most invasive.
Stop at the first one that gets you what you want.
Works the same way across
@synqid/react,@synqid/nextjs, and@synqid/react-native. The token names are identical; the values are CSS strings on web and native numbers/strings on RN.
Level 0 — pick a preset (10 seconds)
Five built-in presets cover the most common visual languages.
<SynqProvider {...config} theme="dark" /> // default
<SynqProvider {...config} theme="light" />
<SynqProvider {...config} theme="glass" /> // dark + heavy blur
<SynqProvider {...config} theme="monochrome" /> // grayscale
<SynqProvider {...config} theme="brutalist" /> // hard edges, yellowOn @synqid/react-native, the prop is uiTheme with the same value
shape.
Level 1 — pick a preset and tweak (30 seconds)
Layer overrides on top of a preset. Anything you do not set keeps the preset’s value.
<SynqProvider
{...config}
theme={{
preset: 'light',
primary: '#FF7B56',
primaryHover: '#E85A2D',
radius: '14px', // sugar — sets all radius* scales
fontFamilyDisplay: '"Cal Sans", system-ui',
}}
/>The full token set for fine-grained control:
| Group | Tokens |
|---|---|
| Colors | primary, primaryForeground, primaryHover, surface, surfaceElevated, border, borderHover, textPrimary, textMuted, textOnPrimary, danger, success, warning, backdrop |
| Typography | fontFamily, fontFamilyDisplay, fontFamilyMono, fontWeightHeadline, fontWeightButton |
| Spacing | spacingXs, spacingSm, spacingMd, spacingLg, spacingXl |
| Radii | radiusSm, radiusMd, radiusLg, radiusFull, radius (sugar) |
| Effects (web only) | shadowSm, shadowMd, shadowLg, glow, backdropBlur |
| Motion (web only) | durationFast, durationBase, easingStandard |
The RN-native token set is identical minus the web-only Effects and
Motion groups, and adds sheetHandle (the bottom-sheet drag bar
color).
Level 2 — light + dark with system follow
When your app has its own dark/light toggle, hand Synq both branches
and a colorScheme strategy. system follows the OS preference and
re-renders on change.
<SynqProvider
{...config}
colorScheme="system" // 'light' | 'dark' | 'system'
theme={{
light: { preset: 'light', primary: '#0A6E5E' },
dark: { preset: 'dark', primary: '#5FD8CA' },
}}
/>colorScheme="system" watches prefers-color-scheme on web and
useColorScheme() on RN — no extra wiring.
Level 3 — provider icons + slot-level classNames
Rebrand the provider buttons or hit specific slots without dropping into compound parts.
import { GoogleMark, AppleMark } from '@/components/brand-icons'
<SynqProvider
{...config}
providerIcons={{
google: <GoogleMark className="size-5" />, // React component
apple: 'https://cdn.acme.com/apple.svg', // URL → <img>
matrica: '<svg viewBox="0 0 24 24">…</svg>', // inline SVG (web only)
}}
signInClassNames={{
content: 'rounded-3xl bg-zinc-950/95 backdrop-blur-xl',
title: 'font-display text-2xl',
provider: 'rounded-xl ring-1 ring-zinc-800 hover:ring-zinc-600',
walletButton: 'rounded-xl bg-purple-600 hover:bg-purple-500',
}}
/>Web slot names: backdrop, content, header, logo, title,
description, closeButton, providerList, provider,
providerIcon, providerLabel, emailInput, otpInput,
walletButton, divider, errorBanner, loadingOverlay, terms,
footer. The connectClassNames prop targets the wallet-only
<Connect> modal with its own slot set.
On RN, use signInSheetStyles / connectSheetStyles with object
styles instead of classNames — slots are background, handle,
container, title, providerButton, providerButtonText,
walletButton, walletButtonText.
Level 4 — compound parts or render-prop (your markup)
When nothing above is enough, drop into the compound API or fully headless render-prop. You bring the JSX; Synq brings the auth behavior. See the @synqid/react or @synqid/react-native compound section.
Recipes
Match Tailwind’s design system
Wire --synq-* CSS variables to your tokens once and the modal
inherits everything else from Tailwind utilities.
.synq-modal {
--synq-primary: theme('colors.brand.500');
--synq-primary-foreground: theme('colors.white');
--synq-surface: theme('colors.zinc.950');
--synq-text-primary: theme('colors.zinc.100');
--synq-radius-lg: theme('borderRadius.2xl');
}Custom font in 3 lines
<SynqProvider
{...config}
theme={{
fontFamilyDisplay: '"Cal Sans", system-ui',
fontFamily: '"Inter", system-ui',
}}
/>The display font is used on the modal title; the body font on everything else.
Disable the glow + backdrop blur
Some apps look better without the brand glow behind the modal or the backdrop blur (cheap on desktop, expensive on older mobile GPUs).
<SynqProvider
{...config}
theme={{ preset: 'dark', glow: 'none', backdropBlur: '0' }}
/>Per-route theme override
Nest a second <SynqProvider> underneath the root with a different
theme to override per route. The auth state is shared — only the
visual tokens differ.
<SynqProvider {...config} theme="dark">
<App />
<Route path="/checkout">
<SynqProvider {...config} theme={{ preset: 'light', primary: '#000' }}>
<Checkout />
</SynqProvider>
</Route>
</SynqProvider>What to read next
- @synqid/react — full theming + compound + render-prop reference
- @synqid/react-native — RN-shaped equivalent
- Concepts → orgs and brands — how brand-level theming flows from the Dashboard