diff --git a/docs/data/joy/components/input/DebouncedInput.js b/docs/data/joy/components/input/DebouncedInput.js
new file mode 100644
index 00000000000000..0e754c0d7a67fb
--- /dev/null
+++ b/docs/data/joy/components/input/DebouncedInput.js
@@ -0,0 +1,45 @@
+import * as React from 'react';
+import PropTypes from 'prop-types';
+import Input from '@mui/joy/Input';
+import Typography from '@mui/joy/Typography';
+import Box from '@mui/joy/Box';
+
+function DebounceInput(props) {
+ const { handleDebounce, debounceTimeout, ...rest } = props;
+
+ const timerRef = React.useRef();
+
+ const handleChange = (event) => {
+ if (timerRef.current) {
+ clearTimeout(timerRef.current);
+ }
+
+ timerRef.current = window.setTimeout(() => {
+ handleDebounce(event.target.value);
+ }, debounceTimeout);
+ };
+
+ return ;
+}
+
+DebounceInput.propTypes = {
+ debounceTimeout: PropTypes.number.isRequired,
+ handleDebounce: PropTypes.func.isRequired,
+};
+
+export default function DebouncedInput() {
+ const [debouncedValue, setDebouncedValue] = React.useState('');
+ const handleDebounce = (value) => {
+ setDebouncedValue(value);
+ };
+ return (
+
+
+ Debounced input: {debouncedValue}
+
+ );
+}
diff --git a/docs/data/joy/components/input/DebouncedInput.tsx b/docs/data/joy/components/input/DebouncedInput.tsx
new file mode 100644
index 00000000000000..ed4db9dc6a53ad
--- /dev/null
+++ b/docs/data/joy/components/input/DebouncedInput.tsx
@@ -0,0 +1,44 @@
+import * as React from 'react';
+import Input, { InputProps } from '@mui/joy/Input';
+import Typography from '@mui/joy/Typography';
+import Box from '@mui/joy/Box';
+
+type DebounceProps = {
+ handleDebounce: (value: string) => void;
+ debounceTimeout: number;
+};
+
+function DebounceInput(props: InputProps & DebounceProps) {
+ const { handleDebounce, debounceTimeout, ...rest } = props;
+
+ const timerRef = React.useRef();
+
+ const handleChange = (event: React.ChangeEvent) => {
+ if (timerRef.current) {
+ clearTimeout(timerRef.current);
+ }
+
+ timerRef.current = window.setTimeout(() => {
+ handleDebounce(event.target.value);
+ }, debounceTimeout);
+ };
+
+ return ;
+}
+
+export default function DebouncedInput() {
+ const [debouncedValue, setDebouncedValue] = React.useState('');
+ const handleDebounce = (value: string) => {
+ setDebouncedValue(value);
+ };
+ return (
+
+
+ Debounced input: {debouncedValue}
+
+ );
+}
diff --git a/docs/data/joy/components/input/DebouncedInput.tsx.preview b/docs/data/joy/components/input/DebouncedInput.tsx.preview
new file mode 100644
index 00000000000000..2a0890efa003b8
--- /dev/null
+++ b/docs/data/joy/components/input/DebouncedInput.tsx.preview
@@ -0,0 +1,6 @@
+
+Debounced input: {debouncedValue}
\ No newline at end of file
diff --git a/docs/data/joy/components/input/InputValidation.js b/docs/data/joy/components/input/InputValidation.js
index 1ec7d7f4047161..d9f49b478f9ae5 100644
--- a/docs/data/joy/components/input/InputValidation.js
+++ b/docs/data/joy/components/input/InputValidation.js
@@ -12,11 +12,7 @@ export default function InputValidation() {
Label
-
+
Opps! something is wrong.
diff --git a/docs/data/joy/components/input/InputValidation.tsx b/docs/data/joy/components/input/InputValidation.tsx
index 1ec7d7f4047161..d9f49b478f9ae5 100644
--- a/docs/data/joy/components/input/InputValidation.tsx
+++ b/docs/data/joy/components/input/InputValidation.tsx
@@ -12,11 +12,7 @@ export default function InputValidation() {
Label
-
+
Opps! something is wrong.
diff --git a/docs/data/joy/components/input/InputValidation.tsx.preview b/docs/data/joy/components/input/InputValidation.tsx.preview
index e97fcad5d4c178..69f14112e61517 100644
--- a/docs/data/joy/components/input/InputValidation.tsx.preview
+++ b/docs/data/joy/components/input/InputValidation.tsx.preview
@@ -1,11 +1,7 @@
Label
-
+
Opps! something is wrong.
diff --git a/docs/data/joy/components/input/input.md b/docs/data/joy/components/input/input.md
index cd2fc91805c666..41f1830a77a8ea 100644
--- a/docs/data/joy/components/input/input.md
+++ b/docs/data/joy/components/input/input.md
@@ -166,6 +166,10 @@ To create a floating label input, a custom component (combination of `` a
{{"demo": "PasswordMeterInput.js"}}
+### Debounced Input
+
+{{"demo": "DebouncedInput.js"}}
+
### Third-party formatting
The Input component can be integrated with third-party formatting libraries for more complex use cases.
diff --git a/docs/data/joy/components/list/ExampleCollapsibleList.js b/docs/data/joy/components/list/ExampleCollapsibleList.js
index 821c5149ded610..d80f04b1f1e7eb 100644
--- a/docs/data/joy/components/list/ExampleCollapsibleList.js
+++ b/docs/data/joy/components/list/ExampleCollapsibleList.js
@@ -89,7 +89,7 @@ export default function ExampleCollapsibleList() {
>
Tutorial
-
+
9
@@ -140,7 +140,7 @@ export default function ExampleCollapsibleList() {
>
How-to Guides
-
+
39
diff --git a/docs/data/joy/components/list/ExampleCollapsibleList.tsx b/docs/data/joy/components/list/ExampleCollapsibleList.tsx
index 985d404b6eaf48..ca274e4fb84b30 100644
--- a/docs/data/joy/components/list/ExampleCollapsibleList.tsx
+++ b/docs/data/joy/components/list/ExampleCollapsibleList.tsx
@@ -91,7 +91,7 @@ export default function ExampleCollapsibleList() {
>
Tutorial
-
+
9
@@ -142,7 +142,7 @@ export default function ExampleCollapsibleList() {
>
How-to Guides
-
+
39
diff --git a/docs/data/joy/components/list/ExampleIOSList.js b/docs/data/joy/components/list/ExampleIOSList.js
index 3293aea42a60f6..9cdc36ab908d6a 100644
--- a/docs/data/joy/components/list/ExampleIOSList.js
+++ b/docs/data/joy/components/list/ExampleIOSList.js
@@ -162,7 +162,12 @@ export default function ExampleIOSList() {
Wi-Fi
- Mars
+
+ Mars
+
@@ -175,7 +180,12 @@ export default function ExampleIOSList() {
Bluetooth
- On
+
+ On
+
diff --git a/docs/data/joy/components/list/ExampleIOSList.tsx b/docs/data/joy/components/list/ExampleIOSList.tsx
index 3293aea42a60f6..9cdc36ab908d6a 100644
--- a/docs/data/joy/components/list/ExampleIOSList.tsx
+++ b/docs/data/joy/components/list/ExampleIOSList.tsx
@@ -162,7 +162,12 @@ export default function ExampleIOSList() {
Wi-Fi
- Mars
+
+ Mars
+
@@ -175,7 +180,12 @@ export default function ExampleIOSList() {
Bluetooth
- On
+
+ On
+
diff --git a/docs/data/joy/components/list/ExampleNavigationMenu.js b/docs/data/joy/components/list/ExampleNavigationMenu.js
index abf7d3788a9d71..b7b18e89b5014c 100644
--- a/docs/data/joy/components/list/ExampleNavigationMenu.js
+++ b/docs/data/joy/components/list/ExampleNavigationMenu.js
@@ -302,6 +302,7 @@ export default function ExampleNavigationMenu() {
'--List-radius': '8px',
'--List-padding': '4px',
'--List-gap': '8px',
+ '--ListItem-gap': '0px',
}}
>
diff --git a/docs/data/joy/components/list/ExampleNavigationMenu.tsx b/docs/data/joy/components/list/ExampleNavigationMenu.tsx
index 81a386557d40be..1106cd57a02304 100644
--- a/docs/data/joy/components/list/ExampleNavigationMenu.tsx
+++ b/docs/data/joy/components/list/ExampleNavigationMenu.tsx
@@ -337,6 +337,7 @@ export default function ExampleNavigationMenu() {
'--List-radius': '8px',
'--List-padding': '4px',
'--List-gap': '8px',
+ '--ListItem-gap': '0px',
}}
>
diff --git a/docs/data/joy/components/switch/ExampleMaterialSwitch.js b/docs/data/joy/components/switch/ExampleMaterialSwitch.js
deleted file mode 100644
index aa1773f03e7db6..00000000000000
--- a/docs/data/joy/components/switch/ExampleMaterialSwitch.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import * as React from 'react';
-import Switch, { switchClasses } from '@mui/joy/Switch';
-
-export default function ExampleMaterialSwitch() {
- const [checked, setChecked] = React.useState(false);
- return (
- setChecked(event.target.checked)}
- sx={(theme) => ({
- display: 'inherit',
- '--Switch-thumbShadow':
- 'rgb(0 0 0 / 20%) 0px 2px 1px -1px, rgb(0 0 0 / 14%) 0px 1px 1px 0px, rgb(0 0 0 / 12%) 0px 1px 3px 0px',
- '--Switch-thumbSize': '20px',
- '--Switch-trackWidth': '34px',
- '--Switch-trackHeight': '14px',
- '--Switch-trackBackground': 'rgb(0, 0, 0, 0.38)',
- '&:hover': {
- '--Switch-trackBackground': 'rgb(0, 0, 0, 0.38)',
- },
- [`&.${switchClasses.checked}`]: {
- '--Switch-thumbBackground': 'rgb(25, 118, 210)',
- '--Switch-trackBackground': 'rgba(25, 118, 210, 0.5)',
- '&:hover': {
- '--Switch-trackBackground': 'rgba(25, 118, 210, 0.5)',
- },
- },
- [`&.${switchClasses.disabled}`]: {
- '--Switch-trackBackground': 'rgb(0, 0, 0, 0.12)',
- '--Switch-thumbColor': 'rgb(245, 245, 245)',
- },
- [`&.${switchClasses.checked}.${switchClasses.disabled}`]: {
- '--Switch-trackBackground': 'rgba(25, 118, 210, 0.12)',
- '--Switch-thumbColor': 'rgb(167, 202, 237)',
- },
- [theme.getColorSchemeSelector('dark')]: {
- '--Switch-thumbBackground': '#fff',
- '--Switch-trackBackground': 'rgba(255, 255, 255, 0.3)',
- [`&.${switchClasses.checked}`]: {
- '--Switch-thumbBackground': 'rgb(144, 202, 249)',
- '--Switch-trackBackground': 'rgba(144, 202, 249, 0.5)',
- },
- },
- })}
- />
- );
-}
diff --git a/docs/data/joy/components/switch/ExampleMaterialSwitch.tsx b/docs/data/joy/components/switch/ExampleMaterialSwitch.tsx
deleted file mode 100644
index 3feb62e218f0ad..00000000000000
--- a/docs/data/joy/components/switch/ExampleMaterialSwitch.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import * as React from 'react';
-import Switch, { switchClasses } from '@mui/joy/Switch';
-import { Theme } from '@mui/joy';
-
-export default function ExampleMaterialSwitch() {
- const [checked, setChecked] = React.useState(false);
- return (
- ) =>
- setChecked(event.target.checked)
- }
- sx={(theme: Theme) => ({
- display: 'inherit',
- '--Switch-thumbShadow':
- 'rgb(0 0 0 / 20%) 0px 2px 1px -1px, rgb(0 0 0 / 14%) 0px 1px 1px 0px, rgb(0 0 0 / 12%) 0px 1px 3px 0px',
- '--Switch-thumbSize': '20px',
- '--Switch-trackWidth': '34px',
- '--Switch-trackHeight': '14px',
- '--Switch-trackBackground': 'rgb(0, 0, 0, 0.38)',
- '&:hover': {
- '--Switch-trackBackground': 'rgb(0, 0, 0, 0.38)',
- },
- [`&.${switchClasses.checked}`]: {
- '--Switch-thumbBackground': 'rgb(25, 118, 210)',
- '--Switch-trackBackground': 'rgba(25, 118, 210, 0.5)',
- '&:hover': {
- '--Switch-trackBackground': 'rgba(25, 118, 210, 0.5)',
- },
- },
- [`&.${switchClasses.disabled}`]: {
- '--Switch-trackBackground': 'rgb(0, 0, 0, 0.12)',
- '--Switch-thumbColor': 'rgb(245, 245, 245)',
- },
- [`&.${switchClasses.checked}.${switchClasses.disabled}`]: {
- '--Switch-trackBackground': 'rgba(25, 118, 210, 0.12)',
- '--Switch-thumbColor': 'rgb(167, 202, 237)',
- },
- [theme.getColorSchemeSelector('dark')]: {
- '--Switch-thumbBackground': '#fff',
- '--Switch-trackBackground': 'rgba(255, 255, 255, 0.3)',
- [`&.${switchClasses.checked}`]: {
- '--Switch-thumbBackground': 'rgb(144, 202, 249)',
- '--Switch-trackBackground': 'rgba(144, 202, 249, 0.5)',
- },
- },
- })}
- />
- );
-}
diff --git a/docs/data/joy/components/switch/ExampleThumbChild.js b/docs/data/joy/components/switch/ExampleThumbChild.js
index 401e8e02048fef..37a88bd60e0e74 100644
--- a/docs/data/joy/components/switch/ExampleThumbChild.js
+++ b/docs/data/joy/components/switch/ExampleThumbChild.js
@@ -5,6 +5,7 @@ import DarkMode from '@mui/icons-material/DarkMode';
export default function ExampleThumbChild() {
return (
);
diff --git a/docs/data/joy/components/switch/ExampleThumbChild.tsx b/docs/data/joy/components/switch/ExampleThumbChild.tsx
index 401e8e02048fef..37a88bd60e0e74 100644
--- a/docs/data/joy/components/switch/ExampleThumbChild.tsx
+++ b/docs/data/joy/components/switch/ExampleThumbChild.tsx
@@ -5,6 +5,7 @@ import DarkMode from '@mui/icons-material/DarkMode';
export default function ExampleThumbChild() {
return (
);
diff --git a/docs/data/joy/components/switch/ExampleThumbChild.tsx.preview b/docs/data/joy/components/switch/ExampleThumbChild.tsx.preview
index 2c1754d3ac3fa2..583800c0d187df 100644
--- a/docs/data/joy/components/switch/ExampleThumbChild.tsx.preview
+++ b/docs/data/joy/components/switch/ExampleThumbChild.tsx.preview
@@ -1,4 +1,5 @@
\ No newline at end of file
diff --git a/docs/data/joy/components/switch/switch.md b/docs/data/joy/components/switch/switch.md
index 2f4f058c6e7d40..eb59edab5ec6c6 100644
--- a/docs/data/joy/components/switch/switch.md
+++ b/docs/data/joy/components/switch/switch.md
@@ -92,15 +92,9 @@ You can use those to customize the component on both the `sx` prop and the theme
## Common examples
-### Material Design
-
-You can also find the Material Design switch design, out of the box, in [Material UI's documentation](/material-ui/react-switch/).
-
-{{"demo": "ExampleMaterialSwitch.js"}}
-
### Fluent UI
-Here's how you'd customize Joy UI's switch to make it look like [Microsoft's Fluent UI](https://developer.microsoft.com/en-us/fluentui#/controls/web/toggle):
+Here's how you'd customize Joy UI's Switch to make it look like [Microsoft's Fluent UI](https://developer.microsoft.com/en-us/fluentui#/controls/web/toggle):
- Unchecked state: `outlined` variant and `neutral` color.
- Checked state: `solid` variant and `primary` color.
diff --git a/docs/data/joy/components/tabs/TabsBottomNavExample.js b/docs/data/joy/components/tabs/TabsBottomNavExample.js
index 2267777076214a..dfba30950d38ca 100644
--- a/docs/data/joy/components/tabs/TabsBottomNavExample.js
+++ b/docs/data/joy/components/tabs/TabsBottomNavExample.js
@@ -4,7 +4,7 @@ import ListItemDecorator from '@mui/joy/ListItemDecorator';
import Tabs from '@mui/joy/Tabs';
import TabList from '@mui/joy/TabList';
import Tab, { tabClasses } from '@mui/joy/Tab';
-import HomeOutlined from '@mui/icons-material/HomeOutlined';
+import HomeRoundedIcon from '@mui/icons-material/HomeRounded';
import FavoriteBorder from '@mui/icons-material/FavoriteBorder';
import Search from '@mui/icons-material/Search';
import Person from '@mui/icons-material/Person';
@@ -17,8 +17,7 @@ export default function TabsBottomNavExample() {
sx={{
flexGrow: 1,
m: -3,
- p: 3,
- py: 5,
+ p: 4,
borderTopLeftRadius: '12px',
borderTopRightRadius: '12px',
bgcolor: `${colors[index]}.500`,
@@ -31,30 +30,36 @@ export default function TabsBottomNavExample() {
onChange={(event, value) => setIndex(value)}
sx={(theme) => ({
p: 1,
- borderRadius: '24px',
+ borderRadius: 16,
maxWidth: 400,
mx: 'auto',
boxShadow: theme.shadow.sm,
'--joy-shadowChannel': theme.vars.palette[colors[index]].darkChannel,
[`& .${tabClasses.root}`]: {
- whiteSpace: 'nowrap',
+ py: 1,
+ flex: 1,
transition: '0.3s',
fontWeight: 'md',
- flex: 1,
+ fontSize: 'md',
[`&:not(.${tabClasses.selected}):not(:hover)`]: {
- opacity: 0.72,
+ opacity: 0.7,
},
},
})}
>
-
+
-
+
Home
diff --git a/docs/data/joy/components/tabs/TabsBottomNavExample.tsx b/docs/data/joy/components/tabs/TabsBottomNavExample.tsx
index 6ade044bb8a479..aa59d760955eba 100644
--- a/docs/data/joy/components/tabs/TabsBottomNavExample.tsx
+++ b/docs/data/joy/components/tabs/TabsBottomNavExample.tsx
@@ -4,7 +4,7 @@ import ListItemDecorator from '@mui/joy/ListItemDecorator';
import Tabs from '@mui/joy/Tabs';
import TabList from '@mui/joy/TabList';
import Tab, { tabClasses } from '@mui/joy/Tab';
-import HomeOutlined from '@mui/icons-material/HomeOutlined';
+import HomeRoundedIcon from '@mui/icons-material/HomeRounded';
import FavoriteBorder from '@mui/icons-material/FavoriteBorder';
import Search from '@mui/icons-material/Search';
import Person from '@mui/icons-material/Person';
@@ -17,8 +17,7 @@ export default function TabsBottomNavExample() {
sx={{
flexGrow: 1,
m: -3,
- p: 3,
- py: 5,
+ p: 4,
borderTopLeftRadius: '12px',
borderTopRightRadius: '12px',
bgcolor: `${colors[index]}.500`,
@@ -31,30 +30,36 @@ export default function TabsBottomNavExample() {
onChange={(event, value) => setIndex(value as number)}
sx={(theme) => ({
p: 1,
- borderRadius: '24px',
+ borderRadius: 16,
maxWidth: 400,
mx: 'auto',
boxShadow: theme.shadow.sm,
'--joy-shadowChannel': theme.vars.palette[colors[index]].darkChannel,
[`& .${tabClasses.root}`]: {
- whiteSpace: 'nowrap',
+ py: 1,
+ flex: 1,
transition: '0.3s',
fontWeight: 'md',
- flex: 1,
+ fontSize: 'md',
[`&:not(.${tabClasses.selected}):not(:hover)`]: {
- opacity: 0.72,
+ opacity: 0.7,
},
},
})}
>
-
+
-
+
Home
diff --git a/docs/data/joy/components/tabs/TabsPageExample.js b/docs/data/joy/components/tabs/TabsPageExample.js
index 915b48892859f3..bd5867ea4b1de5 100644
--- a/docs/data/joy/components/tabs/TabsPageExample.js
+++ b/docs/data/joy/components/tabs/TabsPageExample.js
@@ -5,9 +5,6 @@ import Tabs from '@mui/joy/Tabs';
import TabList from '@mui/joy/TabList';
import Tab, { tabClasses } from '@mui/joy/Tab';
import TabPanel from '@mui/joy/TabPanel';
-import Typography from '@mui/joy/Typography';
-import Input from '@mui/joy/Input';
-import SearchRounded from '@mui/icons-material/SearchRounded';
export default function TabsPageExample() {
const [index, setIndex] = React.useState(0);
@@ -15,9 +12,8 @@ export default function TabsPageExample() {
14
@@ -64,12 +59,20 @@ export default function TabsPageExample() {
size="sm"
variant="soft"
color={index === 1 ? 'primary' : 'neutral'}
- sx={{ ml: 1 }}
>
- 24
+ 20
+
+
+
+ Products{' '}
+
+ 8
- Search library
({
@@ -79,33 +82,9 @@ export default function TabsPageExample() {
clipPath: 'inset(0 -100vmax)',
})}
>
-
-
- Deals panel
-
-
-
-
- Library panel
-
-
-
- }
- />
-
+ Deals
+ Library
+ Products
diff --git a/docs/data/joy/components/tabs/TabsPageExample.tsx b/docs/data/joy/components/tabs/TabsPageExample.tsx
index 745afb97f0faf2..c6b9012c86e25d 100644
--- a/docs/data/joy/components/tabs/TabsPageExample.tsx
+++ b/docs/data/joy/components/tabs/TabsPageExample.tsx
@@ -5,9 +5,6 @@ import Tabs from '@mui/joy/Tabs';
import TabList from '@mui/joy/TabList';
import Tab, { tabClasses } from '@mui/joy/Tab';
import TabPanel from '@mui/joy/TabPanel';
-import Typography from '@mui/joy/Typography';
-import Input from '@mui/joy/Input';
-import SearchRounded from '@mui/icons-material/SearchRounded';
export default function TabsPageExample() {
const [index, setIndex] = React.useState(0);
@@ -15,9 +12,8 @@ export default function TabsPageExample() {
14
@@ -64,12 +59,20 @@ export default function TabsPageExample() {
size="sm"
variant="soft"
color={index === 1 ? 'primary' : 'neutral'}
- sx={{ ml: 1 }}
>
- 24
+ 20
+
+
+
+ Products{' '}
+
+ 8
- Search library
({
@@ -79,33 +82,9 @@ export default function TabsPageExample() {
clipPath: 'inset(0 -100vmax)',
})}
>
-
-
- Deals panel
-
-
-
-
- Library panel
-
-
-
- }
- />
-
+ Deals
+ Library
+ Products
diff --git a/docs/data/joy/components/tabs/TabsScrollable.js b/docs/data/joy/components/tabs/TabsScrollable.js
new file mode 100644
index 00000000000000..dcbde11e12df18
--- /dev/null
+++ b/docs/data/joy/components/tabs/TabsScrollable.js
@@ -0,0 +1,24 @@
+import * as React from 'react';
+import Tabs from '@mui/joy/Tabs';
+import TabList from '@mui/joy/TabList';
+import Tab from '@mui/joy/Tab';
+
+export default function TabsScrollable() {
+ return (
+
+
+ {[...Array(20)].map((_, index) => (
+
+ Tab #{index + 1}
+
+ ))}
+
+
+ );
+}
diff --git a/docs/data/joy/components/tabs/TabsScrollable.tsx b/docs/data/joy/components/tabs/TabsScrollable.tsx
new file mode 100644
index 00000000000000..dcbde11e12df18
--- /dev/null
+++ b/docs/data/joy/components/tabs/TabsScrollable.tsx
@@ -0,0 +1,24 @@
+import * as React from 'react';
+import Tabs from '@mui/joy/Tabs';
+import TabList from '@mui/joy/TabList';
+import Tab from '@mui/joy/Tab';
+
+export default function TabsScrollable() {
+ return (
+
+
+ {[...Array(20)].map((_, index) => (
+
+ Tab #{index + 1}
+
+ ))}
+
+
+ );
+}
diff --git a/docs/data/joy/components/tabs/TabsScrollable.tsx.preview b/docs/data/joy/components/tabs/TabsScrollable.tsx.preview
new file mode 100644
index 00000000000000..0c9dd0e2f1335f
--- /dev/null
+++ b/docs/data/joy/components/tabs/TabsScrollable.tsx.preview
@@ -0,0 +1,15 @@
+
+
+ {[...Array(20)].map((_, index) => (
+
+ Tab #{index + 1}
+
+ ))}
+
+
\ No newline at end of file
diff --git a/docs/data/joy/components/tabs/TabsUsage.js b/docs/data/joy/components/tabs/TabsUsage.js
index 7f1f6d90958183..9451554a2ee17e 100644
--- a/docs/data/joy/components/tabs/TabsUsage.js
+++ b/docs/data/joy/components/tabs/TabsUsage.js
@@ -4,6 +4,7 @@ import TabList from '@mui/joy/TabList';
import Tab from '@mui/joy/Tab';
import TabPanel from '@mui/joy/TabPanel';
import JoyUsageDemo from 'docs/src/modules/components/JoyUsageDemo';
+import Apps from '@mui/icons-material/Apps';
export default function TabsUsage() {
const [index, setIndex] = React.useState(0);
@@ -108,6 +109,7 @@ export default function TabsUsage() {
disableIndicator={disableIndicator}
{...(index === 0 && { color, variant })}
>
+
Tab A
-
- Tab A
- Tab B
- Tab C
-
-
- );
-}
```
-### Basic usage
+The Joy UI set of Tabs components follows the [WAI ARIA design pattern guidelines](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/).
-The tabs structure follows [WAI ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/).
-To target the initially selected tab, specify the `value` prop to the `TabPanel` and use `Tabs`'s `defaultValue`.
+Use the `value` prop on the Tab Panel and the `defaultValue` prop on the Tabs component to target the selected tab.
{{"demo": "TabsBasic.js"}}
+### Disabled tab
+
+Use the `disabled` prop to disable interaction and focus.
+
+{{"demo": "TabDisabled.js"}}
+
+## Customization
+
### Variants
-Both `TabList` and `Tab` accept [global variant](/joy-ui/main-features/global-variants/) values, so you can mix and match to get the desired result.
+The `` and `` components accept the global `variant` prop values.
:::info
-A selected `Tab` does not apply `:hover` and `:active` global variant styles.
+When a Tab is selected, it _won't_ apply globally defined `:hover` and `:active` styles.
:::
{{"demo": "TabsVariants.js"}}
-:::info
+:::warning
To learn how to add more variants to the component, check out [Themed components—Extend variants](/joy-ui/customization/themed-components/#extend-variants).
:::
-### Disabled tab
-
-To disable a tab, use the `disabled` prop on the `Tab` component.
-
-{{"demo": "TabDisabled.js"}}
-
### Vertical
-To set the tabs orientation to vertical, use the `orientation="vertical"` on the `Tabs` component.
-Keyboard navigation (e.g. arrow keys) will adapt automatically to the used orientation.
+Use the `orientation="vertical"` prop on the `` component to make it vertical.
+Keyboard navigation using arrow keys adapts automatically.
{{"demo": "TabsVertical.js"}}
-### Placement
+### Indicator placement
-To change the placement, you should provide the value of `top`, `bottom`, `left` or `right`.
-
-This prop can be applied on the TabList component to change the `underlinePlacement` as in the example:
+Use the `underlinePlacement` prop on the Tab List component to change the placement of the underline border on the Tabs.
{{"demo": "TabsUnderlinePlacement.js"}}
-Or, it can be applied on the Tab component to change the `indicatorPlacement`:
+Control the selected Tab indicator independently using the `indicatorPlacement` prop.
{{"demo": "TabsIndicatorPlacement.js"}}
-The flex direction of the Tabs component will need to be changed based on each placement.
+Depending on the placement of the underline and the selected indicator, you may need to change the flex direction of the Tabs component.
{{"demo": "TabsFlexPlacement.js"}}
### Sticky
-For long content, you can use the `sticky="top"` prop on the TabList component to keep the tabs visible while scrolling.
-
-To stick the TabList at the bottom, use `sticky="bottom"` and render the TabList at the end of the Tabs component.
+Use the `sticky` prop to anchor the Tab List component at the top or bottom.
+This is ideal for use cases that involve longer content.
{{"demo": "TabsSticky.js"}}
### Tab flex
-Use the `tabFlex` prop on the TabList component to make the Tab elements fill the available space as shown in the example below.
-
-The first demo, `tabFlex={1}`, the Tab elements will fill the available space equally.
+Use the `tabFlex` prop on the Tab List component to make the Tab elements fill the available space, as shown in the example below.
-The second demo, `tabFlex="auto`, the Tab elements will fill the available space equally, but the width of each Tab element will be based on the content.
+- In the first demo, the Tab elements fill the available space using `tabFlex={1}`.
+- In the second demo, the Tab elements fill the available space equally using `tabFlex="auto"`, but the width of each respective element is based on its content.
{{"demo": "TabsFlex.js"}}
-:::success
-The value of the `tabFlex` can be any valid [CSS flex](https://developer.mozilla.org/en-US/docs/Web/CSS/flex) value.
+:::info
+The value of the `tabFlex` prop can be any [valid CSS flex value](https://developer.mozilla.org/en-US/docs/Web/CSS/flex).
:::
### Icon
-Since `TabList` uses the same style as the [`List`](/joy-ui/react-list/) component, you can use the icon directly as a child or use `ListItemDecorator` with a text.
+Since the Tab List component uses the same style as the [List](/joy-ui/react-list/) component, you can use the icon directly as a child, or use List Item Decorator with text.
{{"demo": "TabsIcon.js"}}
{{"demo": "TabsIconWithText.js"}}
-### Accessibility
-
-For ensuring proper accessibility, it's recommended by [ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/#wai-aria-roles-states-and-properties-22) to associate a label to the Tabs component.
-To do that, there are two options:
-
-#### Option one
-
-Render a text element with an `id` and provide `aria-labelledby="$is"`to the Tabs component.
-
-```js
-Meaningful label
-...
-```
+### Scrollable tabs
-#### Option two
+Add the `overflow: auto` property to the Tab List component to make the tabs scrollable.
-When not displaying a text element on the screen, use `aria-label` directly on the Tabs component.
-Screen readers will then properly announce the label.
+Polish it further by hiding the scrollbar with `'&::-webkit-scrollbar': { display: 'none' }`, and snapping the scroll to the edge of the Tab List component with [CSS scroll snap properties](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scroll_snap).
-```js
-...
-```
+{{"demo": "TabsScrollable.js"}}
## CSS variables playground
@@ -161,30 +129,56 @@ You can use those to customize the component on both the `sx` prop and the theme
### Segmented controls
-To mimic the iOS segmented controls, add the border-radius to the `sx` prop of the TabList and set the selected Tab's background to `background.surface`.
+To mimic the segmented controls of iOS, add a border-radius to the Tab List component and set the selected Tab background to `background.surface`.
{{"demo": "TabsSegmentedControls.js"}}
### Browser tabs
-In this example, the Tab's variant is set to `outlined` and the indicator is moved to the top via `indicatorPlacement="top"`. The borders of the Tab are set to `transparent` based on the selected state.
+In this example, the Tab's variant prop is set to `outlined` and the indicator is moved to the top via `indicatorPlacement="top"`.
+The borders are then set to `transparent` based on the selected state.
{{"demo": "TabsBrowserExample.js"}}
### Pricing tabs
-This example removes the background of the selected Tab by targeting `[aria-selected="true"]` on the `sx` prop.
+This example removes the background of the selected Tab by targeting the `aria-selected="true"` attribute.
{{"demo": "TabsPricingExample.js"}}
-### With counter chips
+### Centered tabs
-To render tab items at the center of the TabList, use `justifyContent: 'center'` on the `sx` prop of the TabList and set `flex: initial` to each of the Tab to override the default `flex-grow`.
+To center the Tab components in the Tab List, add the `flex: initial` property to override the default `flex-grow` behavior.
+Then, on the list, add `justifyContent: center`.
{{"demo": "TabsPageExample.js"}}
### Mobile bottom navigation
-In this example, each Tab's is applied with one of the theme's color palette when it is selected.
+In this example, each Tab is painted with a color from the theme when selected.
{{"demo": "TabsBottomNavExample.js"}}
+
+## Accessibility
+
+To ensure proper accessibility, the [ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/#wai-aria-roles-states-and-properties-22) recommends associating a label with the Tabs component.
+There are two options to accomplish this:
+
+### Using the id attribute
+
+Add a text element close to the tabs with the `id` attribute.
+Then add the `aria-labelledby` attribute to the Tabs component.
+Make sure to use meaningful labels for both.
+
+```js
+Meaningful label
+...
+```
+
+### Using aria-label
+
+If a text element does not accompany your Tabs component, use the `aria-label` attribute directly to make it readable by screen readers.
+
+```js
+...
+```
diff --git a/docs/data/joy/customization/creating-themed-components/creating-themed-components.md b/docs/data/joy/customization/creating-themed-components/creating-themed-components.md
index 54abc7ca48ccc4..3234034eb7da95 100644
--- a/docs/data/joy/customization/creating-themed-components/creating-themed-components.md
+++ b/docs/data/joy/customization/creating-themed-components/creating-themed-components.md
@@ -1,6 +1,6 @@
# Creating themed components
-Create your own themeable component with Joy UI theming feature.
+Learn how to create fully custom components that accept your app's theme.
## Introduction
diff --git a/docs/data/joy/getting-started/roadmap/roadmap.md b/docs/data/joy/getting-started/roadmap/roadmap.md
new file mode 100644
index 00000000000000..75cbed1e0ac50c
--- /dev/null
+++ b/docs/data/joy/getting-started/roadmap/roadmap.md
@@ -0,0 +1,31 @@
+# Roadmap
+
+Keep up with ongoing projects and help shape the future of Joy UI.
+
+## Priorization method
+
+Joy UI is a community-driven project, meaning we usually pick the issues and suggestions that resonate the most with the community.
+Therefore, make sure to leave an upvote 👍 on [the GitHub issues](https://github.com/mui/material-ui/issues?q=is:open+is:issue+label:%22package:+joy-ui%22) you are most interested in.
+
+Additionally, the MUI team conducts yearly [developer surveys](/blog/?tags=Developer+survey/), which also serve as key inputs for Joy UI's roadmap.
+Your participation is invaluable—keep an eye on MUI's social media to catch the next survey and help shape the future of this product!
+
+## Keeping track of the roadmap
+
+### Public GitHub project
+
+We use a GitHub project to track initiative prioritization across all MUI Core products, including Joy UI.
+We typically add tasks to the project board after discussing them internally.
+
+[**Visit the Joy UI project board** 👉](https://github.com/orgs/mui/projects/18/views/8)
+
+
+
+### Milestones
+
+We also create milestones within the MUI Core repository (where Joy UI's code base is hosted) to keep track of larger cycles.
+Check it out to keep up with ongoing progress and see which issues have been picked up for the stable release.
+
+[**Visit the Joy UI milestones page** 👉](https://github.com/mui/material-ui/milestone/47)
+
+
diff --git a/docs/data/joy/getting-started/templates/framesx-web-blocks/theme.tsx b/docs/data/joy/getting-started/templates/framesx-web-blocks/theme.tsx
index 6c1305214209e3..23200b104b3231 100644
--- a/docs/data/joy/getting-started/templates/framesx-web-blocks/theme.tsx
+++ b/docs/data/joy/getting-started/templates/framesx-web-blocks/theme.tsx
@@ -55,14 +55,13 @@ export default extendTheme({
JoyInput: {
styleOverrides: {
root: ({ ownerState, theme }) => ({
- ...(ownerState.variant === 'outlined' &&
- ownerState.color !== 'context' && {
- [`&:not(.${inputClasses.focused}):hover::before`]: {
- boxShadow: `inset 0 0 0 2px ${
- theme.vars.palette?.[ownerState.color!]?.outlinedBorder
- }`,
- },
- }),
+ ...(ownerState.variant === 'outlined' && {
+ [`&:not(.${inputClasses.focused}):hover::before`]: {
+ boxShadow: `inset 0 0 0 2px ${
+ theme.vars.palette?.[ownerState.color!]?.outlinedBorder
+ }`,
+ },
+ }),
}),
input: {
caretColor: 'var(--Input-focusedHighlight)',
diff --git a/docs/data/joy/getting-started/templates/messages/components/Sidebar.tsx b/docs/data/joy/getting-started/templates/messages/components/Sidebar.tsx
index b87f727c1cb7d1..8cc4572edc5d53 100644
--- a/docs/data/joy/getting-started/templates/messages/components/Sidebar.tsx
+++ b/docs/data/joy/getting-started/templates/messages/components/Sidebar.tsx
@@ -19,7 +19,7 @@ import Stack from '@mui/joy/Stack';
import SearchRoundedIcon from '@mui/icons-material/SearchRounded';
import HomeRoundedIcon from '@mui/icons-material/HomeRounded';
import DashboardRoundedIcon from '@mui/icons-material/DashboardRounded';
-import CollectionsBookmarkRoundedIcon from '@mui/icons-material/CollectionsBookmarkRounded';
+import ShoppingCartRoundedIcon from '@mui/icons-material/ShoppingCartRounded';
import AssignmentRoundedIcon from '@mui/icons-material/AssignmentRounded';
import QuestionAnswerRoundedIcon from '@mui/icons-material/QuestionAnswerRounded';
import GroupRoundedIcon from '@mui/icons-material/GroupRounded';
@@ -27,7 +27,7 @@ import SupportRoundedIcon from '@mui/icons-material/SupportRounded';
import SettingsRoundedIcon from '@mui/icons-material/SettingsRounded';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
import LogoutRoundedIcon from '@mui/icons-material/LogoutRounded';
-import BadgeRoundedIcon from '@mui/icons-material/BadgeRounded';
+import BrightnessAutoRoundedIcon from '@mui/icons-material/BrightnessAutoRounded';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import ColorSchemeToggle from './ColorSchemeToggle';
@@ -83,8 +83,7 @@ export default function Sidebar() {
height: '100dvh',
width: 'var(--Sidebar-width)',
top: 0,
- p: 1.5,
- py: 2,
+ p: 2,
flexShrink: 0,
display: 'flex',
flexDirection: 'column',
@@ -124,9 +123,9 @@ export default function Sidebar() {
/>
-
+
- Profiles
+ Acme Co.
} placeholder="Search" />
@@ -169,10 +168,14 @@ export default function Sidebar() {
-
-
+
+
- Projects
+ Orders
diff --git a/docs/data/joy/getting-started/templates/order-dashboard/App.tsx b/docs/data/joy/getting-started/templates/order-dashboard/App.tsx
index 480cf9fa1a626f..5be8b04289b5b8 100644
--- a/docs/data/joy/getting-started/templates/order-dashboard/App.tsx
+++ b/docs/data/joy/getting-started/templates/order-dashboard/App.tsx
@@ -12,12 +12,10 @@ import ChevronRightRoundedIcon from '@mui/icons-material/ChevronRightRounded';
import DownloadRoundedIcon from '@mui/icons-material/DownloadRounded';
import useScript from './useScript';
-import FirstSidebar from './components/FirstSidebar';
-import SecondSidebar from './components/SecondSidebar';
+import Sidebar from './components/Sidebar';
import OrderTable from './components/OrderTable';
import OrderList from './components/OrderList';
import Header from './components/Header';
-import ColorSchemeToggle from './components/ColorSchemeToggle';
const useEnhancedEffect =
typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
@@ -39,8 +37,7 @@ export default function JoyOrderDashboardTemplate() {
-
-
+
-
-
-
-
-
-
-
-
-
-
- openSidebar()}>
-
-
-
-
- openSidebar()}>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/docs/data/joy/getting-started/templates/order-dashboard/components/Header.tsx b/docs/data/joy/getting-started/templates/order-dashboard/components/Header.tsx
index d2804b1daac6b7..5a716f84dc4d50 100644
--- a/docs/data/joy/getting-started/templates/order-dashboard/components/Header.tsx
+++ b/docs/data/joy/getting-started/templates/order-dashboard/components/Header.tsx
@@ -4,7 +4,6 @@ import Sheet from '@mui/joy/Sheet';
import IconButton from '@mui/joy/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
-import ColorSchemeToggle from './ColorSchemeToggle';
import { toggleSidebar } from '../utils';
export default function Header() {
@@ -44,7 +43,6 @@ export default function Header() {
>
-
);
}
diff --git a/docs/data/joy/getting-started/templates/order-dashboard/components/SecondSidebar.tsx b/docs/data/joy/getting-started/templates/order-dashboard/components/SecondSidebar.tsx
deleted file mode 100644
index 5e72e1e900c805..00000000000000
--- a/docs/data/joy/getting-started/templates/order-dashboard/components/SecondSidebar.tsx
+++ /dev/null
@@ -1,159 +0,0 @@
-import * as React from 'react';
-import Box from '@mui/joy/Box';
-import Sheet from '@mui/joy/Sheet';
-import List from '@mui/joy/List';
-import ListSubheader from '@mui/joy/ListSubheader';
-import ListItem from '@mui/joy/ListItem';
-import ListItemContent from '@mui/joy/ListItemContent';
-import ListItemDecorator from '@mui/joy/ListItemDecorator';
-import ListItemButton from '@mui/joy/ListItemButton';
-// icons
-import BubbleChartIcon from '@mui/icons-material/BubbleChart';
-import InsertChartIcon from '@mui/icons-material/InsertChart';
-import StarsIcon from '@mui/icons-material/Stars';
-import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
-import AccountBoxIcon from '@mui/icons-material/AccountBox';
-import PeopleRoundedIcon from '@mui/icons-material/PeopleRounded';
-import BadgeRoundedIcon from '@mui/icons-material/BadgeRounded';
-import CreditCardRoundedIcon from '@mui/icons-material/CreditCardRounded';
-import AnalyticsRoundedIcon from '@mui/icons-material/AnalyticsRounded';
-
-import { closeSidebar } from '../utils';
-
-export default function SecondSidebar() {
- return (
-
- closeSidebar()}
- />
-
-
-
- Dashboard
-
-
- closeSidebar()}>
-
-
-
- Overview
-
-
-
- closeSidebar()}>
-
-
-
- Analytics
-
-
-
-
-
-
-
- Orders
-
-
-
- closeSidebar()}>
-
-
-
- Saved reports
-
-
-
- closeSidebar()}>
-
-
-
- User reports
-
-
-
- Workspace
-
-
- closeSidebar()}>
-
-
-
- Groups
-
-
-
- closeSidebar()}>
-
-
-
- Authentication
-
-
-
- closeSidebar()}>
-
-
-
- Billing
-
-
-
- closeSidebar()}>
-
-
-
- Analytics
-
-
-
-
-
- );
-}
diff --git a/docs/data/joy/getting-started/templates/order-dashboard/components/Sidebar.tsx b/docs/data/joy/getting-started/templates/order-dashboard/components/Sidebar.tsx
new file mode 100644
index 00000000000000..15c5c1310c47e6
--- /dev/null
+++ b/docs/data/joy/getting-started/templates/order-dashboard/components/Sidebar.tsx
@@ -0,0 +1,323 @@
+import * as React from 'react';
+import GlobalStyles from '@mui/joy/GlobalStyles';
+import Avatar from '@mui/joy/Avatar';
+import Box from '@mui/joy/Box';
+import Button from '@mui/joy/Button';
+import Card from '@mui/joy/Card';
+import Chip from '@mui/joy/Chip';
+import Divider from '@mui/joy/Divider';
+import IconButton from '@mui/joy/IconButton';
+import Input from '@mui/joy/Input';
+import LinearProgress from '@mui/joy/LinearProgress';
+import List from '@mui/joy/List';
+import ListItem from '@mui/joy/ListItem';
+import ListItemButton, { listItemButtonClasses } from '@mui/joy/ListItemButton';
+import ListItemContent from '@mui/joy/ListItemContent';
+import Typography from '@mui/joy/Typography';
+import Sheet from '@mui/joy/Sheet';
+import Stack from '@mui/joy/Stack';
+import SearchRoundedIcon from '@mui/icons-material/SearchRounded';
+import HomeRoundedIcon from '@mui/icons-material/HomeRounded';
+import DashboardRoundedIcon from '@mui/icons-material/DashboardRounded';
+import ShoppingCartRoundedIcon from '@mui/icons-material/ShoppingCartRounded';
+import AssignmentRoundedIcon from '@mui/icons-material/AssignmentRounded';
+import QuestionAnswerRoundedIcon from '@mui/icons-material/QuestionAnswerRounded';
+import GroupRoundedIcon from '@mui/icons-material/GroupRounded';
+import SupportRoundedIcon from '@mui/icons-material/SupportRounded';
+import SettingsRoundedIcon from '@mui/icons-material/SettingsRounded';
+import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
+import LogoutRoundedIcon from '@mui/icons-material/LogoutRounded';
+import BrightnessAutoRoundedIcon from '@mui/icons-material/BrightnessAutoRounded';
+import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
+
+import ColorSchemeToggle from './ColorSchemeToggle';
+import { closeSidebar } from '../utils';
+
+function Toggler({
+ defaultExpanded = false,
+ renderToggle,
+ children,
+}: {
+ defaultExpanded?: boolean;
+ children: React.ReactNode;
+ renderToggle: (params: {
+ open: boolean;
+ setOpen: React.Dispatch>;
+ }) => React.ReactNode;
+}) {
+ const [open, setOpen] = React.useState(defaultExpanded);
+ return (
+
+ {renderToggle({ open, setOpen })}
+ *': {
+ overflow: 'hidden',
+ },
+ }}
+ >
+ {children}
+
+
+ );
+}
+
+export default function Sidebar() {
+ return (
+
+ ({
+ ':root': {
+ '--Sidebar-width': '220px',
+ [theme.breakpoints.up('lg')]: {
+ '--Sidebar-width': '240px',
+ },
+ },
+ })}
+ />
+ closeSidebar()}
+ />
+
+
+
+
+ Acme Co.
+
+
+ } placeholder="Search" />
+
+ theme.vars.radius.sm,
+ }}
+ >
+
+
+
+
+ Home
+
+
+
+
+
+
+
+
+ Dashboard
+
+
+
+
+
+
+
+
+ Orders
+
+
+
+
+
+ (
+ setOpen(!open)}>
+
+
+ Tasks
+
+
+
+ )}
+ >
+
+
+ All tasks
+
+
+ Backlog
+
+
+ In progress
+
+
+ Done
+
+
+
+
+
+
+
+
+
+ Messages
+
+
+ 4
+
+
+
+
+
+ (
+ setOpen(!open)}>
+
+
+ Users
+
+
+
+ )}
+ >
+
+
+
+ My profile
+
+
+
+ Create a new user
+
+
+ Roles & permission
+
+
+
+
+
+
+ theme.vars.radius.sm,
+ '--List-gap': '8px',
+ mb: 2,
+ }}
+ >
+
+
+
+ Support
+
+
+
+
+
+ Settings
+
+
+
+
+
+ Used space
+
+
+
+
+
+ Your team has used 80% of your available space. Need more?
+
+
+
+
+
+
+
+
+
+ Siriwat K.
+ siriwatk@test.com
+
+
+
+
+
+
+ );
+}
diff --git a/docs/data/joy/getting-started/templates/profile-dashboard/components/Sidebar.tsx b/docs/data/joy/getting-started/templates/profile-dashboard/components/Sidebar.tsx
index e4e50355a08d80..50c6caba5d3e76 100644
--- a/docs/data/joy/getting-started/templates/profile-dashboard/components/Sidebar.tsx
+++ b/docs/data/joy/getting-started/templates/profile-dashboard/components/Sidebar.tsx
@@ -19,7 +19,7 @@ import Stack from '@mui/joy/Stack';
import SearchRoundedIcon from '@mui/icons-material/SearchRounded';
import HomeRoundedIcon from '@mui/icons-material/HomeRounded';
import DashboardRoundedIcon from '@mui/icons-material/DashboardRounded';
-import CollectionsBookmarkRoundedIcon from '@mui/icons-material/CollectionsBookmarkRounded';
+import ShoppingCartRoundedIcon from '@mui/icons-material/ShoppingCartRounded';
import AssignmentRoundedIcon from '@mui/icons-material/AssignmentRounded';
import QuestionAnswerRoundedIcon from '@mui/icons-material/QuestionAnswerRounded';
import GroupRoundedIcon from '@mui/icons-material/GroupRounded';
@@ -27,7 +27,7 @@ import SupportRoundedIcon from '@mui/icons-material/SupportRounded';
import SettingsRoundedIcon from '@mui/icons-material/SettingsRounded';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
import LogoutRoundedIcon from '@mui/icons-material/LogoutRounded';
-import BadgeRoundedIcon from '@mui/icons-material/BadgeRounded';
+import BrightnessAutoRoundedIcon from '@mui/icons-material/BrightnessAutoRounded';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import ColorSchemeToggle from './ColorSchemeToggle';
@@ -83,8 +83,7 @@ export default function Sidebar() {
height: '100dvh',
width: 'var(--Sidebar-width)',
top: 0,
- p: 1.5,
- py: 3,
+ p: 2,
flexShrink: 0,
display: 'flex',
flexDirection: 'column',
@@ -124,9 +123,9 @@ export default function Sidebar() {
/>
-
+
- Profiles
+ Acme Co.
} placeholder="Search" />
@@ -169,10 +168,14 @@ export default function Sidebar() {
-
-
+
+
- Projects
+ Orders
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/App.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/App.tsx
index fa1a766df74c00..1cc862e208fff5 100644
--- a/docs/data/joy/getting-started/templates/rental-dashboard/App.tsx
+++ b/docs/data/joy/getting-started/templates/rental-dashboard/App.tsx
@@ -1,145 +1,98 @@
import * as React from 'react';
import { CssVarsProvider } from '@mui/joy/styles';
-import GlobalStyles from '@mui/joy/GlobalStyles';
import CssBaseline from '@mui/joy/CssBaseline';
import Box from '@mui/joy/Box';
-import Divider from '@mui/joy/Divider';
-import Grid from '@mui/joy/Grid';
import Stack from '@mui/joy/Stack';
-import useScript from './useScript';
-import FirstSidebar from './components/FirstSidebar';
-import Header from './components/Header';
+
+import NavBar from './components/NavBar';
import RentalCard from './components/RentalCard';
-import Main from './components/Main';
import HeaderSection from './components/HeaderSection';
import Search from './components/Search';
import Filters from './components/Filters';
-import Toggles from './components/Toggles';
import Pagination from './components/Pagination';
-const useEnhancedEffect =
- typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
-
export default function RentalDashboard() {
- const status = useScript(`https://unpkg.com/feather-icons`);
-
- useEnhancedEffect(() => {
- // Feather icon setup: https://github.com/feathericons/feather#4-replace
- // @ts-ignore
- if (typeof feather !== 'undefined') {
- // @ts-ignore
- feather.replace();
- }
- }, [status]);
-
return (
- ({
- '[data-feather], .feather': {
- color: `var(--Icon-color, ${theme.vars.palette.text.icon})`,
- margin: 'var(--Icon-margin)',
- fontSize: `var(--Icon-fontSize, ${theme.vars.fontSize.xl})`,
- width: '1em',
- height: '1em',
- },
- })}
- />
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- margin: 0,
- }}
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
);
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/ColorSchemeToggle.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/ColorSchemeToggle.tsx
index 7804bd030b07e5..d1b512bb8a123b 100644
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/ColorSchemeToggle.tsx
+++ b/docs/data/joy/getting-started/templates/rental-dashboard/components/ColorSchemeToggle.tsx
@@ -1,48 +1,61 @@
import * as React from 'react';
import { useColorScheme } from '@mui/joy/styles';
-import { ListItem, ListItemButton, ListItemButtonProps } from '@mui/joy';
+import IconButton, { IconButtonProps } from '@mui/joy/IconButton';
+
+import DarkModeRoundedIcon from '@mui/icons-material/DarkModeRounded';
+import LightModeIcon from '@mui/icons-material/LightMode';
export default function ColorSchemeToggle({
onClick,
sx,
...props
-}: ListItemButtonProps) {
+}: IconButtonProps) {
const { mode, setMode } = useColorScheme();
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
- return ;
+ return (
+
+ );
}
-
return (
-
- ) => {
- if (mode === 'light') {
- setMode('dark');
- } else {
- setMode('light');
- }
- onClick?.(event);
- }}
- sx={[
- {
- '& > *:first-child': {
- display: mode === 'dark' ? 'none' : 'initial',
- },
- '& > *:last-child': {
- display: mode === 'light' ? 'none' : 'initial',
- },
+ {
+ if (mode === 'light') {
+ setMode('dark');
+ } else {
+ setMode('light');
+ }
+ onClick?.(event);
+ }}
+ sx={[
+ {
+ '& > *:first-of-type': {
+ display: mode === 'dark' ? 'none' : 'initial',
+ },
+ '& > *:last-of-type': {
+ display: mode === 'light' ? 'none' : 'initial',
},
- ...(Array.isArray(sx) ? sx : [sx]),
- ]}
- >
-
-
-
-
+ },
+ ...(Array.isArray(sx) ? sx : [sx]),
+ ]}
+ >
+
+
+
);
}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/CountrySelector.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/CountrySelector.tsx
index 788ec77f375c1a..1a5109caf79d67 100644
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/CountrySelector.tsx
+++ b/docs/data/joy/getting-started/templates/rental-dashboard/components/CountrySelector.tsx
@@ -3,20 +3,18 @@ import Autocomplete from '@mui/joy/Autocomplete';
import AutocompleteOption from '@mui/joy/AutocompleteOption';
import AspectRatio from '@mui/joy/AspectRatio';
import FormControl, { FormControlProps } from '@mui/joy/FormControl';
+import FormLabel from '@mui/joy/FormLabel';
import ListItemDecorator from '@mui/joy/ListItemDecorator';
import Typography from '@mui/joy/Typography';
export default function ContrySelector({ sx, ...props }: FormControlProps) {
return (
-
+
+ Country
option.code === value.code}
- defaultValue={{ code: 'US', label: 'United States', phone: '1' }}
+ defaultValue={{ code: 'AU', label: 'Australia', phone: '61' }}
options={countries}
renderOption={(optionProps, option) => (
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/Filters.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/Filters.tsx
index 7c8d1b1c3dc451..639b8acea1c63b 100644
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/Filters.tsx
+++ b/docs/data/joy/getting-started/templates/rental-dashboard/components/Filters.tsx
@@ -1,48 +1,100 @@
import * as React from 'react';
+import Box from '@mui/joy/Box';
import Button from '@mui/joy/Button';
+import Drawer from '@mui/joy/Drawer';
+import DialogTitle from '@mui/joy/DialogTitle';
import FormControl from '@mui/joy/FormControl';
+import FormLabel from '@mui/joy/FormLabel';
import Input from '@mui/joy/Input';
-import Grid from '@mui/joy/Grid';
+import ModalClose from '@mui/joy/ModalClose';
+import Stack from '@mui/joy/Stack';
+import Slider, { sliderClasses } from '@mui/joy/Slider';
+import FilterAltOutlined from '@mui/icons-material/FilterAltOutlined';
import CountrySelector from './CountrySelector';
+import OrderSelector from './OrderSelector';
+
+function valueText(value: number) {
+ return `$${value.toLocaleString('en-US')}`;
+}
export default function Filters() {
+ const [open, setOpen] = React.useState(false);
return (
-
+
+
+
);
}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/FirstSidebar.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/FirstSidebar.tsx
deleted file mode 100644
index f36be022f12156..00000000000000
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/FirstSidebar.tsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import * as React from 'react';
-import GlobalStyles from '@mui/joy/GlobalStyles';
-import Avatar from '@mui/joy/Avatar';
-import List from '@mui/joy/List';
-import ListItem from '@mui/joy/ListItem';
-import ListItemButton from '@mui/joy/ListItemButton';
-import IconButton from '@mui/joy/IconButton';
-import Sheet from '@mui/joy/Sheet';
-import MuiLogo from './MuiLogo';
-import { openSidebar, closeSidebar } from '../utils';
-import ColorSchemeToggle from './ColorSchemeToggle';
-
-export default function FirstSidebar() {
- return (
-
-
- closeSidebar()}
- sx={{ display: { md: 'none' }, mt: -2, borderRadius: '50%' }}
- >
-
-
-
-
-
-
-
-
-
-
- openSidebar()}>
-
-
-
-
- openSidebar()}>
-
-
-
-
- openSidebar()}>
-
-
-
-
- openSidebar()}>
-
-
-
-
- openSidebar()}>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/Header.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/Header.tsx
deleted file mode 100644
index d6235ffb95cd1a..00000000000000
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/Header.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import * as React from 'react';
-import { useColorScheme } from '@mui/joy/styles';
-import GlobalStyles from '@mui/joy/GlobalStyles';
-import IconButton, { IconButtonProps } from '@mui/joy/IconButton';
-import Sheet from '@mui/joy/Sheet';
-import MuiLogo from './MuiLogo';
-import { toggleSidebar } from '../utils';
-
-function ColorSchemeToggle({ onClick, sx, ...props }: IconButtonProps) {
- const { mode, setMode } = useColorScheme();
- const [mounted, setMounted] = React.useState(false);
- React.useEffect(() => {
- setMounted(true);
- }, []);
- if (!mounted) {
- return (
-
- );
- }
- return (
- {
- if (mode === 'light') {
- setMode('dark');
- } else {
- setMode('light');
- }
- onClick?.(event);
- }}
- sx={[
- {
- '& > *:first-of-type': {
- display: mode === 'dark' ? 'none' : 'initial',
- },
- '& > *:last-of-type': {
- display: mode === 'light' ? 'none' : 'initial',
- },
- },
- ...(Array.isArray(sx) ? sx : [sx]),
- ]}
- >
-
-
-
- );
-}
-
-export default function Header() {
- return (
-
- ({
- ':root': {
- '--Header-height': '52px',
- [theme.breakpoints.up('md')]: {
- '--Header-height': '0px',
- },
- },
- })}
- />
- toggleSidebar()}
- variant="outlined"
- color="neutral"
- size="sm"
- >
-
-
-
-
-
- );
-}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/HeaderSection.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/HeaderSection.tsx
index dbec55f8481033..45fc2554b81781 100644
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/HeaderSection.tsx
+++ b/docs/data/joy/getting-started/templates/rental-dashboard/components/HeaderSection.tsx
@@ -1,46 +1,17 @@
import * as React from 'react';
-import Button from '@mui/joy/Button';
import Stack from '@mui/joy/Stack';
import Typography from '@mui/joy/Typography';
export default function HeaderSection() {
return (
-
-
-
- 232 stays in Melbourne
-
-
- Book your next stay at one of our properties.
-
-
-
-
-
- }
- >
- Save search
-
+
+
+ Rental properties
+
+
+ Book your next stay at one of our properties.
+
);
}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/Main.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/Main.tsx
deleted file mode 100644
index 912e63a5103aa7..00000000000000
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/Main.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import * as React from 'react';
-import Box from '@mui/joy/Box';
-
-type MainProps = {
- children: React.ReactNode;
-};
-
-export default function Main({ children }: MainProps) {
- return (
-
- {children}
-
- );
-}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/NavBar.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/NavBar.tsx
new file mode 100644
index 00000000000000..f2b216a3093127
--- /dev/null
+++ b/docs/data/joy/getting-started/templates/rental-dashboard/components/NavBar.tsx
@@ -0,0 +1,65 @@
+import * as React from 'react';
+import { Box, IconButton } from '@mui/joy';
+import Typography from '@mui/joy/Typography';
+import Avatar from '@mui/joy/Avatar';
+import MapsHomeWorkIcon from '@mui/icons-material/MapsHomeWork';
+import ColorSchemeToggle from './ColorSchemeToggle';
+
+export default function HeaderSection() {
+ return (
+
+
+
+
+
+
+ Acme Rental
+
+
+
+
+
+
+
+ Siriwat K.
+ siriwatk@test.com
+
+
+
+
+
+ );
+}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/OrderSelector.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/OrderSelector.tsx
new file mode 100644
index 00000000000000..15d19d1819fa0c
--- /dev/null
+++ b/docs/data/joy/getting-started/templates/rental-dashboard/components/OrderSelector.tsx
@@ -0,0 +1,26 @@
+import * as React from 'react';
+import MenuButton from '@mui/joy/MenuButton';
+import Menu from '@mui/joy/Menu';
+import MenuItem from '@mui/joy/MenuItem';
+import ArrowDropDown from '@mui/icons-material/ArrowDropDown';
+import Dropdown from '@mui/joy/Dropdown';
+
+export default function OrderSelector() {
+ return (
+
+ }
+ sx={{ whiteSpace: 'nowrap' }}
+ >
+ Order by
+
+
+
+ );
+}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/Pagination.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/Pagination.tsx
index 9671d994ce3f78..f077a1e44fe4ad 100644
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/Pagination.tsx
+++ b/docs/data/joy/getting-started/templates/rental-dashboard/components/Pagination.tsx
@@ -3,13 +3,20 @@ import Box from '@mui/joy/Box';
import Button from '@mui/joy/Button';
import IconButton, { iconButtonClasses } from '@mui/joy/IconButton';
import Typography from '@mui/joy/Typography';
+import ArrowBackIosRoundedIcon from '@mui/icons-material/ArrowBackIosRounded';
+import ArrowForwardIosRoundedIcon from '@mui/icons-material/ArrowForwardIosRounded';
export default function Pagination() {
return (
-
+
Page 1 of 10
@@ -28,26 +35,27 @@ export default function Pagination() {
color="neutral"
size="sm"
>
-
+
}
+ startDecorator={}
>
Previous
@@ -57,7 +65,7 @@ export default function Pagination() {
{page}
@@ -69,7 +77,7 @@ export default function Pagination() {
size="sm"
variant="plain"
color="neutral"
- endDecorator={}
+ endDecorator={}
>
Next
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/Rating.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/Rating.tsx
index e5bde46ecc813a..514e28979ad7b6 100644
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/Rating.tsx
+++ b/docs/data/joy/getting-started/templates/rental-dashboard/components/Rating.tsx
@@ -5,18 +5,18 @@ import Star from '@mui/icons-material/Star';
export default function Rating() {
return (
-
-
-
-
-
+
+
+
+
+
}
>
- 4.9
+ 4.0
);
}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/RentalCard.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/RentalCard.tsx
index ed68d8038d0764..cfb0f31072901e 100644
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/RentalCard.tsx
+++ b/docs/data/joy/getting-started/templates/rental-dashboard/components/RentalCard.tsx
@@ -1,13 +1,19 @@
import * as React from 'react';
import AspectRatio from '@mui/joy/AspectRatio';
-import Box from '@mui/joy/Box';
import Card from '@mui/joy/Card';
+import CardContent from '@mui/joy/CardContent';
+import CardOverflow from '@mui/joy/CardOverflow';
import Chip from '@mui/joy/Chip';
import IconButton from '@mui/joy/IconButton';
import Link from '@mui/joy/Link';
import Stack from '@mui/joy/Stack';
import Typography from '@mui/joy/Typography';
-import Rating from './Rating';
+import WorkspacePremiumRoundedIcon from '@mui/icons-material/WorkspacePremiumRounded';
+import FavoriteRoundedIcon from '@mui/icons-material/FavoriteRounded';
+import FmdGoodRoundedIcon from '@mui/icons-material/FmdGoodRounded';
+import KingBedRoundedIcon from '@mui/icons-material/KingBedRounded';
+import WifiRoundedIcon from '@mui/icons-material/WifiRounded';
+import Star from '@mui/icons-material/Star';
type RentalCardProps = {
category: React.ReactNode;
@@ -30,146 +36,138 @@ export default function RentalCard({
variant="outlined"
orientation="horizontal"
sx={{
- transition: '250ms all',
- padding: {
- xs: 0,
- sm: 2,
+ bgcolor: 'neutral.softBg',
+ display: 'flex',
+ flexDirection: { xs: 'column', sm: 'row' },
+ '&:hover': {
+ boxShadow: 'lg',
+ borderColor: 'var(--joy-palette-neutral-outlinedDisabledBorder)',
},
- boxShadow: 'none',
- borderRadius: 'sm',
- '&:hover': { boxShadow: 'md', borderColor: 'neutral.outlinedHoverBorder' },
}}
>
-
-
- ({
- borderRadius: 'xs',
- [theme.breakpoints.down('sm')]: {
- borderBottomLeftRadius: 0,
- borderBottomRightRadius: 0,
- },
- })}
+
+
-
{rareFind && (
}
- size="sm"
- sx={{ position: 'absolute', bottom: 8, left: 8 }}
+ color="success"
+ startDecorator={}
+ size="md"
>
Rare find
)}
setIsLiked((prev) => !prev)}
sx={{
- position: 'absolute',
- bottom: 8,
- right: 8,
display: { xs: 'flex', sm: 'none' },
+ ml: 'auto',
+ borderRadius: '50%',
+ zIndex: '20',
}}
>
-
+
-
-
+
+
+
+
-
+ {category}
+
+
+ {title}
+
+
+
+ setIsLiked((prev) => !prev)}
+ sx={{
+ display: { xs: 'none', sm: 'flex' },
+ borderRadius: '50%',
+ }}
>
-
-
- {category}
-
-
-
- {title}
-
-
-
- setIsLiked((prev) => !prev)}
- sx={{
- display: { xs: 'none', sm: 'flex' },
- }}
- >
-
-
-
-
-
-
- 202 reviews
-
+
+
+
-
- }>
- Collingwood VIC
-
- }
- display={{
- xs: 'none',
- md: 'flex',
- }}
- >
- 1 bed
-
- }
- display={{
- xs: 'none',
- md: 'flex',
- }}
- >
- Wi-Fi
-
-
- $540 total
-
-
+
+ }>
+ Collingwood VIC
+
+ }>
+ 1 bed
+
+ }>
+ Wi-Fi
+
+
+
+
+
+
+
+
+
+
+ }
+ sx={{ display: 'flex', gap: 1 }}
+ >
+ 4.0
+
+
+ $540 total
+
-
+
);
}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/Search.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/Search.tsx
index dc35a31c28cf07..45716c18580888 100644
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/Search.tsx
+++ b/docs/data/joy/getting-started/templates/rental-dashboard/components/Search.tsx
@@ -1,30 +1,28 @@
import * as React from 'react';
-import Box from '@mui/joy/Box';
import Button from '@mui/joy/Button';
import FormControl from '@mui/joy/FormControl';
import Input from '@mui/joy/Input';
import Stack from '@mui/joy/Stack';
+import SearchRoundedIcon from '@mui/icons-material/SearchRounded';
+import Typography from '@mui/joy/Typography';
export default function Search() {
return (
-
-
- }
- aria-label="Search"
- />
-
-
-
-
-
+
+
+
+ }
+ aria-label="Search"
+ />
+
-
-
+
+ 232 stays in Melbourne, Australia
+
);
}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/components/Toggles.tsx b/docs/data/joy/getting-started/templates/rental-dashboard/components/Toggles.tsx
deleted file mode 100644
index 3a5a079825260f..00000000000000
--- a/docs/data/joy/getting-started/templates/rental-dashboard/components/Toggles.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import * as React from 'react';
-import { Stack } from '@mui/joy';
-import ToggleGroup from './ToggleGroup';
-
-export default function Toggles() {
- return (
-
-
- , value: 'list' },
- { label: , value: 'map' },
- ]}
- />
-
- );
-}
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/useScript.ts b/docs/data/joy/getting-started/templates/rental-dashboard/useScript.ts
deleted file mode 100644
index 205f011215caa6..00000000000000
--- a/docs/data/joy/getting-started/templates/rental-dashboard/useScript.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import * as React from 'react';
-
-export type UseScriptStatus = 'idle' | 'loading' | 'ready' | 'error';
-
-// Cached script statuses
-const cachedScriptStatuses: Record = {};
-
-/**
- * Simplified version of https://usehooks-ts.com/react-hook/use-script
- */
-function getScriptNode(src: string) {
- const node: HTMLScriptElement | null = document.querySelector(`script[src="${src}"]`);
- const status = node?.getAttribute('data-status') as UseScriptStatus | undefined;
-
- return {
- node,
- status,
- };
-}
-
-function useScript(src: string): UseScriptStatus {
- const [status, setStatus] = React.useState(() => {
- if (typeof window === 'undefined') {
- // SSR Handling - always return 'loading'
- return 'loading';
- }
-
- return cachedScriptStatuses[src] ?? 'loading';
- });
-
- React.useEffect(() => {
- const cachedScriptStatus = cachedScriptStatuses[src];
- if (cachedScriptStatus === 'ready' || cachedScriptStatus === 'error') {
- // If the script is already cached, set its status immediately
- setStatus(cachedScriptStatus);
- return;
- }
-
- // Fetch existing script element by src
- // It may have been added by another instance of this hook
- const script = getScriptNode(src);
- let scriptNode = script.node;
-
- if (!scriptNode) {
- // Create script element and add it to document body
- scriptNode = document.createElement('script');
- scriptNode.src = src;
- scriptNode.async = true;
- scriptNode.setAttribute('data-status', 'loading');
- document.body.appendChild(scriptNode);
-
- // Store status in attribute on script
- // This can be read by other instances of this hook
- const setAttributeFromEvent = (event: Event) => {
- const scriptStatus: UseScriptStatus = event.type === 'load' ? 'ready' : 'error';
-
- scriptNode?.setAttribute('data-status', scriptStatus);
- };
-
- scriptNode.addEventListener('load', setAttributeFromEvent);
- scriptNode.addEventListener('error', setAttributeFromEvent);
- } else {
- // Grab existing script status from attribute and set to state.
- setStatus(script.status ?? cachedScriptStatus ?? 'loading');
- }
-
- // Script event handler to update status in state
- // Note: Even if the script already exists we still need to add
- // event handlers to update the state for *this* hook instance.
- const setStateFromEvent = (event: Event) => {
- const newStatus = event.type === 'load' ? 'ready' : 'error';
- setStatus(newStatus);
- cachedScriptStatuses[src] = newStatus;
- };
-
- // Add event listeners
- scriptNode.addEventListener('load', setStateFromEvent);
- scriptNode.addEventListener('error', setStateFromEvent);
-
- // Remove event listeners on cleanup
- // eslint-disable-next-line consistent-return
- return () => {
- if (scriptNode) {
- scriptNode.removeEventListener('load', setStateFromEvent);
- scriptNode.removeEventListener('error', setStateFromEvent);
- }
-
- if (scriptNode) {
- try {
- scriptNode.remove();
- } catch (error) {
- // ignore error
- }
- }
- };
- }, [src]);
-
- return status;
-}
-
-export default useScript;
diff --git a/docs/data/joy/getting-started/templates/rental-dashboard/utils.ts b/docs/data/joy/getting-started/templates/rental-dashboard/utils.ts
deleted file mode 100644
index 83220658582ce6..00000000000000
--- a/docs/data/joy/getting-started/templates/rental-dashboard/utils.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-export const openSidebar = () => {
- if (typeof document !== 'undefined') {
- document.body.style.overflow = 'hidden';
- document.documentElement.style.setProperty('--SideNavigation-slideIn', '1');
- }
-};
-
-export const closeSidebar = () => {
- if (typeof document !== 'undefined') {
- document.documentElement.style.removeProperty('--SideNavigation-slideIn');
- document.body.style.removeProperty('overflow');
- }
-};
-
-export const toggleSidebar = () => {
- if (typeof window !== 'undefined' && typeof document !== 'undefined') {
- const slideIn = window
- .getComputedStyle(document.documentElement)
- .getPropertyValue('--SideNavigation-slideIn');
- if (slideIn) {
- closeSidebar();
- } else {
- openSidebar();
- }
- }
-};
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionAnyParent.js b/docs/data/joy/main-features/color-inversion/ColorInversionAnyParent.js
new file mode 100644
index 00000000000000..c00e4bdb68b714
--- /dev/null
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionAnyParent.js
@@ -0,0 +1,68 @@
+import * as React from 'react';
+import PropTypes from 'prop-types';
+import { applySolidInversion } from '@mui/joy/colorInversion';
+import Box from '@mui/joy/Box';
+import Button from '@mui/joy/Button';
+import Typography from '@mui/joy/Typography';
+
+function Stat({ description, value }) {
+ return (
+
+
+ {value}
+
+
+ {description}
+
+
+ );
+}
+
+Stat.propTypes = {
+ description: PropTypes.node,
+ value: PropTypes.node,
+};
+
+export default function ColorInversionAnyParent() {
+ return (
+
+ `linear-gradient(45deg, ${theme.vars.palette.neutral[800]}, ${theme.vars.palette.neutral[600]})`,
+ },
+ applySolidInversion('neutral'),
+ ]}
+ >
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua.
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionAnyParent.tsx b/docs/data/joy/main-features/color-inversion/ColorInversionAnyParent.tsx
new file mode 100644
index 00000000000000..3052c901dff3e6
--- /dev/null
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionAnyParent.tsx
@@ -0,0 +1,68 @@
+import * as React from 'react';
+import { applySolidInversion } from '@mui/joy/colorInversion';
+import Box from '@mui/joy/Box';
+import Button from '@mui/joy/Button';
+import Typography from '@mui/joy/Typography';
+
+function Stat({
+ description,
+ value,
+}: {
+ description: React.ReactNode;
+ value: React.ReactNode;
+}) {
+ return (
+
+
+ {value}
+
+
+ {description}
+
+
+ );
+}
+
+export default function ColorInversionAnyParent() {
+ return (
+
+ `linear-gradient(45deg, ${theme.vars.palette.neutral[800]}, ${theme.vars.palette.neutral[600]})`,
+ },
+ applySolidInversion('neutral'),
+ ]}
+ >
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua.
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionAnyParentStyled.js b/docs/data/joy/main-features/color-inversion/ColorInversionAnyParentStyled.js
new file mode 100644
index 00000000000000..bb8b4b7d26349e
--- /dev/null
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionAnyParentStyled.js
@@ -0,0 +1,66 @@
+import * as React from 'react';
+import PropTypes from 'prop-types';
+import { styled } from '@mui/joy/styles';
+import { applySolidInversion } from '@mui/joy/colorInversion';
+import Box from '@mui/joy/Box';
+import Button from '@mui/joy/Button';
+import Typography from '@mui/joy/Typography';
+
+const StyledBox = styled(Box)(({ theme }) => ({
+ padding: 32,
+ display: 'grid',
+ gridTemplateColumns: '1fr 1fr',
+ alignItems: 'center',
+ rowGap: 16,
+ columnGap: 64,
+ borderRadius: 8,
+ background: `linear-gradient(45deg, ${theme.vars.palette.neutral[800]}, ${theme.vars.palette.neutral[600]})`,
+ ...applySolidInversion('neutral'),
+}));
+
+function Stat({ description, value }) {
+ return (
+
+
+ {value}
+
+
+ {description}
+
+
+ );
+}
+
+Stat.propTypes = {
+ description: PropTypes.node,
+ value: PropTypes.node,
+};
+
+export default function ColorInversionAnyParentStyled() {
+ return (
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua.
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionAnyParentStyled.tsx b/docs/data/joy/main-features/color-inversion/ColorInversionAnyParentStyled.tsx
new file mode 100644
index 00000000000000..a8fb6824fd1d3d
--- /dev/null
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionAnyParentStyled.tsx
@@ -0,0 +1,66 @@
+import * as React from 'react';
+import { styled } from '@mui/joy/styles';
+import { applySolidInversion } from '@mui/joy/colorInversion';
+import Box from '@mui/joy/Box';
+import Button from '@mui/joy/Button';
+import Typography from '@mui/joy/Typography';
+
+const StyledBox = styled(Box)(({ theme }) => ({
+ padding: 32,
+ display: 'grid',
+ gridTemplateColumns: '1fr 1fr',
+ alignItems: 'center',
+ rowGap: 16,
+ columnGap: 64,
+ borderRadius: 8,
+ background: `linear-gradient(45deg, ${theme.vars.palette.neutral[800]}, ${theme.vars.palette.neutral[600]})`,
+ ...applySolidInversion('neutral'),
+}));
+
+function Stat({
+ description,
+ value,
+}: {
+ description: React.ReactNode;
+ value: React.ReactNode;
+}) {
+ return (
+
+
+ {value}
+
+
+ {description}
+
+
+ );
+}
+
+export default function ColorInversionAnyParentStyled() {
+ return (
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua.
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionFooter.js b/docs/data/joy/main-features/color-inversion/ColorInversionFooter.js
index c9f599adb6a59e..6e62b499a68e9a 100644
--- a/docs/data/joy/main-features/color-inversion/ColorInversionFooter.js
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionFooter.js
@@ -5,13 +5,11 @@ import Box from '@mui/joy/Box';
import IconButton from '@mui/joy/IconButton';
import Card from '@mui/joy/Card';
import CardContent from '@mui/joy/CardContent';
-import Chip from '@mui/joy/Chip';
import Divider from '@mui/joy/Divider';
import Input from '@mui/joy/Input';
import List from '@mui/joy/List';
import ListSubheader from '@mui/joy/ListSubheader';
import ListItem from '@mui/joy/ListItem';
-import ListItemDecorator from '@mui/joy/ListItemDecorator';
import ListItemButton from '@mui/joy/ListItemButton';
import Typography from '@mui/joy/Typography';
import Sheet from '@mui/joy/Sheet';
@@ -98,19 +96,17 @@ export default function ColorInversionFooter() {
Intro to the MUI ecosystem
-
- MUI blog
-
+ Blog post
- Sitemap
+ Sitemap
Services
@@ -119,79 +115,21 @@ export default function ColorInversionFooter() {
Blog
- Contact us
+ About
- Product
+ Products
-
-
-
-
- MUI Core
-
+ Joy UI
-
-
-
-
- MUI X
-
+ Base UI
-
-
-
-
- MUI Toolpad
-
- BETA
-
-
-
-
-
-
-
-
- Design kits
-
-
-
-
-
-
-
- Templates
-
+ Material UI
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionFooter.tsx b/docs/data/joy/main-features/color-inversion/ColorInversionFooter.tsx
index 933728dc1ce6a3..9fcf01b495e0f0 100644
--- a/docs/data/joy/main-features/color-inversion/ColorInversionFooter.tsx
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionFooter.tsx
@@ -5,13 +5,11 @@ import Box from '@mui/joy/Box';
import IconButton from '@mui/joy/IconButton';
import Card from '@mui/joy/Card';
import CardContent from '@mui/joy/CardContent';
-import Chip from '@mui/joy/Chip';
import Divider from '@mui/joy/Divider';
import Input from '@mui/joy/Input';
import List from '@mui/joy/List';
import ListSubheader from '@mui/joy/ListSubheader';
import ListItem from '@mui/joy/ListItem';
-import ListItemDecorator from '@mui/joy/ListItemDecorator';
import ListItemButton from '@mui/joy/ListItemButton';
import Typography from '@mui/joy/Typography';
import Sheet from '@mui/joy/Sheet';
@@ -103,19 +101,17 @@ export default function ColorInversionFooter() {
Intro to the MUI ecosystem
-
- MUI blog
-
+ Blog post
- Sitemap
+ Sitemap
Services
@@ -124,79 +120,21 @@ export default function ColorInversionFooter() {
Blog
- Contact us
+ About
- Product
+ Products
-
-
-
-
- MUI Core
-
+ Joy UI
-
-
-
-
- MUI X
-
+ Base UI
-
-
-
-
- MUI Toolpad
-
- BETA
-
-
-
-
-
-
-
-
- Design kits
-
-
-
-
-
-
-
- Templates
-
+ Material UI
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionHeader.js b/docs/data/joy/main-features/color-inversion/ColorInversionHeader.js
index 25d3cd590c5dca..28972a47ff64ff 100644
--- a/docs/data/joy/main-features/color-inversion/ColorInversionHeader.js
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionHeader.js
@@ -104,7 +104,7 @@ export default function ColorInversionHeader() {
}
- sx={{ borderRadius: 'xl', display: { xs: 'none', md: 'inline-flex' } }}
+ sx={{ borderRadius: '50%', display: { xs: 'none', md: 'inline-flex' } }}
>
New invoice
@@ -123,14 +123,14 @@ export default function ColorInversionHeader() {
}
sx={{
- '--Input-radius': '40px',
+ '--Input-radius': '50%',
'--Input-paddingInline': '12px',
width: 160,
display: { xs: 'none', lg: 'flex' },
}}
/>
-
+
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionHeader.tsx b/docs/data/joy/main-features/color-inversion/ColorInversionHeader.tsx
index acf66252151040..9394b22a435fdb 100644
--- a/docs/data/joy/main-features/color-inversion/ColorInversionHeader.tsx
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionHeader.tsx
@@ -109,7 +109,7 @@ export default function ColorInversionHeader() {
}
- sx={{ borderRadius: 'xl', display: { xs: 'none', md: 'inline-flex' } }}
+ sx={{ borderRadius: '50%', display: { xs: 'none', md: 'inline-flex' } }}
>
New invoice
@@ -128,14 +128,14 @@ export default function ColorInversionHeader() {
}
sx={{
- '--Input-radius': '40px',
+ '--Input-radius': '50%',
'--Input-paddingInline': '12px',
width: 160,
display: { xs: 'none', lg: 'flex' },
}}
/>
-
+
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionMarketing.js b/docs/data/joy/main-features/color-inversion/ColorInversionMarketing.js
index 580c0bb6f9b880..c9e38ebb35603b 100644
--- a/docs/data/joy/main-features/color-inversion/ColorInversionMarketing.js
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionMarketing.js
@@ -32,8 +32,8 @@ export default function ColorInversionMarketing() {
>
Get started
-
- Instant access to the power of the React UI library
+
+ Instant access to the power of the Joy UI library.
Get started
-
- Instant access to the power of the React UI library
+
+ Instant access to the power of the Joy UI library.
Chat
-
+
5
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.tsx b/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.tsx
index a12eb37f9881a6..9bbfc84c38a28d 100644
--- a/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.tsx
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.tsx
@@ -86,7 +86,13 @@ export default function ColorInversionNavigation() {
Chat
-
+
5
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionOverview.js b/docs/data/joy/main-features/color-inversion/ColorInversionOverview.js
index e13b479c70d6ed..bce6170d920826 100644
--- a/docs/data/joy/main-features/color-inversion/ColorInversionOverview.js
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionOverview.js
@@ -29,9 +29,7 @@ export default function ColorInversionOverview() {
>
-
- Learn how to build super fast websites.
-
+ Learn how to build super fast websites.
}>
Read more
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionOverview.tsx b/docs/data/joy/main-features/color-inversion/ColorInversionOverview.tsx
index e13b479c70d6ed..bce6170d920826 100644
--- a/docs/data/joy/main-features/color-inversion/ColorInversionOverview.tsx
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionOverview.tsx
@@ -29,9 +29,7 @@ export default function ColorInversionOverview() {
>
-
- Learn how to build super fast websites.
-
+ Learn how to build super fast websites.
}>
Read more
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionSkip.js b/docs/data/joy/main-features/color-inversion/ColorInversionSkip.js
new file mode 100644
index 00000000000000..cad9a69a1b9556
--- /dev/null
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionSkip.js
@@ -0,0 +1,62 @@
+import * as React from 'react';
+import AspectRatio from '@mui/joy/AspectRatio';
+import Card from '@mui/joy/Card';
+import SvgIcon from '@mui/joy/SvgIcon';
+import IconButton from '@mui/joy/IconButton';
+import Typography from '@mui/joy/Typography';
+import ArrowForward from '@mui/icons-material/ArrowForward';
+
+export default function ColorInversionSkip() {
+ return (
+
+
+
+
+
+ Design Thinking
+
+ How to apply design thinking to your problem in order to generate innovative
+ and user-centric solutions.
+
+
+
+
+
+
+ );
+}
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionSkip.tsx b/docs/data/joy/main-features/color-inversion/ColorInversionSkip.tsx
new file mode 100644
index 00000000000000..cad9a69a1b9556
--- /dev/null
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionSkip.tsx
@@ -0,0 +1,62 @@
+import * as React from 'react';
+import AspectRatio from '@mui/joy/AspectRatio';
+import Card from '@mui/joy/Card';
+import SvgIcon from '@mui/joy/SvgIcon';
+import IconButton from '@mui/joy/IconButton';
+import Typography from '@mui/joy/Typography';
+import ArrowForward from '@mui/icons-material/ArrowForward';
+
+export default function ColorInversionSkip() {
+ return (
+
+
+
+
+
+ Design Thinking
+
+ How to apply design thinking to your problem in order to generate innovative
+ and user-centric solutions.
+
+
+
+
+
+
+ );
+}
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionSurface.js b/docs/data/joy/main-features/color-inversion/ColorInversionSurface.js
new file mode 100644
index 00000000000000..b7e0b94a246de4
--- /dev/null
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionSurface.js
@@ -0,0 +1,73 @@
+import * as React from 'react';
+import Box from '@mui/joy/Box';
+import Card from '@mui/joy/Card';
+import CardContent from '@mui/joy/CardContent';
+import Typography from '@mui/joy/Typography';
+import SvgIcon from '@mui/joy/SvgIcon';
+
+export default function ColorInversionSurface() {
+ const creditCard = (
+
+
+
+ $4,236
+
+ CREDIT
+
+
+
+
+
+
+
+ •••• •••• •••• 1212
+
+
+
+
+ CARD NAME
+
+
+ JOHN DOE
+
+
+
+
+ EXPIRE
+
+
+ 07/25
+
+
+
+
+ );
+
+ return (
+
+ {creditCard}
+ {React.cloneElement(creditCard, { variant: 'soft' })}
+
+ );
+}
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionSurface.tsx b/docs/data/joy/main-features/color-inversion/ColorInversionSurface.tsx
new file mode 100644
index 00000000000000..3f49510152aaf3
--- /dev/null
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionSurface.tsx
@@ -0,0 +1,72 @@
+import * as React from 'react';
+import Box from '@mui/joy/Box';
+import Card from '@mui/joy/Card';
+import CardContent from '@mui/joy/CardContent';
+import Typography from '@mui/joy/Typography';
+import SvgIcon from '@mui/joy/SvgIcon';
+
+export default function ColorInversionSurface() {
+ const creditCard = (
+
+
+
+ $4,236
+
+ CREDIT
+
+
+
+
+
+
+
+ •••• •••• •••• 1212
+
+
+
+
+ CARD NAME
+
+
+ JOHN DOE
+
+
+
+
+ EXPIRE
+
+
+ 07/25
+
+
+
+
+ );
+ return (
+
+ {creditCard}
+ {React.cloneElement(creditCard, { variant: 'soft' })}
+
+ );
+}
diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionSurface.tsx.preview b/docs/data/joy/main-features/color-inversion/ColorInversionSurface.tsx.preview
new file mode 100644
index 00000000000000..f91cb4f688a1e8
--- /dev/null
+++ b/docs/data/joy/main-features/color-inversion/ColorInversionSurface.tsx.preview
@@ -0,0 +1,2 @@
+{creditCard}
+{React.cloneElement(creditCard, { variant: 'soft' })}
\ No newline at end of file
diff --git a/docs/data/joy/main-features/color-inversion/color-inversion.md b/docs/data/joy/main-features/color-inversion/color-inversion.md
index 7e6bd76d9bb694..a4567b77e81da5 100644
--- a/docs/data/joy/main-features/color-inversion/color-inversion.md
+++ b/docs/data/joy/main-features/color-inversion/color-inversion.md
@@ -4,38 +4,28 @@
## Motivation
-[Global variants](/joy-ui/main-features/global-variants/) provide a consistent `variant` prop that lets you control the hierarchy of importance within a group of Joy UI components. However, they are not working as expected when global variants are used in multiple layers.
-
-The example below (on your right-hand side) shows the problem when the interface has more than one layer that applies the global variants:
+The Joy UI [global variants feature](/joy-ui/main-features/global-variants/) provides a consistent set of values for the `variant` prop.
+But these variants can sometimes cause quirks when the same styles are applied to both parent and child components.
+Check out the two demo cards below to see how things can go wrong:
{{"demo": "ColorInversionMotivation.js"}}
-On the **left**, the Button's variant is `solid`, which is the highest emphasis level compared to other components.
-This conforms to the visual appearance on the screen.
-
-On the **right**, the problem arises when the container's variant becomes `solid`.
-The Button is no longer the highest emphasis element because it has the same background as the container.
-Also, the text and the icon button don't contrast enough with the parent's background.
+- On the left, the Button variant is `solid`, while its parent Card is the default `outlined`, so the design works well.
+- On the right, the `solid` variant is applied to both the Button and the Card, disrupting the design's hierarchy and contrast.
-The color inversion is implemented to solve this issue, keeping the global variants meaningful when multiple layers of global variants are composed together.
+Joy UI's color inversion feature prevents this kind of situation from occurring, while still preserving the hierarchical meaning of the global variants themselves.
## Overview
-When color inversion is enabled on the parent component, the children with implicit color will invert their styles to match the parent's background by keeping the same hierarchy of importance based on their variants.
+When color inversion is enabled on a parent component, all children components invert their styles (regardless of their respective color props) to match the parent's background.
+The inverted styles maintain the semantic meaning of their corresponding global variants—in the example below, the Button is still `solid` even though it's been inverted to contrast with its container.
+If you change the Button's variant to `outlined`, you'll see that the design still works; but try removing the `invertedColors` prop from the parent Card, and you'll see how the design falls apart (and thus, why this feature is so useful):
{{"demo": "ColorInversionOverview.js"}}
-**Implicit** color refers to components that don't have the `color` prop specified.
-
-Color inversion has no effect on children that have an **explicit** `color` prop.
-
-```js
-// implicit color. The styles change when color inversion is enabled.
-…
-
-// explicit color. Color inversion has no effect.
-…
-```
+:::info
+The color inversion feature is only available for `soft` and `solid` variants because the rest of the global variants don't have background by default.
+:::
### Benefits
@@ -45,46 +35,72 @@ Color inversion has no effect on children that have an **explicit** `color` prop
- It works for both light and dark mode.
- It can be disabled at any time without impacting the structure of the components.
- It is an opt-in feature. If you don't use it, the extra CSS variables won't be included in the production style sheet.
-- It doesn't alter the styles of the children if you explicitly specify the `color` prop on them.
+- Some children can be excluded from the color inversion, see ["skip color inversion on a child"](#skip-color-inversion-on-a-child) section.
### Trade-offs
-- If the surface component contains just a few components, the style sheet size of the CSS variables might be **bigger** than customizing the styles of each individual child.
+- If the parent component contains just a few children, the size of the stylesheet generated may be significantly larger than it would be if you customized each child individually. (This may be inconsequential for overall performance.)
- It doesn't work with browsers that don't support [CSS variables](https://caniuse.com/css-variables).
## Usage
-To enable color inversion, use the `invertedColors` prop. Note that this prop only works when the components have the `solid` or `soft` global variant applied.
+### Supported components
-```js
-…
+The following components accept the `invertedColors` prop when applied in conjunction with the `solid` or `soft` variants:
-…
-```
+- [Alert](/joy-ui/react-alert/)
+- [Card](/joy-ui/react-card/)
+- [Drawer](/joy-ui/react-drawer/)
+- [Modal Dialog](/joy-ui/react-modal/#modal-dialog)
+- [Menu](/joy-ui/react-menu/)
+- [Sheet](/joy-ui/react-sheet/)
+
+{{"demo": "ColorInversionSurface.js"}}
-### Portal popup
+### Exceptions
-By default, color inversion has no effect on the popup slot of the Autocomplete, Menu, and Tooltip components.
-To enable it, set `disablePortal` to true on the `slotProps`.
+Color inversion does not affect the popup slot of the Autocomplete, Menu, or Tooltip components by default.
+To enable it, set `disablePortal` to `"true"` using `slotProps` on the respective child component, as demonstrated below:
+
+{{"demo": "ColorInversionPopup.js"}}
:::info
-The popup slot of the Select component has `disablePortal` set to true by default.
+To learn more about the concept of component slots and slot props, visit the [Overriding component structure](/joy-ui/customization/overriding-component-structure/) guide.
:::
-{{"demo": "ColorInversionPopup.js"}}
+### Skip inversion on a child
-## How it works
+When `invertedColors` is applied to a parent, you can add the `data-skip-inverted-colors` attribute to a child to prevent that child from being inverted.
-### Parent component
+{{"demo": "ColorInversionSkip.js"}}
-When `invertedColors` is set to true on the surface component, a set of CSS variables is applied to it.
-The values of those variables come from `theme.colorInversion[variant][color]`, where `variant` and `color` are the component's props.
-The surface component also creates a React context to tell the children to update their styles.
+### Apply color inversion to any parent
+
+```js
+import { applySolidInversion, applySoftInversion } from '@mui/joy/colorInversion';
+```
+
+If you need color inversion for a parent component that isn't [supported by default](#supported-components), you can use the `applySolidInversion` or `applySoftInversion` utilities to add it to any component that contains children.
+(This is what the supported components use behind the scenes when the `invertedColors` prop is applied.)
+
+The examples below show how to use these utilities with both the `sx` prop and the `styled` API:
+
+#### With the sx prop
+
+{{"demo": "ColorInversionAnyParent.js"}}
+
+#### With the styled API
+
+{{"demo": "ColorInversionAnyParentStyled.js"}}
+
+## How it works
+
+Color inversion adds CSS variables to the component using the `invertedColors` prop or the apply utilities. There's no [React context](https://react.dev/learn/passing-data-deeply-with-context) involved in this feature.
```jsx
-// The component style sheet
+// The parent's style sheet
{
// the values of these variables depends on the parent's variant and color.
--variant-softColor: …;
@@ -93,29 +109,26 @@ The surface component also creates a React context to tell the children to updat
--variant-softHoverBg: …;
--variant-softActiveBg: …;
… // other variants
+ --joy-palette-text-primary: …;
+ --joy-palette-text-secondary: …;
+ --joy-palette-text-tertiary: …;
+ --joy-palette-background-surface: …;
+ … // other theme palette tokens
}
```
-### Child component
-
-All Joy UI components that support global variants check the React context that contains the color inversion flag.
-If the flag is true and the child has an implicit color, the internal `color` value will switch to `context` and apply the styles from `theme.variants[variant].context`.
-
-The styles will match the `--variant-*` variables that the parent has.
+As a result, the children will use these CSS variables instead of the theme:
```jsx
-
-
-// Component style sheet
+// The children style sheet
+// The values of these variables are inherited from the parent.
{
- background-color: var(--variant-softBg);
- color: var(--variant-softColor);
+ color: var(--joy-palette-text-primary);
+ background: var(--joy-palette-background-surface);
+ …
}
```
-In summary, the parent creates a React context to tell the children that the feature is enabled, and generates CSS variables that will be used by the children.
-The children with an implicit color switch their default color value to `context` to get the styles from the theme.
-
## Common examples
### Header
diff --git a/docs/data/joy/pages.ts b/docs/data/joy/pages.ts
index 93ea42e037a70a..7058402fb052e6 100644
--- a/docs/data/joy/pages.ts
+++ b/docs/data/joy/pages.ts
@@ -11,6 +11,7 @@ const pages: readonly MuiPage[] = [
{ pathname: '/joy-ui/getting-started/usage' },
{ pathname: '/joy-ui/getting-started/tutorial' },
{ pathname: '/joy-ui/getting-started/templates' },
+ { pathname: '/joy-ui/getting-started/roadmap' },
{
pathname: '/joy-ui/main-features',
subheader: 'main-features',
diff --git a/docs/data/material/components/autocomplete/Virtualize.js b/docs/data/material/components/autocomplete/Virtualize.js
index 29b76273b03c07..7b62b6c4f7b938 100644
--- a/docs/data/material/components/autocomplete/Virtualize.js
+++ b/docs/data/material/components/autocomplete/Virtualize.js
@@ -147,7 +147,6 @@ export default function Virtualize() {
groupBy={(option) => option[0].toUpperCase()}
renderInput={(params) => }
renderOption={(props, option, state) => [props, option, state.index]}
- // TODO: Post React 18 update - validate this conversion, look like a hidden bug
renderGroup={(params) => params}
/>
);
diff --git a/docs/data/material/components/autocomplete/Virtualize.tsx b/docs/data/material/components/autocomplete/Virtualize.tsx
index c9c0755904f28e..cd6eee98854ff5 100644
--- a/docs/data/material/components/autocomplete/Virtualize.tsx
+++ b/docs/data/material/components/autocomplete/Virtualize.tsx
@@ -56,9 +56,9 @@ const ListboxComponent = React.forwardRef<
React.HTMLAttributes
>(function ListboxComponent(props, ref) {
const { children, ...other } = props;
- const itemData: React.ReactChild[] = [];
- (children as React.ReactChild[]).forEach(
- (item: React.ReactChild & { children?: React.ReactChild[] }) => {
+ const itemData: React.ReactElement[] = [];
+ (children as React.ReactElement[]).forEach(
+ (item: React.ReactElement & { children?: React.ReactElement[] }) => {
itemData.push(item);
itemData.push(...(item.children || []));
},
@@ -71,7 +71,7 @@ const ListboxComponent = React.forwardRef<
const itemCount = itemData.length;
const itemSize = smUp ? 36 : 48;
- const getChildSize = (child: React.ReactChild) => {
+ const getChildSize = (child: React.ReactElement) => {
if (child.hasOwnProperty('group')) {
return 48;
}
@@ -149,8 +149,7 @@ export default function Virtualize() {
renderOption={(props, option, state) =>
[props, option, state.index] as React.ReactNode
}
- // TODO: Post React 18 update - validate this conversion, look like a hidden bug
- renderGroup={(params) => params as unknown as React.ReactNode}
+ renderGroup={(params) => params as any}
/>
);
}
diff --git a/docs/data/material/components/autocomplete/Virtualize.tsx.preview b/docs/data/material/components/autocomplete/Virtualize.tsx.preview
index 906d629e7ed941..7aa80fd1fd266e 100644
--- a/docs/data/material/components/autocomplete/Virtualize.tsx.preview
+++ b/docs/data/material/components/autocomplete/Virtualize.tsx.preview
@@ -10,6 +10,5 @@
renderOption={(props, option, state) =>
[props, option, state.index] as React.ReactNode
}
- // TODO: Post React 18 update - validate this conversion, look like a hidden bug
- renderGroup={(params) => params as unknown as React.ReactNode}
+ renderGroup={(params) => params as any}
/>
\ No newline at end of file
diff --git a/docs/data/material/components/chips/ChipMaterialYouPlayground.js b/docs/data/material/components/chips/ChipMaterialYouPlayground.js
new file mode 100644
index 00000000000000..98f10568e8fcb0
--- /dev/null
+++ b/docs/data/material/components/chips/ChipMaterialYouPlayground.js
@@ -0,0 +1,59 @@
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import Chip from '@mui/material-next/Chip';
+import MaterialYouUsageDemo from 'docs/src/modules/components/MaterialYouUsageDemo';
+
+export default function ChipMaterialYouPlayground() {
+ return (
+ (
+
+
+ alert('Clicked Material You Chip')}
+ />
+ alert('Deleted Material You Chip')}
+ />
+
+ )}
+ />
+ );
+}
diff --git a/docs/data/material/components/chips/chips.md b/docs/data/material/components/chips/chips.md
index b13cd2f6e33570..6005af77bdc11f 100644
--- a/docs/data/material/components/chips/chips.md
+++ b/docs/data/material/components/chips/chips.md
@@ -97,6 +97,19 @@ gain depth while clicked or touched.
{{"demo": "ChipsPlayground.js", "hideToolbar": true}}
+## Experimental API
+
+### Material You version
+
+The default Material UI Chip component follows the Material Design 2 specs.
+To get the Material You ([Material Design 3](https://m3.material.io/)) version, use the new experimental `@mui/material-next` package:
+
+```js
+import Chip from '@mui/material-next/Chip';
+```
+
+{{"demo": "ChipMaterialYouPlayground.js", "hideToolbar": true, "bg": "playground"}}
+
## Accessibility
If the Chip is deletable or clickable then it is a button in tab order. When the Chip is focused (e.g. when tabbing) releasing (`keyup` event) `Backspace` or `Delete` will call the `onDelete` handler while releasing `Escape` will blur the Chip.
diff --git a/docs/data/material/components/drawers/PersistentDrawerRight.js b/docs/data/material/components/drawers/PersistentDrawerRight.js
index 245fa63fc829d6..b8639977cf60f5 100644
--- a/docs/data/material/components/drawers/PersistentDrawerRight.js
+++ b/docs/data/material/components/drawers/PersistentDrawerRight.js
@@ -37,6 +37,13 @@ const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })(
}),
marginRight: 0,
}),
+ /**
+ * This is necessary to enable the selection of content. In the DOM, the stacking order is determined
+ * by the order of appearance. Following this rule, elements appearing later in the markup will overlay
+ * those that appear earlier. Since the Drawer comes after the Main content, this adjustment ensures
+ * proper interaction with the underlying content.
+ */
+ position: 'relative',
}),
);
diff --git a/docs/data/material/components/drawers/PersistentDrawerRight.tsx b/docs/data/material/components/drawers/PersistentDrawerRight.tsx
index f4f300d84f03cd..0935adf39ba2c0 100644
--- a/docs/data/material/components/drawers/PersistentDrawerRight.tsx
+++ b/docs/data/material/components/drawers/PersistentDrawerRight.tsx
@@ -38,6 +38,13 @@ const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })<{
}),
marginRight: 0,
}),
+ /**
+ * This is necessary to enable the selection of content. In the DOM, the stacking order is determined
+ * by the order of appearance. Following this rule, elements appearing later in the markup will overlay
+ * those that appear earlier. Since the Drawer comes after the Main content, this adjustment ensures
+ * proper interaction with the underlying content.
+ */
+ position: 'relative',
}));
interface AppBarProps extends MuiAppBarProps {
diff --git a/docs/data/material/components/icons/CreateSvgIcon.js b/docs/data/material/components/icons/CreateSvgIcon.js
index fcea59053c9594..ec540e8058cd14 100644
--- a/docs/data/material/components/icons/CreateSvgIcon.js
+++ b/docs/data/material/components/icons/CreateSvgIcon.js
@@ -1,5 +1,5 @@
import * as React from 'react';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import { createSvgIcon } from '@mui/material/utils';
const HomeIcon = createSvgIcon(
@@ -23,17 +23,11 @@ const PlusIcon = createSvgIcon(
export default function CreateSvgIcon() {
return (
- :not(style)': {
- m: 2,
- },
- }}
- >
+
-
+
);
}
diff --git a/docs/data/material/components/icons/CreateSvgIcon.tsx b/docs/data/material/components/icons/CreateSvgIcon.tsx
index fcea59053c9594..ec540e8058cd14 100644
--- a/docs/data/material/components/icons/CreateSvgIcon.tsx
+++ b/docs/data/material/components/icons/CreateSvgIcon.tsx
@@ -1,5 +1,5 @@
import * as React from 'react';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import { createSvgIcon } from '@mui/material/utils';
const HomeIcon = createSvgIcon(
@@ -23,17 +23,11 @@ const PlusIcon = createSvgIcon(
export default function CreateSvgIcon() {
return (
- :not(style)': {
- m: 2,
- },
- }}
- >
+
-
+
);
}
diff --git a/docs/data/material/components/icons/FontAwesomeIcon.js b/docs/data/material/components/icons/FontAwesomeIcon.js
index 74582f474d10e9..f0cc681d9def22 100644
--- a/docs/data/material/components/icons/FontAwesomeIcon.js
+++ b/docs/data/material/components/icons/FontAwesomeIcon.js
@@ -1,6 +1,6 @@
import * as React from 'react';
import { loadCSS } from 'fg-loadcss';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import { green } from '@mui/material/colors';
import Icon from '@mui/material/Icon';
@@ -18,13 +18,7 @@ export default function FontAwesomeIcon() {
}, []);
return (
- :not(style)': {
- m: 2,
- },
- }}
- >
+
-
+
);
}
diff --git a/docs/data/material/components/icons/FontAwesomeIcon.tsx b/docs/data/material/components/icons/FontAwesomeIcon.tsx
index 086d8cc886d93a..121a0c1ddab0b4 100644
--- a/docs/data/material/components/icons/FontAwesomeIcon.tsx
+++ b/docs/data/material/components/icons/FontAwesomeIcon.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
import { loadCSS } from 'fg-loadcss';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import { green } from '@mui/material/colors';
import Icon from '@mui/material/Icon';
@@ -18,13 +18,7 @@ export default function FontAwesomeIcon() {
}, []);
return (
- :not(style)': {
- m: 2,
- },
- }}
- >
+
-
+
);
}
diff --git a/docs/data/material/components/icons/FontAwesomeIconSize.js b/docs/data/material/components/icons/FontAwesomeIconSize.js
index d7c8f73b2006d4..7aa4e5fcc5e49c 100644
--- a/docs/data/material/components/icons/FontAwesomeIconSize.js
+++ b/docs/data/material/components/icons/FontAwesomeIconSize.js
@@ -1,7 +1,7 @@
import * as React from 'react';
import { loadCSS } from 'fg-loadcss';
import { ThemeProvider, createTheme } from '@mui/material/styles';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import Icon from '@mui/material/Icon';
import MdPhone from '@mui/icons-material/Phone';
import Chip from '@mui/material/Chip';
@@ -35,17 +35,11 @@ export default function FontAwesomeIconSize() {
}, []);
return (
- :not(style)': {
- m: 1,
- },
- }}
- >
+
} label="Call me" />
} label="Call me" />
-
+
);
}
diff --git a/docs/data/material/components/icons/FontAwesomeIconSize.tsx b/docs/data/material/components/icons/FontAwesomeIconSize.tsx
index 52b46aa319bbe2..a074fe9d889200 100644
--- a/docs/data/material/components/icons/FontAwesomeIconSize.tsx
+++ b/docs/data/material/components/icons/FontAwesomeIconSize.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import { loadCSS } from 'fg-loadcss';
import { ThemeProvider, createTheme } from '@mui/material/styles';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import Icon from '@mui/material/Icon';
import MdPhone from '@mui/icons-material/Phone';
import Chip from '@mui/material/Chip';
@@ -35,17 +35,11 @@ export default function FontAwesomeIconSize() {
}, []);
return (
- :not(style)': {
- m: 1,
- },
- }}
- >
+
} label="Call me" />
} label="Call me" />
-
+
);
}
diff --git a/docs/data/material/components/icons/FontAwesomeSvgIconDemo.js b/docs/data/material/components/icons/FontAwesomeSvgIconDemo.js
index f4cd9b88b6db9f..06824b5ca00cd2 100644
--- a/docs/data/material/components/icons/FontAwesomeSvgIconDemo.js
+++ b/docs/data/material/components/icons/FontAwesomeSvgIconDemo.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { faEllipsisV } from '@fortawesome/free-solid-svg-icons/faEllipsisV';
import { faInfo } from '@fortawesome/free-solid-svg-icons/faInfo';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import SvgIcon from '@mui/material/SvgIcon';
@@ -41,13 +41,7 @@ FontAwesomeSvgIcon.propTypes = {
export default function FontAwesomeSvgIconDemo() {
return (
- :not(style)': {
- m: 1,
- },
- }}
- >
+
@@ -60,6 +54,6 @@ export default function FontAwesomeSvgIconDemo() {
}>
Example
-
+
);
}
diff --git a/docs/data/material/components/icons/FontAwesomeSvgIconDemo.tsx b/docs/data/material/components/icons/FontAwesomeSvgIconDemo.tsx
index 580c90f9473691..7c631d9c9e15b9 100644
--- a/docs/data/material/components/icons/FontAwesomeSvgIconDemo.tsx
+++ b/docs/data/material/components/icons/FontAwesomeSvgIconDemo.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import { faEllipsisV } from '@fortawesome/free-solid-svg-icons/faEllipsisV';
import { faInfo } from '@fortawesome/free-solid-svg-icons/faInfo';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import SvgIcon from '@mui/material/SvgIcon';
@@ -42,13 +42,7 @@ const FontAwesomeSvgIcon = React.forwardRef :not(style)': {
- m: 1,
- },
- }}
- >
+
@@ -61,6 +55,6 @@ export default function FontAwesomeSvgIconDemo() {
}>
Example
-
+
);
}
diff --git a/docs/data/material/components/icons/Icons.js b/docs/data/material/components/icons/Icons.js
index e7381e6e23065d..d896873a8358fd 100644
--- a/docs/data/material/components/icons/Icons.js
+++ b/docs/data/material/components/icons/Icons.js
@@ -1,22 +1,16 @@
import * as React from 'react';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import { green } from '@mui/material/colors';
import Icon from '@mui/material/Icon';
export default function Icons() {
return (
- :not(style)': {
- m: 2,
- },
- }}
- >
+
add_circle
add_circle
add_circle
add_circle
add_circle
-
+
);
}
diff --git a/docs/data/material/components/icons/Icons.tsx b/docs/data/material/components/icons/Icons.tsx
index e7381e6e23065d..d896873a8358fd 100644
--- a/docs/data/material/components/icons/Icons.tsx
+++ b/docs/data/material/components/icons/Icons.tsx
@@ -1,22 +1,16 @@
import * as React from 'react';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import { green } from '@mui/material/colors';
import Icon from '@mui/material/Icon';
export default function Icons() {
return (
- :not(style)': {
- m: 2,
- },
- }}
- >
+
add_circle
add_circle
add_circle
add_circle
add_circle
-
+
);
}
diff --git a/docs/data/material/components/icons/SvgIconsColor.js b/docs/data/material/components/icons/SvgIconsColor.js
index 23276a81af602c..8ce08b8f04520d 100644
--- a/docs/data/material/components/icons/SvgIconsColor.js
+++ b/docs/data/material/components/icons/SvgIconsColor.js
@@ -1,5 +1,5 @@
import * as React from 'react';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import { pink } from '@mui/material/colors';
import SvgIcon from '@mui/material/SvgIcon';
@@ -13,13 +13,7 @@ function HomeIcon(props) {
export default function SvgIconsColor() {
return (
- :not(style)': {
- m: 2,
- },
- }}
- >
+
@@ -27,6 +21,6 @@ export default function SvgIconsColor() {
-
+
);
}
diff --git a/docs/data/material/components/icons/SvgIconsColor.tsx b/docs/data/material/components/icons/SvgIconsColor.tsx
index 65eb8b31d8812b..8afc0faca5f04f 100644
--- a/docs/data/material/components/icons/SvgIconsColor.tsx
+++ b/docs/data/material/components/icons/SvgIconsColor.tsx
@@ -1,5 +1,5 @@
import * as React from 'react';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import { pink } from '@mui/material/colors';
import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon';
@@ -13,13 +13,7 @@ function HomeIcon(props: SvgIconProps) {
export default function SvgIconsColor() {
return (
- :not(style)': {
- m: 2,
- },
- }}
- >
+
@@ -27,6 +21,6 @@ export default function SvgIconsColor() {
-
+
);
}
diff --git a/docs/data/material/components/icons/SvgIconsSize.js b/docs/data/material/components/icons/SvgIconsSize.js
index a7b0ea3b1e3089..e32dbb810632ba 100644
--- a/docs/data/material/components/icons/SvgIconsSize.js
+++ b/docs/data/material/components/icons/SvgIconsSize.js
@@ -1,5 +1,5 @@
import * as React from 'react';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import SvgIcon from '@mui/material/SvgIcon';
function HomeIcon(props) {
@@ -12,17 +12,11 @@ function HomeIcon(props) {
export default function SvgIconsSize() {
return (
- :not(style)': {
- m: 2,
- },
- }}
- >
+
-
+
);
}
diff --git a/docs/data/material/components/icons/SvgIconsSize.tsx b/docs/data/material/components/icons/SvgIconsSize.tsx
index f7592b4c4ab0df..efebb2e816dbca 100644
--- a/docs/data/material/components/icons/SvgIconsSize.tsx
+++ b/docs/data/material/components/icons/SvgIconsSize.tsx
@@ -1,5 +1,5 @@
import * as React from 'react';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon';
function HomeIcon(props: SvgIconProps) {
@@ -12,17 +12,11 @@ function HomeIcon(props: SvgIconProps) {
export default function SvgIconsSize() {
return (
- :not(style)': {
- m: 2,
- },
- }}
- >
+
-
+
);
}
diff --git a/docs/data/material/components/icons/icons.md b/docs/data/material/components/icons/icons.md
index ef0fafe9a5991d..472f72bcd7675a 100644
--- a/docs/data/material/components/icons/icons.md
+++ b/docs/data/material/components/icons/icons.md
@@ -12,30 +12,35 @@ materialDesign: https://m2.material.io/design/iconography/system-icons.html
Material UI provides icon support in three ways:
-1. Standardized [Material Icons](#material-svg-icons) exported as React components (SVG icons).
+1. With [Material Icons](#material-svg-icons) exported as React components (SVG icons).
1. With the [SvgIcon](#svgicon) component, a React wrapper for custom SVG icons.
1. With the [Icon](#icon-font-icons) component, a React wrapper for custom font icons.
## Material SVG icons
-Google has created over 2,100 official Material icons, each in five different "themes" (see below).
+Google has created over 2,100 official [Material icons](https://fonts.google.com/icons?icon.set=Material+Icons), each in five different "themes" (see below).
For each SVG icon, we export the respective React component from the `@mui/icons-material` package.
You can [search the full list of these icons](/material-ui/material-icons/).
### Installation
-To install and save in your `package.json` dependencies, run the command below using **npm**:
+Run one of the following commands to install it and save it to your `package.json` dependencies:
-```bash
+
+```bash npm
npm install @mui/icons-material
```
-Or **yarn**:
-
-```bash
+```bash yarn
yarn add @mui/icons-material
```
+```bash pnpm
+pnpm add @mui/icons-material
+```
+
+
+
These components use the Material UI `SvgIcon` component to render the SVG path for each icon, and so have a peer-dependency on `@mui/material`.
If you aren't already using Material UI in your project, you can add it following the [installation guide](/material-ui/getting-started/installation/).
@@ -181,7 +186,7 @@ Below is a comparison of the `FontAwesomeIcon` component and a wrapped `SvgIcon`
FontAwesomeIcon's `fullWidth` prop can also be used to approximate the correct dimensions, but it isn't perfect.
-### Other Libraries
+### Other libraries
#### MDI
@@ -290,7 +295,7 @@ const theme = createTheme({
{{"demo": "FontAwesomeIconSize.js"}}
-## Font vs SVG. Which approach to use?
+## Font vs. SVGs: Which approach to use?
Both approaches work fine, however there are some subtle differences, especially in terms of performance and rendering quality.
Whenever possible SVG is preferred as it allows code splitting, supports more icons, and renders faster and better.
diff --git a/docs/data/material/components/text-fields/FormattedInputs.js b/docs/data/material/components/text-fields/FormattedInputs.js
index df3ecf6b009767..96f41bdb7a787f 100644
--- a/docs/data/material/components/text-fields/FormattedInputs.js
+++ b/docs/data/material/components/text-fields/FormattedInputs.js
@@ -2,7 +2,7 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import { IMaskInput } from 'react-imask';
import { NumericFormat } from 'react-number-format';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import Input from '@mui/material/Input';
import InputLabel from '@mui/material/InputLabel';
import TextField from '@mui/material/TextField';
@@ -73,13 +73,7 @@ export default function FormattedInputs() {
};
return (
- :not(style)': {
- m: 1,
- },
- }}
- >
+
react-imask
-
+
);
}
diff --git a/docs/data/material/components/text-fields/FormattedInputs.tsx b/docs/data/material/components/text-fields/FormattedInputs.tsx
index 994ef02385ff6e..f14a821f121e7f 100644
--- a/docs/data/material/components/text-fields/FormattedInputs.tsx
+++ b/docs/data/material/components/text-fields/FormattedInputs.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import { IMaskInput } from 'react-imask';
import { NumericFormat, NumericFormatProps } from 'react-number-format';
-import Box from '@mui/material/Box';
+import Stack from '@mui/material/Stack';
import Input from '@mui/material/Input';
import InputLabel from '@mui/material/InputLabel';
import TextField from '@mui/material/TextField';
@@ -12,7 +12,7 @@ interface CustomProps {
name: string;
}
-const TextMaskCustom = React.forwardRef(
+const TextMaskCustom = React.forwardRef(
function TextMaskCustom(props, ref) {
const { onChange, ...other } = props;
return (
@@ -54,13 +54,8 @@ const NumericFormatCustom = React.forwardRef(
},
);
-interface State {
- textmask: string;
- numberformat: string;
-}
-
export default function FormattedInputs() {
- const [values, setValues] = React.useState({
+ const [values, setValues] = React.useState({
textmask: '(100) 000-0000',
numberformat: '1320',
});
@@ -73,13 +68,7 @@ export default function FormattedInputs() {
};
return (
- :not(style)': {
- m: 1,
- },
- }}
- >
+
react-imask
-
+
);
}
diff --git a/docs/data/material/customization/dark-mode/dark-mode.md b/docs/data/material/customization/dark-mode/dark-mode.md
index c9122a6ffffa06..b324891b5a8305 100644
--- a/docs/data/material/customization/dark-mode/dark-mode.md
+++ b/docs/data/material/customization/dark-mode/dark-mode.md
@@ -16,7 +16,7 @@ const darkTheme = createTheme({
},
});
-function App() {
+export default function App() {
return (
@@ -24,8 +24,6 @@ function App() {
);
}
-
-export default App;
```
Adding `mode: 'dark'` to the `createTheme` helper modifies several palette values, as shown in the following demo:
diff --git a/docs/data/material/getting-started/templates/templates.md b/docs/data/material/getting-started/templates/templates.md
index 3bf7ca3536eb97..9460e1d877243e 100644
--- a/docs/data/material/getting-started/templates/templates.md
+++ b/docs/data/material/getting-started/templates/templates.md
@@ -9,9 +9,10 @@ title: 9+ Free React Templates
-Our curated collection of Material UI templates includes dashboards, sign-in and sign-up pages, a blog, a checkout flow, and more.
+## Free templates
-The templates can be combined with one of the [example projects](https://github.com/mui/material-ui/tree/master/examples) to form a complete starter.
+Our curated collection of free Material UI templates includes dashboards, sign-in and sign-up pages, a blog, a checkout flow, and more.
+They can be combined with one of the [example projects](/material-ui/getting-started/example-projects/) to form a complete starter.
Sections of each layout are clearly defined either by comments or use of separate files,
making it simple to extract parts of a page (such as a "hero unit", or footer, for example)
@@ -28,4 +29,6 @@ Please feel free to open an [issue](https://github.com/mui/material-ui/issues/ne
Looking for something more? You can find complete templates and themes in the premium template section.
-
+
+
+
diff --git a/docs/data/material/guides/themeable-component/StatComponent.js b/docs/data/material/guides/creating-themed-components/StatComponent.js
similarity index 100%
rename from docs/data/material/guides/themeable-component/StatComponent.js
rename to docs/data/material/guides/creating-themed-components/StatComponent.js
diff --git a/docs/data/material/guides/themeable-component/StatFullTemplate.js b/docs/data/material/guides/creating-themed-components/StatFullTemplate.js
similarity index 100%
rename from docs/data/material/guides/themeable-component/StatFullTemplate.js
rename to docs/data/material/guides/creating-themed-components/StatFullTemplate.js
diff --git a/docs/data/material/guides/themeable-component/StatFullTemplate.tsx b/docs/data/material/guides/creating-themed-components/StatFullTemplate.tsx
similarity index 100%
rename from docs/data/material/guides/themeable-component/StatFullTemplate.tsx
rename to docs/data/material/guides/creating-themed-components/StatFullTemplate.tsx
diff --git a/docs/data/material/guides/themeable-component/StatFullTemplate.tsx.preview b/docs/data/material/guides/creating-themed-components/StatFullTemplate.tsx.preview
similarity index 100%
rename from docs/data/material/guides/themeable-component/StatFullTemplate.tsx.preview
rename to docs/data/material/guides/creating-themed-components/StatFullTemplate.tsx.preview
diff --git a/docs/data/material/guides/themeable-component/StatSlots.js b/docs/data/material/guides/creating-themed-components/StatSlots.js
similarity index 100%
rename from docs/data/material/guides/themeable-component/StatSlots.js
rename to docs/data/material/guides/creating-themed-components/StatSlots.js
diff --git a/docs/data/material/guides/themeable-component/themeable-component.md b/docs/data/material/guides/creating-themed-components/creating-themed-components.md
similarity index 96%
rename from docs/data/material/guides/themeable-component/themeable-component.md
rename to docs/data/material/guides/creating-themed-components/creating-themed-components.md
index 0469f74031e334..5975c8d88da5c1 100644
--- a/docs/data/material/guides/themeable-component/themeable-component.md
+++ b/docs/data/material/guides/creating-themed-components/creating-themed-components.md
@@ -1,12 +1,12 @@
-# Themeable component
+# Creating themed components
-Create your own themeable component with Material UI theming feature.
+Learn how to create fully custom components that accept your app's theme.
## Introduction
Material UI provides a powerful theming feature that lets you add your own components to the theme and treat them as if they're built-in components.
-If you are building a component library on top of Joy UI, you can follow the step-by-step guide below to create a custom component that is themeable across multiple projects.
+If you are building a component library on top of Material UI, you can follow the step-by-step guide below to create a custom component that is themeable across multiple projects.
Alternatively, you can use the provided [template](#template) as a starting point for your component.
@@ -16,7 +16,7 @@ You don't need to connect your component to the theme if you are only using it i
## Step-by-step guide
-This guide will walk you through how to build this statistics component, which accepts the app's theme as though it were a built-in Joy UI component:
+This guide will walk you through how to build this statistics component, which accepts the app's theme as though it were a built-in Material UI component:
{{"demo": "StatComponent.js", "hideToolbar": true}}
diff --git a/docs/data/material/guides/styled-components/styled-components.md b/docs/data/material/guides/styled-components/styled-components.md
index d08a54e727b7df..d2f7502878cab7 100644
--- a/docs/data/material/guides/styled-components/styled-components.md
+++ b/docs/data/material/guides/styled-components/styled-components.md
@@ -100,6 +100,12 @@ For TypeScript, you must also update the `tsconfig.json` as shown here:
+});
```
+:::info
+**Versions compatibility**
+
+To ensure compatibility, it's essential to align the major version of `@mui/styled-engine-sc` with that of the `styled-components` package you're using. For instance, if you opt for `styled-components` version 5, it's necessary to use `@mui/styled-engine-sc` version 5. Similarly, if your preference is `styled-components` version 6, you'll need to upgrade `@mui/styled-engine-sc` to its version 6, which is currently in an alpha state.
+:::
+
## Ready-to-use examples
MUI provides boilerplate examples of Create React App with Material UI and styled-components in both JavaScript and TypeScript:
diff --git a/docs/data/material/pages.ts b/docs/data/material/pages.ts
index 38040df6ad46f5..9c070c672d4a5a 100644
--- a/docs/data/material/pages.ts
+++ b/docs/data/material/pages.ts
@@ -181,7 +181,10 @@ const pages: MuiPage[] = [
title: 'How-to guides',
children: [
{ pathname: '/material-ui/guides/api', title: 'API design approach' },
- { pathname: '/material-ui/guides/themeable-component', title: 'Themeable component' },
+ {
+ pathname: '/material-ui/guides/creating-themed-components',
+ title: 'Creating themed components',
+ },
{ pathname: '/material-ui/guides/understand-mui-packages', title: 'Understand MUI packages' },
{ pathname: '/material-ui/guides/typescript', title: 'TypeScript' },
{ pathname: '/material-ui/guides/interoperability', title: 'Style library interoperability' },
diff --git a/docs/data/system/getting-started/custom-components/StyleFunctionSxDemo.tsx b/docs/data/system/getting-started/custom-components/StyleFunctionSxDemo.tsx
index 53d9f3ee4b14b6..07a6c99d8c4b4c 100644
--- a/docs/data/system/getting-started/custom-components/StyleFunctionSxDemo.tsx
+++ b/docs/data/system/getting-started/custom-components/StyleFunctionSxDemo.tsx
@@ -1,5 +1,5 @@
import * as React from 'react';
-import styled, { InterpolationFunction, ThemeProvider } from 'styled-components';
+import styled, { ThemeProvider, StyleFunction } from 'styled-components';
import { unstable_styleFunctionSx, SxProps } from '@mui/system';
import { createTheme } from '@mui/material/styles';
@@ -10,7 +10,7 @@ interface DivProps {
const theme = createTheme();
const Div = styled('div')(
- unstable_styleFunctionSx as InterpolationFunction,
+ unstable_styleFunctionSx as StyleFunction,
);
export default function StyleFunctionSxDemo() {
diff --git a/docs/data/system/getting-started/the-sx-prop/the-sx-prop.md b/docs/data/system/getting-started/the-sx-prop/the-sx-prop.md
index d29f823eb584a0..ed3cd3240909af 100644
--- a/docs/data/system/getting-started/the-sx-prop/the-sx-prop.md
+++ b/docs/data/system/getting-started/the-sx-prop/the-sx-prop.md
@@ -203,6 +203,43 @@ The `sx` prop can also receive a callback when you need to get theme values that
/>
```
+In TypeScript, to use custom theme properties with the `sx` prop callback, extend the `Theme` type from the `@mui/system` library using [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation):
+
+```tsx
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
+import { orange } from '@mui/material/colors';
+
+declare module '@mui/system' {
+ interface Theme {
+ status: {
+ warning: string;
+ };
+ }
+}
+
+const theme = createTheme({
+ status: {
+ warning: orange[500],
+ },
+});
+
+export default function App() {
+ return (
+
+ ({
+ bgcolor: theme.status.warning,
+ })}
+ >
+ Example
+
+
+ );
+}
+```
+
## Array values
Array types are useful when you want to partially override some styles in the former index:
diff --git a/docs/package.json b/docs/package.json
index f67b0db49742b6..e6c57579f7cd30 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -20,10 +20,10 @@
"link-check": "node ./scripts/reportBrokenLinks.js"
},
"dependencies": {
- "@babel/core": "^7.22.20",
+ "@babel/core": "^7.23.0",
"@babel/plugin-transform-object-assign": "^7.22.5",
- "@babel/runtime": "^7.22.15",
- "@babel/runtime-corejs2": "^7.22.15",
+ "@babel/runtime": "^7.23.1",
+ "@babel/runtime-corejs2": "^7.23.1",
"@docsearch/react": "^3.5.2",
"@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.1",
@@ -32,32 +32,32 @@
"@fortawesome/fontawesome-svg-core": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/react-fontawesome": "^0.2.0",
- "@mui/base": "5.0.0-beta.16",
- "@mui/docs": "^5.14.10",
- "@mui/icons-material": "^5.14.9",
- "@mui/joy": "5.0.0-beta.7",
- "@mui/lab": "5.0.0-alpha.145",
+ "@mui/base": "5.0.0-beta.18",
+ "@mui/docs": "^5.14.12",
+ "@mui/icons-material": "^5.14.12",
+ "@mui/joy": "5.0.0-beta.9",
+ "@mui/lab": "5.0.0-alpha.147",
"@mui/markdown": "^5.0.0",
- "@mui/material": "^5.14.10",
- "@mui/material-next": "6.0.0-alpha.102",
- "@mui/styled-engine": "^5.14.10",
- "@mui/styled-engine-sc": "^5.14.10",
- "@mui/styles": "^5.14.10",
- "@mui/system": "^5.14.10",
- "@mui/types": "^7.2.4",
- "@mui/utils": "^5.14.10",
- "@mui/x-charts": "^6.0.0-alpha.12",
- "@mui/x-data-grid": "6.15.0",
- "@mui/x-data-grid-generator": "6.15.0",
- "@mui/x-data-grid-premium": "6.15.0",
- "@mui/x-data-grid-pro": "6.15.0",
- "@mui/x-date-pickers": "6.15.0",
- "@mui/x-date-pickers-pro": "6.15.0",
+ "@mui/material": "^5.14.12",
+ "@mui/material-next": "6.0.0-alpha.104",
+ "@mui/styled-engine": "^5.14.12",
+ "@mui/styled-engine-sc": "^5.14.12",
+ "@mui/styles": "^5.14.12",
+ "@mui/system": "^5.14.12",
+ "@mui/types": "^7.2.5",
+ "@mui/utils": "^5.14.12",
+ "@mui/x-charts": "^6.0.0-alpha.14",
+ "@mui/x-data-grid": "6.16.1",
+ "@mui/x-data-grid-generator": "6.16.1",
+ "@mui/x-data-grid-premium": "6.16.1",
+ "@mui/x-data-grid-pro": "6.16.1",
+ "@mui/x-date-pickers": "6.16.1",
+ "@mui/x-date-pickers-pro": "6.16.1",
"@mui/x-license-pro": "6.10.2",
- "@mui/x-tree-view": "6.0.0-alpha.4",
+ "@mui/x-tree-view": "6.0.0-beta.0",
"@popperjs/core": "^2.11.8",
"@react-spring/web": "^9.7.3",
- "autoprefixer": "^10.4.15",
+ "autoprefixer": "^10.4.16",
"autosuggest-highlight": "^3.3.4",
"babel-plugin-module-resolver": "^5.0.0",
"babel-plugin-optimize-clsx": "^2.6.2",
@@ -87,11 +87,11 @@
"next": "13.4.19",
"notistack": "3.0.1",
"nprogress": "^0.2.0",
- "postcss": "^8.4.29",
+ "postcss": "^8.4.30",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
- "react-draggable": "^4.4.5",
+ "react-draggable": "^4.4.6",
"react-final-form": "^6.5.9",
"react-imask": "^7.1.3",
"react-intersection-observer": "^9.5.2",
@@ -106,17 +106,16 @@
"react-virtuoso": "^4.6.0",
"react-window": "^1.8.9",
"recharts": "2.8.0",
- "rimraf": "^5.0.1",
- "styled-components": "^5.3.11",
+ "rimraf": "^5.0.5",
+ "styled-components": "^6.0.0",
"stylis": "4.2.0",
"stylis-plugin-rtl": "^2.1.1",
- "stylis-plugin-rtl-sc": "npm:stylis-plugin-rtl@^1.1.0",
"use-count-up": "^3.0.1",
"webpack-bundle-analyzer": "^4.9.1"
},
"devDependencies": {
"@babel/plugin-transform-react-constant-elements": "^7.22.5",
- "@babel/preset-typescript": "^7.22.15",
+ "@babel/preset-typescript": "^7.23.0",
"@mui-internal/docs-utilities": "^1.0.0",
"@mui-internal/test-utils": "^1.0.0",
"@types/autosuggest-highlight": "^3.2.0",
@@ -124,17 +123,16 @@
"@types/css-mediaquery": "^0.1.2",
"@types/json2mq": "^0.2.0",
"@types/markdown-to-jsx": "^7.0.1",
- "@types/node": "^18.17.18",
- "@types/prop-types": "^15.7.5",
- "@types/react": "^18.2.21",
- "@types/react-dom": "^18.2.7",
- "@types/react-swipeable-views": "^0.13.2",
- "@types/react-swipeable-views-utils": "^0.13.4",
- "@types/react-transition-group": "^4.4.6",
- "@types/react-window": "^1.8.5",
- "@types/styled-components": "5.1.27",
+ "@types/node": "^18.18.4",
+ "@types/prop-types": "^15.7.7",
+ "@types/react": "^18.2.23",
+ "@types/react-dom": "^18.2.11",
+ "@types/react-swipeable-views": "^0.13.3",
+ "@types/react-swipeable-views-utils": "^0.13.5",
+ "@types/react-transition-group": "^4.4.7",
+ "@types/react-window": "^1.8.6",
"@types/stylis": "^4.2.0",
- "chai": "^4.3.8",
+ "chai": "^4.3.10",
"cross-fetch": "^4.0.0",
"gm": "^1.25.0",
"marked": "^5.1.2",
diff --git a/docs/pages/base-ui.tsx b/docs/pages/base-ui.tsx
index d614f791a3c923..7872f910b6c141 100644
--- a/docs/pages/base-ui.tsx
+++ b/docs/pages/base-ui.tsx
@@ -21,6 +21,7 @@ export default function Core() {
You can style them with any CSS solutions like PostCSS or Tailwind CSS.`}
card="/static/blog/introducing-base-ui/card.png"
>
+ {/* eslint-disable-next-line @next/next/no-page-custom-font */}
| object
| func"
+ }
+ },
"onItemsChange": { "type": { "name": "func" } },
"slotProps": {
"type": {
diff --git a/docs/pages/base-ui/api/use-slider.json b/docs/pages/base-ui/api/use-slider.json
index 9978166f327161..620535067170fd 100644
--- a/docs/pages/base-ui/api/use-slider.json
+++ b/docs/pages/base-ui/api/use-slider.json
@@ -62,22 +62,22 @@
},
"getHiddenInputProps": {
"type": {
- "name": "<TOther extends EventHandlers = {}>(otherHandlers?: TOther) => UseSliderHiddenInputProps<TOther>",
- "description": "<TOther extends EventHandlers = {}>(otherHandlers?: TOther) => UseSliderHiddenInputProps<TOther>"
+ "name": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSliderHiddenInputProps<ExternalProps>",
+ "description": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSliderHiddenInputProps<ExternalProps>"
},
"required": true
},
"getRootProps": {
"type": {
- "name": "<TOther extends EventHandlers = {}>(otherHandlers?: TOther) => UseSliderRootSlotProps<TOther>",
- "description": "<TOther extends EventHandlers = {}>(otherHandlers?: TOther) => UseSliderRootSlotProps<TOther>"
+ "name": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSliderRootSlotProps<ExternalProps>",
+ "description": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSliderRootSlotProps<ExternalProps>"
},
"required": true
},
"getThumbProps": {
"type": {
- "name": "<TOther extends EventHandlers = {}>(otherHandlers?: TOther) => UseSliderThumbSlotProps<TOther>",
- "description": "<TOther extends EventHandlers = {}>(otherHandlers?: TOther) => UseSliderThumbSlotProps<TOther>"
+ "name": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSliderThumbSlotProps<ExternalProps>",
+ "description": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSliderThumbSlotProps<ExternalProps>"
},
"required": true
},
diff --git a/docs/pages/base-ui/api/use-tab-panel.json b/docs/pages/base-ui/api/use-tab-panel.json
index 6a42b1c8137830..1a3a16364f8c72 100644
--- a/docs/pages/base-ui/api/use-tab-panel.json
+++ b/docs/pages/base-ui/api/use-tab-panel.json
@@ -12,8 +12,8 @@
"returnValue": {
"getRootProps": {
"type": {
- "name": "() => UseTabPanelRootSlotProps",
- "description": "() => UseTabPanelRootSlotProps"
+ "name": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseTabPanelRootSlotProps<ExternalProps>",
+ "description": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseTabPanelRootSlotProps<ExternalProps>"
},
"required": true
},
diff --git a/docs/pages/base-ui/api/use-tab.json b/docs/pages/base-ui/api/use-tab.json
index 1650f8d65a5314..3f8cbe9fad95d6 100644
--- a/docs/pages/base-ui/api/use-tab.json
+++ b/docs/pages/base-ui/api/use-tab.json
@@ -21,8 +21,8 @@
"focusVisible": { "type": { "name": "boolean", "description": "boolean" }, "required": true },
"getRootProps": {
"type": {
- "name": "<TOther extends Record<string, any> = {}>(externalProps?: TOther) => UseTabRootSlotProps<TOther>",
- "description": "<TOther extends Record<string, any> = {}>(externalProps?: TOther) => UseTabRootSlotProps<TOther>"
+ "name": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseTabRootSlotProps<ExternalProps>",
+ "description": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseTabRootSlotProps<ExternalProps>"
},
"required": true
},
diff --git a/docs/pages/base-ui/api/use-tabs-list.json b/docs/pages/base-ui/api/use-tabs-list.json
index e67be1be8e0e09..a853f2012c8b7b 100644
--- a/docs/pages/base-ui/api/use-tabs-list.json
+++ b/docs/pages/base-ui/api/use-tabs-list.json
@@ -19,8 +19,8 @@
},
"getRootProps": {
"type": {
- "name": "<TOther extends Record<string, any> = {}>(externalProps?: TOther) => UseTabsListRootSlotProps<TOther>",
- "description": "<TOther extends Record<string, any> = {}>(externalProps?: TOther) => UseTabsListRootSlotProps<TOther>"
+ "name": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseTabsListRootSlotProps<ExternalProps>",
+ "description": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseTabsListRootSlotProps<ExternalProps>"
},
"required": true
},
diff --git a/docs/pages/careers.tsx b/docs/pages/careers.tsx
index de50376b50ae2c..d2bcddc73265b5 100644
--- a/docs/pages/careers.tsx
+++ b/docs/pages/careers.tsx
@@ -144,6 +144,18 @@ const openRolesData = [
'You will lead the technical, product, and operational development of the store.',
url: '/careers/product-engineer/',
},
+ {
+ title: 'React Engineer - xCharts',
+ description:
+ 'You will help form the xCharts team, build ambitious and complex new features, work on strategic problems, and help grow adoption.',
+ url: '/careers/react-engineer-x-charts/',
+ },
+ {
+ title: 'React Engineer - X',
+ description:
+ 'You will strengthen the MUI X product, build ambitious and complex new features, work on strategic problems, and help grow adoption.',
+ url: '/careers/react-engineer-x/',
+ },
],
},
];
@@ -164,12 +176,12 @@ const nextRolesData = [
'You will join the MUI Toolpad team, to explore the role of MUI in the low code space and help bring the early prototype to a usable product.',
url: '/careers/fullstack-engineer/',
},
- {
- title: 'React Engineer - X',
- description:
- 'You will strengthen the MUI X product, build ambitious and complex new features, work on strategic problems, and help grow adoption.',
- url: '/careers/react-engineer-x/',
- },
+ // {
+ // title: 'React Engineer - X',
+ // description:
+ // 'You will strengthen the MUI X product, build ambitious and complex new features, work on strategic problems, and help grow adoption.',
+ // url: '/careers/react-engineer-x/',
+ // },
{
title: 'React Tech Lead - Core',
description:
diff --git a/docs/pages/careers/react-engineer-x-charts.js b/docs/pages/careers/react-engineer-x-charts.js
new file mode 100644
index 00000000000000..da64dfa7a85cfe
--- /dev/null
+++ b/docs/pages/careers/react-engineer-x-charts.js
@@ -0,0 +1,7 @@
+import * as React from 'react';
+import TopLayoutCareers from 'docs/src/modules/components/TopLayoutCareers';
+import * as pageProps from 'docs/pages/careers/react-engineer-x-charts.md?@mui/markdown';
+
+export default function Page() {
+ return ;
+}
diff --git a/docs/pages/careers/react-engineer-x-charts.md b/docs/pages/careers/react-engineer-x-charts.md
new file mode 100644
index 00000000000000..b0613d0e1cd828
--- /dev/null
+++ b/docs/pages/careers/react-engineer-x-charts.md
@@ -0,0 +1,142 @@
+# React Engineer - xCharts
+
+You will help form the xCharts team, build ambitious and complex new features, work on strategic problems, and help grow adoption.
+
+## Details of the Role
+
+- **Location**: Remote (strong preference for UTC-6 to UTC+5).
+- **Type of work**: Full-time (contractor or employee [depending on circumstances](https://mui-org.notion.site/Hiring-FAQ-64763b756ae44c37b47b081f98915501#494af1f358794028beb4b7697b5d3102)).
+- **Level**: [4 or above](https://mui-org.notion.site/Engineering-levels-25b2fba9dd1f4b43a1b28f47f0170f23).
+- We're a **remote** company, we prefer asynchronous communication over meetings.
+
+## About the company
+
+MUI started with Material UI, the most successful React implementation of Google's Material Design.
+We have gained a large following, thanks to our focus on Material Design fidelity, our obsession with details, on offering a large number of components, our community engagement, and by carefully improving the DX.
+Today, countless teams and organizations rely on our open-source libraries to build their design system.
+
+A couple of years ago, we started to expand our suite of products.
+We released [MUI X](https://mui.com/x/), a collection of advanced components; [MUI Design kits](https://mui.com/design-kits/), the MUI components available for Figma, Sketch, etc.; and also host [Templates](https://mui.com/templates/), a set of pre-built UI kits.
+We've seen rapid growth with all of them (2x per year) and we have more to come.
+We are building [a low-code platform](https://mui.com/toolpad/) for developers to significantly increase the speed and lower the barrier for creating simple CRUD/dashboard UIs with MUI's libraries.
+
+We are a fully distributed team, spread across multiple time zones.
+We work mainly asynchronously, relying mostly on written collaboration.
+Every contributor has the freedom to define how they work — the rest of us won't know what you're doing day-to-day unless you tell us.
+For additional details about the MUI team and culture, you can check our [careers](https://mui.com/careers/) and [about](https://mui.com/about/) pages and also our [public Handbook](https://mui-org.notion.site/Handbook-f086d47e10794d5e839aef9dc67f324b).
+
+## Why we're hiring
+
+The charts team (part of MUI X) needs your help.
+The component is off to [a great start](https://npm-stat.com/charts.html?package=%40mui%2Fx-charts&from=2021-06-01), however we have only started to scratch the surface for the potential of this component. There is x10 more to build.
+
+To be more specific in what we are aiming to achieve in the short to mid-term:
+
+- A tighter integration with the rest of the MUI libraries including Material UI and MUI X Data Grid
+- Faster iteration cycles compared to popular open-source alternatives such as chart.js and Recharts
+
+This should allow us to reach 30% of the downloads of alternative React charting libraries, considering benchmark data in the short term. Developers value having a single touch point, but also one they trust, and one that integrates well into the rest of their application.
+
+In the mid-term, we aspired for this charting library to become a standard in the React ecosystem, outgrowing Material UI or any other UI library.
+We believe we can achieve this with an open-core model.
+We will at least match the features available in the alternative open-source projects, licensed as MIT in MUI X Charts.
+We will then provide extra paid features so developers can use a single charting library, without the need to juggle with paid alternatives as they do today.
+
+In the long term, we envision using the pro-code charting API as a distribution channel for building more abstract charting primitives, using low-code and AI.
+
+## About the role
+
+### Why this is interesting
+
+The advanced components portfolio is still small, with a million interesting and challenging problems to solve.
+
+Our products empower React developers to build awesome applications faster – we see millions of developers on MUI's docs every year, one million a month.
+
+### What you'll do on a day-to-day basis
+
+Depending on the day, you'll:
+
+- **Help guide architectural decisions**.
+ The future of MUI is discussed and planned in our public RFCs and issues.
+ You'll be helping drive these conversations and guiding MUI toward the best possible solutions.
+- **Contribute to deep, meaningful refactors and feature releases**.
+ MUI is a complex codebase. Components we've shipped recently, such as the data grid and date pickers have required months of dedicated, careful work.
+- **Reduce friction**.
+ A large amount of the work on MUI is reducing friction and making it easier to use.
+ This might involve careful API design, identifying and fixing top bugs, creating easier-to-understand error messages, and writing documentation and blog posts about features you ship.
+- **Collaborate with the community**.
+ Many small, as well as meaningful fixes and features, have been contributed by the community. Your role is to draw the best out of the community — to inspire those across the world to create and contribute through your reviews of their issues and pull requests.
+- **Experiment and play**. Great, unexpected features and heisenbug fixes have come from a number of sources — relentlessly methodical processes of elimination, free-flowing team collaboration, inspiration by adjacent libraries and projects, and difficult-to-explain individual strokes of brilliance. Whatever your preferred style is for creating new things that others might not have thought of, you'll find a welcome home on the team.
+- **Take ownership of features from idea/mockup to live deployment**.
+ You'll shape and guide the direction of crucial new features, including new components.
+- **Ship. Early and often**. You'll iterate and ship frequently.
+ You'll have a real impact on the end-user experience and you'll love working on a team that builds stunning UIs and prioritizes delivering real user value as often as possible.
+- **You'll be interacting with the users** on a regular basis, handling inbound support and feature requests (every developer helps with developer requests).
+
+### The best parts of this job
+
+- **You'll be at the cutting edge of application development** — working on one of the fastest-growing UI libraries on the market.
+- **You'll be part of an active, open, friendly community** of developers that are excited about building awesome applications.
+- **Your role will be key to making MUI the go-to UI framework** for building applications, websites, and design systems with React.
+
+### The worst parts of this job
+
+- **Shifting context.**
+ You will necessarily have to shift context and dive into a different feature before the current one is done.
+ It may even be in an area of the codebase you're unfamiliar with or don't have a ton of understanding about.
+ It's fun, rewarding work, but it can be very challenging.
+- **We move quickly but don't sacrifice quality**.
+ We ship early, often, and quickly. You may not be initially comfortable with the cadence with which we ship high-quality features and improvements to end-users. By doing so, we sacrifice on solving each problem 100% in exchange for fast feedback. Solving 50-70% of the issue with quality should be enough for any given iteration. Our users quickly tell us when we haven't pushed a solution far enough.
+- **MUI is a large codebase**. You may bang your head against the wall at times, and then write tests to assist future you 😌.
+ The work you will be doing is somewhat unique and idiosyncratic. You probably have not had a similar role before.
+- **In open-source, you're faced with a nonstop stream of bug reports and support requests**. That means you need to develop an intuition for when to ignore something, and when to dig in further.
+
+## About you
+
+We're looking for someone with strong front-end skills. More important than specific technical skills though is that you're a strong problem solver who loves to learn. Details matter to you.
+
+### Skills you should have
+
+- **Expertise in the modern JavaScript ecosystem**.
+ MUI is built on the shoulders of giants, making use of technologies such as ES2021, TypeScript, Node.js, React, Next.js, webpack, and Babel.
+- **A track record of demonstrating an eye for product and solving real-world user problems**. If you have a knack for solving problems at the root cause, shipping beautiful user interfaces and intuitive APIs, we want you on our team.
+- **Experience building and shipping production code in a team setting** with a passion for writing tested, performant, and high-quality code.
+- **Strong written and verbal communication skills**.
+ As part of the team, you'll interface both directly and indirectly with community members and enterprise customers, and contribute to user documentation. Clear communication is fundamental in creating intuitive and compelling resources.
+- **Ability to dive into complex problems**.
+ You should be able to quickly assess, understand, and iterate upon aspects of our codebase.
+- **Ready and willing to ask and answer questions**.
+ If you're comfortable saying you're unsure, asking for help; but equally reaching out to assist others, you'll be an incredible addition to our team. We thrive because of continuous learning. First-time mistakes should be celebrated, not blamed.
+- **Experience or interest in drawing technologies**.
+ Charts use SVG and canvas which implies using other API than HTML/CSS. Hope you know them or enjoy discovering new documentation.
+- **Avoid monolithic deliverables**.
+ You scope and stage your work into well-defined milestones to ship.
+- **Past work with front-end infrastructure**.
+ Perhaps you've created your company's design system, written a Babel plugin, or written complex React components.
+ It would be great if you could address this in your cover letter!
+
+### What it would be nice if you had, but isn't required
+
+- **You've experience with charts**.
+ You have contributed to building chart libraries, integrated charts in a design system, or contributed to chart intensive applications.
+ You have built complex and advanced features while making sure the accessibility was fully functional.
+- **You've contributed to a design system before**.
+ You have worked on enterprise components in the past, maybe for internal use in your company.
+ You have built complex and advanced features while making sure the accessibility was fully functional.
+- **You've maintained an active repository before**.
+ Maybe you've helped maintain a popular open-source repository, or perhaps you've worked on internal repositories that saw contributions from multiple teams.
+ Previous experience with highly active repository workflows is a definite plus for this role.
+- **You have contributed code to MUI before**. A history of contributing to MUI would be a definite plus.
+
+## Benefits & Compensation
+
+Competitive compensation depending on the profile and location.
+We are ready to pay top market rates for a person that can clearly exceed the role's expectations.
+You can find the other perks & benefits on the [careers](https://mui.com/careers/#perks-amp-benefits) page.
+
+## How to apply?
+
+[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/2a1b0084-53aa-4aca-84ec-f8cfe25093ae/application?utm_source=ZNRrPGBkqO)
+
+Don't tick every bullet? Apply anyway! Research shows that certain folx are less likely to apply for a role than others [unless they meet 100%](https://hbr.org/2014/08/why-women-dont-apply-for-jobs-unless-theyre-100-qualified) of the outlined qualifications.
+If this role excites you, we want to hear from you. We'd love for you to share the unique skills, passion, and experience you could bring to MUI.
diff --git a/docs/pages/careers/react-engineer-x.md b/docs/pages/careers/react-engineer-x.md
index c557c9ee3db9f4..93f5db7357da46 100644
--- a/docs/pages/careers/react-engineer-x.md
+++ b/docs/pages/careers/react-engineer-x.md
@@ -1,4 +1,4 @@
-# React Engineer - X (future role)
+# React Engineer - X
You will strengthen the MUI X product, build ambitious and complex new features, work on strategic problems, and help grow adoption.
diff --git a/docs/pages/experiments/index.js b/docs/pages/experiments/index.js
index 1d636fe93b3b7a..26c01c3bb60516 100644
--- a/docs/pages/experiments/index.js
+++ b/docs/pages/experiments/index.js
@@ -33,108 +33,113 @@ export default function Experiments({ experiments }) {
return (
-
+
+
+
+
+ Welcome to
+
+
+ MUI Experiments
+
+
+
+
+
+ The files under /experiments/*
are committed to git.
+
+
+ These URLs (start with /experiments/*
) are not accessible in
+ production.
+
+
+
+
+
(theme.palette.mode === 'dark' ? 'primaryDark.900' : 'grey.50'),
+ flexGrow: 1,
}}
>
-
- Welcome to
-
-
- MUI Experiments
-
-
-
-
-
- The files under /experiments/*
are committed to git.
-
-
- These URLs (start with /experiments/*
) are not accessible in
- production.
-
-
-
-
-
- (theme.palette.mode === 'dark' ? 'primaryDark.900' : 'grey.50') }}
- >
-
-
- All Experiments ({experiments.length})
-
- {experiments.length > 0 && (
-
+
- {Object.entries(categories).map(([categoryName, children]) => (
-
-
- {categoryName}
-
-
- {(children || []).map((aPage) => {
- return (
-
-
- {aPage.name}
-
+ {experiments.length > 0 && (
+
+ {Object.entries(categories).map(([categoryName, children]) => (
+
+
+ {categoryName}
+
+
+ {(children || []).map((aPage) => {
+ return (
+
+
-
-
- );
- })}
-
-
- ))}
-
- )}
-
+ >
+ {aPage.name}
+
+
+
+ );
+ })}
+
+
+ ))}
+
+ )}
+
+
);
diff --git a/docs/pages/experiments/md3/buttons.tsx b/docs/pages/experiments/md3/buttons.tsx
new file mode 100644
index 00000000000000..8128c2de82628e
--- /dev/null
+++ b/docs/pages/experiments/md3/buttons.tsx
@@ -0,0 +1,228 @@
+import * as React from 'react';
+import TextField from '@mui/material/TextField';
+import Stack from '@mui/material/Stack';
+import MD2Button, { ButtonProps as MD2ButtonProps } from '@mui/material/Button';
+import { unstable_capitalize as capitalize } from '@mui/utils';
+import DeleteIcon from '@mui/icons-material/Delete';
+import SendIcon from '@mui/icons-material/Send';
+import Button, { ButtonProps } from '@mui/material-next/Button';
+import { CssVarsProvider, extendTheme } from '@mui/material-next/styles';
+import CssBaseline from '@mui/material/CssBaseline';
+import { customPalette, ModeSwitcher } from '.';
+
+const variants: ButtonProps['variant'][] = [
+ 'elevated',
+ 'filled',
+ 'filledTonal',
+ 'outlined',
+ 'text',
+];
+const colors: ButtonProps['color'][] = ['primary', 'secondary', 'tertiary'];
+const sizes: ButtonProps['size'][] = ['small', 'medium', 'large'];
+
+const md2Variants: MD2ButtonProps['variant'][] = ['contained', 'outlined', 'text'];
+const md2Colors: MD2ButtonProps['color'][] = [
+ 'primary',
+ 'secondary',
+ 'success',
+ 'error',
+ 'info',
+ 'warning',
+];
+
+function DemoComponents() {
+ const [radius, setRadius] = React.useState
('10');
+ const [gap, setGap] = React.useState('0.5');
+
+ return (
+
+ Enabled
+
+ {variants.map((variant) => (
+
+ ))}
+
+ Enabled without a ripple effect
+
+ {variants.map((variant) => (
+
+ ))}
+
+ Disabled
+
+ {variants.map((variant) => (
+
+ ))}
+
+ Colors
+
+ {colors.map((color) => (
+
+ ))}
+
+
+ {colors.map((color) => (
+
+ ))}
+
+
+ {colors.map((color) => (
+
+ ))}
+
+ Extended buttons
+
+ {colors.map((color) => (
+ }>
+ Send
+
+ ))}
+ }>
+ Send
+
+
+
+ {colors.map((color) => (
+ }>
+ Delete
+
+ ))}
+ }>
+ Delete
+
+
+ Sizes
+
+ {sizes.map((size) => (
+ }>
+ {capitalize(size as string)}
+
+ ))}
+
+
+ {sizes.map((size) => (
+ }>
+ {capitalize(size as string)}
+
+ ))}
+
+ sx prop showcase
+
+
+
+
+ MD2 Button
+
+
+ CSS vars playground
+
+
+ {
+ setRadius(e.target.value);
+ }}
+ />
+ {
+ setGap(e.target.value);
+ }}
+ />
+
+
+ {sizes.map((size) => (
+ }
+ >
+ {capitalize(size as string)}
+
+ ))}
+
+
+ Material Design 2 Buttons
+
+ {md2Variants.map((variant) => (
+
+ {capitalize(variant as string)}
+
+ ))}
+
+
+ {md2Colors.map((color) => (
+
+ {capitalize(color as string)}
+
+ ))}
+
+
+ );
+}
+
+// custom MD3 theme
+const cssVarsTheme = extendTheme({
+ colorSchemes: {
+ light: {
+ ref: {
+ palette: customPalette,
+ },
+ },
+ dark: {
+ ref: {
+ palette: customPalette,
+ },
+ },
+ },
+});
+
+export default function App() {
+ return (
+
+
+
+
+
+
+
+ );
+}
diff --git a/docs/pages/experiments/md3/index.tsx b/docs/pages/experiments/md3/index.tsx
index cb784397491ab5..c67299fe14ec18 100644
--- a/docs/pages/experiments/md3/index.tsx
+++ b/docs/pages/experiments/md3/index.tsx
@@ -1,237 +1,11 @@
import * as React from 'react';
import Tooltip from '@mui/material/Tooltip';
import IconButton from '@mui/material/IconButton';
-import TextField from '@mui/material/TextField';
-import Stack from '@mui/material/Stack';
-import MD2Button, { ButtonProps as MD2ButtonProps } from '@mui/material/Button';
-import { unstable_capitalize as capitalize } from '@mui/utils';
-import DeleteIcon from '@mui/icons-material/Delete';
-import SendIcon from '@mui/icons-material/Send';
-import Button, { ButtonProps } from '@mui/material-next/Button';
-import { CssVarsProvider, useColorScheme, extendTheme } from '@mui/material-next/styles';
import DarkIcon from '@mui/icons-material/DarkModeOutlined';
import LightIcon from '@mui/icons-material/LightModeOutlined';
-import CssBaseline from '@mui/material/CssBaseline';
+import { useColorScheme } from '@mui/material-next/styles';
-function ModeSwitcher() {
- const { mode, setMode } = useColorScheme();
- const [mounted, setMounted] = React.useState(false);
-
- React.useEffect(() => {
- setMounted(true);
- }, []);
-
- if (!mounted) {
- return null;
- }
-
- return (
-
- {
- if (mode === 'light') {
- setMode('dark');
- } else {
- setMode('light');
- }
- }}
- >
- {mode === 'light' ? : }
-
-
- );
-}
-
-const variants: ButtonProps['variant'][] = [
- 'elevated',
- 'filled',
- 'filledTonal',
- 'outlined',
- 'text',
-];
-const colors: ButtonProps['color'][] = ['primary', 'secondary', 'tertiary'];
-const sizes: ButtonProps['size'][] = ['small', 'medium', 'large'];
-
-const md2Variants: MD2ButtonProps['variant'][] = ['contained', 'outlined', 'text'];
-const md2Colors: MD2ButtonProps['color'][] = [
- 'primary',
- 'secondary',
- 'success',
- 'error',
- 'info',
- 'warning',
-];
-
-function DemoComponents() {
- const [radius, setRadius] = React.useState('10');
- const [gap, setGap] = React.useState('0.5');
-
- return (
-
- Enabled
-
- {variants.map((variant) => (
-
- ))}
-
- Enabled without a ripple effect
-
- {variants.map((variant) => (
-
- ))}
-
- Disabled
-
- {variants.map((variant) => (
-
- ))}
-
- Colors
-
- {colors.map((color) => (
-
- ))}
-
-
- {colors.map((color) => (
-
- ))}
-
-
- {colors.map((color) => (
-
- ))}
-
- Extended buttons
-
- {colors.map((color) => (
- }>
- Send
-
- ))}
- }>
- Send
-
-
-
- {colors.map((color) => (
- }>
- Delete
-
- ))}
- }>
- Delete
-
-
- Sizes
-
- {sizes.map((size) => (
- }>
- {capitalize(size as string)}
-
- ))}
-
-
- {sizes.map((size) => (
- }>
- {capitalize(size as string)}
-
- ))}
-
- sx prop showcase
-
-
-
-
- MD2 Button
-
-
- CSS vars playground
-
-
- {
- setRadius(e.target.value);
- }}
- />
- {
- setGap(e.target.value);
- }}
- />
-
-
- {sizes.map((size) => (
- }
- >
- {capitalize(size as string)}
-
- ))}
-
-
- Material Design 2 Buttons
-
- {md2Variants.map((variant) => (
-
- {capitalize(variant as string)}
-
- ))}
-
-
- {md2Colors.map((color) => (
-
- {capitalize(color as string)}
-
- ))}
-
-
- );
-}
-
-const customPalette = {
+export const customPalette = {
primary: {
'0': '#000000',
'10': '#3e001f',
@@ -292,6 +66,7 @@ const customPalette = {
'90': '#ebe0e1',
'92': '#f1e5e6',
'95': '#faeef0',
+ '96': '#f7f2fa',
'99': '#fffbff',
'100': '#ffffff',
},
@@ -327,30 +102,35 @@ const customPalette = {
},
};
-// custom MD3 theme
-const cssVarsTheme = extendTheme({
- colorSchemes: {
- light: {
- ref: {
- palette: customPalette,
- },
- },
- dark: {
- ref: {
- palette: customPalette,
- },
- },
- },
-});
+export function ModeSwitcher() {
+ const { mode, setMode } = useColorScheme();
+ const [mounted, setMounted] = React.useState(false);
+
+ React.useEffect(() => {
+ setMounted(true);
+ }, []);
+
+ if (!mounted) {
+ return null;
+ }
-export default function App() {
return (
-
-
-
-
-
-
-
+
+ {
+ if (mode === 'light') {
+ setMode('dark');
+ } else {
+ setMode('light');
+ }
+ }}
+ >
+ {mode === 'light' ? : }
+
+
);
}
+
+export default function Page() {
+ return Empty
;
+}
diff --git a/docs/pages/experiments/md3/inputs.tsx b/docs/pages/experiments/md3/inputs.tsx
new file mode 100644
index 00000000000000..5a80eb6e60d349
--- /dev/null
+++ b/docs/pages/experiments/md3/inputs.tsx
@@ -0,0 +1,31 @@
+import * as React from 'react';
+import Stack from '@mui/material/Stack';
+import Md2FilledInput from '@mui/material/FilledInput';
+import { ThemeProvider, createTheme } from '@mui/material/styles';
+import FilledInput from '@mui/material-next/FilledInput';
+import { CssVarsProvider, extendTheme } from '@mui/material-next/styles';
+import { ModeSwitcher } from '.';
+
+const md2Theme = createTheme();
+
+const md3Theme = extendTheme();
+
+export default function MaterialYouInputs() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/docs/pages/joy-ui/getting-started/roadmap.js b/docs/pages/joy-ui/getting-started/roadmap.js
new file mode 100644
index 00000000000000..f9b3bec81e8cb4
--- /dev/null
+++ b/docs/pages/joy-ui/getting-started/roadmap.js
@@ -0,0 +1,7 @@
+import * as React from 'react';
+import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
+import * as pageProps from 'docs/data/joy/getting-started/roadmap/roadmap.md?@mui/markdown';
+
+export default function Page() {
+ return ;
+}
diff --git a/docs/pages/joy-ui/getting-started/templates/messages.js b/docs/pages/joy-ui/getting-started/templates/messages.js
index df7035a19800f2..5999366592d307 100644
--- a/docs/pages/joy-ui/getting-started/templates/messages.js
+++ b/docs/pages/joy-ui/getting-started/templates/messages.js
@@ -10,6 +10,7 @@ export default function Messages() {
+ {/* eslint-disable-next-line @next/next/no-page-custom-font */}
+ {/* eslint-disable-next-line @next/next/no-page-custom-font */}
+ {/* eslint-disable-next-line @next/next/no-page-custom-font */}
+ {/* eslint-disable-next-line @next/next/no-page-custom-font */}
+ {/* eslint-disable-next-line @next/next/no-page-custom-font */}
| 'secondary'
| string"
+ "description": "'primary'
| 'secondary'
| 'error'
| 'info'
| 'success'
| 'warning'
| string"
},
"default": "'primary'"
},
@@ -133,6 +133,10 @@
"root",
"colorPrimary",
"colorSecondary",
+ "colorError",
+ "colorInfo",
+ "colorSuccess",
+ "colorWarning",
"marked",
"vertical",
"disabled",
@@ -151,6 +155,10 @@
"sizeSmall",
"thumbColorPrimary",
"thumbColorSecondary",
+ "thumbColorError",
+ "thumbColorInfo",
+ "thumbColorSuccess",
+ "thumbColorWarning",
"thumbSizeSmall",
"valueLabel",
"valueLabelOpen",
diff --git a/docs/pages/material-ui/guides/themeable-component.js b/docs/pages/material-ui/guides/creating-themed-components.js
similarity index 58%
rename from docs/pages/material-ui/guides/themeable-component.js
rename to docs/pages/material-ui/guides/creating-themed-components.js
index e7c2472aa29d84..1fc92e78fa2163 100644
--- a/docs/pages/material-ui/guides/themeable-component.js
+++ b/docs/pages/material-ui/guides/creating-themed-components.js
@@ -1,6 +1,6 @@
import * as React from 'react';
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
-import * as pageProps from 'docs/data/material/guides/themeable-component/themeable-component.md?@mui/markdown';
+import * as pageProps from 'docs/data/material/guides/creating-themed-components/creating-themed-components.md?@mui/markdown';
export default function Page() {
return ;
diff --git a/docs/public/_redirects b/docs/public/_redirects
index 9b45e8509f1fc6..24f6abf16d8e37 100644
--- a/docs/public/_redirects
+++ b/docs/public/_redirects
@@ -494,6 +494,7 @@ https://v4.material-ui.com/* https://v4.mui.com/:splat 301!
/material-ui/api/tree-view/ /x/api/tree-view/tree-view/ 301
/material-ui/api/tree-item/ /x/api/tree-view/tree-item/ 301
/material-ui/guides/styled-engine/ /material-ui/guides/styled-components/ 301
+/material-ui/guides/themeable-component/ /material-ui/guides/creating-themed-components/ 301
# Proxies
@@ -522,3 +523,4 @@ https://v4.material-ui.com/* https://v4.mui.com/:splat 301!
### MUI Design kits
/figma/getting-started/ https://mui-org.notion.site/MUI-for-Figma-docs-4eb22360388047a9a31fc19d300a285e 302
+/r/figma-* https://mui-store.netlify.app/r/figma-:splat 200
diff --git a/docs/public/static/images/themes-display.png b/docs/public/static/images/themes-display.png
new file mode 100644
index 00000000000000..43069c6f6855bf
Binary files /dev/null and b/docs/public/static/images/themes-display.png differ
diff --git a/docs/public/static/joy-ui/roadmap/github-projects.png b/docs/public/static/joy-ui/roadmap/github-projects.png
new file mode 100644
index 00000000000000..d1c9f2496afe4d
Binary files /dev/null and b/docs/public/static/joy-ui/roadmap/github-projects.png differ
diff --git a/docs/public/static/joy-ui/roadmap/milestone.png b/docs/public/static/joy-ui/roadmap/milestone.png
new file mode 100644
index 00000000000000..3700e8f36e0fbc
Binary files /dev/null and b/docs/public/static/joy-ui/roadmap/milestone.png differ
diff --git a/docs/public/static/screenshots/joy-ui/getting-started/templates/framesx-web-blocks.jpg b/docs/public/static/screenshots/joy-ui/getting-started/templates/framesx-web-blocks.jpg
index 5a6eba9397e6a8..ed70f5d8b9fefb 100644
Binary files a/docs/public/static/screenshots/joy-ui/getting-started/templates/framesx-web-blocks.jpg and b/docs/public/static/screenshots/joy-ui/getting-started/templates/framesx-web-blocks.jpg differ
diff --git a/docs/public/static/screenshots/joy-ui/getting-started/templates/messages-dark.jpg b/docs/public/static/screenshots/joy-ui/getting-started/templates/messages-dark.jpg
index c93c04a0e1810e..de46235dd0cb48 100644
Binary files a/docs/public/static/screenshots/joy-ui/getting-started/templates/messages-dark.jpg and b/docs/public/static/screenshots/joy-ui/getting-started/templates/messages-dark.jpg differ
diff --git a/docs/public/static/screenshots/joy-ui/getting-started/templates/messages.jpg b/docs/public/static/screenshots/joy-ui/getting-started/templates/messages.jpg
index 15a318f7009c4a..52147608e66baa 100644
Binary files a/docs/public/static/screenshots/joy-ui/getting-started/templates/messages.jpg and b/docs/public/static/screenshots/joy-ui/getting-started/templates/messages.jpg differ
diff --git a/docs/public/static/screenshots/joy-ui/getting-started/templates/order-dashboard-dark.jpg b/docs/public/static/screenshots/joy-ui/getting-started/templates/order-dashboard-dark.jpg
index 7ee55d135f7a39..d448efa32337f9 100644
Binary files a/docs/public/static/screenshots/joy-ui/getting-started/templates/order-dashboard-dark.jpg and b/docs/public/static/screenshots/joy-ui/getting-started/templates/order-dashboard-dark.jpg differ
diff --git a/docs/public/static/screenshots/joy-ui/getting-started/templates/order-dashboard.jpg b/docs/public/static/screenshots/joy-ui/getting-started/templates/order-dashboard.jpg
index b415d287a70e68..ca647a125f2206 100644
Binary files a/docs/public/static/screenshots/joy-ui/getting-started/templates/order-dashboard.jpg and b/docs/public/static/screenshots/joy-ui/getting-started/templates/order-dashboard.jpg differ
diff --git a/docs/public/static/screenshots/joy-ui/getting-started/templates/profile-dashboard-dark.jpg b/docs/public/static/screenshots/joy-ui/getting-started/templates/profile-dashboard-dark.jpg
index 21b7aa215a9e2b..259453fce3975a 100644
Binary files a/docs/public/static/screenshots/joy-ui/getting-started/templates/profile-dashboard-dark.jpg and b/docs/public/static/screenshots/joy-ui/getting-started/templates/profile-dashboard-dark.jpg differ
diff --git a/docs/public/static/screenshots/joy-ui/getting-started/templates/profile-dashboard.jpg b/docs/public/static/screenshots/joy-ui/getting-started/templates/profile-dashboard.jpg
index 16e35ff0042c29..aaab9711b742e5 100644
Binary files a/docs/public/static/screenshots/joy-ui/getting-started/templates/profile-dashboard.jpg and b/docs/public/static/screenshots/joy-ui/getting-started/templates/profile-dashboard.jpg differ
diff --git a/docs/public/static/screenshots/joy-ui/getting-started/templates/rental-dashboard-dark.jpg b/docs/public/static/screenshots/joy-ui/getting-started/templates/rental-dashboard-dark.jpg
index 90ea71583bc2ac..bdb26ff182ba82 100644
Binary files a/docs/public/static/screenshots/joy-ui/getting-started/templates/rental-dashboard-dark.jpg and b/docs/public/static/screenshots/joy-ui/getting-started/templates/rental-dashboard-dark.jpg differ
diff --git a/docs/public/static/screenshots/joy-ui/getting-started/templates/rental-dashboard.jpg b/docs/public/static/screenshots/joy-ui/getting-started/templates/rental-dashboard.jpg
index d464c6e26cedbe..0af0573f4d9600 100644
Binary files a/docs/public/static/screenshots/joy-ui/getting-started/templates/rental-dashboard.jpg and b/docs/public/static/screenshots/joy-ui/getting-started/templates/rental-dashboard.jpg differ
diff --git a/docs/public/static/styles/prism-okaidia.css b/docs/public/static/styles/prism-okaidia.css
index 0a01bed2a94acb..f47491ed27ff12 100644
--- a/docs/public/static/styles/prism-okaidia.css
+++ b/docs/public/static/styles/prism-okaidia.css
@@ -147,7 +147,6 @@ pre[class*='language-'] {
.token.property,
.token.tag,
-.token.constant,
.token.symbol,
.token.deleted {
color: #fc929e;
diff --git a/docs/scripts/generateTemplateScreenshots.ts b/docs/scripts/generateTemplateScreenshots.ts
index 8279cda61c6ab5..e8c0b5dacade8f 100644
--- a/docs/scripts/generateTemplateScreenshots.ts
+++ b/docs/scripts/generateTemplateScreenshots.ts
@@ -2,9 +2,18 @@ import fs from 'fs/promises';
import path from 'path';
import { chromium } from 'playwright';
+/**
+ * Usage:
+ * - `yarn screenshot` to generate all screenshots
+ * - `yarn screenshot order-dashboard` to generate screenshots for `docs/pages/joy-ui/getting-started/templates/order-dashboard.tsx`
+ * - `yarn screenshot [...templates]` to generate screenshots for the templates in `docs/pages/joy-ui/getting-started/templates/*`
+ */
+
const host = process.env.DEPLOY_PREVIEW || 'http://localhost:3000';
const directory = 'docs/public/static/screenshots';
+const names = new Set(process.argv.slice(2));
+
(async () => {
// eslint-disable-next-line no-console
console.info('Host:', host);
@@ -15,7 +24,11 @@ const directory = 'docs/public/static/screenshots';
path.join(process.cwd(), 'docs/pages/joy-ui/getting-started/templates'),
);
const urls = files
- .filter((file) => !file.startsWith('index'))
+ .filter(
+ (file) =>
+ !file.startsWith('index') &&
+ (names.size === 0 || names.has(file.replace(/\.(js|tsx)$/, ''))),
+ )
.map((file) => `/joy-ui/getting-started/templates/${file.replace(/\.(js|tsx)$/, '/')}`);
try {
diff --git a/docs/src/components/about/AboutEnd.tsx b/docs/src/components/about/AboutEnd.tsx
index 77757e62292bcd..b19620765ca340 100644
--- a/docs/src/components/about/AboutEnd.tsx
+++ b/docs/src/components/about/AboutEnd.tsx
@@ -47,12 +47,11 @@ export default function AboutEnd() {
src="/static/branding/about/illustrations/team-globe-distribution-light.png"
alt="A map illustration with pins loosely positioned where team members from MUI are located."
loading="lazy"
- width="1100"
- height="690"
sx={(theme) => ({
mt: -8,
display: { xs: 'none', sm: 'block' },
- width: { sm: '100%' },
+ width: '100%',
+ aspectRatio: '231/145',
...theme.applyDarkStyles({
content: 'url(/static/branding/about/illustrations/team-globe-distribution-dark.png)',
}),
diff --git a/docs/src/components/action/InfoCard.tsx b/docs/src/components/action/InfoCard.tsx
index dfe90ba4ef635a..1f04dea9bff599 100644
--- a/docs/src/components/action/InfoCard.tsx
+++ b/docs/src/components/action/InfoCard.tsx
@@ -37,7 +37,7 @@ export function GlowingIconContainer({ icon }: GlowingIconContainerProps) {
}
interface InfoCardProps {
- icon: React.ReactNode;
+ icon?: React.ReactNode;
title: string;
description: string;
link?: string;
@@ -61,13 +61,13 @@ export default function InfoCard({ icon, title, description, link }: InfoCardPro
}),
})}
>
-
+ {icon && }
{title}
diff --git a/docs/src/components/footer/EmailSubscribe.tsx b/docs/src/components/footer/EmailSubscribe.tsx
index 7550e467eb7115..c779be1f343f72 100644
--- a/docs/src/components/footer/EmailSubscribe.tsx
+++ b/docs/src/components/footer/EmailSubscribe.tsx
@@ -82,10 +82,10 @@ export default function EmailSubscribe({ sx }: { sx?: SxProps }) {
}}
>
- Thanks! Check your email.
+ Thanks for subscribing!
- You should get a confirmation email soon. Open it up and confirm your email
- address so that we can keep you up to date.
+ Go to your email and open the confirmation email to confirm your
+ subscription.
);
}
@@ -93,14 +93,16 @@ export default function EmailSubscribe({ sx }: { sx?: SxProps }) {
diff --git a/docs/src/components/pricing/PricingTable.tsx b/docs/src/components/pricing/PricingTable.tsx
index d74a93cccd24be..dbb0106ea7a3c8 100644
--- a/docs/src/components/pricing/PricingTable.tsx
+++ b/docs/src/components/pricing/PricingTable.tsx
@@ -1,5 +1,5 @@
import * as React from 'react';
-import { alpha } from '@mui/material/styles';
+import { alpha, styled } from '@mui/material/styles';
import Box, { BoxProps } from '@mui/material/Box';
import Button from '@mui/material/Button';
import Container from '@mui/material/Container';
@@ -558,6 +558,33 @@ const rowHeaders: Record = {
),
'date-picker/simple': ,
'date-picker/range': ,
+
+ // -- charts - components --
+ 'charts/line': ,
+ 'charts/bar': ,
+ 'charts/scatter': ,
+ 'charts/pie': ,
+ 'charts/sparkline': ,
+ 'charts/gauge': ,
+ 'charts/treemap': ,
+ 'charts/heatmap': ,
+ 'charts/radar': ,
+ 'charts/funnel': ,
+ 'charts/sankey': ,
+ 'charts/gantt': ,
+ 'charts/gantt-advanced': ,
+ 'charts/candlestick': ,
+ 'charts/large-dataset': ,
+ // -- charts - features --
+ 'charts/legend': ,
+ 'charts/tooltip': ,
+ 'charts/mouse-zoom': ,
+ 'charts/export': ,
+ // -- charts - datagrid --
+ 'charts/cell-with-charts': ,
+ 'charts/filter-interaction': ,
+ 'charts/selection-interaction': ,
+
'mui-x-production': ,
'mui-x-development': ,
'mui-x-development-perpetual': (
@@ -636,6 +663,23 @@ const rowHeaders: Record = {
const yes = ;
const pending = ;
const no = ;
+const toBeDefined = (
+ svg': { color: 'primary.main', opacity: 1 },
+ fontWeight: 500,
+ pl: '16px',
+ }}
+ title="To be determined"
+ >
+ TBD
+
+
+);
const communityData: Record = {
// MUI Core
@@ -644,11 +688,13 @@ const communityData: Record = {
'Material UI': yes,
'Joy UI': yes,
// MUI X
+ // -- data grid - columns --
'data-grid/column-groups': yes,
'data-grid/column-spanning': yes,
'data-grid/column-resizing': no,
'data-grid/column-reorder': no,
'data-grid/column-pinning': no,
+ // -- data grid - rows --
'data-grid/row-height': yes,
'data-grid/row-spanning': pending,
'data-grid/row-reordering': no,
@@ -656,6 +702,7 @@ const communityData: Record = {
'data-grid/row-selection': yes,
'data-grid/row-multiselection': no,
'data-grid/row-cell-selection': no,
+ // -- data grid - filter --
'data-grid/filter-quick': yes,
'data-grid/filter-column': yes,
'data-grid/header-filters': no,
@@ -664,8 +711,10 @@ const communityData: Record = {
'data-grid/multi-column-sorting': no,
'data-grid/pagination': yes,
'data-grid/pagination-large': no,
+ // -- data grid - edit --
'data-grid/edit-row': yes,
'data-grid/edit-cell': yes,
+ // -- data grid - export --
'data-grid/file-csv': yes,
'data-grid/file-print': yes,
'data-grid/file-clipboard-copy': yes,
@@ -682,8 +731,38 @@ const communityData: Record = {
'data-grid/accessibility': yes,
'data-grid/keyboard-nav': yes,
'data-grid/localization': yes,
+
+ // -- picker --
'date-picker/simple': yes,
'date-picker/range': no,
+
+ // -- charts - components --
+ 'charts/line': yes,
+ 'charts/bar': yes,
+ 'charts/scatter': yes,
+ 'charts/pie': yes,
+ 'charts/sparkline': yes,
+ 'charts/gauge': pending,
+ 'charts/treemap': pending,
+ 'charts/heatmap': pending,
+ 'charts/radar': pending,
+ 'charts/funnel': no,
+ 'charts/sankey': no,
+ 'charts/gantt': no,
+ 'charts/gantt-advanced': no,
+ 'charts/candlestick': no,
+ 'charts/large-dataset': no,
+ // -- charts - features --
+ 'charts/legend': yes,
+ 'charts/tooltip': yes,
+ 'charts/mouse-zoom': no,
+ 'charts/export': no,
+ // -- charts - datagrid --
+ 'charts/cell-with-charts': pending,
+ 'charts/filter-interaction': no,
+ 'charts/selection-interaction': no,
+
+ // -- general --
'mui-x-production': yes,
'mui-x-updates': yes,
'mui-x-development': yes,
@@ -706,11 +785,13 @@ const proData: Record = {
'Material UI': yes,
'Joy UI': yes,
// MUI X
+ // -- data grid - columns --
'data-grid/column-groups': yes,
'data-grid/column-spanning': yes,
'data-grid/column-resizing': yes,
'data-grid/column-reorder': yes,
'data-grid/column-pinning': yes,
+ // -- data grid - rows --
'data-grid/row-height': yes,
'data-grid/row-spanning': pending,
'data-grid/row-reordering': yes,
@@ -718,6 +799,7 @@ const proData: Record = {
'data-grid/row-selection': yes,
'data-grid/row-multiselection': yes,
'data-grid/row-cell-selection': no,
+ // -- data grid - filter --
'data-grid/filter-quick': yes,
'data-grid/filter-column': yes,
'data-grid/header-filters': yes,
@@ -726,8 +808,10 @@ const proData: Record = {
'data-grid/multi-column-sorting': yes,
'data-grid/pagination': yes,
'data-grid/pagination-large': yes,
+ // -- data grid - edit --
'data-grid/edit-row': yes,
'data-grid/edit-cell': yes,
+ // -- data grid - export --
'data-grid/file-csv': yes,
'data-grid/file-print': yes,
'data-grid/file-clipboard-copy': yes,
@@ -746,6 +830,34 @@ const proData: Record = {
'data-grid/localization': yes,
'date-picker/simple': yes,
'date-picker/range': yes,
+
+ // -- charts - components --
+ 'charts/line': yes,
+ 'charts/bar': yes,
+ 'charts/scatter': yes,
+ 'charts/pie': yes,
+ 'charts/sparkline': yes,
+ 'charts/gauge': pending,
+ 'charts/treemap': pending,
+ 'charts/heatmap': pending,
+ 'charts/radar': pending,
+ 'charts/funnel': pending,
+ 'charts/sankey': pending,
+ 'charts/gantt': pending,
+ 'charts/gantt-advanced': no,
+ 'charts/candlestick': no,
+ 'charts/large-dataset': no,
+ // -- charts - features --
+ 'charts/legend': yes,
+ 'charts/tooltip': yes,
+ 'charts/mouse-zoom': pending,
+ 'charts/export': pending,
+ // -- charts - datagrid --
+ 'charts/cell-with-charts': pending,
+ 'charts/filter-interaction': pending,
+ 'charts/selection-interaction': no,
+
+ // -- general --
'mui-x-production': yes,
'mui-x-development': ,
'mui-x-development-perpetual': ,
@@ -773,11 +885,13 @@ const premiumData: Record = {
'Material UI': yes,
'Joy UI': yes,
// MUI X
+ // -- data grid - columns --
'data-grid/column-groups': yes,
'data-grid/column-spanning': yes,
'data-grid/column-resizing': yes,
'data-grid/column-reorder': yes,
'data-grid/column-pinning': yes,
+ // -- data grid - rows --
'data-grid/row-height': yes,
'data-grid/row-spanning': pending,
'data-grid/row-reordering': yes,
@@ -785,6 +899,7 @@ const premiumData: Record = {
'data-grid/row-selection': yes,
'data-grid/row-multiselection': yes,
'data-grid/row-cell-selection': yes,
+ // -- data grid - filter --
'data-grid/filter-quick': yes,
'data-grid/filter-column': yes,
'data-grid/header-filters': yes,
@@ -793,8 +908,10 @@ const premiumData: Record = {
'data-grid/multi-column-sorting': yes,
'data-grid/pagination': yes,
'data-grid/pagination-large': yes,
+ // -- data grid - edit --
'data-grid/edit-row': yes,
'data-grid/edit-cell': yes,
+ // -- data grid - export --
'data-grid/file-csv': yes,
'data-grid/file-print': yes,
'data-grid/file-clipboard-copy': yes,
@@ -813,6 +930,34 @@ const premiumData: Record = {
'data-grid/localization': yes,
'date-picker/simple': yes,
'date-picker/range': yes,
+
+ // -- charts - components --
+ 'charts/line': yes,
+ 'charts/bar': yes,
+ 'charts/scatter': yes,
+ 'charts/pie': yes,
+ 'charts/sparkline': yes,
+ 'charts/gauge': pending,
+ 'charts/treemap': pending,
+ 'charts/heatmap': pending,
+ 'charts/radar': pending,
+ 'charts/funnel': pending,
+ 'charts/sankey': pending,
+ 'charts/gantt': pending,
+ 'charts/gantt-advanced': toBeDefined,
+ 'charts/candlestick': toBeDefined,
+ 'charts/large-dataset': toBeDefined,
+ // -- charts - features --
+ 'charts/legend': yes,
+ 'charts/tooltip': yes,
+ 'charts/mouse-zoom': pending,
+ 'charts/export': pending,
+ // -- charts - datagrid --
+ 'charts/cell-with-charts': pending,
+ 'charts/filter-interaction': pending,
+ 'charts/selection-interaction': pending,
+
+ // -- general --
'mui-x-production': yes,
'mui-x-development': ,
'mui-x-development-perpetual': ,
@@ -1030,6 +1175,22 @@ function PricingTableBuyPremium() {
);
}
+const StyledCollapse = styled(Collapse, {
+ name: 'MuiSlider',
+ slot: 'Track',
+})(({ theme }) => {
+ return {
+ position: 'relative',
+ marginLeft: theme.spacing(1.5),
+ borderLeftWidth: '2px',
+ borderLeftStyle: 'solid',
+ borderColor: theme.palette.grey[100],
+ ...theme.applyDarkStyles({
+ borderColor: theme.palette.primaryDark[700],
+ }),
+ };
+});
+
export default function PricingTable({
columnHeaderHidden,
plans = ['community', 'pro', 'premium'],
@@ -1040,10 +1201,12 @@ export default function PricingTable({
}) {
const router = useRouter();
const [dataGridCollapsed, setDataGridCollapsed] = React.useState(false);
+ const [chartsCollapsed, setChartsCollapsed] = React.useState(false);
React.useEffect(() => {
if (router.query['expand-path'] === 'all') {
setDataGridCollapsed(true);
+ setChartsCollapsed(true);
}
}, [router.query]);
@@ -1060,16 +1223,24 @@ export default function PricingTable({
ml: '-14px',
'&>div:first-of-type': {
ml: '14px',
+ width: 'calc(100% - 14px)', // avoid overflow on hover transparent background
},
};
- const unfoldMore = (
+ const dataGridUnfoldMore = (
);
+ const chartsUnfoldMore = (
+
+ );
+
const renderRow = (key: string) => renderMasterRow(key, gridSx, plans);
const renderNestedRow = (key: string) => renderMasterRow(key, nestedGridSx, plans);
@@ -1133,11 +1304,13 @@ export default function PricingTable({
}}
>
|
- {unfoldMore} |
+ {dataGridUnfoldMore} |
- {unfoldMore}
+ {dataGridUnfoldMore}
+ |
+
+ {dataGridUnfoldMore}
|
- {unfoldMore} |
- ({
- position: 'relative',
- ml: 1.5,
- borderLeftWidth: '2px',
- borderLeftStyle: 'solid',
- borderColor: 'grey.100',
- ...theme.applyDarkStyles({
- borderColor: 'primaryDark.700',
- }),
- })}
- >
+
Column features
{renderNestedRow('data-grid/column-groups')}
{divider}
@@ -1280,12 +1440,118 @@ export default function PricingTable({
{renderNestedRow('data-grid/keyboard-nav')}
{divider}
{renderNestedRow('data-grid/localization')}
-
+
{divider}
{renderRow('date-picker/simple')}
{divider}
{renderRow('date-picker/range')}
{divider}
+
+ |
+ {chartsUnfoldMore} |
+
+ {chartsUnfoldMore}
+ |
+ {chartsUnfoldMore} |
+
+
+
+ Components
+ {renderNestedRow('charts/line')}
+ {divider}
+ {renderNestedRow('charts/bar')}
+ {divider}
+ {renderNestedRow('charts/scatter')}
+ {divider}
+ {renderNestedRow('charts/pie')}
+ {divider}
+ {renderNestedRow('charts/sparkline')}
+ {divider}
+ {renderNestedRow('charts/gauge')}
+ {divider}
+ {renderNestedRow('charts/treemap')}
+ {divider}
+ {renderNestedRow('charts/heatmap')}
+ {divider}
+ {renderNestedRow('charts/radar')}
+ {divider}
+ {renderNestedRow('charts/funnel')}
+ {divider}
+ {renderNestedRow('charts/sankey')}
+ {divider}
+ {renderNestedRow('charts/gantt')}
+ {divider}
+ {renderNestedRow('charts/gantt-advanced')}
+ {divider}
+ {renderNestedRow('charts/candlestick')}
+ {divider}
+ {renderNestedRow('charts/large-dataset')}
+ {divider}
+ Interactions
+ {renderNestedRow('charts/legend')}
+ {divider}
+ {renderNestedRow('charts/tooltip')}
+ {divider}
+ {renderNestedRow('charts/mouse-zoom')}
+ {divider}
+ {renderNestedRow('charts/export')}
+ {divider}
+ Data Grid Integration
+ {renderNestedRow('charts/cell-with-charts')}
+ {divider}
+ {renderNestedRow('charts/filter-interaction')}
+ {divider}
+ {renderNestedRow('charts/selection-interaction')}
+
+ {divider}
{renderRow('mui-x-production')}
{divider}
diff --git a/docs/src/components/productCore/CoreProducts.tsx b/docs/src/components/productCore/CoreProducts.tsx
index 46b551a737e937..1623ee2c0f85b1 100644
--- a/docs/src/components/productCore/CoreProducts.tsx
+++ b/docs/src/components/productCore/CoreProducts.tsx
@@ -1,37 +1,33 @@
import * as React from 'react';
-import { alpha } from '@mui/material/styles';
-// import Box from '@mui/material/Box';
-import Paper from '@mui/material/Paper';
-import Typography from '@mui/material/Typography';
import Grid from '@mui/material/Grid';
import Section from 'docs/src/layouts/Section';
-import Link from 'docs/src/modules/components/Link';
+import InfoCard from 'docs/src/components/action/InfoCard';
// Note: All of the commented code will be put back in once logos for each Core product are done.
const content = [
{
- // logo:
+ // icon:
title: 'Material UI',
description: "An open-source React component library that implements Google's Material Design.",
link: '/material-ui/',
},
{
- // logo:
+ // icon:
title: 'Joy UI',
description:
"An easy to customize open-source React component library that implements MUI's own in-house design principles by default.",
link: '/joy-ui/getting-started/',
},
{
- // logo:
+ // icon:
title: 'Base UI',
description:
- 'A library of unstyled React UI components and hooks. With Base UI, you gain complete control over your app\'s CSS and accessibility features.',
+ "A library of unstyled React UI components and hooks. With Base UI, you gain complete control over your app's CSS and accessibility features.",
link: '/base-ui/',
},
{
- // logo:
+ // icon:
title: 'MUI System',
description: 'A set of CSS utilities to help you build custom designs more efficiently.',
link: '/system/getting-started/',
@@ -44,76 +40,7 @@ export default function CoreProducts() {
{content.map(({ title, description, link }) => (
- ({
- p: 2.5,
- height: '100%',
- position: 'relative',
- borderRadius: '12px',
- border: '1px solid',
- borderColor: 'grey.100',
- background: `linear-gradient(to top right, ${alpha(
- theme.palette.primary[50],
- 0.3,
- )} 40%, ${alpha(theme.palette.grey[50], 0.2)} 100%)`,
- '&:hover': {
- borderColor: 'primary.500',
- boxShadow:
- '0px 1px 6px 0px rgba(194, 224, 255, 1), 0px 2px 30px 0px rgba(234, 237, 241, 0.3) inset',
- },
- ...theme.applyDarkStyles({
- bgcolor: 'primaryDark.900',
- borderColor: 'primaryDark.700',
- background: `linear-gradient(to top right, ${alpha(
- theme.palette.primary[900],
- 0.1,
- )} 40%, ${alpha(theme.palette.primaryDark[800], 0.2)} 100%)`,
- '&:hover': {
- boxShadow: '0px 1px 6px #0059B3, inset 0px 2px 30px rgba(0, 0, 0, 0.1)',
- },
- }),
- })}
- >
- {/* ({
- width: 40,
- height: 40,
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center',
- borderRadius: 1,
- border: '1px solid',
- borderColor: 'primary.200',
- bgcolor: 'primary.50',
- boxShadow:
- '0px 1px 6px 0px rgba(194, 224, 255, 1), 0px 2px 30px 0px rgba(234, 237, 241, 0.3) inset',
- ...theme.applyDarkStyles({
- borderColor: 'primary.400',
- bgcolor: 'primary.900',
- boxShadow:
- '0px 1px 6px 0px rgba(0, 89, 178, 1), 0px 2px 30px 0px rgba(0, 0, 0, 0.25) inset',
- }),
- })}
- >
- {logo}
- */}
-
- {title}
-
-
- {description}
-
-
+
))}
diff --git a/docs/src/layouts/AppFooter.tsx b/docs/src/layouts/AppFooter.tsx
index e38e3156cb56a9..b6d0acf7e4b312 100644
--- a/docs/src/layouts/AppFooter.tsx
+++ b/docs/src/layouts/AppFooter.tsx
@@ -143,10 +143,12 @@ export default function AppFooter(props: AppFooterProps) {
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {stackOverflowUrl ? (
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {stackOverflowUrl ? (
-
-
-
- ) : null}
-
-
+ ) : null}
+
);
diff --git a/docs/src/modules/brandingTheme.ts b/docs/src/modules/brandingTheme.ts
index cf71e165bd13cf..25048e08e49254 100644
--- a/docs/src/modules/brandingTheme.ts
+++ b/docs/src/modules/brandingTheme.ts
@@ -479,13 +479,24 @@ export function getThemedComponents(): ThemeOptions {
'&:hover > span': { transform: 'translateX(2px)' },
}),
...(ownerState.size === 'small' && {
- padding: theme.spacing(0.5, 1),
+ padding: theme.spacing('6px', 1),
fontFamily: theme.typography.fontFamily,
fontSize: defaultTheme.typography.pxToRem(13),
fontWeight: theme.typography.fontWeightSemiBold,
borderRadius: 8,
- '& > span': { transition: '0.2s', marginLeft: 4 },
- '&:hover > span': { transform: 'translateX(2px)' },
+ '& .MuiButton-startIcon': {
+ transition: '0.15s',
+ marginRight: 4,
+ marginLeft: -1,
+ },
+ '& .MuiButton-endIcon': {
+ transition: '0.15s',
+ marginLeft: 4,
+ },
+ '&:hover': {
+ '& .MuiButton-startIcon': { transform: 'translateX(-2px)' },
+ '& .MuiButton-endIcon': { transform: 'translateX(2px)' },
+ },
}),
...(ownerState.variant === 'outlined' &&
ownerState.color === 'secondary' && {
@@ -740,6 +751,39 @@ export function getThemedComponents(): ThemeOptions {
}),
],
},
+ {
+ props: { color: 'info' },
+ style: ({ theme }) => [
+ {
+ height: 34,
+ width: 34,
+ border: `1px solid`,
+ borderColor: (theme.vars || theme).palette.grey[200],
+ color: (theme.vars || theme).palette.grey[600],
+ borderRadius: theme.shape.borderRadius,
+ boxShadow: `inset 0 1px 2px ${
+ (theme.vars || theme).palette.grey[50]
+ }, 0 1px 0.5px ${alpha(theme.palette.grey[100], 0.6)}`,
+ '&:hover': {
+ color: (theme.vars || theme).palette.primary.main,
+ borderColor: (theme.vars || theme).palette.grey[300],
+ background: (theme.vars || theme).palette.grey[50],
+ },
+ },
+ theme.applyDarkStyles({
+ borderColor: (theme.vars || theme).palette.primaryDark[700],
+ color: (theme.vars || theme).palette.grey[400],
+ boxShadow: `inset 0 1px 1px ${
+ (theme.vars || theme).palette.primaryDark[900]
+ }, 0 1px 0.5px ${(theme.vars || theme).palette.common.black}`,
+ '&:hover': {
+ color: (theme.vars || theme).palette.primary[400],
+ borderColor: (theme.vars || theme).palette.primaryDark[600],
+ background: alpha(theme.palette.primaryDark[700], 0.4),
+ },
+ }),
+ ],
+ },
],
},
MuiMenu: {
diff --git a/docs/src/modules/components/AppLayoutDocs.js b/docs/src/modules/components/AppLayoutDocs.js
index a669bfae76168d..2e565a52726078 100644
--- a/docs/src/modules/components/AppLayoutDocs.js
+++ b/docs/src/modules/components/AppLayoutDocs.js
@@ -8,7 +8,6 @@ import NoSsr from '@mui/material/NoSsr';
import { pathnameToLanguage } from 'docs/src/modules/utils/helpers';
import Head from 'docs/src/modules/components/Head';
import AppFrame from 'docs/src/modules/components/AppFrame';
-import EditPage from 'docs/src/modules/components/EditPage';
import AppContainer from 'docs/src/modules/components/AppContainer';
import AppTableOfContents from 'docs/src/modules/components/AppTableOfContents';
import AdManager from 'docs/src/modules/components/AdManager';
@@ -87,15 +86,6 @@ const StyledAppContainer = styled(AppContainer, {
};
});
-const ActionsDiv = styled('div')(({ theme }) => ({
- display: 'flex',
- marginTop: -10,
- marginBottom: -15,
- [theme.breakpoints.up('lg')]: {
- justifyContent: 'flex-end',
- },
-}));
-
export default function AppLayoutDocs(props) {
const router = useRouter();
const {
@@ -158,12 +148,9 @@ export default function AppLayoutDocs(props) {
See https://jakearchibald.com/2014/dont-use-flexbox-for-page-layout/ for more details.
*/}
-
-
-
{children}
-
+
{disableToc ? null : }
diff --git a/docs/src/modules/components/AppLayoutDocsFooter.js b/docs/src/modules/components/AppLayoutDocsFooter.js
index ba555574e4733c..66f7c8bd054a39 100644
--- a/docs/src/modules/components/AppLayoutDocsFooter.js
+++ b/docs/src/modules/components/AppLayoutDocsFooter.js
@@ -1,56 +1,53 @@
/* eslint-disable no-restricted-globals */
+/* eslint-disable material-ui/no-hardcoded-labels */
import * as React from 'react';
import PropTypes from 'prop-types';
import { styled, useTheme } from '@mui/material/styles';
+// Components
import DialogActions from '@mui/material/DialogActions';
import TextField from '@mui/material/TextField';
-import Box from '@mui/material/Box';
import Collapse from '@mui/material/Collapse';
import Button from '@mui/material/Button';
import Alert from '@mui/material/Alert';
import Divider from '@mui/material/Divider';
-import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
import Tooltip from '@mui/material/Tooltip';
+import Stack from '@mui/material/Stack';
+import Snackbar from '@mui/material/Snackbar';
import IconButton from '@mui/material/IconButton';
+// Icons
import ThumbUpAltRoundedIcon from '@mui/icons-material/ThumbUpAltRounded';
import ThumbDownAltRoundedIcon from '@mui/icons-material/ThumbDownAltRounded';
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
import PanToolRoundedIcon from '@mui/icons-material/PanToolRounded';
-import Snackbar from '@mui/material/Snackbar';
-import { getCookie, pageToTitleI18n } from 'docs/src/modules/utils/helpers';
-import PageContext from 'docs/src/modules/components/PageContext';
+import TwitterIcon from '@mui/icons-material/Twitter';
+import LinkedInIcon from '@mui/icons-material/LinkedIn';
+import YouTubeIcon from '@mui/icons-material/YouTube';
+import RssFeedIcon from '@mui/icons-material/RssFeed';
+import ArrowOutwardRoundedIcon from '@mui/icons-material/ArrowOutwardRounded';
+import DiscordIcon from 'docs/src/icons/DiscordIcon';
+// Other imports
+import ROUTES from 'docs/src/route';
import Link from 'docs/src/modules/components/Link';
+import PageContext from 'docs/src/modules/components/PageContext';
+import EditPage from 'docs/src/modules/components/EditPage';
import { useUserLanguage, useTranslate } from 'docs/src/modules/utils/i18n';
+import { getCookie, pageToTitleI18n } from 'docs/src/modules/utils/helpers';
-const PaginationDiv = styled('div')(({ theme }) => {
+const FooterLink = styled(Typography)(({ theme }) => {
return {
- margin: theme.spacing(3, 0, 4),
+ ...theme.typography.body2,
display: 'flex',
- justifyContent: 'space-between',
- [theme.breakpoints.down('sm')]: {
- flexWrap: 'wrap',
- },
- };
-});
-
-const PageLinkButton = styled(Button)(({ theme }) => ({
- fontWeight: theme.typography.fontWeightMedium,
- ...theme.applyDarkStyles({
- color: (theme.vars || theme).palette.primary[300],
- }),
-}));
-
-const FeedbackGrid = styled(Grid)(({ theme }) => {
- return {
- width: 'auto',
- color: theme.palette.text.secondary,
- [theme.breakpoints.down('sm')]: {
- order: 3,
- marginTop: 40,
- width: '100%',
- },
+ alignItems: 'center',
+ gap: 4,
+ fontWeight: (theme.vars || theme).typography.fontWeightSemiBold,
+ color: (theme.vars || theme).palette.primary.main,
+ '& > svg': { transition: '0.2s' },
+ '&:hover > svg': { transform: 'translateX(2px)' },
+ ...theme.applyDarkStyles({
+ color: (theme.vars || theme).palette.primary[300],
+ }),
};
});
@@ -250,7 +247,7 @@ const EMPTY_SECTION = { hash: '', text: '' };
const SPEACIAL_FEEDBACK_HASH = [{ hash: 'new-docs-api-feedback', text: 'New API content design' }];
export default function AppLayoutDocsFooter(props) {
- const { tableOfContents = [] } = props;
+ const { tableOfContents = [], location } = props;
const theme = useTheme();
const t = useTranslate();
@@ -384,85 +381,41 @@ export default function AppLayoutDocsFooter(props) {
return (
-
- {hidePagePagination ? null : (
-
-
-
- {prevPage !== null ? (
- }
- >
- {pageToTitleI18n(prevPage, t)}
-
- ) : (
-
- )}
-
-
- {t('feedbackMessage')}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {nextPage !== null ? (
- }
- >
- {pageToTitleI18n(nextPage, t)}
-
- ) : null}
-
-
- )}
+
+
+
+
+
+ {t('feedbackMessage')}
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
{commentedSection.text ? (
) : (
-
+
{rating === 1 ? t('feedbackMessageUp') : t('feedbackMessageDown')}
)}
@@ -527,15 +481,132 @@ export default function AppLayoutDocsFooter(props) {
)}
-
-
-
+
-
+
+ {hidePagePagination ? null : (
+
+ {prevPage !== null ? (
+ }
+ >
+ {pageToTitleI18n(prevPage, t)}
+
+ ) : (
+
+ )}
+ {nextPage !== null ? (
+ }
+ >
+ {pageToTitleI18n(nextPage, t)}
+
+ ) : null}
+
+ )}
+
+
+
+
+
+ Blog
+
+
+
+ •
+
+
+
+ Store
+
+
+
+ •
+
+
+
+ Careers
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- {pages.reduce(
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
- (items, page) => reduceChildRoutes({ items, page, ...params }),
- [],
- )}
-
+ {pages.reduce((items, page) => reduceChildRoutes({ items, page, ...params }), [])}
);
}
diff --git a/docs/src/modules/components/Demo.js b/docs/src/modules/components/Demo.js
index d54ca1890bdd7c..35666047b34494 100644
--- a/docs/src/modules/components/Demo.js
+++ b/docs/src/modules/components/Demo.js
@@ -198,7 +198,6 @@ const DemoRootMaterial = styled('div', {
shouldForwardProp: (prop) => prop !== 'hideToolbar' && prop !== 'bg',
})(({ theme, hideToolbar, bg }) => ({
position: 'relative',
- outline: 0,
margin: 'auto',
display: 'flex',
justifyContent: 'center',
@@ -241,7 +240,7 @@ const DemoRootMaterial = styled('div', {
padding: theme.spacing(20, 8),
border: `1px solid`,
borderColor: (theme.vars || theme).palette.divider,
- overflow: 'hidden',
+ overflow: 'auto',
backgroundColor: alpha(theme.palette.primary[50], 0.5),
backgroundClip: 'padding-box',
backgroundImage: `radial-gradient(at 51% 52%, ${alpha(
@@ -276,7 +275,6 @@ const DemoRootJoy = joyStyled('div', {
shouldForwardProp: (prop) => prop !== 'hideToolbar' && prop !== 'bg',
})(({ theme, hideToolbar, bg }) => ({
position: 'relative',
- outline: 0,
margin: 'auto',
display: 'flex',
justifyContent: 'center',
diff --git a/docs/src/modules/components/DemoSandbox.js b/docs/src/modules/components/DemoSandbox.js
index b3ad8bb8187e95..78aff5ce50a01e 100644
--- a/docs/src/modules/components/DemoSandbox.js
+++ b/docs/src/modules/components/DemoSandbox.js
@@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
import { create } from 'jss';
import { prefixer } from 'stylis';
import rtlPlugin from 'stylis-plugin-rtl';
-import rtlPluginSc from 'stylis-plugin-rtl-sc';
import createCache from '@emotion/cache';
import { CacheProvider } from '@emotion/react';
import { StyleSheetManager } from 'styled-components';
@@ -66,7 +65,7 @@ function FramedDemo(props) {
diff --git a/docs/src/modules/components/DiamondSponsors.js b/docs/src/modules/components/DiamondSponsors.js
index eb7f6e61a303cc..761ddae3b0cc2c 100644
--- a/docs/src/modules/components/DiamondSponsors.js
+++ b/docs/src/modules/components/DiamondSponsors.js
@@ -1,12 +1,45 @@
import * as React from 'react';
-import { alpha } from '@mui/material/styles';
+import { styled, alpha } from '@mui/material/styles';
import Box from '@mui/material/Box';
import Stack from '@mui/material/Stack';
import Button from '@mui/material/Button';
+import Typography from '@mui/material/Typography';
import DiamondOutlinedIcon from '@mui/icons-material/DiamondOutlined';
import { useTranslate } from 'docs/src/modules/utils/i18n';
import Link from 'docs/src/modules/components/Link';
+const StyledAnchor = styled('a')(({ theme }) => ({
+ boxSizing: 'border-box', // TODO have CssBaseline in the Next.js layout
+ width: '100%',
+ height: 45,
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: 12,
+ border: '1px solid',
+ borderColor: (theme.vars || theme).palette.divider,
+ transition: theme.transitions.create(['color', 'border-color']),
+ boxShadow: `inset 0 1px 1px ${(theme.vars || theme).palette.grey[50]}, 0 1px 2px ${alpha(
+ theme.palette.grey[100],
+ 0.6,
+ )}`,
+ '&:hover': {
+ backgroundColor: (theme.vars || theme).palette.grey[50],
+ },
+ '& img': {
+ display: 'inline-block',
+ },
+ ...theme.applyDarkStyles({
+ boxShadow: `inset 0 1px 1px ${(theme.vars || theme).palette.primaryDark[900]}, 0 1px 0.5px ${
+ (theme.vars || theme).palette.common.black
+ }`,
+ '&:hover': {
+ backgroundColor: (theme.vars || theme).palette.primaryDark[800],
+ borderColor: (theme.vars || theme).palette.primaryDark[600],
+ },
+ }),
+}));
+
export default function DiamondSponsors() {
const t = useTranslate();
@@ -27,64 +60,21 @@ export default function DiamondSponsors() {
target="_blank"
rel="noopener nofollow"
size="small"
- startIcon={}
- sx={(theme) => ({
+ startIcon={}
+ sx={{
width: 'fit-content',
- fontSize: theme.typography.pxToRem(12.5),
- fontWeight: theme.typography.fontWeightSemiBold,
- color: (theme.vars || theme).palette.primary[600],
+ fontSize: (theme) => theme.typography.pxToRem(12.5),
'& svg': {
- width: 14,
- height: 14,
+ marginRight: 0.5,
+ width: 16,
+ height: 16,
},
- ...theme.applyDarkStyles({
- color: (theme.vars || theme).palette.primary[300],
- }),
- })}
+ }}
>
{t('diamondSponsors')}
- ({
- '& a': {
- width: '100%',
- height: 45,
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'center',
- border: '1px solid',
- borderColor: 'divider',
- borderRadius: '12px',
- boxSizing: 'border-box', // TODO have CssBaseline in the Next.js layout
- transition: theme.transitions.create(['color', 'border-color']),
- boxShadow: `inset 0 1px 2px ${
- (theme.vars || theme).palette.grey[50]
- }, 0 1px 0.5px ${alpha(theme.palette.grey[100], 0.6)}`,
- '&:hover': {
- backgroundColor: 'grey.50',
- },
- '& img': {
- display: 'inline-block',
- },
- },
- }),
- (theme) =>
- theme.applyDarkStyles({
- '& a': {
- boxShadow: `inset 0 1px 1px ${
- (theme.vars || theme).palette.primaryDark[900]
- }, 0 1px 0.5px ${(theme.vars || theme).palette.common.black}`,
- '&:hover': {
- backgroundColor: (theme.vars || theme).palette.primaryDark[800],
- borderColor: (theme.vars || theme).palette.primaryDark[600],
- },
- },
- }),
- ]}
- >
-
+
-
-
+
-
+
({
+ width: '100%',
+ p: 1.5,
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: 1,
+ border: '1px dashed',
+ transition: theme.transitions.create(['color', 'border-color', 'background-color']),
+ backgroundColor: alpha(theme.palette.primary[50], 0.5),
+ borderColor: (theme.vars || theme).palette.primary[200],
+ boxShadow: `inset 0 1px 1px ${
+ (theme.vars || theme).palette.grey[50]
+ }, 0 1px 2px ${alpha(theme.palette.primary[100], 0.8)}`,
+ '&:hover': {
+ backgroundColor: alpha(theme.palette.primary[100], 0.5),
+ borderColor: (theme.vars || theme).palette.primary[300],
+ },
+ ...theme.applyDarkStyles({
+ backgroundColor: alpha(theme.palette.primary[400], 0.05),
+ borderColor: alpha(theme.palette.primary[300], 0.3),
+ boxShadow: `inset 0 1px 1px ${
+ (theme.vars || theme).palette.primaryDark[800]
+ }, 0 1px 0.5px ${(theme.vars || theme).palette.common.black}`,
+ '&:hover': {
+ backgroundColor: alpha(theme.palette.primary[400], 0.1),
+ borderColor: (theme.vars || theme).palette.primary[400],
+ },
+ }),
+ })}
>
- +1
+
+ {/* eslint-disable-next-line material-ui/no-hardcoded-labels */}
+ {'Become a diamond sponsor!'}
+
+
+ {/* eslint-disable-next-line material-ui/no-hardcoded-labels */}
+ {'One spot left'}
+
diff --git a/docs/src/modules/components/EditPage.js b/docs/src/modules/components/EditPage.js
index c75f0a30802613..76cb9ef8a16669 100644
--- a/docs/src/modules/components/EditPage.js
+++ b/docs/src/modules/components/EditPage.js
@@ -17,6 +17,9 @@ export default function EditPage(props) {
return (
}
href={
userLanguage === 'en'
? `${process.env.SOURCE_CODE_REPO}/edit/${process.env.SOURCE_GITHUB_BRANCH}${sourceLocation}`
@@ -27,25 +30,10 @@ export default function EditPage(props) {
}
target="_blank"
rel="noopener nofollow"
- size="small"
- startIcon={}
data-ga-event-category={userLanguage === 'en' ? undefined : 'l10n'}
data-ga-event-action={userLanguage === 'en' ? undefined : 'edit-button'}
data-ga-event-label={userLanguage === 'en' ? undefined : userLanguage}
- sx={(theme) => ({
- ml: { md: -1, lg: 0 },
- mb: 2,
- fontWeight: 500,
- fontSize: theme.typography.pxToRem(12.5),
- color: 'primary.600',
- '& svg': {
- width: 14,
- height: 14,
- },
- ...theme.applyDarkStyles({
- color: 'primary.300',
- }),
- })}
+ sx={{ '&:hover > span': { transform: 'translateX(-2px)' } }}
>
{t('editPage')}
diff --git a/docs/src/modules/components/MarkdownElement.js b/docs/src/modules/components/MarkdownElement.js
index 4eb21fa2c71244..dbc067bfcefb6d 100644
--- a/docs/src/modules/components/MarkdownElement.js
+++ b/docs/src/modules/components/MarkdownElement.js
@@ -384,7 +384,7 @@ const Root = styled('div')(
},
},
},
- '& a, & a code': {
+ '& a, & a code, & strong': {
// Style taken from the Link component
color: `var(--muidocs-palette-primary-600, ${lightTheme.palette.primary[600]})`,
textDecoration: 'underline',
@@ -674,7 +674,7 @@ const Root = styled('div')(
},
},
},
- '& a, & a code': {
+ '& a, & a code, & strong': {
color: `var(--muidocs-palette-primary-300, ${darkTheme.palette.primary[300]})`,
},
'& a code': {
diff --git a/docs/src/modules/sandbox/CodeSandbox.test.js b/docs/src/modules/sandbox/CodeSandbox.test.js
index 816b3f2a6cb0b8..d150faf6ffd009 100644
--- a/docs/src/modules/sandbox/CodeSandbox.test.js
+++ b/docs/src/modules/sandbox/CodeSandbox.test.js
@@ -67,7 +67,7 @@ describe('CodeSandbox', () => {