Skip to content

Commit 1b65e78

Browse files
authored
Merge pull request #308 from geturbackend/copilot/docs-update-react-sdk-docs
docs(react-sdk): document UrAuth v0.2.0 customization API and migration notes
1 parent cdd5ee8 commit 1b65e78

4 files changed

Lines changed: 227 additions & 13 deletions

File tree

mintlify/docs/react-sdk/ur-auth.mdx

Lines changed: 181 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ export default function LoginPage() {
1616
return (
1717
<div style={{ display: 'flex', minHeight: '100vh', alignItems: 'center', justifyContent: 'center' }}>
1818
<UrAuth
19-
providers={['google', 'github']}
19+
providers={['google', 'github']}
20+
enableEmailPassword={true}
2021
theme="light"
2122
/>
2223
</div>
@@ -28,12 +29,187 @@ export default function LoginPage() {
2829

2930
| Prop | Type | Default | Description |
3031
|---|---|---|---|
31-
| `theme` | `'light' \| 'dark'` | `'light'` | The visual theme of the component. |
32-
| `providers` | `Array<'google' \| 'github'>` | `[]` | Social auth providers to display. These must be enabled in your urBackend Dashboard first. |
32+
| `theme` | `'light' \| 'dark'` | `'light'` | Visual theme mode (`ThemeMode` internally). |
33+
| `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. |
34+
| `enableEmailPassword` | `boolean` | `true` | Top-level shorthand to enable/disable email/password auth. |
35+
| `colors` | `Partial<AuthColors>` | `undefined` | Overrides for auth widget theme colors. |
36+
| `branding` | `AuthBranding` | `undefined` | Branding/white-label configuration (logo, app name, subtitle, brand color). |
37+
| `labels` | `Partial<AuthLabels>` | `undefined` | Text/copy overrides for tabs, titles, buttons, and footer prompts. |
38+
| `onSuccess` | `() => void` | `undefined` | Called after successful sign-in or sign-up flow. |
3339

34-
## Customizing the Design
40+
> All customization props are optional. If omitted, `<UrAuth>` falls back to the same default behavior/UI style as v0.1.x.
3541
36-
The `<UrAuth>` 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.
42+
## `providers` and `enableEmailPassword`
43+
44+
`providers` now accepts either:
45+
46+
```ts
47+
('google' | 'github')[]
48+
```
49+
50+
or:
51+
52+
```ts
53+
{
54+
google?: boolean;
55+
github?: boolean;
56+
emailPassword?: boolean;
57+
}
58+
```
59+
60+
### Example: Email/password only
61+
62+
```tsx
63+
<UrAuth
64+
providers={{ google: false, github: false, emailPassword: true }}
65+
/>
66+
```
67+
68+
### Example: Google only
69+
70+
```tsx
71+
<UrAuth
72+
providers={{ google: true, github: false, emailPassword: false }}
73+
/>
74+
```
75+
76+
### Example: Disable all methods
77+
78+
```tsx
79+
<UrAuth providers={{ google: false, github: false, emailPassword: false }} />
80+
```
81+
82+
This renders the built-in `No authentication methods are enabled for this screen.` message.
83+
84+
### `enableEmailPassword` interaction
85+
86+
- `enableEmailPassword` is a shorthand global toggle.
87+
- When `providers` is an object and includes `emailPassword`, that object value takes precedence.
88+
- If `providers.emailPassword` is omitted, `enableEmailPassword` is used.
89+
90+
## `colors` theme customization
91+
92+
Use `colors` to override theme tokens:
93+
94+
```ts
95+
type AuthColors = {
96+
background: string;
97+
surface: string;
98+
text: string;
99+
textMuted: string;
100+
border: string;
101+
inputBackground: string;
102+
primary: string;
103+
primaryColor?: string; // alias for primary button color
104+
primaryText: string;
105+
footerBackground: string;
106+
dividerText: string;
107+
socialButtonBackground: string;
108+
};
109+
```
110+
111+
Set a custom brand color on the primary sign-in button:
112+
113+
```tsx
114+
<UrAuth colors={{ primaryColor: '#6366f1' }} />
115+
```
116+
117+
If both `colors.primaryColor` and `branding.primaryColor` are provided, `branding.primaryColor` takes precedence.
118+
119+
## `branding` white-label options
120+
121+
```ts
122+
type AuthBranding = {
123+
brandName?: string;
124+
appName?: string;
125+
title?: string;
126+
subtitle?: string;
127+
logo?: React.ReactNode | string; // URL string or custom React node
128+
logoUrl?: string; // URL alias
129+
primaryColor?: string;
130+
};
131+
```
132+
133+
Example:
134+
135+
```tsx
136+
<UrAuth
137+
branding={{
138+
appName: 'Acme',
139+
logoUrl: 'https://acme.com/logo.png',
140+
subtitle: 'Secure access for your team',
141+
}}
142+
/>
143+
```
144+
145+
## `labels` text overrides (with aliases)
146+
147+
Supported label keys:
148+
149+
- Tabs: `loginTab` (`signInTab` alias), `signupTab` (`signUpTab` alias)
150+
- Titles: `loginTitle` (`signInTitle` alias), `signupTitle` (`signUpTitle` alias), `forgotTitle`, `resetTitle`, `forgotSubtitle`, `resetSubtitle`
151+
- Buttons: `loginButton` (`signInButton` alias), `signupButton` (`signUpButton` alias), `forgotButton`, `resetButton`, `googleButton`, `githubButton`
152+
- Field labels/placeholders: `emailLabel`, `emailPlaceholder`, `passwordLabel`, `passwordPlaceholder`, `nameLabel`, `namePlaceholder`, `otpLabel`, `otpPlaceholder`
153+
- Footer/misc: `forgotPasswordLink`, `socialDivider`, `footerSigninPrompt`, `footerSignupPrompt`, `footerForgotPrompt`, `noAuthMethods`
154+
155+
Example:
156+
157+
```tsx
158+
<UrAuth
159+
labels={{
160+
signInTitle: 'Welcome back to Acme',
161+
signInButton: 'Continue',
162+
footerSigninPrompt: 'Need an account?',
163+
}}
164+
/>
165+
```
166+
167+
## Full v0.2.0 customization example
168+
169+
```tsx
170+
import { UrAuth, GuestRoute } from '@urbackend/react';
171+
172+
export default function LoginPage() {
173+
return (
174+
<GuestRoute fallback={<div>Loading...</div>} onRedirect={() => (window.location.href = '/dashboard')}>
175+
<UrAuth
176+
providers={{
177+
github: true,
178+
google: true,
179+
emailPassword: true,
180+
}}
181+
enableEmailPassword={true}
182+
theme="light"
183+
colors={{
184+
primaryColor: '#4F46E5',
185+
socialButtonBackground: '#ffffff',
186+
}}
187+
branding={{
188+
appName: 'My Custom App',
189+
logoUrl: 'https://vite.dev/logo.svg',
190+
subtitle: 'Secure authentication',
191+
primaryColor: '#4F46E5',
192+
}}
193+
labels={{
194+
signInTitle: 'Welcome back to Custom App',
195+
signInButton: 'Proceed to App',
196+
signUpButton: 'Create your account',
197+
}}
198+
onSuccess={() => {
199+
// route after successful auth
200+
window.location.href = '/dashboard';
201+
}}
202+
/>
203+
</GuestRoute>
204+
);
205+
}
206+
```
207+
208+
## Migration (v0.1.x → v0.2.0)
209+
210+
- `providers` now also accepts object form: `{ google?, github?, emailPassword? }`
211+
- Existing array usage (`['google', 'github']`) still works
212+
- No breaking API changes otherwise
37213

38214
## Behavior
39215

sdks/urbackend-react/CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Changelog
2+
3+
All notable changes to `@urbackend/react` are documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this package adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [v0.2.0] - 2026-06-13
9+
10+
### Added
11+
- Expanded `<UrAuth>` customization with object-form `providers` config (`google`, `github`, `emailPassword`)
12+
- Added `enableEmailPassword` shorthand toggle support
13+
- Added customizable `colors`, `branding`, and `labels` props for theme/copy overrides
14+
- Added label alias support (for example: `signInTitle`/`loginTitle`, `signInButton`/`loginButton`)
15+
- Added configurable branding logo URL support (`branding.logoUrl` alias)
16+
17+
### Changed
18+
- Internal theme typing for `<UrAuth>` uses `ThemeMode` while keeping public values as `'light' | 'dark'`
19+
- Defaults remain backward compatible with v0.1.x when new props are omitted
20+

sdks/urbackend-react/src/components/UrAuth.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ interface AuthColors {
1313
border: string;
1414
inputBackground: string;
1515
primary: string;
16+
primaryColor?: string;
1617
primaryText: string;
1718
footerBackground: string;
1819
dividerText: string;
@@ -25,6 +26,7 @@ interface AuthBranding {
2526
title?: string;
2627
subtitle?: string;
2728
logo?: React.ReactNode | string;
29+
logoUrl?: string;
2830
primaryColor?: string;
2931
}
3032

@@ -200,7 +202,7 @@ export const UrAuth: React.FC<UrAuthProps> = ({
200202
};
201203

202204
const themeColors = { ...defaultThemeColors[theme], ...colors };
203-
const primaryColor = branding?.primaryColor || themeColors.primary;
205+
const primaryColor = branding?.primaryColor || colors?.primaryColor || themeColors.primary;
204206
const secondStopColor = adjustColor(primaryColor, -15);
205207

206208
let isGoogleEnabled = true;
@@ -222,6 +224,7 @@ export const UrAuth: React.FC<UrAuthProps> = ({
222224
const hasSocialAuth = isGoogleEnabled || isGithubEnabled;
223225
const brandName = branding?.brandName || branding?.appName || branding?.title || 'urBackend';
224226
const headerTitle = branding?.title || brandName;
227+
const brandingLogo = branding?.logo ?? branding?.logoUrl;
225228
const headerSubtitle = branding?.subtitle || (mode === 'signin'
226229
? text.loginTitle
227230
: mode === 'signup'
@@ -524,15 +527,15 @@ export const UrAuth: React.FC<UrAuthProps> = ({
524527
)}
525528

526529
<div style={styles.body}>
527-
{(branding?.logo || branding?.brandName || branding?.appName || branding?.title || branding?.subtitle || headerTitle || headerSubtitle) && (
530+
{(brandingLogo || branding?.brandName || branding?.appName || branding?.title || branding?.subtitle || headerTitle || headerSubtitle) && (
528531
<div style={styles.header}>
529532
<div style={styles.brandRow}>
530-
{branding?.logo ? (
533+
{brandingLogo ? (
531534
<div style={styles.brandLogo}>
532-
{typeof branding.logo === 'string' ? (
533-
<img src={branding.logo} alt={brandName} style={{ width: '100%', height: '100%', objectFit: 'contain' }} />
535+
{typeof brandingLogo === 'string' ? (
536+
<img src={brandingLogo} alt={brandName} style={{ width: '100%', height: '100%', objectFit: 'contain' }} />
534537
) : (
535-
branding.logo
538+
brandingLogo
536539
)}
537540
</div>
538541
) : (

sdks/urbackend-react/tests/UrAuth.test.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ describe('UrAuth Component', () => {
9494
expect(primaryButton.style.background).toContain('#4F46E5');
9595
});
9696

97+
it('applies custom primary color from colors.primaryColor', () => {
98+
render(<UrAuth colors={{ primaryColor: '#6366f1' }} />);
99+
const primaryButton = screen.getByRole('button', { name: 'Log In' });
100+
expect(primaryButton.style.background).toContain('#6366f1');
101+
});
102+
97103
it('hides email/password form when disabled via providers object', () => {
98104
render(<UrAuth providers={{ emailPassword: false, google: true }} />);
99105
expect(screen.queryByPlaceholderText('Enter your email address')).not.toBeInTheDocument();
@@ -103,14 +109,14 @@ describe('UrAuth Component', () => {
103109
});
104110

105111
it('only shows GitHub login when configured via providers object', () => {
106-
render(<UrAuth providers={{ github: true }} />);
112+
render(<UrAuth providers={{ github: true, emailPassword: false }} />);
107113
expect(screen.queryByPlaceholderText('Enter your email address')).not.toBeInTheDocument();
108114
expect(screen.getByText('Continue with GitHub')).toBeInTheDocument();
109115
expect(screen.queryByText('Continue with Google')).not.toBeInTheDocument();
110116
});
111117

112118
it('displays message when all authentication methods are disabled', () => {
113-
render(<UrAuth providers={{}} />);
119+
render(<UrAuth providers={{ google: false, github: false, emailPassword: false }} />);
114120
expect(screen.getByText('No authentication methods are enabled for this screen.')).toBeInTheDocument();
115121
});
116122

@@ -130,4 +136,13 @@ describe('UrAuth Component', () => {
130136
expect(logoImg).toBeInTheDocument();
131137
expect(logoImg?.getAttribute('src')).toBe('/assets/logo.png');
132138
});
139+
140+
it('supports logoUrl branding alias', () => {
141+
render(
142+
<UrAuth branding={{ appName: 'My Custom App', logoUrl: '/assets/logo-url.png' }} />
143+
);
144+
const logoImg = screen.getByRole('img', { name: 'My Custom App' });
145+
expect(logoImg).toBeInTheDocument();
146+
expect(logoImg.getAttribute('src')).toBe('/assets/logo-url.png');
147+
});
133148
});

0 commit comments

Comments
 (0)