From e4b5a8431437a49cc3dd8c4b9d21d3a1e3fc5e20 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Jun 2026 17:35:06 +0000 Subject: [PATCH 1/4] Initial plan From b937e5621939a02e693548f5a6215dd2a3ac355a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Jun 2026 17:38:58 +0000 Subject: [PATCH 2/4] docs(react-sdk): document UrAuth v0.2.0 customization options --- mintlify/docs/react-sdk/ur-auth.mdx | 184 +++++++++++++++++- sdks/urbackend-react/CHANGELOG.md | 20 ++ .../urbackend-react/src/components/UrAuth.tsx | 15 +- sdks/urbackend-react/tests/UrAuth.test.tsx | 15 ++ 4 files changed, 223 insertions(+), 11 deletions(-) create mode 100644 sdks/urbackend-react/CHANGELOG.md diff --git a/mintlify/docs/react-sdk/ur-auth.mdx b/mintlify/docs/react-sdk/ur-auth.mdx index 0a4080b5f..88ab0ffcc 100644 --- a/mintlify/docs/react-sdk/ur-auth.mdx +++ b/mintlify/docs/react-sdk/ur-auth.mdx @@ -16,7 +16,8 @@ export default function LoginPage() { return (
@@ -28,12 +29,185 @@ export default function LoginPage() { | Prop | Type | Default | Description | |---|---|---|---| -| `theme` | `'light' \| 'dark'` | `'light'` | The visual theme of the component. | -| `providers` | `Array<'google' \| 'github'>` | `[]` | Social auth providers to display. These must be enabled in your urBackend Dashboard first. | +| `theme` | `'light' \| 'dark'` | `'light'` | Visual theme mode (`ThemeMode` internally). | +| `providers` | `('google' \| 'github')[] \| { google?: boolean; github?: boolean; emailPassword?: boolean }` | `['google', 'github']` | Auth methods to show. Supports legacy array form and v0.2.0 object form. | +| `enableEmailPassword` | `boolean` | `true` | Top-level shorthand to enable/disable email/password auth. | +| `colors` | `Partial` | `undefined` | Overrides for auth widget theme colors. | +| `branding` | `AuthBranding` | `undefined` | Branding/white-label configuration (logo, app name, subtitle, brand color). | +| `labels` | `Partial` | `undefined` | Text/copy overrides for tabs, titles, buttons, and footer prompts. | +| `onSuccess` | `() => void` | `undefined` | Called after successful sign-in or sign-up flow. | -## Customizing the Design +> All customization props are optional. If omitted, `` falls back to the same default behavior/UI style as v0.1.x. -The `` component uses a modern, square design aesthetic (sharp corners). It adapts well to both light and dark backgrounds depending on the `theme` prop you provide. +## `providers` and `enableEmailPassword` + +`providers` now accepts either: + +```ts +('google' | 'github')[] +``` + +or: + +```ts +{ + google?: boolean; + github?: boolean; + emailPassword?: boolean; +} +``` + +### Example: Email/password only + +```tsx + +``` + +### Example: Google only + +```tsx + +``` + +### Example: Disable all methods + +```tsx + +``` + +This renders the built-in `"No authentication methods are enabled for this screen."` message. + +### `enableEmailPassword` interaction + +- `enableEmailPassword` is a shorthand global toggle. +- When `providers` is an object and includes `emailPassword`, that object value takes precedence. +- If `providers.emailPassword` is omitted, `enableEmailPassword` is used. + +## `colors` theme customization + +Use `colors` to override theme tokens: + +```ts +type AuthColors = { + background: string; + surface: string; + text: string; + textMuted: string; + border: string; + inputBackground: string; + primary: string; + primaryColor?: string; // alias for primary button color + primaryText: string; + footerBackground: string; + dividerText: string; + socialButtonBackground: string; +}; +``` + +Set a custom brand color on the primary sign-in button: + +```tsx + +``` + +## `branding` white-label options + +```ts +type AuthBranding = { + brandName?: string; + appName?: string; + title?: string; + subtitle?: string; + logo?: React.ReactNode | string; // URL string or custom React node + logoUrl?: string; // URL alias + primaryColor?: string; +}; +``` + +Example: + +```tsx + +``` + +## `labels` text overrides (with aliases) + +Supported label keys: + +- Tabs: `loginTab` (`signInTab` alias), `signupTab` (`signUpTab` alias) +- Titles: `loginTitle` (`signInTitle` alias), `signupTitle` (`signUpTitle` alias), `forgotTitle`, `resetTitle`, `forgotSubtitle`, `resetSubtitle` +- Buttons: `loginButton` (`signInButton` alias), `signupButton` (`signUpButton` alias), `forgotButton`, `resetButton`, `googleButton`, `githubButton` +- Field labels/placeholders: `emailLabel`, `emailPlaceholder`, `passwordLabel`, `passwordPlaceholder`, `nameLabel`, `namePlaceholder`, `otpLabel`, `otpPlaceholder` +- Footer/misc: `forgotPasswordLink`, `socialDivider`, `footerSigninPrompt`, `footerSignupPrompt`, `footerForgotPrompt`, `noAuthMethods` + +Example: + +```tsx + +``` + +## Full v0.2.0 customization example + +```tsx +import { UrAuth, GuestRoute } from '@urbackend/react'; + +export default function LoginPage() { + return ( + Loading...} onRedirect={() => (window.location.href = '/dashboard')}> + { + // route after successful auth + window.location.href = '/dashboard'; + }} + /> + + ); +} +``` + +## Migration (v0.1.x → v0.2.0) + +- `providers` now also accepts object form: `{ google?, github?, emailPassword? }` +- Existing array usage (`['google', 'github']`) still works +- No breaking API changes otherwise ## Behavior diff --git a/sdks/urbackend-react/CHANGELOG.md b/sdks/urbackend-react/CHANGELOG.md new file mode 100644 index 000000000..7cca606e3 --- /dev/null +++ b/sdks/urbackend-react/CHANGELOG.md @@ -0,0 +1,20 @@ +# Changelog + +All notable changes to `@urbackend/react` are documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this package adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v0.2.0] - 2026-06-13 + +### Added +- Expanded `` customization with object-form `providers` config (`google`, `github`, `emailPassword`) +- Added `enableEmailPassword` shorthand toggle support +- Added customizable `colors`, `branding`, and `labels` props for theme/copy overrides +- Added label alias support (for example: `signInTitle`/`loginTitle`, `signInButton`/`loginButton`) +- Added configurable branding logo URL support (`branding.logoUrl` alias) + +### Changed +- Internal theme typing for `` uses `ThemeMode` while keeping public values as `'light' | 'dark'` +- Defaults remain backward compatible with v0.1.x when new props are omitted + diff --git a/sdks/urbackend-react/src/components/UrAuth.tsx b/sdks/urbackend-react/src/components/UrAuth.tsx index 6754675cf..a7f537cfe 100644 --- a/sdks/urbackend-react/src/components/UrAuth.tsx +++ b/sdks/urbackend-react/src/components/UrAuth.tsx @@ -13,6 +13,7 @@ interface AuthColors { border: string; inputBackground: string; primary: string; + primaryColor?: string; primaryText: string; footerBackground: string; dividerText: string; @@ -25,6 +26,7 @@ interface AuthBranding { title?: string; subtitle?: string; logo?: React.ReactNode | string; + logoUrl?: string; primaryColor?: string; } @@ -200,7 +202,7 @@ export const UrAuth: React.FC = ({ }; const themeColors = { ...defaultThemeColors[theme], ...colors }; - const primaryColor = branding?.primaryColor || themeColors.primary; + const primaryColor = branding?.primaryColor || colors?.primaryColor || themeColors.primary; const secondStopColor = adjustColor(primaryColor, -15); let isGoogleEnabled = true; @@ -222,6 +224,7 @@ export const UrAuth: React.FC = ({ const hasSocialAuth = isGoogleEnabled || isGithubEnabled; const brandName = branding?.brandName || branding?.appName || branding?.title || 'urBackend'; const headerTitle = branding?.title || brandName; + const brandingLogo = branding?.logo ?? branding?.logoUrl; const headerSubtitle = branding?.subtitle || (mode === 'signin' ? text.loginTitle : mode === 'signup' @@ -524,15 +527,15 @@ export const UrAuth: React.FC = ({ )}
- {(branding?.logo || branding?.brandName || branding?.appName || branding?.title || branding?.subtitle || headerTitle || headerSubtitle) && ( + {(brandingLogo || branding?.brandName || branding?.appName || branding?.title || branding?.subtitle || headerTitle || headerSubtitle) && (
- {branding?.logo ? ( + {brandingLogo ? (
- {typeof branding.logo === 'string' ? ( - {brandName} + {typeof brandingLogo === 'string' ? ( + {brandName} ) : ( - branding.logo + brandingLogo )}
) : ( diff --git a/sdks/urbackend-react/tests/UrAuth.test.tsx b/sdks/urbackend-react/tests/UrAuth.test.tsx index 8613008f6..3d3d365a1 100644 --- a/sdks/urbackend-react/tests/UrAuth.test.tsx +++ b/sdks/urbackend-react/tests/UrAuth.test.tsx @@ -94,6 +94,12 @@ describe('UrAuth Component', () => { expect(primaryButton.style.background).toContain('#4F46E5'); }); + it('applies custom primary color from colors.primaryColor', () => { + render(); + const primaryButton = screen.getByRole('button', { name: 'Log In' }); + expect(primaryButton.style.background).toContain('#6366f1'); + }); + it('hides email/password form when disabled via providers object', () => { render(); expect(screen.queryByPlaceholderText('Enter your email address')).not.toBeInTheDocument(); @@ -130,4 +136,13 @@ describe('UrAuth Component', () => { expect(logoImg).toBeInTheDocument(); expect(logoImg?.getAttribute('src')).toBe('/assets/logo.png'); }); + + it('supports logoUrl branding alias', () => { + const { container } = render( + + ); + const logoImg = container.querySelector('img'); + expect(logoImg).toBeInTheDocument(); + expect(logoImg?.getAttribute('src')).toBe('/assets/logo-url.png'); + }); }); From 77d9572368019647e22fb849ab6009b51f126b38 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Jun 2026 17:40:21 +0000 Subject: [PATCH 3/4] docs(react-sdk): clarify primary color precedence --- mintlify/docs/react-sdk/ur-auth.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mintlify/docs/react-sdk/ur-auth.mdx b/mintlify/docs/react-sdk/ur-auth.mdx index 88ab0ffcc..ad05f254d 100644 --- a/mintlify/docs/react-sdk/ur-auth.mdx +++ b/mintlify/docs/react-sdk/ur-auth.mdx @@ -114,6 +114,8 @@ Set a custom brand color on the primary sign-in button: ``` +If both `colors.primaryColor` and `branding.primaryColor` are provided, `branding.primaryColor` takes precedence. + ## `branding` white-label options ```ts From c89ba9f9f736994148b75a70ef9e5e28c1a479ae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 13 Jun 2026 17:49:56 +0000 Subject: [PATCH 4/4] fix review feedback for UrAuth docs and tests --- mintlify/docs/react-sdk/ur-auth.mdx | 4 ++-- sdks/urbackend-react/tests/UrAuth.test.tsx | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mintlify/docs/react-sdk/ur-auth.mdx b/mintlify/docs/react-sdk/ur-auth.mdx index ad05f254d..b7b9be221 100644 --- a/mintlify/docs/react-sdk/ur-auth.mdx +++ b/mintlify/docs/react-sdk/ur-auth.mdx @@ -76,10 +76,10 @@ or: ### Example: Disable all methods ```tsx - + ``` -This renders the built-in `"No authentication methods are enabled for this screen."` message. +This renders the built-in `No authentication methods are enabled for this screen.` message. ### `enableEmailPassword` interaction diff --git a/sdks/urbackend-react/tests/UrAuth.test.tsx b/sdks/urbackend-react/tests/UrAuth.test.tsx index 3d3d365a1..3f3a1f715 100644 --- a/sdks/urbackend-react/tests/UrAuth.test.tsx +++ b/sdks/urbackend-react/tests/UrAuth.test.tsx @@ -109,14 +109,14 @@ describe('UrAuth Component', () => { }); it('only shows GitHub login when configured via providers object', () => { - render(); + render(); expect(screen.queryByPlaceholderText('Enter your email address')).not.toBeInTheDocument(); expect(screen.getByText('Continue with GitHub')).toBeInTheDocument(); expect(screen.queryByText('Continue with Google')).not.toBeInTheDocument(); }); it('displays message when all authentication methods are disabled', () => { - render(); + render(); expect(screen.getByText('No authentication methods are enabled for this screen.')).toBeInTheDocument(); }); @@ -138,11 +138,11 @@ describe('UrAuth Component', () => { }); it('supports logoUrl branding alias', () => { - const { container } = render( + render( ); - const logoImg = container.querySelector('img'); + const logoImg = screen.getByRole('img', { name: 'My Custom App' }); expect(logoImg).toBeInTheDocument(); - expect(logoImg?.getAttribute('src')).toBe('/assets/logo-url.png'); + expect(logoImg.getAttribute('src')).toBe('/assets/logo-url.png'); }); });