From aee36ff0aacfd3da0b07be857b2138c584f8d644 Mon Sep 17 00:00:00 2001 From: Brandon Corbett Date: Mon, 17 Aug 2026 23:49:35 -0400 Subject: [PATCH] feat(styles): make the built-in auth UI themeable with CSS custom properties Every colour in the bundled screens now reads from a --seamless-* custom property with the previous literal as its fallback. Consumers can match the auth UI to their brand by setting variables on :root or on any ancestor of AuthRoutes, with no provider prop and no JavaScript surface. The 118 hardcoded literals collapse onto 16 semantic tokens: four accent tokens, three surface tokens, four neutral tokens, three status tokens, and two effect tokens (overlay and shadow). Near-duplicate shades share a token while each declaration keeps its own original value as the fallback, so a single override unifies the role without shifting the defaults. Four values stay hardcoded. The magic-link pulse ring and the success check disc are translucent tints sitting under an icon, so an override that drops the alpha would paint an opaque disc over the icon it frames. The three transparent keywords are intentionally invisible rather than themeable. This is opt-in and non-breaking. Stripping the var() wrappers from the new files yields output byte-identical to the previous version, so applications that set nothing render exactly as before. --- .changeset/themeable-auth-ui.md | 11 +++++ README.md | 63 +++++++++++++++++++++++++++ src/styles/deviceNameModal.module.css | 18 ++++---- src/styles/login.module.css | 62 +++++++++++++------------- src/styles/magiclink.module.css | 26 +++++------ src/styles/mfaLogin.module.css | 44 +++++++++---------- src/styles/otpInput.module.css | 10 ++--- src/styles/passKeyLogin.module.css | 16 +++---- src/styles/registerPasskey.module.css | 34 +++++++-------- src/styles/termsModal.module.css | 18 ++++---- src/styles/verifyMagiclink.module.css | 16 +++---- src/styles/verifyOTP.module.css | 38 ++++++++-------- 12 files changed, 215 insertions(+), 141 deletions(-) create mode 100644 .changeset/themeable-auth-ui.md diff --git a/.changeset/themeable-auth-ui.md b/.changeset/themeable-auth-ui.md new file mode 100644 index 0000000..ab3111c --- /dev/null +++ b/.changeset/themeable-auth-ui.md @@ -0,0 +1,11 @@ +--- +'@seamless-auth/react': minor +--- + +feat(styles): make the built-in auth UI themeable with CSS custom properties + +Every colour in the bundled screens now reads from a `--seamless-*` custom property with the previous +literal as its fallback, so consumers can match the auth UI to their brand by setting variables on +`:root` or on any ancestor of ``. + +This is opt-in and non-breaking. Applications that set nothing render exactly as before. diff --git a/README.md b/README.md index 9f69ce3..d5a510b 100644 --- a/README.md +++ b/README.md @@ -849,6 +849,69 @@ Two paths are unchanged because they are owned by contracts outside this package - `/oauth/callback` is registered with OAuth providers as an allowed redirect URI, so renaming it would break configured integrations. +## Theming The Built-In UI + +Every colour in the built-in screens is a CSS custom property with a fallback, so the default look is +unchanged if you set nothing. To match your brand, set the tokens you care about on `:root`, or on any +element that wraps ``. + +```css +:root { + --seamless-accent: #1f3a34; + --seamless-accent-hover: #16302b; + --seamless-surface: #f7f5f0; + --seamless-text: #1a1a1a; +} +``` + +Scoping to a wrapper also works, which is useful when the auth screens should look different from the +rest of the app: + +```css +.auth-shell { + --seamless-accent: #1f3a34; + --seamless-accent-soft: #3c6f63; +} +``` + +There is no provider prop or JavaScript API for this. Setting the variables is the whole interface. + +### Tokens + +| Token | Used for | Default | +| ---------------------------- | ---------------------------------------------------------------------- | --------------------------------------------- | +| `--seamless-accent` | Primary buttons, focus rings, selected states, accent borders, spinner | `#2563eb` fills, `#3b82f6` rings and borders | +| `--seamless-accent-hover` | Hover state of primary buttons | `#1d4ed8` | +| `--seamless-accent-contrast` | Label text on accent-filled buttons | `white` | +| `--seamless-accent-soft` | Links, toggle buttons, accent icons | `#60a5fa`, `#a5b4fc` on the magic-link screen | +| `--seamless-surface` | Card and modal backgrounds | `#1f2937` | +| `--seamless-surface-raised` | Inputs and panels sitting on a card | `#374151`, `#4b5563` on the login form | +| `--seamless-surface-hover` | Hover state of secondary buttons | `#4b5563` | +| `--seamless-border` | Input, button, and panel borders | `#4b5563`, `#d1d5db` | +| `--seamless-text` | Headings and body text | `white` | +| `--seamless-text-muted` | Labels, helper text, secondary copy | `#9ca3af`, `#d1d5db` | +| `--seamless-disabled` | Background of disabled submit buttons | `#9ca3af` | +| `--seamless-danger` | Error messages | `#f87171` | +| `--seamless-success` | Success messages and the verified check icon | `#34d399` | +| `--seamless-warning` | OTP countdown and resend timers | `#facc15` | +| `--seamless-overlay` | Modal backdrop scrim | `rgba(0, 0, 0, 0.45)` | +| `--seamless-shadow` | Card and modal shadow colour | `rgba(0, 0, 0, 0.1)` to `rgba(0, 0, 0, 0.4)` | + +### Notes + +- Where the original design used near-duplicate shades for the same role, each declaration keeps its + own original value as the fallback. That is why some rows list more than one default. Nothing shifts + until you set the token, and once you do, every use of that role picks up your value. +- `--seamless-shadow` is the shadow colour only. Offsets and blur are fixed. Setting it applies one + colour to every shadow in the built-in UI, replacing the per-screen alpha values. +- If you set `--seamless-surface` to a light colour, set `--seamless-text` too. The default text + colour is white and will disappear otherwise. +- Two decorative tints are deliberately not tokenised: the pulse ring behind the magic-link mail icon + and the disc behind the success check. Both are translucent and sit directly under an icon, so an + opaque override would hide the icon it is meant to frame. +- The package ships one palette and no `prefers-color-scheme` rules. If you want the auth UI to follow + the system theme, wrap your own overrides in a media query. + ## Backend Expectations This package assumes a Seamless Auth-compatible backend with the auth adapter mounted at `/auth`. diff --git a/src/styles/deviceNameModal.module.css b/src/styles/deviceNameModal.module.css index f397f49..f2dfefe 100644 --- a/src/styles/deviceNameModal.module.css +++ b/src/styles/deviceNameModal.module.css @@ -1,7 +1,7 @@ .overlay { position: fixed; inset: 0; - background: rgba(0, 0, 0, 0.45); + background: var(--seamless-overlay, rgba(0, 0, 0, 0.45)); display: flex; align-items: center; justify-content: center; @@ -9,18 +9,18 @@ } .modal { - background: #1f2937; - color: #fff; + background: var(--seamless-surface, #1f2937); + color: var(--seamless-text, #fff); padding: 24px; border-radius: 12px; width: 100%; max-width: 420px; - box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15); + box-shadow: 0 20px 40px var(--seamless-shadow, rgba(0, 0, 0, 0.15)); } .description { font-size: 14px; - color: #fff; + color: var(--seamless-text, #fff); margin-bottom: 16px; } @@ -28,7 +28,7 @@ width: 100%; padding: 10px 12px; border-radius: 8px; - border: 1px solid #ddd; + border: 1px solid var(--seamless-border, #ddd); margin-bottom: 20px; font-size: 14px; } @@ -40,8 +40,8 @@ } .primary { - background: #2563eb; - color: white; + background: var(--seamless-accent, #2563eb); + color: var(--seamless-accent-contrast, white); border: none; padding: 8px 14px; border-radius: 8px; @@ -50,7 +50,7 @@ .secondary { background: transparent; - border: 1px solid #ccc; + border: 1px solid var(--seamless-border, #ccc); padding: 8px 14px; border-radius: 8px; cursor: pointer; diff --git a/src/styles/login.module.css b/src/styles/login.module.css index 930c9fd..2bdcd6d 100644 --- a/src/styles/login.module.css +++ b/src/styles/login.module.css @@ -2,14 +2,14 @@ display: flex; align-items: center; justify-content: center; - color: white; + color: var(--seamless-text, white); } .card { - background-color: #1f2937; + background-color: var(--seamless-surface, #1f2937); padding: 2rem; border-radius: 0.5rem; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + box-shadow: 0 4px 6px var(--seamless-shadow, rgba(0, 0, 0, 0.1)); width: 100%; max-width: 28rem; } @@ -19,11 +19,11 @@ font-weight: bold; margin-bottom: 1.5rem; text-align: center; - color: white; + color: var(--seamless-text, white); } .message { - color: #68d391; + color: var(--seamless-success, #68d391); text-align: center; } @@ -33,38 +33,38 @@ .label { display: block; - color: #d1d5db; + color: var(--seamless-text-muted, #d1d5db); } .input { width: 100%; padding: 0.5rem; - background-color: #4b5563; - border: 1px solid #d1d5db; + background-color: var(--seamless-surface-raised, #4b5563); + border: 1px solid var(--seamless-border, #d1d5db); border-radius: 0.375rem; margin-top: 0.25rem; } .input:focus { outline: none; - box-shadow: 0 0 0 2px #3b82f6; + box-shadow: 0 0 0 2px var(--seamless-accent, #3b82f6); } .helperText { font-size: 0.75rem; - color: #9ca3af; + color: var(--seamless-text-muted, #9ca3af); margin-top: 0.5rem; } .error { - color: #f87171; + color: var(--seamless-danger, #f87171); font-size: 0.875rem; } .button { width: 100%; - background-color: #2563eb; - color: white; + background-color: var(--seamless-accent, #2563eb); + color: var(--seamless-accent-contrast, white); padding: 0.5rem; border-radius: 0.375rem; transition: background-color 0.3s; @@ -73,11 +73,11 @@ } .button:hover { - background-color: #1d4ed8; + background-color: var(--seamless-accent-hover, #1d4ed8); } .button:disabled { - background-color: #9ca3af; + background-color: var(--seamless-disabled, #9ca3af); cursor: not-allowed; } @@ -85,7 +85,7 @@ margin-top: 1.5rem; width: 100%; font-size: 0.875rem; - color: #60a5fa; + color: var(--seamless-accent-soft, #60a5fa); text-align: center; background: none; border: none; @@ -107,16 +107,16 @@ width: 100%; padding: 0.5rem; border-radius: 0.375rem; - background-color: #4b5563; - border: 1px solid #d1d5db; + background-color: var(--seamless-surface-raised, #4b5563); + border: 1px solid var(--seamless-border, #d1d5db); } .phoneInput { width: 100%; padding: 0.5rem; border-radius: 0.375rem; - background-color: #4b5563; - border: 1px solid #d1d5db; + background-color: var(--seamless-surface-raised, #4b5563); + border: 1px solid var(--seamless-border, #d1d5db); } @media (max-width: 500px) { @@ -131,8 +131,8 @@ margin-top: 18px; padding: 18px; border-radius: 12px; - background: rgba(255, 255, 255, 0.04); - border: 1px solid rgba(255, 255, 255, 0.08); + background: var(--seamless-surface-raised, rgba(255, 255, 255, 0.04)); + border: 1px solid var(--seamless-border, rgba(255, 255, 255, 0.08)); display: flex; flex-direction: column; gap: 14px; @@ -141,12 +141,12 @@ .fallbackHeader { font-size: 0.95rem; font-weight: 600; - color: #f3f4f6; + color: var(--seamless-text, #f3f4f6); } .fallbackDescription { font-size: 0.85rem; - color: #9ca3af; + color: var(--seamless-text-muted, #9ca3af); line-height: 1.4; } @@ -164,27 +164,27 @@ padding: 12px 14px; border-radius: 8px; - background: rgba(0, 0, 0, 0.25); - border: 1px solid rgba(255, 255, 255, 0.08); + background: var(--seamless-surface, rgba(0, 0, 0, 0.25)); + border: 1px solid var(--seamless-border, rgba(255, 255, 255, 0.08)); cursor: pointer; transition: all 0.15s ease; } .fallbackActionButton:hover { - background: rgba(255, 255, 255, 0.06); - border-color: rgba(255, 255, 255, 0.15); + background: var(--seamless-surface-hover, rgba(255, 255, 255, 0.06)); + border-color: var(--seamless-border, rgba(255, 255, 255, 0.15)); } .actionTitle { font-size: 0.9rem; font-weight: 500; - color: #f9fafb; + color: var(--seamless-text, #f9fafb); } .actionSubtext { font-size: 0.75rem; - color: #9ca3af; + color: var(--seamless-text-muted, #9ca3af); margin-top: 2px; } @@ -192,7 +192,7 @@ margin-top: 6px; background: none; border: none; - color: #60a5fa; + color: var(--seamless-accent-soft, #60a5fa); font-size: 0.8rem; cursor: pointer; } diff --git a/src/styles/magiclink.module.css b/src/styles/magiclink.module.css index 98c62da..16fd8f6 100644 --- a/src/styles/magiclink.module.css +++ b/src/styles/magiclink.module.css @@ -2,14 +2,14 @@ display: flex; align-items: center; justify-content: center; - color: white; + color: var(--seamless-text, white); } .card { - background-color: #1f2937; + background-color: var(--seamless-surface, #1f2937); padding: 2.5rem 2rem; border-radius: 0.75rem; - box-shadow: 0 10px 25px rgba(0, 0, 0, 0.25); + box-shadow: 0 10px 25px var(--seamless-shadow, rgba(0, 0, 0, 0.25)); width: 100%; max-width: 420px; text-align: center; @@ -27,7 +27,7 @@ .mailIcon { width: 38px; height: 38px; - color: #a5b4fc; + color: var(--seamless-accent-soft, #a5b4fc); z-index: 2; } @@ -63,7 +63,7 @@ } .message { - color: #d1d5db; + color: var(--seamless-text-muted, #d1d5db); font-size: 0.95rem; margin-bottom: 1rem; line-height: 1.4; @@ -72,7 +72,7 @@ .identifier { font-weight: 600; font-size: 1rem; - background: rgba(255, 255, 255, 0.05); + background: var(--seamless-surface-raised, rgba(255, 255, 255, 0.05)); padding: 0.45rem 0.6rem; border-radius: 6px; margin-bottom: 1rem; @@ -80,7 +80,7 @@ } .helperText { - color: #9ca3af; + color: var(--seamless-text-muted, #9ca3af); font-size: 0.85rem; margin-bottom: 0.6rem; line-height: 1.4; @@ -98,15 +98,15 @@ .secondaryButton { padding: 0.65rem; border-radius: 8px; - border: 1px solid #374151; - background: #111827; - color: white; + border: 1px solid var(--seamless-border, #374151); + background: var(--seamless-surface, #111827); + color: var(--seamless-text, white); cursor: pointer; font-weight: 500; } .secondaryButton:hover:not(:disabled) { - background: #1f2937; + background: var(--seamless-surface-hover, #1f2937); } .secondaryButton:disabled { @@ -116,14 +116,14 @@ .cooldown { font-size: 0.8rem; - color: #9ca3af; + color: var(--seamless-text-muted, #9ca3af); } .linkButton { margin-top: 0.4rem; background: none; border: none; - color: #a5b4fc; + color: var(--seamless-accent-soft, #a5b4fc); font-size: 0.85rem; cursor: pointer; } diff --git a/src/styles/mfaLogin.module.css b/src/styles/mfaLogin.module.css index 49e6d47..b16014c 100644 --- a/src/styles/mfaLogin.module.css +++ b/src/styles/mfaLogin.module.css @@ -1,5 +1,5 @@ .container { - color: white; + color: var(--seamless-text, white); display: flex; align-items: center; justify-content: center; @@ -7,9 +7,9 @@ } .card { - background-color: #1f2937; + background-color: var(--seamless-surface, #1f2937); border-radius: 1rem; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); + box-shadow: 0 4px 20px var(--seamless-shadow, rgba(0, 0, 0, 0.4)); padding: 1.5rem; width: 100%; max-width: 400px; @@ -22,11 +22,11 @@ font-size: 1.5rem; font-weight: 600; text-align: center; - color: white; + color: var(--seamless-text, white); } .msg { - color: #4ade80; + color: var(--seamless-success, #4ade80); text-align: center; } @@ -39,21 +39,21 @@ .button { padding: 0.75rem 1rem; border-radius: 0.5rem; - border: 1px solid #4b5563; - background-color: #374151; + border: 1px solid var(--seamless-border, #4b5563); + background-color: var(--seamless-surface-raised, #374151); transition: background-color 0.2s; - color: white; + color: var(--seamless-text, white); font-weight: 500; text-align: left; } .button:hover { - background-color: #4b5563; + background-color: var(--seamless-surface-hover, #4b5563); } .selected { - background-color: #2563eb; - border-color: #3b82f6; + background-color: var(--seamless-accent, #2563eb); + border-color: var(--seamless-accent, #3b82f6); } .codeLabel { @@ -64,7 +64,7 @@ } .countdown { - color: #facc15; + color: var(--seamless-warning, #facc15); font-size: 0.875rem; } @@ -72,9 +72,9 @@ width: 100%; padding: 0.75rem 1rem; border-radius: 0.5rem; - background-color: #374151; - border: 1px solid #4b5563; - color: white; + background-color: var(--seamless-surface-raised, #374151); + border: 1px solid var(--seamless-border, #4b5563); + color: var(--seamless-text, white); font-family: monospace; font-size: 1.25rem; letter-spacing: 0.2em; @@ -82,28 +82,28 @@ .input:focus { outline: none; - border-color: #3b82f6; - box-shadow: 0 0 0 2px #3b82f6; + border-color: var(--seamless-accent, #3b82f6); + box-shadow: 0 0 0 2px var(--seamless-accent, #3b82f6); } .submit { padding: 0.75rem 1rem; border-radius: 0.5rem; - background-color: #2563eb; - border: 1px solid #3b82f6; - color: white; + background-color: var(--seamless-accent, #2563eb); + border: 1px solid var(--seamless-accent, #3b82f6); + color: var(--seamless-accent-contrast, white); font-weight: 500; cursor: pointer; transition: background-color 0.2s; } .submit:disabled { - background-color: #9ca3af; + background-color: var(--seamless-disabled, #9ca3af); cursor: not-allowed; } .error { - color: #f87171; + color: var(--seamless-danger, #f87171); text-align: center; margin-bottom: 0.5rem; } diff --git a/src/styles/otpInput.module.css b/src/styles/otpInput.module.css index 5d29dbe..5c3b294 100644 --- a/src/styles/otpInput.module.css +++ b/src/styles/otpInput.module.css @@ -11,9 +11,9 @@ text-align: center; font-size: 1.2rem; border-radius: 8px; - border: 1px solid #4b5563; - background: #374151; - color: white; + border: 1px solid var(--seamless-border, #4b5563); + background: var(--seamless-surface-raised, #374151); + color: var(--seamless-text, white); transition: border-color 0.15s ease, box-shadow 0.15s ease; @@ -21,6 +21,6 @@ .otpInput:focus { outline: none; - border-color: #60a5fa; - box-shadow: 0 0 0 2px rgba(96, 165, 250, 0.25); + border-color: var(--seamless-accent, #60a5fa); + box-shadow: 0 0 0 2px var(--seamless-accent, rgba(96, 165, 250, 0.25)); } diff --git a/src/styles/passKeyLogin.module.css b/src/styles/passKeyLogin.module.css index 6382b5a..dac1350 100644 --- a/src/styles/passKeyLogin.module.css +++ b/src/styles/passKeyLogin.module.css @@ -1,5 +1,5 @@ .container { - color: white; + color: var(--seamless-text, white); display: flex; align-items: center; justify-content: center; @@ -7,9 +7,9 @@ } .card { - background-color: #1f2937; + background-color: var(--seamless-surface, #1f2937); border-radius: 1rem; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); + box-shadow: 0 4px 20px var(--seamless-shadow, rgba(0, 0, 0, 0.4)); padding: 2rem; width: 100%; max-width: 400px; @@ -22,24 +22,24 @@ font-size: 1.5rem; font-weight: 600; text-align: center; - color: white; + color: var(--seamless-text, white); } .button { width: 100%; padding: 0.75rem 1rem; border-radius: 0.5rem; - background-color: #2563eb; - color: white; + background-color: var(--seamless-accent, #2563eb); + color: var(--seamless-accent-contrast, white); font-weight: 500; text-align: center; cursor: pointer; transition: background-color 0.2s ease; - border: 1px solid #3b82f6; + border: 1px solid var(--seamless-accent, #3b82f6); } .button:hover { - background-color: #1d4ed8; + background-color: var(--seamless-accent-hover, #1d4ed8); } @media (max-width: 480px) { diff --git a/src/styles/registerPasskey.module.css b/src/styles/registerPasskey.module.css index 869ce80..9108d74 100644 --- a/src/styles/registerPasskey.module.css +++ b/src/styles/registerPasskey.module.css @@ -1,5 +1,5 @@ .container { - color: white; + color: var(--seamless-text, white); display: flex; align-items: center; justify-content: center; @@ -7,9 +7,9 @@ } .card { - background-color: #1f2937; + background-color: var(--seamless-surface, #1f2937); border-radius: 1rem; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); + box-shadow: 0 4px 20px var(--seamless-shadow, rgba(0, 0, 0, 0.4)); padding: 1.5rem; width: 100%; max-width: 400px; @@ -21,17 +21,17 @@ justify-content: center; gap: 0.75rem; padding: 1.5rem; - background-color: #f9fafb; - color: #374151; + background-color: var(--seamless-surface, #f9fafb); + color: var(--seamless-text, #374151); border-radius: 0.75rem; font-weight: 500; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + box-shadow: 0 2px 8px var(--seamless-shadow, rgba(0, 0, 0, 0.1)); } .spinner { animation: spin 1s linear infinite; - border-top: 2px solid #3b82f6; - border-bottom: 2px solid #3b82f6; + border-top: 2px solid var(--seamless-accent, #3b82f6); + border-bottom: 2px solid var(--seamless-accent, #3b82f6); border-left: 2px solid transparent; border-right: 2px solid transparent; border-radius: 9999px; @@ -46,11 +46,11 @@ } .supported { - background-color: #ecfdf5; - color: #065f46; + background-color: var(--seamless-surface, #ecfdf5); + color: var(--seamless-text, #065f46); padding: 1.25rem; border-radius: 0.75rem; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); + box-shadow: 0 2px 12px var(--seamless-shadow, rgba(0, 0, 0, 0.1)); } .title { @@ -66,8 +66,8 @@ .button { width: 100%; padding: 0.75rem 1rem; - background-color: #059669; - color: white; + background-color: var(--seamless-accent, #059669); + color: var(--seamless-accent-contrast, white); border: none; border-radius: 0.5rem; font-weight: 500; @@ -76,7 +76,7 @@ } .button:hover { - background-color: #047857; + background-color: var(--seamless-accent-hover, #047857); } .message { @@ -85,18 +85,18 @@ } .success { - color: #6ee7b7; + color: var(--seamless-success, #6ee7b7); } .error { - color: #f87171; + color: var(--seamless-danger, #f87171); } .skip { margin-top: 1.5rem; width: 100%; font-size: 0.875rem; - color: #60a5fa; + color: var(--seamless-accent-soft, #60a5fa); text-align: center; background: none; border: none; diff --git a/src/styles/termsModal.module.css b/src/styles/termsModal.module.css index 1c651e0..e44be17 100644 --- a/src/styles/termsModal.module.css +++ b/src/styles/termsModal.module.css @@ -2,22 +2,22 @@ position: fixed; inset: 0; z-index: 999; - background-color: rgba(0, 0, 0, 0.7); + background-color: var(--seamless-overlay, rgba(0, 0, 0, 0.7)); display: flex; justify-content: center; align-items: center; } .modal { - background-color: #1a1a1a; - color: white; + background-color: var(--seamless-surface, #1a1a1a); + color: var(--seamless-text, white); padding: 24px; border-radius: 8px; width: 100%; max-width: 640px; max-height: 80vh; overflow-y: auto; - box-shadow: 0 10px 25px rgba(0, 0, 0, 0.4); + box-shadow: 0 10px 25px var(--seamless-shadow, rgba(0, 0, 0, 0.4)); outline: none; } @@ -30,30 +30,30 @@ .title { font-size: 1.25rem; - color: #60a5fa; + color: var(--seamless-accent-soft, #60a5fa); font-weight: bold; } .closeBtn { background: none; border: none; - color: #ccc; + color: var(--seamless-text-muted, #ccc); font-size: 1.75rem; cursor: pointer; } .closeBtn:hover { - color: white; + color: var(--seamless-text, white); } .content { font-size: 0.9rem; line-height: 1.6; - color: #d1d5db; + color: var(--seamless-text-muted, #d1d5db); } .link { - color: #60a5fa; + color: var(--seamless-accent-soft, #60a5fa); text-decoration: underline; } diff --git a/src/styles/verifyMagiclink.module.css b/src/styles/verifyMagiclink.module.css index b97a7b4..0d700e6 100644 --- a/src/styles/verifyMagiclink.module.css +++ b/src/styles/verifyMagiclink.module.css @@ -1,5 +1,5 @@ .container { - color: white; + color: var(--seamless-text, white); display: flex; align-items: center; justify-content: center; @@ -7,12 +7,12 @@ } .card { - background-color: #1f2937; + background-color: var(--seamless-surface, #1f2937); width: 100%; max-width: 28rem; padding: 1.5rem; border-radius: 0.5rem; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + box-shadow: 0 0 10px var(--seamless-shadow, rgba(0, 0, 0, 0.3)); } .title { @@ -20,7 +20,7 @@ font-weight: bold; text-align: center; margin-bottom: 1rem; - color: white; + color: var(--seamless-text, white); } .verificationContent { @@ -35,8 +35,8 @@ width: 28px; height: 28px; border-radius: 50%; - border: 3px solid rgba(255, 255, 255, 0.15); - border-top-color: #60a5fa; + border: 3px solid var(--seamless-border, rgba(255, 255, 255, 0.15)); + border-top-color: var(--seamless-accent, #60a5fa); animation: spin 0.9s linear infinite; } @@ -53,12 +53,12 @@ .checkIcon { width: 22px; height: 22px; - color: #34d399; + color: var(--seamless-success, #34d399); animation: checkPop 0.25s ease-out; } .successText { - color: #34d399; + color: var(--seamless-success, #34d399); font-size: 0.9rem; } diff --git a/src/styles/verifyOTP.module.css b/src/styles/verifyOTP.module.css index 0e1bf18..bb4b77e 100644 --- a/src/styles/verifyOTP.module.css +++ b/src/styles/verifyOTP.module.css @@ -1,5 +1,5 @@ .container { - color: white; + color: var(--seamless-text, white); display: flex; align-items: center; justify-content: center; @@ -7,12 +7,12 @@ } .card { - background-color: #1f2937; + background-color: var(--seamless-surface, #1f2937); width: 100%; max-width: 28rem; padding: 1.5rem; border-radius: 0.5rem; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + box-shadow: 0 0 10px var(--seamless-shadow, rgba(0, 0, 0, 0.3)); } .title { @@ -20,24 +20,24 @@ font-weight: bold; text-align: center; margin-bottom: 1rem; - color: white; + color: var(--seamless-text, white); } .subtitle { - color: #9ca3af; + color: var(--seamless-text-muted, #9ca3af); font-size: 0.875rem; text-align: center; margin-bottom: 1.5rem; } .error { - color: #f87171; + color: var(--seamless-danger, #f87171); text-align: center; margin-bottom: 1rem; } .success { - color: #34d399; + color: var(--seamless-success, #34d399); text-align: center; margin-bottom: 0.75rem; } @@ -52,11 +52,11 @@ display: block; font-size: 0.875rem; margin-bottom: 0.25rem; - color: #d1d5db; + color: var(--seamless-text-muted, #d1d5db); } .timer { - color: #facc15; + color: var(--seamless-warning, #facc15); font-size: 0.875rem; } @@ -64,20 +64,20 @@ width: 100%; padding: 0.5rem; border-radius: 0.375rem; - background-color: #374151; - border: 1px solid #4b5563; - color: white; + background-color: var(--seamless-surface-raised, #374151); + border: 1px solid var(--seamless-border, #4b5563); + color: var(--seamless-text, white); outline: none; } .input:focus { - box-shadow: 0 0 0 2px #3b82f6; + box-shadow: 0 0 0 2px var(--seamless-accent, #3b82f6); } .resend { margin-top: 0.25rem; font-size: 0.75rem; - color: #60a5fa; + color: var(--seamless-accent-soft, #60a5fa); background: none; border: none; cursor: pointer; @@ -85,13 +85,13 @@ } .resend:hover { - color: #3b82f6; + color: var(--seamless-accent, #3b82f6); } .button { width: 100%; - background-color: #2563eb; - color: white; + background-color: var(--seamless-accent, #2563eb); + color: var(--seamless-accent-contrast, white); padding: 0.5rem; border-radius: 0.375rem; transition: background-color 0.2s; @@ -100,14 +100,14 @@ } .button:hover { - background-color: #1d4ed8; + background-color: var(--seamless-accent-hover, #1d4ed8); } .toggle { margin-top: 1.5rem; width: 100%; font-size: 0.875rem; - color: #60a5fa; + color: var(--seamless-accent-soft, #60a5fa); text-align: center; background: none; border: none;