diff --git a/docs/data/toolpad/core/components/sign-in-page/BrandingSignInPage.js b/docs/data/toolpad/core/components/sign-in-page/BrandingSignInPage.js
index c44cd5f38ef..6f63933ad51 100644
--- a/docs/data/toolpad/core/components/sign-in-page/BrandingSignInPage.js
+++ b/docs/data/toolpad/core/components/sign-in-page/BrandingSignInPage.js
@@ -3,11 +3,7 @@ import { AppProvider } from '@toolpad/core/AppProvider';
import { SignInPage } from '@toolpad/core/SignInPage';
import { useTheme } from '@mui/material/styles';
-const providers = [
- { id: 'github', name: 'GitHub' },
- { id: 'google', name: 'Google' },
-];
-
+const providers = [{ id: 'credentials', name: 'Credentials' }];
// preview-start
const BRANDING = {
logo: (
diff --git a/docs/data/toolpad/core/components/sign-in-page/BrandingSignInPage.tsx b/docs/data/toolpad/core/components/sign-in-page/BrandingSignInPage.tsx
index a21cbf4b8d3..8b54d4fcc3e 100644
--- a/docs/data/toolpad/core/components/sign-in-page/BrandingSignInPage.tsx
+++ b/docs/data/toolpad/core/components/sign-in-page/BrandingSignInPage.tsx
@@ -3,10 +3,7 @@ import { AppProvider } from '@toolpad/core/AppProvider';
import { SignInPage, type AuthProvider } from '@toolpad/core/SignInPage';
import { useTheme } from '@mui/material/styles';
-const providers = [
- { id: 'github', name: 'GitHub' },
- { id: 'google', name: 'Google' },
-];
+const providers = [{ id: 'credentials', name: 'Credentials' }];
// preview-start
const BRANDING = {
logo: (
diff --git a/docs/data/toolpad/core/components/sign-in-page/SlotsSignIn.js b/docs/data/toolpad/core/components/sign-in-page/SlotsSignIn.js
index 5173ec90edc..9b75f82997b 100644
--- a/docs/data/toolpad/core/components/sign-in-page/SlotsSignIn.js
+++ b/docs/data/toolpad/core/components/sign-in-page/SlotsSignIn.js
@@ -7,6 +7,7 @@ import {
TextField,
InputAdornment,
Link,
+ Alert,
IconButton,
} from '@mui/material';
import AccountCircle from '@mui/icons-material/AccountCircle';
@@ -95,7 +96,7 @@ function CustomButton() {
fullWidth
sx={{ my: 2 }}
>
- Sign In
+ Log In
);
}
@@ -116,6 +117,18 @@ function ForgotPasswordLink() {
);
}
+function Title() {
+ return
Login
;
+}
+
+function Subtitle() {
+ return (
+
+ We are investigating an ongoing outage.
+
+ );
+}
+
export default function SlotsSignIn() {
const theme = useTheme();
return (
@@ -123,10 +136,12 @@ export default function SlotsSignIn() {
alert(
- `Signing in with "${provider.name}" and credentials: ${formData.get('email')}, ${formData.get('password')}`,
+ `Logging in with "${provider.name}" and credentials: ${formData.get('email')}, ${formData.get('password')}`,
)
}
slots={{
+ title: Title,
+ subtitle: Subtitle,
emailField: CustomEmailField,
passwordField: CustomPasswordField,
submitButton: CustomButton,
diff --git a/docs/data/toolpad/core/components/sign-in-page/SlotsSignIn.tsx b/docs/data/toolpad/core/components/sign-in-page/SlotsSignIn.tsx
index fdea6fc5db8..04472072364 100644
--- a/docs/data/toolpad/core/components/sign-in-page/SlotsSignIn.tsx
+++ b/docs/data/toolpad/core/components/sign-in-page/SlotsSignIn.tsx
@@ -7,6 +7,7 @@ import {
TextField,
InputAdornment,
Link,
+ Alert,
IconButton,
} from '@mui/material';
import AccountCircle from '@mui/icons-material/AccountCircle';
@@ -95,7 +96,7 @@ function CustomButton() {
fullWidth
sx={{ my: 2 }}
>
- Sign In
+ Log In
);
}
@@ -116,6 +117,18 @@ function ForgotPasswordLink() {
);
}
+function Title() {
+ return Login
;
+}
+
+function Subtitle() {
+ return (
+
+ We are investigating an ongoing outage.
+
+ );
+}
+
export default function SlotsSignIn() {
const theme = useTheme();
return (
@@ -123,10 +136,12 @@ export default function SlotsSignIn() {
alert(
- `Signing in with "${provider.name}" and credentials: ${formData.get('email')}, ${formData.get('password')}`,
+ `Logging in with "${provider.name}" and credentials: ${formData.get('email')}, ${formData.get('password')}`,
)
}
slots={{
+ title: Title,
+ subtitle: Subtitle,
emailField: CustomEmailField,
passwordField: CustomPasswordField,
submitButton: CustomButton,
diff --git a/docs/data/toolpad/core/components/sign-in-page/SlotsSignIn.tsx.preview b/docs/data/toolpad/core/components/sign-in-page/SlotsSignIn.tsx.preview
deleted file mode 100644
index 136df8f726a..00000000000
--- a/docs/data/toolpad/core/components/sign-in-page/SlotsSignIn.tsx.preview
+++ /dev/null
@@ -1,15 +0,0 @@
-
- alert(
- `Signing in with "${provider.name}" and credentials: ${formData.get('email')}, ${formData.get('password')}`,
- )
- }
- slots={{
- emailField: CustomEmailField,
- passwordField: CustomPasswordField,
- submitButton: CustomButton,
- signUpLink: SignUpLink,
- forgotPasswordLink: ForgotPasswordLink,
- }}
- providers={providers}
-/>
\ No newline at end of file
diff --git a/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.js b/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.js
index deb2dd12dd8..824dda0beff 100644
--- a/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.js
+++ b/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.js
@@ -3,7 +3,7 @@ import { AppProvider } from '@toolpad/core/AppProvider';
import { SignInPage } from '@toolpad/core/SignInPage';
import { createTheme } from '@mui/material/styles';
import { useColorSchemeShim } from 'docs/src/modules/components/ThemeContext';
-import { getDesignTokens } from './brandingTheme';
+import { getDesignTokens, inputsCustomizations } from './customTheme';
const providers = [
{ id: 'github', name: 'GitHub' },
@@ -32,6 +32,9 @@ export default function ThemeSignInPage() {
...brandingDesignTokens.palette,
mode: calculatedMode,
},
+ components: {
+ ...inputsCustomizations,
+ },
});
// preview-end
diff --git a/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.tsx b/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.tsx
index 797983ef77a..7d8ef141527 100644
--- a/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.tsx
+++ b/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.tsx
@@ -3,7 +3,7 @@ import { AppProvider } from '@toolpad/core/AppProvider';
import { SignInPage, type AuthProvider } from '@toolpad/core/SignInPage';
import { createTheme } from '@mui/material/styles';
import { useColorSchemeShim } from 'docs/src/modules/components/ThemeContext';
-import { getDesignTokens } from './brandingTheme';
+import { getDesignTokens, inputsCustomizations } from './customTheme';
const providers = [
{ id: 'github', name: 'GitHub' },
@@ -32,6 +32,9 @@ export default function ThemeSignInPage() {
...brandingDesignTokens.palette,
mode: calculatedMode,
},
+ components: {
+ ...inputsCustomizations,
+ },
});
// preview-end
diff --git a/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.tsx.preview b/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.tsx.preview
index 01eecbdf4fe..b654f182518 100644
--- a/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.tsx.preview
+++ b/docs/data/toolpad/core/components/sign-in-page/ThemeSignInPage.tsx.preview
@@ -4,6 +4,9 @@ const THEME = createTheme({
...brandingDesignTokens.palette,
mode: calculatedMode,
},
+ components: {
+ ...inputsCustomizations,
+ },
});
// ...
diff --git a/docs/data/toolpad/core/components/sign-in-page/brandingTheme.js b/docs/data/toolpad/core/components/sign-in-page/brandingTheme.js
deleted file mode 100644
index 3c4e67a9552..00000000000
--- a/docs/data/toolpad/core/components/sign-in-page/brandingTheme.js
+++ /dev/null
@@ -1,242 +0,0 @@
-import { createTheme, alpha } from '@mui/material/styles';
-
-const defaultTheme = createTheme();
-
-const blue = {
- 50: '#F0F7FF',
- 100: '#C2E0FF',
- 200: '#99CCF3',
- 300: '#66B2FF',
- 400: '#3399FF',
- main: '#007FFF',
- 500: '#007FFF',
- 600: '#0072E5', // vs blueDark 900: WCAG 4.6 AAA (large), APCA 36 Not for reading text
- 700: '#0059B2',
- 800: '#004C99',
- 900: '#003A75',
-};
-const blueDark = {
- 50: '#E2EDF8',
- 100: '#CEE0F3',
- 200: '#91B9E3',
- 300: '#5090D3',
- main: '#5090D3',
- 400: '#265D97',
- 500: '#1E4976',
- 600: '#173A5E',
- 700: '#132F4C', // contrast 13.64:1
- 800: '#001E3C',
- 900: '#0A1929',
-};
-const grey = {
- 50: '#F3F6F9',
- 100: '#E7EBF0',
- 200: '#E0E3E7',
- 300: '#CDD2D7', // vs blueDark 900: WCAG 11.6 AAA, APCA 78 Best for text
- 400: '#B2BAC2', // vs blueDark 900: WCAG 9 AAA, APCA 63.3 Ok for text
- 500: '#A0AAB4', // vs blueDark 900: WCAG 7.5 AAA, APCA 54.3 Only for large text
- 600: '#6F7E8C', // vs white bg: WCAG 4.1 AA, APCA 68.7 Ok for text
- 700: '#3E5060', // vs white bg: WCAG 8.3 AAA, APCA 88.7 Best for text
- 800: '#2D3843', // vs white bg: WCAG 11.9 AAA, APCA 97.3 Best for text
- 900: '#1A2027',
-};
-
-const systemFont = [
- '-apple-system',
- 'BlinkMacSystemFont',
- '"Segoe UI"',
- 'Roboto',
- '"Helvetica Neue"',
- 'Arial',
- 'sans-serif',
- '"Apple Color Emoji"',
- '"Segoe UI Emoji"',
- '"Segoe UI Symbol"',
-];
-
-export const getDesignTokens = (mode) => ({
- palette: {
- primary: {
- ...blue,
- ...(mode === 'dark' && {
- main: blue[400],
- }),
- },
- divider: mode === 'dark' ? alpha(blue[100], 0.08) : grey[100],
- primaryDark: blueDark,
- mode,
- ...(mode === 'dark' && {
- background: {
- default: blueDark[800],
- paper: blueDark[900],
- },
- }),
- common: {
- black: '#1D1D1D',
- },
- text: {
- ...(mode === 'light' && {
- primary: grey[900],
- secondary: grey[700],
- }),
- ...(mode === 'dark' && {
- primary: '#fff',
- secondary: grey[400],
- }),
- },
- grey: {
- ...(mode === 'light' && {
- main: grey[100],
- contrastText: grey[600],
- }),
- ...(mode === 'dark' && {
- main: blueDark[700],
- contrastText: grey[600],
- }),
- },
- error: {
- 50: '#FFF0F1',
- 100: '#FFDBDE',
- 200: '#FFBDC2',
- 300: '#FF99A2',
- 400: '#FF7A86',
- 500: '#FF505F',
- main: '#EB0014', // contrast 4.63:1
- 600: '#EB0014',
- 700: '#C70011',
- 800: '#94000D',
- 900: '#570007',
- },
- success: {
- 50: '#E9FBF0',
- 100: '#C6F6D9',
- 200: '#9AEFBC',
- 300: '#6AE79C',
- 400: '#3EE07F',
- 500: '#21CC66',
- 600: '#1DB45A',
- ...(mode === 'light' && {
- main: '#1AA251', // contrast 3.31:1
- }),
- ...(mode === 'dark' && {
- main: '#1DB45A', // contrast 6.17:1 (blueDark.800)
- }),
- 700: '#1AA251',
- 800: '#178D46',
- 900: '#0F5C2E',
- },
- warning: {
- 50: '#FFF9EB',
- 100: '#FFF3C1',
- 200: '#FFECA1',
- 300: '#FFDC48', // vs blueDark900: WCAG 10.4 AAA, APCA 72 Ok for text
- 400: '#F4C000', // vs blueDark900: WCAG 6.4 AA normal, APCA 48 Only large text
- 500: '#DEA500', // vs blueDark900: WCAG 8 AAA normal, APCA 58 Only large text
- main: '#DEA500',
- 600: '#D18E00', // vs blueDark900: WCAG 6.4 AA normal, APCA 48 Only large text
- 700: '#AB6800', // vs white bg: WCAG 4.4 AA large, APCA 71 Ok for text
- 800: '#8C5800', // vs white bg: WCAG 5.9 AAA large, APCA 80 Best for text
- 900: '#5A3600', // vs white bg: WCAG 10.7 AAA, APCA 95 Best for text
- },
- action: {
- ...(mode === 'dark' && {
- hoverOpacity: 0.08,
- active: grey[700],
- disabled: grey[200],
- }),
- ...(mode === 'light' && {
- hoverOpacity: 0.04,
- active: grey[700],
- disabled: alpha(grey[700], 0.3),
- }),
- },
- },
- shape: {
- borderRadius: 10,
- },
- spacing: 10,
- typography: {
- fontFamily: ['"IBM Plex Sans"', ...systemFont].join(','),
- fontFamilyCode: [
- 'Consolas',
- 'Menlo',
- 'Monaco',
- 'Andale Mono',
- 'Ubuntu Mono',
- 'monospace',
- ].join(','),
- fontFamilyTagline: ['"PlusJakartaSans-ExtraBold"', ...systemFont].join(','),
- fontFamilySystem: systemFont.join(','),
- fontWeightSemiBold: 600,
- fontWeightExtraBold: 800,
- h1: {
- fontFamily: ['"PlusJakartaSans-ExtraBold"', ...systemFont].join(','),
- fontSize: 'clamp(2.625rem, 1.2857rem + 3.5714vw, 4rem)',
- fontWeight: 800,
- lineHeight: 78 / 70,
- ...(mode === 'light' && {
- color: blueDark[900],
- }),
- },
- h2: {
- fontFamily: ['"PlusJakartaSans-ExtraBold"', ...systemFont].join(','),
- fontSize: 'clamp(1.5rem, 0.9643rem + 1.4286vw, 2.25rem)',
- fontWeight: 800,
- lineHeight: 44 / 36,
- color: mode === 'dark' ? grey[100] : blueDark[700],
- },
- h3: {
- fontFamily: ['"PlusJakartaSans-Bold"', ...systemFont].join(','),
- fontSize: defaultTheme.typography.pxToRem(36),
- lineHeight: 44 / 36,
- letterSpacing: 0.2,
- },
- h4: {
- fontFamily: ['"PlusJakartaSans-Bold"', ...systemFont].join(','),
- fontSize: defaultTheme.typography.pxToRem(28),
- lineHeight: 42 / 28,
- letterSpacing: 0.2,
- },
- h5: {
- fontFamily: ['"PlusJakartaSans-Bold"', ...systemFont].join(','),
- fontSize: defaultTheme.typography.pxToRem(24),
- lineHeight: 36 / 24,
- letterSpacing: 0.1,
- color: mode === 'dark' ? blue[300] : blue.main,
- },
- h6: {
- fontSize: defaultTheme.typography.pxToRem(20),
- lineHeight: 30 / 20,
- },
- button: {
- textTransform: 'initial',
- fontWeight: 700,
- letterSpacing: 0,
- },
- subtitle1: {
- fontSize: defaultTheme.typography.pxToRem(18),
- lineHeight: 24 / 18,
- letterSpacing: 0,
- fontWeight: 500,
- },
- body1: {
- fontSize: defaultTheme.typography.pxToRem(16), // 16px
- lineHeight: 24 / 16,
- letterSpacing: 0,
- },
- body2: {
- fontSize: defaultTheme.typography.pxToRem(14), // 14px
- lineHeight: 21 / 14,
- letterSpacing: 0,
- },
- caption: {
- fontSize: defaultTheme.typography.pxToRem(12), // 12px
- lineHeight: 18 / 12,
- letterSpacing: 0,
- fontWeight: 700,
- },
- allVariants: {
- scrollMarginTop: 'calc(var(--MuiDocs-header-height) + 32px)',
- },
- },
-});
diff --git a/docs/data/toolpad/core/components/sign-in-page/brandingTheme.ts b/docs/data/toolpad/core/components/sign-in-page/brandingTheme.ts
deleted file mode 100644
index 4fffbe86298..00000000000
--- a/docs/data/toolpad/core/components/sign-in-page/brandingTheme.ts
+++ /dev/null
@@ -1,243 +0,0 @@
-import { createTheme, ThemeOptions, alpha } from '@mui/material/styles';
-
-const defaultTheme = createTheme();
-
-const blue = {
- 50: '#F0F7FF',
- 100: '#C2E0FF',
- 200: '#99CCF3',
- 300: '#66B2FF',
- 400: '#3399FF',
- main: '#007FFF',
- 500: '#007FFF',
- 600: '#0072E5', // vs blueDark 900: WCAG 4.6 AAA (large), APCA 36 Not for reading text
- 700: '#0059B2',
- 800: '#004C99',
- 900: '#003A75',
-};
-const blueDark = {
- 50: '#E2EDF8',
- 100: '#CEE0F3',
- 200: '#91B9E3',
- 300: '#5090D3',
- main: '#5090D3',
- 400: '#265D97',
- 500: '#1E4976',
- 600: '#173A5E',
- 700: '#132F4C', // contrast 13.64:1
- 800: '#001E3C',
- 900: '#0A1929',
-};
-const grey = {
- 50: '#F3F6F9',
- 100: '#E7EBF0',
- 200: '#E0E3E7',
- 300: '#CDD2D7', // vs blueDark 900: WCAG 11.6 AAA, APCA 78 Best for text
- 400: '#B2BAC2', // vs blueDark 900: WCAG 9 AAA, APCA 63.3 Ok for text
- 500: '#A0AAB4', // vs blueDark 900: WCAG 7.5 AAA, APCA 54.3 Only for large text
- 600: '#6F7E8C', // vs white bg: WCAG 4.1 AA, APCA 68.7 Ok for text
- 700: '#3E5060', // vs white bg: WCAG 8.3 AAA, APCA 88.7 Best for text
- 800: '#2D3843', // vs white bg: WCAG 11.9 AAA, APCA 97.3 Best for text
- 900: '#1A2027',
-};
-
-const systemFont = [
- '-apple-system',
- 'BlinkMacSystemFont',
- '"Segoe UI"',
- 'Roboto',
- '"Helvetica Neue"',
- 'Arial',
- 'sans-serif',
- '"Apple Color Emoji"',
- '"Segoe UI Emoji"',
- '"Segoe UI Symbol"',
-];
-
-export const getDesignTokens = (mode: 'light' | 'dark') =>
- ({
- palette: {
- primary: {
- ...blue,
- ...(mode === 'dark' && {
- main: blue[400],
- }),
- },
- divider: mode === 'dark' ? alpha(blue[100], 0.08) : grey[100],
- primaryDark: blueDark,
- mode,
- ...(mode === 'dark' && {
- background: {
- default: blueDark[800],
- paper: blueDark[900],
- },
- }),
- common: {
- black: '#1D1D1D',
- },
- text: {
- ...(mode === 'light' && {
- primary: grey[900],
- secondary: grey[700],
- }),
- ...(mode === 'dark' && {
- primary: '#fff',
- secondary: grey[400],
- }),
- },
- grey: {
- ...(mode === 'light' && {
- main: grey[100],
- contrastText: grey[600],
- }),
- ...(mode === 'dark' && {
- main: blueDark[700],
- contrastText: grey[600],
- }),
- },
- error: {
- 50: '#FFF0F1',
- 100: '#FFDBDE',
- 200: '#FFBDC2',
- 300: '#FF99A2',
- 400: '#FF7A86',
- 500: '#FF505F',
- main: '#EB0014', // contrast 4.63:1
- 600: '#EB0014',
- 700: '#C70011',
- 800: '#94000D',
- 900: '#570007',
- },
- success: {
- 50: '#E9FBF0',
- 100: '#C6F6D9',
- 200: '#9AEFBC',
- 300: '#6AE79C',
- 400: '#3EE07F',
- 500: '#21CC66',
- 600: '#1DB45A',
- ...(mode === 'light' && {
- main: '#1AA251', // contrast 3.31:1
- }),
- ...(mode === 'dark' && {
- main: '#1DB45A', // contrast 6.17:1 (blueDark.800)
- }),
- 700: '#1AA251',
- 800: '#178D46',
- 900: '#0F5C2E',
- },
- warning: {
- 50: '#FFF9EB',
- 100: '#FFF3C1',
- 200: '#FFECA1',
- 300: '#FFDC48', // vs blueDark900: WCAG 10.4 AAA, APCA 72 Ok for text
- 400: '#F4C000', // vs blueDark900: WCAG 6.4 AA normal, APCA 48 Only large text
- 500: '#DEA500', // vs blueDark900: WCAG 8 AAA normal, APCA 58 Only large text
- main: '#DEA500',
- 600: '#D18E00', // vs blueDark900: WCAG 6.4 AA normal, APCA 48 Only large text
- 700: '#AB6800', // vs white bg: WCAG 4.4 AA large, APCA 71 Ok for text
- 800: '#8C5800', // vs white bg: WCAG 5.9 AAA large, APCA 80 Best for text
- 900: '#5A3600', // vs white bg: WCAG 10.7 AAA, APCA 95 Best for text
- },
- action: {
- ...(mode === 'dark' && {
- hoverOpacity: 0.08,
- active: grey[700],
- disabled: grey[200],
- }),
- ...(mode === 'light' && {
- hoverOpacity: 0.04,
- active: grey[700],
- disabled: alpha(grey[700], 0.3),
- }),
- },
- },
- shape: {
- borderRadius: 10,
- },
- spacing: 10,
- typography: {
- fontFamily: ['"IBM Plex Sans"', ...systemFont].join(','),
- fontFamilyCode: [
- 'Consolas',
- 'Menlo',
- 'Monaco',
- 'Andale Mono',
- 'Ubuntu Mono',
- 'monospace',
- ].join(','),
- fontFamilyTagline: ['"PlusJakartaSans-ExtraBold"', ...systemFont].join(','),
- fontFamilySystem: systemFont.join(','),
- fontWeightSemiBold: 600,
- fontWeightExtraBold: 800,
- h1: {
- fontFamily: ['"PlusJakartaSans-ExtraBold"', ...systemFont].join(','),
- fontSize: 'clamp(2.625rem, 1.2857rem + 3.5714vw, 4rem)',
- fontWeight: 800,
- lineHeight: 78 / 70,
- ...(mode === 'light' && {
- color: blueDark[900],
- }),
- },
- h2: {
- fontFamily: ['"PlusJakartaSans-ExtraBold"', ...systemFont].join(','),
- fontSize: 'clamp(1.5rem, 0.9643rem + 1.4286vw, 2.25rem)',
- fontWeight: 800,
- lineHeight: 44 / 36,
- color: mode === 'dark' ? grey[100] : blueDark[700],
- },
- h3: {
- fontFamily: ['"PlusJakartaSans-Bold"', ...systemFont].join(','),
- fontSize: defaultTheme.typography.pxToRem(36),
- lineHeight: 44 / 36,
- letterSpacing: 0.2,
- },
- h4: {
- fontFamily: ['"PlusJakartaSans-Bold"', ...systemFont].join(','),
- fontSize: defaultTheme.typography.pxToRem(28),
- lineHeight: 42 / 28,
- letterSpacing: 0.2,
- },
- h5: {
- fontFamily: ['"PlusJakartaSans-Bold"', ...systemFont].join(','),
- fontSize: defaultTheme.typography.pxToRem(24),
- lineHeight: 36 / 24,
- letterSpacing: 0.1,
- color: mode === 'dark' ? blue[300] : blue.main,
- },
- h6: {
- fontSize: defaultTheme.typography.pxToRem(20),
- lineHeight: 30 / 20,
- },
- button: {
- textTransform: 'initial',
- fontWeight: 700,
- letterSpacing: 0,
- },
- subtitle1: {
- fontSize: defaultTheme.typography.pxToRem(18),
- lineHeight: 24 / 18,
- letterSpacing: 0,
- fontWeight: 500,
- },
- body1: {
- fontSize: defaultTheme.typography.pxToRem(16), // 16px
- lineHeight: 24 / 16,
- letterSpacing: 0,
- },
- body2: {
- fontSize: defaultTheme.typography.pxToRem(14), // 14px
- lineHeight: 21 / 14,
- letterSpacing: 0,
- },
- caption: {
- fontSize: defaultTheme.typography.pxToRem(12), // 12px
- lineHeight: 18 / 12,
- letterSpacing: 0,
- fontWeight: 700,
- },
- allVariants: {
- scrollMarginTop: 'calc(var(--MuiDocs-header-height) + 32px)',
- },
- },
- }) as ThemeOptions;
diff --git a/docs/data/toolpad/core/components/sign-in-page/customTheme.js b/docs/data/toolpad/core/components/sign-in-page/customTheme.js
new file mode 100644
index 00000000000..4aff672b14e
--- /dev/null
+++ b/docs/data/toolpad/core/components/sign-in-page/customTheme.js
@@ -0,0 +1,552 @@
+import * as React from 'react';
+
+import { alpha, createTheme } from '@mui/material/styles';
+import { outlinedInputClasses } from '@mui/material/OutlinedInput';
+import CheckBoxOutlineBlankRoundedIcon from '@mui/icons-material/CheckBoxOutlineBlankRounded';
+import CheckRoundedIcon from '@mui/icons-material/CheckRounded';
+import RemoveRoundedIcon from '@mui/icons-material/RemoveRounded';
+
+const defaultTheme = createTheme();
+
+const customShadows = [...defaultTheme.shadows];
+
+export const brand = {
+ 50: 'hsl(210, 100%, 95%)',
+ 100: 'hsl(210, 100%, 92%)',
+ 200: 'hsl(210, 100%, 80%)',
+ 300: 'hsl(210, 100%, 65%)',
+ 400: 'hsl(210, 98%, 48%)',
+ 500: 'hsl(210, 98%, 42%)',
+ 600: 'hsl(210, 98%, 55%)',
+ 700: 'hsl(210, 100%, 35%)',
+ 800: 'hsl(210, 100%, 16%)',
+ 900: 'hsl(210, 100%, 21%)',
+};
+
+export const gray = {
+ 50: 'hsl(220, 35%, 97%)',
+ 100: 'hsl(220, 30%, 94%)',
+ 200: 'hsl(220, 20%, 88%)',
+ 300: 'hsl(220, 20%, 80%)',
+ 400: 'hsl(220, 20%, 65%)',
+ 500: 'hsl(220, 20%, 42%)',
+ 600: 'hsl(220, 20%, 35%)',
+ 700: 'hsl(220, 20%, 25%)',
+ 800: 'hsl(220, 30%, 6%)',
+ 900: 'hsl(220, 35%, 3%)',
+};
+
+export const green = {
+ 50: 'hsl(120, 80%, 98%)',
+ 100: 'hsl(120, 75%, 94%)',
+ 200: 'hsl(120, 75%, 87%)',
+ 300: 'hsl(120, 61%, 77%)',
+ 400: 'hsl(120, 44%, 53%)',
+ 500: 'hsl(120, 59%, 30%)',
+ 600: 'hsl(120, 70%, 25%)',
+ 700: 'hsl(120, 75%, 16%)',
+ 800: 'hsl(120, 84%, 10%)',
+ 900: 'hsl(120, 87%, 6%)',
+};
+
+export const orange = {
+ 50: 'hsl(45, 100%, 97%)',
+ 100: 'hsl(45, 92%, 90%)',
+ 200: 'hsl(45, 94%, 80%)',
+ 300: 'hsl(45, 90%, 65%)',
+ 400: 'hsl(45, 90%, 40%)',
+ 500: 'hsl(45, 90%, 35%)',
+ 600: 'hsl(45, 91%, 25%)',
+ 700: 'hsl(45, 94%, 20%)',
+ 800: 'hsl(45, 95%, 16%)',
+ 900: 'hsl(45, 93%, 12%)',
+};
+
+export const red = {
+ 50: 'hsl(0, 100%, 97%)',
+ 100: 'hsl(0, 92%, 90%)',
+ 200: 'hsl(0, 94%, 80%)',
+ 300: 'hsl(0, 90%, 65%)',
+ 400: 'hsl(0, 90%, 40%)',
+ 500: 'hsl(0, 90%, 30%)',
+ 600: 'hsl(0, 91%, 25%)',
+ 700: 'hsl(0, 94%, 18%)',
+ 800: 'hsl(0, 95%, 12%)',
+ 900: 'hsl(0, 93%, 6%)',
+};
+
+export const getDesignTokens = (mode) => {
+ customShadows[1] =
+ mode === 'dark'
+ ? 'hsla(220, 30%, 5%, 0.7) 0px 4px 16px 0px, hsla(220, 25%, 10%, 0.8) 0px 8px 16px -5px'
+ : 'hsla(220, 30%, 5%, 0.07) 0px 4px 16px 0px, hsla(220, 25%, 10%, 0.07) 0px 8px 16px -5px';
+
+ customShadows[4] =
+ '0px 5px 15px rgba(9, 11, 17, 0.05), 0px 15px 35px -5px rgba(19, 23, 32, 0.05)';
+
+ return {
+ palette: {
+ mode,
+ primary: {
+ light: brand[200],
+ main: brand[400],
+ dark: brand[700],
+ contrastText: brand[50],
+ ...(mode === 'dark' && {
+ contrastText: brand[50],
+ light: brand[300],
+ main: brand[400],
+ dark: brand[700],
+ }),
+ },
+ info: {
+ light: brand[100],
+ main: brand[300],
+ dark: brand[600],
+ contrastText: gray[50],
+ ...(mode === 'dark' && {
+ contrastText: brand[300],
+ light: brand[500],
+ main: brand[700],
+ dark: brand[900],
+ }),
+ },
+ warning: {
+ light: orange[300],
+ main: orange[400],
+ dark: orange[800],
+ ...(mode === 'dark' && {
+ light: orange[400],
+ main: orange[500],
+ dark: orange[700],
+ }),
+ },
+ error: {
+ light: red[300],
+ main: red[400],
+ dark: red[800],
+ ...(mode === 'dark' && {
+ light: red[400],
+ main: red[500],
+ dark: red[700],
+ }),
+ },
+ success: {
+ light: green[300],
+ main: green[400],
+ dark: green[800],
+ ...(mode === 'dark' && {
+ light: green[400],
+ main: green[500],
+ dark: green[700],
+ }),
+ },
+ grey: {
+ ...gray,
+ },
+ divider: mode === 'dark' ? alpha(gray[700], 0.6) : alpha(gray[300], 0.4),
+ background: {
+ default: 'hsl(0, 0%, 99%)',
+ paper: 'hsl(220, 35%, 97%)',
+ ...(mode === 'dark' && {
+ default: gray[900],
+ paper: 'hsl(220, 30%, 7%)',
+ }),
+ },
+ text: {
+ primary: gray[800],
+ secondary: gray[600],
+ warning: orange[400],
+ ...(mode === 'dark' && {
+ primary: 'hsl(0, 0%, 100%)',
+ secondary: gray[400],
+ }),
+ },
+ action: {
+ hover: alpha(gray[200], 0.2),
+ selected: `${alpha(gray[200], 0.3)}`,
+ ...(mode === 'dark' && {
+ hover: alpha(gray[600], 0.2),
+ selected: alpha(gray[600], 0.3),
+ }),
+ },
+ },
+ typography: {
+ h1: {
+ fontSize: defaultTheme.typography.pxToRem(48),
+ fontWeight: 600,
+ lineHeight: 1.2,
+ letterSpacing: -0.5,
+ },
+ h2: {
+ fontSize: defaultTheme.typography.pxToRem(36),
+ fontWeight: 600,
+ lineHeight: 1.2,
+ },
+ h3: {
+ fontSize: defaultTheme.typography.pxToRem(30),
+ lineHeight: 1.2,
+ },
+ h4: {
+ fontSize: defaultTheme.typography.pxToRem(24),
+ fontWeight: 600,
+ lineHeight: 1.5,
+ },
+ h5: {
+ fontSize: defaultTheme.typography.pxToRem(20),
+ fontWeight: 600,
+ },
+ h6: {
+ fontSize: defaultTheme.typography.pxToRem(18),
+ fontWeight: 600,
+ },
+ subtitle1: {
+ fontSize: defaultTheme.typography.pxToRem(18),
+ },
+ subtitle2: {
+ fontSize: defaultTheme.typography.pxToRem(14),
+ fontWeight: 500,
+ },
+ body1: {
+ fontSize: defaultTheme.typography.pxToRem(14),
+ },
+ body2: {
+ fontSize: defaultTheme.typography.pxToRem(14),
+ fontWeight: 400,
+ },
+ caption: {
+ fontSize: defaultTheme.typography.pxToRem(12),
+ fontWeight: 400,
+ },
+ },
+ shape: {
+ borderRadius: 8,
+ },
+ shadows: customShadows,
+ };
+};
+
+export const inputsCustomizations = {
+ MuiButtonBase: {
+ defaultProps: {
+ disableTouchRipple: true,
+ disableRipple: true,
+ },
+ styleOverrides: {
+ root: ({ theme }) => ({
+ boxSizing: 'border-box',
+ transition: 'all 100ms ease-in',
+ '&:focus-visible': {
+ outline: `3px solid ${alpha(theme.palette.primary.main, 0.5)}`,
+ outlineOffset: '2px',
+ },
+ }),
+ },
+ },
+ MuiButton: {
+ styleOverrides: {
+ root: ({ theme }) => ({
+ boxShadow: 'none',
+ borderRadius: theme.shape.borderRadius,
+ textTransform: 'none',
+ variants: [
+ {
+ props: {
+ size: 'small',
+ },
+ style: {
+ height: '2.25rem',
+ padding: '8px 12px',
+ },
+ },
+ {
+ props: {
+ size: 'medium',
+ },
+ style: {
+ height: '2.5rem', // 40px
+ },
+ },
+ {
+ props: {
+ color: 'primary',
+ variant: 'contained',
+ },
+ style: {
+ color: 'white',
+ backgroundColor: gray[900],
+ backgroundImage: `linear-gradient(to bottom, ${gray[700]}, ${gray[800]})`,
+ boxShadow: `inset 0 1px 0 ${gray[600]}, inset 0 -1px 0 1px hsl(220, 0%, 0%)`,
+ border: `1px solid ${gray[700]}`,
+ '&:hover': {
+ backgroundImage: 'none',
+ backgroundColor: gray[700],
+ boxShadow: 'none',
+ },
+ '&:active': {
+ backgroundColor: gray[800],
+ },
+ ...theme.applyStyles('dark', {
+ color: 'black',
+ backgroundColor: gray[50],
+ backgroundImage: `linear-gradient(to bottom, ${gray[100]}, ${gray[50]})`,
+ boxShadow: 'inset 0 -1px 0 hsl(220, 30%, 80%)',
+ border: `1px solid ${gray[50]}`,
+ '&:hover': {
+ backgroundImage: 'none',
+ backgroundColor: gray[300],
+ boxShadow: 'none',
+ },
+ '&:active': {
+ backgroundColor: gray[400],
+ },
+ }),
+ },
+ },
+ {
+ props: {
+ color: 'secondary',
+ variant: 'contained',
+ },
+ style: {
+ color: 'white',
+ backgroundColor: brand[300],
+ backgroundImage: `linear-gradient(to bottom, ${alpha(brand[400], 0.8)}, ${brand[500]})`,
+ boxShadow: `inset 0 2px 0 ${alpha(brand[200], 0.2)}, inset 0 -2px 0 ${alpha(brand[700], 0.4)}`,
+ border: `1px solid ${brand[500]}`,
+ '&:hover': {
+ backgroundColor: brand[700],
+ boxShadow: 'none',
+ },
+ '&:active': {
+ backgroundColor: brand[700],
+ backgroundImage: 'none',
+ },
+ },
+ },
+ {
+ props: {
+ variant: 'outlined',
+ },
+ style: {
+ color: theme.palette.text.primary,
+ border: '1px solid',
+ borderColor: gray[200],
+ backgroundColor: alpha(gray[50], 0.3),
+ '&:hover': {
+ backgroundColor: gray[100],
+ borderColor: gray[300],
+ },
+ '&:active': {
+ backgroundColor: gray[200],
+ },
+ ...theme.applyStyles('dark', {
+ backgroundColor: gray[800],
+ borderColor: gray[700],
+ '&:hover': {
+ backgroundColor: gray[900],
+ borderColor: gray[600],
+ },
+ '&:active': {
+ backgroundColor: gray[900],
+ },
+ }),
+ },
+ },
+ {
+ props: {
+ color: 'secondary',
+ variant: 'outlined',
+ },
+ style: {
+ color: brand[700],
+ border: '1px solid',
+ borderColor: brand[200],
+ backgroundColor: brand[50],
+ '&:hover': {
+ backgroundColor: brand[100],
+ borderColor: brand[400],
+ },
+ '&:active': {
+ backgroundColor: alpha(brand[200], 0.7),
+ },
+ ...theme.applyStyles('dark', {
+ color: brand[50],
+ border: '1px solid',
+ borderColor: brand[900],
+ backgroundColor: alpha(brand[900], 0.3),
+ '&:hover': {
+ borderColor: brand[700],
+ backgroundColor: alpha(brand[900], 0.6),
+ },
+ '&:active': {
+ backgroundColor: alpha(brand[900], 0.5),
+ },
+ }),
+ },
+ },
+ {
+ props: {
+ variant: 'text',
+ },
+ style: {
+ color: gray[600],
+ '&:hover': {
+ backgroundColor: gray[100],
+ },
+ '&:active': {
+ backgroundColor: gray[200],
+ },
+ ...theme.applyStyles('dark', {
+ color: gray[50],
+ '&:hover': {
+ backgroundColor: gray[700],
+ },
+ '&:active': {
+ backgroundColor: alpha(gray[700], 0.7),
+ },
+ }),
+ },
+ },
+ {
+ props: {
+ color: 'secondary',
+ variant: 'text',
+ },
+ style: {
+ color: brand[700],
+ '&:hover': {
+ backgroundColor: alpha(brand[100], 0.5),
+ },
+ '&:active': {
+ backgroundColor: alpha(brand[200], 0.7),
+ },
+ ...theme.applyStyles('dark', {
+ color: brand[100],
+ '&:hover': {
+ backgroundColor: alpha(brand[900], 0.5),
+ },
+ '&:active': {
+ backgroundColor: alpha(brand[900], 0.3),
+ },
+ }),
+ },
+ },
+ ],
+ }),
+ },
+ },
+ MuiLoadingButton: {
+ styleOverrides: {
+ root: ({ theme }) => ({
+ '& .MuiLoadingButton-loadingIndicator': {
+ color: gray[400],
+ ...theme.applyStyles('dark', {
+ color: gray[600],
+ }),
+ },
+ }),
+ },
+ },
+ MuiCheckbox: {
+ defaultProps: {
+ disableRipple: true,
+ icon: (
+
+ ),
+ checkedIcon: ,
+ indeterminateIcon: ,
+ },
+ styleOverrides: {
+ root: ({ theme }) => ({
+ margin: 10,
+ height: 16,
+ width: 16,
+ borderRadius: 5,
+ border: '1px solid ',
+ borderColor: alpha(gray[300], 0.8),
+ boxShadow: '0 0 0 1.5px hsla(210, 0%, 0%, 0.04) inset',
+ backgroundColor: alpha(gray[100], 0.4),
+ transition: 'border-color, background-color, 120ms ease-in',
+ '&:hover': {
+ borderColor: brand[300],
+ },
+ '&.Mui-focusVisible': {
+ outline: `3px solid ${alpha(brand[500], 0.5)}`,
+ outlineOffset: '2px',
+ borderColor: brand[400],
+ },
+ '&.Mui-checked': {
+ color: 'white',
+ backgroundColor: brand[500],
+ borderColor: brand[500],
+ boxShadow: `none`,
+ '&:hover': {
+ backgroundColor: brand[600],
+ },
+ },
+ ...theme.applyStyles('dark', {
+ borderColor: alpha(gray[700], 0.8),
+ boxShadow: '0 0 0 1.5px hsl(210, 0%, 0%) inset',
+ backgroundColor: alpha(gray[900], 0.8),
+ '&:hover': {
+ borderColor: brand[300],
+ },
+ '&.Mui-focusVisible': {
+ borderColor: brand[400],
+ outline: `3px solid ${alpha(brand[500], 0.5)}`,
+ outlineOffset: '2px',
+ },
+ }),
+ }),
+ },
+ },
+ MuiOutlinedInput: {
+ styleOverrides: {
+ input: {
+ padding: 0,
+ },
+ root: ({ theme }) => ({
+ padding: '8px 12px',
+ color: theme.palette.text.primary,
+ borderRadius: theme.shape.borderRadius,
+ border: `1px solid ${theme.palette.divider}`,
+ backgroundColor: theme.palette.background.default,
+ transition: 'border 120ms ease-in',
+ '&:hover': {
+ borderColor: gray[400],
+ },
+ [`&.${outlinedInputClasses.focused}`]: {
+ outline: `3px solid ${alpha(brand[500], 0.5)}`,
+ borderColor: brand[400],
+ },
+ ...theme.applyStyles('dark', {
+ '&:hover': {
+ borderColor: gray[500],
+ },
+ }),
+ variants: [
+ {
+ props: {
+ size: 'small',
+ },
+ style: {
+ height: '2.25rem',
+ },
+ },
+ {
+ props: {
+ size: 'medium',
+ },
+ style: {
+ height: '2.5rem',
+ },
+ },
+ ],
+ }),
+ notchedOutline: {
+ border: 'none',
+ },
+ },
+ },
+};
diff --git a/docs/data/toolpad/core/components/sign-in-page/customTheme.tsx b/docs/data/toolpad/core/components/sign-in-page/customTheme.tsx
new file mode 100644
index 00000000000..c08aaa2f6d0
--- /dev/null
+++ b/docs/data/toolpad/core/components/sign-in-page/customTheme.tsx
@@ -0,0 +1,584 @@
+import * as React from 'react';
+import { PaletteMode } from '@mui/material';
+import {
+ alpha,
+ createTheme,
+ Shadows,
+ Theme,
+ Components,
+} from '@mui/material/styles';
+import { outlinedInputClasses } from '@mui/material/OutlinedInput';
+import CheckBoxOutlineBlankRoundedIcon from '@mui/icons-material/CheckBoxOutlineBlankRounded';
+import CheckRoundedIcon from '@mui/icons-material/CheckRounded';
+import RemoveRoundedIcon from '@mui/icons-material/RemoveRounded';
+
+declare module '@mui/material/Paper' {
+ interface PaperPropsVariantOverrides {
+ highlighted: true;
+ }
+}
+declare module '@mui/material/styles/createPalette' {
+ interface ColorRange {
+ 50: string;
+ 100: string;
+ 200: string;
+ 300: string;
+ 400: string;
+ 500: string;
+ 600: string;
+ 700: string;
+ 800: string;
+ 900: string;
+ }
+
+ interface PaletteColor extends ColorRange {}
+}
+
+const defaultTheme = createTheme();
+
+const customShadows: Shadows = [...defaultTheme.shadows];
+
+export const brand = {
+ 50: 'hsl(210, 100%, 95%)',
+ 100: 'hsl(210, 100%, 92%)',
+ 200: 'hsl(210, 100%, 80%)',
+ 300: 'hsl(210, 100%, 65%)',
+ 400: 'hsl(210, 98%, 48%)',
+ 500: 'hsl(210, 98%, 42%)',
+ 600: 'hsl(210, 98%, 55%)',
+ 700: 'hsl(210, 100%, 35%)',
+ 800: 'hsl(210, 100%, 16%)',
+ 900: 'hsl(210, 100%, 21%)',
+};
+
+export const gray = {
+ 50: 'hsl(220, 35%, 97%)',
+ 100: 'hsl(220, 30%, 94%)',
+ 200: 'hsl(220, 20%, 88%)',
+ 300: 'hsl(220, 20%, 80%)',
+ 400: 'hsl(220, 20%, 65%)',
+ 500: 'hsl(220, 20%, 42%)',
+ 600: 'hsl(220, 20%, 35%)',
+ 700: 'hsl(220, 20%, 25%)',
+ 800: 'hsl(220, 30%, 6%)',
+ 900: 'hsl(220, 35%, 3%)',
+};
+
+export const green = {
+ 50: 'hsl(120, 80%, 98%)',
+ 100: 'hsl(120, 75%, 94%)',
+ 200: 'hsl(120, 75%, 87%)',
+ 300: 'hsl(120, 61%, 77%)',
+ 400: 'hsl(120, 44%, 53%)',
+ 500: 'hsl(120, 59%, 30%)',
+ 600: 'hsl(120, 70%, 25%)',
+ 700: 'hsl(120, 75%, 16%)',
+ 800: 'hsl(120, 84%, 10%)',
+ 900: 'hsl(120, 87%, 6%)',
+};
+
+export const orange = {
+ 50: 'hsl(45, 100%, 97%)',
+ 100: 'hsl(45, 92%, 90%)',
+ 200: 'hsl(45, 94%, 80%)',
+ 300: 'hsl(45, 90%, 65%)',
+ 400: 'hsl(45, 90%, 40%)',
+ 500: 'hsl(45, 90%, 35%)',
+ 600: 'hsl(45, 91%, 25%)',
+ 700: 'hsl(45, 94%, 20%)',
+ 800: 'hsl(45, 95%, 16%)',
+ 900: 'hsl(45, 93%, 12%)',
+};
+
+export const red = {
+ 50: 'hsl(0, 100%, 97%)',
+ 100: 'hsl(0, 92%, 90%)',
+ 200: 'hsl(0, 94%, 80%)',
+ 300: 'hsl(0, 90%, 65%)',
+ 400: 'hsl(0, 90%, 40%)',
+ 500: 'hsl(0, 90%, 30%)',
+ 600: 'hsl(0, 91%, 25%)',
+ 700: 'hsl(0, 94%, 18%)',
+ 800: 'hsl(0, 95%, 12%)',
+ 900: 'hsl(0, 93%, 6%)',
+};
+
+export const getDesignTokens = (mode: PaletteMode) => {
+ customShadows[1] =
+ mode === 'dark'
+ ? 'hsla(220, 30%, 5%, 0.7) 0px 4px 16px 0px, hsla(220, 25%, 10%, 0.8) 0px 8px 16px -5px'
+ : 'hsla(220, 30%, 5%, 0.07) 0px 4px 16px 0px, hsla(220, 25%, 10%, 0.07) 0px 8px 16px -5px';
+
+ customShadows[4] =
+ '0px 5px 15px rgba(9, 11, 17, 0.05), 0px 15px 35px -5px rgba(19, 23, 32, 0.05)';
+
+ return {
+ palette: {
+ mode,
+ primary: {
+ light: brand[200],
+ main: brand[400],
+ dark: brand[700],
+ contrastText: brand[50],
+ ...(mode === 'dark' && {
+ contrastText: brand[50],
+ light: brand[300],
+ main: brand[400],
+ dark: brand[700],
+ }),
+ },
+ info: {
+ light: brand[100],
+ main: brand[300],
+ dark: brand[600],
+ contrastText: gray[50],
+ ...(mode === 'dark' && {
+ contrastText: brand[300],
+ light: brand[500],
+ main: brand[700],
+ dark: brand[900],
+ }),
+ },
+ warning: {
+ light: orange[300],
+ main: orange[400],
+ dark: orange[800],
+ ...(mode === 'dark' && {
+ light: orange[400],
+ main: orange[500],
+ dark: orange[700],
+ }),
+ },
+ error: {
+ light: red[300],
+ main: red[400],
+ dark: red[800],
+ ...(mode === 'dark' && {
+ light: red[400],
+ main: red[500],
+ dark: red[700],
+ }),
+ },
+ success: {
+ light: green[300],
+ main: green[400],
+ dark: green[800],
+ ...(mode === 'dark' && {
+ light: green[400],
+ main: green[500],
+ dark: green[700],
+ }),
+ },
+ grey: {
+ ...gray,
+ },
+ divider: mode === 'dark' ? alpha(gray[700], 0.6) : alpha(gray[300], 0.4),
+ background: {
+ default: 'hsl(0, 0%, 99%)',
+ paper: 'hsl(220, 35%, 97%)',
+ ...(mode === 'dark' && {
+ default: gray[900],
+ paper: 'hsl(220, 30%, 7%)',
+ }),
+ },
+ text: {
+ primary: gray[800],
+ secondary: gray[600],
+ warning: orange[400],
+ ...(mode === 'dark' && {
+ primary: 'hsl(0, 0%, 100%)',
+ secondary: gray[400],
+ }),
+ },
+ action: {
+ hover: alpha(gray[200], 0.2),
+ selected: `${alpha(gray[200], 0.3)}`,
+ ...(mode === 'dark' && {
+ hover: alpha(gray[600], 0.2),
+ selected: alpha(gray[600], 0.3),
+ }),
+ },
+ },
+ typography: {
+ h1: {
+ fontSize: defaultTheme.typography.pxToRem(48),
+ fontWeight: 600,
+ lineHeight: 1.2,
+ letterSpacing: -0.5,
+ },
+ h2: {
+ fontSize: defaultTheme.typography.pxToRem(36),
+ fontWeight: 600,
+ lineHeight: 1.2,
+ },
+ h3: {
+ fontSize: defaultTheme.typography.pxToRem(30),
+ lineHeight: 1.2,
+ },
+ h4: {
+ fontSize: defaultTheme.typography.pxToRem(24),
+ fontWeight: 600,
+ lineHeight: 1.5,
+ },
+ h5: {
+ fontSize: defaultTheme.typography.pxToRem(20),
+ fontWeight: 600,
+ },
+ h6: {
+ fontSize: defaultTheme.typography.pxToRem(18),
+ fontWeight: 600,
+ },
+ subtitle1: {
+ fontSize: defaultTheme.typography.pxToRem(18),
+ },
+ subtitle2: {
+ fontSize: defaultTheme.typography.pxToRem(14),
+ fontWeight: 500,
+ },
+ body1: {
+ fontSize: defaultTheme.typography.pxToRem(14),
+ },
+ body2: {
+ fontSize: defaultTheme.typography.pxToRem(14),
+ fontWeight: 400,
+ },
+ caption: {
+ fontSize: defaultTheme.typography.pxToRem(12),
+ fontWeight: 400,
+ },
+ },
+ shape: {
+ borderRadius: 8,
+ },
+ shadows: customShadows,
+ };
+};
+
+export const inputsCustomizations: Components = {
+ MuiButtonBase: {
+ defaultProps: {
+ disableTouchRipple: true,
+ disableRipple: true,
+ },
+ styleOverrides: {
+ root: ({ theme }) => ({
+ boxSizing: 'border-box',
+ transition: 'all 100ms ease-in',
+ '&:focus-visible': {
+ outline: `3px solid ${alpha(theme.palette.primary.main, 0.5)}`,
+ outlineOffset: '2px',
+ },
+ }),
+ },
+ },
+ MuiButton: {
+ styleOverrides: {
+ root: ({ theme }) => ({
+ boxShadow: 'none',
+ borderRadius: theme.shape.borderRadius,
+ textTransform: 'none',
+ variants: [
+ {
+ props: {
+ size: 'small',
+ },
+ style: {
+ height: '2.25rem',
+ padding: '8px 12px',
+ },
+ },
+ {
+ props: {
+ size: 'medium',
+ },
+ style: {
+ height: '2.5rem', // 40px
+ },
+ },
+ {
+ props: {
+ color: 'primary',
+ variant: 'contained',
+ },
+ style: {
+ color: 'white',
+ backgroundColor: gray[900],
+ backgroundImage: `linear-gradient(to bottom, ${gray[700]}, ${gray[800]})`,
+ boxShadow: `inset 0 1px 0 ${gray[600]}, inset 0 -1px 0 1px hsl(220, 0%, 0%)`,
+ border: `1px solid ${gray[700]}`,
+ '&:hover': {
+ backgroundImage: 'none',
+ backgroundColor: gray[700],
+ boxShadow: 'none',
+ },
+ '&:active': {
+ backgroundColor: gray[800],
+ },
+ ...theme.applyStyles('dark', {
+ color: 'black',
+ backgroundColor: gray[50],
+ backgroundImage: `linear-gradient(to bottom, ${gray[100]}, ${gray[50]})`,
+ boxShadow: 'inset 0 -1px 0 hsl(220, 30%, 80%)',
+ border: `1px solid ${gray[50]}`,
+ '&:hover': {
+ backgroundImage: 'none',
+ backgroundColor: gray[300],
+ boxShadow: 'none',
+ },
+ '&:active': {
+ backgroundColor: gray[400],
+ },
+ }),
+ },
+ },
+ {
+ props: {
+ color: 'secondary',
+ variant: 'contained',
+ },
+ style: {
+ color: 'white',
+ backgroundColor: brand[300],
+ backgroundImage: `linear-gradient(to bottom, ${alpha(brand[400], 0.8)}, ${brand[500]})`,
+ boxShadow: `inset 0 2px 0 ${alpha(brand[200], 0.2)}, inset 0 -2px 0 ${alpha(brand[700], 0.4)}`,
+ border: `1px solid ${brand[500]}`,
+ '&:hover': {
+ backgroundColor: brand[700],
+ boxShadow: 'none',
+ },
+ '&:active': {
+ backgroundColor: brand[700],
+ backgroundImage: 'none',
+ },
+ },
+ },
+ {
+ props: {
+ variant: 'outlined',
+ },
+ style: {
+ color: theme.palette.text.primary,
+ border: '1px solid',
+ borderColor: gray[200],
+ backgroundColor: alpha(gray[50], 0.3),
+ '&:hover': {
+ backgroundColor: gray[100],
+ borderColor: gray[300],
+ },
+ '&:active': {
+ backgroundColor: gray[200],
+ },
+ ...theme.applyStyles('dark', {
+ backgroundColor: gray[800],
+ borderColor: gray[700],
+
+ '&:hover': {
+ backgroundColor: gray[900],
+ borderColor: gray[600],
+ },
+ '&:active': {
+ backgroundColor: gray[900],
+ },
+ }),
+ },
+ },
+ {
+ props: {
+ color: 'secondary',
+ variant: 'outlined',
+ },
+ style: {
+ color: brand[700],
+ border: '1px solid',
+ borderColor: brand[200],
+ backgroundColor: brand[50],
+ '&:hover': {
+ backgroundColor: brand[100],
+ borderColor: brand[400],
+ },
+ '&:active': {
+ backgroundColor: alpha(brand[200], 0.7),
+ },
+ ...theme.applyStyles('dark', {
+ color: brand[50],
+ border: '1px solid',
+ borderColor: brand[900],
+ backgroundColor: alpha(brand[900], 0.3),
+ '&:hover': {
+ borderColor: brand[700],
+ backgroundColor: alpha(brand[900], 0.6),
+ },
+ '&:active': {
+ backgroundColor: alpha(brand[900], 0.5),
+ },
+ }),
+ },
+ },
+ {
+ props: {
+ variant: 'text',
+ },
+ style: {
+ color: gray[600],
+ '&:hover': {
+ backgroundColor: gray[100],
+ },
+ '&:active': {
+ backgroundColor: gray[200],
+ },
+ ...theme.applyStyles('dark', {
+ color: gray[50],
+ '&:hover': {
+ backgroundColor: gray[700],
+ },
+ '&:active': {
+ backgroundColor: alpha(gray[700], 0.7),
+ },
+ }),
+ },
+ },
+ {
+ props: {
+ color: 'secondary',
+ variant: 'text',
+ },
+ style: {
+ color: brand[700],
+ '&:hover': {
+ backgroundColor: alpha(brand[100], 0.5),
+ },
+ '&:active': {
+ backgroundColor: alpha(brand[200], 0.7),
+ },
+ ...theme.applyStyles('dark', {
+ color: brand[100],
+ '&:hover': {
+ backgroundColor: alpha(brand[900], 0.5),
+ },
+ '&:active': {
+ backgroundColor: alpha(brand[900], 0.3),
+ },
+ }),
+ },
+ },
+ ],
+ }),
+ },
+ },
+ // @ts-ignore TODO: MuiLoadingButton is not present in the default `theme`
+ MuiLoadingButton: {
+ styleOverrides: {
+ // @ts-ignore
+ root: ({ theme }) => ({
+ '& .MuiLoadingButton-loadingIndicator': {
+ color: gray[400],
+ ...theme.applyStyles('dark', {
+ color: gray[600],
+ }),
+ },
+ }),
+ },
+ },
+ MuiCheckbox: {
+ defaultProps: {
+ disableRipple: true,
+ icon: (
+
+ ),
+ checkedIcon: ,
+ indeterminateIcon: ,
+ },
+ styleOverrides: {
+ root: ({ theme }) => ({
+ margin: 10,
+ height: 16,
+ width: 16,
+ borderRadius: 5,
+ border: '1px solid ',
+ borderColor: alpha(gray[300], 0.8),
+ boxShadow: '0 0 0 1.5px hsla(210, 0%, 0%, 0.04) inset',
+ backgroundColor: alpha(gray[100], 0.4),
+ transition: 'border-color, background-color, 120ms ease-in',
+ '&:hover': {
+ borderColor: brand[300],
+ },
+ '&.Mui-focusVisible': {
+ outline: `3px solid ${alpha(brand[500], 0.5)}`,
+ outlineOffset: '2px',
+ borderColor: brand[400],
+ },
+ '&.Mui-checked': {
+ color: 'white',
+ backgroundColor: brand[500],
+ borderColor: brand[500],
+ boxShadow: `none`,
+ '&:hover': {
+ backgroundColor: brand[600],
+ },
+ },
+ ...theme.applyStyles('dark', {
+ borderColor: alpha(gray[700], 0.8),
+ boxShadow: '0 0 0 1.5px hsl(210, 0%, 0%) inset',
+ backgroundColor: alpha(gray[900], 0.8),
+ '&:hover': {
+ borderColor: brand[300],
+ },
+ '&.Mui-focusVisible': {
+ borderColor: brand[400],
+ outline: `3px solid ${alpha(brand[500], 0.5)}`,
+ outlineOffset: '2px',
+ },
+ }),
+ }),
+ },
+ },
+
+ MuiOutlinedInput: {
+ styleOverrides: {
+ input: {
+ padding: 0,
+ },
+ root: ({ theme }) => ({
+ padding: '8px 12px',
+ color: theme.palette.text.primary,
+ borderRadius: theme.shape.borderRadius,
+ border: `1px solid ${theme.palette.divider}`,
+ backgroundColor: theme.palette.background.default,
+ transition: 'border 120ms ease-in',
+ '&:hover': {
+ borderColor: gray[400],
+ },
+ [`&.${outlinedInputClasses.focused}`]: {
+ outline: `3px solid ${alpha(brand[500], 0.5)}`,
+ borderColor: brand[400],
+ },
+ ...theme.applyStyles('dark', {
+ '&:hover': {
+ borderColor: gray[500],
+ },
+ }),
+ variants: [
+ {
+ props: {
+ size: 'small',
+ },
+ style: {
+ height: '2.25rem',
+ },
+ },
+ {
+ props: {
+ size: 'medium',
+ },
+ style: {
+ height: '2.5rem',
+ },
+ },
+ ],
+ }),
+ notchedOutline: {
+ border: 'none',
+ },
+ },
+ },
+};
diff --git a/docs/data/toolpad/core/components/sign-in-page/sign-in-page.md b/docs/data/toolpad/core/components/sign-in-page/sign-in-page.md
index cdbc0bcfdc6..ffca59e7c61 100644
--- a/docs/data/toolpad/core/components/sign-in-page/sign-in-page.md
+++ b/docs/data/toolpad/core/components/sign-in-page/sign-in-page.md
@@ -54,14 +54,12 @@ The `SignIn` page component supports magic links. To enable this, you have to se
To render a magic link form, pass in a provider with `nodemailer` as the `id` property.
-{{"demo": "MagicLinkSignInPage.js", "iframe": true, "height": 400}}
-
-### Alerts
-
+:::info
The `SignInPage` component can display a success alert if the email is sent successfully. You can enable this by passing a `success` property in the
response object of the `signIn` prop.
+:::
-{{"demo": "MagicLinkAlertSignInPage.js", "iframe": true, "height": 400}}
+{{"demo": "MagicLinkAlertSignInPage.js", "iframe": true, "height": 450}}
:::info
Check out the complete [Next.js Auth.js Magic Link example](https://github.com/mui/mui-toolpad/tree/master/examples/core/auth-nextjs-email/) example for a working implementation of a magic link sign-in page with Auth.js, Nodemailer, Prisma and PostgreSQL.
@@ -223,29 +221,31 @@ If you're using Vite with React Router, check out the [example with Vite and Rea
You can add your own branding elements to the `SignInPage` through the `branding` prop in the [AppProvider](https://mui.com/toolpad/core/react-app-provider/):
-{{"demo": "BrandingSignInPage.js", "iframe": true, "height": 360 }}
+{{"demo": "BrandingSignInPage.js", "iframe": true, "height": 600 }}
### Theme
Through the `theme` prop in the [AppProvider](https://mui.com/toolpad/core/react-app-provider/), the `SignInPage` can be deeply customized to match any theme:
-{{"demo": "ThemeSignInPage.js", "height": 700 }}
-
-### Slot Props
-
-You can use the `slotProps` prop to customize the underlying components of the `SignInPage`:
+{{"demo": "ThemeSignInPage.js", "iframe": true, "height": 700 }}
-{{"demo": "SlotPropsSignIn.js", "height": 540 }}
+:::info
+Find a full-fledged example using the Next.js App router, Auth.js and this theme [here](https://codesandbox.io/s/github/mui/toolpad/tree/master/examples/core/auth-nextjs-themed).
+:::
### Slots
To enable deep customization beyond what is possible with custom props, the `SignInPage` component allows bringing your own custom granular components, such as inputs and buttons.
-:::info
-Make sure to use the `name` attribute on the custom components with values `email` and `password` to enable data capture by the form action.
+:::warning
+Make sure to pass `email` and `password` as the `name` attribute on custom email and password components, otherwise those values will not be available in the `formData` parameter of the `signIn` prop.
:::
-{{"demo": "SlotsSignIn.js", "height": 540 }}
+{{"demo": "SlotsSignIn.js", "iframe": true, "height": 540 }}
+
+You can use the `slotProps` prop to pass props to the underlying components of each slot:
+
+{{"demo": "SlotPropsSignIn.js", "iframe": true, "height": 540 }}
### 🚧 Layouts
diff --git a/docs/public/static/toolpad/docs/core/auth-next-dark.png b/docs/public/static/toolpad/docs/core/auth-next-dark.png
index a4b127c9b6c..527474a4a77 100644
Binary files a/docs/public/static/toolpad/docs/core/auth-next-dark.png and b/docs/public/static/toolpad/docs/core/auth-next-dark.png differ
diff --git a/docs/public/static/toolpad/docs/core/auth-next.png b/docs/public/static/toolpad/docs/core/auth-next.png
index 57238099e1b..fc266f89294 100644
Binary files a/docs/public/static/toolpad/docs/core/auth-next.png and b/docs/public/static/toolpad/docs/core/auth-next.png differ
diff --git a/docs/src/modules/components/ExamplesGrid/core-examples.ts b/docs/src/modules/components/ExamplesGrid/core-examples.ts
index 92e559394cd..de67bda126c 100644
--- a/docs/src/modules/components/ExamplesGrid/core-examples.ts
+++ b/docs/src/modules/components/ExamplesGrid/core-examples.ts
@@ -92,8 +92,6 @@ export default function examples() {
source: 'https://github.com/mui/toolpad/tree/master/examples/core/auth-nextjs-themed',
codesandbox:
'https://codesandbox.io/s/github/mui/toolpad/tree/master/examples/core/auth-nextjs-themed',
- stackblitz:
- 'https://stackblitz.com/github/mui/toolpad/tree/master/examples/core/auth-nextjs-themed',
},
];
}
diff --git a/examples/core/auth-nextjs-themed/README.md b/examples/core/auth-nextjs-themed/README.md
index 3086b505f85..17c9ac9fbec 100644
--- a/examples/core/auth-nextjs-themed/README.md
+++ b/examples/core/auth-nextjs-themed/README.md
@@ -14,6 +14,20 @@ First, run the development server: `npm run dev`
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+## Run on Code Sandbox
+
+Run this example on CodeSandbox [here](https://codesandbox.io/s/github/mui/toolpad/tree/master/examples/core/auth-nextjs-themed).
+
+## Clone using `create-toolpad-app`
+
+To copy this example and customize it for your needs, run
+
+```bash
+npx create-toolpad-app@latest --example auth-nextjs-themed
+```
+
+and follow the instructions in the terminal.
+
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
diff --git a/examples/core/auth-nextjs-themed/theme/themePrimitives.ts b/examples/core/auth-nextjs-themed/theme/themePrimitives.ts
index 177eb7cef78..bccf187d5f5 100644
--- a/examples/core/auth-nextjs-themed/theme/themePrimitives.ts
+++ b/examples/core/auth-nextjs-themed/theme/themePrimitives.ts
@@ -101,7 +101,7 @@ export const getDesignTokens = (mode: PaletteMode) => {
? 'hsla(220, 30%, 5%, 0.7) 0px 4px 16px 0px, hsla(220, 25%, 10%, 0.8) 0px 8px 16px -5px'
: 'hsla(220, 30%, 5%, 0.07) 0px 4px 16px 0px, hsla(220, 25%, 10%, 0.07) 0px 8px 16px -5px';
- customShadows[10] =
+ customShadows[4] =
'0px 5px 15px rgba(9, 11, 17, 0.05), 0px 15px 35px -5px rgba(19, 23, 32, 0.05)';
return {
diff --git a/packages/toolpad-core/src/SignInPage/SignInPage.tsx b/packages/toolpad-core/src/SignInPage/SignInPage.tsx
index 3510bd938c8..67eb612106f 100644
--- a/packages/toolpad-core/src/SignInPage/SignInPage.tsx
+++ b/packages/toolpad-core/src/SignInPage/SignInPage.tsx
@@ -268,7 +268,6 @@ function SignInPage(props: SignInPageProps) {
{branding?.logo}
@@ -289,7 +288,7 @@ function SignInPage(props: SignInPageProps) {
variant="h5"
color="textPrimary"
sx={{
- mb: 1,
+ my: theme.spacing(1),
fontWeight: 600,
}}
>
@@ -303,7 +302,7 @@ function SignInPage(props: SignInPageProps) {
Welcome, please sign in to continue
)}
-
+
{error && isOauthProvider(selectedProviderId) ? (
{error}
@@ -507,7 +506,7 @@ function SignInPage(props: SignInPageProps) {
type="submit"
fullWidth
size="large"
- variant="contained"
+ variant="outlined"
disableElevation
id="submit-nodemailer"
color="inherit"