diff --git a/docs/Admin.md b/docs/Admin.md index d77fa00494b..ccb1ecd036c 100644 --- a/docs/Admin.md +++ b/docs/Admin.md @@ -145,7 +145,7 @@ Here are all the props accepted by the component: | `basename` | Optional | `string` | - | The base path for all URLs | | `catchAll` | Optional | `Component` | `NotFound` | The fallback component for unknown routes | | `dashboard` | Optional | `Component` | - | The content of the dashboard page | -| `darkTheme` | Optional | `object` | - | The dark theme configuration | +| `darkTheme` | Optional | `object` | `default DarkTheme` | The dark theme configuration | | `defaultTheme` | Optional | `boolean` | `false` | Flag to default to the light theme | | `disableTelemetry` | Optional | `boolean` | `false` | Set to `true` to disable telemetry collection | | `i18nProvider` | Optional | `I18NProvider` | - | The internationalization provider for translations | @@ -156,7 +156,7 @@ Here are all the props accepted by the component: | `ready` | Optional | `Component` | `Ready` | The content of the ready page | | `requireAuth` | Optional | `boolean` | `false` | Flag to require authentication for all routes | | `store` | Optional | `Store` | - | The Store for managing user preferences | -| `theme` | Optional | `object` | - | The main (light) theme configuration | +| `theme` | Optional | `object` | `default LightTheme` | The main (light) theme configuration | | `title` | Optional | `string` | - | The error page title | @@ -433,29 +433,48 @@ const App = () => ( ## `darkTheme` -If you want to support both light and dark mode, you can provide a `darkTheme` in addition to the `theme` prop. The app will use the `darkTheme` by default for users who prefer the dark mode at the OS level, and users will be able to switch from light to dark mode using a new app bar button leveraging [the `` component](./ToggleThemeButton.md). +React-admin provides a [built-in dark theme](./AppTheme.md#default). The app will use the `darkTheme` by default for users who prefer the dark mode at the OS level, and users will be able to switch from light to dark mode using [the `` component](./ToggleThemeButton.md). +If you want to override it, you can provide your own `darkTheme` in addition to the `theme` prop: + ```tsx import { Admin } from 'react-admin'; import { dataProvider } from './dataProvider'; -import { darkTheme, lightTheme } from './themes'; +import { myDarkTheme } from './themes'; const App = () => ( + ... + +); +``` + +If you want to remove the user's ability to switch to dark theme, you can set `darkTheme` to `null`, therefore the `` component won't be shown: + +```tsx +import { Admin } from 'react-admin'; +import { dataProvider } from './dataProvider'; + +const App = () => ( + ... ); ``` +If the `theme` prop is provided and the `darkTheme` prop is not, the dark theme is disabled. + **Tip**: To disable OS preference detection and always use one theme by default, see the [`defaultTheme`](#defaulttheme) prop. ## `defaultTheme` @@ -843,7 +862,7 @@ const App = () => ( You can also [write your own theme](./AppTheme.md#writing-a-custom-theme) to fit your company branding. For more details on predefined and custom themes, refer to [the Application Theme chapter](./AppTheme.md). -If you want to support both a light and a dark theme, check out [the `` prop](#darktheme). +React-admin provides a [built-in dark theme by default](./AppTheme.md#default). If you want to override it, check out [the `` prop](#darktheme). ## `title` diff --git a/docs/AppBar.md b/docs/AppBar.md index 117dcd0db50..6d34cdbabeb 100644 --- a/docs/AppBar.md +++ b/docs/AppBar.md @@ -18,7 +18,7 @@ By default, the `` component displays: - a hamburger icon to toggle the sidebar width, - the page title, - a button to change locales (if the application uses [i18n](./Translation.md)), -- a button to change the theme (if the application uses a [dark theme](./Admin.md#darktheme)), +- a button to change the theme (unless the [dark theme](./Admin.md#darktheme) is disabled), - a loading indicator, - a button to display the user menu. diff --git a/docs/AppTheme.md b/docs/AppTheme.md index 4b8c1e8a0ce..cb3ef3ec006 100644 --- a/docs/AppTheme.md +++ b/docs/AppTheme.md @@ -60,14 +60,17 @@ It's a common practice to support both a light theme and a dark theme in an appl Your browser does not support the video tag. +React-admin provides a [built-in dark theme by default](#default), the default application theme depends on the user's system settings. If the user has chosen a dark mode in their OS, react-admin will use the dark theme. Otherwise, it will use the light theme. -React-admin's `` component accepts a `darkTheme` prop in addition to the `theme` prop. +In addition, users can switch from one theme to the other using [the `` component](./ToggleThemeButton.md), that appears in the AppBar as soon as you define a `darkTheme` prop. -```jsx -import { Admin, defaultTheme } from 'react-admin'; +You can override the dark theme by setting the ``'s `darkTheme` prop with your own theme: -const lightTheme = defaultTheme; -const darkTheme = { ...defaultTheme, palette: { mode: 'dark' } }; +```tsx +import { Admin, defaultDarkTheme, defaultLightTheme } from 'react-admin'; + +const lightTheme = defaultLightTheme; +const darkTheme = { ...defaultDarkTheme, palette: { mode: 'dark' } }; const App = () => ( ( ); ``` -With this setup, the default application theme depends on the user's system settings. If the user has chosen a dark mode in their OS, react-admin will use the dark theme. Otherwise, it will use the light theme. +**Tip**: If you don't need the default dark theme, you can set the ``'s `darkTheme` prop to `null`: -In addition, users can switch from one theme to the other using [the `` component](./ToggleThemeButton.md), which appears in the AppBar as soon as you define a `darkTheme` prop. +```tsx +const App = () => ( + + // ... + +); +``` ## Built-In Themes diff --git a/docs/ToggleThemeButton.md b/docs/ToggleThemeButton.md index 48128034f1d..b906247fe62 100644 --- a/docs/ToggleThemeButton.md +++ b/docs/ToggleThemeButton.md @@ -13,7 +13,7 @@ The `` component lets users switch from light to dark mode, a Your browser does not support the video tag. -It is enabled by default in the `` as soon as you define a dark theme via [the `` prop](./Admin.md#darktheme). +It is enabled by default in the `` as React-admin provides a [built-in dark theme](./AppTheme.md#default). ## Usage @@ -52,10 +52,23 @@ const App = () => ( ## Removing The Button From The AppBar -The `` appears by default in the `` if the `` prop is defined. If you want to remove it, you need to set a custom [`` prop](./AppBar.md#toolbar): +The `` appears by default in the ``. If you want to remove it, you have two solutions: -```jsx -// in src/MyAppBar.js +- you can set the `` `darkTheme` prop to `null`: + +```tsx +// in src/App.tsx +const App = () => ( + + // ... + +); +``` + +- or you can set a custom [`` prop](./AppBar.md#toolbar): + +```tsx +// in src/MyAppBar.tsx import { AppBar, LocalesMenuButton, RefreshIconButton } from 'react-admin'; export const MyAppBar = () => ( @@ -71,7 +84,9 @@ export const MyAppBar = () => ( ## Creating A Dark Theme -For this button to work, you must provide a dark theme to the `` component. The `darkTheme` should be a JSON object that follows the [Material UI theme specification](https://material-ui.com/customization/theming/). +For this button to work, you must provide a dark theme to the `` component. React-admin provides a [built-in dark theme](./AppTheme.md#default), but you can override it according to your needs. + +The `darkTheme` should be a JSON object that follows the [Material UI theme specification](https://material-ui.com/customization/theming/). You can create such a theme from scratch: diff --git a/docs/Upgrade.md b/docs/Upgrade.md index d1e45a7020b..dbe61783248 100644 --- a/docs/Upgrade.md +++ b/docs/Upgrade.md @@ -18,9 +18,22 @@ If you previously relied on the fact that the rows were not clickable by default ``` +## Dark Theme Is Available By Default + +In addition to the light theme, React-admin v5 includes a [dark theme](https://marmelab.com/react-admin/AppTheme.html#light-and-dark-themes), renders a theme switcher in the app bar, and chooses the default theme based on the user OS preferences. + +If you don't need the dark mode feature, you'll have to explicitly disable it: + +```diff +- ++ + ... + +``` + ## Links are now underlined by default - -In the default theme, links are now underlined by default. + +In the default theme, links are now underlined by default. If you use the `` component from `react-admin`, and you want to remove the underline, set the `underline` prop to `none`: diff --git a/packages/ra-ui-materialui/src/AdminContext.spec.tsx b/packages/ra-ui-materialui/src/AdminContext.spec.tsx index bbfea0f82fe..d632c0ead6e 100644 --- a/packages/ra-ui-materialui/src/AdminContext.spec.tsx +++ b/packages/ra-ui-materialui/src/AdminContext.spec.tsx @@ -1,14 +1,12 @@ import * as React from 'react'; import { render, screen } from '@testing-library/react'; -import { Typography, ThemeOptions } from '@mui/material'; +import { Typography } from '@mui/material'; import expect from 'expect'; import { memoryStore } from 'ra-core'; import { AdminContext } from './AdminContext'; import { ThemeTestWrapper } from './layout/ThemeTestWrapper'; - -const lightTheme: ThemeOptions = {}; -const darkTheme: ThemeOptions = { palette: { mode: 'dark' } }; +import { defaultLightTheme } from './theme'; const LIGHT_MODE_TEXT_COLOR = 'rgb(25, 118, 210)'; // text is dark blue in light mode const DARK_MODE_TEXT_COLOR = 'rgb(144, 202, 249)'; // text is light blue in dark mode @@ -16,7 +14,7 @@ const DARK_MODE_TEXT_COLOR = 'rgb(144, 202, 249)'; // text is light blue in dark describe('AdminContext', () => { it('should default to light theme', () => { render( - + Test ); @@ -26,7 +24,7 @@ describe('AdminContext', () => { it('should default to dark theme when the browser detects a dark mode preference', () => { render( - + Test @@ -37,7 +35,7 @@ describe('AdminContext', () => { it('should default to light theme when the browser detects a dark mode preference', () => { render( - + Test @@ -47,11 +45,7 @@ describe('AdminContext', () => { }); it('should default to dark theme when user preference is dark', () => { render( - + Test ); @@ -61,11 +55,18 @@ describe('AdminContext', () => { it('should default to light theme when user preference is light', () => { render( - + + Test + + + ); + const text = screen.getByText('Test'); + expect(getComputedStyle(text).color).toBe(LIGHT_MODE_TEXT_COLOR); + }); + it('should only use main theme even the browser detects a dark mode preference', () => { + render( + + Test diff --git a/packages/ra-ui-materialui/src/AdminContext.tsx b/packages/ra-ui-materialui/src/AdminContext.tsx index ac9ae91764a..2a3eea79f1a 100644 --- a/packages/ra-ui-materialui/src/AdminContext.tsx +++ b/packages/ra-ui-materialui/src/AdminContext.tsx @@ -6,6 +6,7 @@ import { ThemesContext, RaThemeOptions, defaultLightTheme, + defaultDarkTheme, } from './theme'; export const AdminContext = (props: AdminContextProps) => { @@ -22,7 +23,12 @@ export const AdminContext = (props: AdminContextProps) => { @@ -56,6 +62,7 @@ export interface AdminContextProps extends CoreAdminContextProps { /** * The material-UI theme to customize the UI. Prefer the theme prop. + * If not provided, the default light theme is used. * * @see https://marmelab.com/react-admin/Admin.html#theme */ @@ -63,6 +70,8 @@ export interface AdminContextProps extends CoreAdminContextProps { /** * The material-UI theme to apply to the UI when the dark mode is activated. + * If not provided, the default dark theme is used. + * If set to null, the dark mode is disabled. * * @see https://marmelab.com/react-admin/Admin.html#darktheme * @example @@ -80,7 +89,7 @@ export interface AdminContextProps extends CoreAdminContextProps { * * ); */ - darkTheme?: RaThemeOptions; + darkTheme?: RaThemeOptions | null; /** * The default theme to use when the user hasn't chosen a theme yet. diff --git a/packages/ra-ui-materialui/src/button/SortButton.stories.tsx b/packages/ra-ui-materialui/src/button/SortButton.stories.tsx index 7a7607ec6e4..4c3d1c85810 100644 --- a/packages/ra-ui-materialui/src/button/SortButton.stories.tsx +++ b/packages/ra-ui-materialui/src/button/SortButton.stories.tsx @@ -54,13 +54,17 @@ const PlayerList = () => ( ); export const Basic = () => ( - + ); export const I18N = () => ( - + ); @@ -92,7 +96,7 @@ const PlayerListSX = () => ( ); export const SX = () => ( - + ); diff --git a/packages/ra-ui-materialui/src/button/ToggleThemeButton.stories.tsx b/packages/ra-ui-materialui/src/button/ToggleThemeButton.stories.tsx index cf7f0434118..15de1e9a419 100644 --- a/packages/ra-ui-materialui/src/button/ToggleThemeButton.stories.tsx +++ b/packages/ra-ui-materialui/src/button/ToggleThemeButton.stories.tsx @@ -97,12 +97,7 @@ const BookList = () => ( ); export const Basic = () => ( - + ); diff --git a/packages/ra-ui-materialui/src/field/ReferenceArrayField.stories.tsx b/packages/ra-ui-materialui/src/field/ReferenceArrayField.stories.tsx index 6374904f569..56a54cca2bc 100644 --- a/packages/ra-ui-materialui/src/field/ReferenceArrayField.stories.tsx +++ b/packages/ra-ui-materialui/src/field/ReferenceArrayField.stories.tsx @@ -34,7 +34,7 @@ const resouceDefs = { }, }; export const Basic = () => ( - + @@ -47,7 +47,7 @@ export const Basic = () => ( ); export const Children = () => ( - + @@ -79,7 +79,10 @@ const dataProviderWithDifferentIdTypes = fakeRestProvider( ); export const DifferentIdTypes = () => ( - + @@ -108,7 +111,7 @@ const dataProviderWithLog = { export const WithMeta = () => { return ( - + diff --git a/packages/ra-ui-materialui/src/field/TranslatableFields.stories.tsx b/packages/ra-ui-materialui/src/field/TranslatableFields.stories.tsx index 79985743ccf..101e92e9278 100644 --- a/packages/ra-ui-materialui/src/field/TranslatableFields.stories.tsx +++ b/packages/ra-ui-materialui/src/field/TranslatableFields.stories.tsx @@ -44,7 +44,7 @@ const defaultData = [ const i18nProvider = polyglotI18nProvider(() => englishMessages); const Wrapper = ({ children }) => ( - + {children} diff --git a/packages/ra-ui-materialui/src/form/SimpleForm.stories.tsx b/packages/ra-ui-materialui/src/form/SimpleForm.stories.tsx index d5905a8971d..3cb0106bcfe 100644 --- a/packages/ra-ui-materialui/src/form/SimpleForm.stories.tsx +++ b/packages/ra-ui-materialui/src/form/SimpleForm.stories.tsx @@ -34,6 +34,7 @@ const Wrapper = ({ dataProvider={testDataProvider({ getOne: () => Promise.resolve({ data }), })} + defaultTheme="light" > diff --git a/packages/ra-ui-materialui/src/form/TabbedForm.stories.tsx b/packages/ra-ui-materialui/src/form/TabbedForm.stories.tsx index 95085cb09c9..9435a3ffed6 100644 --- a/packages/ra-ui-materialui/src/form/TabbedForm.stories.tsx +++ b/packages/ra-ui-materialui/src/form/TabbedForm.stories.tsx @@ -28,6 +28,7 @@ const Wrapper = ({ children }) => ( dataProvider={testDataProvider({ getOne: () => Promise.resolve({ data }), })} + defaultTheme="light" > diff --git a/packages/ra-ui-materialui/src/form/useRegisterMutationMiddleware.stories.tsx b/packages/ra-ui-materialui/src/form/useRegisterMutationMiddleware.stories.tsx index 83fe25ebb7a..67413d76ed5 100644 --- a/packages/ra-ui-materialui/src/form/useRegisterMutationMiddleware.stories.tsx +++ b/packages/ra-ui-materialui/src/form/useRegisterMutationMiddleware.stories.tsx @@ -107,7 +107,7 @@ export const Basic = () => { true ); return ( - + diff --git a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.stories.tsx b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.stories.tsx index 068402a70bd..4d143bc73fd 100644 --- a/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.stories.tsx +++ b/packages/ra-ui-materialui/src/input/ArrayInput/SimpleFormIterator.stories.tsx @@ -31,167 +31,115 @@ const dataProvider = { }), } as any; -export const Basic = () => ( - +const Wrapper = ({ children }) => ( + - - - - - - + {children} ); +export const Basic = () => ( + + + + + + +); + export const AddButton = () => ( - - - - - Add}> - - - - - - - + + Add}> + + + + ); export const GetItemLabel = () => ( - - - - - `item #${index}`} - > - - - - - - - + + `item #${index}`}> + + + + ); export const FullWidth = () => ( - - - - - - - - - - - - + + + + + + ); export const Inline = () => ( - - - - - - - - - - - - + + + + + + ); export const DisableAdd = () => ( - - - - - - - - - - - - + + + + + + ); export const DisableClear = () => ( - - - - - - - - - - - - + + + + + + ); export const DisableRemove = () => ( - - - - - - - - - - - - + + + + + + ); export const DisableReordering = () => ( - - - - - - - - - - - - + + + + + + ); export const Sx = () => ( - - - - - - - - - - - - + + + + + + ); export const Theming = () => ( @@ -217,6 +165,7 @@ export const Theming = () => ( }, }, }} + defaultTheme="light" > diff --git a/packages/ra-ui-materialui/src/input/AutocompleteArrayInput.stories.tsx b/packages/ra-ui-materialui/src/input/AutocompleteArrayInput.stories.tsx index 40ffeef7227..8ceb63bcbef 100644 --- a/packages/ra-ui-materialui/src/input/AutocompleteArrayInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/AutocompleteArrayInput.stories.tsx @@ -30,51 +30,47 @@ export default { title: 'ra-ui-materialui/input/AutocompleteArrayInput' }; const i18nProvider = polyglotI18nProvider(() => englishMessages); -export const Basic = () => ( - +const Wrapper = ({ children }) => ( + - - - + {children} ); +export const Basic = () => ( + + + +); + export const OnChange = ({ onChange = (value, records) => console.log({ value, records }), }: Pick) => ( - - - - - - - + + + ); const choices = [ @@ -117,22 +113,14 @@ const CreateRole = () => { }; export const CreateProp = () => ( - - - - } - /> - - - + + } + /> + ); const dataProvider = { diff --git a/packages/ra-ui-materialui/src/input/AutocompleteInput.stories.tsx b/packages/ra-ui-materialui/src/input/AutocompleteInput.stories.tsx index 730e9f29f70..116f83c2eb3 100644 --- a/packages/ra-ui-materialui/src/input/AutocompleteInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/AutocompleteInput.stories.tsx @@ -1142,6 +1142,7 @@ export const TranslateChoice = () => { }), } as any } + defaultTheme="light" > diff --git a/packages/ra-ui-materialui/src/input/BooleanInput.stories.tsx b/packages/ra-ui-materialui/src/input/BooleanInput.stories.tsx index f1b2b74a781..60bbb8e22f3 100644 --- a/packages/ra-ui-materialui/src/input/BooleanInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/BooleanInput.stories.tsx @@ -33,7 +33,7 @@ export const CustomIcon = () => ( const i18nProvider = polyglotI18nProvider(() => englishMessages); const Wrapper = ({ children }) => ( - + {children} @@ -48,7 +48,7 @@ const SetFocusButton = ({ source }) => { }; export const SetFocus = () => ( - + diff --git a/packages/ra-ui-materialui/src/input/CheckboxGroupInput.stories.tsx b/packages/ra-ui-materialui/src/input/CheckboxGroupInput.stories.tsx index 4335fc3a541..c53a4e40d1a 100644 --- a/packages/ra-ui-materialui/src/input/CheckboxGroupInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/CheckboxGroupInput.stories.tsx @@ -27,7 +27,7 @@ const choices = [ ]; export const Basic = () => ( - + ( - + ( ); export const Disabled = () => ( - + ( ); export const LabelPlacement = () => ( - + ( ); export const Column = () => ( - + ( ); export const Options = () => ( - + ( ); export const CustomOptionText = () => ( - + { }; export const Validate = () => ( - + ( ); export const HelperText = () => ( - + { }), } as any } + defaultTheme="light" > @@ -302,7 +307,7 @@ const SetFocusButton = ({ source }) => { }; export const SetFocus = () => ( - + diff --git a/packages/ra-ui-materialui/src/input/DateInput.stories.tsx b/packages/ra-ui-materialui/src/input/DateInput.stories.tsx index 70ddb236a37..35053037573 100644 --- a/packages/ra-ui-materialui/src/input/DateInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/DateInput.stories.tsx @@ -38,7 +38,7 @@ export const Validate = () => ( const i18nProvider = polyglotI18nProvider(() => englishMessages); const Wrapper = ({ children }) => ( - + {children} diff --git a/packages/ra-ui-materialui/src/input/DateTimeInput.stories.tsx b/packages/ra-ui-materialui/src/input/DateTimeInput.stories.tsx index 08dd936ed62..59c54e20e0b 100644 --- a/packages/ra-ui-materialui/src/input/DateTimeInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/DateTimeInput.stories.tsx @@ -31,7 +31,7 @@ export const Disabled = () => ( const i18nProvider = polyglotI18nProvider(() => englishMessages); const Wrapper = ({ children }) => ( - + {children} diff --git a/packages/ra-ui-materialui/src/input/FileInput.stories.tsx b/packages/ra-ui-materialui/src/input/FileInput.stories.tsx index ec275a707ba..10cfee3ae3c 100644 --- a/packages/ra-ui-materialui/src/input/FileInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/FileInput.stories.tsx @@ -117,7 +117,7 @@ export const CustomRemoveIcon = () => ( const i18nProvider = polyglotI18nProvider(() => englishMessages); const Wrapper = ({ children }) => ( - + {children} diff --git a/packages/ra-ui-materialui/src/input/ImageInput.stories.tsx b/packages/ra-ui-materialui/src/input/ImageInput.stories.tsx index a1bdbd51633..1c4b21955bb 100644 --- a/packages/ra-ui-materialui/src/input/ImageInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/ImageInput.stories.tsx @@ -96,7 +96,7 @@ export const CustomRemoveIcon = () => ( const i18nProvider = polyglotI18nProvider(() => englishMessages); const Wrapper = ({ children }) => ( - + {children} diff --git a/packages/ra-ui-materialui/src/input/NullableBooleanInput.stories.tsx b/packages/ra-ui-materialui/src/input/NullableBooleanInput.stories.tsx index 0e8f5b10af9..1530a27d4ab 100644 --- a/packages/ra-ui-materialui/src/input/NullableBooleanInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/NullableBooleanInput.stories.tsx @@ -25,7 +25,7 @@ export const Disabled = () => ( const i18nProvider = polyglotI18nProvider(() => englishMessages); const Wrapper = ({ children }) => ( - + {children} diff --git a/packages/ra-ui-materialui/src/input/NumberInput.stories.tsx b/packages/ra-ui-materialui/src/input/NumberInput.stories.tsx index 3ff466adb06..ad294fae9eb 100644 --- a/packages/ra-ui-materialui/src/input/NumberInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/NumberInput.stories.tsx @@ -11,23 +11,27 @@ import { TextInput } from './TextInput'; export default { title: 'ra-ui-materialui/input/NumberInput' }; -export const Basic = () => ( - +const Wrapper = ({ children }) => ( + - - - - + {children} ); +export const Basic = () => ( + + + + +); + export const Float = () => ( - + ( ); export const DefaultValue = () => ( - - - - - - - - - - - - - - + + + + + + + + + + ); export const HelperText = () => ( - - - - - - - - - + + + + + ); export const Label = () => ( - - - - - - - - - + + + + + ); export const FullWidth = () => ( - - - - - - - - + + + + ); export const Margin = () => ( - - - - - - - - - + + + + + ); export const Variant = () => ( - - - - - - - - - + + + + + ); export const Step = () => ( - - - - - - - - - + + + + + ); export const MinMax = () => ( - - - - - - - - - + + + + + ); export const Required = () => ( - - - - - - - - - - + + + + + + ); export const Error = () => ( - + ( ); export const Sx = () => ( - - - - - - - + + + ); const FormStateInspector = () => { @@ -300,33 +203,17 @@ const FieldStateInspector = ({ name = 'views' }) => { }; export const FieldState = () => ( - - - - - - - - - + + + + + ); export const ShouldUnregister = () => ( - - - - - - - + + + ); const SetFocusButton = ({ source }) => { @@ -337,13 +224,9 @@ const SetFocusButton = ({ source }) => { }; export const SetFocus = () => ( - - - - - - - - - + + + + + ); diff --git a/packages/ra-ui-materialui/src/input/RadioButtonGroupInput.stories.tsx b/packages/ra-ui-materialui/src/input/RadioButtonGroupInput.stories.tsx index ec41052c981..16d09d41b51 100644 --- a/packages/ra-ui-materialui/src/input/RadioButtonGroupInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/RadioButtonGroupInput.stories.tsx @@ -77,7 +77,11 @@ const dataProvider = testDataProvider({ } as any); export const InsideReferenceArrayInput = () => ( - + ( getList: () => Promise.reject(new Error('fetch error')), }} i18nProvider={i18nProvider} + defaultTheme="light" > ( const i18nProvider = polyglotI18nProvider(() => englishMessages); const Wrapper = ({ children }) => ( - + {children} @@ -176,6 +181,7 @@ export const TranslateChoice = () => { }), } as any } + defaultTheme="light" > diff --git a/packages/ra-ui-materialui/src/input/ReferenceArrayInput.stories.tsx b/packages/ra-ui-materialui/src/input/ReferenceArrayInput.stories.tsx index e080109fed7..2996fa0dbec 100644 --- a/packages/ra-ui-materialui/src/input/ReferenceArrayInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/ReferenceArrayInput.stories.tsx @@ -71,7 +71,11 @@ export const Basic = () => ( ); export const WithAutocompleteInput = () => ( - +
{}} defaultValues={{ tag_ids: [1, 3] }}> ( } as unknown) as DataProvider } i18nProvider={i18nProvider} + defaultTheme="light" > {}} defaultValues={{ tag_ids: [1, 3] }}> ( ); export const WithSelectArrayInput = () => ( - + {}} defaultValues={{ tag_ids: [1, 3] }}> ( } as unknown) as DataProvider } i18nProvider={i18nProvider} + defaultTheme="light" > {}} defaultValues={{ tag_ids: [1, 3] }}> ( ); export const WithCheckboxGroupInput = () => ( - + {}} defaultValues={{ tag_ids: [1, 3] }}> ( } as unknown) as DataProvider } i18nProvider={i18nProvider} + defaultTheme="light" > {}} defaultValues={{ tag_ids: [1, 3] }}> ( ); export const WithDatagridInput = () => ( - + {}} defaultValues={{ tag_ids: [1, 3] }}> ( } as unknown) as DataProvider } i18nProvider={i18nProvider} + defaultTheme="light" > {}} defaultValues={{ tag_ids: [1, 3] }}> { ], }; return ( - + diff --git a/packages/ra-ui-materialui/src/input/SelectArrayInput.stories.tsx b/packages/ra-ui-materialui/src/input/SelectArrayInput.stories.tsx index 6ecd1def302..0f460c57146 100644 --- a/packages/ra-ui-materialui/src/input/SelectArrayInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/SelectArrayInput.stories.tsx @@ -38,7 +38,7 @@ const FormInspector = ({ source }) => { }; export const Basic = () => ( - + ( ); export const DefaultValue = () => ( - + ( ); export const InsideArrayInput = () => ( - + { }; export const CreateProp = () => ( - + { }; const dataProvider = fakeRestProvider(fakeData, false); return ( - + @@ -233,7 +233,7 @@ export const DifferentSizes = () => { }; const dataProvider = fakeRestProvider(fakeData, false); return ( - + @@ -299,6 +299,7 @@ export const TranslateChoice = () => { }), } as any } + defaultTheme="light" > diff --git a/packages/ra-ui-materialui/src/input/SelectInput.stories.tsx b/packages/ra-ui-materialui/src/input/SelectInput.stories.tsx index b0cccbbec0e..a8200aeb199 100644 --- a/packages/ra-ui-materialui/src/input/SelectInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/SelectInput.stories.tsx @@ -49,6 +49,7 @@ export const InitialValue = () => ( getOne: () => Promise.resolve({ data: { id: 1, gender: 'F' } }), } as any } + defaultTheme="light" > @@ -176,6 +177,7 @@ const Wrapper = ({ children, onSuccess = console.log }) => ( Promise.resolve({ data: { id: 1, ...params.data } }), } as any } + defaultTheme="light" > { }), } as any } + defaultTheme="light" > diff --git a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx index 45b1925ac7d..44ceb043e83 100644 --- a/packages/ra-ui-materialui/src/input/TextInput.stories.tsx +++ b/packages/ra-ui-materialui/src/input/TextInput.stories.tsx @@ -12,134 +12,86 @@ import { FormInspector } from './common'; export default { title: 'ra-ui-materialui/input/TextInput' }; -export const Basic = () => ( - +export const Wrapper = ({ children }) => ( + - - - - + {children} ); +export const Basic = () => ( + + + + +); + export const DefaultValue = () => ( - - - - - - - - - - - - - - + + + + + + + + + + ); export const HelperText = () => ( - - - - - - - - - + + + + + ); export const Label = () => ( - - - - - - - - - + + + + + ); export const FullWidth = () => ( - - - - - - - - + + + + ); export const Margin = () => ( - - - - - - - - - + + + + + ); export const Variant = () => ( - - - - - - - - - + + + + + ); export const Required = () => ( - + ( ); export const Error = () => ( - + ( ); export const Sx = () => ( - - - - - - - + + + ); export const ExtraProps = () => ( - + { }; export const FieldState = () => ( - - - - - - - - - + + + + + ); const AlwaysOnToolbar = ( @@ -281,6 +217,7 @@ export const ValueUndefined = ({ onSuccess = console.log }) => ( update: (resource, { data }) => Promise.resolve({ data }), } as any } + defaultTheme="light" > ( update: (resource, { data }) => Promise.resolve({ data }), } as any } + defaultTheme="light" > ( ); export const Parse = ({ onSuccess = console.log }) => ( - + ( const i18nProvider = polyglotI18nProvider(() => englishMessages); const Wrapper = ({ children }) => ( - + {children} diff --git a/packages/ra-ui-materialui/src/input/TranslatableInputs.stories.tsx b/packages/ra-ui-materialui/src/input/TranslatableInputs.stories.tsx index eb42b389914..4e8976053f7 100644 --- a/packages/ra-ui-materialui/src/input/TranslatableInputs.stories.tsx +++ b/packages/ra-ui-materialui/src/input/TranslatableInputs.stories.tsx @@ -64,7 +64,7 @@ export const Sx = () => ( const i18nProvider = polyglotI18nProvider(() => englishMessages); const Wrapper = ({ children }) => ( - + {children} diff --git a/packages/ra-ui-materialui/src/input/inputs.stories.tsx b/packages/ra-ui-materialui/src/input/inputs.stories.tsx index 036bae16762..e8d4af02464 100644 --- a/packages/ra-ui-materialui/src/input/inputs.stories.tsx +++ b/packages/ra-ui-materialui/src/input/inputs.stories.tsx @@ -35,7 +35,7 @@ export default { const i18nProvider = polyglotI18nProvider(() => englishMessages); export const AllInputs = () => ( - + ( <> @@ -48,7 +45,6 @@ export const Default = () => { store={memoryStore()} dataProvider={testDataProvider()} layout={DefaultLayout} - darkTheme={darkTheme} > {resources.map((resource, index) => ( <Resource @@ -70,7 +66,6 @@ export const Dense = () => { store={memoryStore()} dataProvider={testDataProvider()} layout={LayoutDense} - darkTheme={darkTheme} > {resources.map((resource, index) => ( <Resource diff --git a/packages/ra-ui-materialui/src/list/filter/SavedQueriesList.stories.tsx b/packages/ra-ui-materialui/src/list/filter/SavedQueriesList.stories.tsx index e3d5d4d16c6..9dc628a5bb4 100644 --- a/packages/ra-ui-materialui/src/list/filter/SavedQueriesList.stories.tsx +++ b/packages/ra-ui-materialui/src/list/filter/SavedQueriesList.stories.tsx @@ -3,7 +3,6 @@ import merge from 'lodash/merge'; import { Admin, - defaultTheme, Resource, Datagrid, List, @@ -23,7 +22,6 @@ import frenchMessages from 'ra-language-french'; import { createMemoryHistory } from 'history'; import { SavedQueriesList } from './SavedQueriesList'; -import { RaThemeOptions } from '../..'; import fakeRestProvider from 'ra-data-fakerest'; export default { title: 'ra-ui-materialui/list/filter/SavedQueriesList' }; @@ -188,26 +186,12 @@ const i18nProvider = polyglotI18nProvider( ] ); -const darkTheme: RaThemeOptions = { - ...defaultTheme, - palette: { - secondary: { - light: '#5f5fc4', - main: '#283593', - dark: '#001064', - contrastText: '#fff', - }, - mode: 'dark', - }, -}; - export const WithThemeAndLocale = () => ( <Admin store={memoryStore()} history={createMemoryHistory()} i18nProvider={i18nProvider} dataProvider={dataProvider} - darkTheme={darkTheme} > <Resource name="songs" list={SongList} /> </Admin> diff --git a/packages/ra-ui-materialui/src/theme/defaultTheme.stories.tsx b/packages/ra-ui-materialui/src/theme/defaultTheme.stories.tsx index e0ceefc9338..db5f90b98c9 100644 --- a/packages/ra-ui-materialui/src/theme/defaultTheme.stories.tsx +++ b/packages/ra-ui-materialui/src/theme/defaultTheme.stories.tsx @@ -8,7 +8,6 @@ import { AdminContext } from '../AdminContext'; import { AdminUI } from '../AdminUI'; import { ListGuesser } from '../list'; import { EditGuesser } from '../detail'; -import { defaultLightTheme, defaultDarkTheme } from './defaultTheme'; import { testData } from './testData'; export default { @@ -18,8 +17,6 @@ export default { export const Default = () => ( <AdminContext dataProvider={fakerestDataProvider(testData)} - lightTheme={defaultLightTheme} - darkTheme={defaultDarkTheme} defaultTheme="light" i18nProvider={polyglotI18nProvider(() => englishTranslations, 'en')} > diff --git a/packages/ra-ui-materialui/src/theme/themePriority.stories.tsx b/packages/ra-ui-materialui/src/theme/themePriority.stories.tsx new file mode 100644 index 00000000000..e09074fe78e --- /dev/null +++ b/packages/ra-ui-materialui/src/theme/themePriority.stories.tsx @@ -0,0 +1,192 @@ +import * as React from 'react'; +import { Resource } from 'ra-core'; +import fakerestDataProvider from 'ra-data-fakerest'; +import englishTranslations from 'ra-language-english'; +import polyglotI18nProvider from 'ra-i18n-polyglot'; + +import { AdminContext } from '../AdminContext'; +import { AdminUI } from '../AdminUI'; +import { ListGuesser } from '../list'; +import { EditGuesser } from '../detail'; +import { testData } from './testData'; +import { nanoDarkTheme, nanoLightTheme } from './nanoTheme'; +import { radiantDarkTheme, radiantLightTheme } from './radiantTheme'; + +export default { + title: 'ra-ui-materialui/theme/Priority', +}; + +export const DefaultLightAndDarkTheme = () => ( + <AdminContext + dataProvider={fakerestDataProvider(testData)} + i18nProvider={polyglotI18nProvider(() => englishTranslations, 'en')} + > + <AdminUI> + <Resource + name="products" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="categories" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="tags" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + </AdminUI> + </AdminContext> +); + +export const DisableDarkTheme = () => ( + <AdminContext + dataProvider={fakerestDataProvider(testData)} + i18nProvider={polyglotI18nProvider(() => englishTranslations, 'en')} + darkTheme={null} + > + <AdminUI> + <Resource + name="products" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="categories" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="tags" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + </AdminUI> + </AdminContext> +); + +export const CustomMasterThemeAndNoDarkTheme = () => ( + <AdminContext + dataProvider={fakerestDataProvider(testData)} + i18nProvider={polyglotI18nProvider(() => englishTranslations, 'en')} + theme={nanoLightTheme} + > + <AdminUI> + <Resource + name="products" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="categories" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="tags" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + </AdminUI> + </AdminContext> +); + +export const CustomMasterThemeAndCustomDarkTheme = () => ( + <AdminContext + dataProvider={fakerestDataProvider(testData)} + i18nProvider={polyglotI18nProvider(() => englishTranslations, 'en')} + theme={nanoLightTheme} + darkTheme={radiantDarkTheme} + > + <AdminUI> + <Resource + name="products" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="categories" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="tags" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + </AdminUI> + </AdminContext> +); + +export const DefaultLighThemeAndCustomDarkTheme = () => ( + <AdminContext + dataProvider={fakerestDataProvider(testData)} + i18nProvider={polyglotI18nProvider(() => englishTranslations, 'en')} + darkTheme={nanoDarkTheme} + > + <AdminUI> + <Resource + name="products" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="categories" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="tags" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + </AdminUI> + </AdminContext> +); + +export const CustomLighThemeAndCustomDarkTheme = () => ( + <AdminContext + dataProvider={fakerestDataProvider(testData)} + i18nProvider={polyglotI18nProvider(() => englishTranslations, 'en')} + lightTheme={radiantLightTheme} + darkTheme={nanoDarkTheme} + > + <AdminUI> + <Resource + name="products" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="categories" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + <Resource + name="tags" + list={ListGuesser} + edit={EditGuesser} + recordRepresentation="name" + /> + </AdminUI> + </AdminContext> +);