diff --git a/.circleci/config.yml b/.circleci/config.yml index cceaa62184299b..17ead4d606aa83 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -341,7 +341,7 @@ jobs: test_browser: <<: *defaults docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -371,7 +371,7 @@ jobs: test_e2e: <<: *defaults docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -390,7 +390,7 @@ jobs: test_e2e_website: <<: *defaults docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -405,7 +405,7 @@ jobs: test_profile: <<: *defaults docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -432,7 +432,7 @@ jobs: test_regressions: <<: *defaults docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -486,7 +486,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/next-webpack4/ docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -510,7 +510,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/next-webpack5/ docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -534,7 +534,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/create-react-app/ docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -558,7 +558,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/snowpack/ docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -582,7 +582,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/vite/ docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -606,7 +606,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/esbuild/ docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -634,7 +634,7 @@ jobs: <<: *defaults working_directory: /tmp/material-ui/test/bundling/fixtures/gatsby/ docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: @@ -736,7 +736,7 @@ jobs: test_benchmark: <<: *defaults docker: - - image: mcr.microsoft.com/playwright:v1.20.0-focal + - image: mcr.microsoft.com/playwright:v1.22.2-focal environment: NODE_ENV: development # Needed if playwright is in `devDependencies` steps: diff --git a/.eslintignore b/.eslintignore index 994e23efd8ff66..75f2f355f0d461 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,6 +3,7 @@ /benchmark/**/dist /coverage /docs/export +/docs/pages/playground.tsx /examples/create-react-app*/src/serviceWorker.js /examples/gatsby/public/ /examples/preact/config diff --git a/.eslintrc.js b/.eslintrc.js index 8df154dca97c8f..bda8a0bc86b406 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -371,7 +371,12 @@ module.exports = { ], }, ], - + }, + }, + { + files: ['packages/*/src/**/*{.ts,.tsx,.js}'], + excludedFiles: ['*.d.ts', '*.spec.ts', '*.spec.tsx', 'packages/mui-joy/**/*{.ts,.tsx,.js}'], + rules: { 'material-ui/mui-name-matches-component-name': [ 'error', { diff --git a/.github/ISSUE_TEMPLATE/1.bug.yml b/.github/ISSUE_TEMPLATE/1.bug.yml index f95faf2e3a7a44..c15969db3a2162 100644 --- a/.github/ISSUE_TEMPLATE/1.bug.yml +++ b/.github/ISSUE_TEMPLATE/1.bug.yml @@ -34,12 +34,11 @@ body: attributes: label: Steps to reproduce 🕹 description: | - Provide a link to a live example (you can use codesandbox.io) and an unambiguous set of steps to reproduce this bug. - Include code to reproduce, if relevant (which it most likely is). + Please provide a link to a live example and an unambiguous set of steps to reproduce this bug. + + As a starting point, we recommend you browse our [documentation](https://mui.com/material-ui/getting-started/installation/), and [select](https://mui.com/static/docs/forking-an-example.png) the closest example to your use case. - You can use the official codesandbox template as a starting point: https://mui.com/r/issue-template. - - If you have an issue concerning TypeScript please start from this TypeScript playground: https://mui.com/r/ts-issue-template. + Or you can use the [official template](https://mui.com/r/issue-template) to build a reproduction case. Issues that we can't reproduce will be closed. value: | @@ -59,7 +58,7 @@ body: description: Run `npx @mui/envinfo` and post the results. If you encounter issues with TypeScript please include the used tsconfig. value: |
- `npx @mui/envinfo` + npx @mui/envinfo ``` Don't forget to mention which browser you used. diff --git a/.github/renovate.json b/.github/renovate.json index 679d4f5032061d..5667a07ad21a31 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -8,6 +8,10 @@ "rebaseWhen": "conflicted", "ignoreDeps": [], "labels": ["dependencies"], + "lockFileMaintenance": { + "enabled": true, + "schedule": "before 6:00am on the first day of the month" + }, "packageRules": [ { "matchDepTypes": ["peerDependencies"], diff --git a/.github/workflows/check-if-pr-has-label.yml b/.github/workflows/check-if-pr-has-label.yml new file mode 100644 index 00000000000000..0501d0c1839366 --- /dev/null +++ b/.github/workflows/check-if-pr-has-label.yml @@ -0,0 +1,16 @@ +name: Check if PR has label + +on: + pull_request: + types: [opened, reopened, labeled, unlabeled] + +jobs: + test-label-applied: + # Tests that label is added on the PR + runs-on: ubuntu-latest + steps: + - uses: mnajdova/github-action-required-labels@v2.0 + with: + mode: minimum + count: 1 + labels: "" \ No newline at end of file diff --git a/.github/workflows/close-incomplete-inactive.yml b/.github/workflows/close-incomplete-inactive.yml deleted file mode 100644 index 12a2323b5ccead..00000000000000 --- a/.github/workflows/close-incomplete-inactive.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Close incomplete inactive -on: - schedule: - - cron: "0 0 * * *" -jobs: - close-issues: - runs-on: ubuntu-latest - steps: - - name: Need more information - uses: actions-cool/issues-helper@v3 - with: - actions: 'close-issues' - labels: 'status: incomplete' - inactive-day: 7 - body: | - Since the issue is missing key information, and has been inactive for 7 days, it has been automatically closed. - If you wish to see the issue reopened, please provide the missing information. diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml new file mode 100644 index 00000000000000..496dce78ac0f97 --- /dev/null +++ b/.github/workflows/no-response.yml @@ -0,0 +1,26 @@ +name: No Response + +# Both `issue_comment` and `scheduled` event types are required for this Action +# to work properly. +on: + issue_comment: + types: [created] + schedule: + # Schedule for five minutes after the hour, every hour + - cron: '5 * * * *' + +jobs: + noResponse: + runs-on: ubuntu-latest + steps: + - uses: lee-dohm/no-response@v0.5.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + # Number of days of inactivity before an Issue is closed for lack of response + daysUntilClose: 7 + # Label requiring a response + responseRequiredLabel: 'status: needs more information' + # Comment to post when closing an Issue for lack of response. Set to `false` to disable + closeComment: > + Since the issue is missing key information and has been inactive for 7 days, it has been automatically closed. + If you wish to see the issue reopened, please provide the missing information. \ No newline at end of file diff --git a/.github/workflows/support-stackoverflow.yml b/.github/workflows/support-stackoverflow.yml index 9a77cf7f29ec8a..0f839c43657cd9 100644 --- a/.github/workflows/support-stackoverflow.yml +++ b/.github/workflows/support-stackoverflow.yml @@ -28,6 +28,6 @@ jobs: For support, please check out https://mui.com/getting-started/support/. Thanks! If you have a question on StackOverflow, you are welcome to link to it here, it might help others. - If your issue is subsequently confirmed as a bug, and the report follows the issue template, it can be reopened. + If your issue is subsequently confirmed as a bug, and the report follows the issue template, it can be reopened. close-issue: true lock-issue: false diff --git a/.gitignore b/.gitignore index 48190e100a0371..823978752e3e16 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ # However, in order to prevent issues, they are ignored here. .DS_STORE .idea +# IntelliJ IDEA module file +*.iml .vscode/* !.vscode/launch.json *.log diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc index f0afe4ecf3368c..308795c590aa6e 100644 --- a/.markdownlint.jsonc +++ b/.markdownlint.jsonc @@ -24,5 +24,7 @@ // MD004/ul-style. Buggy "MD004": false, // MD028/no-blanks-blockquote prevent double blockquote - "MD028": false + "MD028": false, + // MD031/blanks-around-fences Some code blocks inside li + "MD031": false } diff --git a/CHANGELOG.md b/CHANGELOG.md index 74f2914d7858ac..df6173b8dc7add 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,920 @@ # [Versions](https://mui.com/versions/) +## 5.8.5 + + + +_Jun 20, 2022_ + +A big thanks to the 14 contributors who made this release possible. Here are some highlights ✨: + +- 🚀 Added support for CSS variables in the `Avatar` component and the `SpeedDialAction` component respectively by @vicasas and @gin1314 +- many other 🐛 bug fixes and 📚 documentation improvements + +### `@mui/material@5.8.5` + +- ​[Avatar] Add support for CSS variables (#32499) @vicasas +- ​[Dialog] Fix broken styles if `maxWidth` is set to `false` (#32987) @kmurgic +- ​[SpeedDialAction] Add support for CSS variables (#32608) @gin1314 +- ​[Tabs] Increment scroll of the minimum amount possible (#33103) @oliviertassinari + +### `@mui/codemod@5.8.5` + +- ​[codemod] Preserve comments within jss-to-tss-react (#33170) @ryancogswell + +### `@mui/lab@5.0.0-alpha.87` + +- ​[Masonry] Fix flickering when used with React 18 (#33163) @mnajdova + +### `@mui/base@5.0.0-alpha.86` + +- ​[BadgeUnstyled] Accept callbacks in componentsProps (#33176) @michaldudak +- ​[ButtonUnstyled] Use useSlotProps (#33096) @michaldudak +- ​[FormControlUnstyled] Accept callbacks in componentsProps (#33180) @michaldudak +- ​[InputUnstyled] Use useSlotProps (#33094) @michaldudak +- ​[ModalUnstyled] Define ownerState and slot props' types (#32901) @michaldudak +- ​[SwitchUnstyled] Use useSlotProps (#33174) @michaldudak + +### `@mui/joy@5.0.0-alpha.33` + +- ​[Joy] Add Checkbox documentation (#33171) @siriwatknp +- ​[Joy] Add List documentation (#33120) @siriwatknp +- ​[Joy] Make slider displays Joy classname (#33051) @siriwatknp + +### Docs + +- ​[blog] Update Blogpost to clear confusion on "no impact" disclaimer. (#33131) @joserodolfofreitas +- ​[blog] Add post about v5 Migration guide update (#33063) @samuelsycamore +- ​[blog] Fix display on Safari (#33102) @oliviertassinari +- ​[docs] Add guide on how to use MUI Base with Tailwind CSS (#33100) @mnajdova +- ​[docs] Improve Joy template UX (#33159) @siriwatknp +- ​[docs] Update Shadow DOM guide (#33160) @cherniavskii +- ​[docs] Fix SEO regressions (#33106) @oliviertassinari +- ​[docs] Add job ad in table of content (#33143) @mnajdova +- ​[docs] Add customization as a value proposition (#33014) @oliviertassinari +- ​[examples] Add example using nextjs & @mui/styles as a starter for the migration to v5 (#33005) @mnajdova +- ​[website] Replace Airtable with Ashby links for applying to a opened position (#33193) @DanailH + +### Core + +- ​[core] Add CSS variables support for Material UI components (#32835) @siriwatknp +- ​[core] Add name to workspace root package.json (#33226) @Janpot +- ​[core] Update bug template with generic instruction (#33153) @joserodolfofreitas +- ​[core] Remove dead and redundant code (#33125) @oliviertassinari +- ​[core] Improve inline code rendering within the details tag (#33086) @Harmouch101 + +All contributors of this release in alphabetical order: @cherniavskii, @DanailH, @gin1314, @Harmouch101, @Janpot, @joserodolfofreitas, @kmurgic, @michaldudak, @mnajdova, @oliviertassinari, @ryancogswell, @samuelsycamore, @siriwatknp, @vicasas + +## 5.8.4 + + + +_Jun 14, 2022_ + +A big thanks to the 24 contributors who made this release possible. Here are some highlights ✨: + +- 🚀 Added support for custom breakpoints in the `Grid` component by @boutahlilsoufiane +- 📚 Added guide on how to use Material UI with Shadow DOM by @cherniavskii +- many other 🐛 bug fixes and 📚 documentation improvements + +### `@mui/material@5.8.4` + +- ​[Button] Add missing classes in `ButtonClasses` type (#33040) @ZeeshanTamboli +- ​[Grid] Fix prop-type key regression (#33123) @oliviertassinari +- ​[Grid] Support custom breakpoints (#31998) @boutahlilsoufiane +- ​[Grow] Limit CSS transition bug workaround to Safari 15.4 only (#32996) @igordanchenko +- ​[Hidden] Remove dependency on hoist-non-react-statics (#33015) @oliviertassinari +- ​[Link] Add support for CSS variables (#33036) @winderica +- ​[Popover] Export `getOffsetTop` & `getOffsetLeft` from Popover's index and add typings (#32959) @rart +- ​[Slider] Fix SliderValueLabelProps type (#32895) @oliviertassinari +- ​[Snackbar] Remove `RTL` direction specific logic (#32808) @aaarichter +- ​[StepIcon] Fix text centering when changing browser font size (#32706) @alansouzati +- ​[Tabs] Scroll by width of the first visible tab if only one tab is partially visible (#32778) @frankkluijtmans + +### `@mui/system@5.8.4` + +- ​[Stack, system] Apply correct responsive styles if any custom breakpoints are provided (#32913) @ZeeshanTamboli +- ​[system] Fix missing typings for ColorFormat (#32417) @l-zoy + +### `@mui/codemod@5.8.4` + +- ​[codemod] Add support for `@mui/styles/makeStyles` imports (#32962) @joshkel + +### `@mui/lab@5.0.0-alpha.86` + +- ​[pickers] Fix broken ref forwarding (#33107) @oliviertassinari +- ​[lab] Fix React's `forwardRef` warning when importing from the index (#33134) @mnajdova + +### `@mui/base@5.0.0-alpha.85` + +- ​[MenuUnstyled] Accept callbacks in componentsProps (#32997) @michaldudak +- ​[ModalUnstyled] Fix errors from the W3C validator about incorrect aria-hidden attribute on some elements (#30920) @mkrtchian +- ​[ModalUnstyled] Fix behavior of not respecting props ariaHidden value (#32055) @tech-meppem + +### `@mui/joy@5.0.0-alpha.32` + +- ​[Joy] Miscellaneous card fixes (#33129) @siriwatknp +- ​[Joy] Miscellaneous fixes (#33073) @siriwatknp +- ​[Joy] Add typography and link docs (#33047) @siriwatknp + +### Docs + +- ​[Contributing.md] Local install instructions (#32975) @Moizsohail +- ​[docs] Add responsive AppBar with drawer (#32769) @dvlprAlamin +- ​[docs] Move codesandbox to MUI org (#33122) @oliviertassinari +- ​[docs] Add Shadow DOM guide (#33007) @cherniavskii +- ​[docs] Fix typo in Material UI overview page (#33087) @oliviertassinari +- ​[docs] Miscellaneous fixes in `MUI Base` docs (#33091) @ZeeshanTamboli +- ​[docs] Fix GitHub capitalization (#33071) @oliviertassinari +- ​[docs] Fix a typo in `InputUnstyled` docs (#33077) @ZeeshanTamboli +- ​[docs] Add notification for Joy blog post (#33059) @siriwatknp +- ​[docs] Improve aspect ratio docs and integration (#33065) @siriwatknp +- ​[docs] Update code block copy label (#33128) @siriwatknp +- ​[docs] Fix typo in Autocomplete CSS API (#32838) @KeaghanKennedy +- ​[docs] Improvements for Radio Group Rating Docs (#32843) @Kai-W +- ​[docs] Enable Joy pages (#33064) @siriwatknp +- ​[website] Add Joy UI to the pricing page (#33099) @danilo-leal +- ​[website] Clarify the pricing a bit (#33069) @oliviertassinari + +### Core + +- ​yarn proptypes @oliviertassinari +- ​[core] Update dependencies to fix security vulnerabilities (#33095) @michaldudak +- ​[core] Import new line convention (#33068) @oliviertassinari +- ​[core] Make repository configurable in changelog script (#33130) @Janpot + +All contributors of this release in alphabetical order: @aaarichter, @alansouzati, @boutahlilsoufiane, @cherniavskii, @danilo-leal, @dvlprAlamin, @frankkluijtmans, @igordanchenko, @Janpot, @joshkel, @Kai-W, @KeaghanKennedy, @l-zoy, @michaldudak, @mkrtchian, @mnajdova, @Moizsohail, @oliviertassinari, @pushys, @rart, @siriwatknp, @tech-meppem, @winderica, @ZeeshanTamboli + +## 5.8.3 + + + +_Jun 7, 2022_ + +A big thanks to the 15 contributors who made this release possible. +This release is mostly about 🐛 bug fixes and 📚 documentation improvements. + +### `@mui/material@5.8.3` + +- [Alert] Constrain message width and allow overflow (#32747) @Janpot +- [Checkbox] Add support for CSS variables (#32579) @haneenmahd +- [Slider] Fix positioning of tooltips on vertical slider (#32919) @abhinav-22-tech + +### `@mui/system@5.8.3` + +- [system] Configurable attributes for libraries (#32971) @siriwatknp + +### `@mui/codemod@5.8.3` + +- [codemod] Fix infinite loop in jss-to-tss-react and add TODO (#33048) @ryancogswell + +### `@mui/lab@5.0.0-alpha.85` + +- [pickers] Add deprecations when importing pickers from the lab (#32950) @flaviendelangle + +### `@mui/joy@5.0.0-alpha.31` + +- [Joy] Add `Slider` component and demos (#32694) @hbjORbj +- [Joy] Add articles about customization approaches (#32887) @siriwatknp +- [Joy] Add automatic adjustment page to core features (#32980) @siriwatknp +- [Joy] Add docs about dark mode (#33002) @siriwatknp +- [Joy] Add template UIs & first look blog post (#32791) @danilo-leal + +### `@mui/base@5.0.0-alpha.84` + +- [base] Remove @mui/system in tests (#32945) @kevinji +- [ButtonUnstyled] Accept callbacks in componentsProps (#32991) @michaldudak +- [SwitchUnstyled] Accept callbacks in componentsProps (#32993) @michaldudak +- [TablePaginationUnstyled] Define ownerState and slot props' types (#32905) @michaldudak +- [TabPanelUnstyled] Define ownerState and slot props' types (#32928) @michaldudak +- [TabsListUnstyled] Define ownerState and slot props' types (#32925) @michaldudak + +### Docs + +- [blog] Fix anchor link scroll (#32994) @oliviertassinari +- [docs] Add "Migration" section to sidebar and revise v4-v5 content (#32740) @samuelsycamore +- [docs] Add What doesn't count as a breaking change? (#32850) @oliviertassinari +- [docs] Fix 301 link @oliviertassinari +- [docs] Fix icon color in `BadgeUnstyled` docs (#32976) @ZeeshanTamboli +- [docs] Improve product identifier (#32707) @danilo-leal +- [docs] Improve UX with back to top (#32896) @oliviertassinari +- [docs] Polish overview page to Material UI (#32954) @oliviertassinari +- [docs] Redirect older URLs (#33037) @oliviertassinari +- [docs] Remove pickers page from the Lab section (#32961) @DanailH +- [docs] Show product identifier on updated MUI X Introduction pages (#32966) @samuelsycamore +- [docs] Throw on 301 links (#32939) @oliviertassinari +- [website] Add Gerda to the about page (#33038) @danilo-leal +- [website] Polish the pricing page (#32811) @oliviertassinari +- [website] Remove unnecessary `address` dependency (#32957) @michaldudak + +### Core + +- [core] Improve icon synonyms (#32742) @oliviertassinari +- [core] Prepare Next.js config for React 18 (#32963) @michaldudak +- [core] Remove dead logic (#32940) @oliviertassinari +- [core] Update dependencies to fix security vulnerabilities (#32947) @michaldudak +- Add security link to README for Tidelift @mbrookes + +All contributors of this release in alphabetical order: @abhinav-22-tech, @DanailH, @danilo-leal, @flaviendelangle, @haneenmahd, @hbjORbj, @Janpot, @kevinji, @mbrookes, @michaldudak, @oliviertassinari, @ryancogswell, @samuelsycamore, @siriwatknp, @ZeeshanTamboli + +## 5.8.2 + + + +_May 30, 2022_ + +A big thanks to the 8 contributors who made this release possible. Here are some highlights ✨: + +- 🐛 bug fixes and 📚 documentation improvements. + +### `@mui/system@5.8.2` + +- ​[system] Add `getColorSchemeSelector` util (#32868) @siriwatknp + +### `@mui/lab@5.0.0-alpha.84` + +- ​[Masonry] Place items to the left when there are less objects than specified in `column` prop (#32873) @hbjORbj + +### `@mui/base@5.0.0-alpha.83` + +- ​[BadgeUnstyled] Define ownerState and slot props' types (#32750) @michaldudak +- ​[SliderUnstyled] Define ownerState and slot props' types (#32739) @michaldudak +- ​[SwitchUnstyled] Define ownerState and slot props' types (#32573) @michaldudak +- ​[TabsUnstyled] Define ownerState and slot props' types (#32918) @michaldudak +- ​[TabUnstyled] Define ownerState and slot props' types (#32915) @michaldudak + +### `@mui/joy@5.0.0-alpha.30` + +- ​[Joy] use `textColor` prop for Typography and Link (#32938) @siriwatknp +- ​[Joy] Make variants for more flexible (#32931) @siriwatknp +- ​[Joy] Improve automatic adjustment (#32923) @siriwatknp +- ​[Joy] Add `Chip` doc (#32819) @hbjORbj +- ​[Joy] Add `AspectRatio` demos (#32848) @siriwatknp +- ​[Joy] Fix wrong urls (#32883) @siriwatknp + +### Docs + +- ​[docs] Iterate on the job ad for React engineer in Core (#32900) @mnajdova +- ​[blog] Fix avatar image resolution (#32890) @oliviertassinari +- ​[docs] Link the first page of the product (#32943) @oliviertassinari +- ​[docs] Batch small changes (#32170) @michaldudak +- ​[docs] Allow function prop to return undefined (#32766) @m4theushw +- ​[docs] Fix wrong link to Material Icons (#32847) @oliviertassinari +- ​[docs] Fix ClassNameGenerator content (#32800) @siriwatknp +- ​[docs] Fix navigation links (#32851) @oliviertassinari +- ​[docs] Document the `size` prop for InputLabel (#32936) @romelperez +- ​[docs] Add note about transparent background on the outlined Alert variant (#32810) @aaarichter +- ​[website] Update the careers's page with the new roles (#32535) @oliviertassinari + +### Core + +- ​[core] Improve the incomplete issues workflow (#32878) @mnajdova +- ​[core] Add CI check that the PR has label (#32886) @mnajdova +- ​[core] Avoid leaking @babel/runtime (#32874) @oliviertassinari + +All contributors of this release in alphabetical order: @aaarichter, @hbjORbj, @m4theushw, @michaldudak, @mnajdova, @oliviertassinari, @romelperez, @siriwatknp + +## 5.8.1 + + + +_May 23, 2022_ + +A big thanks to the 21 contributors who made this release possible. Here are some highlights ✨: + +- 💅 Added CSS variables support for two more Material UI components by @diggis00 and @alisasanib +- And more 🐛 bug fixes and 📚 documentation improvements. + +### `@mui/material@5.8.1` + +- ​[Alert] Fix missing `ownerState` on the `action` slot (#32801) @mnajdova +- ​[Fab] Make the `color` prop type extendable (#31830) @paales +- ​[ListItemButton] Render as link if href specified (#32403) @o-dubrovskyi +- ​[Paper] Add support for CSS variables (#32570) @diggis00 +- ​[Radio] Add support for CSS variables (#32599) @alisasanib +- ​[Slider] Prevent rendering for marks that are out of the min & max bounds (#32436) @abriginets +- ​[Slider] Slider having marks should be customizable in theme (#32816) @ZeeshanTamboli +- ​[TouchRipple] Allows call imperative methods without event (#31955) @alexfauquette + +### `@mui/system@5.8.1` + +- ​[system] Simplify stylesheet injection logic (#32869) @siriwatknp +- ​[system] Fix color scheme specificity (#32628) @siriwatknp +- ​[system] Fix `borderRadius` errors when used inside `CssVarsProvider` (#32817) @mnajdova +- ​[system] Fix toolbar media query mixin getting merged in wrong order (#32713) @ZeeshanTamboli + +### `@mui/lab@5.0.0-alpha.83` + +- ​[lab] Add missing `peerDependencies` (#32623) @nate-summercook +- ​[pickers] Update @mui/x-date-pickers to be usable with React 18 (#32828) @flaviendelangle + +### `@mui/base@5.0.0-alpha.82` + +- ​[SliderUnstyled] Fix `disabledSwap` not being respected in `onChangeCommitted` (#32647) @JeanPetrov + +### `@mui/joy@5.0.0-alpha.29` + +- ​[Joy] Show Joy pages on master (#32866) @siriwatknp +- ​[Joy] Add an overview page (#32836) @danilo-leal +- ​[Joy] Add doc for the card components (#32825) @siriwatknp +- ​[Joy] Miscellaneous fixes (#32815) @siriwatknp + +### Docs + +- ​[docs] Simplify header DOM structure (#32844) @oliviertassinari +- ​[docs] Fix CodeSandbox & StackBlitz generation (#32726) @siriwatknp +- ​[docs] Fix urls to columns pages in pricing table (#32842) @alexfauquette +- ​[docs] Fix Tailwind CSS integration docs (#32512) @robertwt7 +- ​[docs] Fixed wrong command for the `link-underline-hover` codemod (#32793) @veronikaslc +- ​[docs] Fixed broken link on the icons page (#32780) @SamuelMaddox +- ​[docs] Add "back to top" button (#30441) @VibhorJaiswal +- ​[docs] Fix typo in notifications @mbrookes +- ​[docs] New WAI-ARIA guidelines location (#32865) @oliviertassinari +- ​[docs] Mention the ESLint plugin for detecting unused classes in tss-react (#32666) @garronej +- ​[docs] Update `useAutocomplete` demos to use `Mui-focused` class (#32757) @ZeeshanTamboli +- ​[examples] Fix `NextLinkComposedProps` gives a TypeScript error (#32655) @ZeeshanTamboli +- ​[website] Add Pedro to About Us page (#32803) @apedroferreira + +### Core + +- ​[core] Upgrade MUI X dependency (#32824) @oliviertassinari +- ​[typescript] Allow module augmentation for `Mixins` (#32798) @mnajdova + +All contributors of this release in alphabetical order: @abriginets, @alexfauquette, @alisasanib, @apedroferreira, @danilo-leal, @diggis00, @flaviendelangle, @garronej, @JeanPetrov, @mbrookes, @mnajdova, @nate-summercook, @o-dubrovskyi, @oliviertassinari, @paales, @robertwt7, @SamuelMaddox, @siriwatknp, @veronikaslc, @VibhorJaiswal, @ZeeshanTamboli + +## 5.8.0 + + + +_May 17, 2022_ + +A big thanks to the 14 contributors who made this release possible. Here are some highlights ✨: + +- 🚀 [Blog post](https://mui.com/blog/premium-plan-release/) for announcing the release of the Premium plan of MUI X is out thanks to @joserodolfofreitas. +- Codemod for `jss` to `tss-react` migration is out thanks to @ryancogswell +- And more 🐛 bug fixes and 📚 documentation improvements. + +### `@mui/material@5.8.0` + +- ​[Autocomplete] Fix `getInputProps` TypeScript return type (#32730) @ZeeshanTamboli +- ​[Autocomplete] Forward props to renderTags() (#32637) @emlai +- ​[Badge] Fix TypeScript error when adding style overrides for Badge (#32745) @ZeeshanTamboli +- ​[Menu] Fix context menu open position (#32661) @oliviertassinari + +### `@mui/system@5.8.0` + +- ​[system] Add `Container` component and `createContainer` factory (#32263) @mnajdova + +### `@mui/base@5.0.0-alpha.81` + +- ​[InputUnstyled] Support callbacks in componentsProps (#32271) @michaldudak +- ​[InputUnstyled] Define ownerState and slot props' types (#32491) @michaldudak +- ​[MenuUnstyled] Demos improvements (#32714) @michaldudak +- ​[OptionUnstyled] Define ownerState and slot props' types (#32717) @michaldudak + +### `@mui/joy@5.0.0-alpha.28` + +- ​[Joy] Add Badge doc (#32790) @siriwatknp +- ​[Joy] Add global variant feature page (#32695) @siriwatknp +- ​[Joy] Add avatar page (#32711) @siriwatknp + +### `@mui/codemod@5.8.0` + +- ​[codemod] Add jss to tss-react codemod (#31802) @ryancogswell + +### Docs + +- ​[blog] Add release post for MUI X Premium (#32720) @joserodolfofreitas +- ​[docs] Fix wrong code snippet for overriding styles in theme with a callback value (#32781) @ZeeshanTamboli +- ​[docs] Update Crowdin logo (#32782) @andrii-bodnar +- ​[docs] Improve callouts design (#32709) @danilo-leal +- ​[docs] Revise the "Understanding MUI packages" article (#32382) @danilo-leal +- ​[docs] Fix link to the material icons (#32771) @oliviertassinari +- ​[docs] Add notification for Premium release blog post (#32728) @joserodolfofreitas +- ​[docs] Base Portal style revisions and final review (#32157) @samuelsycamore +- ​[docs] Add joy to docs package.json (#32744) @siriwatknp +- ​[docs] Fix TOC-related styles not being applied when disableAd=true (#32733) @cherniavskii +- ​[docs] Add TypeScript guide on the polymorphic components (#32168) @mnajdova +- ​[docs] Fix warning mode pass to React.Fragment (#32729) @siriwatknp +- ​[docs] Revise Showcase copy for clarity + audit appList (#31946) @samuelsycamore +- ​[examples] Update remix example's tsconfig with required values (#32723) @michaldudak +- ​[examples] Update to use React 18's createRoot (#32506) @mnajdova +- ​[l10n] Fix typos and translations on arSD and arEG locales (#31848) @shadigaafar +- ​[website] Improve communication about MUI X components that are still wip (#32708) @danilo-leal +- ​[website] Remove scrollbar on x-axis (#32291) @MrHBS +- ​[website] Update the pricing page for the MUI X premium plan release (#32458) @joserodolfofreitas +- ​[website] Update sponsors (#32725) @oliviertassinari + +### Core + +- ​[core] Enabled Renovate's lockfile maintenance (#32635) @michaldudak +- ​[core] Extract `MuiPage` interface to separate file (#32715) @cherniavskii +- ​[core] Remove unnecessary `spacing` parameter from `createMixins` method (#32690) @ZeeshanTamboli +- ​[private-classnames] Remove package and move everything to utils (#32758) @mnajdova + +All contributors of this release in alphabetical order: @andrii-bodnar, @cherniavskii, @danilo-leal, @emlai, @joserodolfofreitas, @michaldudak, @mnajdova, @MrHBS, @oliviertassinari, @ryancogswell, @samuelsycamore, @shadigaafar, @siriwatknp, @ZeeshanTamboli + +## 5.7.0 + + + +_May 10, 2022_ + +A big thanks to the 27 contributors who made this release possible. Here are some highlights ✨: + +🛠 This release is all about supporting CSS variables in many Material UI components. +Kudos to all contributors! + +### `@mui/material@5.7.0` + +- [StepLabel, StepIcon] Add support for CSS variables (#32609) @vicasas +- [Table, TableRow] Add support for CSS variables (#32614) @vicasas +- [AppBar] Add a logo component for the responsive app bar demo (#32374) @ameetmadan +- [Autocomplete] Fix clearing single array values (#32626) @mikepricedev +- [Autocomplete] Fix keep listbox open on left/right keys when inputValue is not empty (#31407) @alisasanib +- [Autocomplete] Add support for CSS variables (#32598) @ZeeshanTamboli +- [Autocomplete] Render `endAdornment` only when necessary (#32386) @g1eny0ung +- [ButtonGroup] Add support for CSS variables (#32498) @vicasas +- [CardActionArea] Add support for CSS variables (#32554) @vicasas +- [ClickAwayListener] Allow pointer up/down events to event handler (#32264) @vladjerca +- [CssBaseline] Add support for CSS vars (#32618) @haneenmahd +- [Dialog] Add support for CSS variables (#32555) @vicasas +- [Divider] Add support for CSS variables (#32519) @vicasas +- [Drawer] Add support for CSS variables (#32565) @nghiamvt +- [Fab] Add support for CSS variables (#32564) @alisasanib +- [FormControlLabel] Add support for CSS variables (#32588) @elliefoote +- [FormHelperText] Add support for CSS variables (#32596) @ZeeshanTamboli +- [FormLabel] Add support for CSS variables (#32602) @ZeeshanTamboli +- [Icon] Add support for CSS variables (#32595) @Jamaalwbrown +- [IconButton] Add support for CSS variables (#32590) @Ariyapong +- [ImageListItemBar] Add support for CSS variables (#32578) @vicasas +- [Input] Support CSS variables (#32128) @ivan-ngchakming +- [InputAdornment] Add support CSS variables (#32607) @vicasas +- [Link] Fix style overrides color prop (#32653) @siriwatknp +- [ListItem] Add support for CSS variables (#32580) @dan-mba +- [ListItemButton] Add support for CSS variables (#32582) @dan-mba +- [ListItemIcon] Add support for CSS variables (#32583) @dan-mba +- [ListSubheader] Add support for CSS variables (#32584) @dan-mba +- [MenuItem] Add support for CSS variables (#32561) @nghiamvt +- [MobileStepper] Add support for CSS vars (#32606) @haneenmahd +- [Modal] Add support for CSS variables (#32605) @haneenmahd +- [PaginationItem] Add support for CSS vars (#32612) @haneenmahd +- [Rating] Add support for CSS variables (#32556) @vicasas +- [Snackbar] Add support for CSS variables (#32603) @gin1314 +- [SpeedDial] Add support for CSS variables (#32613) @alisasanib +- [Stepper] Export useStepperContext (#31398) @pzi +- [SvgIcon] Add support for CSS variables (#32610) @vicasas +- [TablePagination] Add support for CSS variables (#32615) @haneenmahd +- [TableSortLabel]: Add support for CSS vars (#32616) @haneenmahd +- [Tabs] Add support for CSS variables (#32547) @ZeeshanTamboli +- [ToggleButton] Add support for CSS variables (#32600) @Ariyapong +- [ToggleButtonGroup] Add support for CSS variables (#32617) @haneenmahd +- [Tooltip] Add support for CSS variables (#32594) @gin1314 + +### `@mui/system@5.7.0` + +- [System] Support CSS variables for iframes & custom nodes (#32496) @siriwatknp + +### `@mui/base@5.0.0-alpha.80` + +- [ButtonUnstyled] Fix keyboard navigation on customized elements (#32204) @michaldudak + +### `@mui/private-classnames@5.7.0` + +- [classnames] Add new package for classnames utils (#32502) @mnajdova + +### Docs + +- [docs] Correct links to prevent 301 redirects (#32692) @michaldudak +- [docs] Move, split, and revise "Unstyled components" page (#32562) @samuelsycamore +- [docs] Nest `ListItemButton` in `ListItem` in the Drawer examples (#31987) @stefanprobst +- [docs] Apply callouts in the Material UI docs (#32567) @danilo-leal +- [docs] Show product identifier on new X pages (#32657) @cherniavskii +- [docs] Fix copy button childNode not found (#32652) @siriwatknp +- [docs] Split install commands in isolated code blocks (#32566) @danilo-leal +- [docs] Base Switch style revisions and final review (#32376) @samuelsycamore +- [docs] Adds Badge link to Base doc nav (#32619) @samuelsycamore +- [docs] Base Installation style revisions and final review (#32483) @samuelsycamore +- [docs] Fix broken redirection (#32581) @oliviertassinari +- [docs] Allows to use `import ''` in demonstrations (#32492) @alexfauquette +- [docs] Hide copy button on search icon dialog (#32577) @siriwatknp +- [docs] Use full API link for ThemeProvider (#32549) @jcvidiri +- [Joy] Add principles page (#32648) @siriwatknp +- [Joy] Add Button page (#32576) @siriwatknp +- [Joy] Add "Quick start" and "Tutorial" pages (#32383) @siriwatknp +- [website] Add store to the footer and "hiring" chip adjustment (#32650) @danilo-leal +- [website] Optimize conversion to store (#32646) @oliviertassinari +- [website] Remove copy button on marketing pages (#32649) @siriwatknp +- [website] Add missing space in copy label (#32638) @flaviendelangle + +### Core + +- [core] Security updates (#32636) @michaldudak +- [core] Fix `docs:dev` not working after upgrading `next` to 12.1.0 (#32552) @cherniavskii +- [core] Update minimist to fix security vulnerability (#32575) @michaldudak + +All contributors of this release in alphabetical order: @alexfauquette, @alisasanib, @ameetmadan, @Ariyapong, @cherniavskii, @dan-mba, @danilo-leal, @elliefoote, @flaviendelangle, @g1eny0ung, @gin1314, @haneenmahd, @ivan-ngchakming, @Jamaalwbrown, @jcvidiri, @michaldudak, @mikepricedev, @mnajdova, @nghiamvt, @oliviertassinari, @pzi, @samuelsycamore, @siriwatknp, @stefanprobst, @vicasas, @vladjerca, @ZeeshanTamboli + +## 5.6.4 + + + +_May 2, 2022_ + +A big thanks to the 13 contributors who made this release possible. Here are some highlights ✨: + +- 💅 5 Material UI components were updated to support CSS variables by @ZeeshanTamboli & @vicasas +- And more 🐛 bug fixes and 📚 improvements. + +### `@mui/material@5.6.4` + +- ​[Accordion] Add support for CSS variables (#32542) @ZeeshanTamboli +- ​[AvatarGroup] Add support for CSS variables (#32507) @vicasas +- ​[Badge] Add support for CSS variables (#32516) @vicasas +- ​[BottomNavigation] Add support for CSS variables (#32517) @vicasas +- ​[CircularProgress] Add support for CSS variables (#32543) @ZeeshanTamboli +- ​[FilledInput] Fix type error from undefined `color` (#32258) @hbjORbj +- ​[l10n] Fix typo in csCZ translation of Pagination component (#32509) @Martin005 +- ​[Tabs] Fix `TabIndicatorProps` prop missing `sx` prop (#32503) @b-novikov-ipersonality + +### `@mui/codemod@5.6.4` + +- ​[codemod] Leave numeric arguments to breakpoints functions unchanged (#32426) @ryancogswell +- ​[codemod] Allow for line breaks within theme.spacing parentheses (#32432) @ryancogswell + +### `@mui/joy@5.0.0-alpha.26` + +- ​[Joy] Miscellaneous fixes (#32541) @siriwatknp +- ​[Joy] Add `extendSxProp` to Link (#32505) @siriwatknp +- ​[Joy] Rename variants (#32489) @siriwatknp +- ​[Joy] Add `extendTheme` (#32450) @siriwatknp + +### Docs + +- ​[docs] SEO fixes (#32515) @oliviertassinari +- ​[docs] Replace `Overriding nested component styles` anchor link with text (#32487) @ZeeshanTamboli +- ​[docs] Update the list of external domains (#32514) @oliviertassinari +- ​[docs] Update Material UI code snippets for React 18 (#32361) @samuelsycamore +- ​[docs] Base TextareaAutosize style revisions and final review (#32481) @samuelsycamore +- ​[docs] Base ClickAwayListener style revisions and final review (#32156) @samuelsycamore +- ​[docs] Base Button style revisions and final review (#32380) @samuelsycamore +- ​[docs] Base NoSsr style revisions and final review (#32254) @samuelsycamore +- ​[docs] Correctly capitalize Ctrl @oliviertassinari +- ​[docs] Fix styling in `Basic Popper` demo on the MUI Base docs (#32488) @ZeeshanTamboli +- ​[docs] Add "Overview" page to Base docs (#32310) @samuelsycamore +- ​[docs] Add copy button to code block (#32390) @siriwatknp +- ​[docs] Base Tabs style revisions and final review (#32423) @samuelsycamore +- ​[docs] Base Popper style revisions and final review (#32412) @samuelsycamore +- ​[docs] Improve sidenav for MUI X (#32435) @oliviertassinari +- ​[docs] Don't redirect on deploy preview (#32399) @m4theushw +- ​[docs] A few SEO fixes (#32431) @oliviertassinari +- ​[docs] Update links to the new Group & Pivot pages (#32410) @flaviendelangle +- ​[docs] Support callouts (#32402) @siriwatknp +- ​[docs] Fix import path in the Snackbar article #32462 @mongolyy +- ​[docs] Fix grammar mistake in shadows.md (#32454) @HexM7 +- ​[docs] Improve unstyled button docs (#32429) @oliviertassinari + +### Core + +- ​[experiment] Add template for testing Material UI components with CSS variables (#32500) @siriwatknp + +All contributors of this release in alphabetical order: @b-novikov-ipersonality, @flaviendelangle, @hbjORbj, @HexM7, @m4theushw, @Martin005, @mongolyy, @oliviertassinari, @ryancogswell, @samuelsycamore, @siriwatknp, @vicasas, @ZeeshanTamboli + +## 5.6.3 + + + +_Apr 25, 2022_ + +A big thanks to the 14 contributors who made this release possible. Here are some highlights ✨: + +- 🛠 Fixed TypeScript issue when the `fill` CSS property is used in the system (#32355) @valerii15298 +- And more 🐛 bug fixes and 📚 improvements. + +### `@mui/material@5.6.3` + +- [BottomNavigation] Action icon `padding` fix (#32030) @abhinav-22-tech +- [Dialog] Fix `component` prop is not available in `DialogTitleProps` (#32389) @hbjORbj +- [StepContent] Fix TypeScript type of `TransitionComponent` prop (#32314) @ZeeshanTamboli + +### `@mui/system@5.6.3` + +- [system] Fix prop types when the `fill` CSS property is used (#32355) @valerii15298 +- [system] Fix broken behavior when theme value is `zero` (#32365) @ZeeshanTamboli + +### `@mui/base@5.0.0-alpha.78` + +- [InputUnstyled] `multiline` property should not log DOM warnings for `maxRows` and `minRows` props (#32401) @ZeeshanTamboli + +### `@mui/joy@5.0.0-alpha.25` + +- [Joy] Improve theme focus to be more flexible (#32405) @siriwatknp +- [Joy] Add `Radio`, `RadioGroup` components (#32279) @siriwatknp +- [Joy] Add `Chip` component (#31983) @hbjORbj +- [Joy] Improve controls (#32267) @siriwatknp +- [Joy] Set up docs (#32370) @siriwatknp + +### Docs + +- [docs] Enable row reordering on the pricing page (#31875) @DanailH +- [blog] A few improvements on date picker change (#32325) @oliviertassinari +- [docs] Emphasize how to avoid failing tests when migrating from v4 to v5 (#32159) @dwjohnston +- [docs] Revise the related projects page (#32180) @danilo-leal +- [docs] Cleanup remaining @mui/styles usages (#32313) @mnajdova +- [docs] Fix sidenav mobile color (#32324) @oliviertassinari +- [docs] Base TrapFocus style revisions and final review (#32364) @samuelsycamore +- [docs] Update the README.md to better cover the different products (#32360) @samuelsycamore +- [docs] Improve the propTypes generation and API demos' links (#32295) @mnajdova +- [docs] Add ability to display a plan icon next to a page link in nav bar (#32393) @flaviendelangle +- [docs] Change label on `FormControlLabelPlacement` (#32322) @ainatenhi +- [website] Update Diamond sponsors list (#32433) @oliviertassinari +- [website] Add privacy policy link to website's footer (#32080) @danilo-leal +- [website] Remove the designer role (#32384) @danilo-leal + +### Core + +- [core] `yarn prettier` write @oliviertassinari +- [core] Fix changelog warning message (#32240) @praveen001 +- [core] Update the proptypes scripts to support components in @mui/system (#32456) @mnajdova + +All contributors of this release in alphabetical order: @abhinav-22-tech, @ainatenhi, @DanailH, @danilo-leal, @dwjohnston, @flaviendelangle, @hbjORbj, @mnajdova, @oliviertassinari, @praveen001, @samuelsycamore, @siriwatknp, @valerii15298, @ZeeshanTamboli + +## 5.6.2 + + + +_Apr 18, 2022_ + +A big thanks to the 11 contributors who made this release possible. This release is mostly about 🐛 bug fixes and 📚 documentation improvements. + +### `@mui/material@5.6.2` + +- ​[Autocomplete] Explain how to use getOptionLabel in free solo mode and update getOptionLabel type (#32165) @michaldudak +- ​[Badge] Fix customization of classes (#32185) @michaldudak +- ​[TextField] Add a workaround for Safari CSS transition scale bug (#32188) @igordanchenko + +### `@mui/system@5.6.2` + +- ​[system] Update style function to use vars automatically if available (#32244) @mnajdova + +### `@mui/base@5.0.0-alpha.77` + +- ​[FormControlUnstyled] Revise API (#32134) @michaldudak + +### `@mui/joy@5.0.0-alpha.24` + +- ​[Joy] Add `Badge` component (#31401) @hbjORbj +- ​[Joy] Fix misuse variable in `Input` (#32268) @siriwatknp + +### Docs + +- ​[blog] Fix images for the docs separation post (#32257) @danilo-leal +- ​[docs] Base Form Control style revisions and final review (#32309) @samuelsycamore +- ​[docs] Base TablePagination style revisions and final review (#32178) @samuelsycamore +- ​[docs] Revise the dark mode article (#32179) @danilo-leal +- ​[docs] Add `aria-label` for `IconButton` (#32276) @SiarheiBobryk +- ​[docs] Fix `borderRadius` in the docs example (#32347) @ZeeshanTamboli +- ​[docs] Fix 404 link in the code (#32323) @oliviertassinari +- ​[docs] Sync h1 with side nav label (#32235) @oliviertassinari +- ​[docs] Fix SEO issues (#32282) @oliviertassinari +- ​[docs] Fix broken link in the test contributing guide (#32283) @sirartemis +- ​[docs] Update "How to customize" page anchor links #32315 @abaker93 +- ​[docs] Mark `onBackdropClick` prop as deprecated in `Dialog`, `Modal` and `ModalUnstyled` components (#32297) @ZeeshanTamboli +- ​[docs] Link to advanced components page (#32290) @siriwatknp +- ​[docs] Sync package description with the docs (#32211) @oliviertassinari +- ​[docs] Revise "Component theming" and "How to customize" guides (#31997) @danilo-leal +- ​[docs] Add note in the Contributing guide about linking issues to a PR (#32174) @danilo-leal +- ​[docs] Update RTL guide (#32242) @michaldudak +- ​[docs] Uniformize capitalization (#32238) @oliviertassinari +- ​[website] Improve new role template @oliviertassinari +- ​[website] Remove a gold sponsor (#32261) @hbjORbj +- ​[website] Mark DataGrid Column spanning done on Pricing page (#32305) @cherniavskii + +### Core + +- ​[core] Remove unecessary div (#32237) @oliviertassinari +- ​[core] Revert #32229 (#32262) @michaldudak +- ​[test] Fix running unit tests on Windows (#32260) @michaldudak + +All contributors of this release in alphabetical order: @abaker93, @cherniavskii, @danilo-leal, @hbjORbj, @igordanchenko, @michaldudak, @mnajdova, @oliviertassinari, @samuelsycamore, @SiarheiBobryk, @sirartemis, @siriwatknp, @ZeeshanTamboli + +## 5.6.1 + + + +_Apr 11, 2022_ + +A big thanks to the 8 contributors who made this release possible. +This release is mostly about 🐛 bug fixes and 📚 documentation improvements. + +### `@mui/material@5.6.1` + +- [Grow] Extend Safari CSS transition bug workaround on WebKit browsers (#32202) @igordanchenko +- [Link] Fix style overrides 5.6.0 regression (#32182) @siriwatknp +- [Select] Bug when the first child is a ListSubheader (#27299) @DouglasPds + +### `@mui/base@5.0.0-alpha.76` + +- [ButtonUnstyled] Allow receiving focus when disabled (#32090) @michaldudak + +### Docs + +- [blog] Share what's changed about the new docs structure (#32044) @danilo-leal +- [docs] Format number icons search (#32239) @oliviertassinari +- [docs] Fix small external links issue (#32212) @oliviertassinari +- [docs] Make sidenav crawlable (#32241) @oliviertassinari +- [docs] Base Badge style revisions and final review (#32098) @samuelsycamore +- [docs] Fix wrong url (#32208) @siriwatknp +- [docs] Fix date-pickers redirects (#32207) @siriwatknp +- [docs] Add notification for the doc restructure and date pickers update (#32195) @siriwatknp +- [docs] Fix 404 from `ahrefs` report (#32206) @siriwatknp +- [docs] Remove notifications temporary (#32192) @siriwatknp +- [docs] Redirect to new urls (#32048) @siriwatknp +- [docs] Update Learn page copy and resource list (#31989) @samuelsycamore +- [website] Fix wrong MUI X installation instruction link @oliviertassinari +- [website] Revise homepage copy below the hero section (#31283) @samuelsycamore +- [website] Revise homepage Hero copy for more clarity (#31212) @samuelsycamore +- [website] Give up on promoting roles in our docs @oliviertassinari + +### Core + +- [core] Fix misleading types range (#32236) @oliviertassinari +- [core] Small polish on the product name (#32199) @oliviertassinari + +All contributors of this release in alphabetical order: @danilo-leal, @DouglasPds, @igordanchenko, @l10nbot, @michaldudak, @oliviertassinari, @samuelsycamore, @siriwatknp + +## 5.6.0 + + + +_Apr 5, 2022_ + +A big thanks to the 15 contributors who made this release possible. Here are some highlights ✨: + +- 🧰 Update peer dependencies to support React 18 (#32063) @eps1lon +- 🚀 Added the experimental `CssVarsProvider` in `@mui/material` for generating theme CSS variables (#31138) @mnajdova +- 📣 Moved date and time pickers from the lab to MUI X (#31984) @flaviendelangle +- Several 🐛 bug fixes and 📚 documentation improvements + +### `@mui/material@5.6.0` + +- ​[CssVarsProvider] Add experimental CssVarsProvider in @mui/material (#31138) @mnajdova +- ​[Link] Fix `sx` color to support callback (#32123) @siriwatknp +- ​[Link] Fix color transformation (#32045) @siriwatknp +- ​[ListItemButton] Specified width so that text would ellide (#32083) @MatthijsMud +- ​[TablePagination] Fixed the etEE locale (#32052) @raigoinabox + +### `@mui/base@5.0.0-alpha.75` + +- ​[Badge] Simplify unstyled API (#31974) @michaldudak + +### `@mui/codemod@5.6.0` + +- ​[codemod] Add v5.0.0/date-pickers-moved-to-x codemod (#31373) @flaviendelangle + +### `@mui/lab@5.0.0-alpha.76` + +- ​[DatePicker] Remove date and time pickers from the lab (#31984) @flaviendelangle + +### `@mui/joy@5.0.0-alpha.22` + +- ​[Joy] Add `Card` components (#32027) @siriwatknp + +### Docs + +- ​[blog] New article for the date pickers migration to X (#31831) @flaviendelangle +- ​[docs] Base Menu style revisions and final review (#32097) @samuelsycamore +- ​[docs] Base Select style revisions and final review (#32095) @samuelsycamore +- ​[docs] Base Input style revisions and final review (#32096) @samuelsycamore +- ​[docs] Base Slider style revisions and final review (#32140) @samuelsycamore +- ​[docs] Base Modal style revisions and final review (#32093) @samuelsycamore +- ​[docs] Add page for CSS variables support in @mui/material (#32050) @mnajdova +- ​[docs] Add TSS support for theme style overrides (#31918) @garronej +- ​[docs] Simplify customization examples in ButtonUnstyled demos (#32092) @michaldudak +- ​[docs] Fix linking issues for the redirects (#32101) @siriwatknp +- ​[docs] Create the FormControl page (#32073) @michaldudak +- ​[docs] Remove trap-focus from the navigation (#32079) @psjishnu +- ​[docs] Add date-pickers product identifier (#32076) @siriwatknp +- ​[docs] Move SwitchUnstyled docs to the Base space (#31964) @michaldudak +- ​[docs] Add docs page for unstyled popper (#31813) @siriwatknp +- ​[docs] Copy TextareaAutosize docs to Base (#32034) @michaldudak +- ​[docs] Add react-hook-form-mui to Complementary projects #32015 @TkaczykAdam +- ​[docs] Improve the translation experience (#32021) @oliviertassinari +- ​[docs] Add small size Select demo (#32060) @ivan-ngchakming +- ​[docs] Correct typos (#32029) @apeltop +- ​[docs] Create SliderUnstyled docs (#31850) @michaldudak +- ​[docs] Create TablePaginationUnstyled docs (#32018) @michaldudak +- ​[docs] Move SelectUnstyled docs to the Base space (#31816) @michaldudak +- ​[docs] Create the TabsUnstyled docs (#32023) @michaldudak +- ​[website] The studio finally has a name, use it (#32105) @oliviertassinari +- ​[website] Disable job ad @oliviertassinari + +### Core + +- ​[core] Update peer deps to support React 18 (#32063) @eps1lon +- ​[core] Fix running docs:api on Windows (#32091) @michaldudak +- ​[core] Fix api build script for MUI Base (#32081) @siriwatknp + +All contributors of this release in alphabetical order: @apeltop, @eps1lon, @flaviendelangle, @garronej, @ivan-ngchakming, @m4theushw, @MatthijsMud, @michaldudak, @mnajdova, @oliviertassinari, @psjishnu, @raigoinabox, @samuelsycamore, @siriwatknp, @TkaczykAdam + +## 5.5.3 + + + +_Mar 28, 2022_ + +A big thanks to the 17 contributors who made this release possible. Here are some highlights ✨: + +- ♿️ improved the a11y on some docs demos +- Several 🐛 bug fixes and 📚 documentation improvements + +### `@mui/material@5.5.3` + +- ​[ButtonBase] Start ripple only after mount (#31950) @m4theushw +- ​[FormControlLabel] Fix label prop type to be in-line with other label prop types (#31139) @jannes-io +- ​[Grow] Add a workaround for Safari 15.4 CSS transition bug (#31975) @igordanchenko + +### `@mui/codemod@5.5.3` + +- ​[codemod] Fix variant prop placement (#31990) @ryancogswell + +### `@mui/utils@5.5.3` + +- ​[utils] Improve type inference of useForkRef (#31845) @eps1lon + +### `@mui/base@5.0.0-alpha.74` + +#### Breaking changes + +- ​[base] Remove `BackdropUnstyled` component (#31923) @mnajdova + + The `BackdropUnstyled` component was removed from the `@mui/base` package, as it did not have any specific logic, except adding an `aria-hidden` attribute on the div it rendered. This is not enough to justify it's existence in the base package. Here is an example alternative component you can use: + + ```tsx + const BackdropUnstyled = React.forwardRef( + (props, ref) => { + const { open, className, ...other } = props; + return
; + }, + ); + ``` + +- ​[TrapFocus] Move docs to Base and drop the Unstyled prefix (#31954) @michaldudak + + Removed the `Unstyled_` prefix from the Base export (it remains in the Material UI export, though). + + ```diff + -import { Unstyled_TrapFocus } from '@mui/base'; + +import { TrapFocus } from '@mui/base'; + + // or + + -import TrapFocus from '@mui/base/Unstyled_TrapFocus'; + +import TrapFocus from '@mui/base/TrapFocus'; + ``` + +#### Changes + +- ​[base] Add @mui/types to dependencies (#31951) @bicstone + +### `@mui/joy@5.0.0-alpha.21` + +- ​[Joy] Add `AvatarGroup` component (#31980) @siriwatknp +- ​[Joy] Miscellaneous fixes (#31873) @siriwatknp +- ​[Joy] Miscellaneous fixes 2 (#31971) @siriwatknp + +### Docs + +- ​[docs] Improve the a11y on the hover rating demo (#31970) @mnajdova +- ​[docs] Improve a11y on the `SplitButton` demo (#31969) @mnajdova +- ​[docs] Improve the color description in the API pages (#30976) @mnajdova +- ​[docs] Add docs page for unstyled Modal (#31417) @mnajdova +- ​[docs] Add InputUnstyled docs (#31881) @mnajdova +- ​[docs] Remove "Work in biotech" from the showcase (#31942) @oliviertassinari +- ​[docs] Fix in-house ad for the design kits (#31965) @oliviertassinari +- ​[docs] Fix the documentation for filterOptions in Autocomplete API page (#31416) @santhoshbala0178 +- ​[docs] Update href for 'TypeScript guide on theme customization' (#31880) @NickFoden +- ​[docs] Fix the CSS modules example in the Interoperability page (#31935) @WilsonNet +- ​[docs] Fix small typo in the `styled()` utility page (#31967) @jason1985 +- ​[docs] Update mui-x on material-ui navigation (#31810) @siriwatknp +- ​[docs] Copy ClickAwayListener docs to Base (#31878) @michaldudak +- ​[docs] Refine the redirects (#31939) @siriwatknp +- ​[docs] Fix TOC layout for large screen (#31953) @siriwatknp +- ​[examples] Update remix example to not use NODE_ENV guard for `LiveReload` (#31269) @eswarclynn +- ​[NoSsr] Copy docs to the Base space (#31956) @michaldudak +- ​[Portal] Copy Portal docs to the Base space (#31959) @michaldudak +- ​[website] Remove X-Frame-Options @oliviertassinari +- ​Revert "[website] Remove X-Frame-Options" @oliviertassinari + +### Core + +- ​[core] Fixes error in changelog generator for item sorting/padding (#30088) @dimitropoulos +- ​[core] Fix typo in issue template @oliviertassinari +- ​[core] Replace deprecated String.prototype.substr() (#31806) @CommanderRoot +- ​[test] Add tests for component using `StandardProps` and polymorphic components (#31945) @mnajdova + +All contributors of this release in alphabetical order: @bicstone, @CommanderRoot, @dimitropoulos, @eps1lon, @eswarclynn, @igordanchenko, @jannes-io, @jason1985, @m4theushw, @michaldudak, @mnajdova, @NickFoden, @oliviertassinari, @ryancogswell, @santhoshbala0178, @siriwatknp, @WilsonNet + ## 5.5.2 @@ -251,7 +1166,7 @@ A big thanks to the 17 contributors who made this release possible. Here are som - ​[core] Update playwright docker to match the specified version (#31236) @siriwatknp - ​[core] Remove parallel on buildTypes (#31189) @siriwatknp - ​[core] Fix propTypes generation for optional any props (#31141) @m4theushw -- ​[Typescript] Remove variants deprecation (#31239) @siriwatknp +- ​[typescript] Remove variants deprecation (#31239) @siriwatknp All contributors of this release in alphabetical order: @adriancampos, @Andarist, @bonellia, @davwheat, @greengiraffe, @hbjORbj, @iclaude3, @m4theushw, @michaldudak, @mnajdova, @oliviertassinari, @PunitSoniME, @RedHeadphone, @robertwt7, @samuelsycamore, @siriwatknp, @sviande @@ -316,7 +1231,7 @@ A big thanks to the 16 contributors who made this release possible. Here are som - [Select] Allow customizing Select based on its variant (#30788) @michaldudak - [Portal] Re-export 'Portal' in material (#31003) @liradb2000 - [ToggleButton] Add prop types for `onClick` and `onChange` (#30883) @sydneyjodon-wk -- [Typescript] Added TypeText declaration to the exports file (#30890) @agauravdev +- [typescript] Added TypeText declaration to the exports file (#30890) @agauravdev ### `@mui/system@5.4.2` @@ -350,7 +1265,7 @@ A big thanks to the 16 contributors who made this release possible. Here are som - [docs] Fix force redirection to a different locale (#30967) @oliviertassinari - [docs] Add live Tailwind CSS demo (#30966) @oliviertassinari - [website] Add banner for promoting priority open roles (#31076) @danilo-leal -- [website] Open Full-stack Engineer role for studio (#31038) @newguy-123 +- [website] Open Full-stack Engineer role for studio (#31038) @prakhargupta1 - [website] Minor security improvements (#31062) @oliviertassinari - [website] Improve title of open roles (#30963) @DanailH - [website] Add BIMI avatar (#30444) @oliviertassinari @@ -365,7 +1280,7 @@ A big thanks to the 16 contributors who made this release possible. Here are som - [test] Test if certain Base members are exported from Material UI (#31067) @michaldudak - [core] Remove dead code (#31064) @oliviertassinari -All contributors of this release in alphabetical order: @agauravdev, @alisasanib, @DanailH, @danilo-leal, @huyenltnguyen, @l10nbot, @liradb2000, @mbrookes, @michaldudak, @mnajdova, @newguy-123, @oliviertassinari, @ryohey, @samuelsycamore, @siriwatknp, @sydneyjodon-wk +All contributors of this release in alphabetical order: @agauravdev, @alisasanib, @DanailH, @danilo-leal, @huyenltnguyen, @l10nbot, @liradb2000, @mbrookes, @michaldudak, @mnajdova, @prakhargupta1, @oliviertassinari, @ryohey, @samuelsycamore, @siriwatknp, @sydneyjodon-wk ## 5.4.1 @@ -777,7 +1692,7 @@ A big thanks to the 14 contributors who made this release possible. Here are som ### Core -- ​[core] Rename Material-UI to MUI (#30338) @ZeeshanTamboli +- ​[core] Rename Material UI to MUI (#30338) @ZeeshanTamboli - ​[core] Fix warning in dev mode (#30368) @oliviertassinari - ​[core] Update `buildApi` script to support new structure (#30245) @siriwatknp @@ -1075,14 +1990,14 @@ This is an early release to fix `export 'useId' (imported as 'React') was not fo - ​[core] Fix PR run detection in test_bundle_size_monitor (#29879) @eps1lon - ​[core] Move bundle size monitoring to CircleCI (#29876) @eps1lon - ​[docs] Add keys to Responsive AppBar demo (#29884) @mbrookes -- ​[docs] MUI's 2021 Developer survey (#29765) @newguy-123 +- ​[docs] MUI's 2021 Developer survey (#29765) @prakhargupta1 - ​[docs] Smoother image loading UX (#29858) @oliviertassinari - ​[Select] Fix select display value with React Nodes (#29836) @kegi - ​[system] Add `experimental_sx` utility (#29833) @mnajdova - ​[test] Ignore "detected multiple renderers" warning for now (#29854) @eps1lon - ​[useMediaQuery][utils] Remove usage of React 18 APIs (#29870) @eps1lon -All contributors of this release in alphabetical order: @eps1lon, @karakib2k18, @kegi, @mbrookes, @mnajdova, @newguy-123, @oliviertassinari +All contributors of this release in alphabetical order: @eps1lon, @karakib2k18, @kegi, @mbrookes, @mnajdova, @prakhargupta1, @oliviertassinari ## 5.2.0 @@ -1230,7 +2145,7 @@ A big thanks to the 15 contributors who made this release possible. Here are som - ​[core] Add `experiments` index page (#29582) @siriwatknp - ​[core] Move s3 bucket ownership to mui-org (#29609) @eps1lon - ​[core] Improve support request message (#29614) @mnajdova -- ​[core] Use support request Github Action (#29594) @mnajdova +- ​[core] Use support request GitHub Action (#29594) @mnajdova - ​[core] Remove unused `getJsxPreview` util (#29586) @ZeeshanTamboli - ​[core] Use GitHub issue forms (#28038) @oliviertassinari - ​[core] Add playground (#29423) @oliviertassinari @@ -1776,7 +2691,7 @@ These are the changes done from the last release candidate version (5.0.0-rc.1): - ​[blog] Introducing MUI Core v5.0 (#27912) @oliviertassinari - ​[docs] Fix quotes in font-face literal (#28260) @Aurelain - ​[docs] Update redirects to X's docs (#28263) @m4theushw -- ​[docs] Change Material-UI to MUI in the console (#28270) @mbrookes +- ​[docs] Change Material UI to MUI in the console (#28270) @mbrookes - ​[docs] Docs redesign adjustments (#28203) @mnajdova - ​[docs] How to compose theme in steps (#28246) @goncalovf - ​[docs] Fix DataGrid demo console warning in Table docs (#28235) @ZeeshanTamboli @@ -1797,7 +2712,7 @@ These are the changes done from the last release candidate version (5.0.0-rc.1): ### Core -- ​[core] Replace Material-UI with MUI (#28243) @mnajdova +- ​[core] Replace Material UI with MUI (#28243) @mnajdova - ​[core] Prepare for v5 stable release (#28240) @mnajdova - ​[core] Mark lines that needs to be changed with a major release (#28238) @mnajdova - ​[core] Various updates to what we consider the default branch (#28328) @eps1lon @@ -1858,7 +2773,7 @@ A big thanks to the 13 contributors who made this release possible. Here are som - ​[docs] Improve docs for creating dark theme (#28104) @mnajdova - ​[docs] Don't use Material theme in unstyled demos (#28073) @michaldudak - ​[docs] Fix api doc import example (#28199) @siriwatknp -- ​[docs] Remove demo for re-creating Material-UI switches (#28042) @eps1lon +- ​[docs] Remove demo for re-creating Material UI switches (#28042) @eps1lon - ​[docs] Improve legibility of CTA on landing page (#28124) @akashshyamdev - ​[docs] Fix Link outdated default underline prop (#28134) @outofgamut - ​[docs] Fix branding theme leaking on the templates (#28120) @mnajdova @@ -1900,7 +2815,7 @@ _Sep 1, 2021_ A big thanks to the 18 contributors who made this release possible. Here are some highlights ✨: - 🎉 Renamed packages to `@mui/*` as part of rebranding the company, following the strategy of expanding the library scope beyond Material Design. For more details about it, check the [GitHub discussion](https://github.com/mui/material-ui/discussions/27803). -- 🛠 Added `mui-replace` codemod for migrating `@material-ui/*` to new packages `@mui/*`. Check out this [codemod detail](https://github.com/mui/material-ui/blob/next/packages/mui-codemod/README.md#mui-replace) or head to [migration guide](https://mui.com/guides/migration-v4/#preset-safe) +- 🛠 Added `mui-replace` codemod for migrating `@material-ui/*` to new packages `@mui/*`. Check out this [codemod detail](https://github.com/mui/material-ui/blob/next/packages/mui-codemod/README.md#mui-replace) or head to [migration guide](https://mui.com/material-ui/migration/migration-v4/#preset-safe) - 🧪 Added new `` component to the lab, [check it out](https://mui.com/components/masonry/). It has been crafted by our first intern, @hbjORbj 👏! ### `@mui/material@5.0.0-rc.0` @@ -2346,7 +3261,7 @@ A big thanks to the 20 contributors who made this release possible. Here are som ### Docs - ​[docs] Display Popper arrow correctly (#27339) @Patil2099 -- ​[docs] Focus pickers introduction on Material-UI (#27394) @eps1lon +- ​[docs] Focus pickers introduction on Material UI (#27394) @eps1lon - ​[docs] Fix wrong import path in @material-ui/styles section (#27427) @WeldonTan - ​[docs] Update color imports (#27321) @siriwatknp - ​[docs] Sync params of callbacks between types and JSDoc description (#27366) @eps1lon @@ -2398,7 +3313,7 @@ A big thanks to the 17 contributors who made this release possible. Here are som You can follow our progress at https://github.com/mui/material-ui/issues/27170. - 💄 We have updated the default `info` `success` `warning` color to be more accessible (#26817) @siriwatknp. - You can find the new [default values](https://mui.com/customization/palette/#default-values) in the documentation. + You can find the new [default values](https://mui.com/material-ui/customization/palette/#default-values) in the documentation. colors @@ -2489,7 +3404,7 @@ A big thanks to the 17 contributors who made this release possible. Here are som - [test] Update tests with latest state of StrictMode compatibility (#27042) @eps1lon - [test] Use DOM events instead of mocked, partial events (#27198) @eps1lon - [website] Open 4 new roles (#27123) @oliviertassinari -- [blog] Danilo Leal joins Material-UI (#27231) @oliviertassinari +- [blog] Danilo Leal joins Material UI (#27231) @oliviertassinari All contributors of this release in alphabetical order: @eps1lon, @mbrookes, @michal-perlakowski, @michaldudak, @mnajdova, @moshfeu, @oliviertassinari, @rajzik, @renovate[bot], @sahil-blulabs, @ShirasawaSama, @siriwatknp, @vimutti77 @@ -2926,7 +3841,7 @@ A big thanks to the 11 contributors who made this release possible. Here are som ### Docs -- ​[blog] Michał Dudak joins Material-UI (#26700) @oliviertassinari +- ​[blog] Michał Dudak joins Material UI (#26700) @oliviertassinari - ​[docs] Migrate onepirate premium template to emotion part2 (#26707) @vicasas - ​[docs] Fix TextField demo layout (#26710) @vicasas - ​[docs] Improve Paperbase demo (#26711) @oliviertassinari @@ -3213,7 +4128,7 @@ We are progressively moving all modules that are relevant to styling custom desi - [test] Move ClockPicker tests to ClockPicker.test (#26407) @eps1lon - [test] setProps from createPickerRender should set props on the rendered element (#26405) @eps1lon - [utils] Convert useId to TypeScript (#26491) @eps1lon -- [website] Add Material-UI X page (#25794) @DanailH +- [website] Add Material UI X page (#25794) @DanailH - [website] Add open application section (#26501) @oliviertassinari - [website] Add Siriwat to team page (#26406) @siriwatknp @@ -3305,7 +4220,7 @@ A big thanks to the 16 contributors who made this release possible. Here are som /> ``` -> Follow [this link](https://mui.com/guides/migration-v4/#main-content) for full migration from v4 => v5 +> Follow [this link](https://mui.com/material-ui/migration/migration-v4/) for full migration from v4 => v5 #### Changes @@ -3358,7 +4273,7 @@ A big thanks to the 16 contributors who made this release possible. Here are som - ​[docs] Fix broken overrides link on API pages (#26244) @mnajdova - ​[docs] Improve documentation for Buttons (#26184) @arpitBhalla - ​[docs] Emphasize on props for screen readers (#26222) @atisheyJain03 -- ​[docs] Link third-party routing in Bottom Navigation (#26190) @arpitBhalla +- ​[docs] Link third-party routing in Bottom navigation (#26190) @arpitBhalla - ​[docs] Migrate Select, Progress demos to emotion (#26178) @mnajdova - ​[docs] Add accessibility section to Badges (#26009) @likitarai1 - ​[docs] Migrate Popper, Drawer demos to emotion (#26183) @mnajdova @@ -3468,7 +4383,7 @@ A big thanks to the 17 contributors who made this release possible. Here are som - ​[Box] Remove render prop (#26113) @m4theushw - Its behavior can be obtained using the `sx` prop directly on the child if it's a Material-UI component. For non-Material-UI components use the `sx` prop in conjunction with the `component` prop: + Its behavior can be obtained using the `sx` prop directly on the child if it's a Material UI component. For non-Material UI components use the `sx` prop in conjunction with the `component` prop: ```diff - @@ -3754,8 +4669,8 @@ A big thanks to the 15 contributors who made this release possible. Here are som - ​[Button] Rename `pending` prop to `loading` in LoadingButton (#25874) @m4theushw ```diff - - - + + - + + ``` - ​[ButtonBase] Remove buttonRef prop (#25896) @m4theushw @@ -4084,7 +4999,7 @@ A big thanks to the 21 contributors who made this release possible. Here are som - ​[docs] Add interoperability section for Portal (#25575) @mnajdova - ​[docs] Fix side nav scroll position (#25619) @misaka3 - ​[website] Q1 2021 Update (#25591) @oliviertassinari -- ​[website] Matheus Wichman joins Material-UI (#25590) @oliviertassinari +- ​[website] Matheus Wichman joins Material UI (#25590) @oliviertassinari ### Core @@ -4370,7 +5285,7 @@ The prop didn't solve any important problem better than any of its alternatives ### Docs -- ​[docs] Migrate Bottom Navigation demos to emotion (#25180) @vicasas +- ​[docs] Migrate Bottom navigation demos to emotion (#25180) @vicasas - ​[docs] Migrate Button demos to emotion (#25138) @vicasas - ​[docs] Migrate Divider demos to emotion (#25145) @vicasas - ​[docs] Migrate Pagination demos to emotion (#25183) @vicasas @@ -4605,7 +5520,7 @@ A big thanks to the 30 contributors who made this release possible. Here are som - Increase the minimum version of TypeScript supported from v3.2 to v3.5. (#24795) @petyosi We try to align with types released from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) (i.e. packages published on npm under the `@types` namespace). - We will not change the minimum supported version in a major version of Material-UI. + We will not change the minimum supported version in a major version of Material UI. However, we generally recommend to not use a TypeScript version older than the [lowest supported version of DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped#older-versions-of-typescript-33-and-earlier). #### Changes @@ -5285,7 +6200,7 @@ A big thanks to the 24 contributors who made this release possible. Here are som - [docs] Fix duplicated styles generated from emotion (#23809) @mnajdova - [docs] Fix icon alignment in /components/breadcrumbs (#23818) @eps1lon - [docs] Fix production deploy (#23963) @eps1lon -- [docs] Fix source on Github links (#23821) @praveenkumar-kalidass +- [docs] Fix source on GitHub links (#23821) @praveenkumar-kalidass - [docs] Fix StickyHeaderTable round borders (#23882) @antoniopacheco - [docs] Fix typo in date picker dayjs adapter name (#23935) @andresmrm - [docs] Improve system properties page (#23961) @mnajdova @@ -5333,8 +6248,8 @@ A big thanks to the 17 contributors who made this release possible. Here are som Thanks to @mbrookes developers can automate the migration with a [codemod](https://github.com/mui/material-ui/blob/next/packages/mui-codemod/README.md#box-sx-prop). ```diff - - - + + - + + ``` #### Changes @@ -5445,7 +6360,7 @@ A big thanks to the 18 contributors who made this release possible. Here are som ); ``` - This enforces emotion being injected first. [More details](https://mui.com/guides/interoperability/#css-injection-order) in the documentation. + This enforces emotion being injected first. [More details](https://mui.com/material-ui/guides/interoperability/#css-injection-order) in the documentation. - [Autocomplete] Rename `closeIcon` prop with `clearIcon` to avoid confusion (#23617) @akhilmhdh. @@ -5657,7 +6572,7 @@ A big thanks to the 34 contributors who made this release possible. Here are som - [docs] Improve formatting of the system (#23509) @oliviertassinari - [docs] Improve migration guide for theme.palette (#23416) @hubgit - [docs] Mention delay instead of transition twice (#23393) @benmneb -- [docs] Prepare Material-UI X (#1893) @oliviertassinari +- [docs] Prepare Material UI X (#1893) @oliviertassinari - [docs] Redirect legacy GridList pages to ImageList (#23456) @eps1lon - [docs] Remove redundant aria-label when wrapped in Tooltip (#23455) @eps1lon - [docs] Sync translations (#23316) @l10nbot @@ -5685,19 +6600,19 @@ _Nov 4, 2020_ A big thanks to the 20 contributors who made this release possible. Here are some highlights ✨: - ⚛️ Add support for React 17 (#23311) @eps1lon. - React 17 release is unusual because it doesn't add any new developer-facing features. It was released a couple of days ago. You can learn more about it in the [introduction post](https://reactjs.org/blog/2020/10/20/react-v17.html). Material-UI now supports `^16.8.0 || ^17.0.0`. + React 17 release is unusual because it doesn't add any new developer-facing features. It was released a couple of days ago. You can learn more about it in the [introduction post](https://reactjs.org/blog/2020/10/20/react-v17.html). Material UI now supports `^16.8.0 || ^17.0.0`. - 🛠 Introduce a new `@material-ui/unstyled` package (#23270) @mnajdova. This package will host the unstyled version of the components. In this first iteration, only the Slider is available. You can find it documented under the [same page](https://mui.com/components/slider-styled/#unstyled-slider) as the styled version. **Why an unstyled package?** - While engineering teams are successfully building custom design systems by wrapping Material-UI, we [occasionally hear](https://github.com/mui/material-ui/issues/6218) that Material Design or our styling solution are something they don't need. Some teams prefer SASS, others prefer to customize the components starting from a pristine state. What all these teams have in common is that they value the features coming from the components, such as accessibility. + While engineering teams are successfully building custom design systems by wrapping Material UI, we [occasionally hear](https://github.com/mui/material-ui/issues/6218) that Material Design or our styling solution are something they don't need. Some teams prefer SASS, others prefer to customize the components starting from a pristine state. What all these teams have in common is that they value the features coming from the components, such as accessibility. The unstyled package goes one step down in the abstraction layer, providing more flexibility. Angular Material introduced this approach two years ago. Today their unstyled components account for [25% of the usage](https://npm-stat.com/charts.html?package=%40angular%2Fmaterial&package=%40angular%2Fcdk&from=2017-11-03&to=2020-11-03). Another reason for introducing this package is to prepare the groundwork for a [second theme](https://github.com/mui/material-ui/issues/22485) (not Material Design based). - A note on the terminology: "unstyled" means that the components have the same API as the "styled" components but come without CSS. Material-UI also contains "headless" components that exposes a hook API, e.g. [useAutocomplete](https://mui.com/components/autocomplete/#useautocomplete) or [usePagination](https://mui.com/components/pagination/#usepagination). + A note on the terminology: "unstyled" means that the components have the same API as the "styled" components but come without CSS. Material UI also contains "headless" components that exposes a hook API, e.g. [useAutocomplete](https://mui.com/components/autocomplete/#useautocomplete) or [usePagination](https://mui.com/components/pagination/#usepagination). This change is part of our strategy to iterate on the v5 architecture with the `Slider` first. In the next alpha release, we plan to replace the v4 slider with the v5 slider. Once the new approach is stress-tested and validated, we will roll it out to all the components. @@ -5761,8 +6676,8 @@ A big thanks to the 20 contributors who made this release possible. Here are som ### Docs - [Transition] Document default appear value (#23221) @GuilleDF -- [blog] Danail Hadjiatanasov joins Material-UI (#23223) @oliviertassinari -- [docs] Add Material-UI Builder to in-house ads (#23342) @mbrookes +- [blog] Danail Hadjiatanasov joins Material UI (#23223) @oliviertassinari +- [docs] Add Material UI Builder to in-house ads (#23342) @mbrookes - [docs] Fix a few typos and add comma (#23284) @reedanders - [docs] Fix few propTypes in Inputs (#23331) @youknowhat - [docs] Fix language cookie (#23324) @mbrookes @@ -5798,7 +6713,7 @@ A big thanks to the 23 contributors who made this release possible. Here are some highlights ✨: - 💄 Introduce a new `sx` prop (#23053, #23205) @mnajdova - We have resumed the work on Material-UI System. This is made possible by the latest progress on the new styling solution of v5. + We have resumed the work on Material UI System. This is made possible by the latest progress on the new styling solution of v5. You can read the [introduction blog post](https://medium.com/material-ui/introducing-material-ui-design-system-93e921beb8df) that we did for the system two years ago. The system is meant to solve the following problems: @@ -5971,7 +6886,7 @@ A big thanks to the 25 contributors who made this release possible. Here are some highlights ✨: - 📦 Ship modern bundle (#22814) @eps1lon. - This is a significant update to the [browsers supported](https://mui.com/getting-started/supported-platforms/) by Material-UI. + This is a significant update to the [browsers supported](https://mui.com/material-ui/getting-started/supported-platforms/) by Material UI. The previous policy was defined 2 years ago, and the landscape has evolved since then. The package now includes 4 bundles: 1. `stable` (default, formerly `esm`) which targets a snapshot (on release) of `> 0.5%, last 2 versions, Firefox ESR, not dead, not IE 11"` @@ -5982,7 +6897,7 @@ Here are some highlights ✨: The change yields a 6% reduction in bundle size 📦 (Babel only). In the coming weeks, we will refactor the internals to take advantage of the new browser capabilities that dropping these older platforms allows. For instance, we might be able to remove the span we render inside the ` - ); + return ; } - -ReactDOM.render(, document.querySelector('#app')); ``` -Yes, it's really all you need to get started as you can see in this live and interactive demo: +In the interactive demo below, try changing the code and see how it affects the output. +(Hint: change `variant` to `"outlined"` and `color` to `"secondary"`. +For more options, see the [`Button` component page](https://mui.com/material-ui/react-button/) in our docs.) [![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/4j7m47vlm4) ## Questions -For _how-to_ questions and other non-issues, -please use [StackOverflow](https://stackoverflow.com/questions/tagged/mui) instead of GitHub issues. -There is a StackOverflow tag called "material-ui" that you can use to tag your questions. +For how-to questions that don't involve making changes to the code base, please use [Stack Overflow](https://stackoverflow.com/questions/tagged/mui) instead of GitHub issues. +Use the "mui" tag on Stack Overflow to make it easier for the community to find your question. ## Examples -Are you looking for an example project to get started? -[We host some](https://mui.com/getting-started/example-projects/). +Our documentation features [a collection of example projects using Material UI](https://mui.com/material-ui/getting-started/example-projects/). ## Documentation -Check out our [documentation website](https://mui.com/). +- [Material UI](https://mui.com/material-ui/getting-started/installation/) +- [MUI Base](https://mui.com/base/getting-started/installation/) +- [MUI System](https://mui.com/system/basics/) -## Premium Themes +## Premium themes -You can find complete templates & themes in the [MUI Store](https://mui.com/store/?utm_source=docs&utm_medium=referral&utm_campaign=readme-store). +You can find complete templates and themes in the [MUI Store](https://mui.com/store/?utm_source=docs&utm_medium=referral&utm_campaign=readme-store). ## Contributing -Read the [contributing guide](/CONTRIBUTING.md) to learn about our development process, how to propose bugfixes and improvements, and how to build and test your changes to MUI. +Read the [contributing guide](/CONTRIBUTING.md) to learn about our development process, how to propose bug fixes and improvements, and how to build and test your changes. -Notice that contributions go far beyond pull requests and commits. -Although we love giving you the opportunity to put your stamp on MUI, we also are thrilled to receive a variety of [other contributions](https://mui.com/getting-started/faq/#mui-is-awesome-how-can-i-support-the-project). +Contributing to MUI Core is about more than just issues and pull requests! +There are many other ways to [support MUI](https://mui.com/material-ui/getting-started/faq/#mui-is-awesome-how-can-i-support-the-project) beyond contributing to the code base. ## Changelog -If you have recently updated, please read the [changelog](https://github.com/mui/material-ui/releases) for details of what has changed. +The [changelog](https://github.com/mui/material-ui/releases) is regularly updated to reflect what's changed in each new release. ## Roadmap -The future plans and high priority features and enhancements can be found in the [roadmap](https://mui.com/discover-more/roadmap/) file. +Future plans and high-priority features and enhancements can be found in our [roadmap](https://mui.com/material-ui/discover-more/roadmap/). ## License This project is licensed under the terms of the [MIT license](/LICENSE). +## Security + +For details of supported versions and contact details for reporting security issues, please refer to the [security policy](https://github.com/mui/material-ui/blob/master/SECURITY.md). + ## Sponsoring services These great services sponsor MUI's core infrastructure: [GitHub](https://github.com/) -GitHub allows us to host the Git repository and coordinate contributions. +GitHub lets us host the Git repository and coordinate contributions. [Netlify](https://www.netlify.com/) -Netlify allows us to distribute the documentation. +Netlify lets us distribute the documentation. -[CrowdIn](https://crowdin.com/) +[Crowdin](https://crowdin.com/) -CrowdIn allows us to translate the documentation. +Crowdin lets us translate the documentation. [BrowserStack](https://www.browserstack.com/) -BrowserStack allows us to test in real browsers. +BrowserStack lets us test in real browsers. [CodeCov](https://codecov.io/) -CodeCov allows us to monitor the test coverage. +CodeCov lets us monitor test coverage. diff --git a/benchmark/package.json b/benchmark/package.json index 4136463fd90952..8525bb18a36b31 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -11,13 +11,13 @@ "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": "^1.11.2", - "@emotion/react": "^11.8.2", + "@chakra-ui/system": "^2.1.3", + "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", - "@mdx-js/react": "^2.0.0", - "@mui/material": "^5.5.2", - "@mui/styles": "^5.5.1", - "@mui/system": "^5.5.2", + "@mdx-js/react": "^2.1.1", + "@mui/material": "^5.8.5", + "@mui/styles": "^5.8.4", + "@mui/system": "^5.8.5", "@styled-system/css": "^5.1.5", "benchmark": "^2.1.4", "playwright": "^1.17.1", @@ -25,12 +25,12 @@ "react-dom": "^17.0.2", "react-is": "^17.0.2", "react-jss": "^10.9.0", - "react-redux": "^7.2.6", - "redux": "^4.1.2", + "react-redux": "^7.2.8", + "redux": "^4.2.0", "serve-handler": "^6.1.3", - "styled-components": "^5.3.3", - "theme-ui": "^0.13.1", - "webpack": "^5.70.0", + "styled-components": "^5.3.5", + "theme-ui": "^0.14.5", + "webpack": "^5.73.0", "webpack-cli": "^4.9.2" } } diff --git a/docs/data/base/components/badge/AccessibleBadges.js b/docs/data/base/components/badge/AccessibleBadges.js index 1d895eb585d8e6..622b7e1b5f5f1c 100644 --- a/docs/data/base/components/badge/AccessibleBadges.js +++ b/docs/data/base/components/badge/AccessibleBadges.js @@ -1,13 +1,12 @@ import * as React from 'react'; import { styled } from '@mui/system'; -import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +import BadgeUnstyled, { badgeUnstyledClasses } from '@mui/base/BadgeUnstyled'; import MailIcon from '@mui/icons-material/Mail'; const StyledBadge = styled(BadgeUnstyled)` box-sizing: border-box; margin: 0; padding: 0; - color: rgba(0, 0, 0, 0.85); font-size: 14px; list-style: none; font-family: IBM Plex Sans, sans-serif; @@ -15,7 +14,7 @@ const StyledBadge = styled(BadgeUnstyled)` display: inline-block; line-height: 1; - & .MuiBadge-badge { + & .${badgeUnstyledClasses.badge} { z-index: auto; min-width: 20px; height: 20px; diff --git a/docs/data/base/components/badge/AccessibleBadges.tsx b/docs/data/base/components/badge/AccessibleBadges.tsx index e5754f2761c08b..95d658571b8d8c 100644 --- a/docs/data/base/components/badge/AccessibleBadges.tsx +++ b/docs/data/base/components/badge/AccessibleBadges.tsx @@ -1,13 +1,12 @@ import * as React from 'react'; import { styled } from '@mui/system'; -import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +import BadgeUnstyled, { badgeUnstyledClasses } from '@mui/base/BadgeUnstyled'; import MailIcon from '@mui/icons-material/Mail'; const StyledBadge = styled(BadgeUnstyled)` box-sizing: border-box; margin: 0; padding: 0; - color: rgba(0, 0, 0, 0.85); font-size: 14px; list-style: none; font-family: IBM Plex Sans, sans-serif; @@ -15,7 +14,7 @@ const StyledBadge = styled(BadgeUnstyled)` display: inline-block; line-height: 1; - & .MuiBadge-badge { + & .${badgeUnstyledClasses.badge} { z-index: auto; min-width: 20px; height: 20px; diff --git a/docs/data/base/components/badge/BadgeMax.js b/docs/data/base/components/badge/BadgeMax.js index 4ab282f10a8bd7..9fc1c31b1e1d15 100644 --- a/docs/data/base/components/badge/BadgeMax.js +++ b/docs/data/base/components/badge/BadgeMax.js @@ -1,14 +1,13 @@ import * as React from 'react'; import Stack from '@mui/material/Stack'; import { styled } from '@mui/system'; -import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +import BadgeUnstyled, { badgeUnstyledClasses } from '@mui/base/BadgeUnstyled'; import MailIcon from '@mui/icons-material/Mail'; const StyledBadge = styled(BadgeUnstyled)` box-sizing: border-box; margin: 0; padding: 0; - color: rgba(0, 0, 0, 0.85); font-size: 14px; list-style: none; font-family: IBM Plex Sans, sans-serif; @@ -16,7 +15,7 @@ const StyledBadge = styled(BadgeUnstyled)` display: inline-block; line-height: 1; - & .MuiBadge-badge { + & .${badgeUnstyledClasses.badge} { z-index: auto; min-width: 20px; height: 20px; diff --git a/docs/data/base/components/badge/BadgeMax.tsx b/docs/data/base/components/badge/BadgeMax.tsx index 4ab282f10a8bd7..9fc1c31b1e1d15 100644 --- a/docs/data/base/components/badge/BadgeMax.tsx +++ b/docs/data/base/components/badge/BadgeMax.tsx @@ -1,14 +1,13 @@ import * as React from 'react'; import Stack from '@mui/material/Stack'; import { styled } from '@mui/system'; -import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +import BadgeUnstyled, { badgeUnstyledClasses } from '@mui/base/BadgeUnstyled'; import MailIcon from '@mui/icons-material/Mail'; const StyledBadge = styled(BadgeUnstyled)` box-sizing: border-box; margin: 0; padding: 0; - color: rgba(0, 0, 0, 0.85); font-size: 14px; list-style: none; font-family: IBM Plex Sans, sans-serif; @@ -16,7 +15,7 @@ const StyledBadge = styled(BadgeUnstyled)` display: inline-block; line-height: 1; - & .MuiBadge-badge { + & .${badgeUnstyledClasses.badge} { z-index: auto; min-width: 20px; height: 20px; diff --git a/docs/data/base/components/badge/BadgeVisibility.js b/docs/data/base/components/badge/BadgeVisibility.js index 9591dc07aed366..2f9215514544a7 100644 --- a/docs/data/base/components/badge/BadgeVisibility.js +++ b/docs/data/base/components/badge/BadgeVisibility.js @@ -1,7 +1,7 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { styled } from '@mui/system'; -import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +import BadgeUnstyled, { badgeUnstyledClasses } from '@mui/base/BadgeUnstyled'; import ButtonGroup from '@mui/material/ButtonGroup'; import Button from '@mui/material/Button'; import AddIcon from '@mui/icons-material/Add'; @@ -14,7 +14,6 @@ const StyledBadge = styled(BadgeUnstyled)` box-sizing: border-box; margin: 0; padding: 0; - color: rgba(0, 0, 0, 0.85); font-size: 14px; list-style: none; font-family: IBM Plex Sans, sans-serif; @@ -22,7 +21,7 @@ const StyledBadge = styled(BadgeUnstyled)` display: inline-block; line-height: 1; - & .MuiBadge-badge { + & .${badgeUnstyledClasses.badge} { z-index: auto; min-width: 20px; height: 20px; @@ -45,7 +44,7 @@ const StyledBadge = styled(BadgeUnstyled)` transition: opacity 0.2s ease-in-out; } - & .MuiBadge-invisible { + & .${badgeUnstyledClasses.invisible} { opacity: 0; pointer-events: none; } @@ -68,7 +67,7 @@ export default function BadgeVisibility() { '& > *': { marginBottom: 2, }, - '& .MuiBadge-root': { + [`& .${badgeUnstyledClasses.root}`]: { marginRight: 4, }, }} diff --git a/docs/data/base/components/badge/BadgeVisibility.tsx b/docs/data/base/components/badge/BadgeVisibility.tsx index 9591dc07aed366..2f9215514544a7 100644 --- a/docs/data/base/components/badge/BadgeVisibility.tsx +++ b/docs/data/base/components/badge/BadgeVisibility.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { styled } from '@mui/system'; -import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +import BadgeUnstyled, { badgeUnstyledClasses } from '@mui/base/BadgeUnstyled'; import ButtonGroup from '@mui/material/ButtonGroup'; import Button from '@mui/material/Button'; import AddIcon from '@mui/icons-material/Add'; @@ -14,7 +14,6 @@ const StyledBadge = styled(BadgeUnstyled)` box-sizing: border-box; margin: 0; padding: 0; - color: rgba(0, 0, 0, 0.85); font-size: 14px; list-style: none; font-family: IBM Plex Sans, sans-serif; @@ -22,7 +21,7 @@ const StyledBadge = styled(BadgeUnstyled)` display: inline-block; line-height: 1; - & .MuiBadge-badge { + & .${badgeUnstyledClasses.badge} { z-index: auto; min-width: 20px; height: 20px; @@ -45,7 +44,7 @@ const StyledBadge = styled(BadgeUnstyled)` transition: opacity 0.2s ease-in-out; } - & .MuiBadge-invisible { + & .${badgeUnstyledClasses.invisible} { opacity: 0; pointer-events: none; } @@ -68,7 +67,7 @@ export default function BadgeVisibility() { '& > *': { marginBottom: 2, }, - '& .MuiBadge-root': { + [`& .${badgeUnstyledClasses.root}`]: { marginRight: 4, }, }} diff --git a/docs/data/base/components/badge/ShowZeroBadge.js b/docs/data/base/components/badge/ShowZeroBadge.js index 0443a3f4093f56..43bedb8a44aff4 100644 --- a/docs/data/base/components/badge/ShowZeroBadge.js +++ b/docs/data/base/components/badge/ShowZeroBadge.js @@ -1,14 +1,13 @@ import * as React from 'react'; import Stack from '@mui/material/Stack'; import { styled } from '@mui/system'; -import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +import BadgeUnstyled, { badgeUnstyledClasses } from '@mui/base/BadgeUnstyled'; import MailIcon from '@mui/icons-material/Mail'; const StyledBadge = styled(BadgeUnstyled)` box-sizing: border-box; margin: 0; padding: 0; - color: rgba(0, 0, 0, 0.85); font-size: 14px; list-style: none; font-family: IBM Plex Sans, sans-serif; @@ -16,7 +15,7 @@ const StyledBadge = styled(BadgeUnstyled)` display: inline-block; line-height: 1; - & .MuiBadge-badge { + & .${badgeUnstyledClasses.badge} { z-index: auto; min-width: 20px; height: 20px; @@ -37,7 +36,7 @@ const StyledBadge = styled(BadgeUnstyled)` transform-origin: 100% 0; } - & .MuiBadge-invisible { + & .${badgeUnstyledClasses.invisible} { display: none; } `; diff --git a/docs/data/base/components/badge/ShowZeroBadge.tsx b/docs/data/base/components/badge/ShowZeroBadge.tsx index 0443a3f4093f56..43bedb8a44aff4 100644 --- a/docs/data/base/components/badge/ShowZeroBadge.tsx +++ b/docs/data/base/components/badge/ShowZeroBadge.tsx @@ -1,14 +1,13 @@ import * as React from 'react'; import Stack from '@mui/material/Stack'; import { styled } from '@mui/system'; -import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +import BadgeUnstyled, { badgeUnstyledClasses } from '@mui/base/BadgeUnstyled'; import MailIcon from '@mui/icons-material/Mail'; const StyledBadge = styled(BadgeUnstyled)` box-sizing: border-box; margin: 0; padding: 0; - color: rgba(0, 0, 0, 0.85); font-size: 14px; list-style: none; font-family: IBM Plex Sans, sans-serif; @@ -16,7 +15,7 @@ const StyledBadge = styled(BadgeUnstyled)` display: inline-block; line-height: 1; - & .MuiBadge-badge { + & .${badgeUnstyledClasses.badge} { z-index: auto; min-width: 20px; height: 20px; @@ -37,7 +36,7 @@ const StyledBadge = styled(BadgeUnstyled)` transform-origin: 100% 0; } - & .MuiBadge-invisible { + & .${badgeUnstyledClasses.invisible} { display: none; } `; diff --git a/docs/data/base/components/badge/UnstyledBadge.js b/docs/data/base/components/badge/UnstyledBadge.js index 64ca09a108c729..ec78b22054a5a9 100644 --- a/docs/data/base/components/badge/UnstyledBadge.js +++ b/docs/data/base/components/badge/UnstyledBadge.js @@ -1,12 +1,11 @@ import * as React from 'react'; import { styled, Box } from '@mui/system'; -import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +import BadgeUnstyled, { badgeUnstyledClasses } from '@mui/base/BadgeUnstyled'; const StyledBadge = styled(BadgeUnstyled)` box-sizing: border-box; margin: 0; padding: 0; - color: rgba(0, 0, 0, 0.85); font-size: 14px; font-variant: tabular-nums; list-style: none; @@ -15,7 +14,7 @@ const StyledBadge = styled(BadgeUnstyled)` display: inline-block; line-height: 1; - & .MuiBadge-badge { + & .${badgeUnstyledClasses.badge} { z-index: auto; min-width: 20px; height: 20px; @@ -29,20 +28,6 @@ const StyledBadge = styled(BadgeUnstyled)` background: #07f; border-radius: 10px; box-shadow: 0 0 0 1px #fff; - } - - & .MuiBadge-dot { - padding: 0; - z-index: auto; - min-width: 6px; - width: 6px; - height: 6px; - background: #07f; - border-radius: 100%; - box-shadow: 0 0 0 1px #fff; - } - - & .MuiBadge-anchorOriginTopRight { position: absolute; top: 0; right: 0; @@ -69,13 +54,8 @@ function BadgeContent() { export default function UnstyledBadge() { return ( - :not(style) + :not(style)': { ml: 4 } }}> - - - - - - - + + + ); } diff --git a/docs/data/base/components/badge/UnstyledBadge.tsx b/docs/data/base/components/badge/UnstyledBadge.tsx index 64ca09a108c729..ec78b22054a5a9 100644 --- a/docs/data/base/components/badge/UnstyledBadge.tsx +++ b/docs/data/base/components/badge/UnstyledBadge.tsx @@ -1,12 +1,11 @@ import * as React from 'react'; import { styled, Box } from '@mui/system'; -import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +import BadgeUnstyled, { badgeUnstyledClasses } from '@mui/base/BadgeUnstyled'; const StyledBadge = styled(BadgeUnstyled)` box-sizing: border-box; margin: 0; padding: 0; - color: rgba(0, 0, 0, 0.85); font-size: 14px; font-variant: tabular-nums; list-style: none; @@ -15,7 +14,7 @@ const StyledBadge = styled(BadgeUnstyled)` display: inline-block; line-height: 1; - & .MuiBadge-badge { + & .${badgeUnstyledClasses.badge} { z-index: auto; min-width: 20px; height: 20px; @@ -29,20 +28,6 @@ const StyledBadge = styled(BadgeUnstyled)` background: #07f; border-radius: 10px; box-shadow: 0 0 0 1px #fff; - } - - & .MuiBadge-dot { - padding: 0; - z-index: auto; - min-width: 6px; - width: 6px; - height: 6px; - background: #07f; - border-radius: 100%; - box-shadow: 0 0 0 1px #fff; - } - - & .MuiBadge-anchorOriginTopRight { position: absolute; top: 0; right: 0; @@ -69,13 +54,8 @@ function BadgeContent() { export default function UnstyledBadge() { return ( - :not(style) + :not(style)': { ml: 4 } }}> - - - - - - - + + + ); } diff --git a/docs/data/base/components/badge/UnstyledBadge.tsx.preview b/docs/data/base/components/badge/UnstyledBadge.tsx.preview index 55c0c93be1c769..0f52f923d64e43 100644 --- a/docs/data/base/components/badge/UnstyledBadge.tsx.preview +++ b/docs/data/base/components/badge/UnstyledBadge.tsx.preview @@ -1,6 +1,3 @@ - - - \ No newline at end of file diff --git a/docs/data/base/components/badge/badge-pt.md b/docs/data/base/components/badge/badge-pt.md new file mode 100644 index 00000000000000..0861f4670a68d5 --- /dev/null +++ b/docs/data/base/components/badge/badge-pt.md @@ -0,0 +1,45 @@ +--- +product: base +title: Unstyled React badge +components: BadgeUnstyled +githubLabel: 'component: badge' +packageName: '@mui/base' +--- + +# Unstyled badge + +

Badge generates a small badge to the top-right of its child(ren).

+ +```js +import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +``` + +{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} + +## Basic usage + +{{"demo": "UnstyledBadge.js", "defaultCodeOpen": false}} + +## Badge visibility + +The visibility of badges can be controlled using the `invisible` prop. If a badge is invisible, it has the `MuiBadge-invisible` class. It is up to the developer to provide styles that actually hide the badge. + +{{"demo": "BadgeVisibility.js"}} + +The badge hides automatically when `badgeContent` is zero. You can override this with the `showZero` prop. + +{{"demo": "ShowZeroBadge.js"}} + +## Maximum value + +You can use the `max` prop to cap the value of the badge content. It is set to 99 by default. + +Note that `badgeContent` should be a number (or convertible to a number) for this to work. + +{{"demo": "BadgeMax.js"}} + +## Accessibility + +You can't rely on the content of the badge to be announced correctly. You should provide a full description, for instance, with `aria-label`: + +{{"demo": "AccessibleBadges.js", "defaultCodeOpen": false}} diff --git a/docs/data/base/components/badge/badge-zh.md b/docs/data/base/components/badge/badge-zh.md new file mode 100644 index 00000000000000..2b67d223637257 --- /dev/null +++ b/docs/data/base/components/badge/badge-zh.md @@ -0,0 +1,45 @@ +--- +product: base +title: 无样式的 React 徽章 +components: BadgeUnstyled +githubLabel: 'component: badge' +packageName: '@mui/base' +--- + +# 无样式的徽章 + +

徽章组件会在其子项(们)的右上角生成一个小徽章。

+ +```js +import BadgeUnstyled from '@mui/base/BadgeUnstyled'; +``` + +{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} + +## 基本用法 + +{{"demo": "UnstyledBadge.js", "defaultCodeOpen": false}} + +## 徽章的可见性 + +徽章组件的隐显可以通过 `invisible` 属性来设置。 如果徽章不可见,那么它会被应用 `MuiBadge-invisible` 类。 It is up to the developer to provide styles that actually hide the badge. + +{{"demo": "BadgeVisibility.js"}} + +The badge hides automatically when `badgeContent` is zero. You can override this with the `showZero` prop. + +{{"demo": "ShowZeroBadge.js"}} + +## 最大值 + +您可以使用 `max` 属性来限制徽章内容的最大值。 默认被设置为 99。 + +请注意, `badgeContent` 应该是一个数字(或是一个可被转换为数字的值)才能工作。 + +{{"demo": "BadgeMax.js"}} + +## 无障碍设计 + +如果徽章的内容无法被正确的读取。 那您应该提供一个完整的描述,例如, 使用 `aria-label`: + +{{"demo": "AccessibleBadges.js", "defaultCodeOpen": false}} diff --git a/docs/data/base/components/badge/badge.md b/docs/data/base/components/badge/badge.md index 7790155121ed76..3df14565c71ef9 100644 --- a/docs/data/base/components/badge/badge.md +++ b/docs/data/base/components/badge/badge.md @@ -1,6 +1,6 @@ --- product: base -title: Unstyled React badge +title: Unstyled React Badge component components: BadgeUnstyled githubLabel: 'component: badge' packageName: '@mui/base' @@ -8,7 +8,7 @@ packageName: '@mui/base' # Unstyled badge -

Badge generates a small badge to the top-right of its child(ren).

+

The `BadgeUnstyled` component generates a small label that is attached to its children elements.

```js import BadgeUnstyled from '@mui/base/BadgeUnstyled'; @@ -22,28 +22,31 @@ import BadgeUnstyled from '@mui/base/BadgeUnstyled'; ## Badge visibility -The visibility of badges can be controlled using the `invisible` prop. -If a badge is invisible, it has the `MuiBadge-invisible` class. -It is up to the developer to provide styles that actually hide the badge. +You can control the visibility of a `BadgeUnstyled` by using the `invisible` prop. +Setting a badge to `invisible` does not actually hide it—instead, this prop adds the `MuiBadge-invisible` class to the badge, which you can target with styles to hide however you prefer: {{"demo": "BadgeVisibility.js"}} -The badge hides automatically when `badgeContent` is zero. You can override this with the `showZero` prop. +## Numerical badges -{{"demo": "ShowZeroBadge.js"}} +The following props are useful when `badgeContent` is a number. + +### The showZero prop -## Maximum value +By default, badges automatically hide when `badgeContent={0}`. You can override this behavior with the `showZero` prop: + +{{"demo": "ShowZeroBadge.js"}} -You can use the `max` prop to cap the value of the badge content. -It is set to 99 by default. +### The max prop -Note that `badgeContent` should be a number (or convertible to a number) for this to work. +You can use the `max` prop to set a maximum value for `badgeContent`. +The default is 99. {{"demo": "BadgeMax.js"}} ## Accessibility -You can't rely on the content of the badge to be announced correctly. -You should provide a full description, for instance, with `aria-label`: +Screen readers may not provide users with enough information about a badge's contents. +To make your `BadgeUnstyled` accessible, you must provide a full description with `aria-label`: {{"demo": "AccessibleBadges.js", "defaultCodeOpen": false}} diff --git a/docs/data/base/components/button/UnstyledButtonsDisabledFocus.js b/docs/data/base/components/button/UnstyledButtonsDisabledFocus.js new file mode 100644 index 00000000000000..c1f267626ad661 --- /dev/null +++ b/docs/data/base/components/button/UnstyledButtonsDisabledFocus.js @@ -0,0 +1,52 @@ +import * as React from 'react'; +import ButtonUnstyled, { buttonUnstyledClasses } from '@mui/base/ButtonUnstyled'; +import { styled } from '@mui/system'; +import Stack from '@mui/material/Stack'; + +const blue = { + 500: '#007FFF', + 600: '#0072E5', + 700: '#0059B2', +}; + +const CustomButton = styled(ButtonUnstyled)` + font-family: IBM Plex Sans, sans-serif; + font-weight: bold; + font-size: 0.875rem; + background-color: ${blue[500]}; + padding: 12px 24px; + border-radius: 8px; + color: white; + transition: all 150ms ease; + cursor: pointer; + border: none; + + &:hover { + background-color: ${blue[600]}; + } + + &.${buttonUnstyledClasses.active} { + background-color: ${blue[700]}; + } + + &.${buttonUnstyledClasses.focusVisible} { + box-shadow: 0 4px 20px 0 rgba(61, 71, 82, 0.1), 0 0 0 5px rgba(0, 127, 255, 0.5); + outline: none; + } + + &.${buttonUnstyledClasses.disabled} { + opacity: 0.5; + cursor: not-allowed; + } +`; + +export default function UnstyledButtonsDisabledFocus() { + return ( + + focusableWhenDisabled = false + + focusableWhenDisabled = true + + + ); +} diff --git a/docs/data/base/components/button/UnstyledButtonsDisabledFocus.tsx b/docs/data/base/components/button/UnstyledButtonsDisabledFocus.tsx new file mode 100644 index 00000000000000..c1f267626ad661 --- /dev/null +++ b/docs/data/base/components/button/UnstyledButtonsDisabledFocus.tsx @@ -0,0 +1,52 @@ +import * as React from 'react'; +import ButtonUnstyled, { buttonUnstyledClasses } from '@mui/base/ButtonUnstyled'; +import { styled } from '@mui/system'; +import Stack from '@mui/material/Stack'; + +const blue = { + 500: '#007FFF', + 600: '#0072E5', + 700: '#0059B2', +}; + +const CustomButton = styled(ButtonUnstyled)` + font-family: IBM Plex Sans, sans-serif; + font-weight: bold; + font-size: 0.875rem; + background-color: ${blue[500]}; + padding: 12px 24px; + border-radius: 8px; + color: white; + transition: all 150ms ease; + cursor: pointer; + border: none; + + &:hover { + background-color: ${blue[600]}; + } + + &.${buttonUnstyledClasses.active} { + background-color: ${blue[700]}; + } + + &.${buttonUnstyledClasses.focusVisible} { + box-shadow: 0 4px 20px 0 rgba(61, 71, 82, 0.1), 0 0 0 5px rgba(0, 127, 255, 0.5); + outline: none; + } + + &.${buttonUnstyledClasses.disabled} { + opacity: 0.5; + cursor: not-allowed; + } +`; + +export default function UnstyledButtonsDisabledFocus() { + return ( + + focusableWhenDisabled = false + + focusableWhenDisabled = true + + + ); +} diff --git a/docs/data/base/components/button/UnstyledButtonsDisabledFocus.tsx.preview b/docs/data/base/components/button/UnstyledButtonsDisabledFocus.tsx.preview new file mode 100644 index 00000000000000..1542c3355640a0 --- /dev/null +++ b/docs/data/base/components/button/UnstyledButtonsDisabledFocus.tsx.preview @@ -0,0 +1,4 @@ +focusableWhenDisabled = false + + focusableWhenDisabled = true + \ No newline at end of file diff --git a/docs/data/base/components/button/UnstyledButtonsDisabledFocusCustom.js b/docs/data/base/components/button/UnstyledButtonsDisabledFocusCustom.js new file mode 100644 index 00000000000000..ff4af610dbe6a6 --- /dev/null +++ b/docs/data/base/components/button/UnstyledButtonsDisabledFocusCustom.js @@ -0,0 +1,54 @@ +import * as React from 'react'; +import ButtonUnstyled, { buttonUnstyledClasses } from '@mui/base/ButtonUnstyled'; +import { styled } from '@mui/system'; +import Stack from '@mui/material/Stack'; + +const blue = { + 500: '#007FFF', + 600: '#0072E5', + 700: '#0059B2', +}; + +const CustomButton = styled(ButtonUnstyled)` + font-family: IBM Plex Sans, sans-serif; + font-weight: bold; + font-size: 0.875rem; + background-color: ${blue[500]}; + padding: 12px 24px; + border-radius: 8px; + color: white; + transition: all 150ms ease; + cursor: pointer; + border: none; + + &:hover:not(.${buttonUnstyledClasses.disabled}) { + background-color: ${blue[600]}; + } + + &.${buttonUnstyledClasses.active} { + background-color: ${blue[700]}; + } + + &.${buttonUnstyledClasses.focusVisible} { + box-shadow: 0 4px 20px 0 rgba(61, 71, 82, 0.1), 0 0 0 5px rgba(0, 127, 255, 0.5); + outline: none; + } + + &.${buttonUnstyledClasses.disabled} { + opacity: 0.5; + cursor: not-allowed; + } +`; + +export default function UnstyledButtonsDisabledFocusCustom() { + return ( + + + focusableWhenDisabled = false + + + focusableWhenDisabled = true + + + ); +} diff --git a/docs/data/base/components/button/UnstyledButtonsDisabledFocusCustom.tsx b/docs/data/base/components/button/UnstyledButtonsDisabledFocusCustom.tsx new file mode 100644 index 00000000000000..ff4af610dbe6a6 --- /dev/null +++ b/docs/data/base/components/button/UnstyledButtonsDisabledFocusCustom.tsx @@ -0,0 +1,54 @@ +import * as React from 'react'; +import ButtonUnstyled, { buttonUnstyledClasses } from '@mui/base/ButtonUnstyled'; +import { styled } from '@mui/system'; +import Stack from '@mui/material/Stack'; + +const blue = { + 500: '#007FFF', + 600: '#0072E5', + 700: '#0059B2', +}; + +const CustomButton = styled(ButtonUnstyled)` + font-family: IBM Plex Sans, sans-serif; + font-weight: bold; + font-size: 0.875rem; + background-color: ${blue[500]}; + padding: 12px 24px; + border-radius: 8px; + color: white; + transition: all 150ms ease; + cursor: pointer; + border: none; + + &:hover:not(.${buttonUnstyledClasses.disabled}) { + background-color: ${blue[600]}; + } + + &.${buttonUnstyledClasses.active} { + background-color: ${blue[700]}; + } + + &.${buttonUnstyledClasses.focusVisible} { + box-shadow: 0 4px 20px 0 rgba(61, 71, 82, 0.1), 0 0 0 5px rgba(0, 127, 255, 0.5); + outline: none; + } + + &.${buttonUnstyledClasses.disabled} { + opacity: 0.5; + cursor: not-allowed; + } +`; + +export default function UnstyledButtonsDisabledFocusCustom() { + return ( + + + focusableWhenDisabled = false + + + focusableWhenDisabled = true + + + ); +} diff --git a/docs/data/base/components/button/UnstyledButtonsDisabledFocusCustom.tsx.preview b/docs/data/base/components/button/UnstyledButtonsDisabledFocusCustom.tsx.preview new file mode 100644 index 00000000000000..6c68795155388b --- /dev/null +++ b/docs/data/base/components/button/UnstyledButtonsDisabledFocusCustom.tsx.preview @@ -0,0 +1,6 @@ + + focusableWhenDisabled = false + + + focusableWhenDisabled = true + \ No newline at end of file diff --git a/docs/data/base/components/button/UnstyledButtonsSimple.js b/docs/data/base/components/button/UnstyledButtonsSimple.js index 682c2d87e1a224..89e66ec084b1ef 100644 --- a/docs/data/base/components/button/UnstyledButtonsSimple.js +++ b/docs/data/base/components/button/UnstyledButtonsSimple.js @@ -1,7 +1,7 @@ import * as React from 'react'; -import Stack from '@mui/material/Stack'; import ButtonUnstyled, { buttonUnstyledClasses } from '@mui/base/ButtonUnstyled'; import { styled } from '@mui/system'; +import Stack from '@mui/material/Stack'; const blue = { 500: '#007FFF', @@ -9,7 +9,7 @@ const blue = { 700: '#0059B2', }; -const CustomButtonRoot = styled('button')` +const CustomButton = styled(ButtonUnstyled)` font-family: IBM Plex Sans, sans-serif; font-weight: bold; font-size: 0.875rem; @@ -40,10 +40,6 @@ const CustomButtonRoot = styled('button')` } `; -function CustomButton(props) { - return ; -} - export default function UnstyledButtonsSimple() { return ( diff --git a/docs/data/base/components/button/UnstyledButtonsSimple.tsx b/docs/data/base/components/button/UnstyledButtonsSimple.tsx index aaca68f8eb91c3..89e66ec084b1ef 100644 --- a/docs/data/base/components/button/UnstyledButtonsSimple.tsx +++ b/docs/data/base/components/button/UnstyledButtonsSimple.tsx @@ -1,10 +1,7 @@ import * as React from 'react'; -import Stack from '@mui/material/Stack'; -import ButtonUnstyled, { - buttonUnstyledClasses, - ButtonUnstyledProps, -} from '@mui/base/ButtonUnstyled'; +import ButtonUnstyled, { buttonUnstyledClasses } from '@mui/base/ButtonUnstyled'; import { styled } from '@mui/system'; +import Stack from '@mui/material/Stack'; const blue = { 500: '#007FFF', @@ -12,7 +9,7 @@ const blue = { 700: '#0059B2', }; -const CustomButtonRoot = styled('button')` +const CustomButton = styled(ButtonUnstyled)` font-family: IBM Plex Sans, sans-serif; font-weight: bold; font-size: 0.875rem; @@ -43,10 +40,6 @@ const CustomButtonRoot = styled('button')` } `; -function CustomButton(props: ButtonUnstyledProps) { - return ; -} - export default function UnstyledButtonsSimple() { return ( diff --git a/docs/data/base/components/button/UnstyledButtonsSpan.js b/docs/data/base/components/button/UnstyledButtonsSpan.js index d5e150422ac0ca..231bd8922e1711 100644 --- a/docs/data/base/components/button/UnstyledButtonsSpan.js +++ b/docs/data/base/components/button/UnstyledButtonsSpan.js @@ -1,7 +1,7 @@ import * as React from 'react'; -import Stack from '@mui/material/Stack'; import ButtonUnstyled, { buttonUnstyledClasses } from '@mui/base/ButtonUnstyled'; import { styled } from '@mui/system'; +import Stack from '@mui/material/Stack'; const blue = { 500: '#007FFF', @@ -9,7 +9,7 @@ const blue = { 700: '#0059B2', }; -const CustomButtonRoot = styled('span')` +const CustomButton = styled(ButtonUnstyled)` font-family: IBM Plex Sans, sans-serif; font-weight: bold; font-size: 0.875rem; @@ -40,15 +40,13 @@ const CustomButtonRoot = styled('span')` } `; -function CustomButton(props) { - return ; -} - export default function UnstyledButtonsSpan() { return ( - Button - Disabled + Button + + Disabled + ); } diff --git a/docs/data/base/components/button/UnstyledButtonsSpan.tsx b/docs/data/base/components/button/UnstyledButtonsSpan.tsx index a2159042df4799..231bd8922e1711 100644 --- a/docs/data/base/components/button/UnstyledButtonsSpan.tsx +++ b/docs/data/base/components/button/UnstyledButtonsSpan.tsx @@ -1,10 +1,7 @@ import * as React from 'react'; -import Stack from '@mui/material/Stack'; -import ButtonUnstyled, { - ButtonUnstyledProps, - buttonUnstyledClasses, -} from '@mui/base/ButtonUnstyled'; +import ButtonUnstyled, { buttonUnstyledClasses } from '@mui/base/ButtonUnstyled'; import { styled } from '@mui/system'; +import Stack from '@mui/material/Stack'; const blue = { 500: '#007FFF', @@ -12,7 +9,7 @@ const blue = { 700: '#0059B2', }; -const CustomButtonRoot = styled('span')` +const CustomButton = styled(ButtonUnstyled)` font-family: IBM Plex Sans, sans-serif; font-weight: bold; font-size: 0.875rem; @@ -43,15 +40,13 @@ const CustomButtonRoot = styled('span')` } `; -function CustomButton(props: ButtonUnstyledProps) { - return ; -} - export default function UnstyledButtonsSpan() { return ( - Button - Disabled + Button + + Disabled + ); } diff --git a/docs/data/base/components/button/UnstyledButtonsSpan.tsx.preview b/docs/data/base/components/button/UnstyledButtonsSpan.tsx.preview index 702ae5216245c1..456f8c68ebbaf6 100644 --- a/docs/data/base/components/button/UnstyledButtonsSpan.tsx.preview +++ b/docs/data/base/components/button/UnstyledButtonsSpan.tsx.preview @@ -1,2 +1,4 @@ -Button -Disabled \ No newline at end of file +Button + + Disabled + \ No newline at end of file diff --git a/docs/data/base/components/button/UseButton.js b/docs/data/base/components/button/UseButton.js index 0f61cdb38d7411..d9be7e79cfc67a 100644 --- a/docs/data/base/components/button/UseButton.js +++ b/docs/data/base/components/button/UseButton.js @@ -1,9 +1,9 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import clsx from 'clsx'; -import Stack from '@mui/material/Stack'; import { useButton } from '@mui/base/ButtonUnstyled'; import { styled } from '@mui/system'; +import Stack from '@mui/material/Stack'; const blue = { 500: '#007FFF', @@ -47,7 +47,6 @@ const CustomButton = React.forwardRef(function CustomButton(props, ref) { const { active, disabled, focusVisible, getRootProps } = useButton({ ...props, ref, - component: CustomButtonRoot, }); const classes = { diff --git a/docs/data/base/components/button/UseButton.tsx b/docs/data/base/components/button/UseButton.tsx index 4c47a24862af62..24a9d5eac627cc 100644 --- a/docs/data/base/components/button/UseButton.tsx +++ b/docs/data/base/components/button/UseButton.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import clsx from 'clsx'; -import Stack from '@mui/material/Stack'; import { ButtonUnstyledProps, useButton } from '@mui/base/ButtonUnstyled'; import { styled } from '@mui/system'; +import Stack from '@mui/material/Stack'; const blue = { 500: '#007FFF', @@ -49,7 +49,6 @@ const CustomButton = React.forwardRef(function CustomButton( const { active, disabled, focusVisible, getRootProps } = useButton({ ...props, ref, - component: CustomButtonRoot, }); const classes = { diff --git a/docs/data/base/components/button/button-pt.md b/docs/data/base/components/button/button-pt.md new file mode 100644 index 00000000000000..ed730ca7890613 --- /dev/null +++ b/docs/data/base/components/button/button-pt.md @@ -0,0 +1,45 @@ +--- +product: base +title: Botão React sem estilo +components: ButtonUnstyled +githubLabel: 'component: button' +waiAria: 'https://www.w3.org/TR/wai-aria-practices/#button' +--- + +# Unstyled button + +

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

+ +## Basic usage + +```js +import ButtonUnstyled from '@mui/base/ButtonUnstyled'; +``` + +{{"demo": "UnstyledButtonsSimple.js"}} + +## Customizing the root element + +By default, the `ButtonUnstyled` component renders a native `button` HTML element. You can override this by setting the `component` or `components.Root` prop. If you provide a non-interactive element, such as a `span`, the `ButtonUnstyled` component will automatically add the necessary accessibility attributes. + +{{"demo": "UnstyledButtonsSpan.js"}} + +Compare the attributes on the `span` with the `button` from the previous demo. + +## Complex customization + +In addition to HTML elements, you can also use SVGs with the `ButtonUnstyled` component. + +{{"demo": "UnstyledButtonCustom.js"}} + +## useButton hook + +```js +import { useButton } from '@mui/base/ButtonUnstyled'; +``` + +The `useButton` hook lets you use the functionality of `ButtonUnstyled` in other components. It returns props to be placed on a custom button element, along with fields representing the internal state of the button. + +The `useButton` hook requires the `ref` of the element it's used on. Additionally, you need to provide the `component` prop (unless you intend to use the plain `button`). + +{{"demo": "UseButton.js"}} diff --git a/docs/data/base/components/button/button-zh.md b/docs/data/base/components/button/button-zh.md new file mode 100644 index 00000000000000..5deecba07d963b --- /dev/null +++ b/docs/data/base/components/button/button-zh.md @@ -0,0 +1,45 @@ +--- +product: base +title: 无样式的 React 按钮 +components: ButtonUnstyled +githubLabel: 'component: button' +waiAria: 'https://www.w3.org/TR/wai-aria-practices/#button' +--- + +# 无样式的按钮 + +

按钮允许用户在单次点击时采取行动和作出选择。

+ +## 基本用法 + +```js +import ButtonUnstyled from '@mui/base/ButtonUnstyled'; +``` + +{{"demo": "UnstyledButtonsSimple.js"}} + +## 自定义根元素 + +默认情况下, `ButtonUnstyled` 组件会渲染原生的 `button ` HTML 元素。 您可以通过设置`component` 或`components.Root` 属性来覆盖这个组件. 如果您提供了一个非交互元素,如 `span`,则 ` ButtonUnstyled ` 组件将自动添加必要的辅助属性。 + +{{"demo": "UnstyledButtonsSpan.js"}} + +Compare the attributes on the `span` with the `button` from the previous demo. + +## 复杂的定制 + +In addition to HTML elements, you can also use SVGs with the `ButtonUnstyled` component. + +{{"demo": "UnstyledButtonCustom.js"}} + +## useButton hook + +```js +import { useButton } from '@mui/base/ButtonUnstyled'; +``` + +`useButton` hook 允许您在其他组件中使用 `ButtonUnstyled` 的功能。 It returns props to be placed on a custom button element, along with fields representing the internal state of the button. + +The `useButton` hook requires the `ref` of the element it's used on. Additionally, you need to provide the `component` prop (unless you intend to use the plain `button`). + +{{"demo": "UseButton.js"}} diff --git a/docs/data/base/components/button/button.md b/docs/data/base/components/button/button.md index d38a040a652838..f435a26c7fa44e 100644 --- a/docs/data/base/components/button/button.md +++ b/docs/data/base/components/button/button.md @@ -1,40 +1,64 @@ --- product: base -title: Unstyled React button +title: Unstyled React Button component and hook components: ButtonUnstyled githubLabel: 'component: button' -waiAria: https://www.w3.org/TR/wai-aria-practices/#button +waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/button/ --- # Unstyled button

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

-## Basic usage +## Basic button ```js import ButtonUnstyled from '@mui/base/ButtonUnstyled'; + +Button; ``` -{{"demo": "UnstyledButtonsSimple.js"}} +{{"demo": "UnstyledButtonsSimple.js", "defaultCodeOpen": true}} ## Customizing the root element By default, the `ButtonUnstyled` component renders a native `button` HTML element. You can override this by setting the `component` or `components.Root` prop. -If you provide a non-interactive element, such as a `span`, the `ButtonUnstyled` component will automatically add the necessary accessibility attributes. + +If you provide a non-interactive element such as a ``, the `ButtonUnstyled` component will automatically add the necessary accessibility attributes. + +Compare the attributes on the `` in this demo with the `ButtonUnstyled` from the previous demo: {{"demo": "UnstyledButtonsSpan.js"}} -Compare the attributes on the `span` with the `button` from the previous demo. +### Complex customization + +`ButtonUnstyled` accepts a wide range of custom elements beyond HTML elements. +You can even use SVGs, as the following demo illustrates: + +{{"demo": "UnstyledButtonCustom.js", "defaultCodeOpen": false}} + +## Focus on disabled buttons -## Complex customization +Similarly to the native HTML ` + {open ? ( + + Click me, I will stay visible until you click outside. + + ) : null} +
+ + ); +} diff --git a/docs/data/base/components/click-away-listener/ClickAway.tsx b/docs/data/base/components/click-away-listener/ClickAway.tsx new file mode 100644 index 00000000000000..f1c2ef550804d4 --- /dev/null +++ b/docs/data/base/components/click-away-listener/ClickAway.tsx @@ -0,0 +1,42 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import ClickAwayListener from '@mui/base/ClickAwayListener'; +import { SxProps } from '@mui/system'; + +export default function ClickAway() { + const [open, setOpen] = React.useState(false); + + const handleClick = () => { + setOpen((prev) => !prev); + }; + + const handleClickAway = () => { + setOpen(false); + }; + + const styles: SxProps = { + position: 'absolute', + top: 28, + right: 0, + left: 0, + zIndex: 1, + border: '1px solid', + p: 1, + bgcolor: 'background.paper', + }; + + return ( + + + + {open ? ( + + Click me, I will stay visible until you click outside. + + ) : null} + + + ); +} diff --git a/docs/data/base/components/click-away-listener/ClickAway.tsx.preview b/docs/data/base/components/click-away-listener/ClickAway.tsx.preview new file mode 100644 index 00000000000000..fc79db57923845 --- /dev/null +++ b/docs/data/base/components/click-away-listener/ClickAway.tsx.preview @@ -0,0 +1,12 @@ + + + + {open ? ( + + Click me, I will stay visible until you click outside. + + ) : null} + + \ No newline at end of file diff --git a/docs/data/base/components/click-away-listener/LeadingClickAway.js b/docs/data/base/components/click-away-listener/LeadingClickAway.js new file mode 100644 index 00000000000000..2f19b2b9e88ff7 --- /dev/null +++ b/docs/data/base/components/click-away-listener/LeadingClickAway.js @@ -0,0 +1,45 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import ClickAwayListener from '@mui/base/ClickAwayListener'; + +export default function LeadingClickAway() { + const [open, setOpen] = React.useState(false); + + const handleClick = () => { + setOpen((prev) => !prev); + }; + + const handleClickAway = () => { + setOpen(false); + }; + + const styles = { + position: 'absolute', + top: 28, + right: 0, + left: 0, + zIndex: 1, + border: '1px solid', + p: 1, + bgcolor: 'background.paper', + }; + + return ( + + + + {open ? ( + + Click me, I will stay visible until you click outside. + + ) : null} + + + ); +} diff --git a/docs/data/base/components/click-away-listener/LeadingClickAway.tsx b/docs/data/base/components/click-away-listener/LeadingClickAway.tsx new file mode 100644 index 00000000000000..4fc8a9ded121d6 --- /dev/null +++ b/docs/data/base/components/click-away-listener/LeadingClickAway.tsx @@ -0,0 +1,46 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import ClickAwayListener from '@mui/base/ClickAwayListener'; +import { SxProps } from '@mui/system'; + +export default function LeadingClickAway() { + const [open, setOpen] = React.useState(false); + + const handleClick = () => { + setOpen((prev) => !prev); + }; + + const handleClickAway = () => { + setOpen(false); + }; + + const styles: SxProps = { + position: 'absolute', + top: 28, + right: 0, + left: 0, + zIndex: 1, + border: '1px solid', + p: 1, + bgcolor: 'background.paper', + }; + + return ( + + + + {open ? ( + + Click me, I will stay visible until you click outside. + + ) : null} + + + ); +} diff --git a/docs/data/base/components/click-away-listener/LeadingClickAway.tsx.preview b/docs/data/base/components/click-away-listener/LeadingClickAway.tsx.preview new file mode 100644 index 00000000000000..dc02e5bc909044 --- /dev/null +++ b/docs/data/base/components/click-away-listener/LeadingClickAway.tsx.preview @@ -0,0 +1,16 @@ + + + + {open ? ( + + Click me, I will stay visible until you click outside. + + ) : null} + + \ No newline at end of file diff --git a/docs/data/base/components/click-away-listener/PortalClickAway.js b/docs/data/base/components/click-away-listener/PortalClickAway.js new file mode 100644 index 00000000000000..1dc86aa02348e7 --- /dev/null +++ b/docs/data/base/components/click-away-listener/PortalClickAway.js @@ -0,0 +1,44 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import ClickAwayListener from '@mui/base/ClickAwayListener'; +import Portal from '@mui/base/Portal'; + +export default function PortalClickAway() { + const [open, setOpen] = React.useState(false); + + const handleClick = () => { + setOpen((prev) => !prev); + }; + + const handleClickAway = () => { + setOpen(false); + }; + + const styles = { + position: 'fixed', + width: 200, + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + border: '1px solid', + p: 1, + bgcolor: 'background.paper', + }; + + return ( + +
+ + {open ? ( + + + Click me, I will stay visible until you click outside. + + + ) : null} +
+
+ ); +} diff --git a/docs/data/base/components/click-away-listener/PortalClickAway.tsx b/docs/data/base/components/click-away-listener/PortalClickAway.tsx new file mode 100644 index 00000000000000..0d7bfbab6932a0 --- /dev/null +++ b/docs/data/base/components/click-away-listener/PortalClickAway.tsx @@ -0,0 +1,45 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import ClickAwayListener from '@mui/base/ClickAwayListener'; +import Portal from '@mui/base/Portal'; +import { SxProps } from '@mui/system'; + +export default function PortalClickAway() { + const [open, setOpen] = React.useState(false); + + const handleClick = () => { + setOpen((prev) => !prev); + }; + + const handleClickAway = () => { + setOpen(false); + }; + + const styles: SxProps = { + position: 'fixed', + width: 200, + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + border: '1px solid', + p: 1, + bgcolor: 'background.paper', + }; + + return ( + +
+ + {open ? ( + + + Click me, I will stay visible until you click outside. + + + ) : null} +
+
+ ); +} diff --git a/docs/data/base/components/click-away-listener/PortalClickAway.tsx.preview b/docs/data/base/components/click-away-listener/PortalClickAway.tsx.preview new file mode 100644 index 00000000000000..9695afd7e4ae53 --- /dev/null +++ b/docs/data/base/components/click-away-listener/PortalClickAway.tsx.preview @@ -0,0 +1,14 @@ + +
+ + {open ? ( + + + Click me, I will stay visible until you click outside. + + + ) : null} +
+
\ No newline at end of file diff --git a/docs/data/base/components/click-away-listener/click-away-listener-pt.md b/docs/data/base/components/click-away-listener/click-away-listener-pt.md new file mode 100644 index 00000000000000..052488b11a188f --- /dev/null +++ b/docs/data/base/components/click-away-listener/click-away-listener-pt.md @@ -0,0 +1,54 @@ +--- +product: material-ui +title: Componente React para Detectar clique fora +components: ClickAwayListener +githubLabel: 'component: ClickAwayListener' +packageName: '@mui/base' +--- + +# Observador de Clique (ClickAwayListener) + +

Detecta se um evento de clique ocorreu fora de um elemento. Ele ouve cliques que ocorrem em algum lugar no documento.

+ +- 📦 [1.5 kB gzipped](/size-snapshot/). +- ⚛️ Suporte para portais + +[A paleta](/system/palette/) com funções de estilo. + +## Exemplo + +Por exemplo, se você precisar ocultar um menu quando as pessoas clicarem em qualquer outro lugar da sua página: + +{{"demo": "ClickAway.js"}} + +Observe que o componente aceita apenas um elemento filho. Você pode encontrar demonstrações avançadas na [seção documentação de menu](/material-ui/react-menu/#menulist-composition). + +## Portal + +A demonstração a seguir usa [`Portal`](/material-ui/react-portal/) para renderizar o menu suspenso em uma nova "subárvore" fora da hierarquia atual do DOM. + +{{"demo": "PortalClickAway.js"}} + +## Eventos + +Por padrão, o componente responde aos eventos de clique e de toque final (click + touch end). No entanto, você pode configurá-lo para responder aos eventos de mouse pressionado e toque inicial (mouse down + touch start). + +{{"demo": "LeadingClickAway.js"}} + +> ⚠️ Neste modo, apenas as interações na barra de rolagem do documento são ignoradas. + +## Accessibility + +By default `` will add an `onClick` handler to its children. This can result in e.g. screen readers announcing the children as clickable. However, the purpose of the `onClick` handler is not to make `children` interactive. + +In order to prevent screen readers from marking non-interactive children as "clickable" add `role="presentation"` to the immediate children: + +```tsx + +
+

non-interactive heading

+
+ +``` + +This is also required to fix a quirk in NVDA when using FireFox that prevents announcement of alert messages (see [mui-org/material-ui#29080](https://github.com/mui-org/material-ui/issues/29080)). diff --git a/docs/data/base/components/click-away-listener/click-away-listener-zh.md b/docs/data/base/components/click-away-listener/click-away-listener-zh.md new file mode 100644 index 00000000000000..0f471922451890 --- /dev/null +++ b/docs/data/base/components/click-away-listener/click-away-listener-zh.md @@ -0,0 +1,54 @@ +--- +product: material-ui +title: React Detect click outside(它处点击监听器)组件 +components: ClickAwayListener +githubLabel: 'component: ClickAwayListener' +packageName: '@mui/base' +--- + +# Click away listener 它处点击监听器 + +

用于检测点击事件是否发生在元素之外。 它可以监听文档中某处发生的点击事件。

+ +- 📦 [1.5kB 已压缩的包](/size-snapshot/)。 +- ⚛️ 支持传送门组件 + +{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} + +## 示例 + +例如,当用户在点击页面除菜单外的任何一处,您可能想隐藏一个下拉的菜单: + +{{"demo": "ClickAway.js"}} + +请注意,该组件仅接受一个子元素。 你可以在 [Menu 的文档章节](/material-ui/react-menu/#menulist-composition) 阅读更高级的样例。 + +## Portal + +下面的演示使用 [`传送门组件(Portal)`](/material-ui/react-portal/) 将下拉菜单渲染到当前 DOM 层次之外的新的“子级树”。 + +{{"demo": "PortalClickAway.js"}} + +## 前端(Leading edge) + +默认情况下,组件响应了尾随事件(trailing events)(点击 + 触摸结束)。 然而,您可以配置它来回应一些主要的事件(leading events)(鼠标按下 + 触摸开始)。 + +{{"demo": "LeadingClickAway.js"}} + +> ⚠️ 在此模式下,仅有文档对象滚动条上的交互被忽略。 + +## Accessibility + +By default `` will add an `onClick` handler to its children. This can result in e.g. screen readers announcing the children as clickable. However, the purpose of the `onClick` handler is not to make `children` interactive. This can result in e.g. screen readers announcing the children as clickable. However, the purpose of the `onClick` handler is not to make `children` interactive. + +In order to prevent screen readers from marking non-interactive children as "clickable" add `role="presentation"` to the immediate children: + +```tsx + +
+

non-interactive heading

+
+ +``` + +This is also required to fix a quirk in NVDA when using FireFox that prevents announcement of alert messages (see [mui-org/material-ui#29080](https://github.com/mui-org/material-ui/issues/29080)). diff --git a/docs/data/base/components/click-away-listener/click-away-listener.md b/docs/data/base/components/click-away-listener/click-away-listener.md new file mode 100644 index 00000000000000..b9cad74dafa356 --- /dev/null +++ b/docs/data/base/components/click-away-listener/click-away-listener.md @@ -0,0 +1,66 @@ +--- +product: base +title: React ClickAwayListener component +components: ClickAwayListener +githubLabel: 'component: ClickAwayListener' +packageName: '@mui/base' +--- + +# Click-away listener + +

The ClickAwayListener component detects when a click event happens outside of its child element.

+ +`ClickAwayListener` is a utility component that listens for click events outside of its child. + +> **Note:** the `ClickAwayListener` component only accepts _one_ child element. + +This is useful for components like [`PopperUnstyled`](/base/react-popper/) which should close when the user clicks anywhere else in the document. + +`ClickAwayListener` also supports the [`Portal` component](/base/react-portal/). + +{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} + +## Basic usage + +The following demo shows how to hide a menu dropdown when users click anywhere else on the page: + +{{"demo": "ClickAway.js"}} + +## Portal + +The following demo uses the [`Portal` component](/base/react-portal/) to render the dropdown into a new subtree outside of the current DOM hierarchy: + +{{"demo": "PortalClickAway.js"}} + +## Leading edge + +By default, the `ClickAwayListener` component responds to **trailing events**—the _end_ of a click or touch. + +You can set the component to listen for **leading events** (the start of a click or touch) using the `mouseEvent` and `touchEvent` props, as shown in the following demo: + +{{"demo": "LeadingClickAway.js"}} + +:::warning +⚠️ **Note:** when the component is set to listen for leading events, interactions with the scrollbar are ignored. +::: + +## Accessibility + +By default, `ClickAwayListener` will add an `onClick` handler to its child. +This can result in screen readers announcing that the child is clickable, even though this `onClick` handler has no effect on the child itself. + +To prevent this behavior, add `role="presentation"` to the child element: + +```tsx + +
+

non-interactive heading

+
+
+``` + +This is also required to fix a known issue in NVDA when using Firefox that prevents the announcement of alert messages—see [mui/material-ui#29080](https://github.com/mui/material-ui/issues/29080) for details. + +## Bundle size + +📦 [981 B gzipped](/size-snapshot/). diff --git a/docs/data/base/components/form-control/BasicFormControl.js b/docs/data/base/components/form-control/BasicFormControl.js new file mode 100644 index 00000000000000..732e37016a0755 --- /dev/null +++ b/docs/data/base/components/form-control/BasicFormControl.js @@ -0,0 +1,120 @@ +import * as React from 'react'; +import FormControlUnstyled, { + useFormControlUnstyledContext, +} from '@mui/base/FormControlUnstyled'; +import InputUnstyled, { inputUnstyledClasses } from '@mui/base/InputUnstyled'; +import { styled } from '@mui/system'; +import clsx from 'clsx'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const Input = styled(InputUnstyled)( + ({ theme }) => ` + + .${inputUnstyledClasses.input} { + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } + } +`, +); + +const Label = styled(({ children, className }) => { + const formControlContext = useFormControlUnstyledContext(); + const [dirty, setDirty] = React.useState(false); + + React.useEffect(() => { + if (formControlContext?.filled) { + setDirty(true); + } + }, [formControlContext]); + + if (formControlContext === undefined) { + return

{children}

; + } + + const { error, required, filled } = formControlContext; + const showRequiredError = dirty && required && !filled; + + return ( +

+ {children} + {required ? ' *' : ''} +

+ ); +})` + font-family: IBM Plex Sans, sans-serif; + font-size: 0.875rem; + margin-bottom: 4px; + + &.invalid { + color: red; + } +`; + +const HelperText = styled((props) => { + const formControlContext = useFormControlUnstyledContext(); + const [dirty, setDirty] = React.useState(false); + + React.useEffect(() => { + if (formControlContext?.filled) { + setDirty(true); + } + }, [formControlContext]); + + if (formControlContext === undefined) { + return null; + } + + const { required, filled } = formControlContext; + const showRequiredError = dirty && required && !filled; + + return showRequiredError ?

This field is required.

: null; +})` + font-family: IBM Plex Sans, sans-serif; + font-size: 0.875rem; +`; + +export default function UseFormControl() { + return ( + + + + + + ); +} diff --git a/docs/data/base/components/form-control/BasicFormControl.tsx b/docs/data/base/components/form-control/BasicFormControl.tsx new file mode 100644 index 00000000000000..b984bb276f9095 --- /dev/null +++ b/docs/data/base/components/form-control/BasicFormControl.tsx @@ -0,0 +1,122 @@ +import * as React from 'react'; +import FormControlUnstyled, { + useFormControlUnstyledContext, +} from '@mui/base/FormControlUnstyled'; +import InputUnstyled, { inputUnstyledClasses } from '@mui/base/InputUnstyled'; +import { styled } from '@mui/system'; +import clsx from 'clsx'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const Input = styled(InputUnstyled)( + ({ theme }) => ` + + .${inputUnstyledClasses.input} { + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } + } +`, +); + +const Label = styled( + ({ children, className }: { children?: React.ReactNode; className?: string }) => { + const formControlContext = useFormControlUnstyledContext(); + const [dirty, setDirty] = React.useState(false); + + React.useEffect(() => { + if (formControlContext?.filled) { + setDirty(true); + } + }, [formControlContext]); + + if (formControlContext === undefined) { + return

{children}

; + } + + const { error, required, filled } = formControlContext; + const showRequiredError = dirty && required && !filled; + + return ( +

+ {children} + {required ? ' *' : ''} +

+ ); + }, +)` + font-family: IBM Plex Sans, sans-serif; + font-size: 0.875rem; + margin-bottom: 4px; + + &.invalid { + color: red; + } +`; + +const HelperText = styled((props: {}) => { + const formControlContext = useFormControlUnstyledContext(); + const [dirty, setDirty] = React.useState(false); + + React.useEffect(() => { + if (formControlContext?.filled) { + setDirty(true); + } + }, [formControlContext]); + + if (formControlContext === undefined) { + return null; + } + + const { required, filled } = formControlContext; + const showRequiredError = dirty && required && !filled; + + return showRequiredError ?

This field is required.

: null; +})` + font-family: IBM Plex Sans, sans-serif; + font-size: 0.875rem; +`; + +export default function UseFormControl() { + return ( + + + + + + ); +} diff --git a/docs/data/base/components/form-control/BasicFormControl.tsx.preview b/docs/data/base/components/form-control/BasicFormControl.tsx.preview new file mode 100644 index 00000000000000..15d5fa95c0fc86 --- /dev/null +++ b/docs/data/base/components/form-control/BasicFormControl.tsx.preview @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/docs/data/base/components/form-control/FormControlFunctionChild.js b/docs/data/base/components/form-control/FormControlFunctionChild.js new file mode 100644 index 00000000000000..95f5e3a51cf440 --- /dev/null +++ b/docs/data/base/components/form-control/FormControlFunctionChild.js @@ -0,0 +1,77 @@ +import * as React from 'react'; +import FormControlUnstyled from '@mui/base/FormControlUnstyled'; +import InputUnstyled, { inputUnstyledClasses } from '@mui/base/InputUnstyled'; +import { styled } from '@mui/system'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const Input = styled(InputUnstyled)( + ({ theme }) => ` + + display: inline-block; + + .${inputUnstyledClasses.input} { + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } + } + + &.filled .${inputUnstyledClasses.input} { + box-shadow: 0 0 2px 2px rgba(125, 200, 0, 0.25); + } +`, +); + +const OkMark = styled('span')` + margin-left: 8px; + margin-top: 10px; + position: absolute; + color: rgba(125, 200, 0, 1); +`; + +export default function FormControlFunctionChild() { + return ( + + {({ filled, focused }) => ( + + + {filled && !focused && } + + )} + + ); +} diff --git a/docs/data/base/components/form-control/FormControlFunctionChild.tsx b/docs/data/base/components/form-control/FormControlFunctionChild.tsx new file mode 100644 index 00000000000000..8d2be39fa5247a --- /dev/null +++ b/docs/data/base/components/form-control/FormControlFunctionChild.tsx @@ -0,0 +1,79 @@ +import * as React from 'react'; +import FormControlUnstyled, { + FormControlUnstyledState, +} from '@mui/base/FormControlUnstyled'; +import InputUnstyled, { inputUnstyledClasses } from '@mui/base/InputUnstyled'; +import { styled } from '@mui/system'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const Input = styled(InputUnstyled)( + ({ theme }) => ` + + display: inline-block; + + .${inputUnstyledClasses.input} { + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } + } + + &.filled .${inputUnstyledClasses.input} { + box-shadow: 0 0 2px 2px rgba(125, 200, 0, 0.25); + } +`, +); + +const OkMark = styled('span')` + margin-left: 8px; + margin-top: 10px; + position: absolute; + color: rgba(125, 200, 0, 1); +`; + +export default function FormControlFunctionChild() { + return ( + + {({ filled, focused }: FormControlUnstyledState) => ( + + + {filled && !focused && } + + )} + + ); +} diff --git a/docs/data/base/components/form-control/FormControlFunctionChild.tsx.preview b/docs/data/base/components/form-control/FormControlFunctionChild.tsx.preview new file mode 100644 index 00000000000000..011568bb094c78 --- /dev/null +++ b/docs/data/base/components/form-control/FormControlFunctionChild.tsx.preview @@ -0,0 +1,8 @@ + + {({ filled, focused }: FormControlUnstyledState) => ( + + + {filled && !focused && } + + )} + \ No newline at end of file diff --git a/docs/data/base/components/form-control/UseFormControl.js b/docs/data/base/components/form-control/UseFormControl.js new file mode 100644 index 00000000000000..c44a08036be463 --- /dev/null +++ b/docs/data/base/components/form-control/UseFormControl.js @@ -0,0 +1,51 @@ +import * as React from 'react'; +import FormControlUnstyled, { + useFormControlUnstyledContext, +} from '@mui/base/FormControlUnstyled'; + +function CustomInput() { + const formControlContext = useFormControlUnstyledContext(); + + if (formControlContext === undefined) { + return null; + } + + const { value, required, onChange, disabled, onFocus, onBlur } = + formControlContext; + + return ( + + ); +} + +function ControlStateDisplay() { + const formControlContext = useFormControlUnstyledContext(); + if (formControlContext === undefined) { + return null; + } + + const { filled, focused } = formControlContext; + + return ( +

+ {filled ? 'filled' : 'empty'} |  + {focused ? 'focused' : 'not focused'} +

+ ); +} + +export default function UseFormControl() { + return ( + + + + + ); +} diff --git a/docs/data/base/components/form-control/UseFormControl.tsx b/docs/data/base/components/form-control/UseFormControl.tsx new file mode 100644 index 00000000000000..3af02e62afc7ad --- /dev/null +++ b/docs/data/base/components/form-control/UseFormControl.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; +import FormControlUnstyled, { + useFormControlUnstyledContext, +} from '@mui/base/FormControlUnstyled'; + +function CustomInput() { + const formControlContext = useFormControlUnstyledContext(); + + if (formControlContext === undefined) { + return null; + } + + const { value, required, onChange, disabled, onFocus, onBlur } = + formControlContext; + + return ( + + ); +} + +function ControlStateDisplay() { + const formControlContext = useFormControlUnstyledContext(); + if (formControlContext === undefined) { + return null; + } + + const { filled, focused } = formControlContext; + + return ( +

+ {filled ? 'filled' : 'empty'} |  + {focused ? 'focused' : 'not focused'} +

+ ); +} + +export default function UseFormControl() { + return ( + + + + + ); +} diff --git a/docs/data/base/components/form-control/UseFormControl.tsx.preview b/docs/data/base/components/form-control/UseFormControl.tsx.preview new file mode 100644 index 00000000000000..b2651ef7e5981c --- /dev/null +++ b/docs/data/base/components/form-control/UseFormControl.tsx.preview @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/docs/data/base/components/form-control/form-control-pt.md b/docs/data/base/components/form-control/form-control-pt.md new file mode 100644 index 00000000000000..97938e62327baf --- /dev/null +++ b/docs/data/base/components/form-control/form-control-pt.md @@ -0,0 +1,54 @@ +--- +product: base +title: React form control +components: FormControlUnstyled +packageName: '@mui/base' +--- + +# Unstyled form control + +

+ The FormControlUnstyled is a utility that lets you associate a form input with auxillary components, + such as labels, error indicators or helper text. +

+ +{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} + +## FormControlUnstyled + +FormControlUnstyled wraps an input and other components, enabling to reflect the input's state in these other components. + +For instance, you may want to show an additional element asking the user to enter a value if the input is empty, or display a warning icon if the entered value is incorrect. + +{{"demo": "BasicFormControl.js"}} + +The FormControlUnstyled provides a context that can be read by the useFormControl hook. + +## useFormControl hook + +The useFormControl hook can be used to enable integration between custom form inputs and FormControlUnstyled. Additionally, you can read the form control's state and react to its changes in a custom component. + +The demo below shows both. `CustomInput` is a wrapper around a native HTML `input` that adds FormControlUnstyled integration. `ControlStateDisplay` reads the state of the form control and displays it as text. + +{{"demo": "UseFormControl.js", "defaultCodeOpen": false}} + +Note that even though FormControlUnstyled supports both controlled and uncontrolled-style API (i.e. it accepts `value` and `defaultValue` props), `useFormControl` returns only the controlled `value`. This way, you don't have to implement both in your custom input - FormControlUnstyled does this for you. + +`useFormControl` returns an object with the following fields: + +| Name | Type | Description | +| ---------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `disabled` | boolean | Represents the value of the FormControlUnstyled's `disabled` prop. | +| `error` | boolean | Represents the value of the FormControlUnstyled's `error` prop. Note that it is not calculated automatically (i.e. it's not set when `required: true` and `value: ''`) | +| `filled` | boolean | Set to `true` if `value` is not empty. | +| `focused` | boolean | Set to `true` if the wrapped input has received focus. | +| `required` | boolean | Represents the value of the FormControlUnstyled's `required` prop. | +| `value` | unknown | The current value of the form control. | + +Additionally, the following callbacks are a part of the returned object. They are meant to be used when creating custom inputs. + +| Name | Type | Description | +| ---------- | ------------------------- | ------------------------------------------------------------- | +| `onChange` | React.ChangeEvent => void | Value change handler. Should be forwarded to the inner input. | +| `onBlur` | () => void | Focus change handler. Should be forwarded to the inner input. | +| `onFocus` | () => void | Focus change handler. Should be forwarded to the inner input. | diff --git a/docs/data/base/components/form-control/form-control-zh.md b/docs/data/base/components/form-control/form-control-zh.md new file mode 100644 index 00000000000000..97938e62327baf --- /dev/null +++ b/docs/data/base/components/form-control/form-control-zh.md @@ -0,0 +1,54 @@ +--- +product: base +title: React form control +components: FormControlUnstyled +packageName: '@mui/base' +--- + +# Unstyled form control + +

+ The FormControlUnstyled is a utility that lets you associate a form input with auxillary components, + such as labels, error indicators or helper text. +

+ +{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} + +## FormControlUnstyled + +FormControlUnstyled wraps an input and other components, enabling to reflect the input's state in these other components. + +For instance, you may want to show an additional element asking the user to enter a value if the input is empty, or display a warning icon if the entered value is incorrect. + +{{"demo": "BasicFormControl.js"}} + +The FormControlUnstyled provides a context that can be read by the useFormControl hook. + +## useFormControl hook + +The useFormControl hook can be used to enable integration between custom form inputs and FormControlUnstyled. Additionally, you can read the form control's state and react to its changes in a custom component. + +The demo below shows both. `CustomInput` is a wrapper around a native HTML `input` that adds FormControlUnstyled integration. `ControlStateDisplay` reads the state of the form control and displays it as text. + +{{"demo": "UseFormControl.js", "defaultCodeOpen": false}} + +Note that even though FormControlUnstyled supports both controlled and uncontrolled-style API (i.e. it accepts `value` and `defaultValue` props), `useFormControl` returns only the controlled `value`. This way, you don't have to implement both in your custom input - FormControlUnstyled does this for you. + +`useFormControl` returns an object with the following fields: + +| Name | Type | Description | +| ---------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `disabled` | boolean | Represents the value of the FormControlUnstyled's `disabled` prop. | +| `error` | boolean | Represents the value of the FormControlUnstyled's `error` prop. Note that it is not calculated automatically (i.e. it's not set when `required: true` and `value: ''`) | +| `filled` | boolean | Set to `true` if `value` is not empty. | +| `focused` | boolean | Set to `true` if the wrapped input has received focus. | +| `required` | boolean | Represents the value of the FormControlUnstyled's `required` prop. | +| `value` | unknown | The current value of the form control. | + +Additionally, the following callbacks are a part of the returned object. They are meant to be used when creating custom inputs. + +| Name | Type | Description | +| ---------- | ------------------------- | ------------------------------------------------------------- | +| `onChange` | React.ChangeEvent => void | Value change handler. Should be forwarded to the inner input. | +| `onBlur` | () => void | Focus change handler. Should be forwarded to the inner input. | +| `onFocus` | () => void | Focus change handler. Should be forwarded to the inner input. | diff --git a/docs/data/base/components/form-control/form-control.md b/docs/data/base/components/form-control/form-control.md new file mode 100644 index 00000000000000..b5b64fae1b6b06 --- /dev/null +++ b/docs/data/base/components/form-control/form-control.md @@ -0,0 +1,67 @@ +--- +product: base +title: Unstyled React Form Control component and hook +components: FormControlUnstyled +githubLabel: 'component: FormControl' +packageName: '@mui/base' +--- + +# Unstyled form control + +

+ The FormControlUnstyled component is a utility that lets you associate a form input with auxillary components, such as labels, error indicators, or helper text. +

+ +{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} + +## Basic usage + +`FormControlUnstyled` wraps an input with other associated components in order to make the state of the input available to those components. + +For instance, you may want to show an additional element asking the user to enter a value if the input is empty, or display a warning icon if the entered value is incorrect. + +{{"demo": "BasicFormControl.js"}} + +## useFormControlUnstyledContext hook + +The `FormControlUnstyled` component provides a context that can be read by the `useFormControlUnstyledContext` hook. + +You can use the `useFormControlUnstyledContext` hook to enable integration between custom form inputs and `FormControlUnstyled`. +You can also use it to read the form control's state and react to its changes in a custom component. + +The demo below shows both: + +- `CustomInput` is a wrapper around a native HTML `` that adds `FormControlUnstyled` integration. +- `ControlStateDisplay` reads the state of the form control and displays it as text. + +{{"demo": "UseFormControl.js", "defaultCodeOpen": false}} + +Note that even though `FormControlUnstyled` supports both controlled and uncontrolled-style API +(i.e. it accepts `value` and `defaultValue` props), `useFormControlUnstyledContext` returns only the controlled `value`. +This way, you don't have to implement both in your custom input—`FormControlUnstyled` does this for you. + +`useFormControlUnstyledContext` returns an object with the following fields: + +| Name | Type | Description | +| ---------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `disabled` | boolean | Represents the value of the FormControlUnstyled's `disabled` prop. | +| `error` | boolean | Represents the value of the `FormControlUnstyled` component's `error` prop. Note that it is not calculated automatically (i.e. it's not set when `required: true` and `value: ''`). | +| `filled` | boolean | Set to `true` if `value` is not empty. | +| `focused` | boolean | Set to `true` if the wrapped input has received focus. | +| `required` | boolean | Represents the value of the `FormControlUnstyled` component's `required` prop. | +| `value` | unknown | The current value of the form control. | + +The following callbacks are also part of the returned object—they are meant to be used when creating custom inputs: + +| Name | Type | Description | +| ---------- | ------------------------- | ------------------------------------------------------------- | +| `onChange` | React.ChangeEvent => void | Value change handler. Should be forwarded to the inner input. | +| `onBlur` | () => void | Focus change handler. Should be forwarded to the inner input. | +| `onFocus` | () => void | Focus change handler. Should be forwarded to the inner input. | + +## Using FormControlUnstyled without reading context + +In addition to providing a context, you can access the state of the form control by providing a function as a child of the `FormControlUnstyled`. +The state will be provided as a parameter to this function. + +{{"demo": "FormControlFunctionChild.js"}} diff --git a/docs/data/base/components/input/InputAdornments.js b/docs/data/base/components/input/InputAdornments.js new file mode 100644 index 00000000000000..6f0cf8e7d2c596 --- /dev/null +++ b/docs/data/base/components/input/InputAdornments.js @@ -0,0 +1,162 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import Box from '@mui/material/Box'; +import ButtonUnstyled from '@mui/base/ButtonUnstyled'; +import InputUnstyled, { inputUnstyledClasses } from '@mui/base/InputUnstyled'; +import Visibility from '@mui/icons-material/Visibility'; +import VisibilityOff from '@mui/icons-material/VisibilityOff'; +import { styled } from '@mui/system'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const StyledInputRoot = styled('div')( + ({ theme }) => ` + font-family: IBM Plex Sans, sans-serif; + display: flex; + font-weight: 500; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + align-items: center; + justify-content: center; + + &.${inputUnstyledClasses.focused} { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } +`, +); + +const StyledInputElement = styled('input')( + ({ theme }) => ` + font-size: 0.875rem; + font-family: inherit; + font-weight: 400; + line-height: 1.5; + flex-grow: 1; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: inherit; + border: none; + border-radius: inherit; + padding: 12px 12px; + outline: 0; +`, +); + +const IconButton = styled(ButtonUnstyled)` + display: inline-flex; + align-items: center; + justify-content: center; + border: none; + background: inherit; + cursor: pointer; +`; + +const InputAdornment = styled('div')` + margin: 8px; + display: inline-flex; + align-items: center; + justify-content: center; +`; + +const CustomInput = React.forwardRef(function CustomInput(props, ref) { + const { components, ...other } = props; + return ( + + ); +}); + +CustomInput.propTypes = { + /** + * The components used for each slot inside the InputBase. + * Either a string to use a HTML element or a component. + * @default {} + */ + components: PropTypes.shape({ + Input: PropTypes.elementType, + Root: PropTypes.elementType, + Textarea: PropTypes.elementType, + }), +}; + +export default function InputAdornments() { + const [values, setValues] = React.useState({ + amount: '', + password: '', + weight: '', + weightRange: '', + showPassword: false, + }); + + const handleChange = (prop) => (event) => { + setValues({ ...values, [prop]: event.target.value }); + }; + + const handleClickShowPassword = () => { + setValues({ + ...values, + showPassword: !values.showPassword, + }); + }; + + const handleMouseDownPassword = (event) => { + event.preventDefault(); + }; + + return ( + * + *': { ml: 1 } }}> + kg} + /> + + + {values.showPassword ? : } + + + } + /> + + ); +} diff --git a/docs/data/base/components/input/InputAdornments.tsx b/docs/data/base/components/input/InputAdornments.tsx new file mode 100644 index 00000000000000..673e595c0f33a9 --- /dev/null +++ b/docs/data/base/components/input/InputAdornments.tsx @@ -0,0 +1,163 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import ButtonUnstyled from '@mui/base/ButtonUnstyled'; +import InputUnstyled, { + InputUnstyledProps, + inputUnstyledClasses, +} from '@mui/base/InputUnstyled'; +import Visibility from '@mui/icons-material/Visibility'; +import VisibilityOff from '@mui/icons-material/VisibilityOff'; +import { styled } from '@mui/system'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const StyledInputRoot = styled('div')( + ({ theme }) => ` + font-family: IBM Plex Sans, sans-serif; + display: flex; + font-weight: 500; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + align-items: center; + justify-content: center; + + &.${inputUnstyledClasses.focused} { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } +`, +); + +const StyledInputElement = styled('input')( + ({ theme }) => ` + font-size: 0.875rem; + font-family: inherit; + font-weight: 400; + line-height: 1.5; + flex-grow: 1; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: inherit; + border: none; + border-radius: inherit; + padding: 12px 12px; + outline: 0; +`, +); + +const IconButton = styled(ButtonUnstyled)` + display: inline-flex; + align-items: center; + justify-content: center; + border: none; + background: inherit; + cursor: pointer; +`; + +const InputAdornment = styled('div')` + margin: 8px; + display: inline-flex; + align-items: center; + justify-content: center; +`; + +const CustomInput = React.forwardRef(function CustomInput( + props: InputUnstyledProps, + ref: React.ForwardedRef, +) { + const { components, ...other } = props; + return ( + + ); +}); + +interface State { + amount: string; + password: string; + weight: string; + weightRange: string; + showPassword: boolean; +} + +export default function InputAdornments() { + const [values, setValues] = React.useState({ + amount: '', + password: '', + weight: '', + weightRange: '', + showPassword: false, + }); + + const handleChange = + (prop: keyof State) => (event: React.ChangeEvent) => { + setValues({ ...values, [prop]: event.target.value }); + }; + + const handleClickShowPassword = () => { + setValues({ + ...values, + showPassword: !values.showPassword, + }); + }; + + const handleMouseDownPassword = (event: React.MouseEvent) => { + event.preventDefault(); + }; + + return ( + * + *': { ml: 1 } }}> + kg} + /> + + + {values.showPassword ? : } + + + } + /> + + ); +} diff --git a/docs/data/base/components/input/InputMultiline.js b/docs/data/base/components/input/InputMultiline.js new file mode 100644 index 00000000000000..bd04db680af92b --- /dev/null +++ b/docs/data/base/components/input/InputMultiline.js @@ -0,0 +1,90 @@ +import * as React from 'react'; +import InputUnstyled from '@mui/base/InputUnstyled'; +import { styled } from '@mui/system'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const StyledInputElement = styled('input')( + ({ theme }) => ` + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } +`, +); + +const StyledTextareaElement = styled('textarea', { + shouldForwardProp: (prop) => + !['ownerState', 'minRows', 'maxRows'].includes(prop.toString()), +})( + ({ theme }) => ` + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } +`, +); + +const CustomInput = React.forwardRef(function CustomInput(props, ref) { + return ( + + ); +}); + +export default function UnstyledInputBasic() { + return ( + + ); +} diff --git a/docs/data/base/components/input/InputMultiline.tsx b/docs/data/base/components/input/InputMultiline.tsx new file mode 100644 index 00000000000000..740a3eb311bcc7 --- /dev/null +++ b/docs/data/base/components/input/InputMultiline.tsx @@ -0,0 +1,93 @@ +import * as React from 'react'; +import InputUnstyled, { InputUnstyledProps } from '@mui/base/InputUnstyled'; +import { styled } from '@mui/system'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const StyledInputElement = styled('input')( + ({ theme }) => ` + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } +`, +); + +const StyledTextareaElement = styled('textarea', { + shouldForwardProp: (prop) => + !['ownerState', 'minRows', 'maxRows'].includes(prop.toString()), +})( + ({ theme }) => ` + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } +`, +); + +const CustomInput = React.forwardRef(function CustomInput( + props: InputUnstyledProps, + ref: React.ForwardedRef, +) { + return ( + + ); +}); + +export default function UnstyledInputBasic() { + return ( + + ); +} diff --git a/docs/data/base/components/input/InputMultiline.tsx.preview b/docs/data/base/components/input/InputMultiline.tsx.preview new file mode 100644 index 00000000000000..6aebc7010ec14b --- /dev/null +++ b/docs/data/base/components/input/InputMultiline.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/base/components/input/InputMultilineAutosize.js b/docs/data/base/components/input/InputMultilineAutosize.js new file mode 100644 index 00000000000000..9da963a9a6d475 --- /dev/null +++ b/docs/data/base/components/input/InputMultilineAutosize.js @@ -0,0 +1,88 @@ +import * as React from 'react'; +import InputUnstyled from '@mui/base/InputUnstyled'; +import TextareaAutosize from '@mui/base/TextareaAutosize'; +import { styled } from '@mui/system'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const StyledInputElement = styled('input')( + ({ theme }) => ` + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } +`, +); + +const StyledTextareaElement = styled(TextareaAutosize)( + ({ theme }) => ` + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } +`, +); + +const CustomInput = React.forwardRef(function CustomInput(props, ref) { + return ( + + ); +}); + +export default function UnstyledInputBasic() { + return ( + + ); +} diff --git a/docs/data/base/components/input/InputMultilineAutosize.tsx b/docs/data/base/components/input/InputMultilineAutosize.tsx new file mode 100644 index 00000000000000..5944719d0431c7 --- /dev/null +++ b/docs/data/base/components/input/InputMultilineAutosize.tsx @@ -0,0 +1,91 @@ +import * as React from 'react'; +import InputUnstyled, { InputUnstyledProps } from '@mui/base/InputUnstyled'; +import TextareaAutosize from '@mui/base/TextareaAutosize'; +import { styled } from '@mui/system'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const StyledInputElement = styled('input')( + ({ theme }) => ` + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } +`, +); + +const StyledTextareaElement = styled(TextareaAutosize)( + ({ theme }) => ` + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } +`, +); + +const CustomInput = React.forwardRef(function CustomInput( + props: InputUnstyledProps, + ref: React.ForwardedRef, +) { + return ( + + ); +}); + +export default function UnstyledInputBasic() { + return ( + + ); +} diff --git a/docs/data/base/components/input/InputMultilineAutosize.tsx.preview b/docs/data/base/components/input/InputMultilineAutosize.tsx.preview new file mode 100644 index 00000000000000..6aebc7010ec14b --- /dev/null +++ b/docs/data/base/components/input/InputMultilineAutosize.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/base/components/input/UnstyledInputBasic.js b/docs/data/base/components/input/UnstyledInputBasic.js new file mode 100644 index 00000000000000..ba7fede0fdf12e --- /dev/null +++ b/docs/data/base/components/input/UnstyledInputBasic.js @@ -0,0 +1,57 @@ +import * as React from 'react'; +import InputUnstyled from '@mui/base/InputUnstyled'; +import { styled } from '@mui/system'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const StyledInputElement = styled('input')( + ({ theme }) => ` + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } +`, +); + +const CustomInput = React.forwardRef(function CustomInput(props, ref) { + return ( + + ); +}); + +export default function UnstyledInputBasic() { + return ; +} diff --git a/docs/data/base/components/input/UnstyledInputBasic.tsx b/docs/data/base/components/input/UnstyledInputBasic.tsx new file mode 100644 index 00000000000000..8a333abc3b9b4a --- /dev/null +++ b/docs/data/base/components/input/UnstyledInputBasic.tsx @@ -0,0 +1,60 @@ +import * as React from 'react'; +import InputUnstyled, { InputUnstyledProps } from '@mui/base/InputUnstyled'; +import { styled } from '@mui/system'; + +const blue = { + 100: '#DAECFF', + 200: '#80BFFF', + 400: '#3399FF', + 600: '#0072E5', +}; + +const grey = { + 50: '#F3F6F9', + 100: '#E7EBF0', + 200: '#E0E3E7', + 300: '#CDD2D7', + 400: '#B2BAC2', + 500: '#A0AAB4', + 600: '#6F7E8C', + 700: '#3E5060', + 800: '#2D3843', + 900: '#1A2027', +}; + +const StyledInputElement = styled('input')( + ({ theme }) => ` + width: 320px; + font-size: 0.875rem; + font-family: IBM Plex Sans, sans-serif; + font-weight: 400; + line-height: 1.5; + color: ${theme.palette.mode === 'dark' ? grey[300] : grey[900]}; + background: ${theme.palette.mode === 'dark' ? grey[900] : grey[50]}; + border: 1px solid ${theme.palette.mode === 'dark' ? grey[800] : grey[300]}; + border-radius: 8px; + padding: 12px 12px; + + &:hover { + background: ${theme.palette.mode === 'dark' ? '' : grey[100]}; + border-color: ${theme.palette.mode === 'dark' ? grey[700] : grey[400]}; + } + + &:focus { + outline: 3px solid ${theme.palette.mode === 'dark' ? blue[600] : blue[100]}; + } +`, +); + +const CustomInput = React.forwardRef(function CustomInput( + props: InputUnstyledProps, + ref: React.ForwardedRef, +) { + return ( + + ); +}); + +export default function UnstyledInputBasic() { + return ; +} diff --git a/docs/data/base/components/input/UnstyledInputBasic.tsx.preview b/docs/data/base/components/input/UnstyledInputBasic.tsx.preview new file mode 100644 index 00000000000000..bd1c54843288d5 --- /dev/null +++ b/docs/data/base/components/input/UnstyledInputBasic.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/material/components/text-fields/UseInput.js b/docs/data/base/components/input/UseInput.js similarity index 76% rename from docs/data/material/components/text-fields/UseInput.js rename to docs/data/base/components/input/UseInput.js index 22b6115c184608..a8b67078305253 100644 --- a/docs/data/material/components/text-fields/UseInput.js +++ b/docs/data/base/components/input/UseInput.js @@ -1,6 +1,7 @@ import * as React from 'react'; import { useInput } from '@mui/base'; import { styled } from '@mui/system'; +import { unstable_useForkRef as useForkRef } from '@mui/utils'; const blue = { 100: '#DAECFF', @@ -47,15 +48,20 @@ const StyledInputElement = styled('input')( ); const CustomInput = React.forwardRef(function CustomInput(props, ref) { - const { getRootProps, getInputProps } = useInput(props, ref); + const { getRootProps, getInputProps } = useInput(props); + + const inputProps = getInputProps(); + + // Make sure that both the forwarded ref and the ref returned from the getInputProps are applied on the input element + inputProps.ref = useForkRef(inputProps.ref, ref); return (
- +
); }); export default function UseInput() { - return ; + return ; } diff --git a/docs/data/material/components/text-fields/UseInput.tsx b/docs/data/base/components/input/UseInput.tsx similarity index 77% rename from docs/data/material/components/text-fields/UseInput.tsx rename to docs/data/base/components/input/UseInput.tsx index 855dfe0adef6e7..7bb78790082cd1 100644 --- a/docs/data/material/components/text-fields/UseInput.tsx +++ b/docs/data/base/components/input/UseInput.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { useInput } from '@mui/base'; import { styled } from '@mui/system'; +import { unstable_useForkRef as useForkRef } from '@mui/utils'; const blue = { 100: '#DAECFF', @@ -50,15 +51,20 @@ const CustomInput = React.forwardRef(function CustomInput( props: React.InputHTMLAttributes, ref: React.ForwardedRef, ) { - const { getRootProps, getInputProps } = useInput(props, ref); + const { getRootProps, getInputProps } = useInput(props); + + const inputProps = getInputProps(); + + // Make sure that both the forwarded ref and the ref returned from the getInputProps are applied on the input element + inputProps.ref = useForkRef(inputProps.ref, ref); return (
- +
); }); export default function UseInput() { - return ; + return ; } diff --git a/docs/data/material/components/text-fields/UseInput.tsx.preview b/docs/data/base/components/input/UseInput.tsx.preview similarity index 90% rename from docs/data/material/components/text-fields/UseInput.tsx.preview rename to docs/data/base/components/input/UseInput.tsx.preview index b8514b3008a05c..bd1c54843288d5 100644 --- a/docs/data/material/components/text-fields/UseInput.tsx.preview +++ b/docs/data/base/components/input/UseInput.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/base/components/input/input-pt.md b/docs/data/base/components/input/input-pt.md new file mode 100644 index 00000000000000..f46fa3e47cfad5 --- /dev/null +++ b/docs/data/base/components/input/input-pt.md @@ -0,0 +1,54 @@ +--- +product: base +title: Unstyled React Input component and hook +components: InputUnstyled +githubLabel: 'component: input' +packageName: '@mui/base' +--- + +# Unstyled input + +

The Input component provides users with a field to enter and edit text.

+ +Features: + +- ✨ Supports start and end adornments +- 🚀 Can be transformed to `