diff --git a/.circleci/config.yml b/.circleci/config.yml index a7ad989617f25f..2fcd48297951c5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ version: 2.1 orbs: - aws-cli: circleci/aws-cli@5.3.5 - aws-s3: circleci/aws-s3@4.1.1 + aws-cli: circleci/aws-cli@5.4.1 + aws-s3: circleci/aws-s3@4.1.2 parameters: browserstack-force: @@ -306,7 +306,7 @@ jobs: <<: *default-job resource_class: 'medium+' docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble steps: - checkout - install_js: @@ -334,7 +334,7 @@ jobs: test_e2e: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble steps: - checkout - install_js: @@ -346,7 +346,7 @@ jobs: # NOTE: This workflow runs after successful docs deploy. See /test/e2e-website/README.md#ci <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble steps: - checkout - install_js: @@ -359,7 +359,7 @@ jobs: test_profile: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble steps: - checkout - install_js: @@ -384,7 +384,7 @@ jobs: test_regressions: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble steps: - checkout - install_js: @@ -456,7 +456,7 @@ jobs: test_bundling_next_webpack4: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble working_directory: /tmp/material-ui/test/bundling/fixtures/next-webpack4/ steps: - checkout: @@ -474,7 +474,7 @@ jobs: test_bundling_next_webpack5: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble working_directory: /tmp/material-ui/test/bundling/fixtures/next-webpack5/ steps: - checkout: @@ -492,7 +492,7 @@ jobs: test_bundling_create_react_app: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble working_directory: /tmp/material-ui/test/bundling/fixtures/create-react-app/ steps: - checkout: @@ -510,7 +510,7 @@ jobs: test_bundling_snowpack: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble working_directory: /tmp/material-ui/test/bundling/fixtures/snowpack/ steps: - checkout: @@ -528,7 +528,7 @@ jobs: test_bundling_vite: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble working_directory: /tmp/material-ui/test/bundling/fixtures/vite/ steps: - checkout: @@ -546,7 +546,7 @@ jobs: test_bundling_esbuild: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble working_directory: /tmp/material-ui/test/bundling/fixtures/esbuild/ steps: - checkout: @@ -564,7 +564,7 @@ jobs: test_bundling_gatsby: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.52.0-noble + - image: mcr.microsoft.com/playwright:v1.54.1-noble environment: GATSBY_CPU_COUNT: '3' working_directory: /tmp/material-ui/test/bundling/fixtures/gatsby/ diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index 1e2025bb28e32a..c67e38696ed160 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -7,6 +7,7 @@ "packages/mui-codemod", "packages/mui-core-downloads-tracker", "packages/mui-docs", + "packages/mui-envinfo", "packages/mui-icons-material", "packages/mui-lab", "packages/mui-material-nextjs", @@ -26,6 +27,7 @@ "@mui/codemod": "packages/mui-codemod/build", "@mui/core-downloads-tracker": "packages/mui-core-downloads-tracker/build", "@mui/docs": "packages/mui-docs/build", + "@mui/envinfo": "packages/mui-envinfo/build", "@mui/icons-material": "packages/mui-icons-material/build", "@mui/internal-test-utils": "packages-internal/test-utils", "@mui/internal-docs-utils": "packages-internal/docs-utils", diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index f351a846bcda9c..00000000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,592 +0,0 @@ -// @ts-check - -/** - * @typedef {import('eslint').Linter.Config} Config - */ - -const path = require('path'); -const a11yBase = require('eslint-config-airbnb/rules/react-a11y'); - -const controlHasAssociatedLabelConfig = a11yBase.rules['jsx-a11y/control-has-associated-label']; - -const controlHasAssociatedLabelOptions = - typeof controlHasAssociatedLabelConfig[1] === 'object' ? controlHasAssociatedLabelConfig[1] : {}; - -const OneLevelImportMessage = [ - 'Prefer one level nested imports to avoid bundling everything in dev mode or breaking CJS/ESM split.', - 'See https://github.com/mui/material-ui/pull/24147 for the kind of win it can unlock.', -].join('\n'); -// This only applies to packages published from this monorepo. -// If you build a library around `@mui/material` you can safely use `createStyles` without running into the same issue as we are. -const forbidCreateStylesMessage = - 'Use `MuiStyles` instead if the styles are exported. Otherwise use `as const` assertions. ' + - '`createStyles` will lead to inlined, at-compile-time-resolved type-imports. ' + - 'See https://github.com/microsoft/TypeScript/issues/36097#issuecomment-578324386 for more information'; - -const ENABLE_REACT_COMPILER_PLUGIN = false; - -const NO_RESTRICTED_IMPORTS_PATHS_TOP_LEVEL_PACKAGES = [ - { - name: '@mui/material', - message: OneLevelImportMessage, - }, - { - name: '@mui/lab', - message: OneLevelImportMessage, - }, -]; - -const NO_RESTRICTED_IMPORTS_PATTERNS_DEEPLY_NESTED = [ - { - group: [ - '@mui/*/*/*', - '@pigment-css/*/*/*', - '@base-ui/*/*/*', - // Allow any import depth with any internal packages - '!@mui/internal-*/**', - // TODO delete - '@base-ui-components/*/*/*', // Wait for migration to @base-ui/ - '@base_ui/*/*/*', // Legacy, moved to @base-ui-components/ - '!@mui/docs/**', // @mui/docs should be @mui/internal-docs - ], - message: OneLevelImportMessage, - }, -]; - -const restrictedMethods = ['setTimeout', 'setInterval', 'clearTimeout', 'clearInterval']; - -const restrictedSyntaxRules = restrictedMethods.map((method) => ({ - message: `Use global ${method} instead of window.${method}.`, - selector: `MemberExpression[object.name='window'][property.name='${method}']`, -})); - -module.exports = /** @type {Config} */ ({ - root: true, // So parent files don't get applied - env: { - es2020: true, - browser: true, - node: true, - }, - extends: [ - 'plugin:eslint-plugin-import/recommended', - 'plugin:eslint-plugin-import/typescript', - 'eslint-config-airbnb', - require.resolve('./eslint/config-airbnb-typescript.js'), - 'eslint-config-prettier', - ], - parser: '@typescript-eslint/parser', - parserOptions: { - ecmaVersion: 7, - }, - plugins: [ - 'eslint-plugin-material-ui', - 'eslint-plugin-react-hooks', - '@typescript-eslint', - 'eslint-plugin-consistent-default-export-name', - ...(ENABLE_REACT_COMPILER_PLUGIN ? ['eslint-plugin-react-compiler'] : []), - ], - settings: { - 'import/resolver': { - webpack: { - config: path.join(__dirname, './webpackBaseConfig.js'), - }, - }, - }, - /** - * Sorted alphanumerically within each group. built-in and each plugin form - * their own groups. - */ - rules: { - 'consistent-this': ['error', 'self'], - curly: ['error', 'all'], - 'dot-notation': 'error', - // Just as bad as "max components per file" - 'max-classes-per-file': 'off', - // Too interruptive - 'no-alert': 'error', - // Stylistic opinion - 'arrow-body-style': 'off', - // Allow warn and error for dev environments - 'no-console': ['error', { allow: ['warn', 'error'] }], - 'no-param-reassign': 'off', // It's fine. - // Airbnb use warn https://github.com/airbnb/javascript/blob/63098cbb6c05376dbefc9a91351f5727540c1ce1/packages/eslint-config-airbnb-base/rules/style.js#L97 - // but eslint recommands error - 'func-names': 'error', - 'no-restricted-imports': [ - 'error', - { - patterns: NO_RESTRICTED_IMPORTS_PATTERNS_DEEPLY_NESTED, - }, - ], - 'no-continue': 'off', - 'no-constant-condition': 'error', - 'no-implied-eval': 'error', - 'no-throw-literal': 'error', - // Use the proptype inheritance chain - 'no-prototype-builtins': 'off', - 'no-return-await': 'error', - 'no-underscore-dangle': 'error', - 'nonblock-statement-body-position': 'error', - 'prefer-arrow-callback': ['error', { allowNamedFunctions: true }], - // Destructuring harm grep potential. - 'prefer-destructuring': 'off', - - 'no-use-before-define': 'off', - '@typescript-eslint/no-use-before-define': [ - 'error', - { - functions: false, - classes: true, - variables: true, - }, - ], - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': [ - 'error', - { - vars: 'all', - args: 'after-used', - ignoreRestSiblings: true, - argsIgnorePattern: '^_', - caughtErrors: 'none', - }, - ], - - // Not sure why it doesn't work - 'import/named': 'off', - 'import/no-cycle': 'off', - // Missing yarn workspace support - 'import/no-extraneous-dependencies': 'off', - // The code is already coupled to webpack. Prefer explicit coupling. - 'import/no-webpack-loader-syntax': 'off', - - // doesn't work? - 'jsx-a11y/label-has-associated-control': [ - 'error', - { - // airbnb uses 'both' which requires nesting i.e. - // 'either' allows `htmlFor` - assert: 'either', - }, - ], - // We are a library, we need to support it too - 'jsx-a11y/no-autofocus': 'off', - // Remove when issues are fixed - // https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/issues/959 - // https://github.com/airbnb/javascript/issues/3069 - 'jsx-a11y/control-has-associated-label': [ - 'error', - { - ...controlHasAssociatedLabelOptions, - ignoreElements: [...(controlHasAssociatedLabelOptions.ignoreElements || []), 'th', 'td'], - }, - ], - - 'material-ui/docgen-ignore-before-comment': 'error', - 'material-ui/rules-of-use-theme-variants': 'error', - 'material-ui/no-empty-box': 'error', - 'material-ui/no-styled-box': 'error', - 'material-ui/straight-quotes': 'error', - - 'react-hooks/exhaustive-deps': ['error', { additionalHooks: 'useEnhancedEffect' }], - 'react-hooks/rules-of-hooks': 'error', - - 'react/default-props-match-prop-types': [ - 'error', - { - // Otherwise the rule thinks inner props = outer props - // But in TypeScript we want to know that a certain prop is defined during render - // while it can be ommitted from the callsite. - // Then defaultProps (or default values) will make sure that the prop is defined during render - allowRequiredDefaults: true, - }, - ], - // Can add verbosity to small functions making them harder to grok. - // Though we have to manually enforce it for function components with default values. - 'react/destructuring-assignment': 'off', - 'react/forbid-prop-types': 'off', // Too strict, no time for that - 'react/jsx-curly-brace-presence': 'off', // broken - // airbnb is using .jsx - 'react/jsx-filename-extension': ['error', { extensions: ['.js', '.tsx'] }], - // Prefer over <>. - 'react/jsx-fragments': ['error', 'element'], - // Enforces premature optimization - 'react/jsx-no-bind': 'off', - // We are a UI library. - 'react/jsx-props-no-spreading': 'off', - // This rule is great for raising people awareness of what a key is and how it works. - 'react/no-array-index-key': 'off', - 'react/no-danger': 'error', - 'react/no-unknown-property': ['error', { ignore: ['sx'] }], - 'react/no-direct-mutation-state': 'error', - // Not always relevant - 'react/require-default-props': 'off', - 'react/sort-prop-types': 'error', - // This depends entirely on what you're doing. There's no universal pattern - 'react/state-in-constructor': 'off', - // stylistic opinion. For conditional assignment we want it outside, otherwise as static - 'react/static-property-placement': 'off', - // noopener is enough - // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-target-blank.md#rule-options - 'react/jsx-no-target-blank': ['error', { allowReferrer: true }], - - 'no-restricted-syntax': [ - 'error', - { - message: - "Do not import default or named exports from React. Use a namespace import (import * as React from 'react';) instead.", - selector: - 'ImportDeclaration[source.value="react"] ImportDefaultSpecifier, ImportDeclaration[source.value="react"] ImportSpecifier', - }, - { - message: - "Do not import default or named exports from ReactDOM. Use a namespace import (import * as ReactDOM from 'react-dom';) instead.", - selector: - 'ImportDeclaration[source.value="react-dom"] ImportDefaultSpecifier, ImportDeclaration[source.value="react-dom"] ImportSpecifier', - }, - { - message: - "Do not import default or named exports from ReactDOM. Use a namespace import (import * as ReactDOM from 'react-dom/client';) instead.", - selector: - 'ImportDeclaration[source.value="react-dom/client"] ImportDefaultSpecifier, ImportDeclaration[source.value="react-dom/client"] ImportSpecifier', - }, - { - message: - "Do not import default or named exports from ReactDOMServer. Use a namespace import (import * as ReactDOM from 'react-dom/server';) instead.", - selector: - 'ImportDeclaration[source.value="react-dom/server"] ImportDefaultSpecifier, ImportDeclaration[source.value="react-dom/server"] ImportSpecifier', - }, - { - message: - "The 'use client' pragma can't be used with export * in the same module. This is not supported by Next.js.", - selector: 'ExpressionStatement[expression.value="use client"] ~ ExportAllDeclaration', - }, - { - message: 'Do not call `Error(...)` without `new`. Use `new Error(...)` instead.', - selector: "CallExpression[callee.name='Error']", - }, - ...restrictedSyntaxRules, - ], - - // We re-export default in many places, remove when https://github.com/airbnb/javascript/issues/2500 gets resolved - 'no-restricted-exports': 'off', - // Avoid accidental auto-"fixes" https://github.com/jsx-eslint/eslint-plugin-react/issues/3458 - 'react/no-invalid-html-attribute': 'off', - - 'react/jsx-no-useless-fragment': ['error', { allowExpressions: true }], - 'lines-around-directive': 'off', - ...(ENABLE_REACT_COMPILER_PLUGIN ? { 'react-compiler/react-compiler': 'error' } : {}), - // Prevent the use of `e` as a shorthand for `event`, `error`, etc. - 'id-denylist': ['error', 'e'], - }, - overrides: [ - ...['mui-material', 'mui-system', 'mui-utils', 'mui-lab', 'mui-utils', 'mui-styled-engine'].map( - (packageName) => ({ - files: [`packages/${packageName}/src/**/*.?(c|m)[jt]s?(x)`], - excludedFiles: ['*.test.*', '*.spec.*'], - rules: { - 'material-ui/no-restricted-resolved-imports': [ - 'error', - [ - { - pattern: `**/packages/${packageName}/src/index.*`, - message: - "Don't import from the package index. Import the specific module directly instead.", - }, - ], - ], - }, - }), - ), - { - files: [ - // matching the pattern of the test runner - '*.test.?(c|m)[jt]s?(x)', - ], - extends: ['plugin:mocha/recommended'], - rules: { - // does not work with wildcard imports. Mistakes will throw at runtime anyway - 'import/named': 'off', - 'material-ui/disallow-active-element-as-key-event-target': 'error', - - // upgraded level from recommended - 'mocha/no-exclusive-tests': 'error', - 'mocha/no-skipped-tests': 'error', - - // no rationale provided in /recommended - 'mocha/no-mocha-arrows': 'off', - // definitely a useful rule but too many false positives - // due to `describeConformance` - // "If you're using dynamically generated tests, you should disable this rule."" - 'mocha/no-setup-in-describe': 'off', - // `beforeEach` for a single case is optimized for change - // when we add a test we don't have to refactor the existing - // test to `beforeEach`. - // `beforeEach`+`afterEach` also means that the `beforeEach` - // is cleaned up in `afterEach` if the test causes a crash - 'mocha/no-hooks-for-single-case': 'off', - - // disable eslint-plugin-jsx-a11y - // tests are not driven by assistive technology - // add `jsx-a11y` rules once you encounter them in tests - 'jsx-a11y/click-events-have-key-events': 'off', - 'jsx-a11y/control-has-associated-label': 'off', - 'jsx-a11y/iframe-has-title': 'off', - 'jsx-a11y/label-has-associated-control': 'off', - 'jsx-a11y/mouse-events-have-key-events': 'off', - 'jsx-a11y/no-noninteractive-tabindex': 'off', - 'jsx-a11y/no-static-element-interactions': 'off', - 'jsx-a11y/tabindex-no-positive': 'off', - - // In tests this is generally intended. - 'react/button-has-type': 'off', - // They are accessed to test custom validator implementation with PropTypes.checkPropTypes - 'react/forbid-foreign-prop-types': 'off', - // components that are defined in test are isolated enough - // that they don't need type-checking - 'react/prop-types': 'off', - 'react/no-unused-prop-types': 'off', - }, - }, - // Next.js plugin - { - files: ['docs/**/*'], - extends: ['plugin:@next/next/recommended'], - settings: { - next: { - rootDir: 'docs', - }, - }, - rules: { - // We're not using the Image component at the moment - '@next/next/no-img-element': 'off', - 'no-restricted-imports': [ - 'error', - { - paths: NO_RESTRICTED_IMPORTS_PATHS_TOP_LEVEL_PACKAGES, - patterns: NO_RESTRICTED_IMPORTS_PATTERNS_DEEPLY_NESTED, - }, - ], - 'no-irregular-whitespace': ['error', { skipJSXText: true, skipStrings: true }], - }, - }, - { - files: ['docs/src/modules/components/**/*'], - rules: { - 'material-ui/no-hardcoded-labels': [ - 'error', - { allow: ['MUI', 'X', 'GitHub', 'Stack Overflow'] }, - ], - }, - }, - // demos - { - files: ['docs/src/pages/**/*', 'docs/data/**/*'], - rules: { - // This most often reports data that is defined after the component definition. - // This is safe to do and helps readability of the demo code since the data is mostly irrelevant. - '@typescript-eslint/no-use-before-define': 'off', - 'react/prop-types': 'off', - 'no-alert': 'off', - 'no-console': 'off', - }, - }, - // Next.js entry points pages - { - files: ['docs/pages/**/*'], - rules: { - 'react/prop-types': 'off', - }, - }, - { - files: ['docs/data/**/*'], - excludedFiles: [ - // filenames/match-exported sees filename as 'file-name.d' - // Plugin looks unmaintain, find alternative? (e.g. eslint-plugin-project-structure) - '*.d.ts', - 'docs/data/joy/getting-started/templates/**/*', - 'docs/data/**/{css,system,tailwind}/*', - ], - rules: { - 'consistent-default-export-name/default-export-match-filename': ['error'], - }, - }, - { - files: ['docs/data/material/getting-started/templates/**/*'], - rules: { - // So we can use # to improve the page UX - // and so developer get eslint warning to remind them to fix the links - 'jsx-a11y/anchor-is-valid': 'off', - }, - }, - { - files: ['*.d.ts'], - rules: { - 'import/export': 'off', // Not sure why it doesn't work - }, - }, - { - files: ['packages/*/src/**/*.tsx'], - excludedFiles: '*.spec.tsx', - rules: { - 'react/prop-types': 'off', - }, - }, - { - files: ['packages/*/src/*/*.?(c|m)[jt]s?(x)'], - excludedFiles: [ - '*.spec.*', - '*.test.*', - // deprecated library - '**/mui-joy/**/*', - // used internally, not used on app router yet - '**/mui-docs/**/*', - ], - rules: { - 'material-ui/disallow-react-api-in-server-components': 'error', - }, - }, - { - files: ['packages/*/src/**/*.?(c|m)[jt]s?(x)'], - excludedFiles: '*.spec.*', - rules: { - 'no-restricted-imports': [ - 'error', - { - paths: [ - { - name: '@mui/material/styles', - importNames: ['createStyles'], - message: forbidCreateStylesMessage, - }, - ], - patterns: [ - // Allow deeper imports for TypeScript types. TODO? - '@mui/*/*/*/*', - ], - }, - ], - }, - }, - { - files: ['*.spec.*'], - rules: { - 'no-alert': 'off', - 'no-console': 'off', - 'no-empty-pattern': 'off', - 'no-lone-blocks': 'off', - 'no-shadow': 'off', - - '@typescript-eslint/no-unused-expressions': 'off', - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/no-use-before-define': 'off', - - // Not sure why it doesn't work - 'import/export': 'off', - 'import/prefer-default-export': 'off', - - 'jsx-a11y/anchor-has-content': 'off', - 'jsx-a11y/anchor-is-valid': 'off', - 'jsx-a11y/tabindex-no-positive': 'off', - - 'react/default-props-match-prop-types': 'off', - 'react/no-access-state-in-setstate': 'off', - 'react/no-unused-prop-types': 'off', - 'react/prefer-stateless-function': 'off', - 'react/prop-types': 'off', - 'react/require-default-props': 'off', - 'react/state-in-constructor': 'off', - 'react/static-property-placement': 'off', - 'react/function-component-definition': 'off', - }, - }, - { - files: ['packages-internal/scripts/typescript-to-proptypes/src/**/*.ts'], - rules: { - // Working with flags is common in TypeScript compiler - 'no-bitwise': 'off', - }, - }, - { - files: ['packages/*/src/**/*.?(c|m)[jt]s?(x)'], - excludedFiles: ['*.spec.*'], - rules: { - 'no-restricted-imports': [ - 'error', - { - paths: [ - ...NO_RESTRICTED_IMPORTS_PATHS_TOP_LEVEL_PACKAGES, - { - name: '@mui/utils', - message: OneLevelImportMessage, - }, - ], - }, - ], - // TODO: Consider setting back to `ignoreExternal: true` when the expected behavior is fixed: - // https://github.com/import-js/eslint-plugin-import/issues/2348#issuecomment-1587320057 - // Reevaluate when https://github.com/import-js/eslint-plugin-import/pull/2998 is released. - 'import/no-cycle': ['error', { ignoreExternal: false }], - }, - }, - { - files: ['packages/*/src/**/*.?(c|m)[jt]s?(x)'], - excludedFiles: ['*.d.ts', '*.spec.*', 'packages/mui-joy/**/*'], - rules: { - 'material-ui/mui-name-matches-component-name': 'error', - }, - }, - { - files: ['test/bundling/scripts/**/*.js'], - rules: { - // ES modules need extensions - 'import/extensions': ['error', 'ignorePackages'], - }, - }, - { - files: ['**/*.mjs'], - rules: { - 'import/extensions': ['error', 'ignorePackages'], - }, - }, - { - /** - * Examples are for demonstration purposes and should not be considered a part of the library. - * They don't contain ESLint setup, so we don't want them to contain ESLint directives - * We do, however, want to keep the rules in place to ensure the examples are following - * a reasonably similar code style as the library. - */ - files: ['examples/**/*'], - rules: { - 'no-console': 'off', - 'no-underscore-dangle': 'off', - 'import/no-unresolved': 'off', - 'import/namespace': 'off', - 'import/extensions': 'off', - 'import/named': 'off', - 'import/no-duplicates': 'off', - 'import/no-named-as-default': 'off', - 'import/default': 'off', - 'import/no-named-as-default-member': 'off', - 'import/order': 'off', - // Reset the default until https://github.com/jsx-eslint/eslint-plugin-react/issues/3672 is fixed. - 'react/jsx-no-target-blank': ['error', { allowReferrer: false }], - 'react/prop-types': 'off', - 'no-irregular-whitespace': ['error', { skipJSXText: true, skipStrings: true }], - }, - }, - { - // TODO, move rule to be global, propagate: https://github.com/mui/material-ui/issues/42169 - files: ['examples/material-ui-pigment-css-vite-ts/**/*'], - rules: { - 'react/react-in-jsx-scope': 'off', - }, - }, - { - files: ['apps/**/*'], - rules: { - 'import/no-relative-packages': 'off', - }, - }, - ], -}); diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7d4cf522b2dd4..d3268d38b70091 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,6 @@ jobs: with: node-version: 20 cache: 'pnpm' # https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#caching-packages-dependencies - - run: npm install -g npm@latest - run: pnpm install:codesandbox - run: pnpm build:codesandbox - run: pnpm pkg-pr-new-release diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 88486737f159d9..bc7c2a440cf597 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2 with: languages: typescript config-file: ./.github/codeql/codeql-config.yml @@ -30,4 +30,4 @@ jobs: # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2 diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 9a602d223381c9..fe753121ce0a43 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -40,6 +40,6 @@ jobs: publish_results: true # Upload the results to GitHub's code scanning dashboard. - name: Upload to code-scanning - uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2 with: sarif_file: results.sarif diff --git a/.gitignore b/.gitignore index b96f61af23f923..cbad2d4b1882e3 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ /docs/export /docs/pages/playground/ /docs/public/feed/ +/docs/public/material-ui/ /examples/**/.cache /packages/mui-codemod/lib /packages/mui-envinfo/*.tgz diff --git a/.eslintignore b/.lintignore similarity index 100% rename from .eslintignore rename to .lintignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000000000..bd5535a6035b27 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +pnpm-lock.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f9df97bc51a6c..84ea78ec5b97c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,86 @@ # [Versions](https://mui.com/versions/) +## 7.2.0 + + + +_Jun 26, 2025_ + +A big thanks to the 17 contributors who made this release possible. Here are the highlights ✨: + +- ⚡️ Added `modularCssLayers` theme option for splitting styles into multiple CSS layers (#46001) @siriwatknp. +- 📖 Added example for using Material UI with React Router v7 (#46406) @siriwatknp. + +### `@mui/material@7.2.0` + +- [Backdrop] Fix handling of `component` prop (#46269) @sai6855 +- [Chip] Explicitly define line-height (#46260) @DiegoAndai +- [Chip] Fix handling on event handlers (#46263) @sai6855 +- [OutlinedInput][Input] Deprecate composed classes (#46316) @sai6855 +- [Select] Pass MenuProps.slotProps.list alongside MenuListProps (#46274) @scousino +- [l10] Enable `labelDisplayedRows` translation for Romanian (#46377) @dhu-redwoodtech +- Skip generating `modularCssLayers` CSS var (#46329) @siriwatknp + +### `@mui/system@7.2.0` + +- Add `modularCssLayers` theme flag to split styles into multiple CSS layers (#46001) @siriwatknp + +### `@mui/styled-engine@7.2.0` + +- Do not reuse the emotion cache across SSR requests (#46276) @robbtraister + +### `@mui/codemod@7.2.0` + +- [Dialog] Add codemod for deprecated props (#46328) @sai6855 + +### Docs + +- Don't forward `hasAiSuggestion` (#46415) @bharatkashyap +- Add introduction to MCP (#46224) @bharatkashyap +- Fallback for searchbar during SSR (#46364) @Janpot +- Update InitColorSchemeScript options to match colorSchemeSelector (#46302) @humble-barnacle001 +- Add `ListItemButton` to make the deprecation clear (#46356) @siriwatknp +- Remove "Unstyled" section from component docs (#46272) @mapache-salvaje +- Add Testing section to Rating component doc (#46268) @0210shivam +- Fix fade modal demo (#46271) @brijeshb42 +- [ai] Add suggestions to edit with MUI Chat (#46309) @bharatkashyap +- [Dialog] Fix form dialog uses ARIA roles on incompatible elements (#46307) @ZeeshanTamboli +- [Menu] Fix dark mode styling of grouped header demo (#46317) @sai6855 +- [TextField] Removed type="number" demos (#46314) @KirankumarAmbati +- [examples] Add `material-ui-react-router-ts` example (#46406) @siriwatknp + +### Core + +- pnpm docs:sync-team (3641a0b) @oliviertassinari +- Add cross-env to eslint script (#46358) @ZeeshanTamboli +- Support merging of className and style from theme (#45975) @sai6855 +- [code-infra] Create bundle size package (#45911) @Janpot +- [docs-infra] Add a script to generate Material UI `llms.txt` and docs markdown. (#46308) @siriwatknp +- [docs-infra] Fix stackblitz for js projects (#46220) @Janpot +- [infra] Add emotion as external for bundle monitor (#46372) @Janpot +- [infra] Create update PR on every canary publish for internal packages (#46367) @Janpot +- [infra] Remove deprecated esmExternals (#46365) @Janpot +- [infra] Support project-specific changelog in build scripts (#46425) @michaldudak +- [toolpad][website] Remove references to Toolpad (#46311) @prakhargupta1 + +All contributors of this release in alphabetical order: @0210shivam, @bharatkashyap, @brijeshb42, @dhu-redwoodtech, @DiegoAndai, @humble-barnacle001, @Janpot, @KirankumarAmbati, @mapache-salvaje, @michaldudak, @oliviertassinari, @prakhargupta1, @robbtraister, @sai6855, @scousino, @siriwatknp, @ZeeshanTamboli + +## 7.1.2 + +_Jun 18, 2025_ + +A big thanks to the 2 contributors who made this release possible. + +### `@mui/material@7.1.2` + +- [Chip] Fix handling on event handlers (#46263) @sai6855 + +### Docs + +- Fix fade modal demo (#46271) @brijeshb42 + +All contributors of this release in alphabetical order: @brijeshb42, @sai6855 + ## 7.1.1 diff --git a/apps/bare-next-app/.eslintrc b/apps/bare-next-app/.eslintrc deleted file mode 100644 index 73d03ea1064762..00000000000000 --- a/apps/bare-next-app/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": ["plugin:react/jsx-runtime"], - "rules": { - "import/prefer-default-export": "off", - "import/extensions": "off", - "import/no-unresolved": "off", - "react/no-unknown-property": ["error", { "ignore": ["sx"] }], - }, -} diff --git a/apps/bare-next-app/package.json b/apps/bare-next-app/package.json index d97eb2329c55cb..932ddb9da058ef 100644 --- a/apps/bare-next-app/package.json +++ b/apps/bare-next-app/package.json @@ -23,9 +23,9 @@ }, "devDependencies": { "@pigment-css/nextjs-plugin": "0.0.30", - "@types/node": "^20.17.57", - "@types/react": "^19.1.6", - "@types/react-dom": "^19.1.5", + "@types/node": "^20.19.9", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", "eslint": "^8.57.1", "typescript": "^5.8.3" }, diff --git a/apps/pigment-css-next-app/package.json b/apps/pigment-css-next-app/package.json index 036be9589edac9..14f16611a2873a 100644 --- a/apps/pigment-css-next-app/package.json +++ b/apps/pigment-css-next-app/package.json @@ -22,9 +22,9 @@ }, "devDependencies": { "@pigment-css/nextjs-plugin": "0.0.30", - "@types/node": "^20.17.57", - "@types/react": "^19.1.6", - "@types/react-dom": "^19.1.5", + "@types/node": "^20.19.9", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", "eslint": "^8.57.1", "typescript": "^5.8.3" }, diff --git a/apps/pigment-css-next-app/src/app/material-ui/page.tsx b/apps/pigment-css-next-app/src/app/material-ui/page.tsx index 8d346b5bd4d800..e7ee423f52723b 100644 --- a/apps/pigment-css-next-app/src/app/material-ui/page.tsx +++ b/apps/pigment-css-next-app/src/app/material-ui/page.tsx @@ -1,4 +1,3 @@ -// eslint-disable-next-line @typescript-eslint/no-unused-vars import * as React from 'react'; import Link from 'next/link'; import fs from 'fs/promises'; diff --git a/apps/pigment-css-vite-app/package.json b/apps/pigment-css-vite-app/package.json index 9b9486c227050f..0743d13dd85b00 100644 --- a/apps/pigment-css-vite-app/package.json +++ b/apps/pigment-css-vite-app/package.json @@ -16,7 +16,7 @@ "@mui/system": "workspace:^", "@mui/utils": "workspace:^", "clsx": "^2.1.1", - "@playwright/test": "^1.52.0", + "@playwright/test": "^1.54.1", "react": "^19.1.0", "react-dom": "^19.1.0", "react-error-boundary": "^6.0.0", @@ -27,15 +27,16 @@ "@babel/preset-react": "^7.27.1", "@babel/preset-typescript": "^7.27.1", "@pigment-css/vite-plugin": "0.0.30", - "@types/react": "^19.1.6", - "@types/react-dom": "^19.1.5", + "@testing-library/react": "^16.3.0", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", "@types/webfontloader": "^1.6.38", - "@vitejs/plugin-react": "^4.5.0", - "postcss": "^8.5.4", + "@vitejs/plugin-react": "^4.7.0", + "postcss": "^8.5.6", "postcss-combine-media-query": "^2.0.0", - "vite": "5.4.18", - "vite-plugin-node-polyfills": "0.23.0", - "vite-plugin-pages": "^0.33.0" + "vite": "5.4.19", + "vite-plugin-node-polyfills": "0.24.0", + "vite-plugin-pages": "^0.33.1" }, "nx": { "targets": { diff --git a/apps/pigment-css-vite-app/src/Slider/ZeroSlider.test.jsx b/apps/pigment-css-vite-app/src/Slider/ZeroSlider.test.jsx index ee5cfef2cd2b82..27d8d3af5dcc45 100644 --- a/apps/pigment-css-vite-app/src/Slider/ZeroSlider.test.jsx +++ b/apps/pigment-css-vite-app/src/Slider/ZeroSlider.test.jsx @@ -1,5 +1,4 @@ -/* eslint-disable react/jsx-filename-extension */ -import * as React from 'react'; +/* globals expect */ import { render } from '@testing-library/react'; import Slider from './ZeroSlider'; diff --git a/dangerfile.js b/dangerfile.js index 397cc81a41b8af..ac1c2c4bf612bb 100644 --- a/dangerfile.js +++ b/dangerfile.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/no-unresolved const tsx = require('tsx/cjs/api'); // danger uses babelify under the hood. The implementation is buggy and fails on our diff --git a/docs/.env b/docs/.env index 9908147ec3fb12..add8ffc483eaa6 100644 --- a/docs/.env +++ b/docs/.env @@ -1 +1 @@ -FEEDBACK_URL=https://hgvi836wi8.execute-api.us-east-1.amazonaws.com \ No newline at end of file +FEEDBACK_URL=https://hgvi836wi8.execute-api.us-east-1.amazonaws.com diff --git a/docs/babel.config.js b/docs/babel.config.js index 98e6407f1a83a2..f99552fdd02263 100644 --- a/docs/babel.config.js +++ b/docs/babel.config.js @@ -1,24 +1,9 @@ -const fse = require('fs-extra'); - -const { version: transformRuntimeVersion } = fse.readJSONSync( - require.resolve('@babel/runtime-corejs2/package.json'), -); - module.exports = { assumptions: { noDocumentAll: true, setSpreadProperties: true, }, - presets: [ - // backport of https://github.com/vercel/next.js/pull/9511 - [ - 'next/babel', - { - 'preset-react': { runtime: 'automatic' }, - 'transform-runtime': { corejs: 2, version: transformRuntimeVersion }, - }, - ], - ], + presets: ['next/babel'], plugins: ['babel-plugin-optimize-clsx'], ignore: [/@babel[\\|/]runtime/], // Fix a Windows issue. env: { diff --git a/docs/data/about/teamMembers.json b/docs/data/about/teamMembers.json index 0e338f2d4a40b8..e0f2f2f7832ada 100644 --- a/docs/data/about/teamMembers.json +++ b/docs/data/about/teamMembers.json @@ -201,7 +201,7 @@ { "name": "Raffaella Luzi", "title": "Head of Operations", - "location": "Roma, Italy", + "location": "Rome, Italy", "locationCountry": "it", "about": "NYT crossword 📝 in one hand and a croissant 🥐 in the other.", "github": "rluzists1" @@ -327,5 +327,14 @@ "about": "Learning 📚, my dog 🐶 and Japanese culture 🇯🇵.", "twitter": "rita_codes", "github": "rita-codes" + }, + { + "name": "Connor Davis", + "title": "Software Engineer — Core", + "location": "New York City, US", + "locationCountry": "us", + "about": "Community gardener, non-profit organizer, and nature enthusiast.", + "twitter": "connordav_is", + "github": "dav-is" } ] diff --git a/docs/data/joy/components/accordion/accordion.md b/docs/data/joy/components/accordion/accordion.md index c1277c312680af..001b36fdab64d0 100644 --- a/docs/data/joy/components/accordion/accordion.md +++ b/docs/data/joy/components/accordion/accordion.md @@ -4,7 +4,6 @@ title: React Accordion component components: Accordion, AccordionDetails, AccordionGroup, AccordionSummary githubLabel: 'component: accordion' waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/accordion/ -unstyled: https://base-ui.com/react/components/accordion --- # Accordion diff --git a/docs/data/joy/components/autocomplete/GitHubLabel.js b/docs/data/joy/components/autocomplete/GitHubLabel.js index 44fa83632f59a2..4aad3258c58ebd 100644 --- a/docs/data/joy/components/autocomplete/GitHubLabel.js +++ b/docs/data/joy/components/autocomplete/GitHubLabel.js @@ -55,7 +55,6 @@ export default function GitHubLabel() { return ( - {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} - {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} {flags.length > 0 && ( - // eslint-disable-next-line jsx-a11y/anchor-is-valid - {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} - {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} -{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} - {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} - {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} Date Status Customer + {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} diff --git a/docs/data/joy/getting-started/templates/profile-dashboard/components/DropZone.tsx b/docs/data/joy/getting-started/templates/profile-dashboard/components/DropZone.tsx index 480e0c228e7c99..1c1b6a025cb706 100644 --- a/docs/data/joy/getting-started/templates/profile-dashboard/components/DropZone.tsx +++ b/docs/data/joy/getting-started/templates/profile-dashboard/components/DropZone.tsx @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react'; import Card, { CardProps } from '@mui/joy/Card'; import Link from '@mui/joy/Link'; diff --git a/docs/data/material/components/.eslintrc.js b/docs/data/material/components/.eslintrc.js deleted file mode 100644 index 4eb66e683b1fb8..00000000000000 --- a/docs/data/material/components/.eslintrc.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - rules: { - // useful for interactions feedback - 'no-console': ['off', { allow: ['info'] }], - // not very friendly to prop forwarding - 'react/jsx-handler-names': 'off', - }, -}; diff --git a/docs/data/material/components/app-bar/DashboardLayoutBasic.js b/docs/data/material/components/app-bar/DashboardLayoutBasic.js deleted file mode 100644 index 0e6a790fa28959..00000000000000 --- a/docs/data/material/components/app-bar/DashboardLayoutBasic.js +++ /dev/null @@ -1,152 +0,0 @@ -import * as React from 'react'; -import { createTheme, styled } from '@mui/material/styles'; -import DashboardIcon from '@mui/icons-material/Dashboard'; -import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; -import BarChartIcon from '@mui/icons-material/BarChart'; -import DescriptionIcon from '@mui/icons-material/Description'; -import LayersIcon from '@mui/icons-material/Layers'; -import { AppProvider } from '@toolpad/core/AppProvider'; -import { DashboardLayout } from '@toolpad/core/DashboardLayout'; -import { PageContainer } from '@toolpad/core/PageContainer'; -import Grid from '@mui/material/Grid'; - -const NAVIGATION = [ - { - kind: 'header', - title: 'Main items', - }, - { - segment: 'dashboard', - title: 'Dashboard', - icon: , - }, - { - segment: 'orders', - title: 'Orders', - icon: , - }, - { - kind: 'divider', - }, - { - kind: 'header', - title: 'Analytics', - }, - { - segment: 'reports', - title: 'Reports', - icon: , - children: [ - { - segment: 'sales', - title: 'Sales', - icon: , - }, - { - segment: 'traffic', - title: 'Traffic', - icon: , - }, - ], - }, - { - segment: 'integrations', - title: 'Integrations', - icon: , - }, -]; - -const demoTheme = createTheme({ - colorSchemes: { light: true, dark: true }, - cssVariables: { - colorSchemeSelector: 'class', - }, - breakpoints: { - values: { - xs: 0, - sm: 600, - md: 600, - lg: 1200, - xl: 1536, - }, - }, -}); - -function useDemoRouter(initialPath) { - const [pathname, setPathname] = React.useState(initialPath); - - const router = React.useMemo(() => { - return { - pathname, - searchParams: new URLSearchParams(), - navigate: (path) => setPathname(String(path)), - }; - }, [pathname]); - - return router; -} - -const Skeleton = styled('div')(({ theme, height }) => ({ - backgroundColor: theme.palette.action.hover, - borderRadius: theme.shape.borderRadius, - height, - content: '" "', -})); - -export default function DashboardLayoutBasic(props) { - const { window } = props; - - const router = useDemoRouter('/dashboard'); - - // Remove this const when copying and pasting into your project. - const demoWindow = window ? window() : undefined; - - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/docs/data/material/components/app-bar/DashboardLayoutBasic.tsx b/docs/data/material/components/app-bar/DashboardLayoutBasic.tsx deleted file mode 100644 index 8e5b2c7a589f69..00000000000000 --- a/docs/data/material/components/app-bar/DashboardLayoutBasic.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import * as React from 'react'; -import { createTheme, styled } from '@mui/material/styles'; -import DashboardIcon from '@mui/icons-material/Dashboard'; -import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; -import BarChartIcon from '@mui/icons-material/BarChart'; -import DescriptionIcon from '@mui/icons-material/Description'; -import LayersIcon from '@mui/icons-material/Layers'; -import { AppProvider, Navigation, Router } from '@toolpad/core/AppProvider'; -import { DashboardLayout } from '@toolpad/core/DashboardLayout'; -import { PageContainer } from '@toolpad/core/PageContainer'; -import Grid from '@mui/material/Grid'; - -const NAVIGATION: Navigation = [ - { - kind: 'header', - title: 'Main items', - }, - { - segment: 'dashboard', - title: 'Dashboard', - icon: , - }, - { - segment: 'orders', - title: 'Orders', - icon: , - }, - { - kind: 'divider', - }, - { - kind: 'header', - title: 'Analytics', - }, - { - segment: 'reports', - title: 'Reports', - icon: , - children: [ - { - segment: 'sales', - title: 'Sales', - icon: , - }, - { - segment: 'traffic', - title: 'Traffic', - icon: , - }, - ], - }, - { - segment: 'integrations', - title: 'Integrations', - icon: , - }, -]; - -const demoTheme = createTheme({ - colorSchemes: { light: true, dark: true }, - cssVariables: { - colorSchemeSelector: 'class', - }, - breakpoints: { - values: { - xs: 0, - sm: 600, - md: 600, - lg: 1200, - xl: 1536, - }, - }, -}); - -function useDemoRouter(initialPath: string): Router { - const [pathname, setPathname] = React.useState(initialPath); - - const router = React.useMemo(() => { - return { - pathname, - searchParams: new URLSearchParams(), - navigate: (path: string | URL) => setPathname(String(path)), - }; - }, [pathname]); - - return router; -} - -const Skeleton = styled('div')<{ height: number }>(({ theme, height }) => ({ - backgroundColor: theme.palette.action.hover, - borderRadius: theme.shape.borderRadius, - height, - content: '" "', -})); - -export default function DashboardLayoutBasic(props: any) { - const { window } = props; - - const router = useDemoRouter('/dashboard'); - - // Remove this const when copying and pasting into your project. - const demoWindow = window ? window() : undefined; - - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/docs/data/material/components/app-bar/app-bar.md b/docs/data/material/components/app-bar/app-bar.md index c50927f82a20a1..2fdafabb2cfab4 100644 --- a/docs/data/material/components/app-bar/app-bar.md +++ b/docs/data/material/components/app-bar/app-bar.md @@ -153,11 +153,3 @@ Following the [Material Design guidelines](https://m2.material.io/design/color/d You can override this behavior by setting the `enableColorOnDark` prop to `true`. {{"demo": "EnableColorOnDarkAppBar.js", "bg": true}} - -## Experimental APIs - Toolpad - -### Dashboard Layout - -The [DashboardLayout](https://mui.com/toolpad/core/react-dashboard-layout/) component from `@toolpad/core` is the starting point for dashboarding applications. It takes care of application layout, theming, navigation, and more. An example usage of this component: - -{{"demo": "DashboardLayoutBasic.js", "height": 400, "iframe": true, "defaultExpanded": false}} diff --git a/docs/data/material/components/badges/badges.md b/docs/data/material/components/badges/badges.md index 99d9152dfc5279..18dc6f04d404e2 100644 --- a/docs/data/material/components/badges/badges.md +++ b/docs/data/material/components/badges/badges.md @@ -3,7 +3,6 @@ productId: material-ui title: React Badge component components: Badge githubLabel: 'component: badge' -unstyled: /base-ui/react-badge/ githubSource: packages/mui-material/src/Badge --- diff --git a/docs/data/material/components/breadcrumbs/CollapsedBreadcrumbs.js b/docs/data/material/components/breadcrumbs/CollapsedBreadcrumbs.js index 3e460a24dc008f..389e158df37931 100644 --- a/docs/data/material/components/breadcrumbs/CollapsedBreadcrumbs.js +++ b/docs/data/material/components/breadcrumbs/CollapsedBreadcrumbs.js @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react'; import Breadcrumbs from '@mui/material/Breadcrumbs'; import Typography from '@mui/material/Typography'; diff --git a/docs/data/material/components/breadcrumbs/CollapsedBreadcrumbs.tsx b/docs/data/material/components/breadcrumbs/CollapsedBreadcrumbs.tsx index fb1f1107089fdb..db8ced40240ecd 100644 --- a/docs/data/material/components/breadcrumbs/CollapsedBreadcrumbs.tsx +++ b/docs/data/material/components/breadcrumbs/CollapsedBreadcrumbs.tsx @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react'; import Breadcrumbs from '@mui/material/Breadcrumbs'; import Typography from '@mui/material/Typography'; diff --git a/docs/data/material/components/breadcrumbs/PageContainerBasic.js b/docs/data/material/components/breadcrumbs/PageContainerBasic.js deleted file mode 100644 index edcddf08fcb9c7..00000000000000 --- a/docs/data/material/components/breadcrumbs/PageContainerBasic.js +++ /dev/null @@ -1,121 +0,0 @@ -import * as React from 'react'; -import { styled, createTheme } from '@mui/material/styles'; -import DashboardIcon from '@mui/icons-material/Dashboard'; -import { AppProvider } from '@toolpad/core/AppProvider'; -import { - PageContainer, - PageHeader, - PageHeaderToolbar, -} from '@toolpad/core/PageContainer'; -import Grid from '@mui/material/Grid'; -import Paper from '@mui/material/Paper'; -import Stack from '@mui/material/Stack'; -import Button from '@mui/material/Button'; -import PrintIcon from '@mui/icons-material/Print'; -import DownloadIcon from '@mui/icons-material/Download'; - -const NAVIGATION = [ - { segment: 'inbox', title: 'Inbox' }, - { - segment: 'inbox/all', - title: 'All', - icon: , - }, -]; - -function useDemoRouter(initialPath) { - const [pathname, setPathname] = React.useState(initialPath); - - const router = React.useMemo(() => { - return { - pathname, - searchParams: new URLSearchParams(), - navigate: (path) => setPathname(String(path)), - }; - }, [pathname]); - - return router; -} - -const Skeleton = styled('div')(({ theme, height }) => ({ - backgroundColor: (theme.vars || theme).palette.action.hover, - borderRadius: (theme.vars || theme).shape.borderRadius, - height, - content: '" "', -})); - -function CustomPageToolbar() { - return ( - - - - - - - ); -} - -function CustomPageHeader() { - return ; -} - -const demoTheme = createTheme({ - colorSchemes: { light: true, dark: true }, -}); - -export default function PageContainerBasic(props) { - const { window } = props; - const router = useDemoRouter('/inbox/all'); - // Remove this const when copying and pasting into your project. - const demoWindow = window ? window() : undefined; - - return ( - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/docs/data/material/components/breadcrumbs/PageContainerBasic.tsx b/docs/data/material/components/breadcrumbs/PageContainerBasic.tsx deleted file mode 100644 index 32d6492edfc696..00000000000000 --- a/docs/data/material/components/breadcrumbs/PageContainerBasic.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import * as React from 'react'; -import { styled, createTheme } from '@mui/material/styles'; -import DashboardIcon from '@mui/icons-material/Dashboard'; -import { AppProvider, Navigation, Router } from '@toolpad/core/AppProvider'; -import { - PageContainer, - PageHeader, - PageHeaderToolbar, -} from '@toolpad/core/PageContainer'; -import Grid from '@mui/material/Grid'; -import Paper from '@mui/material/Paper'; -import Stack from '@mui/material/Stack'; -import Button from '@mui/material/Button'; -import PrintIcon from '@mui/icons-material/Print'; -import DownloadIcon from '@mui/icons-material/Download'; - -const NAVIGATION: Navigation = [ - { segment: 'inbox', title: 'Inbox' }, - { - segment: 'inbox/all', - title: 'All', - icon: , - }, -]; - -function useDemoRouter(initialPath: string): Router { - const [pathname, setPathname] = React.useState(initialPath); - - const router = React.useMemo(() => { - return { - pathname, - searchParams: new URLSearchParams(), - navigate: (path: string | URL) => setPathname(String(path)), - }; - }, [pathname]); - - return router; -} - -const Skeleton = styled('div')<{ height: number }>(({ theme, height }) => ({ - backgroundColor: (theme.vars || theme).palette.action.hover, - borderRadius: (theme.vars || theme).shape.borderRadius, - height, - content: '" "', -})); - -function CustomPageToolbar() { - return ( - - - - - - - ); -} - -function CustomPageHeader() { - return ; -} - -const demoTheme = createTheme({ - colorSchemes: { light: true, dark: true }, -}); - -export default function PageContainerBasic(props: any) { - const { window } = props; - const router = useDemoRouter('/inbox/all'); - // Remove this const when copying and pasting into your project. - const demoWindow = window ? window() : undefined; - - return ( - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/docs/data/material/components/breadcrumbs/breadcrumbs.md b/docs/data/material/components/breadcrumbs/breadcrumbs.md index 65ec66134d8182..986ecf3b16b3aa 100644 --- a/docs/data/material/components/breadcrumbs/breadcrumbs.md +++ b/docs/data/material/components/breadcrumbs/breadcrumbs.md @@ -65,11 +65,3 @@ The accessibility of this component relies on: - The set of links is structured using an ordered list (`
    ` element). - To prevent screen reader announcement of the visual separators between links, they are hidden with `aria-hidden`. - A nav element labeled with `aria-label` identifies the structure as a breadcrumb trail and makes it a navigation landmark so that it is easy to locate. - -## Experimental APIs - Toolpad - -### Page Container - -The [PageContainer](https://mui.com/toolpad/core/react-page-container/) component in `@toolpad/core` is the ideal wrapper for the content of your dashboard. It makes the Material UI Container navigation-aware and extends it with page title, breadcrumbs, actions, and more. - -{{"demo": "PageContainerBasic.js", "height": 400, "bg": "inline", "defaultExpanded": false}} diff --git a/docs/data/material/components/buttons/buttons.md b/docs/data/material/components/buttons/buttons.md index 0b1b19fe71ff27..6baf09b775235b 100644 --- a/docs/data/material/components/buttons/buttons.md +++ b/docs/data/material/components/buttons/buttons.md @@ -5,7 +5,6 @@ components: Button, IconButton, ButtonBase materialDesign: https://m2.material.io/components/buttons githubLabel: 'component: button' waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/button/ -unstyled: /base-ui/react-button/ githubSource: packages/mui-material/src/Button --- diff --git a/docs/data/material/components/container/container.md b/docs/data/material/components/container/container.md index 44a7130f5f19bf..e8ac8f736ae5bb 100644 --- a/docs/data/material/components/container/container.md +++ b/docs/data/material/components/container/container.md @@ -34,11 +34,3 @@ The max-width matches the min-width of the current breakpoint. ```jsx ``` - -## Experimental APIs - Toolpad - -### Page Container - -The [PageContainer](https://mui.com/toolpad/core/react-page-container/) component in `@toolpad/core` is the ideal wrapper for the content of your dashboard. It makes the Material UI Container navigation-aware and extends it with page title, breadcrumbs, actions, and more. - -{{"demo": "../breadcrumbs/PageContainerBasic.js", "height": 400, "bg": "inline", "defaultExpanded": false}} diff --git a/docs/data/material/components/dialogs/FormDialog.js b/docs/data/material/components/dialogs/FormDialog.js index 4366550268d90f..c3c1996ea77bfb 100644 --- a/docs/data/material/components/dialogs/FormDialog.js +++ b/docs/data/material/components/dialogs/FormDialog.js @@ -18,49 +18,46 @@ export default function FormDialog() { setOpen(false); }; + const handleSubmit = (event) => { + event.preventDefault(); + const formData = new FormData(event.currentTarget); + const formJson = Object.fromEntries(formData.entries()); + const email = formJson.email; + console.log(email); + handleClose(); + }; + return ( - { - event.preventDefault(); - const formData = new FormData(event.currentTarget); - const formJson = Object.fromEntries(formData.entries()); - const email = formJson.email; - console.log(email); - handleClose(); - }, - }, - }} - > + Subscribe To subscribe to this website, please enter your email address here. We will send updates occasionally. - +
    + +
    - +
    diff --git a/docs/data/material/components/dialogs/FormDialog.tsx b/docs/data/material/components/dialogs/FormDialog.tsx index e5830e9d430d9b..1071beb9faf713 100644 --- a/docs/data/material/components/dialogs/FormDialog.tsx +++ b/docs/data/material/components/dialogs/FormDialog.tsx @@ -18,49 +18,46 @@ export default function FormDialog() { setOpen(false); }; + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + const formData = new FormData(event.currentTarget); + const formJson = Object.fromEntries((formData as any).entries()); + const email = formJson.email; + console.log(email); + handleClose(); + }; + return ( - ) => { - event.preventDefault(); - const formData = new FormData(event.currentTarget); - const formJson = Object.fromEntries((formData as any).entries()); - const email = formJson.email; - console.log(email); - handleClose(); - }, - }, - }} - > + Subscribe To subscribe to this website, please enter your email address here. We will send updates occasionally. - +
    + +
    - +
    diff --git a/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.js b/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.js deleted file mode 100644 index 45c5878821cf2a..00000000000000 --- a/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.js +++ /dev/null @@ -1,115 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import { DialogsProvider, useDialogs } from '@toolpad/core/useDialogs'; -import Button from '@mui/material/Button'; -import Dialog from '@mui/material/Dialog'; -import Alert from '@mui/material/Alert'; -import DialogTitle from '@mui/material/DialogTitle'; -import DialogContent from '@mui/material/DialogContent'; -import DialogActions from '@mui/material/DialogActions'; - -function MyCustomDialog({ open, onClose, payload }) { - return ( - onClose()}> - Custom Error Handler - - - {`An error occurred while deleting item "${payload.id}":`} -
    {payload.error}
    -
    -
    - - - -
    - ); -} - -MyCustomDialog.propTypes = { - /** - * A function to call when the dialog should be closed. If the dialog has a return - * value, it should be passed as an argument to this function. You should use the promise - * that is returned to show a loading state while the dialog is performing async actions - * on close. - * @param result The result to return from the dialog. - * @returns A promise that resolves when the dialog can be fully closed. - */ - onClose: PropTypes.func.isRequired, - /** - * Whether the dialog is open. - */ - open: PropTypes.bool.isRequired, - /** - * The payload that was passed when the dialog was opened. - */ - payload: PropTypes.shape({ - error: PropTypes.string, - id: PropTypes.string, - }).isRequired, -}; - -const mockApiDelete = async (id) => { - return new Promise((resolve, reject) => { - setTimeout(() => { - if (!id) { - reject(new Error('ID is required')); - } else if (parseInt(id, 10) % 2 === 0) { - console.log('id', parseInt(id, 10)); - resolve(true); - } else if (parseInt(id, 10) % 2 === 1) { - reject(new Error('Can not delete odd numbered elements')); - } else if (Number.isNaN(parseInt(id, 10))) { - reject(new Error('ID must be a number')); - } else { - reject(new Error('Unknown error')); - } - }, 1000); - }); -}; - -function DemoContent() { - const dialogs = useDialogs(); - const [isDeleting, setIsDeleting] = React.useState(false); - - const handleDelete = async () => { - const id = await dialogs.prompt('Enter the ID to delete', { - okText: 'Delete', - cancelText: 'Cancel', - }); - - if (id) { - const deleteConfirmed = await dialogs.confirm( - `Are you sure you want to delete "${id}"?`, - ); - if (deleteConfirmed) { - try { - setIsDeleting(true); - await mockApiDelete(id); - dialogs.alert('Deleted!'); - } catch (error) { - const message = error instanceof Error ? error.message : 'Unknown error'; - await dialogs.open(MyCustomDialog, { id, error: message }); - } finally { - setIsDeleting(false); - } - } - } - }; - return ( -
    -
    - -
    -
    - ); -} - -export default function ToolpadDialogsNoSnap() { - return ( - - - - ); -} diff --git a/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.tsx b/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.tsx deleted file mode 100644 index 1d6aa7dacc434f..00000000000000 --- a/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import * as React from 'react'; -import { DialogsProvider, useDialogs, DialogProps } from '@toolpad/core/useDialogs'; -import Button from '@mui/material/Button'; -import Dialog from '@mui/material/Dialog'; -import Alert from '@mui/material/Alert'; -import DialogTitle from '@mui/material/DialogTitle'; -import DialogContent from '@mui/material/DialogContent'; -import DialogActions from '@mui/material/DialogActions'; - -interface DeleteError { - id: string | null; - error: string | null; -} - -function MyCustomDialog({ open, onClose, payload }: DialogProps) { - return ( - onClose()}> - Custom Error Handler - - - {`An error occurred while deleting item "${payload.id}":`} -
    {payload.error}
    -
    -
    - - - -
    - ); -} - -const mockApiDelete = async (id: string | null) => { - return new Promise((resolve, reject) => { - setTimeout(() => { - if (!id) { - reject(new Error('ID is required')); - } else if (parseInt(id, 10) % 2 === 0) { - console.log('id', parseInt(id, 10)); - resolve(true); - } else if (parseInt(id, 10) % 2 === 1) { - reject(new Error('Can not delete odd numbered elements')); - } else if (Number.isNaN(parseInt(id, 10))) { - reject(new Error('ID must be a number')); - } else { - reject(new Error('Unknown error')); - } - }, 1000); - }); -}; - -function DemoContent() { - const dialogs = useDialogs(); - const [isDeleting, setIsDeleting] = React.useState(false); - - const handleDelete = async () => { - const id = await dialogs.prompt('Enter the ID to delete', { - okText: 'Delete', - cancelText: 'Cancel', - }); - - if (id) { - const deleteConfirmed = await dialogs.confirm( - `Are you sure you want to delete "${id}"?`, - ); - if (deleteConfirmed) { - try { - setIsDeleting(true); - await mockApiDelete(id); - dialogs.alert('Deleted!'); - } catch (error) { - const message = error instanceof Error ? error.message : 'Unknown error'; - await dialogs.open(MyCustomDialog, { id, error: message }); - } finally { - setIsDeleting(false); - } - } - } - }; - return ( -
    -
    - -
    -
    - ); -} - -export default function ToolpadDialogsNoSnap() { - return ( - - - - ); -} diff --git a/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.tsx.preview b/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.tsx.preview deleted file mode 100644 index a552fd4edf0f98..00000000000000 --- a/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.tsx.preview +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/data/material/components/dialogs/dialogs.md b/docs/data/material/components/dialogs/dialogs.md index fa0a64e9593ada..e6997cabea1e56 100644 --- a/docs/data/material/components/dialogs/dialogs.md +++ b/docs/data/material/components/dialogs/dialogs.md @@ -167,45 +167,3 @@ The package [`material-ui-confirm`](https://github.com/jonatanklosko/material-ui ## Accessibility Follow the [Modal accessibility section](/material-ui/react-modal/#accessibility). - -## Experimental APIs - Toolpad - -### useDialogs - -You can create and manipulate dialogs imperatively with the [`useDialogs()`](https://mui.com/toolpad/core/react-use-dialogs/) API in `@toolpad/core`. This hook handles - -- state management for opening and closing dialogs -- passing data to dialogs and receiving results back from them -- stacking multiple dialogs -- themed, asynchronous versions of `window.alert()`, `window.confirm()` and `window.prompt()` - -The following example demonstrates some of these features: - -{{"demo": "ToolpadDialogsNoSnap.js", "defaultCodeOpen": false}} - -```tsx -const handleDelete = async () => { - const id = await dialogs.prompt('Enter the ID to delete', { - okText: 'Delete', - cancelText: 'Cancel', - }); - - if (id) { - const deleteConfirmed = await dialogs.confirm( - `Are you sure you want to delete "${id}"?`, - ); - if (deleteConfirmed) { - try { - setIsDeleting(true); - await mockApiDelete(id); - dialogs.alert('Deleted!'); - } catch (error) { - const message = error instanceof Error ? error.message : 'Unknown error'; - await dialogs.open(MyCustomDialog, { id, error: message }); - } finally { - setIsDeleting(false); - } - } - } -}; -``` diff --git a/docs/data/material/components/drawers/drawers.md b/docs/data/material/components/drawers/drawers.md index ec51831dccbdde..a1bf5a3ca922db 100644 --- a/docs/data/material/components/drawers/drawers.md +++ b/docs/data/material/components/drawers/drawers.md @@ -135,11 +135,3 @@ Apps focused on information consumption that use a left-to-right hierarchy. Apps focused on productivity that require balance across the screen. {{"demo": "ClippedDrawer.js", "iframe": true}} - -## Experimental APIs - Toolpad - -### Dashboard Layout - -The [DashboardLayout](https://mui.com/toolpad/core/react-dashboard-layout/) component from `@toolpad/core` is the starting point for dashboarding applications. It takes care of application layout, theming, navigation, and more. An example usage of this component: - -{{"demo": "../app-bar/DashboardLayoutBasic.js", "height": 400, "iframe": true, "isolated": true, "bg": "inline", "defaultExpanded": false}} diff --git a/docs/data/material/components/init-color-scheme-script/init-color-scheme-script.md b/docs/data/material/components/init-color-scheme-script/init-color-scheme-script.md index fc2b2ea6b5f267..9af5a16268ba7c 100644 --- a/docs/data/material/components/init-color-scheme-script/init-color-scheme-script.md +++ b/docs/data/material/components/init-color-scheme-script/init-color-scheme-script.md @@ -49,7 +49,7 @@ export default function RootLayout(props: { children: React.ReactNode }) { return ( - + {props.children} @@ -70,7 +70,7 @@ export default function MyDocument(props) { {/* tags */} - +
    diff --git a/docs/data/material/components/links/ButtonLink.js b/docs/data/material/components/links/ButtonLink.js index 532f634c918188..be1e16b3e8a551 100644 --- a/docs/data/material/components/links/ButtonLink.js +++ b/docs/data/material/components/links/ButtonLink.js @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react'; import Link from '@mui/material/Link'; diff --git a/docs/data/material/components/links/ButtonLink.tsx b/docs/data/material/components/links/ButtonLink.tsx index 532f634c918188..be1e16b3e8a551 100644 --- a/docs/data/material/components/links/ButtonLink.tsx +++ b/docs/data/material/components/links/ButtonLink.tsx @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react'; import Link from '@mui/material/Link'; diff --git a/docs/data/material/components/links/Links.js b/docs/data/material/components/links/Links.js index 213b8d908fa850..44d3be3712deee 100644 --- a/docs/data/material/components/links/Links.js +++ b/docs/data/material/components/links/Links.js @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react'; import Box from '@mui/material/Box'; import Link from '@mui/material/Link'; diff --git a/docs/data/material/components/links/Links.tsx b/docs/data/material/components/links/Links.tsx index 5628edf181c80b..eefeeb0cf82bae 100644 --- a/docs/data/material/components/links/Links.tsx +++ b/docs/data/material/components/links/Links.tsx @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react'; import Box from '@mui/material/Box'; import Link from '@mui/material/Link'; diff --git a/docs/data/material/components/links/UnderlineLink.js b/docs/data/material/components/links/UnderlineLink.js index 5a4b72493274bb..5fe1efc0f3ce4f 100644 --- a/docs/data/material/components/links/UnderlineLink.js +++ b/docs/data/material/components/links/UnderlineLink.js @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react'; import Box from '@mui/material/Box'; import Link from '@mui/material/Link'; diff --git a/docs/data/material/components/links/UnderlineLink.tsx b/docs/data/material/components/links/UnderlineLink.tsx index 6f3a596be35cb3..7b3b274e6c7576 100644 --- a/docs/data/material/components/links/UnderlineLink.tsx +++ b/docs/data/material/components/links/UnderlineLink.tsx @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react'; import Box from '@mui/material/Box'; import Link from '@mui/material/Link'; diff --git a/docs/data/material/components/menus/CustomizedMenus.js b/docs/data/material/components/menus/CustomizedMenus.js index 8e3e96eccc5757..a3bb8d6bc19c45 100644 --- a/docs/data/material/components/menus/CustomizedMenus.js +++ b/docs/data/material/components/menus/CustomizedMenus.js @@ -39,6 +39,9 @@ const StyledMenu = styled((props) => ( fontSize: 18, color: theme.palette.text.secondary, marginRight: theme.spacing(1.5), + ...theme.applyStyles('dark', { + color: 'inherit', + }), }, '&:active': { backgroundColor: alpha( diff --git a/docs/data/material/components/menus/CustomizedMenus.tsx b/docs/data/material/components/menus/CustomizedMenus.tsx index 9dc8baaa9fb576..1f29a6689f1067 100644 --- a/docs/data/material/components/menus/CustomizedMenus.tsx +++ b/docs/data/material/components/menus/CustomizedMenus.tsx @@ -39,6 +39,9 @@ const StyledMenu = styled((props: MenuProps) => ( fontSize: 18, color: theme.palette.text.secondary, marginRight: theme.spacing(1.5), + ...theme.applyStyles('dark', { + color: 'inherit', + }), }, '&:active': { backgroundColor: alpha( diff --git a/docs/data/material/components/menus/GroupedMenu.js b/docs/data/material/components/menus/GroupedMenu.js index 675f63c27b34db..23106a07297434 100644 --- a/docs/data/material/components/menus/GroupedMenu.js +++ b/docs/data/material/components/menus/GroupedMenu.js @@ -3,6 +3,11 @@ import Button from '@mui/material/Button'; import ListSubheader from '@mui/material/ListSubheader'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; +import { styled } from '@mui/material/styles'; + +const StyledListHeader = styled(ListSubheader)({ + backgroundImage: 'var(--Paper-overlay)', +}); export default function GroupedMenu() { const [anchorEl, setAnchorEl] = React.useState(null); @@ -33,13 +38,16 @@ export default function GroupedMenu() { slotProps={{ list: { 'aria-labelledby': 'basic-button', + sx: { + py: 0, + }, }, }} > - Category 1 + Category 1 Option 1 Option 2 - Category 2 + Category 2 Option 3 Option 4 diff --git a/docs/data/material/components/menus/GroupedMenu.tsx b/docs/data/material/components/menus/GroupedMenu.tsx index b4edf3087ab1d3..f76e923ab4417e 100644 --- a/docs/data/material/components/menus/GroupedMenu.tsx +++ b/docs/data/material/components/menus/GroupedMenu.tsx @@ -3,6 +3,11 @@ import Button from '@mui/material/Button'; import ListSubheader from '@mui/material/ListSubheader'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; +import { styled } from '@mui/material/styles'; + +const StyledListHeader = styled(ListSubheader)({ + backgroundImage: 'var(--Paper-overlay)', +}); export default function GroupedMenu() { const [anchorEl, setAnchorEl] = React.useState(null); @@ -33,13 +38,16 @@ export default function GroupedMenu() { slotProps={{ list: { 'aria-labelledby': 'basic-button', + sx: { + py: 0, + }, }, }} > - Category 1 + Category 1 Option 1 Option 2 - Category 2 + Category 2 Option 3 Option 4 diff --git a/docs/data/material/components/menus/menus.md b/docs/data/material/components/menus/menus.md index d0ee40788b332f..f7166b63c2c5ca 100644 --- a/docs/data/material/components/menus/menus.md +++ b/docs/data/material/components/menus/menus.md @@ -5,7 +5,6 @@ components: Menu, MenuItem, MenuList, ClickAwayListener, Popover, Popper githubLabel: 'component: menu' materialDesign: https://m2.material.io/components/menus waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/ -unstyled: /base-ui/react-menu/ githubSource: packages/mui-material/src/Menu --- diff --git a/docs/data/material/components/modal/SpringModal.js b/docs/data/material/components/modal/SpringModal.js index 606c738939ac38..06faa8dd1d4708 100644 --- a/docs/data/material/components/modal/SpringModal.js +++ b/docs/data/material/components/modal/SpringModal.js @@ -33,7 +33,6 @@ const Fade = React.forwardRef(function Fade(props, ref) { }); return ( - // @ts-expect-error https://github.com/pmndrs/react-spring/issues/2341 {React.cloneElement(children, { onClick })} diff --git a/docs/data/material/components/modal/SpringModal.tsx b/docs/data/material/components/modal/SpringModal.tsx index bd62c4f2e6f96b..fb9b3687d2f1b1 100644 --- a/docs/data/material/components/modal/SpringModal.tsx +++ b/docs/data/material/components/modal/SpringModal.tsx @@ -41,7 +41,6 @@ const Fade = React.forwardRef(function Fade(props, re }); return ( - // @ts-expect-error https://github.com/pmndrs/react-spring/issues/2341 {React.cloneElement(children, { onClick })} diff --git a/docs/data/material/components/modal/modal.md b/docs/data/material/components/modal/modal.md index aa0f6c75f912b3..b3e84f2670141b 100644 --- a/docs/data/material/components/modal/modal.md +++ b/docs/data/material/components/modal/modal.md @@ -4,7 +4,6 @@ title: React Modal component components: Modal githubLabel: 'component: modal' waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/ -unstyled: /base-ui/react-modal/ githubSource: packages/mui-material/src/Modal --- diff --git a/docs/data/material/components/popper/SpringPopper.js b/docs/data/material/components/popper/SpringPopper.js index 77055ed67b346d..c86ecf815a0454 100644 --- a/docs/data/material/components/popper/SpringPopper.js +++ b/docs/data/material/components/popper/SpringPopper.js @@ -22,7 +22,6 @@ const Fade = React.forwardRef(function Fade(props, ref) { }); return ( - // @ts-expect-error https://github.com/pmndrs/react-spring/issues/2341 {children} diff --git a/docs/data/material/components/popper/SpringPopper.tsx b/docs/data/material/components/popper/SpringPopper.tsx index cf96081e340e5b..636bedcfc229c1 100644 --- a/docs/data/material/components/popper/SpringPopper.tsx +++ b/docs/data/material/components/popper/SpringPopper.tsx @@ -28,7 +28,6 @@ const Fade = React.forwardRef(function Fade(props, re }); return ( - // @ts-expect-error https://github.com/pmndrs/react-spring/issues/2341 {children} diff --git a/docs/data/material/components/popper/popper.md b/docs/data/material/components/popper/popper.md index 0f0a4b8ea6b8c8..55f14b5fb208ae 100644 --- a/docs/data/material/components/popper/popper.md +++ b/docs/data/material/components/popper/popper.md @@ -3,7 +3,6 @@ productId: material-ui title: React Popper component components: Popper githubLabel: 'component: Popper' -unstyled: /base-ui/react-popper/ githubSource: packages/mui-material/src/Popper --- diff --git a/docs/data/material/components/selects/selects.md b/docs/data/material/components/selects/selects.md index 68f41a0bb7ed76..2d306a48ef700f 100644 --- a/docs/data/material/components/selects/selects.md +++ b/docs/data/material/components/selects/selects.md @@ -5,7 +5,6 @@ components: Select, NativeSelect githubLabel: 'component: select' materialDesign: https://m2.material.io/components/menus#exposed-dropdown-menu waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/ -unstyled: /base-ui/react-select/ githubSource: packages/mui-material/src/Select --- diff --git a/docs/data/material/components/slider/slider.md b/docs/data/material/components/slider/slider.md index d215c00e76cd8d..44f6b3b4603a66 100644 --- a/docs/data/material/components/slider/slider.md +++ b/docs/data/material/components/slider/slider.md @@ -5,7 +5,6 @@ components: Slider githubLabel: 'component: slider' materialDesign: https://m2.material.io/components/sliders waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/slider-multithumb/ -unstyled: /base-ui/react-slider/ githubSource: packages/mui-material/src/Slider --- diff --git a/docs/data/material/components/snackbars/ToolpadNotificationsNoSnap.js b/docs/data/material/components/snackbars/ToolpadNotificationsNoSnap.js deleted file mode 100644 index fc7700914150e4..00000000000000 --- a/docs/data/material/components/snackbars/ToolpadNotificationsNoSnap.js +++ /dev/null @@ -1,43 +0,0 @@ -import * as React from 'react'; -import { - useNotifications, - NotificationsProvider, -} from '@toolpad/core/useNotifications'; -import Button from '@mui/material/Button'; - -function NotifyButton() { - const notifications = useNotifications(); - const [online, setOnline] = React.useState(true); - const prevOnline = React.useRef(online); - React.useEffect(() => { - if (prevOnline.current === online) { - return () => {}; - } - prevOnline.current = online; - - // preview-start - const key = online - ? notifications.show('You are now online', { - severity: 'success', - autoHideDuration: 3000, - }) - : notifications.show('You are now offline', { - severity: 'error', - }); - - return () => { - notifications.close(key); - }; - // preview-end - }, [notifications, online]); - - return ; -} - -export default function ToolpadNotificationsNoSnap() { - return ( - - - - ); -} diff --git a/docs/data/material/components/snackbars/ToolpadNotificationsNoSnap.tsx b/docs/data/material/components/snackbars/ToolpadNotificationsNoSnap.tsx deleted file mode 100644 index fc7700914150e4..00000000000000 --- a/docs/data/material/components/snackbars/ToolpadNotificationsNoSnap.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import * as React from 'react'; -import { - useNotifications, - NotificationsProvider, -} from '@toolpad/core/useNotifications'; -import Button from '@mui/material/Button'; - -function NotifyButton() { - const notifications = useNotifications(); - const [online, setOnline] = React.useState(true); - const prevOnline = React.useRef(online); - React.useEffect(() => { - if (prevOnline.current === online) { - return () => {}; - } - prevOnline.current = online; - - // preview-start - const key = online - ? notifications.show('You are now online', { - severity: 'success', - autoHideDuration: 3000, - }) - : notifications.show('You are now offline', { - severity: 'error', - }); - - return () => { - notifications.close(key); - }; - // preview-end - }, [notifications, online]); - - return ; -} - -export default function ToolpadNotificationsNoSnap() { - return ( - - - - ); -} diff --git a/docs/data/material/components/snackbars/ToolpadNotificationsNoSnap.tsx.preview b/docs/data/material/components/snackbars/ToolpadNotificationsNoSnap.tsx.preview deleted file mode 100644 index a0bef6df003508..00000000000000 --- a/docs/data/material/components/snackbars/ToolpadNotificationsNoSnap.tsx.preview +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/data/material/components/snackbars/snackbars.md b/docs/data/material/components/snackbars/snackbars.md index 3d169988bff194..965c5dbf8c5412 100644 --- a/docs/data/material/components/snackbars/snackbars.md +++ b/docs/data/material/components/snackbars/snackbars.md @@ -157,11 +157,3 @@ The Snackbar component is composed of a root `
    ` that houses interior elemen
    ``` - -## Experimental APIs - Toolpad - -### useNotifications - -You can create and manipulate notifications imperatively with the [`useNotifications()`](https://mui.com/toolpad/core/react-use-notifications/) API in `@toolpad/core`. This API provides state management for opening and closing snackbars. It also allows for queueing multiple notifications at once. - -{{"demo": "ToolpadNotificationsNoSnap.js", "defaultCodeOpen": false}} diff --git a/docs/data/material/components/speed-dial/BasicSpeedDial.js b/docs/data/material/components/speed-dial/BasicSpeedDial.js index 40bd7e17d6242c..b214074e3f1363 100644 --- a/docs/data/material/components/speed-dial/BasicSpeedDial.js +++ b/docs/data/material/components/speed-dial/BasicSpeedDial.js @@ -27,7 +27,11 @@ export default function BasicSpeedDial() { ))} diff --git a/docs/data/material/components/speed-dial/BasicSpeedDial.tsx b/docs/data/material/components/speed-dial/BasicSpeedDial.tsx index 40bd7e17d6242c..b214074e3f1363 100644 --- a/docs/data/material/components/speed-dial/BasicSpeedDial.tsx +++ b/docs/data/material/components/speed-dial/BasicSpeedDial.tsx @@ -27,7 +27,11 @@ export default function BasicSpeedDial() { ))} diff --git a/docs/data/material/components/speed-dial/BasicSpeedDial.tsx.preview b/docs/data/material/components/speed-dial/BasicSpeedDial.tsx.preview deleted file mode 100644 index 93077ee986f078..00000000000000 --- a/docs/data/material/components/speed-dial/BasicSpeedDial.tsx.preview +++ /dev/null @@ -1,13 +0,0 @@ -} -> - {actions.map((action) => ( - - ))} - \ No newline at end of file diff --git a/docs/data/material/components/speed-dial/ControlledOpenSpeedDial.js b/docs/data/material/components/speed-dial/ControlledOpenSpeedDial.js index 905103838e0168..56f606cd1b4c23 100644 --- a/docs/data/material/components/speed-dial/ControlledOpenSpeedDial.js +++ b/docs/data/material/components/speed-dial/ControlledOpenSpeedDial.js @@ -34,7 +34,11 @@ export default function ControlledOpenSpeedDial() { ))} diff --git a/docs/data/material/components/speed-dial/ControlledOpenSpeedDial.tsx b/docs/data/material/components/speed-dial/ControlledOpenSpeedDial.tsx index 905103838e0168..56f606cd1b4c23 100644 --- a/docs/data/material/components/speed-dial/ControlledOpenSpeedDial.tsx +++ b/docs/data/material/components/speed-dial/ControlledOpenSpeedDial.tsx @@ -34,7 +34,11 @@ export default function ControlledOpenSpeedDial() { ))} diff --git a/docs/data/material/components/speed-dial/OpenIconSpeedDial.js b/docs/data/material/components/speed-dial/OpenIconSpeedDial.js index 4ecd8d1d02f9c0..9cc276999be08e 100644 --- a/docs/data/material/components/speed-dial/OpenIconSpeedDial.js +++ b/docs/data/material/components/speed-dial/OpenIconSpeedDial.js @@ -28,7 +28,11 @@ export default function OpenIconSpeedDial() { ))} diff --git a/docs/data/material/components/speed-dial/OpenIconSpeedDial.tsx b/docs/data/material/components/speed-dial/OpenIconSpeedDial.tsx index 4ecd8d1d02f9c0..9cc276999be08e 100644 --- a/docs/data/material/components/speed-dial/OpenIconSpeedDial.tsx +++ b/docs/data/material/components/speed-dial/OpenIconSpeedDial.tsx @@ -28,7 +28,11 @@ export default function OpenIconSpeedDial() { ))} diff --git a/docs/data/material/components/speed-dial/OpenIconSpeedDial.tsx.preview b/docs/data/material/components/speed-dial/OpenIconSpeedDial.tsx.preview deleted file mode 100644 index d4d88535add303..00000000000000 --- a/docs/data/material/components/speed-dial/OpenIconSpeedDial.tsx.preview +++ /dev/null @@ -1,13 +0,0 @@ -} />} -> - {actions.map((action) => ( - - ))} - \ No newline at end of file diff --git a/docs/data/material/components/speed-dial/PlaygroundSpeedDial.js b/docs/data/material/components/speed-dial/PlaygroundSpeedDial.js index 9cb8d045cb39d9..41ab636415daed 100644 --- a/docs/data/material/components/speed-dial/PlaygroundSpeedDial.js +++ b/docs/data/material/components/speed-dial/PlaygroundSpeedDial.js @@ -80,7 +80,11 @@ export default function PlaygroundSpeedDial() { ))} diff --git a/docs/data/material/components/speed-dial/PlaygroundSpeedDial.tsx b/docs/data/material/components/speed-dial/PlaygroundSpeedDial.tsx index 489d57cc2df286..a740a1fa2bddf4 100644 --- a/docs/data/material/components/speed-dial/PlaygroundSpeedDial.tsx +++ b/docs/data/material/components/speed-dial/PlaygroundSpeedDial.tsx @@ -83,7 +83,11 @@ export default function PlaygroundSpeedDial() { ))} diff --git a/docs/data/material/components/speed-dial/SpeedDialTooltipOpen.js b/docs/data/material/components/speed-dial/SpeedDialTooltipOpen.js index e634d7c658086a..15a928bfd57fca 100644 --- a/docs/data/material/components/speed-dial/SpeedDialTooltipOpen.js +++ b/docs/data/material/components/speed-dial/SpeedDialTooltipOpen.js @@ -36,8 +36,12 @@ export default function SpeedDialTooltipOpen() { ))} diff --git a/docs/data/material/components/speed-dial/SpeedDialTooltipOpen.tsx b/docs/data/material/components/speed-dial/SpeedDialTooltipOpen.tsx index e634d7c658086a..15a928bfd57fca 100644 --- a/docs/data/material/components/speed-dial/SpeedDialTooltipOpen.tsx +++ b/docs/data/material/components/speed-dial/SpeedDialTooltipOpen.tsx @@ -36,8 +36,12 @@ export default function SpeedDialTooltipOpen() { ))} diff --git a/docs/data/material/components/speed-dial/speed-dial.md b/docs/data/material/components/speed-dial/speed-dial.md index 7b58695b8954c2..2cbb5597919aa5 100644 --- a/docs/data/material/components/speed-dial/speed-dial.md +++ b/docs/data/material/components/speed-dial/speed-dial.md @@ -54,7 +54,7 @@ It is enabled here across all devices for demo purposes, but in production it co #### Required - You should provide an `ariaLabel` for the speed dial component. -- You should provide a `tooltipTitle` for each speed dial action. +- You should provide a tooltip title using `slotProps.tooltip.title` for each speed dial action. #### Provided diff --git a/docs/data/material/components/switches/switches.md b/docs/data/material/components/switches/switches.md index 6f1ae3c042c4c7..5a00651b17db63 100644 --- a/docs/data/material/components/switches/switches.md +++ b/docs/data/material/components/switches/switches.md @@ -4,7 +4,6 @@ title: React Switch component components: Switch, FormControl, FormGroup, FormLabel, FormControlLabel githubLabel: 'component: switch' materialDesign: https://m2.material.io/components/selection-controls#switches -unstyled: /base-ui/react-switch/ githubSource: packages/mui-material/src/Switch --- @@ -72,10 +71,6 @@ You can change the placement of the label: ## Accessibility -- It will render an element with the `checkbox` role not `switch` role since this - role isn't widely supported yet. Please test first if assistive technology of your - target audience supports this role properly. Then you can change the role with - `` - All form controls should have labels, and this includes radio buttons, checkboxes, and switches. In most cases, this is done by using the `