Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[docs] Fix unnecessary redirects for v7 #45677

Merged
merged 3 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ To customize a specific part of a component, you can use the class name provided

First, use your browser's dev tools to identify the class for the component slot you want to override.

The styles injected into the DOM by Material UI rely on class names that all [follow a standard pattern](/system/styles/advanced/#class-names):
The styles injected into the DOM by Material UI rely on class names that all [follow a standard pattern](https://v6.mui.com/system/styles/advanced/#class-names):
`[hash]-Mui[Component name]-[name of the slot]`.

In this case, the styles are applied with `.css-ae2u5c-MuiSlider-thumb` but you only really need to target the `.MuiSlider-thumb`, where `Slider` is the component and `thumb` is the slot. Use this class name to write a CSS selector within the `sx` prop (`& .MuiSlider-thumb`), and add your overrides.
Expand Down Expand Up @@ -101,7 +101,7 @@ For consistency with native elements, Material UI's state classes have the same

#### What custom state classes are available in Material UI?

You can rely on the following [global class names](/system/styles/advanced/#class-names) generated by Material UI:
You can rely on the following [global class names](https://v6.mui.com/system/styles/advanced/#class-names) generated by Material UI:

| State | Global class name |
| :------------ | :------------------ |
Expand Down
2 changes: 1 addition & 1 deletion docs/data/material/customization/theming/theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ function DeepChild() {

## Nesting the theme

[You can nest](/system/styles/advanced/#theme-nesting) multiple theme providers.
[You can nest](https://v6.mui.com/system/styles/advanced/#theme-nesting) multiple theme providers.

{{"demo": "ThemeNesting.js"}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<p class="description">Configure classname generation at build time.</p>

This API is introduced in `@mui/material` (v5.0.5) as a replacement of deprecated [`createGenerateClassName`](/system/styles/api/#creategenerateclassname-options-class-name-generator).
This API is introduced in `@mui/material` (v5.0.5) as a replacement of deprecated [`createGenerateClassName`](https://v6.mui.com/system/styles/api/#creategenerateclassname-options-class-name-generator).

:::warning
This API is at an unstable stage and is subject to change in the future.
Expand Down
6 changes: 3 additions & 3 deletions docs/data/material/getting-started/faq/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ If you have several applications running on one page, consider using one @mui/st
## [legacy] Why aren't my components rendering correctly in production builds?

The #1 reason this happens is likely due to class name conflicts once your code is in a production bundle.
For Material UI to work, the `className` values of all components on a page must be generated by a single instance of the [class name generator](/system/styles/advanced/#class-names).
For Material UI to work, the `className` values of all components on a page must be generated by a single instance of the [class name generator](https://v6.mui.com/system/styles/advanced/#class-names).

To correct this issue, all components on the page need to be initialized such that there is only ever **one class name generator** among them.

Expand All @@ -412,7 +412,7 @@ You could end up accidentally using two class name generators in a variety of sc
If you are using webpack with the [SplitChunksPlugin](https://webpack.js.org/plugins/split-chunks-plugin/), try configuring the [`runtimeChunk` setting under `optimizations`](https://webpack.js.org/configuration/optimization/#optimization-runtimechunk).
:::

Overall, it's simple to recover from this problem by wrapping each Material UI application with [`StylesProvider`](/system/styles/api/#stylesprovider) components at the top of their component trees **and using a single class name generator shared among them**.
Overall, it's simple to recover from this problem by wrapping each Material UI application with [`StylesProvider`](https://v6.mui.com/system/styles/api/#stylesprovider) components at the top of their component trees **and using a single class name generator shared among them**.

### [legacy] CSS works only on first load and goes missing

Expand Down Expand Up @@ -452,7 +452,7 @@ Another symptom is that the styling changes between initial page load and the do

#### Action to Take

The class names value relies on the concept of [class name generator](/system/styles/advanced/#class-names).
The class names value relies on the concept of [class name generator](https://v6.mui.com/system/styles/advanced/#class-names).
The whole page needs to be rendered with **a single generator**.
This generator needs to behave identically on the server and on the client. For instance:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ app.listen(port);
The first thing that we need to do on every request is to create a new `emotion cache`.

When rendering, we will wrap `App`, the root component,
inside a [`CacheProvider`](https://emotion.sh/docs/cache-provider) and [`ThemeProvider`](/system/styles/api/#themeprovider) to make the style configuration and the `theme` available to all components in the component tree.
inside a [`CacheProvider`](https://emotion.sh/docs/cache-provider) and [`ThemeProvider`](https://v6.mui.com/system/styles/api/#themeprovider) to make the style configuration and the `theme` available to all components in the component tree.

The key step in server-side rendering is to render the initial HTML of the component **before** we send it to the client-side. To do this, we use [ReactDOMServer.renderToString()](https://react.dev/reference/react-dom/server/renderToString).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export default function PlainCssSliderDeep1() {
}
```

The above demo relies on the [default `className` values](/system/styles/advanced/), but you can provide your own class name with the `slotProps` API.
The above demo relies on the [default `className` values](https://v6.mui.com/system/styles/advanced/), but you can provide your own class name with the `slotProps` API.

```css title="PlainCssSliderDeep2.css"
.slider {
Expand Down Expand Up @@ -164,7 +164,7 @@ export default function PlainCssSliderDeep2() {
## Global CSS

Explicitly providing the class names to the component is too much effort?
[You can target the class names generated by Material UI](/system/styles/advanced/).
[You can target the class names generated by Material UI](https://v6.mui.com/system/styles/advanced/).

[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/global-classnames-dho8k)

Expand Down Expand Up @@ -314,7 +314,7 @@ The following examples override the slider's `thumb` style in addition to the cu

{{"demo": "StyledComponentsDeep.js", "defaultCodeOpen": true}}

The above demo relies on the [default `className` values](/system/styles/advanced/), but you can provide your own class name with the `slotProps` API.
The above demo relies on the [default `className` values](https://v6.mui.com/system/styles/advanced/), but you can provide your own class name with the `slotProps` API.

```jsx
import * as React from 'react';
Expand Down Expand Up @@ -518,7 +518,7 @@ export default function CssModulesSliderDeep1() {
}
```

The above demo relies on the [default `className` values](/system/styles/advanced/), but you can provide your own class name with the `slotProps` API.
The above demo relies on the [default `className` values](https://v6.mui.com/system/styles/advanced/), but you can provide your own class name with the `slotProps` API.

```css title="CssModulesSliderDeep2.module.css"
.slider {
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/blog/april-2019-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Here are the most significant improvements in April:
This API targets plain CSS and styled-components users.
It can be challenging to apply your class name on the right element with the `classes` API. It can also be cumbersome. ⚠️ Using global class names provide more power but comes with a responsibility. We encourage any pattern that increases your **custom style isolation**.

[![Global class names](/static/blog/april-2019-update/global-class-names.png)](/system/styles/advanced/)
[![Global class names](/static/blog/april-2019-update/global-class-names.png)](https://v6.mui.com/system/styles/advanced/)

- 📅 We have moved material-ui-pickers to our organization: [@material-ui/pickers](https://www.npmjs.com/package/@material-ui/pickers). A big thanks to **@dmtrKovalenko** for creating and owning these date/time components.
- 🔥 We have fixed more Strict Mode warnings, getting us closer to [Concurrent React](https://legacy.reactjs.org/blog/2018/11/27/react-16-roadmap.html#react-16x-q2-2019-the-one-with-concurrent-mode) support.
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/blog/march-2019-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

- We have committed to [a new Roadmap](/material-ui/discover-more/roadmap/) (prioritized) for the next 6 months.
- We have migrated 50% of the codebase from the Classes API to the Hooks API. Once we are done with this task we can remove the internal usage of higher-order components.
- We have introduced [a simplified server-side rendering API](/system/styles/advanced/#server-side-rendering), inspired by styled-components.
- We have introduced [a simplified server-side rendering API](https://v6.mui.com/system/styles/advanced/#server-side-rendering), inspired by styled-components.

Check warning on line 26 in docs/pages/blog/march-2019-update.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'We'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'We'.", "location": {"path": "docs/pages/blog/march-2019-update.md", "range": {"start": {"line": 26, "column": 3}}}, "severity": "WARNING"}

## Our roadmap intent for April

Expand Down
4 changes: 2 additions & 2 deletions docs/pages/blog/material-ui-v4-is-out.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@

- **classes boilerplate**. Early in the v1 effort, we [decided](https://github.com/oliviertassinari/a-journey-toward-better-style) to use a CSS-in-JS styling solution: [JSS](https://cssinjs.org/). The large majority of the CSS-in-JS solutions output non-deterministic class names, for example `.fHmkjM`. This design decision helps the isolation of the style of each component, however, it makes the overrides harder. We introduced a `classes` API in v1 to target all our elements as an attempt to mitigate this problem.
We have observed the use of this API for months and have seen many people struggling with it. It can be challenging to apply the class name on the right element and requires boilerplate as well.
As an attempt to further improve the situation, we have changed the class name generation to [output global class names](/system/styles/advanced/), while keeping the `classes` API working as before 💅.
As an attempt to further improve the situation, we have changed the class name generation to [output global class names](https://v6.mui.com/system/styles/advanced/), while keeping the `classes` API working as before 💅.

Check warning on line 70 in docs/pages/blog/material-ui-v4-is-out.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'we'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'we'.", "location": {"path": "docs/pages/blog/material-ui-v4-is-out.md", "range": {"start": {"line": 70, "column": 51}}}, "severity": "WARNING"}

![styled-components](/static/blog/material-ui-v4-is-out/styled-components.png)

Expand Down Expand Up @@ -254,7 +254,7 @@

<p class="blog-description">Inline mode</p>

- A new [@mui/styles](/system/styles/basics/) package that isolates our styling solution. It can be used independently of the core components. It comes with a hooks API that requires less boilerplate 😍
- A new [@mui/styles](https://v6.mui.com/system/styles/basics/) package that isolates our styling solution. It can be used independently of the core components. It comes with a hooks API that requires less boilerplate 😍

Check warning on line 257 in docs/pages/blog/material-ui-v4-is-out.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'our'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'our'.", "location": {"path": "docs/pages/blog/material-ui-v4-is-out.md", "range": {"start": {"line": 257, "column": 87}}}, "severity": "WARNING"}

```jsx
import * as React from 'react';
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/blog/mui-core-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ const StyledDiv = styled.div`
<p class="blog-description"><a href="https://codesandbox.io/p/sandbox/elastic-yonath-uedfv?file=/src/App.js">CodeSandbox</a></p>

You can find it in [styled-components](https://styled-components.com/), [emotion](https://emotion.sh/docs/styled), [goober](https://goober.js.org/), [stitches](https://stitches.dev/docs/api#styled), or [linaria](https://linaria.dev/).
While Material UI is compatible with any styling solution (as long as the styles have more specificity, for example, Tailwind CSS), many developers still felt the need to learn something new: the [`makeStyles`](https://mui.com/system/styles/basics/#hook-api) API.
While Material UI is compatible with any styling solution (as long as the styles have more specificity, for example, Tailwind CSS), many developers still felt the need to learn something new: the [`makeStyles`](https://v6.mui.com/system/styles/basics/#hook-api) API.

2. Our React integration with JSS (`@mui/styles`) is **too slow** to unlock the next layer of customization DX we aim for.
The static CSS generation using v4 was fast enough, even [faster](https://codesandbox.io/p/sandbox/nb05w?file=/src/App.js) than emotion,
Expand Down
42 changes: 33 additions & 9 deletions docs/scripts/reportBrokenLinks.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,62 @@
// @ts-check
/* eslint-disable no-console */
import path from 'path';
import fse from 'fs-extra';
import { parseDocFolder, getAnchor } from './reportBrokenLinksLib';

/**
* The remaining pat to the code is specific to this repository
* The remaining path to the code is specific to this repository
*/
const UNSUPPORTED_PATHS = ['/api/', '/careers/', '/store/', '/x/', '/system/styles/'];
const EXTERNAL_PATHS = [
'/api/',
// Not defined in .md file
'/careers/',
// Same domain, different project
'/store/',
// Same domain, different project
'/x/',
// these url segments are specific to Base UI and added by scripts (can not be found in markdown)
'components-api',
'hooks-api',
'#unstyled',
];

const docsSpaceRoot = path.join(path.dirname(new URL(import.meta.url).pathname), '../');

/** @type {string[]} */
const buffer = [];
/**
*
* @param {string} text
*/
function write(text) {
buffer.push(text);
}

/**
*
* @param {string[]} lines
*/
function save(lines) {
const fileContents = [...lines, ''].join('\n');
fse.writeFileSync(path.join(docsSpaceRoot, '.link-check-errors.txt'), fileContents);
}

/**
*
* @param {string} link
* @returns {string}
*/
function getPageUrlFromLink(link) {
const [rep] = link.split('/#');
return rep;
}

// {[url with hash]: true}
/** @type {Record<string, boolean>} */
const availableLinks = {};

// {[url with hash]: list of files using this link}
// Per link a list a of files where it is used
/** @type {Record<string, string[]>} */
const usedLinks = {};

parseDocFolder(path.join(docsSpaceRoot, './pages/'), availableLinks, usedLinks);
Expand All @@ -37,11 +65,7 @@ write('Broken links found by `pnpm docs:link-check` that exist:\n');
Object.keys(usedLinks)
.filter((link) => link.startsWith('/'))
.filter((link) => !availableLinks[link])
// these url segments are specific to Base UI and added by scripts (can not be found in markdown)
.filter((link) =>
['components-api', 'hooks-api', '#unstyled'].every((str) => !link.includes(str)),
)
.filter((link) => UNSUPPORTED_PATHS.every((unsupportedPath) => !link.includes(unsupportedPath)))
.filter((link) => EXTERNAL_PATHS.every((externalPath) => !link.includes(externalPath)))
.sort()
.forEach((linkKey) => {
//
Expand Down
66 changes: 54 additions & 12 deletions docs/scripts/reportBrokenLinksLib.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
// @ts-check
import path from 'path';
import fse from 'fs-extra';
import { createRender } from '@mui/internal-markdown';
import { marked } from 'marked';
import { LANGUAGES_IGNORE_PAGES } from '../config';

// Use renderer to extract all links into a markdown document
/**
* Use renderer to extract all links into a markdown document
* @param {string} markdown
* @returns {string[]}
*/
function getPageLinks(markdown) {
/** @type {string[]} */
const hrefs = [];

const renderer = new marked.Renderer();
renderer.link = ({ href }) => {
if (href.startsWith('/')) {
hrefs.push(href);
}
return '';
};
marked(markdown, { renderer });
return hrefs;
}

// List all .js files in a folder
/**
* List all .js files in a folder
* @param {string} folderPath
* @returns {string[]}
*/
function getJsFilesInFolder(folderPath) {
const files = fse.readdirSync(folderPath, { withFileTypes: true });
return files.reduce((acc, file) => {
Expand All @@ -30,11 +41,15 @@ function getJsFilesInFolder(folderPath) {
return [...acc, path.join(folderPath, file.name).replace(/\\/g, '/')];
}
return acc;
}, []);
}, /** @type {string[]} */ ([]));
}

// Returns url assuming it's "./docs/pages/x/..." becomes "mui.com/x/..."
const jsFilePathToUrl = (jsFilePath) => {
/**
* Returns url assuming it's "./docs/pages/x/..." becomes "mui.com/x/..."
* @param {string} jsFilePath
* @returns {string}
*/
function jsFilePathToUrl(jsFilePath) {
const folder = path.dirname(jsFilePath);
const file = path.basename(jsFilePath);

Expand All @@ -47,8 +62,13 @@ const jsFilePathToUrl = (jsFilePath) => {
}

return `${root}${page}`;
};
}

/**
*
* @param {string} link
* @returns {string}
*/
function cleanLink(link) {
const startQueryIndex = link.indexOf('?');
const endQueryIndex = link.indexOf('#', startQueryIndex);
Expand All @@ -62,7 +82,13 @@ function cleanLink(link) {
return `${link.slice(0, startQueryIndex)}${link.slice(endQueryIndex)}`;
}

/**
*
* @param {string} fileName
* @returns {{ hashes: string[], links: string[] }}
*/
function getLinksAndAnchors(fileName) {
/** @type {Record<string, string>} */
const headingHashes = {};
const render = createRender({
headingHashes,
Expand All @@ -87,7 +113,12 @@ function getLinksAndAnchors(fileName) {

const markdownImportRegExp = /'(.*)\?(muiMarkdown|@mui\/markdown)'/g;

const getMdFilesImported = (jsPageFile) => {
/**
*
* @param {string} jsPageFile
* @returns {string[]}
*/
function getMdFilesImported(jsPageFile) {
// For each JS file extract the markdown rendered if it exists
const fileContent = fse.readFileSync(jsPageFile, 'utf8');
/**
Expand Down Expand Up @@ -125,9 +156,15 @@ const getMdFilesImported = (jsPageFile) => {

return cleanImportPath;
});
};
}

const parseDocFolder = (folderPath, availableLinks = {}, usedLinks = {}) => {
/**
*
* @param {string} folderPath
* @param {Record<string, boolean>} availableLinks
* @param {Record<string, string[]>} usedLinks
*/
function parseDocFolder(folderPath, availableLinks = {}, usedLinks = {}) {
const jsPageFiles = getJsFilesInFolder(folderPath);

const mdFiles = jsPageFiles.flatMap((jsPageFile) => {
Expand Down Expand Up @@ -159,13 +196,18 @@ const parseDocFolder = (folderPath, availableLinks = {}, usedLinks = {}) => {
availableLinks[`${url}#${hash}`] = true;
});
});
};
}

const getAnchor = (link) => {
/**
*
* @param {string} link
* @returns {string}
*/
function getAnchor(link) {
const splittedPath = link.split('/');
const potentialAnchor = splittedPath[splittedPath.length - 1];
return potentialAnchor.includes('#') ? potentialAnchor : '';
};
}

// Export useful method for doing similar checks in other repositories
export { parseDocFolder, getAnchor };
Loading