diff --git a/.circleci/config.yml b/.circleci/config.yml index 8e6930a6c46ed5..5c1aaf708fee2a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -348,7 +348,7 @@ jobs: <<: *defaults resource_class: 'medium+' docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -378,7 +378,7 @@ jobs: test_e2e: <<: *defaults docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -397,7 +397,7 @@ jobs: test_e2e_website: <<: *defaults docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -412,7 +412,7 @@ jobs: test_profile: <<: *defaults docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -439,7 +439,7 @@ jobs: test_regressions: <<: *defaults docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -493,7 +493,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/next-webpack4/ docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -517,7 +517,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/next-webpack5/ docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -541,7 +541,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/create-react-app/ docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -565,7 +565,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/snowpack/ docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -589,7 +589,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/vite/ docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -613,7 +613,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/esbuild/ docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -641,7 +641,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/gatsby/ docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -743,7 +743,7 @@ jobs: test_benchmark: <<: *defaults docker: - - image: mcr.microsoft.com/playwright:v1.29.1-focal + - image: mcr.microsoft.com/playwright:v1.29.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: diff --git a/.github/ISSUE_TEMPLATE/3.rfc.yml b/.github/ISSUE_TEMPLATE/3.rfc.yml index c80ade9784051e..bedf972a271001 100644 --- a/.github/ISSUE_TEMPLATE/3.rfc.yml +++ b/.github/ISSUE_TEMPLATE/3.rfc.yml @@ -1,7 +1,7 @@ name: RFC šŸ’¬ description: Request for comments for your proposal. title: '[RFC] ' -labels: ['RFC'] +labels: ['status: needs triage', 'RFC'] body: - type: markdown attributes: diff --git a/.gitignore b/.gitignore index 2281b26c1fdb3f..5da201e38b5634 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ /docs/.env.local /docs/export /docs/pages/playground/ +/docs/public/feed/ /examples/**/.cache /packages/mui-codemod/lib /packages/mui-envinfo/*.tgz @@ -32,3 +33,4 @@ build node_modules package-lock.json size-snapshot.json +docs/public/static/blog/feed/* diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a950241cbd2c4..425746e0d6a3c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,185 @@ # [Versions](https://mui.com/versions/) +## 5.11.6 + + + +_Jan 23, 2023_ + +A big thanks to the 13 contributors who made this release possible. Here are some highlights āœØ: + +- @ZeeshanTamboli improved the logic for handling the value label in the `SliderUnstyled` (#35805) +- many other šŸ› bug fixes and šŸ“š documentation improvements + +### `@mui/material@5.11.6` + +- ​[Box] Fix usage of not supported features in TypeScript 3.5 (#35877) @mnajdova +- ​[Button] Fix border color for secondary disabled button (#35866) @SaidMarar +- ​[SwipeableDrawer] Add callback to customise touchstart ignore for swipeable drawer (#30759) @tech-meppem + +### `@mui/base@5.0.0-alpha.115` + +#### Breaking changes + +- ​[SliderUnstyled] Improved logic for displaying the value label (#35805) @ZeeshanTamboli + + - The `valueLabelDisplay` prop is removed from `SliderUnstyled`. The prop was not working as intended in `SliderUnstyled` (See #35398). You can instead provide a `valueLabel` slot with the `slots` prop API to show the value label: + + ```diff + - + + + ``` + + The following demo shows how to show a value label when it is hovered over with the thumb: https://mui.com/base/react-slider/#value-label + + - The following classes are removed from `sliderUnstyledClasses` since they are not needed for the value label: + + ```diff + - valueLabel + - valueLabelOpen + - valueLabelCircle + - valueLabelLabel + ``` + + In the custom value label component, you can define your own classNames and target them with CSS. + + - The `SliderValueLabelUnstyled` component is removed from SliderUnstyled. You should provide your own custom component for the value label. + + - To avoid using `React.cloneElement` API in value label, the component hierarchy structure of the value label is changed.Ā The value label is now inside the Thumb slot - `Thumb` -> `Input`, `ValueLabel`. + +#### Changes + +- ​[InputUnstyled] Fix externally provided `inputRef` is ignored (#35807) @sai6855 + +### `@mui/joy@5.0.0-alpha.64` + +- ​[Avatar][joy] Remove `imgProps` prop and add Codemod script for migration (#35859) @hbjORbj + +### Docs + +- ​[blog] Date and time pickers revamped (#35486) @joserodolfofreitas +- ​[docs] Fix incorrect breakpoint use (#34948) @rosita-dmello +- ​[docs] Replace react-virtualized with react-virtuoso in Table (#35700) @petyosi +- ​[docs] Fix account menu demo not closing with keyboard. (#35870) @mj12albert +- ​[docs] Fix typos in the docs of Joy UI (#35876) @HeVictor +- ​[docs] Fix wording in `Color` page (#35873) @oliv37 + +### Core + +- ​[core] Fix release changelog to handle commits with empty author field (#35921) @mnajdova +- ​[core] Revert `docs-utilities` migration to TypeScript and fix type (#35881) @ZeeshanTamboli +- ​[core] Migrate internal `docs-utilities` package to TypeScript (#35846) @ZeeshanTamboli +- ​[website] Designer don't spend their time writing code @oliviertassinari +- ​[website] Emphasis the technical background need for this role @oliviertassinari + +All contributors of this release in alphabetical order: @HeVictor, @hbjORbj, @joserodolfofreitas, @mj12albert, @mnajdova, @oliv37, @oliviertassinari, @petyosi, @rosita-dmello, @sai6855, @SaidMarar, @tech-meppem, @ZeeshanTamboli + +## 5.11.5 + + + +_Jan 17, 2023_ + +A big thanks to the 17 contributors who made this release possible. +This release was mostly about šŸ› bug fixes and šŸ“š documentation improvements. + +### `@mui/material@5.11.5` + +- [Material UI] Custom channel token should suppress the warning (#35804) @siriwatknp +- [Autocomplete] Fix value type when `strictNullChecks` is `false` (#35367) @fenghan34 +- [Slider] Replace `SliderUnstyled` with `useSlider` hook (#35770) @ZeeshanTamboli +- [l10n] Add Belarusian translation (#35742) @volhalink + +### `@mui/system@5.11.5` + +- [system] Improve the `createBox` types (#35532) @mnajdova + +### `@mui/codemod@5.11.5` + +- Add `joy-text-field-to-input` codemod (#35462) @hbjORbj + +### `@mui/base@5.0.0-alpha.114` + +- [base] Fix typos (#35802) @nnmax +- [Slider] Convert code to TypeScript (#35445) @sai6855 + +### `@mui/joy@5.0.0-alpha.63` + +- [Tabs][joy] Don't apply `:hover, :active` styles when `selected` (#35750) @sai6855 +- Remove `TextField` component and replace its usage in docs with `FormControl`/`FormLabel`/`Input` (#35462) @hbjORbj +- [TextField] Throw error with migration message (#35845) @siriwatknp +- Miscellaneous fixes (#35847) @siriwatknp + +### Docs + +- [docs] Improve pickers lab migration stressing `mui-x` usage (#35740) @LukasTy +- [docs] Fix incorrectly named AccessibleTable demo component (#35832) @HeVictor +- [docs] Clarify where to find docs for MUI Base components in Material UI (#35799) @samuelsycamore +- [docs] Fix typos (#35814) @alexfauquette +- [docs] Revise and expand the Joy UI Card page (#35745) @samuelsycamore +- [docs] Fix navigation layout shift (#35679) @oliviertassinari +- [docs] Fix typo in the Composition page (#35774) @msoyka +- [docs][joy] Update Customization section code example to use the correct API (#35765) @pupudu +- [docs][joy] Fix grammar in `Typography` docs (#35796) @atrefonas +- [examples] Remove `next-env.d.ts` from Next.js examples (#35772) @Juneezee + +### Core + +- [website] Improve pricing page (#35767) @oliviertassinari +- [website] Add Greg in about page (#35816) @oliviertassinari +- [website] Update the Accessibility Engineer role (#35751) @oliviertassinari +- [website] Add docs for MUI for Figma @oliviertassinari + +All contributors of this release in alphabetical order: @alexfauquette, @atrefonas, @fenghan34, @hbjORbj, @HeVictor, @Juneezee, @LukasTy, @mnajdova, @msoyka, @nnmax, @oliviertassinari, @pupudu, @sai6855, @samuelsycamore, @siriwatknp, @volhalink, @ZeeshanTamboli + +## 5.11.4 + + + +_Jan 9, 2023_ + +A big thanks to the 14 contributors who made this release possible. +This release was mostly about šŸ› bug fixes and šŸ“š documentation improvements. + +### `@mui/material@5.11.4` + +- [Autocomplete] Add index to renderOption's AutocompleteRenderOptionState (#35578) @CowDotDev +- [Autocomplete] Fix grammar in console.error in `useAutocomplete` (#35723) @hamirmahal +- [Modal] Fix can't override Backdrop Props using new Slots API (#35140) @ZeeshanTamboli +- [Select] Revert "Update `renderValue` prop's TypeScript type (#34177)" (#35733) @michaldudak +- [Tabs] Throw error only if individual `Tab` is hidden, not the whole `Tabs` (#34026) @Ryczko +- [TextField] Improve WCAG 2.4.7 with error={true} (#35687) @oliviertassinari +- [Tooltip] Remove `data-foo` attribute (#35736) @koolskateguy89 + +### `@mui/joy@5.0.0-alpha.62` + +- [Autocomplete][joy] Specify `type` attribute for popup indicator (#35648) @hbjORbj +- [Joy] Miscellaneous improvements (#35769) @siriwatknp +- [Joy] Improve `onKeyDown` event handler for demo (#35642) @hbjORbj + +### `@mui/base@5.0.0-alpha.113` + +- [Portal][base] Convert code to TypeScript (#35657) @sai6855 + +### Docs + +- [docs] Revise and expand Joy UI Button doc (#35737) @samuelsycamore +- [docs] Document the workaround for crashing a translated page (#35720) @michaldudak +- [docs] Fix API page for `MenuItem` to list all valid props (#35561) @mnajdova +- [docs] Fix ad exception in Joy UI (#35685) @oliviertassinari +- [docs] Fix content wider than screen regression @oliviertassinari +- [examples] Add `Vite.js with TypeScript` example (#35683) @miha53cevic + +### Core + +- [core] Close 2022 developer survey @oliviertassinari +- [core] Fix the product license reference name (#35703) @oliviertassinari +- [core] Use TypeScript AST instead of TTP for component doc building (#35379) @flaviendelangle +- [test] Always use & for nesting styles (#35702) @oliviertassinari +- [website] Improve Lead Designer role description (#35684) @oliviertassinari + +All contributors of this release in alphabetical order: @CowDotDev, @flaviendelangle, @hamirmahal, @hbjORbj, @koolskateguy89, @michaldudak, @miha53cevic, @mnajdova, @oliviertassinari, @Ryczko, @sai6855, @samuelsycamore, @siriwatknp, @ZeeshanTamboli + ## 5.11.3 diff --git a/benchmark/package.json b/benchmark/package.json index 8c765f0d3000cb..bcaf2c9c0a47cf 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -11,16 +11,16 @@ "server:system": "cd ../ && cross-env NODE_ENV=production BABEL_ENV=benchmark babel-node benchmark/server/scenarios/system.js --inspect=0.0.0.0:9229 --extensions \".tsx,.ts,.js\"" }, "dependencies": { - "@chakra-ui/system": "^2.3.7", + "@chakra-ui/system": "^2.3.8", "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", "@mdx-js/react": "^2.2.1", - "@mui/material": "^5.11.3", + "@mui/material": "^5.11.6", "@mui/styles": "^5.11.2", - "@mui/system": "^5.11.2", + "@mui/system": "^5.11.5", "@styled-system/css": "^5.1.5", "benchmark": "^2.1.4", - "playwright": "^1.29.1", + "playwright": "^1.29.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-is": "^18.2.0", diff --git a/docs/data/base/components/button/button.md b/docs/data/base/components/button/button.md index d6d3e92bd6c59b..4d74420b2217d2 100644 --- a/docs/data/base/components/button/button.md +++ b/docs/data/base/components/button/button.md @@ -10,14 +10,14 @@ waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/button/

Buttons let users take actions and make choices with a single tap.

-{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} - ## Introduction The Unstyled Button component replaces the native HTML ` + + + + ); +} diff --git a/docs/data/joy/components/button/BasicButtons.tsx b/docs/data/joy/components/button/BasicButtons.tsx new file mode 100644 index 00000000000000..15c152d5d8029e --- /dev/null +++ b/docs/data/joy/components/button/BasicButtons.tsx @@ -0,0 +1,13 @@ +import * as React from 'react'; +import Button from '@mui/joy/Button'; +import Box from '@mui/joy/Box'; + +export default function BasicButtons() { + return ( + + + + + + ); +} diff --git a/docs/data/joy/components/button/BasicButtons.tsx.preview b/docs/data/joy/components/button/BasicButtons.tsx.preview new file mode 100644 index 00000000000000..4d33dc1940fa3f --- /dev/null +++ b/docs/data/joy/components/button/BasicButtons.tsx.preview @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/docs/data/joy/components/button/ButtonDisabled.js b/docs/data/joy/components/button/ButtonDisabled.js index a9a47de487c7a2..e048a8cbf14f45 100644 --- a/docs/data/joy/components/button/ButtonDisabled.js +++ b/docs/data/joy/components/button/ButtonDisabled.js @@ -2,7 +2,7 @@ import * as React from 'react'; import Box from '@mui/joy/Box'; import Button from '@mui/joy/Button'; -export default function ButtonVariants() { +export default function DisabledButtons() { return ( - - + + + ); } diff --git a/docs/data/joy/components/button/ButtonLoading.tsx b/docs/data/joy/components/button/ButtonLoading.tsx index 231860dc44b56c..cac8452c703c21 100644 --- a/docs/data/joy/components/button/ButtonLoading.tsx +++ b/docs/data/joy/components/button/ButtonLoading.tsx @@ -1,17 +1,22 @@ import * as React from 'react'; -import Stack from '@mui/joy/Stack'; -import SendIcon from '@mui/icons-material/Send'; +import Box from '@mui/joy/Box'; import Button from '@mui/joy/Button'; -export default function ButtonLoading() { +export default function LoadingButtons() { return ( - - - - + + + ); } diff --git a/docs/data/joy/components/button/ButtonLoading.tsx.preview b/docs/data/joy/components/button/ButtonLoading.tsx.preview index ca37d5ae89ed8c..7b260fd7a643ab 100644 --- a/docs/data/joy/components/button/ButtonLoading.tsx.preview +++ b/docs/data/joy/components/button/ButtonLoading.tsx.preview @@ -1,6 +1,12 @@ - - + + \ No newline at end of file diff --git a/docs/data/joy/components/button/ButtonLoadingIndicator.js b/docs/data/joy/components/button/ButtonLoadingIndicator.js new file mode 100644 index 00000000000000..231860dc44b56c --- /dev/null +++ b/docs/data/joy/components/button/ButtonLoadingIndicator.js @@ -0,0 +1,17 @@ +import * as React from 'react'; +import Stack from '@mui/joy/Stack'; +import SendIcon from '@mui/icons-material/Send'; +import Button from '@mui/joy/Button'; + +export default function ButtonLoading() { + return ( + + + + + ); +} diff --git a/docs/data/joy/components/button/ButtonLoadingIndicator.tsx b/docs/data/joy/components/button/ButtonLoadingIndicator.tsx new file mode 100644 index 00000000000000..231860dc44b56c --- /dev/null +++ b/docs/data/joy/components/button/ButtonLoadingIndicator.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; +import Stack from '@mui/joy/Stack'; +import SendIcon from '@mui/icons-material/Send'; +import Button from '@mui/joy/Button'; + +export default function ButtonLoading() { + return ( + + + + + ); +} diff --git a/docs/data/joy/components/button/ButtonLoadingIndicator.tsx.preview b/docs/data/joy/components/button/ButtonLoadingIndicator.tsx.preview new file mode 100644 index 00000000000000..ca37d5ae89ed8c --- /dev/null +++ b/docs/data/joy/components/button/ButtonLoadingIndicator.tsx.preview @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/docs/data/joy/components/button/ButtonsSimple.js b/docs/data/joy/components/button/ButtonsSimple.js new file mode 100644 index 00000000000000..88636b8fb0e9ee --- /dev/null +++ b/docs/data/joy/components/button/ButtonsSimple.js @@ -0,0 +1,12 @@ +import * as React from 'react'; +import Button from '@mui/joy/Button'; +import Box from '@mui/joy/Box'; + +export default function UnstyledButtonsSimple() { + return ( + + + + + ); +} diff --git a/docs/data/joy/components/button/ButtonsSimple.tsx.preview b/docs/data/joy/components/button/ButtonsSimple.tsx.preview new file mode 100644 index 00000000000000..b7b5add52ab6c2 --- /dev/null +++ b/docs/data/joy/components/button/ButtonsSimple.tsx.preview @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/docs/data/joy/components/button/button.md b/docs/data/joy/components/button/button.md index 36a8db10e4d12c..af047dabd94c79 100644 --- a/docs/data/joy/components/button/button.md +++ b/docs/data/joy/components/button/button.md @@ -8,120 +8,147 @@ unstyled: /base/react-button/ # Button -

Buttons allow users to take actions, and make choices, with a single tap.

+

Buttons let users take actions and make choices with a single tap.

## Introduction Buttons communicate actions that users can take. +The Joy UI Button component replaces the native HTML `; -} ``` +The Joy UI Button behaves similar to the native HTML ` +``` diff --git a/docs/data/joy/components/card/CardCovers.js b/docs/data/joy/components/card/CardCovers.js deleted file mode 100644 index ab94de7b7f5cfe..00000000000000 --- a/docs/data/joy/components/card/CardCovers.js +++ /dev/null @@ -1,56 +0,0 @@ -import * as React from 'react'; -import Card from '@mui/joy/Card'; -import CardCover from '@mui/joy/CardCover'; -import CardContent from '@mui/joy/CardContent'; -import Typography from '@mui/joy/Typography'; - -export default function CardCovers() { - return ( - - -
- - 3 - -
-
- -
- - 2 - -
-
- -
- - 1 - -
-
- - - Content - - -
- ); -} diff --git a/docs/data/joy/components/card/CardCovers.tsx b/docs/data/joy/components/card/CardCovers.tsx deleted file mode 100644 index ab94de7b7f5cfe..00000000000000 --- a/docs/data/joy/components/card/CardCovers.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import * as React from 'react'; -import Card from '@mui/joy/Card'; -import CardCover from '@mui/joy/CardCover'; -import CardContent from '@mui/joy/CardContent'; -import Typography from '@mui/joy/Typography'; - -export default function CardCovers() { - return ( - - -
- - 3 - -
-
- -
- - 2 - -
-
- -
- - 1 - -
-
- - - Content - - -
- ); -} diff --git a/docs/data/joy/components/card/CardLayers3d.js b/docs/data/joy/components/card/CardLayers3d.js new file mode 100644 index 00000000000000..c98afdcf507f35 --- /dev/null +++ b/docs/data/joy/components/card/CardLayers3d.js @@ -0,0 +1,70 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import Card from '@mui/joy/Card'; +import CardCover from '@mui/joy/CardCover'; +import CardContent from '@mui/joy/CardContent'; +import Typography from '@mui/joy/Typography'; + +export default function CardLayers3d() { + return ( + div, & > div > div': { + transition: 'inherit', + }, + '&:hover': { + '& > div': { + transform: 'rotateY(30deg)', + '& > div:nth-child(2)': { + transform: 'scaleY(0.9) translate3d(20px, 30px, 40px)', + }, + '& > div:nth-child(3)': { + transform: 'translate3d(45px, 50px, 40px)', + }, + }, + }, + }} + > + + + Card + + + + Card Cover + + + + + Card Content + + + + + ); +} diff --git a/docs/data/joy/components/card/CardLayers3d.tsx b/docs/data/joy/components/card/CardLayers3d.tsx new file mode 100644 index 00000000000000..c98afdcf507f35 --- /dev/null +++ b/docs/data/joy/components/card/CardLayers3d.tsx @@ -0,0 +1,70 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import Card from '@mui/joy/Card'; +import CardCover from '@mui/joy/CardCover'; +import CardContent from '@mui/joy/CardContent'; +import Typography from '@mui/joy/Typography'; + +export default function CardLayers3d() { + return ( + div, & > div > div': { + transition: 'inherit', + }, + '&:hover': { + '& > div': { + transform: 'rotateY(30deg)', + '& > div:nth-child(2)': { + transform: 'scaleY(0.9) translate3d(20px, 30px, 40px)', + }, + '& > div:nth-child(3)': { + transform: 'translate3d(45px, 50px, 40px)', + }, + }, + }, + }} + > + + + Card + + + + Card Cover + + + + + Card Content + + + + + ); +} diff --git a/docs/data/joy/components/card/CardVariables.js b/docs/data/joy/components/card/CardVariables.js index 3ffc5e8d59501a..558c2df561d582 100644 --- a/docs/data/joy/components/card/CardVariables.js +++ b/docs/data/joy/components/card/CardVariables.js @@ -7,7 +7,10 @@ import CardCover from '@mui/joy/CardCover'; import CardContent from '@mui/joy/CardContent'; import CardOverflow from '@mui/joy/CardOverflow'; import Link from '@mui/joy/Link'; -import TextField from '@mui/joy/TextField'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import FormHelperText from '@mui/joy/FormHelperText'; +import Input from '@mui/joy/Input'; import Typography from '@mui/joy/Typography'; import BrandingProvider from 'docs/src/BrandingProvider'; import HighlightedCode from 'docs/src/modules/components/HighlightedCode'; @@ -142,37 +145,44 @@ export default function CardVariables() { CSS variables {vars.map((data) => ( - px} - type={data.type} - helperText={ - data.defaultValue ? `Default as ${data.defaultValue}` : undefined - } - onChange={(event) => { - const { value } = event.target; - setSx((prevSx) => { - if (!value) { - const newSx = { ...prevSx }; - // @ts-ignore - delete newSx[data.var]; - return newSx; - } - return { - ...prevSx, - [data.var]: `${value}px`, - }; - }); - }} - sx={{ - maxWidth: 160, - '& .JoyInput-root': { '--Input-paddingInline': '0.5rem' }, - }} - /> + + + {data.var} + + px} + type={data.type} + sx={{ + maxWidth: 160, + '& .JoyInput-root': { '--Input-paddingInline': '0.5rem' }, + }} + onChange={(event) => { + const { value } = event.target; + setSx((prevSx) => { + if (!value) { + const newSx = { ...prevSx }; + // @ts-ignore + delete newSx[data.var]; + return newSx; + } + return { + ...prevSx, + [data.var]: `${value}px`, + }; + }); + }} + /> + {data.defaultValue ? ( + {`Default as ${data.defaultValue}`} + ) : null} + ))} diff --git a/docs/data/joy/components/card/InteractiveCard.js b/docs/data/joy/components/card/InteractiveCard.js index a09621a1326f00..8d99b98c3a6922 100644 --- a/docs/data/joy/components/card/InteractiveCard.js +++ b/docs/data/joy/components/card/InteractiveCard.js @@ -9,7 +9,7 @@ export default function InteractiveCard() { return ( + + Cards contain content and actions about a single subject.

+

A card is a generic container for grouping related UI elements and content.

## Introduction -Cards are most frequently used for easy to scan, relevant, and actionable information. -Joy UI provides four Card-related components: +The Joy UI Card component includes several complementary utility components to handle various use cases: -- [`Card`](#basic-usage): a container to control the content direction. -- [`CardOverflow`](#overflow): a handy component that takes care of stretching the content to fill all edges of the card. -- [`CardCover`](#back-cover): a container for displaying background images within the card, also used to create gradient layers. -- [`CardContent`](#back-cover): a wrapper that brings content to the front when used with `CardCover`. +- [Card](#basics): a surface-level container for grouping related components. +- [Card Overflow](#overflow): a supplemental wrapper that expands a Card's contents to fill all edges. +- [Card Cover](#card-layers): an optional container for displaying background images and gradient layers behind the Card Content. +- [Card Content](#card-layers): an optional wrapper that brings content to the front (commonly but not always used with the Card Cover). -## Component - -After [installation](/joy-ui/getting-started/installation/), you can start building with this component using the following basic elements: +## Basics ```jsx import Card from '@mui/joy/Card'; -import Typography from '@mui/joy/Typography'; - -export default function MyApp() { - return ( - - Hello world! - - ); -} ``` -### Basic usage - -`Card` is a surface-level component that can house multiple others. -The most common components you'd use with it are `Typography`, `AspectRatio`, and `Button`. +Card is a surface-level container for grouping related components. +The demo below shows a typical Card that groups together Typography, Aspect Ratio, and Button components, among others: {{"demo": "BasicCard.js" }} -### Overflow +## Customization + +### Expand to fill -To have content spanning from edge to edge of the card, wrap it with the `CardOverflow` component. -It automatically takes care of the top and bottom edges if rendered as the first or last child of the parent card. +```jsx +import CardOverflow from '@mui/joy/CardOverflow'; +``` + +By default, the Card component adds padding around the outer edges of its contents. +To eliminate this white space, add the Card Overflow component inside the Card as a wrapper around the content to be expanded. + +Note that Card Overflow only works when it's the first and/or last child of the parent Card. +In the demo below, the top and bottom sections are expanded to fill the edges: {{"demo": "OverflowCard.js" }} -### Back cover +### Card layers -The `CardCover` component is responsible for housing the content that covers the whole card. -Think of card covers as a background layer that stay behind the `CardContent`. +```jsx +import CardCover from '@mui/joy/CardCover'; +import CardContent from '@mui/joy/CardContent'; +``` -{{"demo": "CardCovers.js" }} +The default Card provides a single flat surface for other components to sit on top of. +Use the Card Cover and Card Content components to expose multiple layers between a Card and the UI elements on its surface. -### Media +Card Cover makes it possible to add images, videos, and color and gradient overlays underneath the Card Content. +Hover your mouse on the demo below to see how the layers are stacked: -Use a plain image or a video element inside the `CardCover` to display media. -It uses [`object-fit: cover`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) on the image as a default value. +{{"demo": "CardLayers3d.js" }} -{{"demo": "MediaCover.js" }} +#### Images and videos + +Use an image or a video element inside the Card Cover to display media. +The component uses [`object-fit: cover`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) to fill the whole Card by default. -### Gradient overlay +{{"demo": "MediaCover.js" }} -To create a gradient overlay, frequently seen when a colorful image is used as background, insert an additional `CardCover` component. +#### Gradient overlay -:::warning -Make sure to darken the gradient overlay up to have enough contrast between the background image and the text content. -::: +To create a gradient overlayā€”frequently seen when a bright image is used as a backgroundā€”insert an additional Card Cover component between the image layer and the content layer. +You can add any number of Card Covers to create more sophisticated stacked layers this way. {{"demo": "GradientCover.js" }} -### Row +### Horizontal alignment -To show a horizontal card, use the `row` prop. -The `CardOverflow` will adapt based on its position. +Card contents are arranged in a column by default. +For horizontal alignment, add the `row` prop to the Card. +If present, the [Card Overflow](#expand-to-fill) component will adapt accordingly. {{"demo": "RowCard.js" }} ### Actions -#### Multiple actions +Cards often include actions that users can take, like proceeding to a new page or section of the app. +There may be individual (discrete) actions _within_ a given card, or _the entire card itself_ may trigger an action when clicked or tapped. -By default, whenever you have additional action elements such as links and buttons, they stay on top of the whole interactive area. -In some cases, you might have to manually control each element's `z-index`. +The following sections explain how to approach each of these scenarios. -:::success -Use the CSS pseudo-class [`:focus-within`](https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-within) to style the card when any of its children are focused. -::: +#### Discrete actions + +By default, action elements like links and buttons sit above the surface-level interactive area of the Card. +In some cases, you might have to adjust the z-index to bring these elements to the frontā€”for instance, the Favorite Icon Button in the demo below needs a higher z-index in order to sit on top of its Aspect Ratio sibling: {{"demo": "MultipleInteractionCard.js" }} -#### Whole card area +:::success +You can use the CSS pseudo-class [`:focus-within`](https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-within) to apply styles to the Card when any of its children receive focus. +::: -To make the entire card area clickable, wrap the card's title with the `Link` component. -Then, add the `overlay` prop to expand it. +#### Whole Card actions -By doing that, you ensure good keyboard navigation support given that the `focus-visible` styles also apply to the entire card. -Learn more about best accessibility practices with cards in the [Inclusive Component's documentation](https://inclusive-components.design/cards/). +To make the entire Card clickable, add a [Link](/joy-ui/react-link/) component to the title (or some other important text content) inside the Card. +Then add the `overlay` prop to the Link to spread it across the Card as a whole. -{{"demo": "InteractiveCard.js" }} +:::info +This approach helps to ensure proper keyboard navigation support by applying `focus-visible` styles to the Card itself. +Learn more about this and other best practices for accessible cards in the [Inclusive Components blog](https://inclusive-components.design/cards/). +::: -## CSS variables +{{"demo": "InteractiveCard.js" }} -Play around with all the CSS variables available in the component to see how the design changes. +## CSS variable playground -You can use those to customize the component on both the `sx` prop and the theme. +Play around with the CSS variables available to the Card component to see how the design changes. +You can use these to customize the component with both the `sx` prop and the theme. :::success -If you want to adjust a card's padding or border-radius, it's preferable to do it using the variables below instead of using CSS properties directly. -That's because the variables will also be used to calculate a proper radius for the card's children. +If you need to adjust a Card's padding or border radius, it's preferable to do so using these variables rather than plain CSS properties. +This is because the variables are also used to calculate a proper radius for the Card's children, to prevent a mismatch between their relative proportions. ::: {{"demo": "CardVariables.js" , "hideToolbar": true}} ## Common examples -### Container responsive - -This demo uses a similar technique to [the flexbox holy albatross](https://heydonworks.com/article/the-flexbox-holy-albatross/) to stack the elements when the container's width is below a specified number. +### Instagram post -{{"demo": "ContainerResponsive.js" }} +{{"demo": "InstagramPost.js" }} ### Dribbble shot {{"demo": "DribbbleShot.js" }} -### Instagram post +### Resizable container -{{"demo": "InstagramPost.js" }} +This demo uses a technique similar to Heydon Pickering's [Flexbox Holy Albatross](https://heydonworks.com/article/the-flexbox-holy-albatross/) to create a stretchable Card that switches between vertical and horizontal alignment when its width passes a specified thresholdā€”without using media queries to define breakpoints. +Try resizing it by clicking and dragging the bottom-right corner to see how it behaves. + +{{"demo": "ContainerResponsive.js" }} + +## Anatomy + +The Card component and all of its supplementary components are composed of a single root `
`: + +```html +
+
+ +
+
+ +
+
+ +
+
+``` + +:::info +Keep in mind that [Card Overflow](#expand-to-fill) must be the first or last child of a Card in order to functionā€”accordingly, it will have a `data-first-child` or `data-last-child` attribute appended to its `
`. +::: diff --git a/docs/data/joy/components/checkbox/CheckboxColors.js b/docs/data/joy/components/checkbox/CheckboxColors.js new file mode 100644 index 00000000000000..177b0c852c3456 --- /dev/null +++ b/docs/data/joy/components/checkbox/CheckboxColors.js @@ -0,0 +1,16 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import Checkbox from '@mui/joy/Checkbox'; + +export default function CheckboxColors() { + return ( + + + + + + + + + ); +} diff --git a/docs/data/joy/components/checkbox/CheckboxSizes.js b/docs/data/joy/components/checkbox/CheckboxSizes.js new file mode 100644 index 00000000000000..e360080185de86 --- /dev/null +++ b/docs/data/joy/components/checkbox/CheckboxSizes.js @@ -0,0 +1,13 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import Checkbox from '@mui/joy/Checkbox'; + +export default function CheckboxSizes() { + return ( + + + + + + ); +} diff --git a/docs/data/joy/components/checkbox/CheckboxUsage.js b/docs/data/joy/components/checkbox/CheckboxUsage.js index b0606fcd9b2fb8..2bf7a268f8b256 100644 --- a/docs/data/joy/components/checkbox/CheckboxUsage.js +++ b/docs/data/joy/components/checkbox/CheckboxUsage.js @@ -10,13 +10,13 @@ export default function CheckboxUsage() { { propName: 'variant', knob: 'select', - defaultValue: 'soft', + defaultValue: 'outlined', options: ['plain', 'outlined', 'soft', 'solid'], }, { propName: 'color', knob: 'color', - defaultValue: 'primary', + defaultValue: 'neutral', }, { propName: 'size', diff --git a/docs/data/joy/components/checkbox/CheckboxVariants.js b/docs/data/joy/components/checkbox/CheckboxVariants.js new file mode 100644 index 00000000000000..e40fd2be7d8f95 --- /dev/null +++ b/docs/data/joy/components/checkbox/CheckboxVariants.js @@ -0,0 +1,14 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import Checkbox from '@mui/joy/Checkbox'; + +export default function CheckboxVariants() { + return ( + + + + + + + ); +} diff --git a/docs/data/joy/components/checkbox/ExampleButtonCheckbox.js b/docs/data/joy/components/checkbox/ExampleButtonCheckbox.js index 14f23cbf27cdb0..27c8be8747a045 100644 --- a/docs/data/joy/components/checkbox/ExampleButtonCheckbox.js +++ b/docs/data/joy/components/checkbox/ExampleButtonCheckbox.js @@ -14,7 +14,7 @@ export default function ExampleButtonCheckbox() { variant="outlined" aria-label="Screens" role="group" - row + orientation="horizontal" sx={{ bgcolor: 'background.body', flexGrow: 0, @@ -46,7 +46,7 @@ export default function ExampleButtonCheckbox() { label={item} checked={value.includes(item)} color="neutral" - variant="plain" + variant={value.includes(item) ? 'outlined' : 'plain'} onChange={(event) => { if (event.target.checked) { setValue((val) => [...val, item]); @@ -57,11 +57,8 @@ export default function ExampleButtonCheckbox() { slotProps={{ action: ({ checked }) => ({ sx: { - bgcolor: checked ? 'background.surface' : 'transparent', + bgcolor: checked ? 'background.level1' : 'transparent', boxShadow: checked ? 'sm' : 'none', - '&:hover': { - bgcolor: checked ? 'background.surface' : 'transparent', - }, }, }), }} diff --git a/docs/data/joy/components/checkbox/ExampleChoiceChipCheckbox.js b/docs/data/joy/components/checkbox/ExampleChoiceChipCheckbox.js index f450650981482e..c06fb1477d409c 100644 --- a/docs/data/joy/components/checkbox/ExampleChoiceChipCheckbox.js +++ b/docs/data/joy/components/checkbox/ExampleChoiceChipCheckbox.js @@ -19,7 +19,7 @@ export default function ExampleChoiceChipCheckbox() { .${checkboxClasses.checkbox}`]: { position: 'relative' } }} // to demonstrate the focus outline diff --git a/docs/data/joy/components/checkbox/GroupCheckboxes.js b/docs/data/joy/components/checkbox/GroupCheckboxes.js index 44e4cf55aebafc..78f6825dcccee8 100644 --- a/docs/data/joy/components/checkbox/GroupCheckboxes.js +++ b/docs/data/joy/components/checkbox/GroupCheckboxes.js @@ -9,7 +9,7 @@ export default function GroupCheckboxes() { return ( - Sandwich Condiments + Sandwich Dressings diff --git a/docs/data/joy/components/checkbox/HelperTextCheckbox.js b/docs/data/joy/components/checkbox/HelperTextCheckbox.js index 1c28445ce8794b..722058486b87b2 100644 --- a/docs/data/joy/components/checkbox/HelperTextCheckbox.js +++ b/docs/data/joy/components/checkbox/HelperTextCheckbox.js @@ -7,7 +7,7 @@ export default function HelperTextCheckbox() { return ( - A description for the checkbox. + A description for the Checkbox. ); } diff --git a/docs/data/joy/components/checkbox/HoverCheckbox.js b/docs/data/joy/components/checkbox/HoverCheckbox.js index 5baeb23e7876c4..a576b8ba0bc7a3 100644 --- a/docs/data/joy/components/checkbox/HoverCheckbox.js +++ b/docs/data/joy/components/checkbox/HoverCheckbox.js @@ -6,7 +6,7 @@ export default function HoverCheckbox() { return ( } - label="Label" + label="My unchecked icon appears on hover" slotProps={{ root: ({ checked, focusVisible }) => ({ sx: !checked diff --git a/docs/data/joy/components/checkbox/IconlessCheckbox.js b/docs/data/joy/components/checkbox/IconlessCheckbox.js index 8cecae5c240ffa..f25e8fe335f173 100644 --- a/docs/data/joy/components/checkbox/IconlessCheckbox.js +++ b/docs/data/joy/components/checkbox/IconlessCheckbox.js @@ -13,7 +13,7 @@ export default function IconlessCheckbox() { {[ - 'Perpperoni', + 'Pepperoni', 'Cheese', 'Olives', 'Tomatoes', diff --git a/docs/data/joy/components/checkbox/IconsCheckbox.js b/docs/data/joy/components/checkbox/IconsCheckbox.js index 46807620574bd3..b2c4f4e073f57c 100644 --- a/docs/data/joy/components/checkbox/IconsCheckbox.js +++ b/docs/data/joy/components/checkbox/IconsCheckbox.js @@ -3,5 +3,7 @@ import Checkbox from '@mui/joy/Checkbox'; import Close from '@mui/icons-material/Close'; export default function IconsCheckbox() { - return } label="Label" />; + return ( + } label="I have an icon when unchecked" /> + ); } diff --git a/docs/data/joy/components/checkbox/OverlayCheckbox.js b/docs/data/joy/components/checkbox/OverlayCheckbox.js index f1b142d3bdf2d7..f4d0413f57f485 100644 --- a/docs/data/joy/components/checkbox/OverlayCheckbox.js +++ b/docs/data/joy/components/checkbox/OverlayCheckbox.js @@ -15,11 +15,11 @@ export default function OverlayCheckbox() { }} > - + Checkboxes allow the user to select one or more items from a set.

+

Checkboxes give users binary choices when presented with multiple options in a series.

## Introduction -The `Checkbox` component is the one to be used when you want to allow users to select multiple options. -For toggling between on and off or single option selection, consider using a switch or radio button, respectively. +Checkboxes provide users with a graphical representation of a binary choice (yes or no, on or off). +They are most commonly presented in a series, giving the user multiple choices to make. -{{"demo": "CheckboxUsage.js", "hideToolbar": true, "bg": "gradient"}} +The Joy UI Checkbox component replaces the native HTML `` element, and offers expanded options for styling and accessibility. -:::info -To learn how to add more variants or sizes to the component, check out the [Themed components](/joy-ui/customization/themed-components/) page. -::: +:::success +When should you use checkboxes rather than switches or radio buttons? -{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} +- Use a switch to provide the user with **a single binary choice**ā€”checkboxes are preferable when you need to give the user multiple binary choices. +- Use radio buttons to give the user **mutually exclusive options**ā€”checkboxes are preferable when you need to let the user select one, some, all, or none from a series of options. + ::: -## Component +{{"demo": "CheckboxUsage.js", "hideToolbar": true, "bg": "gradient"}} -After [installation](/joy-ui/getting-started/installation/), you can start building with this component using the following basic elements: +{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} + +## Basics ```jsx -import Box from '@mui/joy/Box'; import Checkbox from '@mui/joy/Checkbox'; - -export default function MyApp() { - return ( - - - - ); -} ``` -### Checked - -When unchecked, the checkbox component uses the `outlined` variant. -When checked, the variant changes to `solid`. +The basic Checkbox component is a single input set to the unchecked state. +Use the `label` prop to provide text, and add `defaultChecked` when the input should be checked by default. {{"demo": "BasicCheckbox.js"}} -### Icon +## Customization + +### Variants + +The Checkbox component supports Joy UI's four [global variants](/joy-ui/main-features/global-variants/): `solid`, `soft`, `outlined`, and `plain`. By default, when unchecked, the Checkbox is set to `outlined`; +when checked, the variant changes to `solid`. + +Adding the `variant` prop to your Checkbox overrides this default behavior. Try checking and unchecking the Checkboxes in the demo below to see the differences: + +{{"demo": "CheckboxVariants.js"}} + +:::info +To learn how to add your own variants, check out [Themed componentsā€”Extend variants](/joy-ui/customization/themed-components/#extend-variants). +Note that you lose the global variants when you add custom variants. +::: + +### Sizes + +The Checkbox component comes in three sizes: `sm`, `md` (default), and `lg`. + +{{"demo": "CheckboxSizes.js"}} + +:::info +To learn how to add custom sizes to the component, check out [Themed componentsā€”Extend sizes](/joy-ui/customization/themed-components/#extend-sizes). +::: -`Checkbox`, by default, comes without an unchecked component. -To add an icon to both uncheck and checked states, use the `uncheckedIcon` and `checkedIcon` props. +### Colors + +Every palette included in the theme is available via the `color` prop. + +{{"demo": "CheckboxColors.js"}} + +### Icons + +By default, the Checkbox component is empty when unchecked. +Use the `uncheckedIcon` prop to add a custom icon for the unchecked state. +You can also use `checkedIcon` to customize the checked state. {{"demo": "IconsCheckbox.js"}} #### Appear on hover -Target the icon by using the `svg` selector and then use `opacity` to show the unchecked icon when hovering the checkbox. +You can use the `uncheckedIcon` as a "preview" of the checked state by making it appear when the user hovers over the empty Checkbox. + +The demo below shows how to target the icon by using the `svg` selector and apply `opacity` for a smooth effect: {{"demo": "HoverCheckbox.js"}} -#### Without an icon +#### No icons -To rely only on variants to communicate the checkbox state change, use the `disableIcon` prop to remove the icon. +Use the `disableIcon` prop to remove the icon entirely. +In this case, the state of the Checkbox is communicated through the type of variant applied to the label. +Try clicking on the Checkbox labels in the demo below to see how this works: {{"demo": "IconlessCheckbox.js"}} ### Focus outline -The focus outline, by default, wraps both the checkbox itself and its label. -To change that, target the `checkboxClasses.checkbox` class and add `position: 'relative'`. +By default, the focus outline wraps both the Checkbox input and its label. +To set the focus outline so that it only wraps the input, target the `checkboxClasses.checkbox` class and add `position: 'relative'`, as shown in the demo below: {{"demo": "FocusCheckbox.js"}} +### Clickable container + +Use the `overlay` prop to shift the focus outline from the Checkbox to its container, making the entire container clickable to toggle the state of the Checkbox. +This works with any wrapper element with [positioning](https://developer.mozilla.org/en-US/docs/Web/CSS/position#types_of_positioning)ā€”the demo below uses [Sheet](/joy-ui/react-sheet/) (by default, it has `relative` position): + +{{"demo": "OverlayCheckbox.js"}} + ### Indeterminate -Technically, the checkbox component only has two states: checked or unchecked. -However, visually, there is a third state called _indeterminate_. +The default Checkbox is _dual-state:_ the user can toggle between checked and unchecked. + +There is also the option for a _tri-state_ or indeterminate Checkbox that supports a state known as "partially checked." + +This indeterminate state is often used to communicate the fact that only some out of a set of Checkboxes are checked. +As such, it's usually reserved for parent Checkboxes that can control the states of their children. -It's common to find it in tables where you have one checkbox that selects every table row. -Use the `indeterminate` prop to circle around these states. +The demo below shows how to implement the `indeterminate` prop on a parent Checkbox that watches for the checked state in its children. +If only one child is checked, then the parent displays the indeterminate state. +Clicking on the parent Checkbox toggles selecting and deselecting all children. :::warning -When the indeterminate state is set, the value of the `checked` prop only impacts the form submitted values. +When the indeterminate state is set, the value of the `checked` prop only impacts form-submitted values. It has no accessibility or UX implications. ::: @@ -89,47 +130,64 @@ It has no accessibility or UX implications. ### Helper text -To add a description to the checkbox, use `FormControl` and `FormHelperText`. The checkbox will be linked to the helper text via `aria-describedby` attribute. +```jsx +import FormControl from '@mui/joy/FormControl'; +import FormHelperText from '@mui/joy/FormHelperText'; +``` + +Use the Form Control and Form Helper Text components add a description to the Checkbox. +The Checkbox will be linked to the helper text via the `aria-describedby` attribute. {{"demo": "HelperTextCheckbox.js"}} ### Group -To group multiple checkboxes, use `role="group"` on the wrapper component. +To group multiple Checkboxes, wrap them in a container component like Box with `role="group"`. -Combine with the [`List`](/joy-ui/react-list/) component to ensure consistent spacing and enable screen readers to interpret the checkbox group as a list. -Learn more about checkbox accessible design patters [in the W3C documentation](https://www.w3.org/WAI/ARIA/apg/example-index/checkbox/checkbox.html). +Combine with the [List](/joy-ui/react-list/) component to ensure consistent spacing and enable screen readers to interpret the Checkbox group as a list. +Learn more about accessible design patterns for checkboxes [in the W3C documentation](https://www.w3.org/WAI/ARIA/apg/example-index/checkbox/checkbox.html). {{"demo": "GroupCheckboxes.js"}} -### Overlay - -Use the `overlay` prop to make the entire surface of the wrapper container the checkbox is in clickable. - -{{"demo": "OverlayCheckbox.js"}} - ## Common examples ### Filtering status -In this example, we're using variants _and_ colors, within the `ListItem` and `Checkbox` component, to communicate state changes +This example uses variants and colors available to the List Item and Checkbox components to communicate state changes. {{"demo": "ExampleFilterStatusCheckbox.js"}} ### Filtering members -Note that in this example, we're using the CSS `flexDirection: 'rowReverse'` property to properly position the label and icon. - -Don't forget to use the `label` prop to ensure proper checkbox accessibility. +This example uses the CSS `flexDirection: 'rowReverse'` property to position the label and icon. +Don't forget to use the `label` prop to ensure proper Checkbox accessibility. {{"demo": "ExampleFilterMemberCheckbox.js"}} ### Choice chips -You can use checkboxes to create a chip alike design, most often used to filter between different options. +You can use Checkbox to recreate a kind of [Chip](/joy-ui/react-chip/) component, which is commonly implemented in the form of a group of filtering options. {{"demo": "ExampleChoiceChipCheckbox.js"}} ### Viewport checklist {{"demo": "ExampleButtonCheckbox.js"}} + +## Anatomy + +The Checkbox component is composed of a root `` that wraps the input and `
` to ``. ### Clickable -To make chips clikcable, pass a function to the `onClick` prop. +To make chips clickable, pass a function to the `onClick` prop. {{"demo": "ClickableChip.js"}} diff --git a/docs/data/joy/components/chip/chip-zh.md b/docs/data/joy/components/chip/chip-zh.md index f79afe4e95dd93..541e94fe17b3ed 100644 --- a/docs/data/joy/components/chip/chip-zh.md +++ b/docs/data/joy/components/chip/chip-zh.md @@ -12,8 +12,6 @@ githubLabel: 'component: chip' Chips are most frequently used in two main use cases: as pills of informative content or as filtering options. -The badge component is most frequently used to signal status (online, offline, busy, etc) and whether there's notifications or not. - {{"demo": "ChipUsage.js", "hideToolbar": true}} {{"component": "modules/components/ComponentLinkHeader.js", "design": false}} diff --git a/docs/data/joy/components/chip/chip.md b/docs/data/joy/components/chip/chip.md index 3088d6f17d69ed..c20c9e4a56df3d 100644 --- a/docs/data/joy/components/chip/chip.md +++ b/docs/data/joy/components/chip/chip.md @@ -12,8 +12,6 @@ githubLabel: 'component: chip' Chips are most frequently used in two main use cases: as pills of informative content or as filtering options. -The badge component is most frequently used to signal status (online, offline, busy, etc) and whether there's notifications or not. - {{"demo": "ChipUsage.js", "hideToolbar": true, "bg": "gradient"}} :::info diff --git a/docs/data/joy/components/divider/DividerInCard.js b/docs/data/joy/components/divider/DividerInCard.js index 97729581f011fe..0f0135b81d2a39 100644 --- a/docs/data/joy/components/divider/DividerInCard.js +++ b/docs/data/joy/components/divider/DividerInCard.js @@ -8,17 +8,19 @@ import Typography from '@mui/joy/Typography'; import ArrowForward from '@mui/icons-material/ArrowForward'; export default function DividerInCard() { - const [row, setRow] = React.useState(false); + const [orientation, setOrientation] = React.useState('vertical'); return ( setRow(event.target.checked)} + checked={orientation === 'horizontal'} + onChange={(event) => + setOrientation(event.target.checked ? 'horizontal' : 'vertical') + } sx={{ mb: 2 }} /> @@ -26,7 +28,7 @@ export default function DividerInCard() { Headline - + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry standard dummy text ever @@ -37,7 +39,7 @@ export default function DividerInCard() { variant="soft" color="neutral" endDecorator={} - sx={{ width: '100%', mt: row ? 2 : 0 }} + sx={{ width: '100%', mt: orientation === 'horizontal' ? 2 : 0 }} > See more diff --git a/docs/data/joy/components/divider/DividerInModalDialog.js b/docs/data/joy/components/divider/DividerInModalDialog.js index 2d2d324f5a2cbc..5a94fbeee4c79f 100644 --- a/docs/data/joy/components/divider/DividerInModalDialog.js +++ b/docs/data/joy/components/divider/DividerInModalDialog.js @@ -8,6 +8,8 @@ import Typography from '@mui/joy/Typography'; export default function DividerInModalDialog() { return ( - + Modal Title - - + + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry standard dummy text ever since the 1500s - + direction justifyContent alignItems direction justifyContent alignItems {[0, 0.5, 1, 2, 3, 4, 8, 12].map((value) => ( diff --git a/docs/data/joy/components/grid/SpacingGrid.tsx b/docs/data/joy/components/grid/SpacingGrid.tsx index 3126a52eb323b6..ecf4995de899a8 100644 --- a/docs/data/joy/components/grid/SpacingGrid.tsx +++ b/docs/data/joy/components/grid/SpacingGrid.tsx @@ -46,7 +46,7 @@ export default function SpacingGrid() { aria-label="spacing" value={spacing.toString()} onChange={handleChange} - row + orientation="horizontal" sx={{ flexWrap: 'wrap', gap: 2, '--RadioGroup-gap': '0px' }} > {[0, 0.5, 1, 2, 3, 4, 8, 12].map((value) => ( diff --git a/docs/data/joy/components/list/ExampleNavigationMenu.js b/docs/data/joy/components/list/ExampleNavigationMenu.js index e196fb5a0e04d6..060870dbffe894 100644 --- a/docs/data/joy/components/list/ExampleNavigationMenu.js +++ b/docs/data/joy/components/list/ExampleNavigationMenu.js @@ -303,7 +303,7 @@ export default function ExampleNavigationMenu() { - + Discard - setOpen(false)} - > - + setOpen(false)}> + } > Confirmation - - + + Are you sure you want to discard all of your notes? - + diff --git a/docs/data/joy/components/modal/BasicModalDialog.js b/docs/data/joy/components/modal/BasicModalDialog.js index cf7d007063ecf7..713ad6724c15fe 100644 --- a/docs/data/joy/components/modal/BasicModalDialog.js +++ b/docs/data/joy/components/modal/BasicModalDialog.js @@ -1,6 +1,8 @@ import * as React from 'react'; import Button from '@mui/joy/Button'; -import TextField from '@mui/joy/TextField'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import Input from '@mui/joy/Input'; import Modal from '@mui/joy/Modal'; import ModalDialog from '@mui/joy/ModalDialog'; import Stack from '@mui/joy/Stack'; @@ -23,28 +25,12 @@ export default function BasicModalDialog() { - + Create new project - + Fill in the information of the project.
- - + + Name + + + + Description + +
diff --git a/docs/data/joy/components/modal/FadeModalDialog.js b/docs/data/joy/components/modal/FadeModalDialog.js index 37262235dab95b..db83867e7ed4c4 100644 --- a/docs/data/joy/components/modal/FadeModalDialog.js +++ b/docs/data/joy/components/modal/FadeModalDialog.js @@ -47,13 +47,7 @@ export default function FadeModalDialog() { }[state], }} > - + Transition modal - + Keep mounted modal diff --git a/docs/data/joy/components/modal/LayoutModalDialog.js b/docs/data/joy/components/modal/LayoutModalDialog.js index 32ef3eeb82c890..90e096147fa29e 100644 --- a/docs/data/joy/components/modal/LayoutModalDialog.js +++ b/docs/data/joy/components/modal/LayoutModalDialog.js @@ -29,13 +29,7 @@ export default function LayoutModalDialog() { layout={open || undefined} > - + Modal Dialog diff --git a/docs/data/joy/components/modal/ModalUsage.js b/docs/data/joy/components/modal/ModalUsage.js index f15a6a117e20e7..23a19f4fc3de51 100644 --- a/docs/data/joy/components/modal/ModalUsage.js +++ b/docs/data/joy/components/modal/ModalUsage.js @@ -57,15 +57,13 @@ ${prependLinesSpace(code, 2)} aria-describedby="modal-usage-description" > - + Modal title + + A description of the dialog should give primary message or purpose of + the dialog. +
diff --git a/docs/data/joy/components/modal/NestedModals.js b/docs/data/joy/components/modal/NestedModals.js index 0849b250c72a7d..5730074057a028 100644 --- a/docs/data/joy/components/modal/NestedModals.js +++ b/docs/data/joy/components/modal/NestedModals.js @@ -27,20 +27,10 @@ export default function NestedModals({ random }) { }, })} > - + Infinite modals - + Welcome to the infinite nested modals. diff --git a/docs/data/joy/components/modal/ServerModal.js b/docs/data/joy/components/modal/ServerModal.js index 6bb6058f1f9f84..1d3b03b7bce449 100644 --- a/docs/data/joy/components/modal/ServerModal.js +++ b/docs/data/joy/components/modal/ServerModal.js @@ -34,13 +34,7 @@ export default function ServerModal() { aria-describedby="server-modal-description" layout="center" > - + Server-side modal diff --git a/docs/data/joy/components/modal/SizeModalDialog.js b/docs/data/joy/components/modal/SizeModalDialog.js index 37d7f3b649f380..9e70939c95c084 100644 --- a/docs/data/joy/components/modal/SizeModalDialog.js +++ b/docs/data/joy/components/modal/SizeModalDialog.js @@ -43,13 +43,7 @@ export default function SizeModalDialog() { size={open || undefined} > - + Modal Dialog diff --git a/docs/data/joy/components/modal/VariantModalDialog.js b/docs/data/joy/components/modal/VariantModalDialog.js index d1052945879c36..7e913e5d5ee511 100644 --- a/docs/data/joy/components/modal/VariantModalDialog.js +++ b/docs/data/joy/components/modal/VariantModalDialog.js @@ -35,13 +35,7 @@ export default function VariantModalDialog() { variant={open || undefined} > - + Modal Dialog diff --git a/docs/data/joy/components/modal/modal.md b/docs/data/joy/components/modal/modal.md index bc8d946ee98288..5dc66fad2481d1 100644 --- a/docs/data/joy/components/modal/modal.md +++ b/docs/data/joy/components/modal/modal.md @@ -78,6 +78,8 @@ The possible values are: To create a modal dialog, renders the `ModalDialog` component inside the `Modal`. +It will apply spacing to the elements that have `aria-labelledby` or `aria-describedby` attribute. + {{"demo": "BasicModalDialog.js"}} #### Layout diff --git a/docs/data/joy/components/radio/ExampleAlignmentButtons.js b/docs/data/joy/components/radio/ExampleAlignmentButtons.js index f8ccf227fe71ff..9e8f478adc5cba 100644 --- a/docs/data/joy/components/radio/ExampleAlignmentButtons.js +++ b/docs/data/joy/components/radio/ExampleAlignmentButtons.js @@ -11,7 +11,7 @@ export default function ExampleAlignmentButtons() { const [alignment, setAlignment] = React.useState('left'); return ( setRow(event.target.checked)} + checked={orientation === 'horizontal'} + onChange={(event) => + setOrientation(event.target.checked ? 'horizontal' : 'vertical') + } sx={{ [`&&:not(.${switchClasses.checked})`]: { '--Switch-track-background': (theme) => @@ -52,7 +54,7 @@ export default function ExamplePaymentChannels() { {[1, 2, 3].map((num) => ( diff --git a/docs/data/joy/components/radio/RadioUsage.js b/docs/data/joy/components/radio/RadioUsage.js index 7924106aa0b134..7cbf5ce708628e 100644 --- a/docs/data/joy/components/radio/RadioUsage.js +++ b/docs/data/joy/components/radio/RadioUsage.js @@ -1,7 +1,5 @@ import * as React from 'react'; -import JoyUsageDemo, { - prependLinesSpace, -} from 'docs/src/modules/components/JoyUsageDemo'; +import JoyUsageDemo from 'docs/src/modules/components/JoyUsageDemo'; import FormControl from '@mui/joy/FormControl'; import FormLabel from '@mui/joy/FormLabel'; import RadioGroup from '@mui/joy/RadioGroup'; @@ -36,14 +34,11 @@ export default function RadioUsage() { codeBlockDisplay: false, }, ]} - getCodeBlock={(code, props) => ` -${prependLinesSpace(code, 2)} -`} - renderDemo={({ row, ...props }) => ( + renderDemo={({ orientation, ...props }) => ( Pizza crust direction alignItems justifyContent spacing direction alignItems justifyContent spacing + + + Dessert (100g serving) + Calories + Fat (g) + Carbs (g) + Protein (g) + + + + + Frozen yoghurt + 159 + 6 + 24 + 4 + + + Ice cream sandwich + 237 + 9 + 37 + 4.3 + + + Eclair + 262 + 16 + 24 + 6 + + + Cupcake + 305 + 3.7 + 67 + 4.3 + + + Gingerbread + 356 + 16 + 49 + 3.9 + + + + ); +} diff --git a/docs/data/joy/components/table/BasicTable.tsx b/docs/data/joy/components/table/BasicTable.tsx new file mode 100644 index 00000000000000..5ec58e70cfcf76 --- /dev/null +++ b/docs/data/joy/components/table/BasicTable.tsx @@ -0,0 +1,55 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +export default function BasicTable() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Dessert (100g serving)CaloriesFat (g)Carbs (g)Protein (g)
Frozen yoghurt1596244
Ice cream sandwich2379374.3
Eclair26216246
Cupcake3053.7674.3
Gingerbread35616493.9
+ ); +} diff --git a/docs/data/joy/components/table/TableAlignment.js b/docs/data/joy/components/table/TableAlignment.js new file mode 100644 index 00000000000000..bc03ce24c873ba --- /dev/null +++ b/docs/data/joy/components/table/TableAlignment.js @@ -0,0 +1,41 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableAlignment() { + return ( + *:not(:first-child)': { textAlign: 'right' } }}> + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+ ); +} diff --git a/docs/data/joy/components/table/TableAlignment.tsx b/docs/data/joy/components/table/TableAlignment.tsx new file mode 100644 index 00000000000000..73c34a9b4648ce --- /dev/null +++ b/docs/data/joy/components/table/TableAlignment.tsx @@ -0,0 +1,47 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableAlignment() { + return ( + *:not(:first-child)': { textAlign: 'right' } }}> + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+ ); +} diff --git a/docs/data/joy/components/table/TableBorder.js b/docs/data/joy/components/table/TableBorder.js new file mode 100644 index 00000000000000..040b8232b19dd5 --- /dev/null +++ b/docs/data/joy/components/table/TableBorder.js @@ -0,0 +1,64 @@ +import * as React from 'react'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; +import Table from '@mui/joy/Table'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableBorder() { + const [borderAxis, setBorderAxis] = React.useState('xBetween'); + return ( +
+ + Border axis: + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Dessert (100g serving)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableBorder.tsx b/docs/data/joy/components/table/TableBorder.tsx new file mode 100644 index 00000000000000..4c44758576a584 --- /dev/null +++ b/docs/data/joy/components/table/TableBorder.tsx @@ -0,0 +1,71 @@ +import * as React from 'react'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; +import Table, { TableProps } from '@mui/joy/Table'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableBorder() { + const [borderAxis, setBorderAxis] = + React.useState('xBetween'); + return ( +
+ + Border axis: + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Dessert (100g serving)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableCaption.js b/docs/data/joy/components/table/TableCaption.js new file mode 100644 index 00000000000000..c477d3f0dffa43 --- /dev/null +++ b/docs/data/joy/components/table/TableCaption.js @@ -0,0 +1,42 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableCaption() { + return ( + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
A caption should be a summary of the table.
MenuCaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+ ); +} diff --git a/docs/data/joy/components/table/TableCaption.tsx b/docs/data/joy/components/table/TableCaption.tsx new file mode 100644 index 00000000000000..3a6cae7f5ad54d --- /dev/null +++ b/docs/data/joy/components/table/TableCaption.tsx @@ -0,0 +1,48 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableCaption() { + return ( + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
A caption should be a summary of the table.
MenuCaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+ ); +} diff --git a/docs/data/joy/components/table/TableCollapsibleRow.js b/docs/data/joy/components/table/TableCollapsibleRow.js new file mode 100644 index 00000000000000..c4e85a38c90ab5 --- /dev/null +++ b/docs/data/joy/components/table/TableCollapsibleRow.js @@ -0,0 +1,165 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import IconButton from '@mui/joy/IconButton'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; +import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; +import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; + +function createData(name, calories, fat, carbs, protein, price) { + return { + name, + calories, + fat, + carbs, + protein, + price, + history: [ + { + date: '2020-01-05', + customerId: '11091700', + amount: 3, + }, + { + date: '2020-01-02', + customerId: 'Anonymous', + amount: 1, + }, + ], + }; +} + +function Row(props) { + const { row } = props; + const [open, setOpen] = React.useState(props.initialOpen || false); + + return ( + + + + setOpen(!open)} + > + {open ? : } + + + {row.name} + {row.calories} + {row.fat} + {row.carbs} + {row.protein} + + + + {open && ( + + + History + + thead > tr > th:nth-child(n + 3), & > tbody > tr > td:nth-child(n + 3)': + { textAlign: 'right' }, + '--TableCell-paddingX': '0.5rem', + }} + > + + + + + + + + + + {row.history.map((historyRow) => ( + + + + + + + ))} + +
DateCustomerAmountTotal price ($)
{historyRow.date}{historyRow.customerId}{historyRow.amount} + {Math.round(historyRow.amount * row.price * 100) / 100} +
+
+ )} + + +
+ ); +} + +Row.propTypes = { + initialOpen: PropTypes.bool, + row: PropTypes.shape({ + calories: PropTypes.number.isRequired, + carbs: PropTypes.number.isRequired, + fat: PropTypes.number.isRequired, + history: PropTypes.arrayOf( + PropTypes.shape({ + amount: PropTypes.number.isRequired, + customerId: PropTypes.string.isRequired, + date: PropTypes.string.isRequired, + }), + ).isRequired, + name: PropTypes.string.isRequired, + price: PropTypes.number.isRequired, + protein: PropTypes.number.isRequired, + }).isRequired, +}; + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0, 3.99), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3, 4.99), + createData('Eclair', 262, 16.0, 24, 6.0, 3.79), + createData('Cupcake', 305, 3.7, 67, 4.3, 2.5), + createData('Gingerbread', 356, 16.0, 49, 3.9, 1.5), +]; + +export default function TableCollapsibleRow() { + return ( + + thead > tr > th:nth-child(n + 3), & > tbody > tr > td:nth-child(n + 3)': + { textAlign: 'right' }, + '& > tbody > tr:nth-child(odd) > td, & > tbody > tr:nth-child(odd) > th[scope="row"]': + { + borderBottom: 0, + }, + }} + > + + + + + + + + + + + {rows.map((row, index) => ( + + ))} + +
+ Dessert (100g serving)CaloriesFat (g)Carbs (g)Protein (g)
+
+ ); +} diff --git a/docs/data/joy/components/table/TableCollapsibleRow.tsx b/docs/data/joy/components/table/TableCollapsibleRow.tsx new file mode 100644 index 00000000000000..cf49c05e4fe106 --- /dev/null +++ b/docs/data/joy/components/table/TableCollapsibleRow.tsx @@ -0,0 +1,152 @@ +import * as React from 'react'; +import IconButton from '@mui/joy/IconButton'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; +import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; +import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, + price: number, +) { + return { + name, + calories, + fat, + carbs, + protein, + price, + history: [ + { + date: '2020-01-05', + customerId: '11091700', + amount: 3, + }, + { + date: '2020-01-02', + customerId: 'Anonymous', + amount: 1, + }, + ], + }; +} + +function Row(props: { row: ReturnType; initialOpen?: boolean }) { + const { row } = props; + const [open, setOpen] = React.useState(props.initialOpen || false); + + return ( + + + + setOpen(!open)} + > + {open ? : } + + + {row.name} + {row.calories} + {row.fat} + {row.carbs} + {row.protein} + + + + {open && ( + + + History + + thead > tr > th:nth-child(n + 3), & > tbody > tr > td:nth-child(n + 3)': + { textAlign: 'right' }, + '--TableCell-paddingX': '0.5rem', + }} + > + + + + + + + + + + {row.history.map((historyRow) => ( + + + + + + + ))} + +
DateCustomerAmountTotal price ($)
{historyRow.date}{historyRow.customerId}{historyRow.amount} + {Math.round(historyRow.amount * row.price * 100) / 100} +
+
+ )} + + +
+ ); +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0, 3.99), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3, 4.99), + createData('Eclair', 262, 16.0, 24, 6.0, 3.79), + createData('Cupcake', 305, 3.7, 67, 4.3, 2.5), + createData('Gingerbread', 356, 16.0, 49, 3.9, 1.5), +]; + +export default function TableCollapsibleRow() { + return ( + + thead > tr > th:nth-child(n + 3), & > tbody > tr > td:nth-child(n + 3)': + { textAlign: 'right' }, + '& > tbody > tr:nth-child(odd) > td, & > tbody > tr:nth-child(odd) > th[scope="row"]': + { + borderBottom: 0, + }, + }} + > + + + + + + + + + + + {rows.map((row, index) => ( + + ))} + +
+ Dessert (100g serving)CaloriesFat (g)Carbs (g)Protein (g)
+
+ ); +} diff --git a/docs/data/joy/components/table/TableColumnPinning.js b/docs/data/joy/components/table/TableColumnPinning.js new file mode 100644 index 00000000000000..36f55e04e9b653 --- /dev/null +++ b/docs/data/joy/components/table/TableColumnPinning.js @@ -0,0 +1,116 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import Button from '@mui/joy/Button'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('1', 159, 6.0, 24, 4.0), + createData('2', 237, 9.0, 37, 4.3), + createData('3', 262, 16.0, 24, 6.0), + createData('4', 305, 3.7, 67, 4.3), +]; + +export default function TableColumnPinning() { + return ( + + + ā† Scroll direction ā†’ + + + `linear-gradient(to right, ${theme.vars.palette.background.surface} 30%, rgba(255, 255, 255, 0)), + linear-gradient(to right, rgba(255, 255, 255, 0), ${theme.vars.palette.background.surface} 70%) 0 100%, + radial-gradient( + farthest-side at 0 50%, + rgba(0, 0, 0, 0.12), + rgba(0, 0, 0, 0) + ), + radial-gradient( + farthest-side at 100% 50%, + rgba(0, 0, 0, 0.12), + rgba(0, 0, 0, 0) + ) + 0 100%`, + backgroundSize: + '40px calc(100% - var(--TableCell-height)), 40px calc(100% - var(--TableCell-height)), 14px calc(100% - var(--TableCell-height)), 14px calc(100% - var(--TableCell-height))', + backgroundRepeat: 'no-repeat', + backgroundAttachment: 'local, local, scroll, scroll', + backgroundPosition: + 'var(--Table-firstColumnWidth) var(--TableCell-height), calc(100% - var(--Table-lastColumnWidth)) var(--TableCell-height), var(--Table-firstColumnWidth) var(--TableCell-height), calc(100% - var(--Table-lastColumnWidth)) var(--TableCell-height)', + backgroundColor: 'background.surface', + }} + > + *:first-child': { + position: 'sticky', + left: 0, + boxShadow: '1px 0 var(--TableCell-borderColor)', + bgcolor: 'background.surface', + }, + '& tr > *:last-child': { + position: 'sticky', + right: 0, + bgcolor: 'var(--TableCell-headBackground)', + }, + }} + > + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + + ))} + +
RowCaloriesFat (g)Carbs (g)Protein (g) +
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein} + + + + +
+
+
+ ); +} diff --git a/docs/data/joy/components/table/TableColumnPinning.tsx b/docs/data/joy/components/table/TableColumnPinning.tsx new file mode 100644 index 00000000000000..745e5e84763eda --- /dev/null +++ b/docs/data/joy/components/table/TableColumnPinning.tsx @@ -0,0 +1,123 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import Button from '@mui/joy/Button'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('1', 159, 6.0, 24, 4.0), + createData('2', 237, 9.0, 37, 4.3), + createData('3', 262, 16.0, 24, 6.0), + createData('4', 305, 3.7, 67, 4.3), +]; + +export default function TableColumnPinning() { + return ( + + + ā† Scroll direction ā†’ + + `linear-gradient(to right, ${theme.vars.palette.background.surface} 30%, rgba(255, 255, 255, 0)), + linear-gradient(to right, rgba(255, 255, 255, 0), ${theme.vars.palette.background.surface} 70%) 0 100%, + radial-gradient( + farthest-side at 0 50%, + rgba(0, 0, 0, 0.12), + rgba(0, 0, 0, 0) + ), + radial-gradient( + farthest-side at 100% 50%, + rgba(0, 0, 0, 0.12), + rgba(0, 0, 0, 0) + ) + 0 100%`, + backgroundSize: + '40px calc(100% - var(--TableCell-height)), 40px calc(100% - var(--TableCell-height)), 14px calc(100% - var(--TableCell-height)), 14px calc(100% - var(--TableCell-height))', + backgroundRepeat: 'no-repeat', + backgroundAttachment: 'local, local, scroll, scroll', + backgroundPosition: + 'var(--Table-firstColumnWidth) var(--TableCell-height), calc(100% - var(--Table-lastColumnWidth)) var(--TableCell-height), var(--Table-firstColumnWidth) var(--TableCell-height), calc(100% - var(--Table-lastColumnWidth)) var(--TableCell-height)', + backgroundColor: 'background.surface', + }} + > + *:first-child': { + position: 'sticky', + left: 0, + boxShadow: '1px 0 var(--TableCell-borderColor)', + bgcolor: 'background.surface', + }, + '& tr > *:last-child': { + position: 'sticky', + right: 0, + bgcolor: 'var(--TableCell-headBackground)', + }, + }} + > + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + + ))} + +
RowCaloriesFat (g)Carbs (g)Protein (g) +
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein} + + + + +
+
+
+ ); +} diff --git a/docs/data/joy/components/table/TableColumnWidth.js b/docs/data/joy/components/table/TableColumnWidth.js new file mode 100644 index 00000000000000..058c0da5cfd591 --- /dev/null +++ b/docs/data/joy/components/table/TableColumnWidth.js @@ -0,0 +1,41 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableColumnWidth() { + return ( + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+ ); +} diff --git a/docs/data/joy/components/table/TableColumnWidth.tsx b/docs/data/joy/components/table/TableColumnWidth.tsx new file mode 100644 index 00000000000000..78c5358e6b340e --- /dev/null +++ b/docs/data/joy/components/table/TableColumnWidth.tsx @@ -0,0 +1,47 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableColumnWidth() { + return ( + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+ ); +} diff --git a/docs/data/joy/components/table/TableFooter.js b/docs/data/joy/components/table/TableFooter.js new file mode 100644 index 00000000000000..08d7b33ab6c4c3 --- /dev/null +++ b/docs/data/joy/components/table/TableFooter.js @@ -0,0 +1,51 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableFooter() { + return ( + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + + + + + + + + + + +
A caption should be a summary of the table.
MenuCaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
Totals1,31950.720122.5
+ ); +} diff --git a/docs/data/joy/components/table/TableFooter.tsx b/docs/data/joy/components/table/TableFooter.tsx new file mode 100644 index 00000000000000..e0c9f32a34611f --- /dev/null +++ b/docs/data/joy/components/table/TableFooter.tsx @@ -0,0 +1,57 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableFooter() { + return ( + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + + + + + + + + + + +
A caption should be a summary of the table.
MenuCaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
Totals1,31950.720122.5
+ ); +} diff --git a/docs/data/joy/components/table/TableGlobalVariant.js b/docs/data/joy/components/table/TableGlobalVariant.js new file mode 100644 index 00000000000000..a2c6719c21fdfb --- /dev/null +++ b/docs/data/joy/components/table/TableGlobalVariant.js @@ -0,0 +1,39 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +export default function TableGlobalVariant() { + return ( + ({ + '& tr > *:first-child': { bgcolor: 'info.softBg' }, + '& th[scope="col"]': theme.variants.solid.neutral, + '& td': theme.variants.soft.neutral, + })} + > + + + + + + + + + + + + + + + + + + + + + + + +
Alien football stars
PlayerGlooblesZa'taak
TR-774,569
Khiresh Odo77,223
Mia Oolong96,219
+ ); +} diff --git a/docs/data/joy/components/table/TableGlobalVariant.tsx b/docs/data/joy/components/table/TableGlobalVariant.tsx new file mode 100644 index 00000000000000..a2c6719c21fdfb --- /dev/null +++ b/docs/data/joy/components/table/TableGlobalVariant.tsx @@ -0,0 +1,39 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +export default function TableGlobalVariant() { + return ( + ({ + '& tr > *:first-child': { bgcolor: 'info.softBg' }, + '& th[scope="col"]': theme.variants.solid.neutral, + '& td': theme.variants.soft.neutral, + })} + > + + + + + + + + + + + + + + + + + + + + + + + +
Alien football stars
PlayerGlooblesZa'taak
TR-774,569
Khiresh Odo77,223
Mia Oolong96,219
+ ); +} diff --git a/docs/data/joy/components/table/TableHover.js b/docs/data/joy/components/table/TableHover.js new file mode 100644 index 00000000000000..0dea70716a2c87 --- /dev/null +++ b/docs/data/joy/components/table/TableHover.js @@ -0,0 +1,41 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableHover() { + return ( + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+ ); +} diff --git a/docs/data/joy/components/table/TableHover.tsx b/docs/data/joy/components/table/TableHover.tsx new file mode 100644 index 00000000000000..1a37a8fb8fca6d --- /dev/null +++ b/docs/data/joy/components/table/TableHover.tsx @@ -0,0 +1,47 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableHover() { + return ( + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+ ); +} diff --git a/docs/data/joy/components/table/TableRowColumnSpan.js b/docs/data/joy/components/table/TableRowColumnSpan.js new file mode 100644 index 00000000000000..556707f8b1d018 --- /dev/null +++ b/docs/data/joy/components/table/TableRowColumnSpan.js @@ -0,0 +1,54 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +export default function TableRowColumnSpan() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameID + Membership Dates + Balance
JoinedCanceled
Margaret Nguyen427311 + + n/a0.00
Edvard Galinski533175 + + + + 37.00
Hoshi Nakamura601942 + + n/a15.00
+ ); +} diff --git a/docs/data/joy/components/table/TableRowColumnSpan.tsx b/docs/data/joy/components/table/TableRowColumnSpan.tsx new file mode 100644 index 00000000000000..556707f8b1d018 --- /dev/null +++ b/docs/data/joy/components/table/TableRowColumnSpan.tsx @@ -0,0 +1,54 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; + +export default function TableRowColumnSpan() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameID + Membership Dates + Balance
JoinedCanceled
Margaret Nguyen427311 + + n/a0.00
Edvard Galinski533175 + + + + 37.00
Hoshi Nakamura601942 + + n/a15.00
+ ); +} diff --git a/docs/data/joy/components/table/TableRowHead.js b/docs/data/joy/components/table/TableRowHead.js new file mode 100644 index 00000000000000..78b31bf0358593 --- /dev/null +++ b/docs/data/joy/components/table/TableRowHead.js @@ -0,0 +1,44 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Sheet from '@mui/joy/Sheet'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableRowHead() { + return ( + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableRowHead.tsx b/docs/data/joy/components/table/TableRowHead.tsx new file mode 100644 index 00000000000000..5aff0cf42192ca --- /dev/null +++ b/docs/data/joy/components/table/TableRowHead.tsx @@ -0,0 +1,50 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Sheet from '@mui/joy/Sheet'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableRowHead() { + return ( + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableScrollingShadows.js b/docs/data/joy/components/table/TableScrollingShadows.js new file mode 100644 index 00000000000000..c043592107ef1e --- /dev/null +++ b/docs/data/joy/components/table/TableScrollingShadows.js @@ -0,0 +1,83 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('1', 159, 6.0, 24, 4.0), + createData('2', 237, 9.0, 37, 4.3), + createData('3', 262, 16.0, 24, 6.0), + createData('4', 305, 3.7, 67, 4.3), + createData('5', 356, 16.0, 49, 3.9), + createData('6', 159, 6.0, 24, 4.0), + createData('7', 237, 9.0, 37, 4.3), + createData('8', 262, 16.0, 24, 6.0), + createData('9', 305, 3.7, 67, 4.3), + createData('10', 356, 16.0, 49, 3.9), +]; + +export default function TableScrollingShadows() { + return ( +
+ + The table body is scrollable. + + + `linear-gradient(${theme.vars.palette.background.surface} 30%, rgba(255, 255, 255, 0)), + linear-gradient(rgba(255, 255, 255, 0), ${theme.vars.palette.background.surface} 70%) 0 100%, + radial-gradient( + farthest-side at 50% 0, + rgba(0, 0, 0, 0.12), + rgba(0, 0, 0, 0) + ), + radial-gradient( + farthest-side at 50% 100%, + rgba(0, 0, 0, 0.12), + rgba(0, 0, 0, 0) + ) + 0 100%`, + backgroundSize: '100% 40px, 100% 40px, 100% 14px, 100% 14px', + backgroundRepeat: 'no-repeat', + backgroundAttachment: 'local, local, scroll, scroll', + backgroundPosition: + '0 var(--TableHeader-height), 0 100%, 0 var(--TableHeader-height), 0 100%', + backgroundColor: 'background.surface', + }} + > + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
RowCaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+
+ ); +} diff --git a/docs/data/joy/components/table/TableScrollingShadows.tsx b/docs/data/joy/components/table/TableScrollingShadows.tsx new file mode 100644 index 00000000000000..2d1ca4a736c838 --- /dev/null +++ b/docs/data/joy/components/table/TableScrollingShadows.tsx @@ -0,0 +1,90 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('1', 159, 6.0, 24, 4.0), + createData('2', 237, 9.0, 37, 4.3), + createData('3', 262, 16.0, 24, 6.0), + createData('4', 305, 3.7, 67, 4.3), + createData('5', 356, 16.0, 49, 3.9), + createData('6', 159, 6.0, 24, 4.0), + createData('7', 237, 9.0, 37, 4.3), + createData('8', 262, 16.0, 24, 6.0), + createData('9', 305, 3.7, 67, 4.3), + createData('10', 356, 16.0, 49, 3.9), +]; + +export default function TableScrollingShadows() { + return ( +
+ + The table body is scrollable. + + `linear-gradient(${theme.vars.palette.background.surface} 30%, rgba(255, 255, 255, 0)), + linear-gradient(rgba(255, 255, 255, 0), ${theme.vars.palette.background.surface} 70%) 0 100%, + radial-gradient( + farthest-side at 50% 0, + rgba(0, 0, 0, 0.12), + rgba(0, 0, 0, 0) + ), + radial-gradient( + farthest-side at 50% 100%, + rgba(0, 0, 0, 0.12), + rgba(0, 0, 0, 0) + ) + 0 100%`, + backgroundSize: '100% 40px, 100% 40px, 100% 14px, 100% 14px', + backgroundRepeat: 'no-repeat', + backgroundAttachment: 'local, local, scroll, scroll', + backgroundPosition: + '0 var(--TableHeader-height), 0 100%, 0 var(--TableHeader-height), 0 100%', + backgroundColor: 'background.surface', + }} + > + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
RowCaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+
+ ); +} diff --git a/docs/data/joy/components/table/TableSheet.js b/docs/data/joy/components/table/TableSheet.js new file mode 100644 index 00000000000000..e485ea60c4a4ec --- /dev/null +++ b/docs/data/joy/components/table/TableSheet.js @@ -0,0 +1,49 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Sheet from '@mui/joy/Sheet'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableSheet() { + return ( + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Nutrition of your favorite menus.
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableSheet.tsx b/docs/data/joy/components/table/TableSheet.tsx new file mode 100644 index 00000000000000..74d6ff41fabccd --- /dev/null +++ b/docs/data/joy/components/table/TableSheet.tsx @@ -0,0 +1,55 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Sheet from '@mui/joy/Sheet'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableSheet() { + return ( + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Nutrition of your favorite menus.
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableSheetColorInversion.js b/docs/data/joy/components/table/TableSheetColorInversion.js new file mode 100644 index 00000000000000..1e456b2e64cf61 --- /dev/null +++ b/docs/data/joy/components/table/TableSheetColorInversion.js @@ -0,0 +1,64 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Sheet from '@mui/joy/Sheet'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableSheetColorInversion() { + return ( + + `linear-gradient(45deg, ${theme.vars.palette.primary[500]}, ${theme.vars.palette.primary[400]})`, + '& tr:last-child': { + '& td:first-child': { + borderBottomLeftRadius: '8px', + }, + '& td:last-child': { + borderBottomRightRadius: '8px', + }, + }, + }} + > + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Nutrition of your favorite menus.
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableSheetColorInversion.tsx b/docs/data/joy/components/table/TableSheetColorInversion.tsx new file mode 100644 index 00000000000000..cb9ec80525cba8 --- /dev/null +++ b/docs/data/joy/components/table/TableSheetColorInversion.tsx @@ -0,0 +1,70 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Sheet from '@mui/joy/Sheet'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableSheetColorInversion() { + return ( + + `linear-gradient(45deg, ${theme.vars.palette.primary[500]}, ${theme.vars.palette.primary[400]})`, + '& tr:last-child': { + '& td:first-child': { + borderBottomLeftRadius: '8px', + }, + '& td:last-child': { + borderBottomRightRadius: '8px', + }, + }, + }} + > + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Nutrition of your favorite menus.
Column width (40%)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableSizes.js b/docs/data/joy/components/table/TableSizes.js new file mode 100644 index 00000000000000..68a9e1d87f31ec --- /dev/null +++ b/docs/data/joy/components/table/TableSizes.js @@ -0,0 +1,60 @@ +import * as React from 'react'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import RadioGroup from '@mui/joy/RadioGroup'; +import Radio from '@mui/joy/Radio'; +import Table from '@mui/joy/Table'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableSizes() { + const [size, setSize] = React.useState('md'); + return ( +
+ + Size: + setSize(event.target.value)} + > + + + + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Dessert (100g serving)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableSizes.tsx b/docs/data/joy/components/table/TableSizes.tsx new file mode 100644 index 00000000000000..a045c959341d3c --- /dev/null +++ b/docs/data/joy/components/table/TableSizes.tsx @@ -0,0 +1,66 @@ +import * as React from 'react'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import RadioGroup from '@mui/joy/RadioGroup'; +import Radio from '@mui/joy/Radio'; +import Table, { TableProps } from '@mui/joy/Table'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableSizes() { + const [size, setSize] = React.useState('md'); + return ( +
+ + Size: + setSize(event.target.value as typeof size)} + > + + + + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Dessert (100g serving)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableSortAndSelection.js b/docs/data/joy/components/table/TableSortAndSelection.js new file mode 100644 index 00000000000000..59c0dc8d5fd5b1 --- /dev/null +++ b/docs/data/joy/components/table/TableSortAndSelection.js @@ -0,0 +1,467 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import Box from '@mui/joy/Box'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; +import Checkbox from '@mui/joy/Checkbox'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import IconButton from '@mui/joy/IconButton'; +import Link from '@mui/joy/Link'; +import Tooltip from '@mui/joy/Tooltip'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; +import DeleteIcon from '@mui/icons-material/Delete'; +import FilterListIcon from '@mui/icons-material/FilterList'; +import KeyboardArrowLeftIcon from '@mui/icons-material/KeyboardArrowLeft'; +import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; +import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; +import { visuallyHidden } from '@mui/utils'; + +function createData(name, calories, fat, carbs, protein) { + return { + name, + calories, + fat, + carbs, + protein, + }; +} + +const rows = [ + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Donut', 452, 25.0, 51, 4.9), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Gingerbread', 356, 16.0, 49, 3.9), + createData('Honeycomb', 408, 3.2, 87, 6.5), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Jelly Bean', 375, 0.0, 94, 0.0), + createData('KitKat', 518, 26.0, 65, 7.0), + createData('Lollipop', 392, 0.2, 98, 0.0), + createData('Marshmallow', 318, 0, 81, 2.0), + createData('Nougat', 360, 19.0, 9, 37.0), + createData('Oreo', 437, 18.0, 63, 4.0), +]; + +function labelDisplayedRows({ from, to, count }) { + return `${from}ā€“${to} of ${count !== -1 ? count : `more than ${to}`}`; +} + +function descendingComparator(a, b, orderBy) { + if (b[orderBy] < a[orderBy]) { + return -1; + } + if (b[orderBy] > a[orderBy]) { + return 1; + } + return 0; +} + +function getComparator(order, orderBy) { + return order === 'desc' + ? (a, b) => descendingComparator(a, b, orderBy) + : (a, b) => -descendingComparator(a, b, orderBy); +} + +// Since 2020 all major browsers ensure sort stability with Array.prototype.sort(). +// stableSort() brings sort stability to non-modern browsers (notably IE11). If you +// only support modern browsers you can replace stableSort(exampleArray, exampleComparator) +// with exampleArray.slice().sort(exampleComparator) +function stableSort(array, comparator) { + const stabilizedThis = array.map((el, index) => [el, index]); + stabilizedThis.sort((a, b) => { + const order = comparator(a[0], b[0]); + if (order !== 0) { + return order; + } + return a[1] - b[1]; + }); + return stabilizedThis.map((el) => el[0]); +} + +const headCells = [ + { + id: 'name', + numeric: false, + disablePadding: true, + label: 'DessertĀ (100g serving)', + }, + { + id: 'calories', + numeric: true, + disablePadding: false, + label: 'Calories', + }, + { + id: 'fat', + numeric: true, + disablePadding: false, + label: 'FatĀ (g)', + }, + { + id: 'carbs', + numeric: true, + disablePadding: false, + label: 'CarbsĀ (g)', + }, + { + id: 'protein', + numeric: true, + disablePadding: false, + label: 'ProteinĀ (g)', + }, +]; + +function EnhancedTableHead(props) { + const { onSelectAllClick, order, orderBy, numSelected, rowCount, onRequestSort } = + props; + const createSortHandler = (property) => (event) => { + onRequestSort(event, property); + }; + + return ( + + + + 0 && numSelected < rowCount} + checked={rowCount > 0 && numSelected === rowCount} + onChange={onSelectAllClick} + slotProps={{ + input: { + 'aria-label': 'select all desserts', + }, + }} + sx={{ verticalAlign: 'sub' }} + /> + + {headCells.map((headCell) => { + const active = orderBy === headCell.id; + return ( + + {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} + + ) : null + } + endDecorator={ + !headCell.numeric ? ( + + ) : null + } + sx={{ + '& svg': { + transition: '0.2s', + transform: + active && order === 'desc' ? 'rotate(0deg)' : 'rotate(180deg)', + }, + '&:hover': { '& svg': { opacity: 1 } }, + }} + > + {headCell.label} + {active ? ( + + {order === 'desc' ? 'sorted descending' : 'sorted ascending'} + + ) : null} + + + ); + })} + + + ); +} + +EnhancedTableHead.propTypes = { + numSelected: PropTypes.number.isRequired, + onRequestSort: PropTypes.func.isRequired, + onSelectAllClick: PropTypes.func.isRequired, + order: PropTypes.oneOf(['asc', 'desc']).isRequired, + orderBy: PropTypes.string.isRequired, + rowCount: PropTypes.number.isRequired, +}; + +function EnhancedTableToolbar(props) { + const { numSelected } = props; + + return ( + 0 && { + bgcolor: 'background.level1', + }), + borderTopLeftRadius: 'var(--internal-action-radius)', + borderTopRightRadius: 'var(--internal-action-radius)', + }} + > + {numSelected > 0 ? ( + + {numSelected} selected + + ) : ( + + Nutrition + + )} + + {numSelected > 0 ? ( + + + + + + ) : ( + + + + + + )} + + ); +} + +EnhancedTableToolbar.propTypes = { + numSelected: PropTypes.number.isRequired, +}; + +export default function TableSortAndSelection() { + const [order, setOrder] = React.useState('asc'); + const [orderBy, setOrderBy] = React.useState('calories'); + const [selected, setSelected] = React.useState([]); + const [page, setPage] = React.useState(0); + const [rowsPerPage, setRowsPerPage] = React.useState(5); + + const handleRequestSort = (event, property) => { + const isAsc = orderBy === property && order === 'asc'; + setOrder(isAsc ? 'desc' : 'asc'); + setOrderBy(property); + }; + + const handleSelectAllClick = (event) => { + if (event.target.checked) { + const newSelected = rows.map((n) => n.name); + setSelected(newSelected); + return; + } + setSelected([]); + }; + + const handleClick = (event, name) => { + const selectedIndex = selected.indexOf(name); + let newSelected = []; + + if (selectedIndex === -1) { + newSelected = newSelected.concat(selected, name); + } else if (selectedIndex === 0) { + newSelected = newSelected.concat(selected.slice(1)); + } else if (selectedIndex === selected.length - 1) { + newSelected = newSelected.concat(selected.slice(0, -1)); + } else if (selectedIndex > 0) { + newSelected = newSelected.concat( + selected.slice(0, selectedIndex), + selected.slice(selectedIndex + 1), + ); + } + + setSelected(newSelected); + }; + + const handleChangePage = (newPage) => { + setPage(newPage); + }; + + const handleChangeRowsPerPage = (event, newValue) => { + setRowsPerPage(parseInt(newValue.toString(), 10)); + setPage(0); + }; + + const getLabelDisplayedRowsTo = () => { + if (rows.length === -1) { + return (page + 1) * rowsPerPage; + } + return rowsPerPage === -1 + ? rows.length + : Math.min(rows.length, (page + 1) * rowsPerPage); + }; + + const isSelected = (name) => selected.indexOf(name) !== -1; + + // Avoid a layout jump when reaching the last page with empty rows. + const emptyRows = + page > 0 ? Math.max(0, (1 + page) * rowsPerPage - rows.length) : 0; + + return ( + + + + theme.vars.palette.info.softBg, + '& thead th:nth-child(1)': { + width: '40px', + }, + '& thead th:nth-child(2)': { + width: '30%', + }, + '& tr > *:nth-child(n+3)': { textAlign: 'right' }, + }} + > + + + {stableSort(rows, getComparator(order, orderBy)) + .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) + .map((row, index) => { + const isItemSelected = isSelected(row.name); + const labelId = `enhanced-table-checkbox-${index}`; + + return ( + handleClick(event, row.name)} + role="checkbox" + aria-checked={isItemSelected} + tabIndex={-1} + key={row.name} + // selected={isItemSelected} + style={ + isItemSelected + ? { + '--TableCell-dataBackground': + 'var(--TableCell-selectedBackground)', + '--TableCell-headBackground': + 'var(--TableCell-selectedBackground)', + } + : {} + } + > + + + + + + + + ); + })} + {emptyRows > 0 && ( + + + )} + + + + + + +
+ + + {row.name} + {row.calories}{row.fat}{row.carbs}{row.protein}
+
+ + + Rows per page: + + + + {labelDisplayedRows({ + from: rows.length === 0 ? 0 : page * rowsPerPage + 1, + to: getLabelDisplayedRowsTo(), + count: rows.length === -1 ? -1 : rows.length, + })} + + + handleChangePage(page - 1)} + sx={{ bgcolor: 'background.surface' }} + > + + + = Math.ceil(rows.length / rowsPerPage) - 1 + : false + } + onClick={() => handleChangePage(page + 1)} + sx={{ bgcolor: 'background.surface' }} + > + + + + +
+
+ ); +} diff --git a/docs/data/joy/components/table/TableSortAndSelection.tsx b/docs/data/joy/components/table/TableSortAndSelection.tsx new file mode 100644 index 00000000000000..c285581a91fbe9 --- /dev/null +++ b/docs/data/joy/components/table/TableSortAndSelection.tsx @@ -0,0 +1,511 @@ +import * as React from 'react'; +import Box from '@mui/joy/Box'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; +import Checkbox from '@mui/joy/Checkbox'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import IconButton from '@mui/joy/IconButton'; +import Link from '@mui/joy/Link'; +import Tooltip from '@mui/joy/Tooltip'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; +import DeleteIcon from '@mui/icons-material/Delete'; +import FilterListIcon from '@mui/icons-material/FilterList'; +import KeyboardArrowLeftIcon from '@mui/icons-material/KeyboardArrowLeft'; +import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; +import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; +import { visuallyHidden } from '@mui/utils'; + +interface Data { + calories: number; + carbs: number; + fat: number; + name: string; + protein: number; +} + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +): Data { + return { + name, + calories, + fat, + carbs, + protein, + }; +} + +const rows = [ + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Donut', 452, 25.0, 51, 4.9), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Gingerbread', 356, 16.0, 49, 3.9), + createData('Honeycomb', 408, 3.2, 87, 6.5), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Jelly Bean', 375, 0.0, 94, 0.0), + createData('KitKat', 518, 26.0, 65, 7.0), + createData('Lollipop', 392, 0.2, 98, 0.0), + createData('Marshmallow', 318, 0, 81, 2.0), + createData('Nougat', 360, 19.0, 9, 37.0), + createData('Oreo', 437, 18.0, 63, 4.0), +]; + +function labelDisplayedRows({ + from, + to, + count, +}: { + from: number; + to: number; + count: number; +}) { + return `${from}ā€“${to} of ${count !== -1 ? count : `more than ${to}`}`; +} + +function descendingComparator(a: T, b: T, orderBy: keyof T) { + if (b[orderBy] < a[orderBy]) { + return -1; + } + if (b[orderBy] > a[orderBy]) { + return 1; + } + return 0; +} + +type Order = 'asc' | 'desc'; + +function getComparator( + order: Order, + orderBy: Key, +): ( + a: { [key in Key]: number | string }, + b: { [key in Key]: number | string }, +) => number { + return order === 'desc' + ? (a, b) => descendingComparator(a, b, orderBy) + : (a, b) => -descendingComparator(a, b, orderBy); +} + +// Since 2020 all major browsers ensure sort stability with Array.prototype.sort(). +// stableSort() brings sort stability to non-modern browsers (notably IE11). If you +// only support modern browsers you can replace stableSort(exampleArray, exampleComparator) +// with exampleArray.slice().sort(exampleComparator) +function stableSort(array: readonly T[], comparator: (a: T, b: T) => number) { + const stabilizedThis = array.map((el, index) => [el, index] as [T, number]); + stabilizedThis.sort((a, b) => { + const order = comparator(a[0], b[0]); + if (order !== 0) { + return order; + } + return a[1] - b[1]; + }); + return stabilizedThis.map((el) => el[0]); +} + +interface HeadCell { + disablePadding: boolean; + id: keyof Data; + label: string; + numeric: boolean; +} + +const headCells: readonly HeadCell[] = [ + { + id: 'name', + numeric: false, + disablePadding: true, + label: 'DessertĀ (100g serving)', + }, + { + id: 'calories', + numeric: true, + disablePadding: false, + label: 'Calories', + }, + { + id: 'fat', + numeric: true, + disablePadding: false, + label: 'FatĀ (g)', + }, + { + id: 'carbs', + numeric: true, + disablePadding: false, + label: 'CarbsĀ (g)', + }, + { + id: 'protein', + numeric: true, + disablePadding: false, + label: 'ProteinĀ (g)', + }, +]; + +interface EnhancedTableProps { + numSelected: number; + onRequestSort: (event: React.MouseEvent, property: keyof Data) => void; + onSelectAllClick: (event: React.ChangeEvent) => void; + order: Order; + orderBy: string; + rowCount: number; +} + +function EnhancedTableHead(props: EnhancedTableProps) { + const { onSelectAllClick, order, orderBy, numSelected, rowCount, onRequestSort } = + props; + const createSortHandler = + (property: keyof Data) => (event: React.MouseEvent) => { + onRequestSort(event, property); + }; + + return ( + + + + 0 && numSelected < rowCount} + checked={rowCount > 0 && numSelected === rowCount} + onChange={onSelectAllClick} + slotProps={{ + input: { + 'aria-label': 'select all desserts', + }, + }} + sx={{ verticalAlign: 'sub' }} + /> + + {headCells.map((headCell) => { + const active = orderBy === headCell.id; + return ( + + {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} + + ) : null + } + endDecorator={ + !headCell.numeric ? ( + + ) : null + } + sx={{ + '& svg': { + transition: '0.2s', + transform: + active && order === 'desc' ? 'rotate(0deg)' : 'rotate(180deg)', + }, + '&:hover': { '& svg': { opacity: 1 } }, + }} + > + {headCell.label} + {active ? ( + + {order === 'desc' ? 'sorted descending' : 'sorted ascending'} + + ) : null} + + + ); + })} + + + ); +} + +interface EnhancedTableToolbarProps { + numSelected: number; +} + +function EnhancedTableToolbar(props: EnhancedTableToolbarProps) { + const { numSelected } = props; + + return ( + 0 && { + bgcolor: 'background.level1', + }), + borderTopLeftRadius: 'var(--internal-action-radius)', + borderTopRightRadius: 'var(--internal-action-radius)', + }} + > + {numSelected > 0 ? ( + + {numSelected} selected + + ) : ( + + Nutrition + + )} + + {numSelected > 0 ? ( + + + + + + ) : ( + + + + + + )} + + ); +} + +export default function TableSortAndSelection() { + const [order, setOrder] = React.useState('asc'); + const [orderBy, setOrderBy] = React.useState('calories'); + const [selected, setSelected] = React.useState([]); + const [page, setPage] = React.useState(0); + const [rowsPerPage, setRowsPerPage] = React.useState(5); + + const handleRequestSort = ( + event: React.MouseEvent, + property: keyof Data, + ) => { + const isAsc = orderBy === property && order === 'asc'; + setOrder(isAsc ? 'desc' : 'asc'); + setOrderBy(property); + }; + + const handleSelectAllClick = (event: React.ChangeEvent) => { + if (event.target.checked) { + const newSelected = rows.map((n) => n.name); + setSelected(newSelected); + return; + } + setSelected([]); + }; + + const handleClick = (event: React.MouseEvent, name: string) => { + const selectedIndex = selected.indexOf(name); + let newSelected: readonly string[] = []; + + if (selectedIndex === -1) { + newSelected = newSelected.concat(selected, name); + } else if (selectedIndex === 0) { + newSelected = newSelected.concat(selected.slice(1)); + } else if (selectedIndex === selected.length - 1) { + newSelected = newSelected.concat(selected.slice(0, -1)); + } else if (selectedIndex > 0) { + newSelected = newSelected.concat( + selected.slice(0, selectedIndex), + selected.slice(selectedIndex + 1), + ); + } + + setSelected(newSelected); + }; + + const handleChangePage = (newPage: number) => { + setPage(newPage); + }; + + const handleChangeRowsPerPage = (event: any, newValue: number | null) => { + setRowsPerPage(parseInt(newValue!.toString(), 10)); + setPage(0); + }; + + const getLabelDisplayedRowsTo = () => { + if (rows.length === -1) { + return (page + 1) * rowsPerPage; + } + return rowsPerPage === -1 + ? rows.length + : Math.min(rows.length, (page + 1) * rowsPerPage); + }; + + const isSelected = (name: string) => selected.indexOf(name) !== -1; + + // Avoid a layout jump when reaching the last page with empty rows. + const emptyRows = + page > 0 ? Math.max(0, (1 + page) * rowsPerPage - rows.length) : 0; + + return ( + + + + theme.vars.palette.info.softBg, + '& thead th:nth-child(1)': { + width: '40px', + }, + '& thead th:nth-child(2)': { + width: '30%', + }, + '& tr > *:nth-child(n+3)': { textAlign: 'right' }, + }} + > + + + {stableSort(rows, getComparator(order, orderBy)) + .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) + .map((row, index) => { + const isItemSelected = isSelected(row.name); + const labelId = `enhanced-table-checkbox-${index}`; + + return ( + handleClick(event, row.name)} + role="checkbox" + aria-checked={isItemSelected} + tabIndex={-1} + key={row.name} + // selected={isItemSelected} + style={ + isItemSelected + ? ({ + '--TableCell-dataBackground': + 'var(--TableCell-selectedBackground)', + '--TableCell-headBackground': + 'var(--TableCell-selectedBackground)', + } as React.CSSProperties) + : {} + } + > + + + + + + + + ); + })} + {emptyRows > 0 && ( + + + )} + + + + + + +
+ + + {row.name} + {row.calories}{row.fat}{row.carbs}{row.protein}
+
+ + + Rows per page: + + + + {labelDisplayedRows({ + from: rows.length === 0 ? 0 : page * rowsPerPage + 1, + to: getLabelDisplayedRowsTo(), + count: rows.length === -1 ? -1 : rows.length, + })} + + + handleChangePage(page - 1)} + sx={{ bgcolor: 'background.surface' }} + > + + + = Math.ceil(rows.length / rowsPerPage) - 1 + : false + } + onClick={() => handleChangePage(page + 1)} + sx={{ bgcolor: 'background.surface' }} + > + + + + +
+
+ ); +} diff --git a/docs/data/joy/components/table/TableStickyHeader.js b/docs/data/joy/components/table/TableStickyHeader.js new file mode 100644 index 00000000000000..2ce54f84ec6083 --- /dev/null +++ b/docs/data/joy/components/table/TableStickyHeader.js @@ -0,0 +1,59 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} +const rows = [ + createData('1', 159, 6.0, 24, 4.0), + createData('2', 237, 9.0, 37, 4.3), + createData('3', 262, 16.0, 24, 6.0), + createData('4', 305, 3.7, 67, 4.3), + createData('5', 356, 16.0, 49, 3.9), + createData('6', 159, 6.0, 24, 4.0), + createData('7', 237, 9.0, 37, 4.3), + createData('8', 262, 16.0, 24, 6.0), + createData('9', 305, 3.7, 67, 4.3), + createData('10', 356, 16.0, 49, 3.9), +]; + +export default function TableStickyHeader() { + return ( +
+ + The table body is scrollable. + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
RowCaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+
+ ); +} diff --git a/docs/data/joy/components/table/TableStickyHeader.tsx b/docs/data/joy/components/table/TableStickyHeader.tsx new file mode 100644 index 00000000000000..0dcb21a375f312 --- /dev/null +++ b/docs/data/joy/components/table/TableStickyHeader.tsx @@ -0,0 +1,65 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} +const rows = [ + createData('1', 159, 6.0, 24, 4.0), + createData('2', 237, 9.0, 37, 4.3), + createData('3', 262, 16.0, 24, 6.0), + createData('4', 305, 3.7, 67, 4.3), + createData('5', 356, 16.0, 49, 3.9), + createData('6', 159, 6.0, 24, 4.0), + createData('7', 237, 9.0, 37, 4.3), + createData('8', 262, 16.0, 24, 6.0), + createData('9', 305, 3.7, 67, 4.3), + createData('10', 356, 16.0, 49, 3.9), +]; + +export default function TableStickyHeader() { + return ( +
+ + The table body is scrollable. + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
RowCaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+
+ ); +} diff --git a/docs/data/joy/components/table/TableStripe.js b/docs/data/joy/components/table/TableStripe.js new file mode 100644 index 00000000000000..cb88dc157e0904 --- /dev/null +++ b/docs/data/joy/components/table/TableStripe.js @@ -0,0 +1,60 @@ +import * as React from 'react'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import RadioGroup from '@mui/joy/RadioGroup'; +import Radio from '@mui/joy/Radio'; +import Table from '@mui/joy/Table'; +import Sheet from '@mui/joy/Sheet'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableStripe() { + const [stripe, setStripe] = React.useState('odd'); + return ( + + + Stripe: + setStripe(event.target.value)} + > + + + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Dessert (100g serving)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableStripe.tsx b/docs/data/joy/components/table/TableStripe.tsx new file mode 100644 index 00000000000000..92f5e0b897ebc7 --- /dev/null +++ b/docs/data/joy/components/table/TableStripe.tsx @@ -0,0 +1,66 @@ +import * as React from 'react'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import RadioGroup from '@mui/joy/RadioGroup'; +import Radio from '@mui/joy/Radio'; +import Table from '@mui/joy/Table'; +import Sheet from '@mui/joy/Sheet'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableStripe() { + const [stripe, setStripe] = React.useState('odd'); + return ( + + + Stripe: + setStripe(event.target.value)} + > + + + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Dessert (100g serving)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableTextEllipsis.js b/docs/data/joy/components/table/TableTextEllipsis.js new file mode 100644 index 00000000000000..f7d664d36c5baf --- /dev/null +++ b/docs/data/joy/components/table/TableTextEllipsis.js @@ -0,0 +1,45 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Link from '@mui/joy/Link'; + +export default function TableTextEllipsis() { + return ( + + + + + + + + + + + + + + + + + +
Name + Description (you should see a part of this message) +
Morty D Ardiousdellois Addami + Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at + velit. Vivamus vel nulla eget eros elementum pellentesque. Quisque porta + volutpat erat. Quisque erat eros, viverra eget, congue eget, semper + rutrum, nulla. +
Joseph Morriso + + + In eleifend quam a odio + + . Suspendisse potenti in hac habitasse platea dictumst. + +
+ ); +} diff --git a/docs/data/joy/components/table/TableTextEllipsis.tsx b/docs/data/joy/components/table/TableTextEllipsis.tsx new file mode 100644 index 00000000000000..f7d664d36c5baf --- /dev/null +++ b/docs/data/joy/components/table/TableTextEllipsis.tsx @@ -0,0 +1,45 @@ +import * as React from 'react'; +import Table from '@mui/joy/Table'; +import Typography from '@mui/joy/Typography'; +import Link from '@mui/joy/Link'; + +export default function TableTextEllipsis() { + return ( + + + + + + + + + + + + + + + + + +
Name + Description (you should see a part of this message) +
Morty D Ardiousdellois Addami + Cras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at + velit. Vivamus vel nulla eget eros elementum pellentesque. Quisque porta + volutpat erat. Quisque erat eros, viverra eget, congue eget, semper + rutrum, nulla. +
Joseph Morriso + + + In eleifend quam a odio + + . Suspendisse potenti in hac habitasse platea dictumst. + +
+ ); +} diff --git a/docs/data/joy/components/table/TableUsage.js b/docs/data/joy/components/table/TableUsage.js new file mode 100644 index 00000000000000..1bf1fc6df373fe --- /dev/null +++ b/docs/data/joy/components/table/TableUsage.js @@ -0,0 +1,107 @@ +import * as React from 'react'; +import JoyUsageDemo from 'docs/src/modules/components/JoyUsageDemo'; +import Box from '@mui/joy/Box'; +import Table from '@mui/joy/Table'; +import Sheet from '@mui/joy/Sheet'; +import Typography from '@mui/joy/Typography'; + +export default function ButtonUsage() { + return ( + ( + + + The table is scrollable. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDJob TitleName
1DoctorChris Johnson
2ElectricianJoseph Morris
3OperatorAiden Moreno
4BakerMike Simmons
5ClerkEnoch Addison
+
+
+ )} + /> + ); +} diff --git a/docs/data/joy/components/table/TableVariables.js b/docs/data/joy/components/table/TableVariables.js new file mode 100644 index 00000000000000..4c617f3edc38b6 --- /dev/null +++ b/docs/data/joy/components/table/TableVariables.js @@ -0,0 +1,52 @@ +import * as React from 'react'; +import JoyVariablesDemo from 'docs/src/modules/components/JoyVariablesDemo'; +import Table from '@mui/joy/Table'; +import Sheet from '@mui/joy/Sheet'; + +export default function TableVariables() { + return ( + ( + + + + + + + + + + + + + + + + + + +
NameRole
AdamDeveloper
JosephManager
+
+ )} + /> + ); +} diff --git a/docs/data/joy/components/table/TableVariants.js b/docs/data/joy/components/table/TableVariants.js new file mode 100644 index 00000000000000..61b6231ba29ede --- /dev/null +++ b/docs/data/joy/components/table/TableVariants.js @@ -0,0 +1,94 @@ +import * as React from 'react'; + +import Box from '@mui/joy/Box'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; +import RadioGroup from '@mui/joy/RadioGroup'; +import Radio from '@mui/joy/Radio'; +import Table from '@mui/joy/Table'; + +function createData(name, calories, fat, carbs, protein) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableVariants() { + const [variant, setVariant] = React.useState('plain'); + const [color, setColor] = React.useState('neutral'); + return ( +
+ + + Variant: + setVariant(event.target.value)} + > + + + + + + + + Color: + + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Dessert (100g serving)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/TableVariants.tsx b/docs/data/joy/components/table/TableVariants.tsx new file mode 100644 index 00000000000000..bec3b79094ae23 --- /dev/null +++ b/docs/data/joy/components/table/TableVariants.tsx @@ -0,0 +1,100 @@ +import * as React from 'react'; +import { VariantProp, ColorPaletteProp } from '@mui/joy/styles'; +import Box from '@mui/joy/Box'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; +import RadioGroup from '@mui/joy/RadioGroup'; +import Radio from '@mui/joy/Radio'; +import Table from '@mui/joy/Table'; + +function createData( + name: string, + calories: number, + fat: number, + carbs: number, + protein: number, +) { + return { name, calories, fat, carbs, protein }; +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9), +]; + +export default function TableVariants() { + const [variant, setVariant] = React.useState('plain'); + const [color, setColor] = React.useState('neutral'); + return ( +
+ + + Variant: + setVariant(event.target.value as typeof variant)} + > + + + + + + + + Color: + + + + + + + + + + + + + + + {rows.map((row) => ( + + + + + + + + ))} + +
Dessert (100g serving)CaloriesFat (g)Carbs (g)Protein (g)
{row.name}{row.calories}{row.fat}{row.carbs}{row.protein}
+
+ ); +} diff --git a/docs/data/joy/components/table/table.md b/docs/data/joy/components/table/table.md new file mode 100644 index 00000000000000..603ca1b9ed174b --- /dev/null +++ b/docs/data/joy/components/table/table.md @@ -0,0 +1,288 @@ +--- +product: joy-ui +title: React Table component +githubLabel: 'component: table' +waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/table/ +--- + +# Table + +

Tables display sets of data organized in rows and columns.

+ +## Introduction + +The Joy UI Table component lets you use plain HTML structure to assemble a table in JSX. + +{{"demo": "TableUsage.js", "hideToolbar": true, "bg": "gradient"}} + +{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} + +## Basics + +Joy UI Table will apply the styles based on a table structure using ``, ``, and `` elements. + +```jsx +import Table from '@mui/joy/Table'; +``` + +{{"demo": "BasicTable.js"}} + +:::info +By default, **header** cells (``) contain the `surface` background color, whereas **data** cells (``) have no background. +::: + +## Customization + +### Column width + +Use the `sx` prop to target the header and provide the width as a number or percentage. + +Columns that don't have an explicit width will spread equally to fill the rest of the area. + +{{"demo": "TableColumnWidth.js"}} + +:::info +The Table component uses a [`fixed`](https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout) layout to let you control the width of each column. + +To learn more about why we take this approach, check out this article from Chris Coyier on [Fixed Table Layouts](https://css-tricks.com/fixing-tables-long-strings/). +::: + +#### Inline style + +An alternative way of controlling the column's width is to use [inline styles](https://reactjs.org/docs/dom-elements.html#style) on the `` element: + +```js + + + Column 1 + Column 2 + + +``` + +### Alignment + +Use the `sx` prop to target columns with the appropriate CSS selector and apply the [`text-align`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-align) property. + +```js +// target cells that are not the first in their respective rows. + *:not(:first-child)': { textAlign: 'right' } }}> +``` + +{{"demo": "TableAlignment.js"}} + +### Variants + +Table supports Joy UI's four [global variants](/joy-ui/main-features/global-variants/): `plain` (default), `outlined`, `soft`, and `solid`. + +{{"demo": "TableVariants.js"}} + +:::info +To learn how to add your own variants, check out [Themed componentsā€”Extend variants](/joy-ui/customization/themed-components/#extend-variants). +Note that you lose the global variants when you add custom variants. +::: + +### Sizes + +The component comes in three sizes: `sm`, `md` (default), and `lg`. + +{{"demo": "TableSizes.js"}} + +:::info +To learn how to add custom sizes to the component, check out [Themed componentsā€”Extend sizes](/joy-ui/customization/themed-components/#extend-sizes). +::: + +### Stripe + +To create constast between rows, use the `stripe` prop with `odd` or `even` values. + +{{"demo": "TableStripe.js"}} + +:::success + +The `stripe` prop supports complex arguments with the [`:nth-child()`](https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child#syntax) CSS selector. + +For example, you can use `3n` as a value to create stripes on row numbers three, six, nine, and so on: + +```js +
+``` + +::: + +### Hover + +To highlight a row of the table body when hovering over it, set the `hoverAxis` prop to true. + +{{"demo": "TableHover.js"}} + +### Border + +Use the `borderAxis` prop to control the border appearance. + +{{"demo": "TableBorder.js"}} + +#### Adding custom borders + +Customize the table theme based on `borderAxis` prop using the [`extendTheme()`](/joy-ui/customization/themed-components/#change-styles-based-on-props) function. + +```js +import { CssVarsProvider, extendTheme } from '@mui/joy/styles'; + +const theme = extendTheme({ + components: { + JoyTable: { + styleOverrides: { + root: ({ ownerState }) => ({ + ...(ownerState.borderAxis === 'header' && { + // this example applies borders between and + '& thead th:not([colspan])': { + borderBottom: '2px solid var(--TableCell-borderColor)', + }, + }), + }); + } + } + } +}) + +ā€¦ +``` + +For TypeScript, you have to add the new values via module augmentation: + +```ts +// this could be any file that's included in your tsconfig.json +declare module '@mui/joy/Table' { + interface TablePropsBorderAxisOverrides { + header: true; + } +} +``` + +### Sticky header + +Set the `stickyHeader` prop to true to make the header follow the user as they scroll down the page. + +:::success +For `stickyHeader` to work correctly, the Table must be a child of a fixed-height element with overflow `auto` (or `scroll`). +We recommend wrapping your Table with [Sheet](/joy-ui/react-sheet/) for this purpose. +See [usage with Sheet](#usage-with-sheet) to learn more. +::: + +{{"demo": "TableStickyHeader.js"}} + +### Caption + +Add a caption to summarize the contents of a Table by inserting a `
` element as the Table's first child. + +{{"demo": "TableCaption.js"}} + +:::success +To display a caption at the bottom of the Table, set the [caption side](https://developer.mozilla.org/en-US/docs/Web/CSS/caption-side) to `bottom`: + +```js + +``` + +::: + +### Footer + +Use [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot) to add a footer to the Table. + +{{"demo": "TableFooter.js"}} + +### Row head + +Set `scope="row"` to `` to apply the same style as column headers. +The demo below illustrates a common use case: setting the first column to match the header styles. + +{{"demo": "TableRowHead.js"}} + +### Row and column span + +Use `rowSpan` and `columnSpan` to expand a cell across multiple rows or columns. + +{{"demo": "TableRowColumnSpan.js"}} + +:::warning +Note that the CSS cannot figure out how apply borders on every corner without duplicating some. + +There are two workarounds: + +1. Manually remove the right border for a specific cell: + + ```js + // In this example, we remove the border from + // the right side of the header cell to avoid duplication. + + ``` + +2. Set Table's the border collapse to `collapse`: + + ```js +
` elements inside `
Canceled
+ // Note that this will change the behavior when `stickyHeader` is true: + // the bottom border of the sticky header will not "stick". + ``` + +::: + +### Text ellipsis + +To truncate the text, set `noWrap` to true. + +{{"demo": "TableTextEllipsis.js"}} + +:::info +The header cells always truncate the text to keep the header's height predictable. +::: + +## CSS variable playground + +Play around with the CSS variables available to the Table component to see how the design changes. +You can use these to customize the components with both the `sx` prop and the theme. + +{{"demo": "TableVariables.js"}} + +## Usage with Sheet + +import Sheet from `@mui/joy/Sheet` +When Table becomes a child of [Sheet](/joy-ui/react-sheet/) component, the table header background is inherited from the Sheet. + +{{"demo": "TableSheet.js"}} + +### Color inversion + +When [color inversion](/joy-ui/main-features/color-inversion/) is enabled, the Table's styles will adapt based on its [variant](#variants). + +{{"demo": "TableSheetColorInversion.js"}} + +## Common examples + +### Sort and selection + +Use form components such as [Button](/joy-ui/react-button/), [Select](/joy-ui/react-select/) and [Switch](/joy-ui/react-switch/) to create sort and selection features. + +{{"demo": "TableSortAndSelection.js"}} + +### First and last column pinning + +{{"demo": "TableColumnPinning.js"}} + +### Collapsible row + +{{"demo": "TableCollapsibleRow.js"}} + +### Applying global variants + +Use `theme.variants.*` to apply global variant styles to the Table. + +{{"demo": "TableGlobalVariant.js"}} + +### Scrolling shadows + +Inspired by this article from Lea Verou on [CSS scrolling shadows](https://lea.verou.me/2012/04/background-attachment-local/), the shadows appear and hide when scrolling on the Table. + +{{"demo": "TableScrollingShadows.js"}} diff --git a/docs/data/joy/components/tabs/TabsUnderlineExample.js b/docs/data/joy/components/tabs/TabsUnderlineExample.js new file mode 100644 index 00000000000000..fc54348b068310 --- /dev/null +++ b/docs/data/joy/components/tabs/TabsUnderlineExample.js @@ -0,0 +1,38 @@ +import * as React from 'react'; +import Tabs from '@mui/joy/Tabs'; +import TabList from '@mui/joy/TabList'; +import Tab, { tabClasses } from '@mui/joy/Tab'; + +export default function TabsUnderlineExample() { + return ( + + + Feature + Specifications + Review + Support + + + ); +} diff --git a/docs/data/joy/components/tabs/TabsUnderlineExample.tsx b/docs/data/joy/components/tabs/TabsUnderlineExample.tsx new file mode 100644 index 00000000000000..fc54348b068310 --- /dev/null +++ b/docs/data/joy/components/tabs/TabsUnderlineExample.tsx @@ -0,0 +1,38 @@ +import * as React from 'react'; +import Tabs from '@mui/joy/Tabs'; +import TabList from '@mui/joy/TabList'; +import Tab, { tabClasses } from '@mui/joy/Tab'; + +export default function TabsUnderlineExample() { + return ( + + + Feature + Specifications + Review + Support + + + ); +} diff --git a/docs/data/joy/components/tabs/TabsVertical.js b/docs/data/joy/components/tabs/TabsVertical.js index 5382103bb9550e..89f5a645637703 100644 --- a/docs/data/joy/components/tabs/TabsVertical.js +++ b/docs/data/joy/components/tabs/TabsVertical.js @@ -9,7 +9,6 @@ export default function TabsVertical() { @@ -17,13 +16,13 @@ export default function TabsVertical() { Second tab Third tab - + First tab panel - + Second tab panel - + Third tab panel diff --git a/docs/data/joy/components/tabs/TabsVertical.tsx b/docs/data/joy/components/tabs/TabsVertical.tsx index 5382103bb9550e..89f5a645637703 100644 --- a/docs/data/joy/components/tabs/TabsVertical.tsx +++ b/docs/data/joy/components/tabs/TabsVertical.tsx @@ -9,7 +9,6 @@ export default function TabsVertical() { @@ -17,13 +16,13 @@ export default function TabsVertical() { Second tab Third tab - + First tab panel - + Second tab panel - + Third tab panel diff --git a/docs/data/joy/components/tabs/tabs.md b/docs/data/joy/components/tabs/tabs.md index aa7ff5d3ba6566..f63627fba6c17a 100644 --- a/docs/data/joy/components/tabs/tabs.md +++ b/docs/data/joy/components/tabs/tabs.md @@ -56,6 +56,10 @@ To target the initially selected tab, specify the `value` prop to the `TabPanel` 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. +:::info +A selected `Tab` does not apply `:hover` and `:active` global variant styles. +::: + {{"demo": "TabsVariants.js"}} :::info @@ -116,6 +120,10 @@ You can use those to customize the component on both the `sx` prop and the theme ## Common examples +### Underline tabs + +{{"demo": "TabsUnderlineExample.js"}} + ### Pricing tabs {{"demo": "TabsPricingExample.js"}} diff --git a/docs/data/joy/components/text-field/TextFieldColors.js b/docs/data/joy/components/text-field/TextFieldColors.js deleted file mode 100644 index c197ceb1828d21..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldColors.js +++ /dev/null @@ -1,42 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldColors() { - return ( - - - - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldColors.tsx b/docs/data/joy/components/text-field/TextFieldColors.tsx deleted file mode 100644 index c197ceb1828d21..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldColors.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldColors() { - return ( - - - - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldComposition.js b/docs/data/joy/components/text-field/TextFieldComposition.js deleted file mode 100644 index 112e731c471acb..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldComposition.js +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import FormControl from '@mui/joy/FormControl'; -import FormLabel from '@mui/joy/FormLabel'; -import FormHelperText from '@mui/joy/FormHelperText'; -import Input from '@mui/joy/Input'; - -export default function TextFieldComposition() { - return ( - - Label - - This is a helper text. - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldComposition.tsx b/docs/data/joy/components/text-field/TextFieldComposition.tsx deleted file mode 100644 index 112e731c471acb..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldComposition.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import FormControl from '@mui/joy/FormControl'; -import FormLabel from '@mui/joy/FormLabel'; -import FormHelperText from '@mui/joy/FormHelperText'; -import Input from '@mui/joy/Input'; - -export default function TextFieldComposition() { - return ( - - Label - - This is a helper text. - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldComposition.tsx.preview b/docs/data/joy/components/text-field/TextFieldComposition.tsx.preview deleted file mode 100644 index 96205c163b0132..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldComposition.tsx.preview +++ /dev/null @@ -1,5 +0,0 @@ - - Label - - This is a helper text. - \ No newline at end of file diff --git a/docs/data/joy/components/text-field/TextFieldDecorators.js b/docs/data/joy/components/text-field/TextFieldDecorators.js deleted file mode 100644 index 039e621a93d0e1..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldDecorators.js +++ /dev/null @@ -1,31 +0,0 @@ -import * as React from 'react'; -import Stack from '@mui/joy/Stack'; -import TextField from '@mui/joy/TextField'; -import Chip from '@mui/joy/Chip'; -import PersonRoundedIcon from '@mui/icons-material/PersonRounded'; -import EditIcon from '@mui/icons-material/Edit'; -import CheckIcon from '@mui/icons-material/Check'; - -export default function TextFieldDecorator() { - return ( - - } - endDecorator={ - - New stuff - - } - /> - } - endDecorator={} - /> - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldDecorators.tsx b/docs/data/joy/components/text-field/TextFieldDecorators.tsx deleted file mode 100644 index 039e621a93d0e1..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldDecorators.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import * as React from 'react'; -import Stack from '@mui/joy/Stack'; -import TextField from '@mui/joy/TextField'; -import Chip from '@mui/joy/Chip'; -import PersonRoundedIcon from '@mui/icons-material/PersonRounded'; -import EditIcon from '@mui/icons-material/Edit'; -import CheckIcon from '@mui/icons-material/Check'; - -export default function TextFieldDecorator() { - return ( - - } - endDecorator={ - - New stuff - - } - /> - } - endDecorator={} - /> - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldFormProps.js b/docs/data/joy/components/text-field/TextFieldFormProps.js deleted file mode 100644 index 234fbe1c7e5b01..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldFormProps.js +++ /dev/null @@ -1,26 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldFormProps() { - return ( - - - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldFormProps.tsx b/docs/data/joy/components/text-field/TextFieldFormProps.tsx deleted file mode 100644 index 234fbe1c7e5b01..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldFormProps.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldFormProps() { - return ( - - - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldFormProps.tsx.preview b/docs/data/joy/components/text-field/TextFieldFormProps.tsx.preview deleted file mode 100644 index 4d65b24104290e..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldFormProps.tsx.preview +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/data/joy/components/text-field/TextFieldFullwidth.js b/docs/data/joy/components/text-field/TextFieldFullwidth.js deleted file mode 100644 index d3b5e22a5cfbe9..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldFullwidth.js +++ /dev/null @@ -1,11 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldFullWidth() { - return ( - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldFullwidth.tsx b/docs/data/joy/components/text-field/TextFieldFullwidth.tsx deleted file mode 100644 index d3b5e22a5cfbe9..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldFullwidth.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldFullWidth() { - return ( - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldFullwidth.tsx.preview b/docs/data/joy/components/text-field/TextFieldFullwidth.tsx.preview deleted file mode 100644 index d2406d8341f0f5..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldFullwidth.tsx.preview +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/data/joy/components/text-field/TextFieldSizes.js b/docs/data/joy/components/text-field/TextFieldSizes.js deleted file mode 100644 index 4a13aeb7435182..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldSizes.js +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldSizes() { - return ( - - - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldSizes.tsx b/docs/data/joy/components/text-field/TextFieldSizes.tsx deleted file mode 100644 index 4a13aeb7435182..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldSizes.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldSizes() { - return ( - - - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldSizes.tsx.preview b/docs/data/joy/components/text-field/TextFieldSizes.tsx.preview deleted file mode 100644 index bb1dfc9e32264c..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldSizes.tsx.preview +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/data/joy/components/text-field/TextFieldUsage.js b/docs/data/joy/components/text-field/TextFieldUsage.js deleted file mode 100644 index bef0dc3ef343ac..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldUsage.js +++ /dev/null @@ -1,51 +0,0 @@ -import * as React from 'react'; -import JoyUsageDemo from 'docs/src/modules/components/JoyUsageDemo'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldUsage() { - return ( - ( - - - - )} - /> - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldValidation.js b/docs/data/joy/components/text-field/TextFieldValidation.js deleted file mode 100644 index bd832ed2a13d12..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldValidation.js +++ /dev/null @@ -1,16 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldValidator() { - return ( - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldValidation.tsx b/docs/data/joy/components/text-field/TextFieldValidation.tsx deleted file mode 100644 index bd832ed2a13d12..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldValidation.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldValidator() { - return ( - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldValidation.tsx.preview b/docs/data/joy/components/text-field/TextFieldValidation.tsx.preview deleted file mode 100644 index 449a117d4cdd9a..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldValidation.tsx.preview +++ /dev/null @@ -1,6 +0,0 @@ - \ No newline at end of file diff --git a/docs/data/joy/components/text-field/TextFieldVariants.js b/docs/data/joy/components/text-field/TextFieldVariants.js deleted file mode 100644 index 0a62259e7de2fb..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldVariants.js +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldVariants() { - return ( - - - - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldVariants.tsx b/docs/data/joy/components/text-field/TextFieldVariants.tsx deleted file mode 100644 index 0a62259e7de2fb..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldVariants.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/joy/Box'; -import TextField from '@mui/joy/TextField'; - -export default function TextFieldVariants() { - return ( - - - - - - - ); -} diff --git a/docs/data/joy/components/text-field/TextFieldVariants.tsx.preview b/docs/data/joy/components/text-field/TextFieldVariants.tsx.preview deleted file mode 100644 index e9a252c68f4f13..00000000000000 --- a/docs/data/joy/components/text-field/TextFieldVariants.tsx.preview +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/docs/data/joy/components/text-field/text-field-pt.md b/docs/data/joy/components/text-field/text-field-pt.md deleted file mode 100644 index e2fc3ed7ca2ffb..00000000000000 --- a/docs/data/joy/components/text-field/text-field-pt.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -product: joy-ui -title: React Text field component -githubLabel: 'component: text field' -unstyled: /base/react-input/ ---- - -# Text field - -

Text fields let users enter and edit text.

- -## Introduction - -Text fields allow users to enter text into a UI. They typically appear in forms and dialogs. - -{{"demo": "TextFieldUsage.js"}} - -{{"component": "modules/components/ComponentLinkHeader.js"}} - -## Component - -After [installation](/joy-ui/getting-started/installation/), you can start building with this component using the following basic elements: - -```jsx -import TextField from '@mui/joy/TextField'; - -export default function MyApp() { - return ; -} -``` - -### Variants - -The text field component supports the four global variants: solid (default), soft, outlined, and plain. - -{{"demo": "TextFieldVariants.js"}} - -### Sizes - -The text field component comes with three sizes out of the box: `sm`, `md` (the default), and `lg`. - -{{"demo": "TextFieldSizes.js"}} - -### Colors - -Toggle the palette that's being used to color the by text field by using the `color` prop. - -{{"demo": "TextFieldColors.js"}} - -### Form props - -Standard form attributes are supported e.g. `required`, `disabled`, `type`, etc. as well as a `helperText` which is used to give context about a field's input, such as how the input will be used. - -{{"demo": "TextFieldFormProps.js"}} - -### Validation - -To toggle the error state, use the `error` prop. And, to provide feedback about the error to the user, use the `helperText` prop. - -{{"demo": "TextFieldValidation.js"}} - -### Input decorators - -Use the `startDecorator` and/or `endDecorator` props to add supporting icons or elements to the text field. - -{{"demo": "TextFieldDecorators.js"}} - -### Full width - -To make the text field take up the full width of its container, use the `fullWidth` prop. - -{{"demo": "TextFieldFullwidth.js"}} diff --git a/docs/data/joy/components/text-field/text-field-zh.md b/docs/data/joy/components/text-field/text-field-zh.md deleted file mode 100644 index e2fc3ed7ca2ffb..00000000000000 --- a/docs/data/joy/components/text-field/text-field-zh.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -product: joy-ui -title: React Text field component -githubLabel: 'component: text field' -unstyled: /base/react-input/ ---- - -# Text field - -

Text fields let users enter and edit text.

- -## Introduction - -Text fields allow users to enter text into a UI. They typically appear in forms and dialogs. - -{{"demo": "TextFieldUsage.js"}} - -{{"component": "modules/components/ComponentLinkHeader.js"}} - -## Component - -After [installation](/joy-ui/getting-started/installation/), you can start building with this component using the following basic elements: - -```jsx -import TextField from '@mui/joy/TextField'; - -export default function MyApp() { - return ; -} -``` - -### Variants - -The text field component supports the four global variants: solid (default), soft, outlined, and plain. - -{{"demo": "TextFieldVariants.js"}} - -### Sizes - -The text field component comes with three sizes out of the box: `sm`, `md` (the default), and `lg`. - -{{"demo": "TextFieldSizes.js"}} - -### Colors - -Toggle the palette that's being used to color the by text field by using the `color` prop. - -{{"demo": "TextFieldColors.js"}} - -### Form props - -Standard form attributes are supported e.g. `required`, `disabled`, `type`, etc. as well as a `helperText` which is used to give context about a field's input, such as how the input will be used. - -{{"demo": "TextFieldFormProps.js"}} - -### Validation - -To toggle the error state, use the `error` prop. And, to provide feedback about the error to the user, use the `helperText` prop. - -{{"demo": "TextFieldValidation.js"}} - -### Input decorators - -Use the `startDecorator` and/or `endDecorator` props to add supporting icons or elements to the text field. - -{{"demo": "TextFieldDecorators.js"}} - -### Full width - -To make the text field take up the full width of its container, use the `fullWidth` prop. - -{{"demo": "TextFieldFullwidth.js"}} diff --git a/docs/data/joy/components/text-field/text-field.md b/docs/data/joy/components/text-field/text-field.md index 5f7d8c11378b70..c3b2a2ac6c6ad8 100644 --- a/docs/data/joy/components/text-field/text-field.md +++ b/docs/data/joy/components/text-field/text-field.md @@ -2,80 +2,78 @@ product: joy-ui title: React Text Field component githubLabel: 'component: text field' -unstyled: /base/react-input/ --- # Text Field

Text fields let users enter and edit text.

-## Introduction +:::warning +**TextField** component has been removed in [`@mui/joy@5.0.0-alpha.63`](https://github.com/mui/material-ui/releases/tag/v5.11.5). We recommend using [`Input`](/joy-ui/react-input/), `FormControl` and `FormLabel` instead. -Text fields allow users to enter text into a UI. -They typically appear in forms and dialogs. +To learn more why it has been removed, visit the [RFC](https://github.com/mui/material-ui/issues/34176). +::: -{{"demo": "TextFieldUsage.js", "hideToolbar": true, "bg": "gradient"}} +## Migration -{{"component": "modules/components/ComponentLinkHeader.js"}} +### Codemod -## Component +Run this [codemod](https://github.com/mui/material-ui/blob/master/packages/mui-codemod/README.md#joy-text-field-to-input) in your project's terminal: -After [installation](/joy-ui/getting-started/installation/), you can start building with this component using the following basic elements: - -```jsx -import TextField from '@mui/joy/TextField'; - -export default function MyApp() { - return ; -} +```sh +npx @mui/codemod v5.0.0/joy-text-field-to-input ``` -### Composition - -`TextField` is composed of smallar componentsļ¼`FormControl`, `FormLabel`, `FormerHelperText`, and `Input`. -You can either use each one of them separately or plainly use the `TextField` itself. - -{{"demo": "TextFieldComposition.js"}} - -### Variants - -The text field component supports the four global variants: `solid` (default), `soft`, `outlined`, and `plain`. - -{{"demo": "TextFieldVariants.js"}} - -### Sizes - -The text field component comes with three sizes out of the box: `sm`, `md` (the default), and `lg`. - -{{"demo": "TextFieldSizes.js"}} - -### Colors - -Toggle the palette that's being used to color the by text field by using the `color` prop. - -{{"demo": "TextFieldColors.js"}} - -### Form props - -Standard form attributes are supported e.g. `required`, `disabled`, `type`, etc. as well as a `helperText` which is used to give context about a field's input, such as how the input will be used. - -{{"demo": "TextFieldFormProps.js"}} - -### Validation - -To toggle the error state, use the `error` prop. -And, to provide feedback about the error to the user, use the `helperText` prop. - -{{"demo": "TextFieldValidation.js"}} - -### Input decorators - -Use the `startDecorator` and/or `endDecorator` props to add supporting icons or elements to the text field. - -{{"demo": "TextFieldDecorators.js"}} - -### Full width - -To make the text field take up the full width of its container, use the `fullWidth` prop. - -{{"demo": "TextFieldFullwidth.js"}} +It will go through all files under `` and replace `` with the `` composition. + +### Manual + +Replace the `TextField` with composition: + +```diff +-import TextField from '@mui/joy/TextField'; ++import FormControl from '@mui/joy/FormControl'; ++import FormLabel from '@mui/joy/FormLabel'; ++import FormHelperText from '@mui/joy/FormHelperText'; ++import Input from '@mui/joy/Input'; + +- ++ ++ ++ Label ++ ++ ++ ++ Help! ++ ++ +``` diff --git a/docs/data/joy/components/typography/typography.md b/docs/data/joy/components/typography/typography.md index a9725e20ea6783..1936cc9d95900f 100644 --- a/docs/data/joy/components/typography/typography.md +++ b/docs/data/joy/components/typography/typography.md @@ -27,7 +27,7 @@ export default function MyApp() { ### System props -As a CSS utility component, `Typography` supports every [`system`](/system/properties/) properties. +As a CSS utility component, `Typography` supports every [`system`](/system/properties/) property. ```jsx diff --git a/docs/data/joy/customization/approaches/approaches-pt.md b/docs/data/joy/customization/approaches/approaches-pt.md index 2ebe5a2868d3d8..1c4cd947480a93 100644 --- a/docs/data/joy/customization/approaches/approaches-pt.md +++ b/docs/data/joy/customization/approaches/approaches-pt.md @@ -96,6 +96,6 @@ function MyApp() { Creating new and custom components is always an option when you don't find exactly what you're looking for. You can, however, ensure design consistency with other Joy UI components by pulling styles from the theme through the `styled` function. -You also gain as beenfit the ability to use the `sx` prop, that also accept theme tokens, to customize this newly created component. +You also gain the ability to use the `sx` prop, which also accepts theme tokens, to customize this newly created component. {{"demo": "StyledComponent.js"}} diff --git a/docs/data/joy/customization/approaches/approaches-zh.md b/docs/data/joy/customization/approaches/approaches-zh.md index 2ebe5a2868d3d8..1c4cd947480a93 100644 --- a/docs/data/joy/customization/approaches/approaches-zh.md +++ b/docs/data/joy/customization/approaches/approaches-zh.md @@ -96,6 +96,6 @@ function MyApp() { Creating new and custom components is always an option when you don't find exactly what you're looking for. You can, however, ensure design consistency with other Joy UI components by pulling styles from the theme through the `styled` function. -You also gain as beenfit the ability to use the `sx` prop, that also accept theme tokens, to customize this newly created component. +You also gain the ability to use the `sx` prop, which also accepts theme tokens, to customize this newly created component. {{"demo": "StyledComponent.js"}} diff --git a/docs/data/joy/customization/approaches/approaches.md b/docs/data/joy/customization/approaches/approaches.md index ed79a29b517c6c..08b2ffd02142df 100644 --- a/docs/data/joy/customization/approaches/approaches.md +++ b/docs/data/joy/customization/approaches/approaches.md @@ -25,7 +25,7 @@ Here are some examples that reproduce popular designs (only the light mode, thou ### Customizing theme tokens -Theme tokens refer to both [_low-level_ and _global variant_ design tokens](/joy-ui/customization/theme-tokens/). +Theme tokens refer to both _low-level_ and _global variant_ design tokens. For example, instead of assigning the same hex code every time you want to change a given component's background color, you assign a theme token instead. If, at any point, you want to change that, you'd change in one place only, ensuring you consistency across all the components that use that theme token. @@ -80,10 +80,12 @@ const theme = extendTheme({ components: { // The component identifier always start with `Joy${ComponentName}`. JoyButton: { - styleOverrides: ({ theme }) => ({ - // theme.vars.* return the CSS variables. - fontSize: theme.vars.fontSize.lg, // 'var(--joy-fontSize-lg)' - }), + styleOverrides: { + root: ({ theme }) => { + // theme.vars.* return the CSS variables. + fontSize: theme.vars.fontSize.lg, // 'var(--joy-fontSize-lg)' + }, + }, }, }, }); @@ -102,6 +104,6 @@ function MyApp() { Creating new and custom components is always an option when you don't find exactly what you're looking for. You can, however, ensure design consistency with other Joy UI components by pulling styles from the theme through the `styled` function. -You also gain as beenfit the ability to use the `sx` prop, that also accept theme tokens, to customize this newly created component. +You also gain the ability to use the `sx` prop, which also accepts theme tokens, to customize this newly created component. {{"demo": "StyledComponent.js"}} diff --git a/docs/data/joy/customization/dark-mode/dark-mode.md b/docs/data/joy/customization/dark-mode/dark-mode.md index c68553ee66470e..1720637972e3da 100644 --- a/docs/data/joy/customization/dark-mode/dark-mode.md +++ b/docs/data/joy/customization/dark-mode/dark-mode.md @@ -6,6 +6,10 @@ To set dark mode as the default for your app, add `defaultMode: 'dark'` to your `` wrapper component: +:::warning +When you change the `defaultMode` to another value, you must clear the local storage for it to take effect. +::: + {{"demo": "DarkModeByDefault.js"}} For server-side applications, check out the framework setup in [the section below](#server-side-rendering) and provide the same value to the `getInitColorSchemeScript` function: diff --git a/docs/data/joy/customization/default-theme-viewer/JoyDefaultTheme.js b/docs/data/joy/customization/default-theme-viewer/JoyDefaultTheme.js new file mode 100644 index 00000000000000..7b83d51ed7c326 --- /dev/null +++ b/docs/data/joy/customization/default-theme-viewer/JoyDefaultTheme.js @@ -0,0 +1,52 @@ +import * as React from 'react'; +import { extendTheme } from '@mui/joy/styles'; +import Box from '@mui/joy/Box'; +import { ThemeProvider, createTheme } from '@mui/material/styles'; +import ThemeViewer, { + useNodeIdsLazy, +} from 'docs/src/modules/components/ThemeViewer'; + +const defaultTheme = extendTheme(); + +export default function JoyDefaultTheme() { + const [expandPaths, setExpandPaths] = React.useState(null); + + React.useEffect(() => { + let expandPath; + decodeURI(document.location.search.slice(1)) + .split('&') + .forEach((param) => { + const [name, value] = param.split('='); + if (name === 'expand-path') { + expandPath = value; + } + }); + + if (!expandPath) { + return; + } + + setExpandPaths( + expandPath + .replace('$.', '') + .split('.') + .reduce((acc, path) => { + const last = acc.length > 0 ? `${acc[acc.length - 1]}.` : ''; + acc.push(last + path); + return acc; + }, []), + ); + }, []); + + const data = defaultTheme; + const allNodeIds = useNodeIdsLazy(data); + React.useDebugValue(allNodeIds); + + return ( + + createTheme()}> + + + + ); +} diff --git a/docs/data/joy/customization/default-theme-viewer/default-theme-viewer.md b/docs/data/joy/customization/default-theme-viewer/default-theme-viewer.md new file mode 100644 index 00000000000000..73e3bff69c90d8 --- /dev/null +++ b/docs/data/joy/customization/default-theme-viewer/default-theme-viewer.md @@ -0,0 +1,15 @@ +# Default theme viewer + +

Here's what the theme object looks like with the default values.

+ +:::warning +This is a work in progress. We're still iterating on Joy UI's default theme. +::: + +## Explore + +Explore the default theme: + +{{"demo": "JoyDefaultTheme.js", "hideToolbar": true, "bg": "inline"}} + +To create your own theme, starts with customizing the [theme colors](/joy-ui/customization/theme-colors/). diff --git a/docs/data/joy/customization/default-theme/default-theme-pt.md b/docs/data/joy/customization/default-theme/default-theme-pt.md deleted file mode 100644 index b2c7f16bbd37c5..00000000000000 --- a/docs/data/joy/customization/default-theme/default-theme-pt.md +++ /dev/null @@ -1,100 +0,0 @@ -# Default Theme - -

Here's what the theme object looks like with the default values.

- -:::warning -**āš ļø Work in progress:** we're still iterating on the whole Joy UI default theme. -::: - -**Typography-related:** - -```js -extendTheme({ - fontSize: { - xs: '0.75rem', - sm: '0.875rem', - md: '1rem', - lg: '1.25rem', - xl: '1.5rem', - xl2: '1.875rem', - xl3: '2.25rem', - xl4: '3rem', - xl5: '3.75rem', - xl6: '4.5rem', - }, -}); -``` - -```js -extendTheme({ - fontFamily: { - body: '"Public Sans", var(--joy-fontFamily-fallback)', - display: '"Public Sans", var(--joy-fontFamily-fallback)', - code: 'Source Code Pro,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace', - fallback: - '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', - }, -}); -``` - -```js -extendTheme({ - fontWeight: { - xs: 200, - sm: 300, - md: 500, - lg: 700, - xl: 800, - }, -}); -``` - -```js -extendTheme({ - lineHeight: { - sm: 1.25, - md: 1.5, - lg: 1.7, - }, -}); -``` - -```js -extendTheme({ - letterSpacing: { - sm: '-0.01em', - md: '0.083em', - lg: '0.125em', - }, -}); -``` - -```js -extendTheme({ - radius: { - xs: '4px', - sm: '8px', - md: '12px', - lg: '16px', - xl: '20px', - }, -}); -} -``` - -**Box shadows:** - -All the shadows are listed [here](https://github.com/mui/material-ui/blob/master/packages/mui-joy/src/styles/types/shadow.ts). We recommend to use `var(--joy-shadowRing)` and `var(--joy-shadowChannel)` for creating the shadows because you can customize the shadow color on the component. - -```js -extendTheme({ - shadows: { - // default tokens - xs: 'var(--joy-shadowRing), 0 1px 2px 0 rgba(var(--joy-shadowChannel) / 0.12)', - sm: '...', - md: '...', - lg: '...', - xl: '...', - }, -}); -``` diff --git a/docs/data/joy/customization/default-theme/default-theme-zh.md b/docs/data/joy/customization/default-theme/default-theme-zh.md deleted file mode 100644 index b2c7f16bbd37c5..00000000000000 --- a/docs/data/joy/customization/default-theme/default-theme-zh.md +++ /dev/null @@ -1,100 +0,0 @@ -# Default Theme - -

Here's what the theme object looks like with the default values.

- -:::warning -**āš ļø Work in progress:** we're still iterating on the whole Joy UI default theme. -::: - -**Typography-related:** - -```js -extendTheme({ - fontSize: { - xs: '0.75rem', - sm: '0.875rem', - md: '1rem', - lg: '1.25rem', - xl: '1.5rem', - xl2: '1.875rem', - xl3: '2.25rem', - xl4: '3rem', - xl5: '3.75rem', - xl6: '4.5rem', - }, -}); -``` - -```js -extendTheme({ - fontFamily: { - body: '"Public Sans", var(--joy-fontFamily-fallback)', - display: '"Public Sans", var(--joy-fontFamily-fallback)', - code: 'Source Code Pro,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace', - fallback: - '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', - }, -}); -``` - -```js -extendTheme({ - fontWeight: { - xs: 200, - sm: 300, - md: 500, - lg: 700, - xl: 800, - }, -}); -``` - -```js -extendTheme({ - lineHeight: { - sm: 1.25, - md: 1.5, - lg: 1.7, - }, -}); -``` - -```js -extendTheme({ - letterSpacing: { - sm: '-0.01em', - md: '0.083em', - lg: '0.125em', - }, -}); -``` - -```js -extendTheme({ - radius: { - xs: '4px', - sm: '8px', - md: '12px', - lg: '16px', - xl: '20px', - }, -}); -} -``` - -**Box shadows:** - -All the shadows are listed [here](https://github.com/mui/material-ui/blob/master/packages/mui-joy/src/styles/types/shadow.ts). We recommend to use `var(--joy-shadowRing)` and `var(--joy-shadowChannel)` for creating the shadows because you can customize the shadow color on the component. - -```js -extendTheme({ - shadows: { - // default tokens - xs: 'var(--joy-shadowRing), 0 1px 2px 0 rgba(var(--joy-shadowChannel) / 0.12)', - sm: '...', - md: '...', - lg: '...', - xl: '...', - }, -}); -``` diff --git a/docs/data/joy/customization/default-theme/default-theme.md b/docs/data/joy/customization/default-theme/default-theme.md deleted file mode 100644 index 574b97e7610123..00000000000000 --- a/docs/data/joy/customization/default-theme/default-theme.md +++ /dev/null @@ -1,101 +0,0 @@ -# Default theme - -

Here's what the theme object looks like with the default values.

- -:::warning -This is a work in progress. We're still iterating on Joy UI's default theme. -::: - -**Typography-related:** - -```js -extendTheme({ - fontSize: { - xs: '0.75rem', - sm: '0.875rem', - md: '1rem', - lg: '1.25rem', - xl: '1.5rem', - xl2: '1.875rem', - xl3: '2.25rem', - xl4: '3rem', - xl5: '3.75rem', - xl6: '4.5rem', - }, -}); -``` - -```js -extendTheme({ - fontFamily: { - body: '"Public Sans", var(--joy-fontFamily-fallback)', - display: '"Public Sans", var(--joy-fontFamily-fallback)', - code: 'Source Code Pro,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace', - fallback: - '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', - }, -}); -``` - -```js -extendTheme({ - fontWeight: { - xs: 200, - sm: 300, - md: 500, - lg: 700, - xl: 800, - }, -}); -``` - -```js -extendTheme({ - lineHeight: { - sm: 1.25, - md: 1.5, - lg: 1.7, - }, -}); -``` - -```js -extendTheme({ - letterSpacing: { - sm: '-0.01em', - md: '0.083em', - lg: '0.125em', - }, -}); -``` - -```js -extendTheme({ - radius: { - xs: '4px', - sm: '8px', - md: '12px', - lg: '16px', - xl: '20px', - }, -}); -} -``` - -**Box shadows:** - -All the shadows are listed [here](https://github.com/mui/material-ui/blob/master/packages/mui-joy/src/styles/types/shadow.ts). -We recommend to use `var(--joy-shadowRing)` and `var(--joy-shadowChannel)` for creating the shadows because you can customize the shadow color on the component. - -```js -extendTheme({ - shadows: { - // default tokens - xs: 'var(--joy-shadowRing), 0 1px 2px 0 rgba(var(--joy-shadowChannel) / 0.12)', - sm: '...', - md: '...', - lg: '...', - xl: '...', - }, -}); -``` diff --git a/docs/data/joy/customization/theme-tokens/BootstrapVariantTokens.js b/docs/data/joy/customization/theme-colors/BootstrapVariantTokens.js similarity index 100% rename from docs/data/joy/customization/theme-tokens/BootstrapVariantTokens.js rename to docs/data/joy/customization/theme-colors/BootstrapVariantTokens.js diff --git a/docs/data/joy/customization/theme-colors/PaletteThemeViewer.js b/docs/data/joy/customization/theme-colors/PaletteThemeViewer.js new file mode 100644 index 00000000000000..0cc6fab730583d --- /dev/null +++ b/docs/data/joy/customization/theme-colors/PaletteThemeViewer.js @@ -0,0 +1,236 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import * as React from 'react'; +import useClipboardCopy from 'docs/src/modules/utils/useClipboardCopy'; +import { extendTheme, styled } from '@mui/joy/styles'; +import Box from '@mui/joy/Box'; +import Link from '@mui/joy/Link'; +import Tooltip from '@mui/joy/Tooltip'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; +import LightMode from '@mui/icons-material/LightModeOutlined'; +import DarkMode from '@mui/icons-material/DarkModeOutlined'; +import InfoOutlined from '@mui/icons-material/InfoOutlined'; +import Check from '@mui/icons-material/Check'; + +const defaultTheme = extendTheme(); + +const traverseObject = (palette) => { + const result = {}; + const traverse = (object, parts = []) => { + if (object && typeof object === 'object') { + // eslint-disable-next-line no-restricted-syntax + for (const key of Object.keys(object)) { + traverse(object[key], [...parts, key]); + } + } else { + result[parts.join('.')] = object; + } + }; + traverse(palette); + return result; +}; + +// https://stackoverflow.com/a/38641281/559913 +const collator = new Intl.Collator(undefined, { + numeric: true, + sensitivity: 'base', +}); + +const Table = styled('table')(({ theme }) => ({ + border: '1px solid', + borderColor: theme.vars.palette.divider, + borderRadius: theme.vars.radius.xs, + borderCollapse: 'separate', + borderSpacing: 0, + display: 'block', + height: 500, + overflowY: 'scroll', + th: { + textAlign: 'left', + padding: '8px 6px', + position: 'sticky', + top: 0, + zIndex: 1, + ...theme.variants.soft.neutral, + }, + td: { + verticalAlign: 'top', + padding: '3px 6px', + }, + tr: { + '&:hover': { + backgroundColor: theme.vars.palette.background.level1, + }, + '&:first-of-type': { + '& td': { paddingTop: 6 }, + }, + }, +})); + +export default function PaletteThemeViewer() { + const { copy, isCopied } = useClipboardCopy(); + const light = traverseObject(defaultTheme.colorSchemes.light.palette); + const dark = traverseObject(defaultTheme.colorSchemes.dark.palette); + const paletteTokens = Array.from( + new Set([...Object.keys(dark), ...Object.keys(light)]), + ).sort(collator.compare); + const renderSwatch = (colorScheme, token) => ( + + ); + + return ( + + + }> + Copied + + +
+ + + + + + + + + {paletteTokens + .filter((token) => token !== 'mode') + .map((token) => ( + + + + + + ))} + +
+ + Token + + + } + textColor="inherit" + > + Light + + + } + textColor="inherit" + > + Dark + +
+ copy(token)} + endDecorator={ + light[token].match(/^[0-9]+\s[0-9]+\s[0-9]+$/) ? ( + + Translucent color usage:
+ + rgba(var(--joy-palette-{token.replace('.', '-')}) / + 0.6) + + + } + sx={{ pointerEvents: 'none' }} + > + +
+ ) : null + } + sx={{ cursor: 'copy' }} + > + {token} + +
+ copy(light[token])} + > + {light[token]} + + + copy(dark[token])} + > + {dark[token]} + +
+ + ); +} diff --git a/docs/data/joy/customization/theme-colors/PaletteThemeViewer.tsx b/docs/data/joy/customization/theme-colors/PaletteThemeViewer.tsx new file mode 100644 index 00000000000000..623ccb0de59d37 --- /dev/null +++ b/docs/data/joy/customization/theme-colors/PaletteThemeViewer.tsx @@ -0,0 +1,235 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import * as React from 'react'; +import useClipboardCopy from 'docs/src/modules/utils/useClipboardCopy'; +import { extendTheme, Palette, styled } from '@mui/joy/styles'; +import Box from '@mui/joy/Box'; +import Link from '@mui/joy/Link'; +import Tooltip from '@mui/joy/Tooltip'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; +import LightMode from '@mui/icons-material/LightModeOutlined'; +import DarkMode from '@mui/icons-material/DarkModeOutlined'; +import InfoOutlined from '@mui/icons-material/InfoOutlined'; +import Check from '@mui/icons-material/Check'; + +const defaultTheme = extendTheme(); + +const traverseObject = (palette: Palette) => { + const result: Record = {}; + const traverse = (object: any, parts: string[] = []) => { + if (object && typeof object === 'object') { + // eslint-disable-next-line no-restricted-syntax + for (const key of Object.keys(object)) { + traverse(object[key], [...parts, key]); + } + } else { + result[parts.join('.')] = object; + } + }; + traverse(palette); + return result; +}; + +// https://stackoverflow.com/a/38641281/559913 +const collator = new Intl.Collator(undefined, { + numeric: true, + sensitivity: 'base', +}); + +const Table = styled('table')(({ theme }) => ({ + border: '1px solid', + borderColor: theme.vars.palette.divider, + borderRadius: theme.vars.radius.xs, + borderCollapse: 'separate', + borderSpacing: 0, + display: 'block', + height: 500, + overflowY: 'scroll', + th: { + textAlign: 'left', + padding: '8px 6px', + position: 'sticky', + top: 0, + zIndex: 1, + ...theme.variants.soft.neutral, + }, + td: { + verticalAlign: 'top', + padding: '3px 6px', + }, + tr: { + '&:hover': { + backgroundColor: theme.vars.palette.background.level1, + }, + '&:first-of-type': { + '& td': { paddingTop: 6 }, + }, + }, +})); + +export default function PaletteThemeViewer() { + const { copy, isCopied } = useClipboardCopy(); + const light = traverseObject(defaultTheme.colorSchemes.light.palette); + const dark = traverseObject(defaultTheme.colorSchemes.dark.palette); + const paletteTokens = Array.from( + new Set([...Object.keys(dark), ...Object.keys(light)]), + ).sort(collator.compare); + const renderSwatch = (colorScheme: 'light' | 'dark', token: string) => ( + + ); + return ( + + + }> + Copied + + + + + + + + + + + + {paletteTokens + .filter((token) => token !== 'mode') + .map((token) => ( + + + + + + ))} + +
+ + Token + + + } + textColor="inherit" + > + Light + + + } + textColor="inherit" + > + Dark + +
+ copy(token)} + endDecorator={ + light[token].match(/^[0-9]+\s[0-9]+\s[0-9]+$/) ? ( + + Translucent color usage:
+ + rgba(var(--joy-palette-{token.replace('.', '-')}) / + 0.6) + + + } + sx={{ pointerEvents: 'none' }} + > + +
+ ) : null + } + sx={{ cursor: 'copy' }} + > + {token} + +
+ copy(light[token])} + > + {light[token]} + + + copy(dark[token])} + > + {dark[token]} + +
+
+ ); +} diff --git a/docs/data/joy/customization/theme-tokens/RemoveActiveTokens.js b/docs/data/joy/customization/theme-colors/RemoveActiveTokens.js similarity index 100% rename from docs/data/joy/customization/theme-tokens/RemoveActiveTokens.js rename to docs/data/joy/customization/theme-colors/RemoveActiveTokens.js diff --git a/docs/data/joy/customization/theme-colors/theme-colors.md b/docs/data/joy/customization/theme-colors/theme-colors.md new file mode 100644 index 00000000000000..0413fb059dd664 --- /dev/null +++ b/docs/data/joy/customization/theme-colors/theme-colors.md @@ -0,0 +1,284 @@ +# Theme colors + +

Learn about the theme's default colors and how to customize them.

+ +## Default tokens + +The table below lists all the default tokens and their values in light and dark color schemes. +Some tokens reuse values from other tokens using the [`var(--*)`](https://developer.mozilla.org/en-US/docs/Web/CSS/var) syntax. + +{{"demo": "PaletteThemeViewer.js", "bg": "inline"}} + +### Channel tokens + +The default tokens ending with `Channel` are automatically generated for each palette. +These tokens are useful for creating translucent colors (`rgba`). + +- `lightChannel`: is generated from the palette's `200` token. +- `mainChannel`: is generated from the palette's `500` token. +- `darkChannel`: is generated from the palette's `800` token. + +The example usage is: + +```js +import Typography from '@mui/joy/Typography'; + + ({ + color: `rgba(${theme.vars.palette.primary.mainChannel} / 0.72)`, + })} +> +``` + +### Global variant tokens + +By default, Joy UI has four built-in [global variants](/joy-ui/main-features/global-variants/) tokens: `plain`, `outlined`, `soft`, and `solid`. + +The global variant token is composed of three parts, in the format of **variant type | state | CSS property**. + +For example: + +- `solidBg` refers to the solid variant's background color in its initial state. +- `outlinedHoverBorder` refers to the outlined variant's border color in its hover state. + +There are six palettes (`primary`, `neutral`, `danger`, `info`, `success`, and `warning`) that contain the global variant tokens as listed in the [table above](#default-tokens). + +## Customizing the default palette + +For each color scheme, the default colors are grouped within the `palette` node. + +For example, the snippet below customizes the primary palette in dark mode: + +```js +import { extendTheme } from '@mui/joy/styles'; + +const theme = extendTheme({ + colorSchemes: { + dark: { + palette: { + primary: { + 50: '#C0CCD9', + 100: '#A5B8CF', + 200: '#6A96CA', + 300: '#4886D0', + 400: '#2178DD', + 500: '#096BDE', + 600: '#1B62B5', + 700: '#265995', + 800: '#2F4968', + 900: '#2F3C4C', + }, + }, + }, + }, +}); + +// Then, pass it to ``. +``` + +## Customizing global variant tokens + +We recommend using the [Button](/joy-ui/react-button/) component as a jumping-off point when customizing the global variants, because it gives you access to more of the interactive variants available than some other components. + +As an example, let's customize Joy UI's Button so to match the style of [Bootstrap](https://getbootstrap.com/docs/5.2/components/buttons/#examples): + +- Bootstrap's default buttons are comparable to Joy UI's `solid` variant. +- Bootstrap's `secondary` variant uses a grey color, similar to Joy UI's `neutral`. +- Bootstrap's `btn-light` is similar to Joy UI's button using the `soft` variant and `neutral` color palette. +- Joy UI's defaults don't include anything similar to Bootstrap's `btn-dark`. + - We can recreate it using one of the three main customization approaches. + +{{"demo": "BootstrapVariantTokens.js"}} + +:::info +Customizing the global variant tokens affects all Joy UI components that support the `variant` prop. +::: + +## Removing the default tokens + +To remove any default token, use `undefined` as a value. +This removes it from the `theme` object and prevents the corresponding CSS variable from being generated. + +For example, all default global variant tokens comes with styles for the `:active` pseudo class. +Here's how you'd remove it from the solid variant. + +```jsx +// āš ļø If the value is `undefined`, it should be `undefined` for all color schemes. +const theme = extendTheme({ + colorSchemes: { + light: { + palette: { + primary: { + solidActiveBg: undefined, + }, + }, + }, + dark: { + palette: { + primary: { + solidActiveBg: undefined, + }, + }, + }, + }, +}); +``` + +{{"demo": "RemoveActiveTokens.js"}} + +## Adding more colors + +Any custom tokens that you add to theme are available for use with both the `styled` and `sx` APIs. + +```js +extendTheme({ + colorSchemes: { + light: { + palette: { + // Example of new color tokens. + // We recommend to limit them to 3 levels deepļ¼in this case: + // `palette.gradient.primary`. + gradient: { + primary: 'linear-gradient(to top, var(--joy-palette-primary-main), #000)', + }, + }, + }, + }, +}); + +// `sx` prop usage example: + + ); +} diff --git a/docs/data/joy/customization/theme-shadow/CustomShadowOnElement.tsx b/docs/data/joy/customization/theme-shadow/CustomShadowOnElement.tsx new file mode 100644 index 00000000000000..831e154568b7df --- /dev/null +++ b/docs/data/joy/customization/theme-shadow/CustomShadowOnElement.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import Button from '@mui/joy/Button'; + +export default function CustomShadowOnElement() { + return ( + + ); +} diff --git a/docs/data/joy/customization/theme-shadow/ShadowThemeViewer.js b/docs/data/joy/customization/theme-shadow/ShadowThemeViewer.js new file mode 100644 index 00000000000000..977f6e7a821717 --- /dev/null +++ b/docs/data/joy/customization/theme-shadow/ShadowThemeViewer.js @@ -0,0 +1,154 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import * as React from 'react'; +import useClipboardCopy from 'docs/src/modules/utils/useClipboardCopy'; +import { styled, extendTheme } from '@mui/joy/styles'; +import Box from '@mui/joy/Box'; +import Link from '@mui/joy/Link'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; +import LightMode from '@mui/icons-material/LightModeOutlined'; +import DarkMode from '@mui/icons-material/DarkModeOutlined'; +import Check from '@mui/icons-material/CheckCircle'; + +const Table = styled('table')(({ theme }) => ({ + border: '1px solid', + borderColor: theme.vars.palette.divider, + borderRadius: theme.vars.radius.xs, + borderCollapse: 'separate', + borderSpacing: 0, + width: '100%', + overflowY: 'scroll', + th: { + textAlign: 'left', + padding: 12, + position: 'sticky', + top: 0, + zIndex: 1, + ...theme.variants.soft.neutral, + }, + td: { + verticalAlign: 'top', + padding: '8px 12px', + }, + tr: { + '&:hover': { + backgroundColor: theme.vars.palette.background.level1, + }, + '&:first-of-type': { + '& td': { paddingTop: 6 }, + }, + }, +})); +const defaultTheme = extendTheme(); + +export default function ShadowThemeViewer() { + const { copy, isCopied } = useClipboardCopy(); + const tokens = Object.keys(defaultTheme.shadow); + const formatShadowLayers = (shadow) => + React.Children.toArray( + shadow + .split(', ') + .reduce( + (result, curr, index, array) => + array.length - 1 !== index + ? [...result, `${curr},`,
] + : [...result, curr], + [], + ), + ); + + return ( + + + }> + Copied + + + + + + + + + + + + + {tokens.map((token) => ( + + + + + + + ))} + +
+ Token + + Value + + }> + Light + + + }> + Dark + +
+ {token} + + copy(token)} + > + {formatShadowLayers(defaultTheme.shadow[token])} + + + theme.shadow[token], + borderRadius: 'xs', + mr: 2, + }} + /> + + theme.shadow[token], + borderRadius: 'xs', + }} + /> +
+
+ ); +} diff --git a/docs/data/joy/customization/theme-shadow/ShadowThemeViewer.tsx b/docs/data/joy/customization/theme-shadow/ShadowThemeViewer.tsx new file mode 100644 index 00000000000000..7adba3da08e703 --- /dev/null +++ b/docs/data/joy/customization/theme-shadow/ShadowThemeViewer.tsx @@ -0,0 +1,153 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import * as React from 'react'; +import useClipboardCopy from 'docs/src/modules/utils/useClipboardCopy'; +import { styled, extendTheme, Shadow } from '@mui/joy/styles'; +import Box from '@mui/joy/Box'; +import Link from '@mui/joy/Link'; +import Typography from '@mui/joy/Typography'; +import Sheet from '@mui/joy/Sheet'; +import LightMode from '@mui/icons-material/LightModeOutlined'; +import DarkMode from '@mui/icons-material/DarkModeOutlined'; +import Check from '@mui/icons-material/CheckCircle'; + +const Table = styled('table')(({ theme }) => ({ + border: '1px solid', + borderColor: theme.vars.palette.divider, + borderRadius: theme.vars.radius.xs, + borderCollapse: 'separate', + borderSpacing: 0, + width: '100%', + overflowY: 'scroll', + th: { + textAlign: 'left', + padding: 12, + position: 'sticky', + top: 0, + zIndex: 1, + ...theme.variants.soft.neutral, + }, + td: { + verticalAlign: 'top', + padding: '8px 12px', + }, + tr: { + '&:hover': { + backgroundColor: theme.vars.palette.background.level1, + }, + '&:first-of-type': { + '& td': { paddingTop: 6 }, + }, + }, +})); +const defaultTheme = extendTheme(); + +export default function ShadowThemeViewer() { + const { copy, isCopied } = useClipboardCopy(); + const tokens = Object.keys(defaultTheme.shadow) as Array; + const formatShadowLayers = (shadow: string) => + React.Children.toArray( + shadow + .split(', ') + .reduce>( + (result, curr, index, array) => + array.length - 1 !== index + ? [...result, `${curr},`,
] + : [...result, curr], + [], + ), + ); + return ( + + + }> + Copied + + + + + + + + + + + + + {tokens.map((token) => ( + + + + + + + ))} + +
+ Token + + Value + + }> + Light + + + }> + Dark + +
+ {token} + + copy(token)} + > + {formatShadowLayers(defaultTheme.shadow[token])} + + + theme.shadow[token], + borderRadius: 'xs', + mr: 2, + }} + /> + + theme.shadow[token], + borderRadius: 'xs', + }} + /> +
+
+ ); +} diff --git a/docs/data/joy/customization/theme-shadow/theme-shadow.md b/docs/data/joy/customization/theme-shadow/theme-shadow.md new file mode 100644 index 00000000000000..99c03c08c49591 --- /dev/null +++ b/docs/data/joy/customization/theme-shadow/theme-shadow.md @@ -0,0 +1,158 @@ +# Theme shadow + +

Learn about the theme's default shadow and how to customize it.

+ +## Default tokens + +Joy UI uses a T-shirt scale (sm, md, lg, etc.) for defining shadows used by components such as [Card](/joy-ui/react-card/), [Menu](/joy-ui/react-menu/), and more. + +These tokens are grouped inside the `theme.shadow` node: + +{{"demo": "ShadowThemeViewer.js", "bg": "inline"}} + +## Customizing the default shadow + +Provide key-values to the `shadow` node to override the default shadows: + +```js +import { extendTheme } from '@mui/joy/styles'; + +const theme = extendTheme({ + shadow: { + xs: '{CSS box-shadow}', + sm: '{CSS box-shadow}', + md: '{CSS box-shadow}', + lg: '{CSS box-shadow}', + xl: '{CSS box-shadow}', + }, +}); + +// Then, pass it to ``. +``` + +:::success +We recommend using `var(--joy-shadowRing)` and `var(--joy-shadowChannel)` for shadow values, similar to the [default token value](#default-tokens). +::: + +## Adding new shadows + +You can add any custom keys to the `shadow` node: + +```js +import { extendTheme } from '@mui/joy/styles'; + +const theme = extendTheme({ + shadow: { + subtle: '{CSS box-shadow}', + strong: '{CSS box-shadow}', + }, +}); + +// Then, pass it to ``. +``` + +### TypeScript + +When working in TypeScript, you need to augment the theme's `Shadow` interface with the new keys: + +```ts +// You can put this to any file that's included in your tsconfig +declare module '@mui/joy/styles' { + interface Shadow { + subtle: string; + strong: string; + } +} +``` + +## Shadow ring + +The shadow ring can be configured for both light and dark color schemes. +To create a shadow ring, provide a valid CSS box-shadow value to the `shadowRing` node: + +```js +import { extendTheme } from '@mui/joy/styles'; + +const theme = extendTheme({ + colorSchemes: { + light: { + // This creates a 1px box-shadow. + shadowRing: '0 0 0 1px rgba(0 0 0 / 0.1)', + }, + dark: { + shadowChannel: '0 0 0 1px rgba(255 255 255 / 0.1)', + }, + }, +}); + +// Then, pass it to ``. +``` + +:::warning +Customizing the theme's shadow ring will affect all Joy UI components that consume the theme's shadows. + +If you want to create a shadow ring for a specific element, see [Customizing shadows on an element](#customizing-shadows-on-an-element). +::: + +## Shadow colors + +The color of the shadow comes from the theme token named `var(--joy-shadowChannel)`. +You can customize the value for both light and dark color schemes: + +```js +import { extendTheme } from '@mui/joy/styles'; + +const theme = extendTheme({ + colorSchemes: { + light: { + shadowChannel: '12 12 12', + }, + dark: { + shadowChannel: '0 0 0', + }, + }, +}); + +// Then, pass it to ``. +``` + +:::warning +The `shadowChannel` value must be rgb channels, e.g. `187 187 187`. +::: + +## Customizing shadows on an element + +To customize a shadow color or shadow ring on a specific instance, use the raw value from the `theme.shadow.*`. + +:::warning +**Don't** use shadows from `theme.vars` or the shorthand syntax `{ shadow: '{key}' }` because the value points to the global CSS variable which does not work with the custom `shadowChannel` and `shadowRing` on the instance. +::: + +```js +// āœ… + - - The shadow applied - -
- - - - No custom shadow - - - - - ); -} diff --git a/docs/data/joy/customization/theme-tokens/theme-tokens-pt.md b/docs/data/joy/customization/theme-tokens/theme-tokens-pt.md deleted file mode 100644 index a9352acfdae468..00000000000000 --- a/docs/data/joy/customization/theme-tokens/theme-tokens-pt.md +++ /dev/null @@ -1,355 +0,0 @@ -# Theme tokens - -

Learn about the two categories of tokens within Joy UI's default theme and how to customize them.

- -The [W3C Community Group](https://github.com/design-tokens/community-group) defines design tokens as: _"...indivisible pieces of a design system such as colors, spacing, typography scale."_ Joy UI builds up on this concept to develop its theme, consisting of two categories: low-level and global variant tokens. - -## Low-level tokens - -Low-level tokens refer to the smallest units of style that defines the look and feel Joy UI has out-of-the-box. They're labeled as _low-level_ because they can be used to compose larger tokens, such as the typography scale. - -### Structure - -Joy UI's default theme has three main categories of low-level design tokens: - -1. Color -2. Typography -3. Shape-related - -#### Color - -The first theme node within the color category is `colorSchemes`. It houses the `light` and `dark` nodes, and inside each one of them, there is a `palette` node, containing the [global variant tokens](#global-variant-tokens) adjusted for both modes. - -```js -colorSchemes: { - light: { - palette: { - primary: { - plainColor: 'valid CSS color', - plainHoverBg: 'valid CSS color', - plainActiveBg: 'valid CSS color', - }, - neutral: {...}, - ... - }, - }, - dark: { - palette: { - primary: { - plainColor: 'valid CSS color', - plainHoverBg: 'valid CSS color', - plainActiveBg: 'valid CSS color', - }, - neutral: {...}, - ... - }, - }, -} -``` - -Visit the [ColorSystem interface](https://github.com/mui/material-ui/blob/master/packages/mui-joy/src/styles/types/colorSystem.ts#L142) to see all of the available interfaces. - -#### Channel tokens - -The tokens ended with `Channel` are automatically generated from the provided theme unless you explicitly specify them. These tokens are useful for creating translucent (alpha) colors. - -```js -import Typography from '@mui/joy/Typography'; - - ({ - color: `rgba(${theme.vars.palette.primary.mainChannel} / 0.72)`, - })} -> -``` - -#### Typography - -Within the typography-related tokens, there are first the ones that map out to common CSS typography properties: - -```js -fontSize: {...}, -fontFamily: {...}, -fontWeight: {...}, -lineHeight: {...}, -letterSpacing: {...}, -``` - -They're then used to build up Joy UI's typographic scale: - -```js -typography: { - h1: { - fontFamily: 'var(--joy-fontFamily-display)', - fontWeight: 'var(--joy-fontWeight-lg)' as CSSProperties['fontWeight'], - fontSize: 'var(--joy-fontSize-xl4)', - lineHeight: 'var(--joy-lineHeight-sm)', - letterSpacing: 'var(--joy-letterSpacing-sm)', - color: 'var(--joy-palette-text-primary)', - }, - h2: {...}, - h3: {...}, - ... -} -``` - -#### Shape - -The two main theme nodes related to shape elements are: - -```js -radius: {...}, -shadow: {...}, -``` - -### Overriding low-level tokens - -To customize the theme's low-level design tokens, use the `extendTheme` API to create a new theme and then pass it to the `CssVarsProvider`. The specified tokens will be deeply merged into the default values. - -```js -import { CssVarsProvider, extendTheme } from '@mui/joy/styles'; - -const theme = extendTheme({ - colorSchemes: { - light: { - palette: { - background: { - // palette.neutral.50 is the default token - body: 'var(--joy-palette-neutral-50)', - }, - }, - }, - }, -}); - -function App() { - return ...; -} -``` - -:::info -**Note**: Joy UI will add the prefix (default as `joy`) to all CSS variables. To change it, use ``. and the generated CSS variables will then be: - -```diff -- --joy-palette-primary-50: /* color */ ; -+ --myproduct-palette-primary-50: /* color */ ; -``` - -::: - -### Adding low-level tokens - -You can add any custom tokens to the theme and still be able to use them in APIs like `styled` and `sx` prop. - -```ts -extendTheme({ - colorSchemes: { - light: { - palette: { - // Example of new color tokens. - // We recommend to limit them to 3 levels deepļ¼in this case `palette.brand.primary`. - brand: { - primary: 'green', - secondary: 'red', - }, - }, - }, - }, -}); -``` - -For **TypeScript**, you need to augment the theme structure to include the new tokens. - -```ts -import { CssVarsProvider, extendTheme } from '@mui/joy/styles'; - -declare module '@mui/joy/styles' { - interface Palette { - brand: { - primary: string; - secondary: string; - }; - } -} -``` - -After that, you can use those tokens in the `styled` function or the `sx` prop: - -```jsx -// sx prop - Sign up} diff --git a/docs/data/joy/getting-started/tutorial/tutorial-pt.md b/docs/data/joy/getting-started/tutorial/tutorial-pt.md index 3d617a69f43ff1..faeb189c137be3 100644 --- a/docs/data/joy/getting-started/tutorial/tutorial-pt.md +++ b/docs/data/joy/getting-started/tutorial/tutorial-pt.md @@ -88,13 +88,15 @@ import Typography from '@mui/joy/Typography'; ; ``` -### 4. Using `TextField` to create user name and password inputs +### 4. Using `FormControl`, `FormLabel` and `Input` to create user name and password inputs -The `TextField` component is made of the `FormLabel`, `Input` and `FormHelperText` components. +The `FormControl`, `FormLabel` and `Input` components can be used together to provide you with a sophisticated field for user input. ```jsx // ...other imports -import TextField from '@mui/joy/TextField'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import Input from '@mui/joy/Input'; ...typography - - + + Email + + + + Password + + ; ``` diff --git a/docs/data/joy/getting-started/tutorial/tutorial-zh.md b/docs/data/joy/getting-started/tutorial/tutorial-zh.md index 3d617a69f43ff1..faeb189c137be3 100644 --- a/docs/data/joy/getting-started/tutorial/tutorial-zh.md +++ b/docs/data/joy/getting-started/tutorial/tutorial-zh.md @@ -88,13 +88,15 @@ import Typography from '@mui/joy/Typography'; ; ``` -### 4. Using `TextField` to create user name and password inputs +### 4. Using `FormControl`, `FormLabel` and `Input` to create user name and password inputs -The `TextField` component is made of the `FormLabel`, `Input` and `FormHelperText` components. +The `FormControl`, `FormLabel` and `Input` components can be used together to provide you with a sophisticated field for user input. ```jsx // ...other imports -import TextField from '@mui/joy/TextField'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import Input from '@mui/joy/Input'; ...typography - - + + Email + + + + Password + + ; ``` diff --git a/docs/data/joy/getting-started/tutorial/tutorial.md b/docs/data/joy/getting-started/tutorial/tutorial.md index 72649be3d90539..1cf167cb0a5181 100644 --- a/docs/data/joy/getting-started/tutorial/tutorial.md +++ b/docs/data/joy/getting-started/tutorial/tutorial.md @@ -118,33 +118,38 @@ Try changing the values for the `level` and `component` props to see how they af (Note that while `level` only accepts the 13 values listed above, you can pass any HTML tag to `component`, as well as custom React components.) ::: -## Add Text Field for user inputs +## Add text field for user inputs -The [Text Field](/joy-ui/react-text-field/) component bundles together the Form Control, Form Label, Input, and Form Helper Text components to provide you with a sophisticated field for user input. +The Form Control, Form Label, and Input components can be used together to provide you with a sophisticated field for user input. -Add an import for Text Field with the rest of your imports: +Add imports for Form Control, Form Label, and Input with the rest of your imports: ```jsx -import TextField from '@mui/joy/TextField'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; +import Input from '@mui/joy/Input'; ``` -Insert these two Text Fields below the `
` from the previous step, inside the Sheet: +Insert these two text fields below the `
` from the previous step, inside the Sheet: ```jsx - - + + Email + + + + Password + + ``` ## Import Button and Link for user actions @@ -158,7 +163,7 @@ import Button from '@mui/joy/Button'; import Link from '@mui/joy/Link'; ``` -Add the following Button, Typography, and Link components after the Text Fields from the previous step, still nested inside the Sheet. +Add the following Button, Typography, and Link components after the text fields from the previous step, still nested inside the Sheet. Notice that the Link is appended to the Typography inside of [the `endDecorator` prop](/joy-ui/react-typography/#decorators): ```jsx @@ -238,7 +243,6 @@ Here's a recap of the components used: - [Typography](/joy-ui/react-typography/) - [Button](/joy-ui/react-button/) - [Link](/joy-ui/react-link/) -- [Text Field](/joy-ui/react-text-field/) Here are some of the major features introduced: diff --git a/docs/data/joy/guides/using-icon-libraries/using-icon-libraries.md b/docs/data/joy/guides/using-icon-libraries/using-icon-libraries.md index 9b01caf7f7bc18..bc445510a62954 100644 --- a/docs/data/joy/guides/using-icon-libraries/using-icon-libraries.md +++ b/docs/data/joy/guides/using-icon-libraries/using-icon-libraries.md @@ -18,7 +18,7 @@ yarn add @mui/icons-material @mui/material ``` :::warning -Because `@mui/material` is a required dependency of `@mui/icons-material`, you have add a workaround with yarn resolutions: +Because `@mui/material` is a required dependency of `@mui/icons-material`, you have to add a workaround with yarn resolutions: ```json { diff --git a/docs/data/joy/guides/using-joy-ui-and-material-ui/using-joy-ui-and-material-ui.md b/docs/data/joy/guides/using-joy-ui-and-material-ui/using-joy-ui-and-material-ui.md index cefb154dbf6199..8c2eb13bac0ad9 100644 --- a/docs/data/joy/guides/using-joy-ui-and-material-ui/using-joy-ui-and-material-ui.md +++ b/docs/data/joy/guides/using-joy-ui-and-material-ui/using-joy-ui-and-material-ui.md @@ -25,13 +25,16 @@ For this case, the Material UI theme should override the Joy UI's. ```js import { deepmerge } from '@mui/utils'; import { - useColorScheme, Experimental_CssVarsProvider as CssVarsProvider, experimental_extendTheme as extendMuiTheme, + shouldSkipGeneratingVar as muiShouldSkipGeneratingVar, } from '@mui/material/styles'; -import { extendTheme as extendJoyTheme } from '@mui/joy/styles'; +import { + extendTheme as extendJoyTheme, + shouldSkipGeneratingVar as joyShouldSkipGeneratingVar, +} from '@mui/joy/styles'; -const joyTheme = extendJoyTheme({ +const { unstable_sxConfig: joySxConfig, ...joyTheme } = extendTheme({ // This is required to point to `var(--mui-*)` because we are using // `CssVarsProvider` from Material UI. cssVarPrefix: 'mui', @@ -83,15 +86,27 @@ const joyTheme = extendJoyTheme({ // Note: you can't put `joyTheme` inside Material UI's `extendMuiTheme(joyTheme)` // because some of the values in the Joy UI theme refers to CSS variables and // not raw colors. -const muiTheme = extendMuiTheme(); +const { unstable_sxConfig: muiSxConfig, ...muiTheme } = extendMuiTheme(); // You can use your own `deepmerge` function. // muiTheme will deeply merge to joyTheme. -const theme = deepmerge(joyTheme, muiTheme); +const mergedTheme = (deepmerge(joyTheme, muiTheme) as unknown) as ReturnType< + typeof extendMuiTheme +>; + +mergedTheme.unstable_sxConfig = { + ...joySxConfig, + ...muiSxConfig +}; export default function App() { return ( - + + muiShouldSkipGeneratingVar(keys) || joyShouldSkipGeneratingVar(keys) + } + > ...Material UI and Joy UI components ); @@ -110,15 +125,18 @@ This setup uses the `CssVarsProvider` component from Joy UI and configures the M ```js import { deepmerge } from '@mui/utils'; -import { experimental_extendTheme as extendMuiTheme } from '@mui/material/styles'; +import { + experimental_extendTheme as extendMuiTheme, + shouldSkipGeneratingVar as muiShouldSkipGeneratingVar, +} from '@mui/material/styles'; import colors from '@mui/joy/colors'; import { extendTheme as extendJoyTheme, CssVarsProvider, - useColorScheme, + shouldSkipGeneratingVar as joyShouldSkipGeneratingVar, } from '@mui/joy/styles'; -const muiTheme = extendMuiTheme({ +const { unstable_sxConfig: muiSxConfig, ...muiTheme } = extendMuiTheme({ // This is required to point to `var(--joy-*)` because we are using // `CssVarsProvider` from Joy UI. cssVarPrefix: 'joy', @@ -184,15 +202,27 @@ const muiTheme = extendMuiTheme({ }, }); -const joyTheme = extendJoyTheme(); +const { unstable_sxConfig: joySxConfig, ...joyTheme} = extendJoyTheme(); // You can use your own `deepmerge` function. // joyTheme will deeply merge to muiTheme. -const theme = deepmerge(muiTheme, joyTheme); +const mergedTheme = (deepmerge(muiTheme, joyTheme) as unknown) as ReturnType< + typeof extendJoyTheme +>; + +mergedTheme.unstable_sxConfig = { + ...muiSxConfig, + ...joySxConfig +}; export default function App() { return ( - + + muiShouldSkipGeneratingVar(keys) || joyShouldSkipGeneratingVar(keys) + } + > ...Material UI and Joy UI components ); @@ -287,3 +317,32 @@ declare module '@mui/material/styles' { } } ``` + +## Caveat + +Both libraries have the same class name prefix: + +```js +import MaterialTypography, { + typographyClasses as muiTypographyClasses, +} from '@mui/material/Typography'; +import JoyTypography, { + typographyClasses as joyTyographyClasses, +} from '@mui/joy/Typography'; +import Stack from '@mui/material/Stack'; + + + {/* Both components are red. */} + Red + Red +; +``` + +However, the class name prefix are the same diff --git a/docs/data/joy/main-features/automatic-adjustment/InputVariables.js b/docs/data/joy/main-features/automatic-adjustment/InputVariables.js index b8f0c5b5d74245..419758d1bbb8e6 100644 --- a/docs/data/joy/main-features/automatic-adjustment/InputVariables.js +++ b/docs/data/joy/main-features/automatic-adjustment/InputVariables.js @@ -3,7 +3,8 @@ import Box from '@mui/joy/Box'; import Button from '@mui/joy/Button'; import ListDivider from '@mui/joy/ListDivider'; import Input from '@mui/joy/Input'; -import TextField from '@mui/joy/TextField'; +import FormControl from '@mui/joy/FormControl'; +import FormLabel from '@mui/joy/FormLabel'; export default function InputIntegration() { const [radius, setRadius] = React.useState(16); @@ -25,20 +26,24 @@ export default function InputIntegration() { /> - setRadius(event.target.valueAsNumber)} - /> - setChildHeight(event.target.valueAsNumber)} - /> + + --Input-radius + setRadius(event.target.valueAsNumber)} + /> + + + --Input-childHeight + setChildHeight(event.target.valueAsNumber)} + /> + ); diff --git a/docs/data/joy/main-features/automatic-adjustment/automatic-adjustment-pt.md b/docs/data/joy/main-features/automatic-adjustment/automatic-adjustment-pt.md index 9ee0cd60277167..9098f20474df0a 100644 --- a/docs/data/joy/main-features/automatic-adjustment/automatic-adjustment-pt.md +++ b/docs/data/joy/main-features/automatic-adjustment/automatic-adjustment-pt.md @@ -2,7 +2,7 @@

Joy UI components adapt to one another when composed together to ensure the best look and feel.

-When composing a UI of multiple, especially nested, components, oftentime you get small inconsistencies between them. That's probably when you'll be adjusting pixels by a few nudges here and there to get them just right. Over time, these small and arbitrary changes build up to become a problem. +When composing a UI of multiple, especially nested, components, oftentimes you get small inconsistencies between them. That's probably when you'll be adjusting pixels by a few nudges here and there to get them just right. Over time, these small and arbitrary changes build up to become a problem. That's why we've built Joy UI to heavily rely on CSS variables, assigning to them the heavy lifting for these small adjustments. It saves you time and ensures consistency. Let's look through a few examples: diff --git a/docs/data/joy/main-features/automatic-adjustment/automatic-adjustment-zh.md b/docs/data/joy/main-features/automatic-adjustment/automatic-adjustment-zh.md index 9ee0cd60277167..9098f20474df0a 100644 --- a/docs/data/joy/main-features/automatic-adjustment/automatic-adjustment-zh.md +++ b/docs/data/joy/main-features/automatic-adjustment/automatic-adjustment-zh.md @@ -2,7 +2,7 @@

Joy UI components adapt to one another when composed together to ensure the best look and feel.

-When composing a UI of multiple, especially nested, components, oftentime you get small inconsistencies between them. That's probably when you'll be adjusting pixels by a few nudges here and there to get them just right. Over time, these small and arbitrary changes build up to become a problem. +When composing a UI of multiple, especially nested, components, oftentimes you get small inconsistencies between them. That's probably when you'll be adjusting pixels by a few nudges here and there to get them just right. Over time, these small and arbitrary changes build up to become a problem. That's why we've built Joy UI to heavily rely on CSS variables, assigning to them the heavy lifting for these small adjustments. It saves you time and ensures consistency. Let's look through a few examples: diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionFooter.js b/docs/data/joy/main-features/color-inversion/ColorInversionFooter.js index c3bf3ed2a24486..c7f5674aca9db4 100644 --- a/docs/data/joy/main-features/color-inversion/ColorInversionFooter.js +++ b/docs/data/joy/main-features/color-inversion/ColorInversionFooter.js @@ -113,7 +113,12 @@ export default function ColorInversionFooter() { - + Sitemap diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionFooter.tsx b/docs/data/joy/main-features/color-inversion/ColorInversionFooter.tsx index a975030b428dcc..b1e7213a9f22df 100644 --- a/docs/data/joy/main-features/color-inversion/ColorInversionFooter.tsx +++ b/docs/data/joy/main-features/color-inversion/ColorInversionFooter.tsx @@ -112,7 +112,12 @@ export default function ColorInversionFooter() { - + Sitemap diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.js b/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.js index af8b73ae0a42f0..afdca626ad4982 100644 --- a/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.js +++ b/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.js @@ -108,7 +108,7 @@ export default function ColorInversionNavigation() { - + 35% diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.tsx b/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.tsx index af8b73ae0a42f0..afdca626ad4982 100644 --- a/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.tsx +++ b/docs/data/joy/main-features/color-inversion/ColorInversionNavigation.tsx @@ -108,7 +108,7 @@ export default function ColorInversionNavigation() { - + 35% diff --git a/docs/data/joy/main-features/color-inversion/ColorInversionPopup.js b/docs/data/joy/main-features/color-inversion/ColorInversionPopup.js index 0c9ad35decc01e..5b95fd98280f9a 100644 --- a/docs/data/joy/main-features/color-inversion/ColorInversionPopup.js +++ b/docs/data/joy/main-features/color-inversion/ColorInversionPopup.js @@ -27,7 +27,7 @@ export default function ColorInversionPopup() { const [menuButton, setMenuButton] = React.useState(null); return ( (null); return ( An alert displays a short, important message in a way that attracts the user's attention without interrupting the user's task.

-**Note:** This component is not documented in the [Material Design guidelines](https://m2.material.io/), but MUI supports it. +:::info +This component is not documented in the [Material Design guidelines](https://m2.material.io/), but it is available in Material UI. +::: {{"component": "modules/components/ComponentLinkHeader.js"}} diff --git a/docs/data/material/components/autocomplete/Virtualize.js b/docs/data/material/components/autocomplete/Virtualize.js index 9d98972465277a..29b76273b03c07 100644 --- a/docs/data/material/components/autocomplete/Virtualize.js +++ b/docs/data/material/components/autocomplete/Virtualize.js @@ -29,7 +29,7 @@ function renderRow(props) { return ( - {dataSet[1]} + {`#${dataSet[2] + 1} - ${dataSet[1]}`} ); } @@ -146,7 +146,7 @@ export default function Virtualize() { options={OPTIONS} groupBy={(option) => option[0].toUpperCase()} renderInput={(params) => } - renderOption={(props, option) => [props, option]} + 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 5fdcb8224811ee..c9c0755904f28e 100644 --- a/docs/data/material/components/autocomplete/Virtualize.tsx +++ b/docs/data/material/components/autocomplete/Virtualize.tsx @@ -28,7 +28,7 @@ function renderRow(props: ListChildComponentProps) { return ( - {dataSet[1]} + {`#${dataSet[2] + 1} - ${dataSet[1]}`} ); } @@ -146,7 +146,9 @@ export default function Virtualize() { options={OPTIONS} groupBy={(option) => option[0].toUpperCase()} renderInput={(params) => } - renderOption={(props, option) => [props, option] as React.ReactNode} + 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} /> diff --git a/docs/data/material/components/autocomplete/Virtualize.tsx.preview b/docs/data/material/components/autocomplete/Virtualize.tsx.preview index c7b94cecd14f73..906d629e7ed941 100644 --- a/docs/data/material/components/autocomplete/Virtualize.tsx.preview +++ b/docs/data/material/components/autocomplete/Virtualize.tsx.preview @@ -7,7 +7,9 @@ options={OPTIONS} groupBy={(option) => option[0].toUpperCase()} renderInput={(params) => } - renderOption={(props, option) => [props, option] as React.ReactNode} + 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} /> \ No newline at end of file diff --git a/docs/data/material/components/click-away-listener/click-away-listener.md b/docs/data/material/components/click-away-listener/click-away-listener.md index f11266598ad2bd..4b58066bf7f91c 100644 --- a/docs/data/material/components/click-away-listener/click-away-listener.md +++ b/docs/data/material/components/click-away-listener/click-away-listener.md @@ -9,11 +9,11 @@ githubLabel: 'component: ClickAwayListener'

The Click-Away Listener component detects when a click event happens outside of its child element.

-## MUI Base +## This document has moved + +:::warning +Please refer to the [Click-Away Listener](/base/react-click-away-listener/) component page in the MUI Base docs for demos and details on usage. -:::info Click-Away Listener is a part of the standalone [MUI Base](/base/getting-started/overview/) component library. It is currently re-exported from `@mui/material` for your convenience, but it will be removed from this package in a future major version, after `@mui/base` gets a stable release. - -Please refer to the [Click-Away Listener](/base/react-click-away-listener/) component page in the MUI Base docs for examples and details on usage. ::: diff --git a/docs/data/material/components/lists/lists.md b/docs/data/material/components/lists/lists.md index 532313cf19720d..7e08aaebc83a3d 100644 --- a/docs/data/material/components/lists/lists.md +++ b/docs/data/material/components/lists/lists.md @@ -102,7 +102,7 @@ Virtualization helps with performance issues. {{"demo": "VirtualizedList.js", "bg": true}} The use of [react-window](https://github.com/bvaughn/react-window) when possible is encouraged. -If this library doesn't cover your use case, you should consider using [react-virtualized](https://github.com/bvaughn/react-virtualized), then alternatives like [react-virtuoso](https://github.com/petyosi/react-virtuoso). +If this library doesn't cover your use case, you should consider using alternatives like [react-virtuoso](https://github.com/petyosi/react-virtuoso). ## Customization diff --git a/docs/data/material/components/menus/AccountMenu.js b/docs/data/material/components/menus/AccountMenu.js index 8e67439c924eb6..bfcc715e02ca11 100644 --- a/docs/data/material/components/menus/AccountMenu.js +++ b/docs/data/material/components/menus/AccountMenu.js @@ -74,26 +74,26 @@ export default function AccountMenu() { transformOrigin={{ horizontal: 'right', vertical: 'top' }} anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }} > - + Profile - + My account - + Add another account - + Settings - + diff --git a/docs/data/material/components/menus/AccountMenu.tsx b/docs/data/material/components/menus/AccountMenu.tsx index 1a13ebd4fab1e9..7f6d3c8545c341 100644 --- a/docs/data/material/components/menus/AccountMenu.tsx +++ b/docs/data/material/components/menus/AccountMenu.tsx @@ -74,26 +74,26 @@ export default function AccountMenu() { transformOrigin={{ horizontal: 'right', vertical: 'top' }} anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }} > - + Profile - + My account - + Add another account - + Settings - + diff --git a/docs/data/material/components/no-ssr/no-ssr.md b/docs/data/material/components/no-ssr/no-ssr.md index e2df0fc310f65a..0e5ff47b973bae 100644 --- a/docs/data/material/components/no-ssr/no-ssr.md +++ b/docs/data/material/components/no-ssr/no-ssr.md @@ -8,11 +8,11 @@ components: NoSsr

The No-SSR component defers the rendering of children components from the server to the client.

-## MUI Base +## This document has moved + +:::warning +Please refer to the [No-SSR](/base/react-no-ssr/) component page in the MUI Base docs for demos and details on usage. -:::info No-SSR is a part of the standalone [MUI Base](/base/getting-started/overview/) component library. It is currently re-exported from `@mui/material` for your convenience, but it will be removed from this package in a future major version, after `@mui/base` gets a stable release. - -Please refer to the [No-SSR](/base/react-no-ssr/) component page in the MUI Base docs for examples and details on usage. ::: diff --git a/docs/data/material/components/portal/portal.md b/docs/data/material/components/portal/portal.md index c0d35e031f3a08..c93220ff335fe1 100644 --- a/docs/data/material/components/portal/portal.md +++ b/docs/data/material/components/portal/portal.md @@ -9,11 +9,11 @@ githubLabel: 'component: Portal'

The Portal component lets you render its children into a DOM node that exists outside of the Portal's own DOM hierarchy.

-## MUI Base +## This document has moved + +:::warning +Please refer to the [Portal](/base/react-portal/) component page in the MUI Base docs for demos and details on usage. -:::info Portal is a part of the standalone [MUI Base](/base/getting-started/overview/) component library. It is currently re-exported from `@mui/material` for your convenience, but it will be removed from this package in a future major version, after `@mui/base` gets a stable release. - -Please refer to the [Portal](/base/react-portal/) component page in the MUI Base docs for examples and details on usage. ::: diff --git a/docs/data/material/components/steppers/steppers.md b/docs/data/material/components/steppers/steppers.md index 66fc4bc6c4ccc2..a98c27942417c7 100644 --- a/docs/data/material/components/steppers/steppers.md +++ b/docs/data/material/components/steppers/steppers.md @@ -18,8 +18,8 @@ Steppers may display a transient feedback message after a step is saved. {{"component": "modules/components/ComponentLinkHeader.js"}} -:::warning -Steppers are no longer documented in the [Material Design guidelines](https://m2.material.io/), but Material UI will continue to support them. +:::info +This component is no longer documented in the [Material Design guidelines](https://m2.material.io/), but Material UI will continue to support it. ::: ## Horizontal stepper diff --git a/docs/data/material/components/tables/AcccessibleTable.js b/docs/data/material/components/tables/AccessibleTable.js similarity index 97% rename from docs/data/material/components/tables/AcccessibleTable.js rename to docs/data/material/components/tables/AccessibleTable.js index 562470de636304..49de3c18d9bf24 100644 --- a/docs/data/material/components/tables/AcccessibleTable.js +++ b/docs/data/material/components/tables/AccessibleTable.js @@ -17,7 +17,7 @@ const rows = [ createData('Eclair', 262, 16.0, 24, 6.0), ]; -export default function AcccessibleTable() { +export default function AccessibleTable() { return ( diff --git a/docs/data/material/components/tables/AcccessibleTable.tsx b/docs/data/material/components/tables/AccessibleTable.tsx similarity index 97% rename from docs/data/material/components/tables/AcccessibleTable.tsx rename to docs/data/material/components/tables/AccessibleTable.tsx index 8f8643382b93b3..58b87347368fd9 100644 --- a/docs/data/material/components/tables/AcccessibleTable.tsx +++ b/docs/data/material/components/tables/AccessibleTable.tsx @@ -23,7 +23,7 @@ const rows = [ createData('Eclair', 262, 16.0, 24, 6.0), ]; -export default function AcccessibleTable() { +export default function AccessibleTable() { return (
diff --git a/docs/data/material/components/tables/ReactVirtualizedTable.js b/docs/data/material/components/tables/ReactVirtualizedTable.js index f3823119a8d014..cea6e821e6641e 100644 --- a/docs/data/material/components/tables/ReactVirtualizedTable.js +++ b/docs/data/material/components/tables/ReactVirtualizedTable.js @@ -1,159 +1,12 @@ import * as React from 'react'; -import PropTypes from 'prop-types'; -import clsx from 'clsx'; -import { styled } from '@mui/material/styles'; +import Table from '@mui/material/Table'; +import TableBody from '@mui/material/TableBody'; import TableCell from '@mui/material/TableCell'; +import TableContainer from '@mui/material/TableContainer'; +import TableHead from '@mui/material/TableHead'; +import TableRow from '@mui/material/TableRow'; import Paper from '@mui/material/Paper'; -import { AutoSizer, Column, Table } from 'react-virtualized'; - -const classes = { - flexContainer: 'ReactVirtualizedDemo-flexContainer', - tableRow: 'ReactVirtualizedDemo-tableRow', - tableRowHover: 'ReactVirtualizedDemo-tableRowHover', - tableCell: 'ReactVirtualizedDemo-tableCell', - noClick: 'ReactVirtualizedDemo-noClick', -}; - -const styles = ({ theme }) => ({ - // temporary right-to-left patch, waiting for - // https://github.com/bvaughn/react-virtualized/issues/454 - '& .ReactVirtualized__Table__headerRow': { - ...(theme.direction === 'rtl' && { - paddingLeft: '0 !important', - }), - ...(theme.direction !== 'rtl' && { - paddingRight: undefined, - }), - }, - [`& .${classes.flexContainer}`]: { - display: 'flex', - alignItems: 'center', - boxSizing: 'border-box', - }, - [`& .${classes.tableRow}`]: { - cursor: 'pointer', - }, - [`& .${classes.tableRowHover}`]: { - '&:hover': { - backgroundColor: theme.palette.grey[200], - }, - }, - [`& .${classes.tableCell}`]: { - flex: 1, - }, - [`& .${classes.noClick}`]: { - cursor: 'initial', - }, -}); - -class MuiVirtualizedTable extends React.PureComponent { - static defaultProps = { - headerHeight: 48, - rowHeight: 48, - }; - - getRowClassName = ({ index }) => { - const { onRowClick } = this.props; - - return clsx(classes.tableRow, classes.flexContainer, { - [classes.tableRowHover]: index !== -1 && onRowClick != null, - }); - }; - - cellRenderer = ({ cellData, columnIndex }) => { - const { columns, rowHeight, onRowClick } = this.props; - return ( - - {cellData} - - ); - }; - - headerRenderer = ({ label, columnIndex }) => { - const { headerHeight, columns } = this.props; - - return ( - - {label} - - ); - }; - - render() { - const { columns, rowHeight, headerHeight, ...tableProps } = this.props; - return ( - - {({ height, width }) => ( -
- {columns.map(({ dataKey, ...other }, index) => { - return ( - - this.headerRenderer({ - ...headerProps, - columnIndex: index, - }) - } - className={classes.flexContainer} - cellRenderer={this.cellRenderer} - dataKey={dataKey} - {...other} - /> - ); - })} -
- )} - - ); - } -} - -MuiVirtualizedTable.propTypes = { - columns: PropTypes.arrayOf( - PropTypes.shape({ - dataKey: PropTypes.string.isRequired, - label: PropTypes.string.isRequired, - numeric: PropTypes.bool, - width: PropTypes.number.isRequired, - }), - ).isRequired, - headerHeight: PropTypes.number, - onRowClick: PropTypes.func, - rowHeight: PropTypes.number, -}; - -const VirtualizedTable = styled(MuiVirtualizedTable)(styles); - -// --- +import { TableVirtuoso } from 'react-virtuoso'; const sample = [ ['Frozen yoghurt', 159, 6.0, 24, 4.0], @@ -167,50 +20,96 @@ function createData(id, dessert, calories, fat, carbs, protein) { return { id, dessert, calories, fat, carbs, protein }; } -const rows = []; +const columns = [ + { + width: 200, + label: 'Dessert', + dataKey: 'dessert', + }, + { + width: 120, + label: 'Calories\u00A0(g)', + dataKey: 'calories', + numeric: true, + }, + { + width: 120, + label: 'Fat\u00A0(g)', + dataKey: 'fat', + numeric: true, + }, + { + width: 120, + label: 'Carbs\u00A0(g)', + dataKey: 'carbs', + numeric: true, + }, + { + width: 120, + label: 'Protein\u00A0(g)', + dataKey: 'protein', + numeric: true, + }, +]; -for (let i = 0; i < 200; i += 1) { +const rows = Array.from({ length: 200 }, (_, index) => { const randomSelection = sample[Math.floor(Math.random() * sample.length)]; - rows.push(createData(i, ...randomSelection)); + return createData(index, ...randomSelection); +}); + +const VirtuosoTableComponents = { + Scroller: React.forwardRef((props, ref) => ( + + )), + Table: (props) => , + TableHead, + TableRow: ({ item: _item, ...props }) => , + TableBody: React.forwardRef((props, ref) => ), +}; + +function fixedHeaderContent() { + return ( + + {columns.map((column) => ( + + {column.label} + + ))} + + ); +} + +function rowContent(_index, row) { + return ( + + {columns.map((column) => ( + + {row[column.dataKey]} + + ))} + + ); } export default function ReactVirtualizedTable() { return ( - rows[index]} - columns={[ - { - width: 200, - label: 'Dessert', - dataKey: 'dessert', - }, - { - width: 120, - label: 'Calories\u00A0(g)', - dataKey: 'calories', - numeric: true, - }, - { - width: 120, - label: 'Fat\u00A0(g)', - dataKey: 'fat', - numeric: true, - }, - { - width: 120, - label: 'Carbs\u00A0(g)', - dataKey: 'carbs', - numeric: true, - }, - { - width: 120, - label: 'Protein\u00A0(g)', - dataKey: 'protein', - numeric: true, - }, - ]} + ); diff --git a/docs/data/material/components/tables/ReactVirtualizedTable.tsx b/docs/data/material/components/tables/ReactVirtualizedTable.tsx index fd8d69a50825b7..cfaf59636fa8e7 100644 --- a/docs/data/material/components/tables/ReactVirtualizedTable.tsx +++ b/docs/data/material/components/tables/ReactVirtualizedTable.tsx @@ -1,174 +1,12 @@ import * as React from 'react'; -import clsx from 'clsx'; -import { Theme, styled } from '@mui/material/styles'; +import Table from '@mui/material/Table'; +import TableBody from '@mui/material/TableBody'; import TableCell from '@mui/material/TableCell'; +import TableContainer from '@mui/material/TableContainer'; +import TableHead from '@mui/material/TableHead'; +import TableRow from '@mui/material/TableRow'; import Paper from '@mui/material/Paper'; -import { - AutoSizer, - Column, - Table, - TableCellRenderer, - TableHeaderProps, -} from 'react-virtualized'; - -const classes = { - flexContainer: 'ReactVirtualizedDemo-flexContainer', - tableRow: 'ReactVirtualizedDemo-tableRow', - tableRowHover: 'ReactVirtualizedDemo-tableRowHover', - tableCell: 'ReactVirtualizedDemo-tableCell', - noClick: 'ReactVirtualizedDemo-noClick', -}; - -const styles = ({ theme }: { theme: Theme }) => - ({ - // temporary right-to-left patch, waiting for - // https://github.com/bvaughn/react-virtualized/issues/454 - '& .ReactVirtualized__Table__headerRow': { - ...(theme.direction === 'rtl' && { - paddingLeft: '0 !important', - }), - ...(theme.direction !== 'rtl' && { - paddingRight: undefined, - }), - }, - [`& .${classes.flexContainer}`]: { - display: 'flex', - alignItems: 'center', - boxSizing: 'border-box', - }, - [`& .${classes.tableRow}`]: { - cursor: 'pointer', - }, - [`& .${classes.tableRowHover}`]: { - '&:hover': { - backgroundColor: theme.palette.grey[200], - }, - }, - [`& .${classes.tableCell}`]: { - flex: 1, - }, - [`& .${classes.noClick}`]: { - cursor: 'initial', - }, - } as const); - -interface ColumnData { - dataKey: string; - label: string; - numeric?: boolean; - width: number; -} - -interface Row { - index: number; -} - -interface MuiVirtualizedTableProps { - columns: readonly ColumnData[]; - headerHeight?: number; - onRowClick?: () => void; - rowCount: number; - rowGetter: (row: Row) => Data; - rowHeight?: number; -} - -class MuiVirtualizedTable extends React.PureComponent { - static defaultProps = { - headerHeight: 48, - rowHeight: 48, - }; - - getRowClassName = ({ index }: Row) => { - const { onRowClick } = this.props; - - return clsx(classes.tableRow, classes.flexContainer, { - [classes.tableRowHover]: index !== -1 && onRowClick != null, - }); - }; - - cellRenderer: TableCellRenderer = ({ cellData, columnIndex }) => { - const { columns, rowHeight, onRowClick } = this.props; - return ( - - {cellData} - - ); - }; - - headerRenderer = ({ - label, - columnIndex, - }: TableHeaderProps & { columnIndex: number }) => { - const { headerHeight, columns } = this.props; - - return ( - - {label} - - ); - }; - - render() { - const { columns, rowHeight, headerHeight, ...tableProps } = this.props; - return ( - - {({ height, width }) => ( -
- {columns.map(({ dataKey, ...other }, index) => { - return ( - - this.headerRenderer({ - ...headerProps, - columnIndex: index, - }) - } - className={classes.flexContainer} - cellRenderer={this.cellRenderer} - dataKey={dataKey} - {...other} - /> - ); - })} -
- )} - - ); - } -} - -const VirtualizedTable = styled(MuiVirtualizedTable)(styles); - -// --- +import { TableVirtuoso, TableComponents } from 'react-virtuoso'; interface Data { calories: number; @@ -178,6 +16,14 @@ interface Data { id: number; protein: number; } + +interface ColumnData { + dataKey: keyof Data; + label: string; + numeric?: boolean; + width: number; +} + type Sample = [string, number, number, number, number]; const sample: readonly Sample[] = [ @@ -199,50 +45,98 @@ function createData( return { id, dessert, calories, fat, carbs, protein }; } -const rows: Data[] = []; +const columns: ColumnData[] = [ + { + width: 200, + label: 'Dessert', + dataKey: 'dessert', + }, + { + width: 120, + label: 'Calories\u00A0(g)', + dataKey: 'calories', + numeric: true, + }, + { + width: 120, + label: 'Fat\u00A0(g)', + dataKey: 'fat', + numeric: true, + }, + { + width: 120, + label: 'Carbs\u00A0(g)', + dataKey: 'carbs', + numeric: true, + }, + { + width: 120, + label: 'Protein\u00A0(g)', + dataKey: 'protein', + numeric: true, + }, +]; -for (let i = 0; i < 200; i += 1) { +const rows: Data[] = Array.from({ length: 200 }, (_, index) => { const randomSelection = sample[Math.floor(Math.random() * sample.length)]; - rows.push(createData(i, ...randomSelection)); + return createData(index, ...randomSelection); +}); + +const VirtuosoTableComponents: TableComponents = { + Scroller: React.forwardRef((props, ref) => ( + + )), + Table: (props) => , + TableHead, + TableRow: ({ item: _item, ...props }) => , + TableBody: React.forwardRef((props, ref) => ( + + )), +}; + +function fixedHeaderContent() { + return ( + + {columns.map((column) => ( + + {column.label} + + ))} + + ); +} + +function rowContent(_index: number, row: Data) { + return ( + + {columns.map((column) => ( + + {row[column.dataKey]} + + ))} + + ); } export default function ReactVirtualizedTable() { return ( - rows[index]} - columns={[ - { - width: 200, - label: 'Dessert', - dataKey: 'dessert', - }, - { - width: 120, - label: 'Calories\u00A0(g)', - dataKey: 'calories', - numeric: true, - }, - { - width: 120, - label: 'Fat\u00A0(g)', - dataKey: 'fat', - numeric: true, - }, - { - width: 120, - label: 'Carbs\u00A0(g)', - dataKey: 'carbs', - numeric: true, - }, - { - width: 120, - label: 'Protein\u00A0(g)', - dataKey: 'protein', - numeric: true, - }, - ]} + ); diff --git a/docs/data/material/components/tables/ReactVirtualizedTable.tsx.preview b/docs/data/material/components/tables/ReactVirtualizedTable.tsx.preview new file mode 100644 index 00000000000000..4d83b69f40940f --- /dev/null +++ b/docs/data/material/components/tables/ReactVirtualizedTable.tsx.preview @@ -0,0 +1,8 @@ + + + \ No newline at end of file diff --git a/docs/data/material/components/tables/tables-pt.md b/docs/data/material/components/tables/tables-pt.md index b83667e081ae1d..ffd13792d813f6 100644 --- a/docs/data/material/components/tables/tables-pt.md +++ b/docs/data/material/components/tables/tables-pt.md @@ -120,7 +120,7 @@ No exemplo a seguir, nĆ³s demonstramos como usar [react-virtualized](https://git A caption functions like a heading for a table. Most screen readers announce the content of captions. Captions help users to find a table and understand what it's about and decide if they want to read it. -{{"demo": "AcccessibleTable.js", "bg": true}} +{{"demo": "AccessibleTable.js", "bg": true}} ## Unstyled diff --git a/docs/data/material/components/tables/tables-zh.md b/docs/data/material/components/tables/tables-zh.md index 0f80652b9ac9be..a12799cc42fce8 100644 --- a/docs/data/material/components/tables/tables-zh.md +++ b/docs/data/material/components/tables/tables-zh.md @@ -120,7 +120,7 @@ Here is an example of a table with scrollable rows and fixed column headers. It A caption functions like a heading for a table. Most screen readers announce the content of captions. Captions help users to find a table and understand what it's about and decide if they want to read it. -{{"demo": "AcccessibleTable.js", "bg": true}} +{{"demo": "AccessibleTable.js", "bg": true}} ## Unstyled diff --git a/docs/data/material/components/tables/tables.md b/docs/data/material/components/tables/tables.md index 419ba84feea167..2a1ac2a1c9de8d 100644 --- a/docs/data/material/components/tables/tables.md +++ b/docs/data/material/components/tables/tables.md @@ -115,7 +115,7 @@ A simple example with spanning rows & columns. ## Virtualized table -In the following example, we demonstrate how to use [react-virtualized](https://github.com/bvaughn/react-virtualized) with the `Table` component. +In the following example, we demonstrate how to use [react-virtuoso](https://github.com/petyosi/react-virtuoso) with the `Table` component. It renders 200 rows and can easily handle more. Virtualization helps with performance issues. @@ -129,7 +129,7 @@ Virtualization helps with performance issues. A caption functions like a heading for a table. Most screen readers announce the content of captions. Captions help users to find a table and understand what it's about and decide if they want to read it. -{{"demo": "AcccessibleTable.js", "bg": true}} +{{"demo": "AccessibleTable.js", "bg": true}} ## Unstyled diff --git a/docs/data/material/components/text-fields/text-fields.md b/docs/data/material/components/text-fields/text-fields.md index 83dda1aa4fd21c..d777e05d1b6524 100644 --- a/docs/data/material/components/text-fields/text-fields.md +++ b/docs/data/material/components/text-fields/text-fields.md @@ -22,9 +22,11 @@ It comes with three variants: outlined (default), filled, and standard. {{"demo": "BasicTextFields.js"}} -**Note:** The standard variant of the `TextField` is no longer documented in the [Material Design guidelines](https://m2.material.io/) -([here's why](https://medium.com/google-design/the-evolution-of-material-designs-text-fields-603688b3fe03)), -but MUI will continue to support it. +:::info +The standard variant of the Text Field is no longer documented in the [Material Design guidelines](https://m2.material.io/) +([this article explains why](https://medium.com/google-design/the-evolution-of-material-designs-text-fields-603688b3fe03)), +but Material UI will continue to support it. +::: ## Form props diff --git a/docs/data/material/components/textarea-autosize/textarea-autosize.md b/docs/data/material/components/textarea-autosize/textarea-autosize.md index a4067908fe61af..df6d4930978f04 100644 --- a/docs/data/material/components/textarea-autosize/textarea-autosize.md +++ b/docs/data/material/components/textarea-autosize/textarea-autosize.md @@ -9,11 +9,11 @@ githubLabel: 'component: TextareaAutosize'

The Textarea Autosize component gives you a textarea HTML element that automatically adjusts its height to match the length of the content within.

-## MUI Base +## This document has moved + +:::warning +Please refer to the [Textarea Autosize](/base/react-textarea-autosize/) component page in the MUI Base docs for demos and details on usage. -:::info Textarea Autosize is a part of the standalone [MUI Base](/base/getting-started/overview/) component library. It is currently re-exported from `@mui/material` for your convenience, but it will be removed from this package in a future major version, after `@mui/base` gets a stable release. - -Please refer to the [Textarea Autosize](/base/react-textarea-autosize/) component page in the MUI Base docs for examples and details on usage. ::: diff --git a/docs/data/material/components/timeline/timeline.md b/docs/data/material/components/timeline/timeline.md index adfaef3f278444..d4c45eef716c6e 100644 --- a/docs/data/material/components/timeline/timeline.md +++ b/docs/data/material/components/timeline/timeline.md @@ -10,7 +10,9 @@ packageName: '@mui/lab'

The timeline displays a list of events in chronological order.

-**Note:** This component is not documented in the [Material Design guidelines](https://m2.material.io/), but MUI supports it. +:::info +This component is not documented in the [Material Design guidelines](https://m2.material.io/), but it is available in Material UI. +::: {{"component": "modules/components/ComponentLinkHeader.js"}} diff --git a/docs/data/material/customization/color/color.md b/docs/data/material/customization/color/color.md index e3b3306f240d42..78dca24bb9b8d6 100644 --- a/docs/data/material/customization/color/color.md +++ b/docs/data/material/customization/color/color.md @@ -65,13 +65,13 @@ const theme = createTheme({ }); ``` -Only the `main` shades need be provided (unless you wish to further customize `light`, `dark` or `contrastText`), as the other colors will be calculated by `createTheme()`, as described in the [Theme customization](/material-ui/customization/palette/) section. +Only the `main` shades need to be provided (unless you wish to further customize `light`, `dark` or `contrastText`), as the other colors will be calculated by `createTheme()`, as described in the [Theme customization](/material-ui/customization/palette/) section. If you are using the default primary and / or secondary shades then by providing the color object, `createTheme()` will use the appropriate shades from the material color for main, light and dark. ### Tools by the community -- [mui-theme-creator](https://bareynol.github.io/mui-theme-creator/): A tool to help design and customize themes for the MUI component library. Includes basic site templates to show various components and how they are affected by the theme +- [mui-theme-creator](https://zenoo.github.io/mui-theme-creator/): A tool to help design and customize themes for the MUI component library. Includes basic site templates to show various components and how they are affected by the theme - [Material palette generator](https://m2.material.io/inline-tools/color/): The Material palette generator can be used to generate a palette for any color you input. ## 2014 Material Design color palettes diff --git a/docs/data/material/customization/default-theme/DefaultTheme.js b/docs/data/material/customization/default-theme/DefaultTheme.js index f4288f285a7571..65896c27791d1c 100644 --- a/docs/data/material/customization/default-theme/DefaultTheme.js +++ b/docs/data/material/customization/default-theme/DefaultTheme.js @@ -1,234 +1,12 @@ import * as React from 'react'; -import PropTypes from 'prop-types'; import Box from '@mui/material/Box'; -import ExpandIcon from '@mui/icons-material/ExpandMore'; -import CollapseIcon from '@mui/icons-material/ChevronRight'; -import TreeView from '@mui/lab/TreeView'; -import MuiTreeItem, { treeItemClasses } from '@mui/lab/TreeItem'; -import clsx from 'clsx'; -import { styled, createTheme, lighten } from '@mui/material/styles'; +import { createTheme } from '@mui/material/styles'; import FormControlLabel from '@mui/material/FormControlLabel'; import Switch from '@mui/material/Switch'; import { useTranslate } from 'docs/src/modules/utils/i18n'; - -/** - * @param {unknown} value - */ -function getType(value) { - if (Array.isArray(value)) { - return 'array'; - } - - if (/^(#|rgb|rgba|hsl|hsla)/.test(value)) { - return 'color'; - } - - if (value === null) { - return 'null'; - } - - return typeof value; -} - -/** - * @param {unknown} value - * @param {ReturnType} type - */ -function getLabel(value, type) { - switch (type) { - case 'array': - return `Array(${value.length})`; - case 'null': - return 'null'; - case 'undefined': - return 'undefined'; - case 'function': - return `f ${value.name}()`; - case 'object': - return 'Object'; - case 'string': - return `"${value}"`; - case 'symbol': - return `Symbol(${String(value)})`; - case 'bigint': - case 'boolean': - case 'number': - default: - return String(value); - } -} - -function getTokenType(type) { - switch (type) { - case 'color': - return 'string'; - case 'object': - case 'array': - return 'comment'; - default: - return type; - } -} - -const Color = styled('span')(({ theme }) => ({ - backgroundColor: '#fff', - display: 'inline-block', - marginBottom: -1, - marginRight: theme.spacing(0.5), - border: '1px solid', - backgroundImage: - 'url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%202%202%22%3E%3Cpath%20d%3D%22M1%202V0h1v1H0v1z%22%20fill-opacity%3D%22.2%22%2F%3E%3C%2Fsvg%3E")', -})); - -function ObjectEntryLabel(props) { - const { objectKey, objectValue } = props; - const type = getType(objectValue); - const label = getLabel(objectValue, type); - const tokenType = getTokenType(type); - - return ( - - {`${objectKey}: `} - {type === 'color' ? ( - - - - ) : null} - {label} - - ); -} - -ObjectEntryLabel.propTypes = { - objectKey: PropTypes.any, - objectValue: PropTypes.any, -}; - -const TreeItem = styled(MuiTreeItem)({ - [`&:focus > .${treeItemClasses.content}`]: { - backgroundColor: lighten('#333', 0.08), - outline: `2px dashed ${lighten('#333', 0.3)}`, - }, - [`& .${treeItemClasses.content}`]: { - '&:hover': { - backgroundColor: lighten('#333', 0.08), - }, - }, -}); - -function ObjectEntry(props) { - const { nodeId, objectKey, objectValue } = props; - const keyPrefix = nodeId; - let children = null; - - if ( - (objectValue !== null && typeof objectValue === 'object') || - typeof objectValue === 'function' - ) { - children = - Object.keys(objectValue).length === 0 - ? undefined - : Object.keys(objectValue).map((key) => { - return ( - - ); - }); - } - - return ( - } - > - {children} - - ); -} -ObjectEntry.propTypes = { - nodeId: PropTypes.string.isRequired, - objectKey: PropTypes.any.isRequired, - objectValue: PropTypes.any, -}; - -function Inspector(props) { - const { data, expandPaths, ...other } = props; - - const keyPrefix = '$ROOT'; - const defaultExpanded = React.useMemo(() => { - return Array.isArray(expandPaths) - ? expandPaths.map((expandPath) => `${keyPrefix}.${expandPath}`) - : []; - }, [keyPrefix, expandPaths]); - // for default* to take effect we need to remount - const key = React.useMemo(() => defaultExpanded.join(''), [defaultExpanded]); - - return ( - } - defaultEndIcon={
} - defaultExpanded={defaultExpanded} - defaultExpandIcon={} - {...other} - > - {Object.keys(data).map((objectKey) => { - return ( - - ); - })} - - ); -} - -Inspector.propTypes = { - data: PropTypes.any, - expandPaths: PropTypes.arrayOf(PropTypes.string), -}; - -function computeNodeIds(object, prefix) { - if ( - (object !== null && typeof object === 'object') || - typeof object === 'function' - ) { - const ids = []; - Object.keys(object).forEach((key) => { - ids.push( - `${prefix}${key}`, - ...computeNodeIds(object[key], `${prefix}${key}.`), - ); - }); - - return ids; - } - return []; -} - -function useNodeIdsLazy(object) { - const [allNodeIds, setAllNodeIds] = React.useState([]); - // technically we want to compute them lazily until we need them (expand all) - // yielding is good enough. technically we want to schedule the computation - // with low pri and upgrade the priority later - React.useEffect(() => { - setAllNodeIds(computeNodeIds(object, '')); - }, [object]); - - return allNodeIds; -} +import ThemeViewer, { + useNodeIdsLazy, +} from 'docs/src/modules/components/ThemeViewer'; function DefaultTheme() { const [checked, setChecked] = React.useState(false); @@ -244,9 +22,6 @@ function DefaultTheme() { const [name, value] = param.split('='); if (name === 'expand-path') { expandPath = value; - } else if (name === 'expend-path' && !expandPath) { - // 'expend-path' is for backwards compatibility of any external links with a prior typo. - expandPath = value; } }); @@ -308,7 +83,7 @@ function DefaultTheme() { } label={t('useDarkTheme')} /> - + ); } diff --git a/docs/data/material/customization/default-theme/default-theme.md b/docs/data/material/customization/default-theme/default-theme.md index c1f0b7baf26d75..ce207da8da5b2c 100644 --- a/docs/data/material/customization/default-theme/default-theme.md +++ b/docs/data/material/customization/default-theme/default-theme.md @@ -1,4 +1,4 @@ -# Default theme +# Default theme viewer

Here's what the theme object looks like with the default values.

diff --git a/docs/data/material/customization/theming/theming.md b/docs/data/material/customization/theming/theming.md index 952fb2d5e61265..9da418f38a1236 100644 --- a/docs/data/material/customization/theming/theming.md +++ b/docs/data/material/customization/theming/theming.md @@ -80,7 +80,7 @@ declare module '@mui/material/styles' { The community has built great tools to build a theme: -- [mui-theme-creator](https://bareynol.github.io/mui-theme-creator/): A tool to help design and customize themes for the MUI component library. Includes basic site templates to show various components and how they are affected by the theme +- [mui-theme-creator](https://zenoo.github.io/mui-theme-creator/): A tool to help design and customize themes for the MUI component library. Includes basic site templates to show various components and how they are affected by the theme - [Material palette generator](https://m2.material.io/inline-tools/color/): The Material palette generator can be used to generate a palette for any color you input. ## Accessing the theme in a component diff --git a/docs/data/material/customization/typography/typography-zh.md b/docs/data/material/customization/typography/typography-zh.md index 3c0ce30e1b8560..07539d4cfa5b92 100644 --- a/docs/data/material/customization/typography/typography-zh.md +++ b/docs/data/material/customization/typography/typography-zh.md @@ -101,7 +101,7 @@ return ( ); ``` -Note that if you want to add additional `@font-face` declarations, you need to use the string CSS template syntax for adding style overrides, so that the previosly defined `@font-face` declarations won't be replaced. +Note that if you want to add additional `@font-face` declarations, you need to use the string CSS template syntax for adding style overrides, so that the previously defined `@font-face` declarations won't be replaced. ## 字体大小ļ¼ˆFont sizeļ¼‰ diff --git a/docs/data/material/customization/typography/typography.md b/docs/data/material/customization/typography/typography.md index e346ee3203c3d9..e05c317d2f7678 100644 --- a/docs/data/material/customization/typography/typography.md +++ b/docs/data/material/customization/typography/typography.md @@ -80,7 +80,7 @@ return ( ); ``` -Note that if you want to add additional `@font-face` declarations, you need to use the string CSS template syntax for adding style overrides, so that the previosly defined `@font-face` declarations won't be replaced. +Note that if you want to add additional `@font-face` declarations, you need to use the string CSS template syntax for adding style overrides, so that the previously defined `@font-face` declarations won't be replaced. ## Font size diff --git a/docs/data/material/getting-started/example-projects/example-projects.md b/docs/data/material/getting-started/example-projects/example-projects.md index f819dc2fa1f546..ad29cdd69a6ef4 100644 --- a/docs/data/material/getting-started/example-projects/example-projects.md +++ b/docs/data/material/getting-started/example-projects/example-projects.md @@ -16,7 +16,7 @@ You can find some example projects in the [GitHub repository](https://github.com - [CDN](https://github.com/mui/material-ui/tree/master/examples/cdn) - [Plain server-side](https://github.com/mui/material-ui/tree/master/examples/ssr) - [Tailwind CSS](https://github.com/mui/material-ui/tree/master/examples/tailwind-css) -- [Vite.js](https://github.com/mui/material-ui/tree/master/examples/vitejs) +- [Vite.js](https://github.com/mui/material-ui/tree/master/examples/vitejs) ([TypeScript version](https://github.com/mui/material-ui/tree/master/examples/vitejs-with-typescript)) - [Use styled-components as style engine](https://github.com/mui/material-ui/tree/master/examples/create-react-app-with-styled-components) ([TypeScript version](https://github.com/mui/material-ui/tree/master/examples/create-react-app-with-styled-components-typescript)) - [Next.js + @mui/styles (v4 migration helper)](https://github.com/mui/material-ui/tree/master/examples/nextjs-with-typescript-v4-migration) diff --git a/docs/data/material/guides/composition/composition.md b/docs/data/material/guides/composition/composition.md index 82feab9d50126a..0036b08b78da06 100644 --- a/docs/data/material/guides/composition/composition.md +++ b/docs/data/material/guides/composition/composition.md @@ -151,7 +151,7 @@ You can find a code example with the Button and react-router-dom in [these demos #### Generic -It's also is possible to have a generic `CustomComponent` which will accept any React component, and HTML elements. +It's also possible to have a generic `CustomComponent` which will accept any React component, and HTML elements. ```ts function GenericCustomComponent( diff --git a/docs/data/material/guides/pickers-migration/pickers-migration.md b/docs/data/material/guides/pickers-migration/pickers-migration.md index eee7daa8d8e425..226f0d7467ec0c 100644 --- a/docs/data/material/guides/pickers-migration/pickers-migration.md +++ b/docs/data/material/guides/pickers-migration/pickers-migration.md @@ -1,10 +1,15 @@ # Migration from @material-ui/pickers -

@material-ui/pickers was moved to the @mui/lab.

+

@material-ui/pickers was moved to the @mui/lab.

+ +:::success +**Only use this migration guide if you need to use Date and Time pickers from `@mui/lab`.** + +The components are available in alpha version in the lab between `v5.0.0-alpha.30` and `v5.0.0-alpha.89` inclusively. +They won't receive any new feature of bug fixes and won't be compatible with future major releases of MUI packages. + +If you want to use the **stable version** of those components, please have a look at the new [MUI X packages](/x/react-date-pickers/getting-started/) `@mui/x-date-pickers` and `@mui/x-date-pickers-pro`. -:::info -**Stable package available**: The pickers are not available in `@mui/lab` after `v5.0.0-alpha.89`. -They have been moved from `@mui/lab` to the MUI X packages `@mui/x-date-pickers` and `@mui/x-date-pickers-pro`. To migrate from `@mui/lab` to `@mui/x-date-pickers` you can follow the dedicated [migration guide](/x/react-date-pickers/migration-lab/). ::: @@ -17,7 +22,12 @@ This guide is an overview of the core concepts that were changed from pickers v3 ## Installation You need to install the `@mui/lab` package if it's not already installed. -āš ļø Make sure you have installed the latest version, `"@mui/lab": ^5.0.0-alpha.30"` or above. +āš ļø Make sure you have installed a version between `v5.0.0-alpha.30` and `v5.0.0-alpha.89` inclusively. + +:::warning +The pickers are no longer available in `@mui/lab` starting `v5.0.0-alpha.90`. +Please refer to the information on top of the page to use the latest pickers components. +::: ## Imports @@ -123,13 +133,17 @@ Mask is no longer required. Also, if your provided mask is not valid, pickers wi ## And many more -- ```diff - - - - + + + ); diff --git a/docs/data/system/experimental-api/configure-the-sx-prop/ChangeTheBehaviorSxProp.tsx b/docs/data/system/experimental-api/configure-the-sx-prop/ChangeTheBehaviorSxProp.tsx index eb0477a69f2a34..c085075d1ad5ea 100644 --- a/docs/data/system/experimental-api/configure-the-sx-prop/ChangeTheBehaviorSxProp.tsx +++ b/docs/data/system/experimental-api/configure-the-sx-prop/ChangeTheBehaviorSxProp.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; -import { createTheme, ThemeProvider, Box, Stack } from '@mui/system'; +import { Box, Stack } from '@mui/system'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; // Retain type safety. declare module '@mui/system' { @@ -12,7 +13,7 @@ declare module '@mui/system' { const theme = createTheme({ unstable_sxConfig: { - // You can now use the background key in sx + // You can now use the borderRadius key in sx // by providing direct values from the palette borderRadius: { themeKey: 'shape', @@ -29,9 +30,9 @@ export default function ChangeTheBehaviorSxProp() { return ( - - - + + + ); diff --git a/docs/data/system/experimental-api/configure-the-sx-prop/ChangeTheBehaviorSxProp.tsx.preview b/docs/data/system/experimental-api/configure-the-sx-prop/ChangeTheBehaviorSxProp.tsx.preview index 563ab3ef514f8b..af739183743110 100644 --- a/docs/data/system/experimental-api/configure-the-sx-prop/ChangeTheBehaviorSxProp.tsx.preview +++ b/docs/data/system/experimental-api/configure-the-sx-prop/ChangeTheBehaviorSxProp.tsx.preview @@ -1,5 +1,5 @@ - - - + + + \ No newline at end of file diff --git a/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.js b/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.js index 2b96d7f2a88f43..2bbe7036c255d4 100644 --- a/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.js +++ b/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.js @@ -1,5 +1,6 @@ import * as React from 'react'; -import { createTheme, ThemeProvider, Box, handleBreakpoints } from '@mui/system'; +import { Box, handleBreakpoints } from '@mui/system'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; const customTheme = createTheme({ unstable_sxConfig: { @@ -29,7 +30,7 @@ export default function ExtendSxProp() { diff --git a/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.tsx b/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.tsx index a6f071dc97282f..1958c2c766bbe7 100644 --- a/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.tsx +++ b/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; -import { createTheme, ThemeProvider, Box, handleBreakpoints } from '@mui/system'; +import { Box, handleBreakpoints } from '@mui/system'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; const customTheme = createTheme({ unstable_sxConfig: { @@ -29,7 +30,7 @@ export default function ExtendSxProp() { diff --git a/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.tsx.preview b/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.tsx.preview index 4ca9079ae6b641..62c06b159188cc 100644 --- a/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.tsx.preview +++ b/docs/data/system/experimental-api/configure-the-sx-prop/ExtendTheSxProp.tsx.preview @@ -2,7 +2,7 @@ \ No newline at end of file diff --git a/docs/notifications.json b/docs/notifications.json index f32b2c74f715b3..43e7ce0cda3d12 100644 --- a/docs/notifications.json +++ b/docs/notifications.json @@ -5,18 +5,13 @@ "text": "Love Material UI, but don't need Material Design? Try MUI Base, the new \"unstyled\" alternative. Read more in this announcement." }, { - "id": 69, - "title": "Date Pickers get a stable v5 release.", - "text": "Migrate to the latest version for improved DX, customizability, and API consistency. Check out the blog post for details." - }, - { - "id": 71, + "id": 72, "title": "A major update is coming for MUI Xā€”and you can get involved", "text": "Check out the blog post for details, and let us know what you want to see in MUI X v6." }, { - "id": 72, - "title": "The MUI Developer survey is live!", - "text": "Please take a few minutes to complete the survey and help us shape the roadmap for 2023." + "id": 73, + "title": "Date and Time Pickers revamped", + "text": "Discover the exciting new features landing now with v6 beta." } ] diff --git a/docs/package.json b/docs/package.json index 14141fa3c0d3f4..7069322c8b351a 100644 --- a/docs/package.json +++ b/docs/package.json @@ -23,7 +23,7 @@ "@babel/core": "^7.20.7", "@babel/plugin-transform-object-assign": "^7.18.6", "@babel/runtime-corejs2": "^7.20.7", - "@docsearch/react": "^3.3.1", + "@docsearch/react": "^3.3.2", "@emotion/cache": "^11.10.5", "@emotion/react": "^11.10.5", "@emotion/server": "^11.10.0", @@ -31,25 +31,25 @@ "@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/free-solid-svg-icons": "^6.2.1", "@fortawesome/react-fontawesome": "^0.2.0", - "@mui/base": "5.0.0-alpha.112", + "@mui/base": "5.0.0-alpha.115", "@mui/docs": "^5.11.2", "@mui/icons-material": "^5.11.0", - "@mui/joy": "5.0.0-alpha.61", - "@mui/lab": "5.0.0-alpha.114", + "@mui/joy": "5.0.0-alpha.64", + "@mui/lab": "5.0.0-alpha.117", "@mui/markdown": "^5.0.0", - "@mui/material": "^5.11.3", - "@mui/material-next": "6.0.0-alpha.69", + "@mui/material": "^5.11.6", + "@mui/material-next": "6.0.0-alpha.72", "@mui/styled-engine": "^5.11.0", "@mui/styled-engine-sc": "^5.11.0", "@mui/styles": "^5.11.2", - "@mui/system": "^5.11.2", + "@mui/system": "^5.11.5", "@mui/types": "^7.2.3", - "@mui/x-data-grid": "6.0.0-alpha.11", - "@mui/x-data-grid-generator": "6.0.0-alpha.11", - "@mui/x-data-grid-pro": "6.0.0-alpha.11", - "@mui/x-date-pickers": "6.0.0-alpha.11", - "@mui/x-date-pickers-pro": "6.0.0-alpha.11", - "@mui/x-license-pro": "6.0.0-alpha.9", + "@mui/x-data-grid": "6.0.0-alpha.14", + "@mui/x-data-grid-generator": "6.0.0-alpha.14", + "@mui/x-data-grid-pro": "6.0.0-alpha.14", + "@mui/x-date-pickers": "6.0.0-alpha.14", + "@mui/x-date-pickers-pro": "6.0.0-alpha.14", + "@mui/x-license-pro": "6.0.0-alpha.14", "@trendmicro/react-interpolate": "^0.5.5", "@types/autosuggest-highlight": "^3.2.0", "@types/css-mediaquery": "^0.1.1", @@ -58,7 +58,6 @@ "@types/react-dom": "^18.0.10", "@types/react-swipeable-views": "^0.13.1", "@types/react-swipeable-views-utils": "^0.13.4", - "@types/react-virtualized": "^9.21.21", "@types/react-window": "^1.8.5", "@types/styled-components": "5.1.26", "autoprefixer": "^10.4.13", @@ -67,7 +66,7 @@ "babel-plugin-optimize-clsx": "^2.6.2", "babel-plugin-react-remove-properties": "^0.3.0", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", - "clean-css": "^5.3.1", + "clean-css": "^5.3.2", "clipboard-copy": "^4.0.1", "clsx": "^1.2.1", "core-js": "^2.6.11", @@ -77,6 +76,7 @@ "date-fns-jalali": "^2.21.3-1", "exceljs": "^4.3.0", "express": "^4.18.2", + "feed": "^4.2.2", "fg-loadcss": "^3.1.0", "final-form": "^4.20.7", "flexsearch": "^0.7.31", @@ -92,7 +92,7 @@ "next": "13.1.1", "notistack": "2.0.8", "nprogress": "^0.2.0", - "postcss": "^8.4.20", + "postcss": "^8.4.21", "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -108,7 +108,7 @@ "react-spring": "^8.0.27", "react-swipeable-views": "^0.14.0", "react-transition-group": "^4.4.5", - "react-virtualized": "^9.22.3", + "react-virtuoso": "^4.0.1", "react-window": "^1.8.8", "recharts": "2.2.0", "rimraf": "^3.0.2", diff --git a/docs/pages/about.tsx b/docs/pages/about.tsx index 645dbde0469b86..f434f4978df76b 100644 --- a/docs/pages/about.tsx +++ b/docs/pages/about.tsx @@ -29,25 +29,25 @@ import BrandingCssVarsProvider from 'docs/src/BrandingCssVarsProvider'; import AppHeaderBanner from 'docs/src/components/banner/AppHeaderBanner'; interface Profile { - /** - * image url - */ - src: string; name: string; /** - * Role, what are you workin on? + * Role, what are you working on? */ title: string; /** - * Country wher you live in, ISO 3166-1. + * Country where you live in, ISO 3166-1. */ locationCountry: string; // https://flagpedia.net/download/api /** - * Lives in + * Image URL. + */ + src?: string; + /** + * Lives in. */ location?: string; /** - * Short summary about you + * Short summary about you. */ about?: string; github?: string; @@ -91,7 +91,7 @@ function Person(props: Profile & { sx?: PaperProps['sx'] }) { }} src={props.src} alt={props.name} - {...(props.src.startsWith('https://avatars.githubusercontent.com') && { + {...(props.src?.startsWith('https://avatars.githubusercontent.com') && { src: `${props.src}?s=70`, srcSet: `${props.src}?s=140 2x`, })} @@ -399,6 +399,22 @@ const teamMembers: Array = [ about: 'šŸ› ļø DYI projects, šŸ„šŸ»ā€ā™‚ļø Wakeboarding & šŸŽļø F1', github: 'bytasv', }, + { + src: '/static/branding/about/greg.png', + name: 'Greg Abaoag', + title: 'Executive Assistant', + location: 'Philippines', + locationCountry: 'ph', + about: 'Loves DIY, singing and learning', + github: 'gzrae', + }, + { + name: 'Tina Deinekhovska', + title: 'Business Administrator', + location: 'London, UK', + locationCountry: 'gb', + about: 'Empathic art-lover, incurable optimist keen on biking, gardening', + }, { src: '/static/branding/about/lukas.png', name: 'Lukas Tyla', @@ -665,6 +681,7 @@ function AboutContent() { color="primary" fontWeight="extraBold" sx={{ mb: 1 }} + id="company" > Company diff --git a/docs/pages/base/api/badge-unstyled.json b/docs/pages/base/api/badge-unstyled.json index 061394f0054ada..ff3cf3f6a195b3 100644 --- a/docs/pages/base/api/badge-unstyled.json +++ b/docs/pages/base/api/badge-unstyled.json @@ -3,9 +3,9 @@ "badgeContent": { "type": { "name": "node" } }, "children": { "type": { "name": "node" } }, "component": { "type": { "name": "elementType" } }, - "invisible": { "type": { "name": "bool" } }, + "invisible": { "type": { "name": "bool" }, "default": "false" }, "max": { "type": { "name": "number" }, "default": "99" }, - "showZero": { "type": { "name": "bool" } }, + "showZero": { "type": { "name": "bool" }, "default": "false" }, "slotProps": { "type": { "name": "shape", diff --git a/docs/pages/base/api/button-unstyled.json b/docs/pages/base/api/button-unstyled.json index 0d8eb201e62173..693f9f8225510a 100644 --- a/docs/pages/base/api/button-unstyled.json +++ b/docs/pages/base/api/button-unstyled.json @@ -7,8 +7,8 @@ } }, "component": { "type": { "name": "elementType" } }, - "disabled": { "type": { "name": "bool" } }, - "focusableWhenDisabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "focusableWhenDisabled": { "type": { "name": "bool" }, "default": "false" }, "slotProps": { "type": { "name": "shape", "description": "{ root?: func
| object }" }, "default": "{}" diff --git a/docs/pages/base/api/click-away-listener.json b/docs/pages/base/api/click-away-listener.json index 3f3e2df71deb06..a16c09f70dc1b1 100644 --- a/docs/pages/base/api/click-away-listener.json +++ b/docs/pages/base/api/click-away-listener.json @@ -2,7 +2,7 @@ "props": { "children": { "type": { "name": "custom", "description": "element" }, "required": true }, "onClickAway": { "type": { "name": "func" }, "required": true }, - "disableReactTree": { "type": { "name": "bool" } }, + "disableReactTree": { "type": { "name": "bool" }, "default": "false" }, "mouseEvent": { "type": { "name": "enum", diff --git a/docs/pages/base/api/focus-trap.json b/docs/pages/base/api/focus-trap.json index 7152d1a72eb1f1..a3bde11162bea4 100644 --- a/docs/pages/base/api/focus-trap.json +++ b/docs/pages/base/api/focus-trap.json @@ -2,9 +2,9 @@ "props": { "open": { "type": { "name": "bool" }, "required": true }, "children": { "type": { "name": "custom", "description": "element" } }, - "disableAutoFocus": { "type": { "name": "bool" } }, - "disableEnforceFocus": { "type": { "name": "bool" } }, - "disableRestoreFocus": { "type": { "name": "bool" } }, + "disableAutoFocus": { "type": { "name": "bool" }, "default": "false" }, + "disableEnforceFocus": { "type": { "name": "bool" }, "default": "false" }, + "disableRestoreFocus": { "type": { "name": "bool" }, "default": "false" }, "getTabbable": { "type": { "name": "func" } }, "isEnabled": { "type": { "name": "func" }, diff --git a/docs/pages/base/api/form-control-unstyled.json b/docs/pages/base/api/form-control-unstyled.json index 2bc8014c37c3fc..26e152d6bd30f0 100644 --- a/docs/pages/base/api/form-control-unstyled.json +++ b/docs/pages/base/api/form-control-unstyled.json @@ -2,9 +2,9 @@ "props": { "children": { "type": { "name": "union", "description": "node
| func" } }, "component": { "type": { "name": "elementType" } }, - "disabled": { "type": { "name": "bool" } }, - "error": { "type": { "name": "bool" } }, - "required": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "error": { "type": { "name": "bool" }, "default": "false" }, + "required": { "type": { "name": "bool" }, "default": "false" }, "slotProps": { "type": { "name": "shape", "description": "{ root?: func
| object }" }, "default": "{}" diff --git a/docs/pages/base/api/input-unstyled.json b/docs/pages/base/api/input-unstyled.json index 6119f8483e4df8..15bc795ae065f9 100644 --- a/docs/pages/base/api/input-unstyled.json +++ b/docs/pages/base/api/input-unstyled.json @@ -11,7 +11,7 @@ "id": { "type": { "name": "string" } }, "maxRows": { "type": { "name": "number" } }, "minRows": { "type": { "name": "number" } }, - "multiline": { "type": { "name": "bool" } }, + "multiline": { "type": { "name": "bool" }, "default": "false" }, "name": { "type": { "name": "string" } }, "placeholder": { "type": { "name": "string" } }, "readOnly": { "type": { "name": "bool" } }, diff --git a/docs/pages/base/api/menu-item-unstyled.json b/docs/pages/base/api/menu-item-unstyled.json index dec6ad9cb8b796..a5a26e8126cb9c 100644 --- a/docs/pages/base/api/menu-item-unstyled.json +++ b/docs/pages/base/api/menu-item-unstyled.json @@ -1,7 +1,7 @@ { "props": { "component": { "type": { "name": "elementType" } }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "label": { "type": { "name": "string" } }, "slotProps": { "type": { "name": "shape", "description": "{ root?: func
| object }" }, diff --git a/docs/pages/base/api/menu-unstyled.json b/docs/pages/base/api/menu-unstyled.json index f5dc28f0a806bd..d366f4d5d1603e 100644 --- a/docs/pages/base/api/menu-unstyled.json +++ b/docs/pages/base/api/menu-unstyled.json @@ -8,9 +8,9 @@ } }, "component": { "type": { "name": "elementType" } }, - "keepMounted": { "type": { "name": "bool" } }, + "keepMounted": { "type": { "name": "bool" }, "default": "false" }, "onClose": { "type": { "name": "func" } }, - "open": { "type": { "name": "bool" } }, + "open": { "type": { "name": "bool" }, "default": "false" }, "slotProps": { "type": { "name": "shape", diff --git a/docs/pages/base/api/modal-unstyled.json b/docs/pages/base/api/modal-unstyled.json index f0a9f32e3c8123..4647cf6e2f62f3 100644 --- a/docs/pages/base/api/modal-unstyled.json +++ b/docs/pages/base/api/modal-unstyled.json @@ -3,17 +3,17 @@ "children": { "type": { "name": "custom", "description": "element" }, "required": true }, "open": { "type": { "name": "bool" }, "required": true }, "classes": { "type": { "name": "object" } }, - "closeAfterTransition": { "type": { "name": "bool" } }, + "closeAfterTransition": { "type": { "name": "bool" }, "default": "false" }, "component": { "type": { "name": "elementType" } }, "container": { "type": { "name": "union", "description": "HTML element
| func" } }, - "disableAutoFocus": { "type": { "name": "bool" } }, - "disableEnforceFocus": { "type": { "name": "bool" } }, - "disableEscapeKeyDown": { "type": { "name": "bool" } }, - "disablePortal": { "type": { "name": "bool" } }, - "disableRestoreFocus": { "type": { "name": "bool" } }, - "disableScrollLock": { "type": { "name": "bool" } }, - "hideBackdrop": { "type": { "name": "bool" } }, - "keepMounted": { "type": { "name": "bool" } }, + "disableAutoFocus": { "type": { "name": "bool" }, "default": "false" }, + "disableEnforceFocus": { "type": { "name": "bool" }, "default": "false" }, + "disableEscapeKeyDown": { "type": { "name": "bool" }, "default": "false" }, + "disablePortal": { "type": { "name": "bool" }, "default": "false" }, + "disableRestoreFocus": { "type": { "name": "bool" }, "default": "false" }, + "disableScrollLock": { "type": { "name": "bool" }, "default": "false" }, + "hideBackdrop": { "type": { "name": "bool" }, "default": "false" }, + "keepMounted": { "type": { "name": "bool" }, "default": "false" }, "onBackdropClick": { "type": { "name": "func" }, "deprecated": true, diff --git a/docs/pages/base/api/multi-select-unstyled.json b/docs/pages/base/api/multi-select-unstyled.json index 061326ea2d836f..106f9b34eafdf6 100644 --- a/docs/pages/base/api/multi-select-unstyled.json +++ b/docs/pages/base/api/multi-select-unstyled.json @@ -1,10 +1,10 @@ { "props": { - "autoFocus": { "type": { "name": "bool" } }, + "autoFocus": { "type": { "name": "bool" }, "default": "false" }, "component": { "type": { "name": "elementType" } }, - "defaultListboxOpen": { "type": { "name": "bool" } }, + "defaultListboxOpen": { "type": { "name": "bool" }, "default": "false" }, "defaultValue": { "type": { "name": "array" }, "default": "[]" }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "getSerializedValue": { "type": { "name": "func" } }, "listboxId": { "type": { "name": "string" } }, "listboxOpen": { "type": { "name": "bool" }, "default": "undefined" }, diff --git a/docs/pages/base/api/no-ssr.json b/docs/pages/base/api/no-ssr.json index db2b52a4e84a18..7d30f785012183 100644 --- a/docs/pages/base/api/no-ssr.json +++ b/docs/pages/base/api/no-ssr.json @@ -1,7 +1,7 @@ { "props": { "children": { "type": { "name": "node" } }, - "defer": { "type": { "name": "bool" } }, + "defer": { "type": { "name": "bool" }, "default": "false" }, "fallback": { "type": { "name": "node" }, "default": "null" } }, "name": "NoSsr", diff --git a/docs/pages/base/api/option-group-unstyled.json b/docs/pages/base/api/option-group-unstyled.json index 6b2ec3fec55506..b8f6f18ebf8cd0 100644 --- a/docs/pages/base/api/option-group-unstyled.json +++ b/docs/pages/base/api/option-group-unstyled.json @@ -1,7 +1,7 @@ { "props": { "component": { "type": { "name": "elementType" } }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "label": { "type": { "name": "node" } }, "slotProps": { "type": { diff --git a/docs/pages/base/api/option-unstyled.json b/docs/pages/base/api/option-unstyled.json index c8692f2ec55735..bf0272a430848e 100644 --- a/docs/pages/base/api/option-unstyled.json +++ b/docs/pages/base/api/option-unstyled.json @@ -2,7 +2,7 @@ "props": { "value": { "type": { "name": "any" }, "required": true }, "component": { "type": { "name": "elementType" } }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "label": { "type": { "name": "string" } }, "slotProps": { "type": { "name": "shape", "description": "{ root?: func
| object }" }, diff --git a/docs/pages/base/api/popper-unstyled.json b/docs/pages/base/api/popper-unstyled.json index 0b02a1cbcf978a..a9f432d9abc257 100644 --- a/docs/pages/base/api/popper-unstyled.json +++ b/docs/pages/base/api/popper-unstyled.json @@ -13,8 +13,8 @@ "type": { "name": "enum", "description": "'ltr'
| 'rtl'" }, "default": "'ltr'" }, - "disablePortal": { "type": { "name": "bool" } }, - "keepMounted": { "type": { "name": "bool" } }, + "disablePortal": { "type": { "name": "bool" }, "default": "false" }, + "keepMounted": { "type": { "name": "bool" }, "default": "false" }, "modifiers": { "type": { "name": "arrayOf", @@ -44,7 +44,7 @@ "type": { "name": "shape", "description": "{ root?: elementType }" }, "default": "{}" }, - "transition": { "type": { "name": "bool" } } + "transition": { "type": { "name": "bool" }, "default": "false" } }, "name": "PopperUnstyled", "styles": { "classes": [], "globalClasses": {}, "name": null }, diff --git a/docs/pages/base/api/portal.json b/docs/pages/base/api/portal.json index 070dcbb50644cd..efff7c204bd87a 100644 --- a/docs/pages/base/api/portal.json +++ b/docs/pages/base/api/portal.json @@ -2,7 +2,7 @@ "props": { "children": { "type": { "name": "node" } }, "container": { "type": { "name": "union", "description": "HTML element
| func" } }, - "disablePortal": { "type": { "name": "bool" } } + "disablePortal": { "type": { "name": "bool" }, "default": "false" } }, "name": "Portal", "styles": { "classes": [], "globalClasses": {}, "name": null }, diff --git a/docs/pages/base/api/select-unstyled.json b/docs/pages/base/api/select-unstyled.json index 19ce9d2148f620..f1f95452f7f71e 100644 --- a/docs/pages/base/api/select-unstyled.json +++ b/docs/pages/base/api/select-unstyled.json @@ -1,10 +1,10 @@ { "props": { - "autoFocus": { "type": { "name": "bool" } }, + "autoFocus": { "type": { "name": "bool" }, "default": "false" }, "component": { "type": { "name": "elementType" } }, - "defaultListboxOpen": { "type": { "name": "bool" } }, + "defaultListboxOpen": { "type": { "name": "bool" }, "default": "false" }, "defaultValue": { "type": { "name": "any" } }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "getSerializedValue": { "type": { "name": "func" } }, "listboxId": { "type": { "name": "string" } }, "listboxOpen": { "type": { "name": "bool" }, "default": "undefined" }, diff --git a/docs/pages/base/api/slider-unstyled.json b/docs/pages/base/api/slider-unstyled.json index 810e019f824f42..e4af3218df1492 100644 --- a/docs/pages/base/api/slider-unstyled.json +++ b/docs/pages/base/api/slider-unstyled.json @@ -8,11 +8,11 @@ "defaultValue": { "type": { "name": "union", "description": "Array<number>
| number" } }, - "disabled": { "type": { "name": "bool" } }, - "disableSwap": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableSwap": { "type": { "name": "bool" }, "default": "false" }, "getAriaLabel": { "type": { "name": "func" } }, "getAriaValueText": { "type": { "name": "func" } }, - "isRtl": { "type": { "name": "bool" } }, + "isRtl": { "type": { "name": "bool" }, "default": "false" }, "marks": { "type": { "name": "union", @@ -29,11 +29,11 @@ "type": { "name": "enum", "description": "'horizontal'
| 'vertical'" }, "default": "'horizontal'" }, - "scale": { "type": { "name": "func" }, "default": "(x) => x" }, + "scale": { "type": { "name": "func" }, "default": "function Identity(x) {\n return x;\n}" }, "slotProps": { "type": { "name": "shape", - "description": "{ input?: func
| object, mark?: func
| object, markLabel?: func
| object, rail?: func
| object, root?: func
| object, thumb?: func
| object, track?: func
| object, valueLabel?: func
| { children?: element, className?: string, open?: bool, style?: object, value?: number, valueLabelDisplay?: 'auto'
| 'off'
| 'on' } }" + "description": "{ input?: func
| object, mark?: func
| object, markLabel?: func
| object, rail?: func
| object, root?: func
| object, thumb?: func
| object, track?: func
| object, valueLabel?: any
| func }" }, "default": "{}" }, @@ -56,13 +56,9 @@ "value": { "type": { "name": "union", "description": "Array<number>
| number" } }, - "valueLabelDisplay": { - "type": { "name": "enum", "description": "'auto'
| 'off'
| 'on'" }, - "default": "'off'" - }, "valueLabelFormat": { "type": { "name": "union", "description": "func
| string" }, - "default": "(x) => x" + "default": "function Identity(x) {\n return x;\n}" } }, "name": "SliderUnstyled", @@ -80,10 +76,6 @@ "thumb", "active", "focusVisible", - "valueLabel", - "valueLabelOpen", - "valueLabelCircle", - "valueLabelLabel", "mark", "markActive", "markLabel", @@ -102,10 +94,6 @@ "thumb": "MuiSlider-thumb", "active": "Mui-active", "focusVisible": "Mui-focusVisible", - "valueLabel": "MuiSlider-valueLabel", - "valueLabelOpen": "MuiSlider-valueLabelOpen", - "valueLabelCircle": "MuiSlider-valueLabelCircle", - "valueLabelLabel": "MuiSlider-valueLabelLabel", "mark": "MuiSlider-mark", "markActive": "MuiSlider-markActive", "markLabel": "MuiSlider-markLabel", @@ -115,7 +103,7 @@ }, "spread": true, "forwardsRefTo": "HTMLSpanElement", - "filename": "/packages/mui-base/src/SliderUnstyled/SliderUnstyled.js", + "filename": "/packages/mui-base/src/SliderUnstyled/SliderUnstyled.tsx", "inheritance": null, "demos": "", "cssComponent": false diff --git a/docs/pages/base/api/snackbar-unstyled.json b/docs/pages/base/api/snackbar-unstyled.json index e12e2341a17e74..0517f39d14fbca 100644 --- a/docs/pages/base/api/snackbar-unstyled.json +++ b/docs/pages/base/api/snackbar-unstyled.json @@ -2,7 +2,7 @@ "props": { "autoHideDuration": { "type": { "name": "number" }, "default": "null" }, "component": { "type": { "name": "elementType" } }, - "disableWindowBlurListener": { "type": { "name": "bool" } }, + "disableWindowBlurListener": { "type": { "name": "bool" }, "default": "false" }, "exited": { "type": { "name": "bool" }, "default": "true" }, "onClose": { "type": { "name": "func" } }, "open": { "type": { "name": "bool" } }, diff --git a/docs/pages/base/api/tab-unstyled.json b/docs/pages/base/api/tab-unstyled.json index 9ea5db19aa392d..ae3d0e1266a936 100644 --- a/docs/pages/base/api/tab-unstyled.json +++ b/docs/pages/base/api/tab-unstyled.json @@ -7,7 +7,7 @@ } }, "component": { "type": { "name": "elementType" } }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "onChange": { "type": { "name": "func" } }, "slotProps": { "type": { "name": "shape", "description": "{ root?: func
| object }" }, diff --git a/docs/pages/base/api/table-pagination-unstyled.json b/docs/pages/base/api/table-pagination-unstyled.json index d200d7d523fd6e..1ccb0f8f9c9bda 100644 --- a/docs/pages/base/api/table-pagination-unstyled.json +++ b/docs/pages/base/api/table-pagination-unstyled.json @@ -40,7 +40,35 @@ } }, "name": "TablePaginationUnstyled", - "styles": { "classes": [], "globalClasses": {}, "name": null }, + "styles": { + "classes": [ + "root", + "toolbar", + "spacer", + "selectLabel", + "selectRoot", + "select", + "selectIcon", + "input", + "menuItem", + "displayedRows", + "actions" + ], + "globalClasses": { + "root": "MuiTablePagination-root", + "toolbar": "MuiTablePagination-toolbar", + "spacer": "MuiTablePagination-spacer", + "selectLabel": "MuiTablePagination-selectLabel", + "selectRoot": "MuiTablePagination-selectRoot", + "select": "MuiTablePagination-select", + "selectIcon": "MuiTablePagination-selectIcon", + "input": "MuiTablePagination-input", + "menuItem": "MuiTablePagination-menuItem", + "displayedRows": "MuiTablePagination-displayedRows", + "actions": "MuiTablePagination-actions" + }, + "name": null + }, "spread": true, "forwardsRefTo": "HTMLTableCellElement", "filename": "/packages/mui-base/src/TablePaginationUnstyled/TablePaginationUnstyled.tsx", diff --git a/docs/pages/blog.tsx b/docs/pages/blog.tsx index f025f33639bcb4..2e53f9016e0171 100644 --- a/docs/pages/blog.tsx +++ b/docs/pages/blog.tsx @@ -23,9 +23,11 @@ import BrandingCssVarsProvider from 'docs/src/BrandingCssVarsProvider'; import { authors as AUTHORS } from 'docs/src/modules/components/TopLayoutBlog'; import HeroEnd from 'docs/src/components/home/HeroEnd'; import Link from 'docs/src/modules/components/Link'; +import generateRssFeed from 'docs/scripts/generateRSSFeed'; export const getStaticProps = () => { const data = getAllBlogPosts(); + generateRssFeed(data.allBlogPosts); return { props: data, }; diff --git a/docs/pages/blog/making-customizable-components.md b/docs/pages/blog/making-customizable-components.md index dcc928d7db5203..8aa6bbb8a26587 100644 --- a/docs/pages/blog/making-customizable-components.md +++ b/docs/pages/blog/making-customizable-components.md @@ -46,13 +46,15 @@ you can play around with it in [CodeSandbox](https://codesandbox.io/s/fast-http- ```css /* two classes are more specific than the default single class selector */ .uglySwitch .MuiSwitch-thumb { - background-color: 'green'; + background-color: green; } + .uglySwitch .MuiTouchRipple-root { - border: 'solid red 2px'; + border: 2px solid red; } + .uglySwitch .MuiSwitch-track { - background-color: 'orange'; + background-color: orange; opacity: 1; } ``` @@ -257,9 +259,9 @@ By adding this prop to the default filter panel, we can derive a customized pane ```jsx import { GridFilterPanel } from '@mui/x-data-grid'; -const CustomFilterPanel = (props) => ( - -); +function CustomFilterPanel(props) { + return ; +} ``` But this strategy of adding props to customize components is a bit verbose. diff --git a/docs/pages/blog/v6-beta-pickers.js b/docs/pages/blog/v6-beta-pickers.js new file mode 100644 index 00000000000000..71a077ecc16810 --- /dev/null +++ b/docs/pages/blog/v6-beta-pickers.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import TopLayoutBlog from 'docs/src/modules/components/TopLayoutBlog'; +import { docs } from './v6-beta-pickers.md?@mui/markdown'; + +export default function Page() { + return ; +} diff --git a/docs/pages/blog/v6-beta-pickers.md b/docs/pages/blog/v6-beta-pickers.md new file mode 100644 index 00000000000000..dd725446b5dd0c --- /dev/null +++ b/docs/pages/blog/v6-beta-pickers.md @@ -0,0 +1,126 @@ +--- +title: Date and Time Pickers revamped +description: Check out the new features coming in v6 beta. +date: 2023-01-22T00:00:00.000Z +authors: ['josefreitas'] +tags: ['MUI X', 'News'] +--- + +There's a lot of exciting news in [MUI X v6.0.0-beta.0](https://github.com/mui/mui-x/releases/v6.0.0-beta.0), but there's hardly anything comparable to the revamp we're delivering for the Date and Time Pickers. + +This is the result of our ongoing efforts to improve the usability and customizability of these components. +We kept the best aspects of the previous versions, and we're fleshing out the package with a [new documentation](https://next.mui.com/x/react-date-pickers/getting-started/), major new features and one fundamental change: a new input type to replace the masked text fields. + +## The new date and time fields + +These new input components are called [Fields](https://next.mui.com/x/react-date-pickers/fields/), and they provide massive improvements to the experience of editing the value with a keyboard. + +The previous generation of pickers, whose text input is based on a [mask approach](https://www.npmjs.com/package/rifm), are often cumbersome and fall flat on edge cases as well simple cases like modifying dates. + +For example, watch what happens when we edit the month on this masked input: + + + +As you can notice, the day and year leak to the previous sections of the date, presenting a serious challenge to usability. + +In contrast, the new fields are specialized in editing date and time values. +They recognize the values on the input (day, month, year, etc.) and respond accordingly. + + + +The Fields are included in the pickers, but they're also available as standalone components. +You can import them from the latest v6 package. + +```jsx +import { DateField } from '@mui/x-date-pickers/DateField'; + +; +``` + +They're by default used in the new Pickers (you don't need to declare a text field anymore). + +```jsx +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +; +``` + +## Enhanced keyboard usability + +With the new Fields, the keyboard interaction is a first-class experience. +Not only can you type the date as text, but you can also use arrow keys to navigate and edit date and time values. + + + +Moreover, notice in the following example that as we increase the month, the component automatically watches for valid values throughout each piece of your date input, like you're navigating in a calendar. + + + +For a quick comparison, let's check out how the old and new approaches behave in typical scenarios. + + + +Please, try it out for yourself in the live demo below. + + + +### Fields roadmap + +The Fields are still in beta, and there are many improvements on the way. +The following list describes some of the most notable features planned. + +- **[Smart pasting](https://github.com/mui/mui-x/issues/7253)** \ + Date strings pasted in Fields will be parsed and matched with the sections of the date. +- **[Support days of the week](https://github.com/mui/mui-x/issues/7254)** \ + Users will be able to select a day in the week just like the can select a month. + +We'd love to hear your [feedback](https://github.com/mui/mui-x/issues/new/choose) to help us improve these components even further. + +## Other significant improvements + +Now that you've seen what's fundamentally changed with the Pickers, let's briefly review some other noteworthy improvements. + +- **[Customization of layout and internal components](https://next.mui.com/x/react-date-pickers/custom-layout/)** \ + Combining the concept of slots with the grid layout, you now can rearrange, extend, and customize most of the components used internally by the Pickers' views. +- **Default render input**\ + You don't need to provide the usual `TextField` on `renderInput` anymore unless you need it customized. + In which case you can do it by: + + 1. Customizing through props via `field` and `input` slots ([codebox example](https://codesandbox.io/s/customizing-fields-with-props-o66r1c?file=/demo.tsx)). + 2. Build a new field component using the Field's headless API (documentation coming soon). + 3. Use an entirely [custom text field](https://next.mui.com/x/react-date-pickers/date-picker/#custom-input-component) to suit your use case. + +- **Drag to edit**\ + Editing a date range is even easier now with the new drag-and-drop interface. Change `start` and `end` dates at will. + +- **Range shortcuts** (available from v6.0.0-beta.1)\ + Add quick and customizable shortcuts for your users. Choose to display them on the left, right, bottom or top. + Date Range shortcuts. + +## Should we retire the masked inputs? + +We believe that after using the date fields, you'll have no reason to come back to the masked input approach. +It has a few irreparable usability issues, and it sets some hard limits on what we can do with the input. + +Our plan is to replace them entirely, but you can help us steer our roadmap. + +If you want to voice your opinions or get involved, please consider scheduling a [user interview](https://forms.gle/7uq8PzE26FgwkPs46) with us. + +As always, you can get in touch by opening new bug reports or feature requests in our [GitHub repository](https://github.com/mui/mui-x/issues/new/choose). diff --git a/docs/pages/joy-ui/customization/default-theme.js b/docs/pages/joy-ui/customization/default-theme-viewer.js similarity index 82% rename from docs/pages/joy-ui/customization/default-theme.js rename to docs/pages/joy-ui/customization/default-theme-viewer.js index 4353dab2b0658c..f9d7d1f31db2ec 100644 --- a/docs/pages/joy-ui/customization/default-theme.js +++ b/docs/pages/joy-ui/customization/default-theme-viewer.js @@ -1,6 +1,6 @@ import * as React from 'react'; import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from 'docs/data/joy/customization/default-theme/default-theme.md?@mui/markdown'; +import * as pageProps from 'docs/data/joy/customization/default-theme-viewer/default-theme-viewer.md?@mui/markdown'; export default function Page() { return ; diff --git a/docs/pages/joy-ui/customization/theme-tokens.js b/docs/pages/joy-ui/customization/theme-colors.js similarity index 63% rename from docs/pages/joy-ui/customization/theme-tokens.js rename to docs/pages/joy-ui/customization/theme-colors.js index bbd168849dfb1b..3e42d92c980c2c 100644 --- a/docs/pages/joy-ui/customization/theme-tokens.js +++ b/docs/pages/joy-ui/customization/theme-colors.js @@ -1,6 +1,6 @@ import * as React from 'react'; import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from 'docs/data/joy/customization/theme-tokens/theme-tokens.md?@mui/markdown'; +import * as pageProps from 'docs/data/joy/customization/theme-colors/theme-colors.md?@mui/markdown'; export default function Page() { return ; diff --git a/docs/pages/joy-ui/customization/theme-shadow.js b/docs/pages/joy-ui/customization/theme-shadow.js new file mode 100644 index 00000000000000..d7a1c16b7c5481 --- /dev/null +++ b/docs/pages/joy-ui/customization/theme-shadow.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/customization/theme-shadow/theme-shadow.md?@mui/markdown'; + +export default function Page() { + return ; +} diff --git a/docs/pages/joy-ui/react-table.js b/docs/pages/joy-ui/react-table.js new file mode 100644 index 00000000000000..77bc93dc767fbe --- /dev/null +++ b/docs/pages/joy-ui/react-table.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/components/table/table.md?@mui/markdown'; + +export default function Page() { + return ; +} diff --git a/docs/pages/material-ui/api/accordion-actions.json b/docs/pages/material-ui/api/accordion-actions.json index 3aa1d840b66ec9..beed19fb0f2ff3 100644 --- a/docs/pages/material-ui/api/accordion-actions.json +++ b/docs/pages/material-ui/api/accordion-actions.json @@ -2,7 +2,7 @@ "props": { "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, - "disableSpacing": { "type": { "name": "bool" } }, + "disableSpacing": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/accordion.json b/docs/pages/material-ui/api/accordion.json index 7d4d04155f5df6..66f4fe9b18f055 100644 --- a/docs/pages/material-ui/api/accordion.json +++ b/docs/pages/material-ui/api/accordion.json @@ -2,12 +2,12 @@ "props": { "children": { "type": { "name": "custom", "description": "node" }, "required": true }, "classes": { "type": { "name": "object" } }, - "defaultExpanded": { "type": { "name": "bool" } }, - "disabled": { "type": { "name": "bool" } }, - "disableGutters": { "type": { "name": "bool" } }, + "defaultExpanded": { "type": { "name": "bool" }, "default": "false" }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableGutters": { "type": { "name": "bool" }, "default": "false" }, "expanded": { "type": { "name": "bool" } }, "onChange": { "type": { "name": "func" } }, - "square": { "type": { "name": "bool" } }, + "square": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/app-bar.json b/docs/pages/material-ui/api/app-bar.json index a4a0e01301dad5..3a8fce657a8e63 100644 --- a/docs/pages/material-ui/api/app-bar.json +++ b/docs/pages/material-ui/api/app-bar.json @@ -9,7 +9,7 @@ }, "default": "'primary'" }, - "enableColorOnDark": { "type": { "name": "bool" } }, + "enableColorOnDark": { "type": { "name": "bool" }, "default": "false" }, "position": { "type": { "name": "enum", diff --git a/docs/pages/material-ui/api/autocomplete.json b/docs/pages/material-ui/api/autocomplete.json index 0d3560a64fa32e..cca686211fc219 100644 --- a/docs/pages/material-ui/api/autocomplete.json +++ b/docs/pages/material-ui/api/autocomplete.json @@ -2,9 +2,9 @@ "props": { "options": { "type": { "name": "array" }, "required": true }, "renderInput": { "type": { "name": "func" }, "required": true }, - "autoComplete": { "type": { "name": "bool" } }, - "autoHighlight": { "type": { "name": "bool" } }, - "autoSelect": { "type": { "name": "bool" } }, + "autoComplete": { "type": { "name": "bool" }, "default": "false" }, + "autoHighlight": { "type": { "name": "bool" }, "default": "false" }, + "autoSelect": { "type": { "name": "bool" }, "default": "false" }, "blurOnSelect": { "type": { "name": "union", @@ -16,7 +16,7 @@ "classes": { "type": { "name": "object" } }, "clearIcon": { "type": { "name": "node" }, "default": "" }, "clearOnBlur": { "type": { "name": "bool" }, "default": "!props.freeSolo" }, - "clearOnEscape": { "type": { "name": "bool" } }, + "clearOnEscape": { "type": { "name": "bool" }, "default": "false" }, "clearText": { "type": { "name": "string" }, "default": "'Clear'" }, "closeText": { "type": { "name": "string" }, "default": "'Close'" }, "componentsProps": { @@ -30,20 +30,20 @@ "type": { "name": "custom", "description": "any" }, "default": "props.multiple ? [] : null" }, - "disableClearable": { "type": { "name": "bool" } }, - "disableCloseOnSelect": { "type": { "name": "bool" } }, - "disabled": { "type": { "name": "bool" } }, - "disabledItemsFocusable": { "type": { "name": "bool" } }, - "disableListWrap": { "type": { "name": "bool" } }, - "disablePortal": { "type": { "name": "bool" } }, + "disableClearable": { "type": { "name": "bool" }, "default": "false" }, + "disableCloseOnSelect": { "type": { "name": "bool" }, "default": "false" }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" }, + "disableListWrap": { "type": { "name": "bool" }, "default": "false" }, + "disablePortal": { "type": { "name": "bool" }, "default": "false" }, "filterOptions": { "type": { "name": "func" } }, - "filterSelectedOptions": { "type": { "name": "bool" } }, + "filterSelectedOptions": { "type": { "name": "bool" }, "default": "false" }, "forcePopupIcon": { "type": { "name": "union", "description": "'auto'
| bool" }, "default": "'auto'" }, - "freeSolo": { "type": { "name": "bool" } }, - "fullWidth": { "type": { "name": "bool" } }, + "freeSolo": { "type": { "name": "bool" }, "default": "false" }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, "getLimitTagsText": { "type": { "name": "func" }, "default": "(more) => `+${more}`" }, "getOptionDisabled": { "type": { "name": "func" } }, "getOptionLabel": { @@ -53,15 +53,15 @@ "groupBy": { "type": { "name": "func" } }, "handleHomeEndKeys": { "type": { "name": "bool" }, "default": "!props.freeSolo" }, "id": { "type": { "name": "string" } }, - "includeInputInList": { "type": { "name": "bool" } }, + "includeInputInList": { "type": { "name": "bool" }, "default": "false" }, "inputValue": { "type": { "name": "string" } }, "isOptionEqualToValue": { "type": { "name": "func" } }, "limitTags": { "type": { "name": "custom", "description": "integer" }, "default": "-1" }, "ListboxComponent": { "type": { "name": "elementType" }, "default": "'ul'" }, "ListboxProps": { "type": { "name": "object" } }, - "loading": { "type": { "name": "bool" } }, + "loading": { "type": { "name": "bool" }, "default": "false" }, "loadingText": { "type": { "name": "node" }, "default": "'Loadingā€¦'" }, - "multiple": { "type": { "name": "bool" } }, + "multiple": { "type": { "name": "bool" }, "default": "false" }, "noOptionsText": { "type": { "name": "node" }, "default": "'No options'" }, "onChange": { "type": { "name": "func" } }, "onClose": { "type": { "name": "func" } }, @@ -69,12 +69,12 @@ "onInputChange": { "type": { "name": "func" } }, "onOpen": { "type": { "name": "func" } }, "open": { "type": { "name": "bool" } }, - "openOnFocus": { "type": { "name": "bool" } }, + "openOnFocus": { "type": { "name": "bool" }, "default": "false" }, "openText": { "type": { "name": "string" }, "default": "'Open'" }, "PaperComponent": { "type": { "name": "elementType" }, "default": "Paper" }, "PopperComponent": { "type": { "name": "elementType" }, "default": "Popper" }, "popupIcon": { "type": { "name": "node" }, "default": "" }, - "readOnly": { "type": { "name": "bool" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "renderGroup": { "type": { "name": "func" } }, "renderOption": { "type": { "name": "func" } }, "renderTags": { "type": { "name": "func" } }, diff --git a/docs/pages/material-ui/api/backdrop.json b/docs/pages/material-ui/api/backdrop.json index aebe294fc76361..61eb4c56ff41ed 100644 --- a/docs/pages/material-ui/api/backdrop.json +++ b/docs/pages/material-ui/api/backdrop.json @@ -12,7 +12,7 @@ "type": { "name": "shape", "description": "{ root?: object }" }, "default": "{}" }, - "invisible": { "type": { "name": "bool" } }, + "invisible": { "type": { "name": "bool" }, "default": "false" }, "slotProps": { "type": { "name": "shape", "description": "{ root?: object }" }, "default": "{}" diff --git a/docs/pages/material-ui/api/badge.json b/docs/pages/material-ui/api/badge.json index 88177f01071f33..69423b5f2e5692 100644 --- a/docs/pages/material-ui/api/badge.json +++ b/docs/pages/material-ui/api/badge.json @@ -29,13 +29,13 @@ }, "default": "{}" }, - "invisible": { "type": { "name": "bool" } }, + "invisible": { "type": { "name": "bool" }, "default": "false" }, "max": { "type": { "name": "number" }, "default": "99" }, "overlap": { "type": { "name": "enum", "description": "'circular'
| 'rectangular'" }, "default": "'rectangular'" }, - "showZero": { "type": { "name": "bool" } }, + "showZero": { "type": { "name": "bool" }, "default": "false" }, "slotProps": { "type": { "name": "shape", diff --git a/docs/pages/material-ui/api/bottom-navigation.json b/docs/pages/material-ui/api/bottom-navigation.json index bcd227c7df08eb..aefee67d5233d3 100644 --- a/docs/pages/material-ui/api/bottom-navigation.json +++ b/docs/pages/material-ui/api/bottom-navigation.json @@ -4,7 +4,7 @@ "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, "onChange": { "type": { "name": "func" } }, - "showLabels": { "type": { "name": "bool" } }, + "showLabels": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/button-base.json b/docs/pages/material-ui/api/button-base.json index dca661a0aa1464..9416904bd5539a 100644 --- a/docs/pages/material-ui/api/button-base.json +++ b/docs/pages/material-ui/api/button-base.json @@ -1,14 +1,14 @@ { "props": { "action": { "type": { "name": "custom", "description": "ref" } }, - "centerRipple": { "type": { "name": "bool" } }, + "centerRipple": { "type": { "name": "bool" }, "default": "false" }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "custom", "description": "element type" } }, - "disabled": { "type": { "name": "bool" } }, - "disableRipple": { "type": { "name": "bool" } }, - "disableTouchRipple": { "type": { "name": "bool" } }, - "focusRipple": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableRipple": { "type": { "name": "bool" }, "default": "false" }, + "disableTouchRipple": { "type": { "name": "bool" }, "default": "false" }, + "focusRipple": { "type": { "name": "bool" }, "default": "false" }, "focusVisibleClassName": { "type": { "name": "string" } }, "LinkComponent": { "type": { "name": "elementType" }, "default": "'a'" }, "onFocusVisible": { "type": { "name": "func" } }, diff --git a/docs/pages/material-ui/api/button-group.json b/docs/pages/material-ui/api/button-group.json index 62d4462332b2b6..f56bccb4eeeac1 100644 --- a/docs/pages/material-ui/api/button-group.json +++ b/docs/pages/material-ui/api/button-group.json @@ -10,11 +10,11 @@ "default": "'primary'" }, "component": { "type": { "name": "elementType" } }, - "disabled": { "type": { "name": "bool" } }, - "disableElevation": { "type": { "name": "bool" } }, - "disableFocusRipple": { "type": { "name": "bool" } }, - "disableRipple": { "type": { "name": "bool" } }, - "fullWidth": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableElevation": { "type": { "name": "bool" }, "default": "false" }, + "disableFocusRipple": { "type": { "name": "bool" }, "default": "false" }, + "disableRipple": { "type": { "name": "bool" }, "default": "false" }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, "orientation": { "type": { "name": "enum", "description": "'horizontal'
| 'vertical'" }, "default": "'horizontal'" diff --git a/docs/pages/material-ui/api/button.json b/docs/pages/material-ui/api/button.json index c5fffae8e5d842..855c2efb9db0c8 100644 --- a/docs/pages/material-ui/api/button.json +++ b/docs/pages/material-ui/api/button.json @@ -10,12 +10,12 @@ "default": "'primary'" }, "component": { "type": { "name": "elementType" } }, - "disabled": { "type": { "name": "bool" } }, - "disableElevation": { "type": { "name": "bool" } }, - "disableFocusRipple": { "type": { "name": "bool" } }, - "disableRipple": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableElevation": { "type": { "name": "bool" }, "default": "false" }, + "disableFocusRipple": { "type": { "name": "bool" }, "default": "false" }, + "disableRipple": { "type": { "name": "bool" }, "default": "false" }, "endIcon": { "type": { "name": "node" } }, - "fullWidth": { "type": { "name": "bool" } }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, "href": { "type": { "name": "string" } }, "size": { "type": { diff --git a/docs/pages/material-ui/api/card-actions.json b/docs/pages/material-ui/api/card-actions.json index aea0a3c21259d0..3022ff5434e356 100644 --- a/docs/pages/material-ui/api/card-actions.json +++ b/docs/pages/material-ui/api/card-actions.json @@ -2,7 +2,7 @@ "props": { "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, - "disableSpacing": { "type": { "name": "bool" } }, + "disableSpacing": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/card-header.json b/docs/pages/material-ui/api/card-header.json index 52dc6b11c49424..049e7feb273082 100644 --- a/docs/pages/material-ui/api/card-header.json +++ b/docs/pages/material-ui/api/card-header.json @@ -4,7 +4,7 @@ "avatar": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, - "disableTypography": { "type": { "name": "bool" } }, + "disableTypography": { "type": { "name": "bool" }, "default": "false" }, "subheader": { "type": { "name": "node" } }, "subheaderTypographyProps": { "type": { "name": "object" } }, "sx": { diff --git a/docs/pages/material-ui/api/checkbox.json b/docs/pages/material-ui/api/checkbox.json index 4494ffa485d98a..e1ee7c81743a2f 100644 --- a/docs/pages/material-ui/api/checkbox.json +++ b/docs/pages/material-ui/api/checkbox.json @@ -11,16 +11,16 @@ "default": "'primary'" }, "defaultChecked": { "type": { "name": "bool" } }, - "disabled": { "type": { "name": "bool" } }, - "disableRipple": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableRipple": { "type": { "name": "bool" }, "default": "false" }, "icon": { "type": { "name": "node" }, "default": "" }, "id": { "type": { "name": "string" } }, - "indeterminate": { "type": { "name": "bool" } }, + "indeterminate": { "type": { "name": "bool" }, "default": "false" }, "indeterminateIcon": { "type": { "name": "node" }, "default": "" }, "inputProps": { "type": { "name": "object" } }, "inputRef": { "type": { "name": "custom", "description": "ref" } }, "onChange": { "type": { "name": "func" } }, - "required": { "type": { "name": "bool" } }, + "required": { "type": { "name": "bool" }, "default": "false" }, "size": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/chip.json b/docs/pages/material-ui/api/chip.json index 2d8251bf56d0f3..5739bd649d6f04 100644 --- a/docs/pages/material-ui/api/chip.json +++ b/docs/pages/material-ui/api/chip.json @@ -13,7 +13,7 @@ }, "component": { "type": { "name": "elementType" } }, "deleteIcon": { "type": { "name": "element" } }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "icon": { "type": { "name": "element" } }, "label": { "type": { "name": "node" } }, "onDelete": { "type": { "name": "func" } }, @@ -24,7 +24,7 @@ }, "default": "'medium'" }, - "skipFocusWhenDisabled": { "type": { "name": "bool" } }, + "skipFocusWhenDisabled": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/css-baseline.json b/docs/pages/material-ui/api/css-baseline.json index f883305ba828e9..1c6085454ef209 100644 --- a/docs/pages/material-ui/api/css-baseline.json +++ b/docs/pages/material-ui/api/css-baseline.json @@ -1,7 +1,7 @@ { "props": { "children": { "type": { "name": "node" } }, - "enableColorScheme": { "type": { "name": "bool" } } + "enableColorScheme": { "type": { "name": "bool" }, "default": "false" } }, "name": "CssBaseline", "styles": { "classes": [], "globalClasses": {}, "name": null }, diff --git a/docs/pages/material-ui/api/dialog-actions.json b/docs/pages/material-ui/api/dialog-actions.json index e7aa059e48719c..6b01beb6ef9d95 100644 --- a/docs/pages/material-ui/api/dialog-actions.json +++ b/docs/pages/material-ui/api/dialog-actions.json @@ -2,7 +2,7 @@ "props": { "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, - "disableSpacing": { "type": { "name": "bool" } }, + "disableSpacing": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/dialog-content.json b/docs/pages/material-ui/api/dialog-content.json index 65b25cbaf43bd7..8d9eb39e2f5d0f 100644 --- a/docs/pages/material-ui/api/dialog-content.json +++ b/docs/pages/material-ui/api/dialog-content.json @@ -2,7 +2,7 @@ "props": { "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, - "dividers": { "type": { "name": "bool" } }, + "dividers": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/dialog.json b/docs/pages/material-ui/api/dialog.json index 53ab57bb4ab70d..1832bc1e526c07 100644 --- a/docs/pages/material-ui/api/dialog.json +++ b/docs/pages/material-ui/api/dialog.json @@ -11,9 +11,9 @@ }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, - "disableEscapeKeyDown": { "type": { "name": "bool" } }, - "fullScreen": { "type": { "name": "bool" } }, - "fullWidth": { "type": { "name": "bool" } }, + "disableEscapeKeyDown": { "type": { "name": "bool" }, "default": "false" }, + "fullScreen": { "type": { "name": "bool" }, "default": "false" }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, "maxWidth": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/divider.json b/docs/pages/material-ui/api/divider.json index b2adc9b28a8046..78ac16f26d5f25 100644 --- a/docs/pages/material-ui/api/divider.json +++ b/docs/pages/material-ui/api/divider.json @@ -1,11 +1,11 @@ { "props": { - "absolute": { "type": { "name": "bool" } }, + "absolute": { "type": { "name": "bool" }, "default": "false" }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, - "flexItem": { "type": { "name": "bool" } }, - "light": { "type": { "name": "bool" } }, + "flexItem": { "type": { "name": "bool" }, "default": "false" }, + "light": { "type": { "name": "bool" }, "default": "false" }, "orientation": { "type": { "name": "enum", "description": "'horizontal'
| 'vertical'" }, "default": "'horizontal'" diff --git a/docs/pages/material-ui/api/drawer.json b/docs/pages/material-ui/api/drawer.json index 750968c8530f69..2e7b230b0b708b 100644 --- a/docs/pages/material-ui/api/drawer.json +++ b/docs/pages/material-ui/api/drawer.json @@ -10,10 +10,10 @@ "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "elevation": { "type": { "name": "custom", "description": "integer" }, "default": "16" }, - "hideBackdrop": { "type": { "name": "bool" } }, + "hideBackdrop": { "type": { "name": "bool" }, "default": "false" }, "ModalProps": { "type": { "name": "object" }, "default": "{}" }, "onClose": { "type": { "name": "func" } }, - "open": { "type": { "name": "bool" } }, + "open": { "type": { "name": "bool" }, "default": "false" }, "PaperProps": { "type": { "name": "object" }, "default": "{}" }, "SlideProps": { "type": { "name": "object" } }, "sx": { diff --git a/docs/pages/material-ui/api/fab.json b/docs/pages/material-ui/api/fab.json index 494b1a3a4c79d5..59c2791f0ec52b 100644 --- a/docs/pages/material-ui/api/fab.json +++ b/docs/pages/material-ui/api/fab.json @@ -10,8 +10,8 @@ "default": "'default'" }, "component": { "type": { "name": "elementType" } }, - "disabled": { "type": { "name": "bool" } }, - "disableFocusRipple": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableFocusRipple": { "type": { "name": "bool" }, "default": "false" }, "disableRipple": { "type": { "name": "bool" } }, "href": { "type": { "name": "string" } }, "size": { diff --git a/docs/pages/material-ui/api/filled-input.json b/docs/pages/material-ui/api/filled-input.json index 7c0dcb91135a26..5db9484966a4bd 100644 --- a/docs/pages/material-ui/api/filled-input.json +++ b/docs/pages/material-ui/api/filled-input.json @@ -22,8 +22,8 @@ "disableUnderline": { "type": { "name": "bool" } }, "endAdornment": { "type": { "name": "node" } }, "error": { "type": { "name": "bool" } }, - "fullWidth": { "type": { "name": "bool" } }, - "hiddenLabel": { "type": { "name": "bool" } }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, + "hiddenLabel": { "type": { "name": "bool" }, "default": "false" }, "id": { "type": { "name": "string" } }, "inputComponent": { "type": { "name": "elementType" }, "default": "'input'" }, "inputProps": { "type": { "name": "object" }, "default": "{}" }, @@ -31,7 +31,7 @@ "margin": { "type": { "name": "enum", "description": "'dense'
| 'none'" } }, "maxRows": { "type": { "name": "union", "description": "number
| string" } }, "minRows": { "type": { "name": "union", "description": "number
| string" } }, - "multiline": { "type": { "name": "bool" } }, + "multiline": { "type": { "name": "bool" }, "default": "false" }, "name": { "type": { "name": "string" } }, "onChange": { "type": { "name": "func" } }, "placeholder": { "type": { "name": "string" } }, diff --git a/docs/pages/material-ui/api/form-control.json b/docs/pages/material-ui/api/form-control.json index 99d314869ad9fe..cd1687047aeda4 100644 --- a/docs/pages/material-ui/api/form-control.json +++ b/docs/pages/material-ui/api/form-control.json @@ -10,11 +10,11 @@ "default": "'primary'" }, "component": { "type": { "name": "elementType" } }, - "disabled": { "type": { "name": "bool" } }, - "error": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "error": { "type": { "name": "bool" }, "default": "false" }, "focused": { "type": { "name": "bool" } }, - "fullWidth": { "type": { "name": "bool" } }, - "hiddenLabel": { "type": { "name": "bool" } }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, + "hiddenLabel": { "type": { "name": "bool" }, "default": "false" }, "margin": { "type": { "name": "enum", @@ -22,7 +22,7 @@ }, "default": "'none'" }, - "required": { "type": { "name": "bool" } }, + "required": { "type": { "name": "bool" }, "default": "false" }, "size": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/form-group.json b/docs/pages/material-ui/api/form-group.json index c5f15c24328614..39f5ed0fe79c54 100644 --- a/docs/pages/material-ui/api/form-group.json +++ b/docs/pages/material-ui/api/form-group.json @@ -2,7 +2,7 @@ "props": { "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, - "row": { "type": { "name": "bool" } }, + "row": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/grid.json b/docs/pages/material-ui/api/grid.json index 39d4830d82d609..9f54488f785b36 100644 --- a/docs/pages/material-ui/api/grid.json +++ b/docs/pages/material-ui/api/grid.json @@ -16,7 +16,7 @@ } }, "component": { "type": { "name": "elementType" } }, - "container": { "type": { "name": "bool" } }, + "container": { "type": { "name": "bool" }, "default": "false" }, "direction": { "type": { "name": "union", @@ -24,7 +24,7 @@ }, "default": "'row'" }, - "item": { "type": { "name": "bool" } }, + "item": { "type": { "name": "bool" }, "default": "false" }, "lg": { "type": { "name": "union", @@ -86,7 +86,7 @@ }, "default": "false" }, - "zeroMinWidth": { "type": { "name": "bool" } } + "zeroMinWidth": { "type": { "name": "bool" }, "default": "false" } }, "name": "Grid", "styles": { diff --git a/docs/pages/material-ui/api/hidden.json b/docs/pages/material-ui/api/hidden.json index 2161cc2b75dd0b..5a1b1280d7d9d3 100644 --- a/docs/pages/material-ui/api/hidden.json +++ b/docs/pages/material-ui/api/hidden.json @@ -11,22 +11,22 @@ "description": "'xs'
| 'sm'
| 'md'
| 'lg'
| 'xl'" } }, - "lgDown": { "type": { "name": "bool" } }, - "lgUp": { "type": { "name": "bool" } }, - "mdDown": { "type": { "name": "bool" } }, - "mdUp": { "type": { "name": "bool" } }, + "lgDown": { "type": { "name": "bool" }, "default": "false" }, + "lgUp": { "type": { "name": "bool" }, "default": "false" }, + "mdDown": { "type": { "name": "bool" }, "default": "false" }, + "mdUp": { "type": { "name": "bool" }, "default": "false" }, "only": { "type": { "name": "union", "description": "'xs'
| 'sm'
| 'md'
| 'lg'
| 'xl'
| Array<'xs'
| 'sm'
| 'md'
| 'lg'
| 'xl'>" } }, - "smDown": { "type": { "name": "bool" } }, - "smUp": { "type": { "name": "bool" } }, - "xlDown": { "type": { "name": "bool" } }, - "xlUp": { "type": { "name": "bool" } }, - "xsDown": { "type": { "name": "bool" } }, - "xsUp": { "type": { "name": "bool" } } + "smDown": { "type": { "name": "bool" }, "default": "false" }, + "smUp": { "type": { "name": "bool" }, "default": "false" }, + "xlDown": { "type": { "name": "bool" }, "default": "false" }, + "xlUp": { "type": { "name": "bool" }, "default": "false" }, + "xsDown": { "type": { "name": "bool" }, "default": "false" }, + "xsUp": { "type": { "name": "bool" }, "default": "false" } }, "name": "Hidden", "styles": { "classes": [], "globalClasses": {}, "name": null }, diff --git a/docs/pages/material-ui/api/icon-button.json b/docs/pages/material-ui/api/icon-button.json index 73c91703985447..e0db0d0a705284 100644 --- a/docs/pages/material-ui/api/icon-button.json +++ b/docs/pages/material-ui/api/icon-button.json @@ -9,9 +9,9 @@ }, "default": "'default'" }, - "disabled": { "type": { "name": "bool" } }, - "disableFocusRipple": { "type": { "name": "bool" } }, - "disableRipple": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableFocusRipple": { "type": { "name": "bool" }, "default": "false" }, + "disableRipple": { "type": { "name": "bool" }, "default": "false" }, "edge": { "type": { "name": "enum", diff --git a/docs/pages/material-ui/api/input-adornment.json b/docs/pages/material-ui/api/input-adornment.json index 4e015eb2786a0e..1c4861ab9b541e 100644 --- a/docs/pages/material-ui/api/input-adornment.json +++ b/docs/pages/material-ui/api/input-adornment.json @@ -7,8 +7,8 @@ "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, - "disablePointerEvents": { "type": { "name": "bool" } }, - "disableTypography": { "type": { "name": "bool" } }, + "disablePointerEvents": { "type": { "name": "bool" }, "default": "false" }, + "disableTypography": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/input-base.json b/docs/pages/material-ui/api/input-base.json index aa915da17d6fac..2938883f586566 100644 --- a/docs/pages/material-ui/api/input-base.json +++ b/docs/pages/material-ui/api/input-base.json @@ -19,10 +19,10 @@ }, "defaultValue": { "type": { "name": "any" } }, "disabled": { "type": { "name": "bool" } }, - "disableInjectingGlobalStyles": { "type": { "name": "bool" } }, + "disableInjectingGlobalStyles": { "type": { "name": "bool" }, "default": "false" }, "endAdornment": { "type": { "name": "node" } }, "error": { "type": { "name": "bool" } }, - "fullWidth": { "type": { "name": "bool" } }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, "id": { "type": { "name": "string" } }, "inputComponent": { "type": { "name": "custom", "description": "element type" }, @@ -33,7 +33,7 @@ "margin": { "type": { "name": "enum", "description": "'dense'
| 'none'" } }, "maxRows": { "type": { "name": "union", "description": "number
| string" } }, "minRows": { "type": { "name": "union", "description": "number
| string" } }, - "multiline": { "type": { "name": "bool" } }, + "multiline": { "type": { "name": "bool" }, "default": "false" }, "name": { "type": { "name": "string" } }, "onBlur": { "type": { "name": "func" } }, "onChange": { "type": { "name": "func" } }, diff --git a/docs/pages/material-ui/api/input-label.json b/docs/pages/material-ui/api/input-label.json index 716c178dcf478a..87a2b43b2a82f7 100644 --- a/docs/pages/material-ui/api/input-label.json +++ b/docs/pages/material-ui/api/input-label.json @@ -8,7 +8,7 @@ "description": "'error'
| 'info'
| 'primary'
| 'secondary'
| 'success'
| 'warning'
| string" } }, - "disableAnimation": { "type": { "name": "bool" } }, + "disableAnimation": { "type": { "name": "bool" }, "default": "false" }, "disabled": { "type": { "name": "bool" } }, "error": { "type": { "name": "bool" } }, "focused": { "type": { "name": "bool" } }, diff --git a/docs/pages/material-ui/api/input.json b/docs/pages/material-ui/api/input.json index 06ab9faca0d047..13ba87bedf874f 100644 --- a/docs/pages/material-ui/api/input.json +++ b/docs/pages/material-ui/api/input.json @@ -22,7 +22,7 @@ "disableUnderline": { "type": { "name": "bool" } }, "endAdornment": { "type": { "name": "node" } }, "error": { "type": { "name": "bool" } }, - "fullWidth": { "type": { "name": "bool" } }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, "id": { "type": { "name": "string" } }, "inputComponent": { "type": { "name": "elementType" }, "default": "'input'" }, "inputProps": { "type": { "name": "object" }, "default": "{}" }, @@ -30,7 +30,7 @@ "margin": { "type": { "name": "enum", "description": "'dense'
| 'none'" } }, "maxRows": { "type": { "name": "union", "description": "number
| string" } }, "minRows": { "type": { "name": "union", "description": "number
| string" } }, - "multiline": { "type": { "name": "bool" } }, + "multiline": { "type": { "name": "bool" }, "default": "false" }, "name": { "type": { "name": "string" } }, "onChange": { "type": { "name": "func" } }, "placeholder": { "type": { "name": "string" } }, diff --git a/docs/pages/material-ui/api/list-item-button.json b/docs/pages/material-ui/api/list-item-button.json index de960fdb183f79..f758520225917b 100644 --- a/docs/pages/material-ui/api/list-item-button.json +++ b/docs/pages/material-ui/api/list-item-button.json @@ -4,16 +4,16 @@ "type": { "name": "enum", "description": "'center'
| 'flex-start'" }, "default": "'center'" }, - "autoFocus": { "type": { "name": "bool" } }, + "autoFocus": { "type": { "name": "bool" }, "default": "false" }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, - "dense": { "type": { "name": "bool" } }, - "disabled": { "type": { "name": "bool" } }, - "disableGutters": { "type": { "name": "bool" } }, - "divider": { "type": { "name": "bool" } }, + "dense": { "type": { "name": "bool" }, "default": "false" }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableGutters": { "type": { "name": "bool" }, "default": "false" }, + "divider": { "type": { "name": "bool" }, "default": "false" }, "focusVisibleClassName": { "type": { "name": "string" } }, - "selected": { "type": { "name": "bool" } }, + "selected": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/list-item-text.json b/docs/pages/material-ui/api/list-item-text.json index 986736d83cb3ef..712c37684f44de 100644 --- a/docs/pages/material-ui/api/list-item-text.json +++ b/docs/pages/material-ui/api/list-item-text.json @@ -2,8 +2,8 @@ "props": { "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, - "disableTypography": { "type": { "name": "bool" } }, - "inset": { "type": { "name": "bool" } }, + "disableTypography": { "type": { "name": "bool" }, "default": "false" }, + "inset": { "type": { "name": "bool" }, "default": "false" }, "primary": { "type": { "name": "node" } }, "primaryTypographyProps": { "type": { "name": "object" } }, "secondary": { "type": { "name": "node" } }, diff --git a/docs/pages/material-ui/api/list-item.json b/docs/pages/material-ui/api/list-item.json index 09c43fa770f80e..c2b297e798b10a 100644 --- a/docs/pages/material-ui/api/list-item.json +++ b/docs/pages/material-ui/api/list-item.json @@ -6,11 +6,13 @@ }, "autoFocus": { "type": { "name": "bool" }, + "default": "false", "deprecated": true, "deprecationInfo": "checkout ListItemButton instead" }, "button": { "type": { "name": "bool" }, + "default": "false", "deprecated": true, "deprecationInfo": "checkout ListItemButton instead" }, @@ -31,18 +33,20 @@ "deprecated": true }, "ContainerProps": { "type": { "name": "object" }, "default": "{}", "deprecated": true }, - "dense": { "type": { "name": "bool" } }, + "dense": { "type": { "name": "bool" }, "default": "false" }, "disabled": { "type": { "name": "bool" }, + "default": "false", "deprecated": true, "deprecationInfo": "checkout ListItemButton instead" }, - "disableGutters": { "type": { "name": "bool" } }, - "disablePadding": { "type": { "name": "bool" } }, - "divider": { "type": { "name": "bool" } }, + "disableGutters": { "type": { "name": "bool" }, "default": "false" }, + "disablePadding": { "type": { "name": "bool" }, "default": "false" }, + "divider": { "type": { "name": "bool" }, "default": "false" }, "secondaryAction": { "type": { "name": "node" } }, "selected": { "type": { "name": "bool" }, + "default": "false", "deprecated": true, "deprecationInfo": "checkout ListItemButton instead" }, diff --git a/docs/pages/material-ui/api/list-subheader.json b/docs/pages/material-ui/api/list-subheader.json index 0dc83e7c42ce47..5b1410ce8945bd 100644 --- a/docs/pages/material-ui/api/list-subheader.json +++ b/docs/pages/material-ui/api/list-subheader.json @@ -10,9 +10,9 @@ "default": "'default'" }, "component": { "type": { "name": "elementType" } }, - "disableGutters": { "type": { "name": "bool" } }, - "disableSticky": { "type": { "name": "bool" } }, - "inset": { "type": { "name": "bool" } }, + "disableGutters": { "type": { "name": "bool" }, "default": "false" }, + "disableSticky": { "type": { "name": "bool" }, "default": "false" }, + "inset": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/list.json b/docs/pages/material-ui/api/list.json index 4a20714dd18aeb..074b65164b7ef3 100644 --- a/docs/pages/material-ui/api/list.json +++ b/docs/pages/material-ui/api/list.json @@ -3,8 +3,8 @@ "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, - "dense": { "type": { "name": "bool" } }, - "disablePadding": { "type": { "name": "bool" } }, + "dense": { "type": { "name": "bool" }, "default": "false" }, + "disablePadding": { "type": { "name": "bool" }, "default": "false" }, "subheader": { "type": { "name": "node" } }, "sx": { "type": { diff --git a/docs/pages/material-ui/api/loading-button.json b/docs/pages/material-ui/api/loading-button.json index eb48367d37ac29..da366c62e9153c 100644 --- a/docs/pages/material-ui/api/loading-button.json +++ b/docs/pages/material-ui/api/loading-button.json @@ -2,8 +2,8 @@ "props": { "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, - "disabled": { "type": { "name": "bool" } }, - "loading": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "loading": { "type": { "name": "bool" }, "default": "false" }, "loadingIndicator": { "type": { "name": "node" }, "default": "" diff --git a/docs/pages/material-ui/api/menu-item.json b/docs/pages/material-ui/api/menu-item.json index 3cd2757aeb40ae..52b9047a815ff1 100644 --- a/docs/pages/material-ui/api/menu-item.json +++ b/docs/pages/material-ui/api/menu-item.json @@ -1,14 +1,14 @@ { "props": { - "autoFocus": { "type": { "name": "bool" } }, + "autoFocus": { "type": { "name": "bool" }, "default": "false" }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, - "dense": { "type": { "name": "bool" } }, - "disableGutters": { "type": { "name": "bool" } }, - "divider": { "type": { "name": "bool" } }, + "dense": { "type": { "name": "bool" }, "default": "false" }, + "disableGutters": { "type": { "name": "bool" }, "default": "false" }, + "divider": { "type": { "name": "bool" }, "default": "false" }, "focusVisibleClassName": { "type": { "name": "string" } }, - "selected": { "type": { "name": "bool" } }, + "selected": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/menu-list.json b/docs/pages/material-ui/api/menu-list.json index df784b45646ea7..7c1f3095b33c84 100644 --- a/docs/pages/material-ui/api/menu-list.json +++ b/docs/pages/material-ui/api/menu-list.json @@ -1,17 +1,21 @@ { "props": { - "autoFocus": { "type": { "name": "bool" } }, - "autoFocusItem": { "type": { "name": "bool" } }, + "autoFocus": { "type": { "name": "bool" }, "default": "false" }, + "autoFocusItem": { "type": { "name": "bool" }, "default": "false" }, "children": { "type": { "name": "node" } }, - "disabledItemsFocusable": { "type": { "name": "bool" } }, - "disableListWrap": { "type": { "name": "bool" } }, + "disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" }, + "disableListWrap": { "type": { "name": "bool" }, "default": "false" }, "variant": { "type": { "name": "enum", "description": "'menu'
| 'selectedMenu'" }, "default": "'selectedMenu'" } }, "name": "MenuList", - "styles": { "classes": [], "globalClasses": {}, "name": null }, + "styles": { + "classes": ["root", "padding", "dense", "subheader"], + "globalClasses": {}, + "name": "MuiMenuList" + }, "spread": true, "forwardsRefTo": "HTMLUListElement", "filename": "/packages/mui-material/src/MenuList/MenuList.js", diff --git a/docs/pages/material-ui/api/menu.json b/docs/pages/material-ui/api/menu.json index 9eb48a581fa40b..be960662071ae6 100644 --- a/docs/pages/material-ui/api/menu.json +++ b/docs/pages/material-ui/api/menu.json @@ -5,7 +5,7 @@ "autoFocus": { "type": { "name": "bool" }, "default": "true" }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, - "disableAutoFocusItem": { "type": { "name": "bool" } }, + "disableAutoFocusItem": { "type": { "name": "bool" }, "default": "false" }, "MenuListProps": { "type": { "name": "object" }, "default": "{}" }, "onClose": { "type": { "name": "func" } }, "PopoverClasses": { "type": { "name": "object" } }, diff --git a/docs/pages/material-ui/api/modal.json b/docs/pages/material-ui/api/modal.json index 8c6962e0b71e9f..d0e44005a3572f 100644 --- a/docs/pages/material-ui/api/modal.json +++ b/docs/pages/material-ui/api/modal.json @@ -14,7 +14,7 @@ "deprecationInfo": "Use slotProps.backdrop instead." }, "classes": { "type": { "name": "object" } }, - "closeAfterTransition": { "type": { "name": "bool" } }, + "closeAfterTransition": { "type": { "name": "bool" }, "default": "false" }, "component": { "type": { "name": "elementType" } }, "components": { "type": { "name": "shape", "description": "{ Backdrop?: elementType, Root?: elementType }" }, @@ -28,14 +28,14 @@ "default": "{}" }, "container": { "type": { "name": "union", "description": "HTML element
| func" } }, - "disableAutoFocus": { "type": { "name": "bool" } }, - "disableEnforceFocus": { "type": { "name": "bool" } }, - "disableEscapeKeyDown": { "type": { "name": "bool" } }, - "disablePortal": { "type": { "name": "bool" } }, - "disableRestoreFocus": { "type": { "name": "bool" } }, - "disableScrollLock": { "type": { "name": "bool" } }, - "hideBackdrop": { "type": { "name": "bool" } }, - "keepMounted": { "type": { "name": "bool" } }, + "disableAutoFocus": { "type": { "name": "bool" }, "default": "false" }, + "disableEnforceFocus": { "type": { "name": "bool" }, "default": "false" }, + "disableEscapeKeyDown": { "type": { "name": "bool" }, "default": "false" }, + "disablePortal": { "type": { "name": "bool" }, "default": "false" }, + "disableRestoreFocus": { "type": { "name": "bool" }, "default": "false" }, + "disableScrollLock": { "type": { "name": "bool" }, "default": "false" }, + "hideBackdrop": { "type": { "name": "bool" }, "default": "false" }, + "keepMounted": { "type": { "name": "bool" }, "default": "false" }, "onBackdropClick": { "type": { "name": "func" }, "deprecated": true, diff --git a/docs/pages/material-ui/api/outlined-input.json b/docs/pages/material-ui/api/outlined-input.json index 1f71d6528410cb..aa05f61ba41fd6 100644 --- a/docs/pages/material-ui/api/outlined-input.json +++ b/docs/pages/material-ui/api/outlined-input.json @@ -17,7 +17,7 @@ "disabled": { "type": { "name": "bool" } }, "endAdornment": { "type": { "name": "node" } }, "error": { "type": { "name": "bool" } }, - "fullWidth": { "type": { "name": "bool" } }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, "id": { "type": { "name": "string" } }, "inputComponent": { "type": { "name": "elementType" }, "default": "'input'" }, "inputProps": { "type": { "name": "object" }, "default": "{}" }, @@ -26,7 +26,7 @@ "margin": { "type": { "name": "enum", "description": "'dense'
| 'none'" } }, "maxRows": { "type": { "name": "union", "description": "number
| string" } }, "minRows": { "type": { "name": "union", "description": "number
| string" } }, - "multiline": { "type": { "name": "bool" } }, + "multiline": { "type": { "name": "bool" }, "default": "false" }, "name": { "type": { "name": "string" } }, "notched": { "type": { "name": "bool" } }, "onChange": { "type": { "name": "func" } }, diff --git a/docs/pages/material-ui/api/pagination-item.json b/docs/pages/material-ui/api/pagination-item.json index 9a169fe3b6d2c2..51be4568bc71f0 100644 --- a/docs/pages/material-ui/api/pagination-item.json +++ b/docs/pages/material-ui/api/pagination-item.json @@ -16,9 +16,9 @@ }, "default": "{}" }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "page": { "type": { "name": "node" } }, - "selected": { "type": { "name": "bool" } }, + "selected": { "type": { "name": "bool" }, "default": "false" }, "shape": { "type": { "name": "enum", "description": "'circular'
| 'rounded'" }, "default": "'circular'" diff --git a/docs/pages/material-ui/api/pagination.json b/docs/pages/material-ui/api/pagination.json index 245b51f28fb6d9..74381ee3355ccb 100644 --- a/docs/pages/material-ui/api/pagination.json +++ b/docs/pages/material-ui/api/pagination.json @@ -11,10 +11,10 @@ }, "count": { "type": { "name": "custom", "description": "integer" }, "default": "1" }, "defaultPage": { "type": { "name": "custom", "description": "integer" }, "default": "1" }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "getItemAriaLabel": { "type": { "name": "func" } }, - "hideNextButton": { "type": { "name": "bool" } }, - "hidePrevButton": { "type": { "name": "bool" } }, + "hideNextButton": { "type": { "name": "bool" }, "default": "false" }, + "hidePrevButton": { "type": { "name": "bool" }, "default": "false" }, "onChange": { "type": { "name": "func" } }, "page": { "type": { "name": "custom", "description": "integer" } }, "renderItem": { @@ -25,8 +25,8 @@ "type": { "name": "enum", "description": "'circular'
| 'rounded'" }, "default": "'circular'" }, - "showFirstButton": { "type": { "name": "bool" } }, - "showLastButton": { "type": { "name": "bool" } }, + "showFirstButton": { "type": { "name": "bool" }, "default": "false" }, + "showLastButton": { "type": { "name": "bool" }, "default": "false" }, "siblingCount": { "type": { "name": "custom", "description": "integer" }, "default": "1" }, "size": { "type": { diff --git a/docs/pages/material-ui/api/paper.json b/docs/pages/material-ui/api/paper.json index 62bc4cb90ccc73..449081d0501ae1 100644 --- a/docs/pages/material-ui/api/paper.json +++ b/docs/pages/material-ui/api/paper.json @@ -4,7 +4,7 @@ "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, "elevation": { "type": { "name": "custom", "description": "integer" }, "default": "1" }, - "square": { "type": { "name": "bool" } }, + "square": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/popper.json b/docs/pages/material-ui/api/popper.json index 292d8c77a6a0d0..57a9043dd83ecb 100644 --- a/docs/pages/material-ui/api/popper.json +++ b/docs/pages/material-ui/api/popper.json @@ -17,8 +17,8 @@ "default": "{}" }, "container": { "type": { "name": "union", "description": "HTML element
| func" } }, - "disablePortal": { "type": { "name": "bool" } }, - "keepMounted": { "type": { "name": "bool" } }, + "disablePortal": { "type": { "name": "bool" }, "default": "false" }, + "keepMounted": { "type": { "name": "bool" }, "default": "false" }, "modifiers": { "type": { "name": "arrayOf", @@ -54,7 +54,7 @@ "description": "Array<func
| object
| bool>
| func
| object" } }, - "transition": { "type": { "name": "bool" } } + "transition": { "type": { "name": "bool" }, "default": "false" } }, "name": "Popper", "styles": { "classes": [], "globalClasses": {}, "name": null }, diff --git a/docs/pages/material-ui/api/radio-group.json b/docs/pages/material-ui/api/radio-group.json index 1f06add39ad3b4..2423856c880012 100644 --- a/docs/pages/material-ui/api/radio-group.json +++ b/docs/pages/material-ui/api/radio-group.json @@ -7,7 +7,11 @@ "value": { "type": { "name": "any" } } }, "name": "RadioGroup", - "styles": { "classes": [], "globalClasses": {}, "name": null }, + "styles": { + "classes": ["root", "row", "error"], + "globalClasses": { "error": "Mui-error" }, + "name": "MuiRadioGroup" + }, "spread": true, "forwardsRefTo": "HTMLDivElement", "filename": "/packages/mui-material/src/RadioGroup/RadioGroup.js", diff --git a/docs/pages/material-ui/api/radio.json b/docs/pages/material-ui/api/radio.json index 235f889cf1cd7b..3413c5d6b1404e 100644 --- a/docs/pages/material-ui/api/radio.json +++ b/docs/pages/material-ui/api/radio.json @@ -11,14 +11,14 @@ "default": "'primary'" }, "disabled": { "type": { "name": "bool" } }, - "disableRipple": { "type": { "name": "bool" } }, + "disableRipple": { "type": { "name": "bool" }, "default": "false" }, "icon": { "type": { "name": "node" }, "default": "" }, "id": { "type": { "name": "string" } }, "inputProps": { "type": { "name": "object" } }, "inputRef": { "type": { "name": "custom", "description": "ref" } }, "name": { "type": { "name": "string" } }, "onChange": { "type": { "name": "func" } }, - "required": { "type": { "name": "bool" } }, + "required": { "type": { "name": "bool" }, "default": "false" }, "size": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/rating.json b/docs/pages/material-ui/api/rating.json index 2cbcf894d74f7e..56c58e3a174298 100644 --- a/docs/pages/material-ui/api/rating.json +++ b/docs/pages/material-ui/api/rating.json @@ -2,14 +2,14 @@ "props": { "classes": { "type": { "name": "object" } }, "defaultValue": { "type": { "name": "number" }, "default": "null" }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "emptyIcon": { "type": { "name": "node" }, "default": "" }, "emptyLabelText": { "type": { "name": "node" }, "default": "'Empty'" }, "getLabelText": { "type": { "name": "func" }, "default": "function defaultLabelText(value) {\n return `${value} Star${value !== 1 ? 's' : ''}`;\n}" }, - "highlightSelectedOnly": { "type": { "name": "bool" } }, + "highlightSelectedOnly": { "type": { "name": "bool" }, "default": "false" }, "icon": { "type": { "name": "node" }, "default": "" }, "IconContainerComponent": { "type": { "name": "elementType" }, @@ -20,7 +20,7 @@ "onChange": { "type": { "name": "func" } }, "onChangeActive": { "type": { "name": "func" } }, "precision": { "type": { "name": "custom", "description": "number" }, "default": "1" }, - "readOnly": { "type": { "name": "bool" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "size": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/select.json b/docs/pages/material-ui/api/select.json index 38fe8be0fabee2..90c314a55f5ec2 100644 --- a/docs/pages/material-ui/api/select.json +++ b/docs/pages/material-ui/api/select.json @@ -1,11 +1,11 @@ { "props": { - "autoWidth": { "type": { "name": "bool" } }, + "autoWidth": { "type": { "name": "bool" }, "default": "false" }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" }, "default": "{}" }, - "defaultOpen": { "type": { "name": "bool" } }, + "defaultOpen": { "type": { "name": "bool" }, "default": "false" }, "defaultValue": { "type": { "name": "any" } }, - "displayEmpty": { "type": { "name": "bool" } }, + "displayEmpty": { "type": { "name": "bool" }, "default": "false" }, "IconComponent": { "type": { "name": "elementType" }, "default": "ArrowDropDownIcon" }, "id": { "type": { "name": "string" } }, "input": { "type": { "name": "element" } }, @@ -13,8 +13,8 @@ "label": { "type": { "name": "node" } }, "labelId": { "type": { "name": "string" } }, "MenuProps": { "type": { "name": "object" } }, - "multiple": { "type": { "name": "bool" } }, - "native": { "type": { "name": "bool" } }, + "multiple": { "type": { "name": "bool" }, "default": "false" }, + "native": { "type": { "name": "bool" }, "default": "false" }, "onChange": { "type": { "name": "func" } }, "onClose": { "type": { "name": "func" } }, "onOpen": { "type": { "name": "func" } }, diff --git a/docs/pages/material-ui/api/slider.json b/docs/pages/material-ui/api/slider.json index aa9ca8c8932c9e..4de96de5f0b9e7 100644 --- a/docs/pages/material-ui/api/slider.json +++ b/docs/pages/material-ui/api/slider.json @@ -28,8 +28,8 @@ "defaultValue": { "type": { "name": "union", "description": "Array<number>
| number" } }, - "disabled": { "type": { "name": "bool" } }, - "disableSwap": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableSwap": { "type": { "name": "bool" }, "default": "false" }, "getAriaLabel": { "type": { "name": "func" } }, "getAriaValueText": { "type": { "name": "func" } }, "marks": { @@ -48,7 +48,7 @@ "type": { "name": "enum", "description": "'horizontal'
| 'vertical'" }, "default": "'horizontal'" }, - "scale": { "type": { "name": "func" }, "default": "(x) => x" }, + "scale": { "type": { "name": "func" }, "default": "function Identity(x) {\n return x;\n}" }, "size": { "type": { "name": "union", @@ -94,13 +94,15 @@ }, "valueLabelFormat": { "type": { "name": "union", "description": "func
| string" }, - "default": "(x) => x" + "default": "function Identity(x) {\n return x;\n}" } }, "name": "Slider", "styles": { "classes": [ "root", + "colorPrimary", + "colorSecondary", "marked", "vertical", "disabled", @@ -112,20 +114,18 @@ "thumb", "active", "focusVisible", - "valueLabel", - "valueLabelOpen", - "valueLabelCircle", - "valueLabelLabel", "mark", "markActive", "markLabel", "markLabelActive", - "colorPrimary", - "colorSecondary", "sizeSmall", "thumbColorPrimary", "thumbColorSecondary", - "thumbSizeSmall" + "thumbSizeSmall", + "valueLabel", + "valueLabelOpen", + "valueLabelCircle", + "valueLabelLabel" ], "globalClasses": { "disabled": "Mui-disabled", @@ -137,7 +137,7 @@ "spread": true, "forwardsRefTo": "HTMLSpanElement", "filename": "/packages/mui-material/src/Slider/Slider.js", - "inheritance": { "component": "SliderUnstyled", "pathname": "/base/api/slider-unstyled/" }, + "inheritance": null, "demos": "", "cssComponent": false } diff --git a/docs/pages/material-ui/api/snackbar.json b/docs/pages/material-ui/api/snackbar.json index 20451afddec908..d830a23c2b27f3 100644 --- a/docs/pages/material-ui/api/snackbar.json +++ b/docs/pages/material-ui/api/snackbar.json @@ -13,7 +13,7 @@ "classes": { "type": { "name": "object" } }, "ClickAwayListenerProps": { "type": { "name": "object" } }, "ContentProps": { "type": { "name": "object" } }, - "disableWindowBlurListener": { "type": { "name": "bool" } }, + "disableWindowBlurListener": { "type": { "name": "bool" }, "default": "false" }, "key": { "type": { "name": "custom", "description": "any" } }, "message": { "type": { "name": "node" } }, "onClose": { "type": { "name": "func" } }, diff --git a/docs/pages/material-ui/api/speed-dial-action.json b/docs/pages/material-ui/api/speed-dial-action.json index 4b4009f9951ef7..48b0aed9a77e5a 100644 --- a/docs/pages/material-ui/api/speed-dial-action.json +++ b/docs/pages/material-ui/api/speed-dial-action.json @@ -13,7 +13,7 @@ } }, "TooltipClasses": { "type": { "name": "object" } }, - "tooltipOpen": { "type": { "name": "bool" } }, + "tooltipOpen": { "type": { "name": "bool" }, "default": "false" }, "tooltipPlacement": { "type": { "name": "enum", diff --git a/docs/pages/material-ui/api/speed-dial.json b/docs/pages/material-ui/api/speed-dial.json index 14255424269e46..8c075bb55dfcb9 100644 --- a/docs/pages/material-ui/api/speed-dial.json +++ b/docs/pages/material-ui/api/speed-dial.json @@ -11,7 +11,7 @@ "default": "'up'" }, "FabProps": { "type": { "name": "object" }, "default": "{}" }, - "hidden": { "type": { "name": "bool" } }, + "hidden": { "type": { "name": "bool" }, "default": "false" }, "icon": { "type": { "name": "node" } }, "onClose": { "type": { "name": "func" } }, "onOpen": { "type": { "name": "func" } }, diff --git a/docs/pages/material-ui/api/step-icon.json b/docs/pages/material-ui/api/step-icon.json index 46a145e11a2b01..73d1efe640185b 100644 --- a/docs/pages/material-ui/api/step-icon.json +++ b/docs/pages/material-ui/api/step-icon.json @@ -1,9 +1,9 @@ { "props": { - "active": { "type": { "name": "bool" } }, + "active": { "type": { "name": "bool" }, "default": "false" }, "classes": { "type": { "name": "object" } }, - "completed": { "type": { "name": "bool" } }, - "error": { "type": { "name": "bool" } }, + "completed": { "type": { "name": "bool" }, "default": "false" }, + "error": { "type": { "name": "bool" }, "default": "false" }, "icon": { "type": { "name": "node" } }, "sx": { "type": { diff --git a/docs/pages/material-ui/api/step-label.json b/docs/pages/material-ui/api/step-label.json index ac17c0494342a3..7fd9b4019c0f77 100644 --- a/docs/pages/material-ui/api/step-label.json +++ b/docs/pages/material-ui/api/step-label.json @@ -6,7 +6,7 @@ "type": { "name": "shape", "description": "{ label?: object }" }, "default": "{}" }, - "error": { "type": { "name": "bool" } }, + "error": { "type": { "name": "bool" }, "default": "false" }, "icon": { "type": { "name": "node" } }, "optional": { "type": { "name": "node" } }, "slotProps": { diff --git a/docs/pages/material-ui/api/step.json b/docs/pages/material-ui/api/step.json index b7ae13fe2ec09e..e1f39bf5d0ee0f 100644 --- a/docs/pages/material-ui/api/step.json +++ b/docs/pages/material-ui/api/step.json @@ -6,7 +6,7 @@ "completed": { "type": { "name": "bool" } }, "component": { "type": { "name": "elementType" } }, "disabled": { "type": { "name": "bool" } }, - "expanded": { "type": { "name": "bool" } }, + "expanded": { "type": { "name": "bool" }, "default": "false" }, "index": { "type": { "name": "custom", "description": "integer" } }, "last": { "type": { "name": "bool" } }, "sx": { diff --git a/docs/pages/material-ui/api/stepper.json b/docs/pages/material-ui/api/stepper.json index 41b76130db56d2..da17ffa0f5e4b5 100644 --- a/docs/pages/material-ui/api/stepper.json +++ b/docs/pages/material-ui/api/stepper.json @@ -1,12 +1,12 @@ { "props": { "activeStep": { "type": { "name": "custom", "description": "integer" }, "default": "0" }, - "alternativeLabel": { "type": { "name": "bool" } }, + "alternativeLabel": { "type": { "name": "bool" }, "default": "false" }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, "connector": { "type": { "name": "element" }, "default": "" }, - "nonLinear": { "type": { "name": "bool" } }, + "nonLinear": { "type": { "name": "bool" }, "default": "false" }, "orientation": { "type": { "name": "enum", "description": "'horizontal'
| 'vertical'" }, "default": "'horizontal'" diff --git a/docs/pages/material-ui/api/svg-icon.json b/docs/pages/material-ui/api/svg-icon.json index 6a1e6248ec91ad..66e5a1548aa2b0 100644 --- a/docs/pages/material-ui/api/svg-icon.json +++ b/docs/pages/material-ui/api/svg-icon.json @@ -18,7 +18,7 @@ "default": "'medium'" }, "htmlColor": { "type": { "name": "string" } }, - "inheritViewBox": { "type": { "name": "bool" } }, + "inheritViewBox": { "type": { "name": "bool" }, "default": "false" }, "shapeRendering": { "type": { "name": "string" } }, "sx": { "type": { diff --git a/docs/pages/material-ui/api/swipeable-drawer.json b/docs/pages/material-ui/api/swipeable-drawer.json index 13b2e251d53e13..7dc9d235666fea 100644 --- a/docs/pages/material-ui/api/swipeable-drawer.json +++ b/docs/pages/material-ui/api/swipeable-drawer.json @@ -2,16 +2,20 @@ "props": { "onClose": { "type": { "name": "func" }, "required": true }, "onOpen": { "type": { "name": "func" }, "required": true }, + "allowSwipeInChildren": { + "type": { "name": "union", "description": "bool
| func" }, + "default": "false" + }, "children": { "type": { "name": "node" } }, - "disableBackdropTransition": { "type": { "name": "bool" } }, - "disableDiscovery": { "type": { "name": "bool" } }, + "disableBackdropTransition": { "type": { "name": "bool" }, "default": "false" }, + "disableDiscovery": { "type": { "name": "bool" }, "default": "false" }, "disableSwipeToOpen": { "type": { "name": "bool" }, "default": "typeof navigator !== 'undefined' && /iPad|iPhone|iPod/.test(navigator.userAgent)" }, "hysteresis": { "type": { "name": "number" }, "default": "0.52" }, "minFlingVelocity": { "type": { "name": "number" }, "default": "450" }, - "open": { "type": { "name": "bool" } }, + "open": { "type": { "name": "bool" }, "default": "false" }, "SwipeAreaProps": { "type": { "name": "object" } }, "swipeAreaWidth": { "type": { "name": "number" }, "default": "20" }, "transitionDuration": { diff --git a/docs/pages/material-ui/api/switch.json b/docs/pages/material-ui/api/switch.json index ee47143778c0cd..bad2eb7c80c29a 100644 --- a/docs/pages/material-ui/api/switch.json +++ b/docs/pages/material-ui/api/switch.json @@ -12,7 +12,7 @@ }, "defaultChecked": { "type": { "name": "bool" } }, "disabled": { "type": { "name": "bool" } }, - "disableRipple": { "type": { "name": "bool" } }, + "disableRipple": { "type": { "name": "bool" }, "default": "false" }, "edge": { "type": { "name": "enum", @@ -25,7 +25,7 @@ "inputProps": { "type": { "name": "object" } }, "inputRef": { "type": { "name": "custom", "description": "ref" } }, "onChange": { "type": { "name": "func" } }, - "required": { "type": { "name": "bool" } }, + "required": { "type": { "name": "bool" }, "default": "false" }, "size": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/tab-list.json b/docs/pages/material-ui/api/tab-list.json index cf2a4f0c912a0a..ccd8dafc185a04 100644 --- a/docs/pages/material-ui/api/tab-list.json +++ b/docs/pages/material-ui/api/tab-list.json @@ -1,7 +1,25 @@ { "props": { "children": { "type": { "name": "node" } } }, "name": "TabList", - "styles": { "classes": [], "globalClasses": {}, "name": null }, + "styles": { + "classes": [ + "root", + "vertical", + "flexContainer", + "flexContainerVertical", + "centered", + "scroller", + "fixed", + "scrollableX", + "scrollableY", + "hideScrollbar", + "scrollButtons", + "scrollButtonsHideMobile", + "indicator" + ], + "globalClasses": {}, + "name": "MuiTabList" + }, "spread": true, "forwardsRefTo": "HTMLDivElement", "filename": "/packages/mui-lab/src/TabList/TabList.js", diff --git a/docs/pages/material-ui/api/tab-scroll-button.json b/docs/pages/material-ui/api/tab-scroll-button.json index fa9ef36ac30ec3..2338234e3219e5 100644 --- a/docs/pages/material-ui/api/tab-scroll-button.json +++ b/docs/pages/material-ui/api/tab-scroll-button.json @@ -10,7 +10,7 @@ }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/tab.json b/docs/pages/material-ui/api/tab.json index 4326f503f294cd..d1b169ffe04c85 100644 --- a/docs/pages/material-ui/api/tab.json +++ b/docs/pages/material-ui/api/tab.json @@ -2,9 +2,9 @@ "props": { "children": { "type": { "name": "custom", "description": "unsupportedProp" } }, "classes": { "type": { "name": "object" } }, - "disabled": { "type": { "name": "bool" } }, - "disableFocusRipple": { "type": { "name": "bool" } }, - "disableRipple": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableFocusRipple": { "type": { "name": "bool" }, "default": "false" }, + "disableRipple": { "type": { "name": "bool" }, "default": "false" }, "icon": { "type": { "name": "union", "description": "element
| string" } }, "iconPosition": { "type": { @@ -21,7 +21,7 @@ } }, "value": { "type": { "name": "any" } }, - "wrapped": { "type": { "name": "bool" } } + "wrapped": { "type": { "name": "bool" }, "default": "false" } }, "name": "Tab", "styles": { diff --git a/docs/pages/material-ui/api/table-pagination.json b/docs/pages/material-ui/api/table-pagination.json index b5033e1feb3568..9888e2c2ec4849 100644 --- a/docs/pages/material-ui/api/table-pagination.json +++ b/docs/pages/material-ui/api/table-pagination.json @@ -27,8 +27,8 @@ "default": "[10, 25, 50, 100]" }, "SelectProps": { "type": { "name": "object" }, "default": "{}" }, - "showFirstButton": { "type": { "name": "bool" } }, - "showLastButton": { "type": { "name": "bool" } }, + "showFirstButton": { "type": { "name": "bool" }, "default": "false" }, + "showLastButton": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/table-row.json b/docs/pages/material-ui/api/table-row.json index 2b8cf6e6fcddf7..72cf106dd26cec 100644 --- a/docs/pages/material-ui/api/table-row.json +++ b/docs/pages/material-ui/api/table-row.json @@ -3,8 +3,8 @@ "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, - "hover": { "type": { "name": "bool" } }, - "selected": { "type": { "name": "bool" } }, + "hover": { "type": { "name": "bool" }, "default": "false" }, + "selected": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/table-sort-label.json b/docs/pages/material-ui/api/table-sort-label.json index 764552c8cb030d..5da16dbd627be7 100644 --- a/docs/pages/material-ui/api/table-sort-label.json +++ b/docs/pages/material-ui/api/table-sort-label.json @@ -1,13 +1,13 @@ { "props": { - "active": { "type": { "name": "bool" } }, + "active": { "type": { "name": "bool" }, "default": "false" }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "direction": { "type": { "name": "enum", "description": "'asc'
| 'desc'" }, "default": "'asc'" }, - "hideSortIcon": { "type": { "name": "bool" } }, + "hideSortIcon": { "type": { "name": "bool" }, "default": "false" }, "IconComponent": { "type": { "name": "elementType" }, "default": "ArrowDownwardIcon" }, "sx": { "type": { diff --git a/docs/pages/material-ui/api/table.json b/docs/pages/material-ui/api/table.json index 8b822ef30f057b..96e5fd3f212e82 100644 --- a/docs/pages/material-ui/api/table.json +++ b/docs/pages/material-ui/api/table.json @@ -17,7 +17,7 @@ }, "default": "'medium'" }, - "stickyHeader": { "type": { "name": "bool" } }, + "stickyHeader": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/tabs.json b/docs/pages/material-ui/api/tabs.json index fb925fc52de082..eb8a853409a260 100644 --- a/docs/pages/material-ui/api/tabs.json +++ b/docs/pages/material-ui/api/tabs.json @@ -1,10 +1,10 @@ { "props": { "action": { "type": { "name": "custom", "description": "ref" } }, - "allowScrollButtonsMobile": { "type": { "name": "bool" } }, + "allowScrollButtonsMobile": { "type": { "name": "bool" }, "default": "false" }, "aria-label": { "type": { "name": "string" } }, "aria-labelledby": { "type": { "name": "string" } }, - "centered": { "type": { "name": "bool" } }, + "centered": { "type": { "name": "bool" }, "default": "false" }, "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, @@ -49,7 +49,7 @@ }, "default": "'standard'" }, - "visibleScrollbar": { "type": { "name": "bool" } } + "visibleScrollbar": { "type": { "name": "bool" }, "default": "false" } }, "name": "Tabs", "styles": { diff --git a/docs/pages/material-ui/api/text-field.json b/docs/pages/material-ui/api/text-field.json index e40ff8db22bf61..4b2bf2c3187eed 100644 --- a/docs/pages/material-ui/api/text-field.json +++ b/docs/pages/material-ui/api/text-field.json @@ -1,7 +1,7 @@ { "props": { "autoComplete": { "type": { "name": "string" } }, - "autoFocus": { "type": { "name": "bool" } }, + "autoFocus": { "type": { "name": "bool" }, "default": "false" }, "classes": { "type": { "name": "object" } }, "color": { "type": { @@ -11,10 +11,10 @@ "default": "'primary'" }, "defaultValue": { "type": { "name": "any" } }, - "disabled": { "type": { "name": "bool" } }, - "error": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "error": { "type": { "name": "bool" }, "default": "false" }, "FormHelperTextProps": { "type": { "name": "object" } }, - "fullWidth": { "type": { "name": "bool" } }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, "helperText": { "type": { "name": "node" } }, "id": { "type": { "name": "string" } }, "InputLabelProps": { "type": { "name": "object" } }, @@ -31,13 +31,13 @@ }, "maxRows": { "type": { "name": "union", "description": "number
| string" } }, "minRows": { "type": { "name": "union", "description": "number
| string" } }, - "multiline": { "type": { "name": "bool" } }, + "multiline": { "type": { "name": "bool" }, "default": "false" }, "name": { "type": { "name": "string" } }, "onChange": { "type": { "name": "func" } }, "placeholder": { "type": { "name": "string" } }, - "required": { "type": { "name": "bool" } }, + "required": { "type": { "name": "bool" }, "default": "false" }, "rows": { "type": { "name": "union", "description": "number
| string" } }, - "select": { "type": { "name": "bool" } }, + "select": { "type": { "name": "bool" }, "default": "false" }, "SelectProps": { "type": { "name": "object" } }, "size": { "type": { diff --git a/docs/pages/material-ui/api/toggle-button-group.json b/docs/pages/material-ui/api/toggle-button-group.json index c87635a7e5aee3..04ba7249d1fa66 100644 --- a/docs/pages/material-ui/api/toggle-button-group.json +++ b/docs/pages/material-ui/api/toggle-button-group.json @@ -9,9 +9,9 @@ }, "default": "'standard'" }, - "disabled": { "type": { "name": "bool" } }, - "exclusive": { "type": { "name": "bool" } }, - "fullWidth": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "exclusive": { "type": { "name": "bool" }, "default": "false" }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, "onChange": { "type": { "name": "func" } }, "orientation": { "type": { "name": "enum", "description": "'horizontal'
| 'vertical'" }, diff --git a/docs/pages/material-ui/api/toggle-button.json b/docs/pages/material-ui/api/toggle-button.json index 8edf34a3056f40..1084178a0397fa 100644 --- a/docs/pages/material-ui/api/toggle-button.json +++ b/docs/pages/material-ui/api/toggle-button.json @@ -10,10 +10,10 @@ }, "default": "'standard'" }, - "disabled": { "type": { "name": "bool" } }, - "disableFocusRipple": { "type": { "name": "bool" } }, - "disableRipple": { "type": { "name": "bool" } }, - "fullWidth": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, + "disableFocusRipple": { "type": { "name": "bool" }, "default": "false" }, + "disableRipple": { "type": { "name": "bool" }, "default": "false" }, + "fullWidth": { "type": { "name": "bool" }, "default": "false" }, "onChange": { "type": { "name": "func" } }, "onClick": { "type": { "name": "func" } }, "selected": { "type": { "name": "bool" } }, diff --git a/docs/pages/material-ui/api/toolbar.json b/docs/pages/material-ui/api/toolbar.json index 12cb597c03f338..4d5af73bdc0645 100644 --- a/docs/pages/material-ui/api/toolbar.json +++ b/docs/pages/material-ui/api/toolbar.json @@ -3,7 +3,7 @@ "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, - "disableGutters": { "type": { "name": "bool" } }, + "disableGutters": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/tooltip.json b/docs/pages/material-ui/api/tooltip.json index bb86f42025476d..543a57a48782e0 100644 --- a/docs/pages/material-ui/api/tooltip.json +++ b/docs/pages/material-ui/api/tooltip.json @@ -1,7 +1,7 @@ { "props": { "children": { "type": { "name": "custom", "description": "element" }, "required": true }, - "arrow": { "type": { "name": "bool" } }, + "arrow": { "type": { "name": "bool" }, "default": "false" }, "classes": { "type": { "name": "object" } }, "components": { "type": { @@ -17,15 +17,15 @@ }, "default": "{}" }, - "describeChild": { "type": { "name": "bool" } }, - "disableFocusListener": { "type": { "name": "bool" } }, - "disableHoverListener": { "type": { "name": "bool" } }, - "disableInteractive": { "type": { "name": "bool" } }, - "disableTouchListener": { "type": { "name": "bool" } }, + "describeChild": { "type": { "name": "bool" }, "default": "false" }, + "disableFocusListener": { "type": { "name": "bool" }, "default": "false" }, + "disableHoverListener": { "type": { "name": "bool" }, "default": "false" }, + "disableInteractive": { "type": { "name": "bool" }, "default": "false" }, + "disableTouchListener": { "type": { "name": "bool" }, "default": "false" }, "enterDelay": { "type": { "name": "number" }, "default": "100" }, "enterNextDelay": { "type": { "name": "number" }, "default": "0" }, "enterTouchDelay": { "type": { "name": "number" }, "default": "700" }, - "followCursor": { "type": { "name": "bool" } }, + "followCursor": { "type": { "name": "bool" }, "default": "false" }, "id": { "type": { "name": "string" } }, "leaveDelay": { "type": { "name": "number" }, "default": "0" }, "leaveTouchDelay": { "type": { "name": "number" }, "default": "1500" }, diff --git a/docs/pages/material-ui/api/tree-item.json b/docs/pages/material-ui/api/tree-item.json index d12c469900ef6a..06e46e3cc67a05 100644 --- a/docs/pages/material-ui/api/tree-item.json +++ b/docs/pages/material-ui/api/tree-item.json @@ -9,7 +9,7 @@ "default": "TreeItemContent" }, "ContentProps": { "type": { "name": "object" } }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "endIcon": { "type": { "name": "node" } }, "expandIcon": { "type": { "name": "node" } }, "icon": { "type": { "name": "node" } }, diff --git a/docs/pages/material-ui/api/tree-view.json b/docs/pages/material-ui/api/tree-view.json index 44c75e7da0cdce..26619fe9642cf4 100644 --- a/docs/pages/material-ui/api/tree-view.json +++ b/docs/pages/material-ui/api/tree-view.json @@ -14,11 +14,11 @@ "type": { "name": "union", "description": "Array<string>
| string" }, "default": "[]" }, - "disabledItemsFocusable": { "type": { "name": "bool" } }, - "disableSelection": { "type": { "name": "bool" } }, + "disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" }, + "disableSelection": { "type": { "name": "bool" }, "default": "false" }, "expanded": { "type": { "name": "arrayOf", "description": "Array<string>" } }, "id": { "type": { "name": "string" } }, - "multiSelect": { "type": { "name": "bool" } }, + "multiSelect": { "type": { "name": "bool" }, "default": "false" }, "onNodeFocus": { "type": { "name": "func" } }, "onNodeSelect": { "type": { "name": "func" } }, "onNodeToggle": { "type": { "name": "func" } }, diff --git a/docs/pages/material-ui/api/typography.json b/docs/pages/material-ui/api/typography.json index 942ee0e1de21f4..3d77fe192c651b 100644 --- a/docs/pages/material-ui/api/typography.json +++ b/docs/pages/material-ui/api/typography.json @@ -10,9 +10,9 @@ "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" } }, "component": { "type": { "name": "elementType" } }, - "gutterBottom": { "type": { "name": "bool" } }, - "noWrap": { "type": { "name": "bool" } }, - "paragraph": { "type": { "name": "bool" } }, + "gutterBottom": { "type": { "name": "bool" }, "default": "false" }, + "noWrap": { "type": { "name": "bool" }, "default": "false" }, + "paragraph": { "type": { "name": "bool" }, "default": "false" }, "sx": { "type": { "name": "union", diff --git a/docs/public/_redirects b/docs/public/_redirects index a141e9c9da8768..d1c83c356795d2 100644 --- a/docs/public/_redirects +++ b/docs/public/_redirects @@ -401,6 +401,8 @@ https://v4.material-ui.com/* https://v4.mui.com/:splat 301! /:lang/experimental-api/classname-generator/ /:lang/material-ui/experimental-api/classname-generator/ 301 /experimental-api/css-variables/ /material-ui/experimental-api/css-theme-variables/overview/ 301 /:lang/experimental-api/css-variables/ /:lang/material-ui/experimental-api/css-theme-variables/overview/ 301 +/joy-ui/customization/default-theme/ /joy-ui/tools/default-theme-viewer/ 301 +/:lang/joy-ui/customization/default-theme/ /:lang/joy-ui/tools/default-theme-viewer/ 301 /pt/material-ui/* /material-ui/:splat 301 /zh/material-ui/* /material-ui/:splat 301 /pt/joy-ui/* /joy-ui/:splat 301 @@ -436,3 +438,6 @@ https://v4.material-ui.com/* https://v4.mui.com/:splat 301! /toolpad/_next/* https://mui-toolpad-docs.netlify.app/_next/:splat 200 /toolpad/* https://mui-toolpad-docs.netlify.app/toolpad/:splat 200 /r/toolpad-* https://mui-toolpad-docs.netlify.app/r/toolpad-:splat 200 + +### MUI Design kits +/figma/getting-started/ https://mui-org.notion.site/MUI-for-Figma-docs-4eb22360388047a9a31fc19d300a285e 302 diff --git a/docs/public/static/blog/v6-beta-pickers/basic-date-field.mp4 b/docs/public/static/blog/v6-beta-pickers/basic-date-field.mp4 new file mode 100644 index 00000000000000..98129da24aa3e9 Binary files /dev/null and b/docs/public/static/blog/v6-beta-pickers/basic-date-field.mp4 differ diff --git a/docs/public/static/blog/v6-beta-pickers/date-field-navigation.mp4 b/docs/public/static/blog/v6-beta-pickers/date-field-navigation.mp4 new file mode 100644 index 00000000000000..2c086dacf9e867 Binary files /dev/null and b/docs/public/static/blog/v6-beta-pickers/date-field-navigation.mp4 differ diff --git a/docs/public/static/blog/v6-beta-pickers/date-range-shortcuts.png b/docs/public/static/blog/v6-beta-pickers/date-range-shortcuts.png new file mode 100644 index 00000000000000..07790e9cf5d05d Binary files /dev/null and b/docs/public/static/blog/v6-beta-pickers/date-range-shortcuts.png differ diff --git a/docs/public/static/blog/v6-beta-pickers/edit-drag-nocrop.mp4 b/docs/public/static/blog/v6-beta-pickers/edit-drag-nocrop.mp4 new file mode 100644 index 00000000000000..3d1e3df18cfe1e Binary files /dev/null and b/docs/public/static/blog/v6-beta-pickers/edit-drag-nocrop.mp4 differ diff --git a/docs/public/static/blog/v6-beta-pickers/edit-drag.mp4 b/docs/public/static/blog/v6-beta-pickers/edit-drag.mp4 new file mode 100644 index 00000000000000..473b4ef1669c05 Binary files /dev/null and b/docs/public/static/blog/v6-beta-pickers/edit-drag.mp4 differ diff --git a/docs/public/static/blog/v6-beta-pickers/masked-input-bad-ux.mp4 b/docs/public/static/blog/v6-beta-pickers/masked-input-bad-ux.mp4 new file mode 100644 index 00000000000000..1446a266ab7edd Binary files /dev/null and b/docs/public/static/blog/v6-beta-pickers/masked-input-bad-ux.mp4 differ diff --git a/docs/public/static/blog/v6-beta-pickers/masked-input.mp4 b/docs/public/static/blog/v6-beta-pickers/masked-input.mp4 new file mode 100644 index 00000000000000..3f55ed6da83eab Binary files /dev/null and b/docs/public/static/blog/v6-beta-pickers/masked-input.mp4 differ diff --git a/docs/public/static/blog/v6-beta-pickers/quick-comparison-fields.mp4 b/docs/public/static/blog/v6-beta-pickers/quick-comparison-fields.mp4 new file mode 100644 index 00000000000000..aef08bafbee144 Binary files /dev/null and b/docs/public/static/blog/v6-beta-pickers/quick-comparison-fields.mp4 differ diff --git a/docs/public/static/blog/v6-beta-pickers/smart-field.mp4 b/docs/public/static/blog/v6-beta-pickers/smart-field.mp4 new file mode 100644 index 00000000000000..1f53d7e0ede386 Binary files /dev/null and b/docs/public/static/blog/v6-beta-pickers/smart-field.mp4 differ diff --git a/docs/public/static/branding/about/bilal.png b/docs/public/static/branding/about/bilal.png index 942b563bc43a5f..9a3e5ccb0f76c5 100644 Binary files a/docs/public/static/branding/about/bilal.png and b/docs/public/static/branding/about/bilal.png differ diff --git a/docs/public/static/branding/about/danail.png b/docs/public/static/branding/about/danail.png index 487b8fb52c007c..b073861e0c15e3 100644 Binary files a/docs/public/static/branding/about/danail.png and b/docs/public/static/branding/about/danail.png differ diff --git a/docs/public/static/branding/about/gerda.png b/docs/public/static/branding/about/gerda.png index b9858fb6cfcd10..b978890576ff5b 100644 Binary files a/docs/public/static/branding/about/gerda.png and b/docs/public/static/branding/about/gerda.png differ diff --git a/docs/public/static/branding/about/greg.png b/docs/public/static/branding/about/greg.png new file mode 100644 index 00000000000000..d0fe157fac522f Binary files /dev/null and b/docs/public/static/branding/about/greg.png differ diff --git a/docs/public/static/branding/about/jose.png b/docs/public/static/branding/about/jose.png index a9e83fe435ae2a..f5f609f1a5dac6 100644 Binary files a/docs/public/static/branding/about/jose.png and b/docs/public/static/branding/about/jose.png differ diff --git a/docs/public/static/branding/about/lukas.png b/docs/public/static/branding/about/lukas.png index 3359f833aa80ac..6204b466a87bc7 100644 Binary files a/docs/public/static/branding/about/lukas.png and b/docs/public/static/branding/about/lukas.png differ diff --git a/docs/public/static/branding/about/sycamore.png b/docs/public/static/branding/about/sycamore.png index 00485246805603..fa4482ff6761a8 100644 Binary files a/docs/public/static/branding/about/sycamore.png and b/docs/public/static/branding/about/sycamore.png differ diff --git a/docs/public/static/branding/about/vytautas.png b/docs/public/static/branding/about/vytautas.png index 833a186288d1e5..f61971ff48e741 100644 Binary files a/docs/public/static/branding/about/vytautas.png and b/docs/public/static/branding/about/vytautas.png differ diff --git a/docs/public/static/branding/store-templates/template-dark1.jpeg b/docs/public/static/branding/store-templates/template-1dark.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-dark1.jpeg rename to docs/public/static/branding/store-templates/template-1dark.jpg diff --git a/docs/public/static/branding/store-templates/template-light1.jpeg b/docs/public/static/branding/store-templates/template-1light.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-light1.jpeg rename to docs/public/static/branding/store-templates/template-1light.jpg diff --git a/docs/public/static/branding/store-templates/template-dark2.jpeg b/docs/public/static/branding/store-templates/template-2dark.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-dark2.jpeg rename to docs/public/static/branding/store-templates/template-2dark.jpg diff --git a/docs/public/static/branding/store-templates/template-light2.jpeg b/docs/public/static/branding/store-templates/template-2light.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-light2.jpeg rename to docs/public/static/branding/store-templates/template-2light.jpg diff --git a/docs/public/static/branding/store-templates/template-dark3.jpeg b/docs/public/static/branding/store-templates/template-3dark.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-dark3.jpeg rename to docs/public/static/branding/store-templates/template-3dark.jpg diff --git a/docs/public/static/branding/store-templates/template-light3.jpeg b/docs/public/static/branding/store-templates/template-3light.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-light3.jpeg rename to docs/public/static/branding/store-templates/template-3light.jpg diff --git a/docs/public/static/branding/store-templates/template-4dark.jpg b/docs/public/static/branding/store-templates/template-4dark.jpg new file mode 100644 index 00000000000000..cfdd3a954d438d Binary files /dev/null and b/docs/public/static/branding/store-templates/template-4dark.jpg differ diff --git a/docs/public/static/branding/store-templates/template-4light.jpg b/docs/public/static/branding/store-templates/template-4light.jpg new file mode 100644 index 00000000000000..41c8d005af98e5 Binary files /dev/null and b/docs/public/static/branding/store-templates/template-4light.jpg differ diff --git a/docs/public/static/branding/store-templates/template-dark5.jpeg b/docs/public/static/branding/store-templates/template-5dark.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-dark5.jpeg rename to docs/public/static/branding/store-templates/template-5dark.jpg diff --git a/docs/public/static/branding/store-templates/template-light5.jpeg b/docs/public/static/branding/store-templates/template-5light.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-light5.jpeg rename to docs/public/static/branding/store-templates/template-5light.jpg diff --git a/docs/public/static/branding/store-templates/template-dark6.jpeg b/docs/public/static/branding/store-templates/template-6dark.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-dark6.jpeg rename to docs/public/static/branding/store-templates/template-6dark.jpg diff --git a/docs/public/static/branding/store-templates/template-light6.jpeg b/docs/public/static/branding/store-templates/template-6light.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-light6.jpeg rename to docs/public/static/branding/store-templates/template-6light.jpg diff --git a/docs/public/static/branding/store-templates/template-bazar-dark.jpeg b/docs/public/static/branding/store-templates/template-bazar-dark.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-bazar-dark.jpeg rename to docs/public/static/branding/store-templates/template-bazar-dark.jpg diff --git a/docs/public/static/branding/store-templates/template-bazar-light.jpeg b/docs/public/static/branding/store-templates/template-bazar-light.jpg similarity index 100% rename from docs/public/static/branding/store-templates/template-bazar-light.jpeg rename to docs/public/static/branding/store-templates/template-bazar-light.jpg diff --git a/docs/public/static/branding/store-templates/template-dark4.jpeg b/docs/public/static/branding/store-templates/template-dark4.jpeg deleted file mode 100644 index fde0dc60e39f04..00000000000000 Binary files a/docs/public/static/branding/store-templates/template-dark4.jpeg and /dev/null differ diff --git a/docs/public/static/branding/store-templates/template-light4.jpeg b/docs/public/static/branding/store-templates/template-light4.jpeg deleted file mode 100644 index b936794a495ac6..00000000000000 Binary files a/docs/public/static/branding/store-templates/template-light4.jpeg and /dev/null differ diff --git a/docs/scripts/generateRSSFeed.ts b/docs/scripts/generateRSSFeed.ts new file mode 100644 index 00000000000000..59ea849788f88c --- /dev/null +++ b/docs/scripts/generateRSSFeed.ts @@ -0,0 +1,47 @@ +import fs from 'fs'; +import { Feed } from 'feed'; +import { BlogPost } from 'docs/lib/sourcing'; +import ROUTES from 'docs/src/route'; + +export default function generateRssFeed(allBlogPosts: Array) { + if (process.env.NODE_ENV !== 'production') { + return; + } + const siteUrl = 'https://mui.com'; + + const feed = new Feed({ + title: 'MUI - Blog', + description: + 'Follow the MUI blog to learn about new product features, latest advancements in UI development, and business initiatives.', + id: `${siteUrl}/blog`, + link: `${siteUrl}/blog`, + language: 'en', + image: `${siteUrl}/static/logo.svg`, + favicon: `${siteUrl}/favicon.ico`, + copyright: `Copyright Ā© ${new Date().getFullYear()} Material UI SAS.`, + feedLinks: { + rss2: `${siteUrl}/public${ROUTES.rssFeed}`, + }, + }); + + allBlogPosts.forEach((post) => { + const postAuthors = post.authors && post.authors.map((author) => ({ name: author })); + const postDate = post.date ? new Date(post.date) : new Date(); + const postCategory = post.tags.map((tag) => ({ name: tag })); + const postLink = `${siteUrl}/blog/${post.slug}`; + + feed.addItem({ + title: post.title, + image: post.image, + id: postLink, + link: postLink, + description: post.description, + category: postCategory, + date: postDate, + author: postAuthors, + }); + }); + + fs.mkdirSync(`public${ROUTES.rssFeed.replace('rss.xml', '')}`, { recursive: true }); + fs.writeFileSync(`public${ROUTES.rssFeed}`, feed.rss2()); +} diff --git a/docs/src/components/banner/AppHeaderBanner.tsx b/docs/src/components/banner/AppHeaderBanner.tsx index 45c18eadbac65f..c8e8d5e20dcd91 100644 --- a/docs/src/components/banner/AppHeaderBanner.tsx +++ b/docs/src/components/banner/AppHeaderBanner.tsx @@ -4,47 +4,51 @@ import Link from 'docs/src/modules/components/Link'; import ROUTES from 'docs/src/route'; import FEATURE_TOGGLE from 'docs/src/featureToggle'; -const getSurveyMessage = () => ( - - šŸš€ Influence the future of MUI!  Please take a few minutes for the  - - MUI Developer survey 2022 ā†’ - - -); +function getSurveyMessage() { + return ( + + šŸš€ Influence the future of MUI!  Please take a few minutes for the  + + MUI Developer survey 2022 ā†’ + + + ); +} -const getDefaultHiringMessage = () => ( - - šŸš€  We're hiring a Designer, Full-stack Engineer, React Support Engineer, and - more!   - - Check the careers page ā†’ - - -); +function getDefaultHiringMessage() { + return ( + + šŸš€  We're hiring a Designer, Full-stack Engineer, React Support Engineer, and + more!   + + Check the careers page ā†’ + + + ); +} export default function AppHeaderBanner() { - const showSurveyMessage = true; + const showSurveyMessage = false; const bannerMessage = showSurveyMessage ? getSurveyMessage() : getDefaultHiringMessage(); return FEATURE_TOGGLE.enable_website_banner ? ( diff --git a/docs/src/components/home/StoreTemplatesBanner.tsx b/docs/src/components/home/StoreTemplatesBanner.tsx index 7c5fc5b801b60b..cbeb47448d3684 100644 --- a/docs/src/components/home/StoreTemplatesBanner.tsx +++ b/docs/src/components/home/StoreTemplatesBanner.tsx @@ -56,7 +56,7 @@ const linkMapping = { }; const brands = Object.keys(linkMapping) as Array; -type TemplateBrand = typeof brands[number]; +type TemplateBrand = (typeof brands)[number]; const StoreTemplateLink = React.forwardRef< HTMLAnchorElement, @@ -104,15 +104,15 @@ const StoreTemplateImage = React.forwardRef< return ( theme.applyDarkStyles({ - content: `url(/static/branding/store-templates/template-dark${ + content: `url(/static/branding/store-templates/template-${ Object.keys(linkMapping).indexOf(brand) + 1 - }.jpeg)`, + }dark.jpg)`, }) } {...props} @@ -126,7 +126,7 @@ export function PrefetchStoreTemplateImages() { loading: 'lazy' as const, width: '900', height: '494', - src: `/static/branding/store-templates/template-${mode}${num}.jpeg`, + src: `/static/branding/store-templates/template-${num}${mode}.jpg`, }; } return ( diff --git a/docs/src/components/pricing/HeroPricing.tsx b/docs/src/components/pricing/HeroPricing.tsx index 6e1622fe01768f..cd83b676ebd277 100644 --- a/docs/src/components/pricing/HeroPricing.tsx +++ b/docs/src/components/pricing/HeroPricing.tsx @@ -10,7 +10,7 @@ export default function HeroPricing() { - Price capped at 10 developers. + No additional fee beyond 10 devs.
); @@ -922,7 +923,15 @@ export default function PricingTable({ columnHeaderHidden?: boolean; plans?: Array<'community' | 'pro' | 'premium'>; }) { + const router = useRouter(); const [dataGridCollapsed, setDataGridCollapsed] = React.useState(false); + + React.useEffect(() => { + if (router.query['expand-path'] === 'all') { + setDataGridCollapsed(true); + } + }, [router.query]); + const tableRef = React.useRef(null); const gridSx = { display: 'grid', @@ -930,6 +939,14 @@ export default function PricingTable({ columnHeaderHidden ? '0px' : '240px' }, 1fr))`, }; + + const unfoldMore = ( + + ); + function renderRow(key: string) { return ( }> MUI X (open-core) - + - - - + {unfoldMore} - - - - + {unfoldMore} + {unfoldMore}
diff --git a/docs/src/modules/components/AppLayoutDocs.js b/docs/src/modules/components/AppLayoutDocs.js index f3c6cf2ce76615..444fa61f6f2f86 100644 --- a/docs/src/modules/components/AppLayoutDocs.js +++ b/docs/src/modules/components/AppLayoutDocs.js @@ -122,7 +122,9 @@ function AppLayoutDocs(props) { See https://jakearchibald.com/2014/dont-use-flexbox-for-page-layout/ for more details. */} - {location && } + + + {children} @@ -141,7 +143,7 @@ AppLayoutDocs.propTypes = { description: PropTypes.string.isRequired, disableAd: PropTypes.bool.isRequired, disableToc: PropTypes.bool.isRequired, - location: PropTypes.string, + location: PropTypes.string.isRequired, title: PropTypes.string.isRequired, toc: PropTypes.array.isRequired, }; diff --git a/docs/src/modules/components/AppNavDrawer.js b/docs/src/modules/components/AppNavDrawer.js index c95e1f495b1517..cc4e6ba40cc2b3 100644 --- a/docs/src/modules/components/AppNavDrawer.js +++ b/docs/src/modules/components/AppNavDrawer.js @@ -159,6 +159,7 @@ const ToolbarDiv = styled('div')(({ theme }) => ({ padding: theme.spacing(1.45, 2), paddingRight: 0, height: 'var(--MuiDocs-header-height)', + boxSizing: 'border-box', // TODO have CssBaseline in the Next.js layout display: 'flex', flexGrow: 1, flexDirection: 'row', @@ -179,6 +180,7 @@ const AppNavPaperComponent = styled('div')(({ theme }) => { return { width: 'var(--MuiDocs-navDrawer-width)', boxShadow: 'none', + boxSizing: 'border-box', // TODO have CssBaseline in the Next.js layout paddingBottom: theme.spacing(5), [theme.breakpoints.up('xs')]: { borderRadius: '0px 10px 10px 0px', diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js index cf206710986ae1..f25683958390e0 100644 --- a/docs/src/modules/components/AppTableOfContents.js +++ b/docs/src/modules/components/AppTableOfContents.js @@ -127,7 +127,7 @@ const shouldShowJobAd = () => { export default function AppTableOfContents(props) { const { toc } = props; const t = useTranslate(); - const showSurveyBanner = true; + const showSurveyBanner = false; const showAddJob = shouldShowJobAd() && !showSurveyBanner; const items = React.useMemo(() => flatten(toc), [toc]); diff --git a/docs/src/modules/components/CodeCopyButton.tsx b/docs/src/modules/components/CodeCopyButton.tsx index f64da582102db5..4a314345b796e2 100644 --- a/docs/src/modules/components/CodeCopyButton.tsx +++ b/docs/src/modules/components/CodeCopyButton.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import copy from 'clipboard-copy'; +import useClipboardCopy from 'docs/src/modules/utils/useClipboardCopy'; interface CodeCopyButtonProps { code: string; @@ -7,23 +7,11 @@ interface CodeCopyButtonProps { export default function CodeCopyButton(props: CodeCopyButtonProps) { const { code, ...other } = props; - const [copied, setCopied] = React.useState(false); + const { copy, isCopied } = useClipboardCopy(); // This component is designed to be wrapped in NoSsr const macOS = window.navigator.platform.toUpperCase().indexOf('MAC') >= 0; const key = macOS ? 'āŒ˜' : 'Ctrl + '; - React.useEffect(() => { - if (copied) { - const timeout = setTimeout(() => { - setCopied(false); - }, 2000); - return () => { - clearTimeout(timeout); - }; - } - return undefined; - }, [copied]); - return (
', () => { + const { render } = createRenderer({ emotionCompat: true }); + + describeConformance(
, () => ({ + classes, + inheritComponent: 'table', + render, + ThemeProvider, + muiName: 'JoyTable', + refInstanceof: window.HTMLTableElement, + testComponentPropWith: 'header', + testVariantProps: { variant: 'solid' }, + testCustomVariant: true, + skip: [ + 'classesRoot', + 'componentsProp', + // Emotion `compat` is not set with `createMount` for these tests + 'componentProp', + 'mergeClassName', + 'propsSpread', + 'reactTestRenderer', + 'refForwarding', + ], + })); + + describeJoyColorInversion(
, { muiName: 'JoyTable', classes, emotionCompat: true }); + + describe('prop: variant', () => { + it('plain by default', () => { + const { getByRole } = render(
); + + expect(getByRole('table')).to.have.class(classes.variantPlain); + }); + + (['plain', 'outlined', 'soft', 'solid'] as const).forEach((variant) => { + it(`should render ${variant}`, () => { + const { getByRole } = render(
); + + expect(getByRole('table')).to.have.class( + classes[`variant${capitalize(variant)}` as keyof typeof classes], + ); + }); + }); + }); + + describe('prop: color', () => { + it('adds a neutral class by default', () => { + const { getByRole } = render(
); + + expect(getByRole('table')).to.have.class(classes.colorNeutral); + }); + + (['primary', 'success', 'info', 'danger', 'neutral', 'warning'] as const).forEach((color) => { + it(`should render ${color}`, () => { + const { getByRole } = render(
); + + expect(getByRole('table')).to.have.class( + classes[`color${capitalize(color)}` as keyof typeof classes], + ); + }); + }); + }); + + describe('prop: size', () => { + it('adds a md class by default', () => { + const { getByRole } = render(
); + + expect(getByRole('table')).to.have.class(classes.sizeMd); + }); + + (['sm', 'lg'] as const).forEach((size) => { + it(`should render ${size}`, () => { + const { getByRole } = render(
); + + expect(getByRole('table')).to.have.class( + classes[`size${capitalize(size)}` as keyof typeof classes], + ); + }); + }); + }); + + describe('prop: borderAxis', () => { + it('adds `xBetween` by default', () => { + const { getByRole } = render(
); + + expect(getByRole('table')).to.have.class(classes.borderAxisXBetween); + }); + + (['none', 'x', 'xBetween', 'y', 'yBetween', 'both', 'bothBetween'] as const).forEach((axis) => { + it(`should render border-axis ${axis}`, () => { + const { getByRole } = render(
); + + expect(getByRole('table')).to.have.class( + classes[`borderAxis${capitalize(axis)}` as keyof typeof classes], + ); + }); + }); + }); + + it('adds `hoverRow` class', () => { + const { getByRole } = render(
); + + expect(getByRole('table')).to.have.class(classes.hoverRow); + }); + + it('adds `noWrap` class', () => { + const { getByRole } = render(
); + + expect(getByRole('table')).to.have.class(classes.noWrap); + }); + + it('adds `stickyHeader` class', () => { + const { getByRole } = render(
); + + expect(getByRole('table')).to.have.class(classes.stickyHeader); + }); +}); diff --git a/packages/mui-joy/src/Table/Table.tsx b/packages/mui-joy/src/Table/Table.tsx new file mode 100644 index 00000000000000..03dd4879cc8f5a --- /dev/null +++ b/packages/mui-joy/src/Table/Table.tsx @@ -0,0 +1,422 @@ +import * as React from 'react'; +import clsx from 'clsx'; +import PropTypes from 'prop-types'; +import { unstable_capitalize as capitalize } from '@mui/utils'; +import { unstable_composeClasses as composeClasses } from '@mui/base'; +import { OverridableComponent } from '@mui/types'; +import { useThemeProps } from '../styles'; +import { useColorInversion } from '../styles/ColorInversion'; +import styled from '../styles/styled'; +import { getTableUtilityClass } from './tableClasses'; +import { TableProps, TableOwnerState, TableTypeMap } from './TableProps'; +import typographyClasses from '../Typography/typographyClasses'; +import { TypographyContext } from '../Typography/Typography'; + +const useUtilityClasses = (ownerState: TableOwnerState) => { + const { size, variant, color, borderAxis, stickyHeader, noWrap, hoverRow } = ownerState; + const slots = { + root: [ + 'root', + stickyHeader && 'stickyHeader', + noWrap && 'noWrap', + hoverRow && 'hoverRow', + borderAxis && `borderAxis${capitalize(borderAxis)}`, + variant && `variant${capitalize(variant)}`, + color && `color${capitalize(color)}`, + size && `size${capitalize(size)}`, + ], + }; + + return composeClasses(slots, getTableUtilityClass, {}); +}; + +const tableSelector = { + getColumn(col: number | string) { + if (typeof col === 'number' && col < 0) { + return `& tr > *:nth-last-child(${Math.abs(col)})`; + } + return `& tr > *:nth-child(${col})`; + }, + /** + * Except first column + */ + getColumnExceptFirst() { + return '& tr > *:not(:first-child)'; + }, + /** + * Every cell in the table + */ + getCell() { + return '& th, & td'; + }, + /** + * `th` cell of the table (could exist in the body) + */ + getHeadCell() { + return '& th'; + }, + /** + * Only the cell of `thead` + */ + getHeaderCell() { + return '& thead th'; + }, + getHeaderCellOfRow(row: number | string) { + return `& thead tr:nth-child(${row}) th`; + }, + getBottomHeaderCell() { + return '& thead th:not([colspan])'; + }, + getHeaderNestedFirstColumn() { + return '& thead tr:not(:first-of-type) th:not([colspan]):first-child'; + }, + /** + * The body cell that contains data + */ + getDataCell() { + return '& td'; + }, + getDataCellExceptLastRow() { + return '& tr:not(:last-child) > td'; + }, + /** + * The body cell either `td` or `th` + */ + getBodyCellExceptLastRow() { + return `${this.getDataCellExceptLastRow()}, & tr:not(:last-child) > th[scope="row"]`; + }, + getBodyCellOfRow(row: number | string) { + if (typeof row === 'number' && row < 0) { + return `& tbody tr:nth-last-child(${Math.abs(row)}) td, & tbody tr:nth-last-child(${Math.abs( + row, + )}) th[scope="row"]`; + } + return `& tbody tr:nth-child(${row}) td, & tbody tr:nth-child(${row}) th[scope="row"]`; + }, + getBodyRow(row?: number | string) { + if (row === undefined) { + return `& tbody tr`; + } + return `& tbody tr:nth-child(${row})`; + }, + getFooterCell() { + return '& tfoot th, & tfoot td'; + }, +}; + +const TableRoot = styled('table', { + name: 'JoyTable', + slot: 'Root', + overridesResolver: (props, styles) => styles.root, +})<{ ownerState: TableOwnerState }>(({ theme, ownerState }) => { + const variantStyle = theme.variants[ownerState.variant!]?.[ownerState.color!]; + return [ + { + '--Table-headerUnderlineThickness': '2px', + '--TableCell-borderColor': variantStyle?.borderColor ?? theme.vars.palette.divider, + '--TableCell-headBackground': `var(--Sheet-background, ${theme.vars.palette.background.surface})`, + ...(ownerState.size === 'sm' && { + '--private_TableCell-height': 'var(--TableCell-height, 32px)', + '--TableCell-paddingX': '0.25rem', + '--TableCell-paddingY': '0.25rem', + fontSize: theme.vars.fontSize.xs, + }), + ...(ownerState.size === 'md' && { + '--private_TableCell-height': 'var(--TableCell-height, 40px)', + '--TableCell-paddingX': '0.5rem', + '--TableCell-paddingY': '0.375rem', + fontSize: theme.vars.fontSize.sm, + }), + ...(ownerState.size === 'lg' && { + '--private_TableCell-height': 'var(--TableCell-height, 48px)', + '--TableCell-paddingX': '0.75rem', + '--TableCell-paddingY': '0.5rem', + fontSize: theme.vars.fontSize.md, + }), + tableLayout: 'fixed', + width: '100%', + borderSpacing: '0px', + borderCollapse: 'separate', + color: theme.vars.palette.text.primary, + ...theme.variants[ownerState.variant!]?.[ownerState.color!], + '& caption': { + color: theme.vars.palette.text.tertiary, + padding: 'calc(2 * var(--TableCell-paddingY)) var(--TableCell-paddingX)', + }, + [tableSelector.getDataCell()]: { + padding: 'var(--TableCell-paddingY) var(--TableCell-paddingX)', + height: 'var(--private_TableCell-height)', + borderColor: 'var(--TableCell-borderColor)', // must come after border bottom + backgroundColor: 'var(--TableCell-dataBackground)', // use `background-color` in case the Sheet has gradient background + ...(ownerState.noWrap && { + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + overflow: 'hidden', + }), + }, + [tableSelector.getHeadCell()]: { + textAlign: 'left', + padding: 'var(--TableCell-paddingY) var(--TableCell-paddingX)', + backgroundColor: 'var(--TableCell-headBackground)', // use `background-color` in case the Sheet has gradient background + height: 'var(--private_TableCell-height)', + fontWeight: theme.vars.fontWeight.lg, + borderColor: 'var(--TableCell-borderColor)', + color: theme.vars.palette.text.secondary, + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + overflow: 'hidden', + }, + [tableSelector.getHeaderCell()]: { + verticalAlign: 'bottom', + // Automatic radius adjustment with Sheet + '&:first-child': { + borderTopLeftRadius: 'var(--TableCell-cornerRadius, var(--internal-action-radius))', + }, + '&:last-child': { + borderTopRightRadius: 'var(--TableCell-cornerRadius, var(--internal-action-radius))', + }, + }, + '& tfoot tr > *': { + backgroundColor: `var(--TableCell-footBackground, ${theme.vars.palette.background.level1})`, + // Automatic radius adjustment with Sheet + '&:first-child': { + borderBottomLeftRadius: 'var(--TableCell-cornerRadius, var(--internal-action-radius))', + }, + '&:last-child': { + borderBottomRightRadius: 'var(--TableCell-cornerRadius, var(--internal-action-radius))', + }, + }, + }, + (ownerState.borderAxis?.startsWith('x') || ownerState.borderAxis?.startsWith('both')) && { + // insert border between rows + [tableSelector.getHeaderCell()]: { + borderBottomWidth: 1, + borderBottomStyle: 'solid', + }, + [tableSelector.getBottomHeaderCell()]: { + borderBottomWidth: 'var(--Table-headerUnderlineThickness)', + borderBottomStyle: 'solid', + }, + [tableSelector.getBodyCellExceptLastRow()]: { + borderBottomWidth: 1, + borderBottomStyle: 'solid', + }, + [tableSelector.getFooterCell()]: { + borderTopWidth: 1, + borderTopStyle: 'solid', + }, + }, + (ownerState.borderAxis?.startsWith('y') || ownerState.borderAxis?.startsWith('both')) && { + // insert border between columns + [`${tableSelector.getColumnExceptFirst()}, ${tableSelector.getHeaderNestedFirstColumn()}`]: { + borderLeftWidth: 1, + borderLeftStyle: 'solid', + }, + }, + (ownerState.borderAxis === 'x' || ownerState.borderAxis === 'both') && { + // insert border at the top of header and bottom of body + [tableSelector.getHeaderCellOfRow(1)]: { + borderTopWidth: 1, + borderTopStyle: 'solid', + }, + [tableSelector.getBodyCellOfRow(-1)]: { + borderBottomWidth: 1, + borderBottomStyle: 'solid', + }, + [tableSelector.getFooterCell()]: { + borderBottomWidth: 1, + borderBottomStyle: 'solid', + }, + }, + (ownerState.borderAxis === 'y' || ownerState.borderAxis === 'both') && { + // insert border on the left of first column and right of the last column + [tableSelector.getColumn(1)]: { + borderLeftWidth: 1, + borderLeftStyle: 'solid', + }, + [tableSelector.getColumn(-1)]: { + borderRightWidth: 1, + borderRightStyle: 'solid', + }, + }, + ownerState.stripe && { + [tableSelector.getBodyRow(ownerState.stripe)]: { + // For customization, a table cell can look for this variable with a fallback value. + background: `var(--TableRow-stripeBackground, ${theme.vars.palette.background.level1})`, + color: theme.vars.palette.text.primary, + }, + }, + ownerState.hoverRow && { + [tableSelector.getBodyRow()]: { + '&:hover': { + background: `var(--TableRow-hoverBackground, ${theme.vars.palette.background.level2})`, + }, + }, + }, + ownerState.stickyHeader && { + // The column header + [tableSelector.getHeadCell()]: { + position: 'sticky', + top: 0, + }, + [tableSelector.getHeaderCell()]: { + zIndex: 1, + }, + [tableSelector.getHeaderCellOfRow(2)]: { + // support upto 2 rows for the sticky header + top: 'var(--private_TableCell-height)', + }, + }, + { + // Typography integration + [tableSelector.getCell()]: { + [`& .${typographyClasses.noWrap}`]: { + display: 'block', + }, + }, + }, + ]; +}); + +const Table = React.forwardRef(function Table(inProps, ref) { + const props = useThemeProps({ + props: inProps, + name: 'JoyTable', + }); + + const { + className, + component, + children, + borderAxis = 'xBetween', + hoverRow = false, + noWrap = false, + size = 'md', + variant = 'plain', + color: colorProp = 'neutral', + stripe, + stickyHeader = false, + ...other + } = props; + const { getColor } = useColorInversion(variant); + const color = getColor(inProps.color, colorProp); + + const ownerState = { + ...props, + borderAxis, + hoverRow, + noWrap, + component, + size, + color, + variant, + stripe, + stickyHeader, + }; + + const classes = useUtilityClasses(ownerState); + + return ( + + + {children} + + + ); +}) as OverridableComponent; + +Table.propTypes /* remove-proptypes */ = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit TypeScript types and run "yarn proptypes" | + // ---------------------------------------------------------------------- + /** + * The axis to display a border on the table cell. + * @default 'xBetween' + */ + borderAxis: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf(['both', 'bothBetween', 'none', 'x', 'xBetween', 'y', 'yBetween']), + PropTypes.string, + ]), + /** + * Children of the table + */ + children: PropTypes.node, + /** + * @ignore + */ + className: PropTypes.string, + /** + * The color of the component. It supports those theme colors that make sense for this component. + * @default 'neutral' + */ + color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf(['danger', 'info', 'neutral', 'primary', 'success', 'warning']), + PropTypes.string, + ]), + /** + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, + /** + * If `true`, the table row will shade on hover. + * @default false + */ + hoverRow: PropTypes.bool, + /** + * If `true`, the body cells will not wrap, but instead will truncate with a text overflow ellipsis. + * + * Note: Header cells are always truncated with overflow ellipsis. + * + * @default false + */ + noWrap: PropTypes.bool, + /** + * The size of the component. + * It accepts theme values between 'sm' and 'lg'. + * @default 'md' + */ + size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf(['sm', 'md', 'lg']), + PropTypes.string, + ]), + /** + * Set the header sticky. + * + * āš ļø It doesn't work with IE11. + * @default false + */ + stickyHeader: PropTypes.bool, + /** + * The odd or even row of the table body will have subtle background color. + */ + stripe: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf(['odd', 'even']), + PropTypes.string, + ]), + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + /** + * The variant to use. + * @default 'plain' + */ + variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf(['outlined', 'plain', 'soft', 'solid']), + PropTypes.string, + ]), +} as any; + +export default Table; diff --git a/packages/mui-joy/src/Table/TableProps.ts b/packages/mui-joy/src/Table/TableProps.ts new file mode 100644 index 00000000000000..79dcdfacd3bdd2 --- /dev/null +++ b/packages/mui-joy/src/Table/TableProps.ts @@ -0,0 +1,79 @@ +import * as React from 'react'; +import { OverridableStringUnion, OverrideProps } from '@mui/types'; +import { ColorPaletteProp, VariantProp, SxProps, ApplyColorInversion } from '../styles/types'; + +export type TableSlot = 'root'; + +export interface TablePropsSizeOverrides {} +export interface TablePropsColorOverrides {} +export interface TablePropsVariantOverrides {} +export interface TablePropsBorderAxisOverrides {} + +export interface TableTypeMap

{ + props: P & { + /** + * The axis to display a border on the table cell. + * @default 'xBetween' + */ + borderAxis?: OverridableStringUnion< + 'none' | 'x' | 'xBetween' | 'y' | 'yBetween' | 'both' | 'bothBetween', + TablePropsBorderAxisOverrides + >; + /** + * Children of the table + */ + children?: React.ReactNode; + /** + * The color of the component. It supports those theme colors that make sense for this component. + * @default 'neutral' + */ + color?: OverridableStringUnion; + /** + * If `true`, the table row will shade on hover. + * @default false + */ + hoverRow?: boolean; + /** + * If `true`, the body cells will not wrap, but instead will truncate with a text overflow ellipsis. + * + * Note: Header cells are always truncated with overflow ellipsis. + * + * @default false + */ + noWrap?: boolean; + /** + * The size of the component. + * It accepts theme values between 'sm' and 'lg'. + * @default 'md' + */ + size?: OverridableStringUnion<'sm' | 'md' | 'lg', TablePropsSizeOverrides>; + /** + * Set the header sticky. + * + * āš ļø It doesn't work with IE11. + * @default false + */ + stickyHeader?: boolean; + /** + * The odd or even row of the table body will have subtle background color. + */ + stripe?: 'odd' | 'even' | (string & Record); + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx?: SxProps; + /** + * The variant to use. + * @default 'plain' + */ + variant?: OverridableStringUnion; + }; + defaultComponent: D; +} + +export type TableProps< + D extends React.ElementType = TableTypeMap['defaultComponent'], + P = { component?: React.ElementType }, +> = OverrideProps, D>; + +export interface TableOwnerState extends ApplyColorInversion {} diff --git a/packages/mui-joy/src/Table/index.ts b/packages/mui-joy/src/Table/index.ts new file mode 100644 index 00000000000000..0bcd389394be06 --- /dev/null +++ b/packages/mui-joy/src/Table/index.ts @@ -0,0 +1,4 @@ +export { default } from './Table'; +export * from './tableClasses'; +export { default as tableClasses } from './tableClasses'; +export * from './TableProps'; diff --git a/packages/mui-joy/src/Table/tableClasses.ts b/packages/mui-joy/src/Table/tableClasses.ts new file mode 100644 index 00000000000000..9164a3216cce28 --- /dev/null +++ b/packages/mui-joy/src/Table/tableClasses.ts @@ -0,0 +1,90 @@ +import { generateUtilityClass, generateUtilityClasses } from '../className'; + +export interface TableClasses { + /** Styles applied to the root element. */ + root: string; + /** Styles applied to the root element if `color="primary"`. */ + colorPrimary: string; + /** Styles applied to the root element if `color="neutral"`. */ + colorNeutral: string; + /** Styles applied to the root element if `color="danger"`. */ + colorDanger: string; + /** Styles applied to the root element if `color="info"`. */ + colorInfo: string; + /** Styles applied to the root element if `color="success"`. */ + colorSuccess: string; + /** Styles applied to the root element if `color="warning"`. */ + colorWarning: string; + /** Styles applied to the root element when color inversion is triggered. */ + colorContext: string; + /** Styles applied to the root element if `variant="plain"`. */ + variantPlain: string; + /** Styles applied to the root element if `variant="outlined"`. */ + variantOutlined: string; + /** Styles applied to the root element if `variant="soft"`. */ + variantSoft: string; + /** Styles applied to the root element if `variant="solid"`. */ + variantSolid: string; + /** Styles applied to the root element if `size="sm"`. */ + sizeSm: string; + /** Styles applied to the root element if `size="md"`. */ + sizeMd: string; + /** Styles applied to the root element if `size="lg"`. */ + sizeLg: string; + /** Styles applied to the root element if `stickyHeader` is true. */ + stickyHeader: string; + /** Styles applied to the root element if `noWrap` is true. */ + noWrap: string; + /** Styles applied to the root element if `hoverRow` is true. */ + hoverRow: string; + /** Styles applied to the root element if `borderAxis="none"`. */ + borderAxisNone: string; + /** Styles applied to the root element if `borderAxis="x"`. */ + borderAxisX: string; + /** Styles applied to the root element if `borderAxis="xBetween"`. */ + borderAxisXBetween: string; + /** Styles applied to the root element if `borderAxis="y"`. */ + borderAxisY: string; + /** Styles applied to the root element if `borderAxis="yBetween"`. */ + borderAxisYBetween: string; + /** Styles applied to the root element if `borderAxis="both"`. */ + borderAxisBoth: string; + /** Styles applied to the root element if `borderAxis="bothBetween"`. */ + borderAxisBothBetween: string; +} + +export type TableClassKey = keyof TableClasses; + +export function getTableUtilityClass(slot: string): string { + return generateUtilityClass('JoyTable', slot); +} + +const tableClasses: TableClasses = generateUtilityClasses('JoyTable', [ + 'root', + 'colorPrimary', + 'colorNeutral', + 'colorDanger', + 'colorInfo', + 'colorSuccess', + 'colorWarning', + 'colorContext', + 'variantPlain', + 'variantOutlined', + 'variantSoft', + 'variantSolid', + 'sizeSm', + 'sizeMd', + 'sizeLg', + 'stickyHeader', + 'noWrap', + 'hoverRow', + 'borderAxisNone', + 'borderAxisX', + 'borderAxisXBetween', + 'borderAxisY', + 'borderAxisYBetween', + 'borderAxisBoth', + 'borderAxisBothBetween', +]); + +export default tableClasses; diff --git a/packages/mui-joy/src/Tabs/Tabs.tsx b/packages/mui-joy/src/Tabs/Tabs.tsx index a6526f4a7ca4a0..fb9f8747cb053a 100644 --- a/packages/mui-joy/src/Tabs/Tabs.tsx +++ b/packages/mui-joy/src/Tabs/Tabs.tsx @@ -46,6 +46,7 @@ const TabsRoot = styled(SheetRoot, { flexDirection: 'column', ...(ownerState.orientation === 'vertical' && { flexDirection: 'row', + alignItems: 'flex-start', }), })); @@ -58,7 +59,7 @@ const Tabs = React.forwardRef(function Tabs(inProps, ref) { const { children, value: valueProp, - defaultValue, + defaultValue = valueProp === undefined ? 0 : undefined, orientation = 'horizontal', direction = 'ltr', component, @@ -72,7 +73,7 @@ const Tabs = React.forwardRef(function Tabs(inProps, ref) { const { getColor } = useColorInversion(variant); const color = getColor(inProps.color, colorProp); - const { tabsContextValue } = useTabs({ ...props, orientation }); + const { tabsContextValue } = useTabs({ ...props, orientation, defaultValue }); const ownerState = { ...props, diff --git a/packages/mui-joy/src/Tabs/tabsClasses.ts b/packages/mui-joy/src/Tabs/tabsClasses.ts index b3db18a28400a1..f3b25f08c13333 100644 --- a/packages/mui-joy/src/Tabs/tabsClasses.ts +++ b/packages/mui-joy/src/Tabs/tabsClasses.ts @@ -40,10 +40,10 @@ export interface TabsClasses { export type TabsClassKey = keyof TabsClasses; export function getTabsUtilityClass(slot: string): string { - return generateUtilityClass('JoyTabs', slot); + return generateUtilityClass('MuiTabs', slot); } -const tabListClasses: TabsClasses = generateUtilityClasses('JoyTabs', [ +const tabListClasses: TabsClasses = generateUtilityClasses('MuiTabs', [ 'root', 'horizontal', 'vertical', diff --git a/packages/mui-joy/src/TextField/TextField.spec.tsx b/packages/mui-joy/src/TextField/TextField.spec.tsx deleted file mode 100644 index 66181e546a7782..00000000000000 --- a/packages/mui-joy/src/TextField/TextField.spec.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react'; -import TextField from '@mui/joy/TextField'; -import { expectType } from '@mui/types'; - -} - endDecorator={

} -/>; - { - expectType, typeof event>(event); - }} -/>; diff --git a/packages/mui-joy/src/TextField/TextField.test.js b/packages/mui-joy/src/TextField/TextField.test.js deleted file mode 100644 index 848c8ec5ec8c75..00000000000000 --- a/packages/mui-joy/src/TextField/TextField.test.js +++ /dev/null @@ -1,174 +0,0 @@ -import * as React from 'react'; -import { expect } from 'chai'; -import { spy } from 'sinon'; -import { describeConformance, createRenderer, act, fireEvent } from 'test/utils'; -import { ThemeProvider } from '@mui/joy/styles'; -import TextField, { textFieldClasses as classes } from '@mui/joy/TextField'; -import { inputClasses } from '@mui/joy/Input'; -import { formHelperTextClasses } from '@mui/joy/FormHelperText'; - -describe('Joy ', () => { - const { render } = createRenderer(); - - describeConformance(, () => ({ - classes, - inheritComponent: 'div', - render, - ThemeProvider, - muiName: 'JoyTextField', - refInstanceof: window.HTMLDivElement, - skip: ['componentsProp', 'classesRoot', 'themeVariants'], - })); - - it('should have root className', () => { - const { container } = render(); - expect(container.firstChild).to.have.class(classes.root); - }); - - it('should accept className prop', () => { - const { container } = render(); - expect(container.firstChild).to.have.class('foo-bar'); - }); - - it('should provide proper id to elements', () => { - const { container, getByRole } = render( - , - ); - expect(getByRole('textbox')).to.have.attribute('id', 'textfield'); - expect(container.querySelector('label')).to.have.attribute('id', 'textfield-label'); - expect(container.querySelector(`.${formHelperTextClasses.root}`)).to.have.attribute( - 'id', - 'textfield-helper-text', - ); - }); - - it('should have configurable variant', () => { - const { container, rerender } = render(); - expect(container.firstChild).to.have.class(classes.variantOutlined); // default variant - - rerender(); - expect(container.firstChild).to.have.class(classes.variantSoft); - expect(container.querySelector(`.${inputClasses.root}`)).to.have.class( - inputClasses.variantSoft, - ); - }); - - it('should have configurable size', () => { - const { container, rerender } = render(); - expect(container.firstChild).to.have.class(classes.sizeMd); // default variant - - rerender(); - expect(container.firstChild).to.have.class(classes.sizeSm); - expect(container.querySelector(`.${inputClasses.root}`)).to.have.class(inputClasses.sizeSm); - }); - - it('should have configurable color', () => { - const { container } = render(); - - expect(container.firstChild).to.have.class(classes.colorPrimary); - expect(container.querySelector(`.${inputClasses.root}`)).to.have.class( - inputClasses.colorPrimary, - ); - }); - - it('should pass `type` to Input', () => { - const { getByLabelText } = render(); - - expect(getByLabelText(/password/)).to.have.attribute('type', 'password'); - }); - - it('should pass `name` to Input', () => { - const { getByRole } = render(); - - expect(getByRole('textbox')).to.have.attribute('name', 'username'); - }); - - it('should be error', () => { - const { container } = render(); - - expect(container.firstChild).to.have.class(classes.error); - expect(container.querySelector(`.${inputClasses.root}`)).to.have.class(inputClasses.error); - }); - - it('should be disabled', () => { - const { container } = render(); - - expect(container.firstChild).to.have.class(classes.disabled); - expect(container.querySelector(`.${inputClasses.root}`)).to.have.class(inputClasses.disabled); - }); - - it('should have fullWidth classes', () => { - const { container } = render(); - - expect(container.firstChild).to.have.class(classes.fullWidth); - expect(container.querySelector(`.${inputClasses.root}`)).to.have.class(inputClasses.fullWidth); - }); - - it('should show asterisk if required', () => { - const { getByRole, container } = render( - label
} />, - ); - - expect(container.querySelector(`label`)).to.have.text('label\u2009*'); - expect(getByRole('textbox')).to.have.attribute('required'); - }); - - it('should accept defaultValue', () => { - const { getByRole } = render(); - expect(getByRole('textbox')).to.have.value('foo'); - }); - - it('should pass value and handler props to Input', () => { - const handleChange = spy(); - const handleFocus = spy(); - const handleBlur = spy(); - const handleKeyUp = spy(); - const handleKeyDown = spy(); - const { getByRole } = render( - , - ); - const input = getByRole('textbox'); - - expect(input).to.have.value('bar'); - - act(() => { - input.focus(); - }); - expect(handleFocus.callCount).to.equal(1); - - fireEvent.keyDown(input, { key: 'a' }); - expect(handleKeyDown.callCount).to.equal(1); - - fireEvent.change(input, { target: { value: 'a' } }); - expect(handleChange.callCount).to.equal(1); - - fireEvent.keyUp(input, { key: 'a' }); - expect(handleKeyUp.callCount).to.equal(1); - - act(() => { - input.blur(); - }); - expect(handleBlur.callCount).to.equal(1); - }); - - it('should accept startDecorator', () => { - const { getByText } = render(); - expect(getByText('foo')).toBeVisible(); - }); - - it('should accept endDecorator', () => { - const { getByText } = render(); - expect(getByText('bar')).toBeVisible(); - }); -}); diff --git a/packages/mui-joy/src/TextField/TextField.tsx b/packages/mui-joy/src/TextField/TextField.tsx index 4059e705590488..cfcd020fa3926a 100644 --- a/packages/mui-joy/src/TextField/TextField.tsx +++ b/packages/mui-joy/src/TextField/TextField.tsx @@ -1,356 +1,8 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import clsx from 'clsx'; -import { OverridableComponent } from '@mui/types'; -import { unstable_useId as useId, unstable_capitalize as capitalize } from '@mui/utils'; -import composeClasses from '@mui/base/composeClasses'; -import FormLabel from '../FormLabel'; -import FormHelperText from '../FormHelperText'; -import JoyInput from '../Input'; -import { styled, useThemeProps } from '../styles'; -import useSlot from '../utils/useSlot'; -import { TextFieldOwnerState, TextFieldTypeMap } from './TextFieldProps'; -import textFieldClasses, { getTextFieldUtilityClass } from './textFieldClasses'; - -const useUtilityClasses = (ownerState: TextFieldOwnerState) => { - const { error, disabled, variant, size, color, fullWidth } = ownerState; - const slots = { - root: [ - 'root', - error && 'error', - disabled && 'disabled', - fullWidth && 'fullWidth', - variant && `variant${capitalize(variant)}`, - size && `size${capitalize(size)}`, - color && `color${capitalize(color)}`, - ], - }; - - return composeClasses(slots, getTextFieldUtilityClass, {}); -}; - -const TextFieldRoot = styled('div', { - name: 'JoyTextField', - slot: 'Root', - overridesResolver: (props, styles) => styles.root, -})<{ ownerState: TextFieldOwnerState }>(({ theme, ownerState }) => ({ - '--FormLabel-margin': '0 0 0.25rem 0', - '--FormHelperText-margin': '0.25rem 0 0 0', - '--FormLabel-asterisk-color': theme.vars.palette.danger[500], - '--FormHelperText-color': theme.vars.palette[ownerState.color!]?.[500], - ...(ownerState.size === 'sm' && { - '--FormHelperText-fontSize': theme.vars.fontSize.xs, - '--FormLabel-fontSize': theme.vars.fontSize.xs, - }), - [`&.${textFieldClasses.error}`]: { - '--FormHelperText-color': theme.vars.palette.danger[500], - }, - [`&.${textFieldClasses.disabled}`]: { - '--FormLabel-color': theme.vars.palette[ownerState.color || 'neutral']?.plainDisabledColor, - '--FormHelperText-color': theme.vars.palette[ownerState.color || 'neutral']?.plainDisabledColor, - }, - display: 'flex', - flexDirection: 'column', - ...(ownerState.fullWidth && { - width: '100%', - }), -})); - -const TextField = React.forwardRef(function TextField(inProps, ref) { - const props = useThemeProps({ - props: inProps, - name: 'JoyTextField', - }); - - const { - children, - className, - component, - slots = {}, - slotProps = {}, - label, - helperText, - id: idOverride, - autoComplete, - autoFocus, - placeholder, - defaultValue, - value, - name, - onBlur, - onChange, - onFocus, - color, - disabled = false, - error = false, - required = false, - size = 'md', - variant = 'outlined', - fullWidth = false, - type = 'text', - startDecorator, - endDecorator, - ...other - } = props; - - const id = useId(idOverride); - const helperTextId = helperText && id ? `${id}-helper-text` : undefined; - const formLabelId = label && id ? `${id}-label` : undefined; - - const ownerState = { - label, - helperText, - startDecorator, - endDecorator, - disabled, - error, - required, - size, - variant, - fullWidth, - type, - ...props, - }; - - const classes = useUtilityClasses(ownerState); - - const [SlotRoot, rootProps] = useSlot('root', { - ref, - className: clsx(classes.root, className), - elementType: TextFieldRoot, - // @ts-ignore internal logic - externalForwardedProps: { ...other, component, slots, slotProps }, - ownerState, - }); - - const Input = slots.input || JoyInput; - - return ( - // @ts-ignore neglect 'context' color - - {label && ( - - {label} - - )} - - - {helperText && ( - - {helperText} - - )} - +/** + * @ignore - do not document. + */ +export default (function DeletedTextField() { + throw new Error( + 'MUI: `TextField` component has been removed in favor of Input composition.\n\nTo migrate, run `npx @mui/codemod v5.0.0/joy-text-field-to-input `.\nFor the codemod detail, visit https://github.com/mui/material-ui/blob/master/packages/mui-codemod/README.md#joy-text-field-to-input\n\nTo learn more why it has been removed, visit the RFC https://github.com/mui/material-ui/issues/34176', ); -}) as OverridableComponent; - -TextField.propTypes /* remove-proptypes */ = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit TypeScript types and run "yarn proptypes" | - // ---------------------------------------------------------------------- - /** - * @ignore - */ - autoComplete: PropTypes.string, - /** - * @ignore - */ - autoFocus: PropTypes.bool, - /** - * @ignore - */ - children: PropTypes.node, - /** - * @ignore - */ - className: PropTypes.string, - /** - * The color of the component. It supports those theme colors that make sense for this component. - * @default 'neutral' - */ - color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ - PropTypes.oneOf(['danger', 'info', 'neutral', 'primary', 'success', 'warning']), - PropTypes.string, - ]), - /** - * The component used for the root node. - * Either a string to use a HTML element or a component. - */ - component: PropTypes.elementType, - /** - * @ignore - */ - defaultValue: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string), - PropTypes.number, - PropTypes.string, - ]), - /** - * @ignore - */ - disabled: PropTypes.bool, - /** - * Trailing adornment for this input. - */ - endDecorator: PropTypes.node, - /** - * If `true`, the `input` will indicate an error. - * The prop defaults to the value (`false`) inherited from the parent FormControl component. - */ - error: PropTypes.bool, - /** - * If `true`, the button will take up the full width of its container. - * @default false - */ - fullWidth: PropTypes.bool, - /** - * The helper text content. - */ - helperText: PropTypes.node, - /** - * The id of the `input` element. - * Use this prop to make `label` and `helperText` accessible for screen readers. - */ - id: PropTypes.string, - /** - * The label content. - */ - label: PropTypes.node, - /** - * Name attribute of the `input` element. - */ - name: PropTypes.string, - /** - * @ignore - */ - onBlur: PropTypes.func, - /** - * @ignore - */ - onChange: PropTypes.func, - /** - * @ignore - */ - onFocus: PropTypes.func, - /** - * The short hint displayed in the `input` before the user enters a value. - */ - placeholder: PropTypes.string, - /** - * @ignore - */ - required: PropTypes.bool, - /** - * The size of the component. - * @default 'md' - */ - size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ - PropTypes.oneOf(['sm', 'md', 'lg']), - PropTypes.string, - ]), - /** - * @ignore - */ - slotProps: PropTypes.shape({ - helperText: PropTypes.object, - input: PropTypes.object, - label: PropTypes.object, - root: PropTypes.object, - }), - /** - * @ignore - */ - slots: PropTypes.shape({ - helperText: PropTypes.elementType, - input: PropTypes.elementType, - label: PropTypes.elementType, - root: PropTypes.elementType, - }), - /** - * Leading adornment for this input. - */ - startDecorator: PropTypes.node, - /** - * @ignore - */ - type: PropTypes /* @typescript-to-proptypes-ignore */.oneOf([ - 'button', - 'checkbox', - 'color', - 'date', - 'datetime-local', - 'email', - 'file', - 'hidden', - 'image', - 'month', - 'number', - 'password', - 'radio', - 'range', - 'reset', - 'search', - 'submit', - 'tel', - 'text', - 'time', - 'url', - 'week', - ]), - /** - * @ignore - */ - value: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string), - PropTypes.number, - PropTypes.string, - ]), - /** - * The variant to use. - * @default 'outlined' - */ - variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ - PropTypes.oneOf(['outlined', 'plain', 'soft', 'solid']), - PropTypes.string, - ]), -} as any; - -export default TextField; +}); diff --git a/packages/mui-joy/src/TextField/TextFieldProps.ts b/packages/mui-joy/src/TextField/TextFieldProps.ts deleted file mode 100644 index bded6834bac229..00000000000000 --- a/packages/mui-joy/src/TextField/TextFieldProps.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as React from 'react'; -import { OverrideProps } from '@mui/types'; -import { FormHelperTextProps } from '../FormHelperText/FormHelperTextProps'; -import { FormLabelProps } from '../FormLabel/FormLabelProps'; -import { InputProps } from '../Input/InputProps'; - -export type TextFieldSlot = 'root'; - -type InputRootKeys = - | 'autoComplete' - | 'autoFocus' - | 'disabled' - | 'error' - | 'required' - | 'fullWidth' - | 'placeholder' - | 'defaultValue' - | 'value' - | 'onChange' - | 'onFocus' - | 'onBlur' - | 'type' - | 'variant' - | 'color' - | 'size' - | 'startDecorator' - | 'endDecorator' - | 'sx'; - -export interface TextFieldTypeMap

{ - props: P & - Pick & { - slots?: { - root?: React.ElementType; - label?: React.ElementType; - input?: React.ElementType; - helperText?: React.ElementType; - }; - slotProps?: { - root?: React.ComponentPropsWithRef<'div'>; - label?: FormLabelProps; - input?: Omit; - helperText?: FormHelperTextProps; - }; - /** - * The id of the `input` element. - * Use this prop to make `label` and `helperText` accessible for screen readers. - */ - id?: string; - /** - * The label content. - */ - label?: React.ReactNode; - /** - * Name attribute of the `input` element. - */ - name?: string; - /** - * The short hint displayed in the `input` before the user enters a value. - */ - placeholder?: string; - /** - * The helper text content. - */ - helperText?: React.ReactNode; - }; - defaultComponent: D; -} - -export type TextFieldProps< - D extends React.ElementType = TextFieldTypeMap['defaultComponent'], - P = { - component?: React.ElementType; - }, -> = OverrideProps, D>; - -export interface TextFieldOwnerState extends TextFieldProps {} diff --git a/packages/mui-joy/src/TextField/index.ts b/packages/mui-joy/src/TextField/index.ts index d03daa37fe8c95..0198002999a808 100644 --- a/packages/mui-joy/src/TextField/index.ts +++ b/packages/mui-joy/src/TextField/index.ts @@ -1,4 +1 @@ export { default } from './TextField'; -export { default as textFieldClasses } from './textFieldClasses'; -export * from './textFieldClasses'; -export * from './TextFieldProps'; diff --git a/packages/mui-joy/src/TextField/textFieldClasses.ts b/packages/mui-joy/src/TextField/textFieldClasses.ts deleted file mode 100644 index 018c4fe5aaca91..00000000000000 --- a/packages/mui-joy/src/TextField/textFieldClasses.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { generateUtilityClass, generateUtilityClasses } from '../className'; - -export interface TextFieldClasses { - /** Styles applied to the root element. */ - root: string; - /** Styles applied to the root element if `disabled={true}`. */ - disabled: string; - /** State class applied to the root element if `error={true}`. */ - error: string; - /** Styles applied to the root element if the component is focused. */ - focused: string; - /** Styles applied to the root element if `color="primary"`. */ - colorPrimary: string; - /** Styles applied to the root element if `color="neutral"`. */ - colorNeutral: string; - /** Styles applied to the root element if `color="danger"`. */ - colorDanger: string; - /** Styles applied to the root element if `color="info"`. */ - colorInfo: string; - /** Styles applied to the root element if `color="success"`. */ - colorSuccess: string; - /** Styles applied to the root element if `color="warning"`. */ - colorWarning: string; - /** Styles applied to the root element if `size="sm"`. */ - sizeSm: string; - /** Styles applied to the root element if `size="md"`. */ - sizeMd: string; - /** Styles applied to the root element if `size="lg"`. */ - sizeLg: string; - /** Styles applied to the root element if `variant="plain"`. */ - variantPlain: string; - /** Styles applied to the root element if `variant="outlined"`. */ - variantOutlined: string; - /** Styles applied to the root element if `variant="soft"`. */ - variantSoft: string; - /** Styles applied to the root element if `fullWidth={true}`. */ - fullWidth: string; -} - -export type TextFieldClassKey = keyof TextFieldClasses; - -export function getTextFieldUtilityClass(slot: string): string { - return generateUtilityClass('JoyTextField', slot); -} - -const textFieldClasses: TextFieldClasses = generateUtilityClasses('JoyTextField', [ - 'root', - 'disabled', - 'error', - 'focused', - 'colorPrimary', - 'colorNeutral', - 'colorDanger', - 'colorInfo', - 'colorSuccess', - 'colorWarning', - 'sizeSm', - 'sizeMd', - 'sizeLg', - 'variantPlain', - 'variantOutlined', - 'variantSoft', - 'fullWidth', -]); - -export default textFieldClasses; diff --git a/packages/mui-joy/src/Textarea/Textarea.test.tsx b/packages/mui-joy/src/Textarea/Textarea.test.tsx index 2710f4f0f3e61d..dfe176c48421b9 100644 --- a/packages/mui-joy/src/Textarea/Textarea.test.tsx +++ b/packages/mui-joy/src/Textarea/Textarea.test.tsx @@ -7,6 +7,7 @@ import { createRenderer, screen, act, + fireEvent, } from 'test/utils'; import Textarea, { textareaClasses as classes } from '@mui/joy/Textarea'; import { ThemeProvider } from '@mui/joy/styles'; @@ -34,6 +35,11 @@ describe('Joy