Skip to content

Commit

Permalink
[docs-infra] Remove random layout assignment (#40862)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfauquette authored Feb 14, 2024
1 parent d8558a5 commit a8563ea
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 82 deletions.
21 changes: 20 additions & 1 deletion docs/src/modules/components/ApiPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import ClassesSection, {
getClassesToC,
} from 'docs/src/modules/components/ApiPage/sections/ClassesSection';
import SlotsSection from 'docs/src/modules/components/ApiPage/sections/SlotsSection';
import { DEFAULT_API_LAYOUT_STORAGE_KEYS } from 'docs/src/modules/components/ApiPage/sections/ToggleDisplayOption';

export function getTranslatedHeader(t, header) {
const translations = {
Expand Down Expand Up @@ -68,7 +69,13 @@ Heading.propTypes = {
};

export default function ApiPage(props) {
const { descriptions, disableAd = false, pageContent } = props;
const {
descriptions,
disableAd = false,
pageContent,
defaultLayout = 'table',
layoutStorageKey = DEFAULT_API_LAYOUT_STORAGE_KEYS,
} = props;
const t = useTranslate();
const userLanguage = useUserLanguage();

Expand Down Expand Up @@ -257,6 +264,8 @@ export default function ApiPage(props) {
propertiesDescriptions={propDescriptions}
componentName={pageContent.name}
spreadHint={spreadHint}
defaultLayout={defaultLayout}
layoutStorageKey={layoutStorageKey.props}
/>
{cssComponent && (
<React.Fragment>
Expand Down Expand Up @@ -314,13 +323,17 @@ export default function ApiPage(props) {
slotGuideLink &&
t('api-docs.slotDescription').replace(/{{slotGuideLink}}/, slotGuideLink)
}
defaultLayout={defaultLayout}
layoutStorageKey={layoutStorageKey.slots}
/>
<ClassesSection
componentClasses={componentClasses}
componentName={pageContent.name}
classDescriptions={classDescriptions}
spreadHint={t('api-docs.classesDescription')}
styleOverridesLink={styleOverridesLink}
defaultLayout={defaultLayout}
layoutStorageKey={layoutStorageKey.classes}
displayClassKeys
/>
</MarkdownElement>
Expand All @@ -334,8 +347,14 @@ export default function ApiPage(props) {
}

ApiPage.propTypes = {
defaultLayout: PropTypes.oneOf(['collapsed', 'expanded', 'table']),
descriptions: PropTypes.object.isRequired,
disableAd: PropTypes.bool,
layoutStorageKey: PropTypes.shape({
classes: PropTypes.string,
props: PropTypes.string,
slots: PropTypes.string,
}),
pageContent: PropTypes.object.isRequired,
};

Expand Down
14 changes: 11 additions & 3 deletions docs/src/modules/components/ApiPage/sections/ClassesSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useTranslate } from 'docs/src/modules/utils/i18n';
import { ComponentClassDefinition } from '@mui-internal/docs-utils';
import Box from '@mui/material/Box';
import ToggleDisplayOption, {
API_LAYOUT_STORAGE_KEYS,
ApiDisplayOptions,
useApiPageOption,
} from 'docs/src/modules/components/ApiPage/sections/ToggleDisplayOption';
import ClassesList, { getHash } from 'docs/src/modules/components/ApiPage/list/ClassesList';
Expand Down Expand Up @@ -49,6 +49,8 @@ export type ClassesSectionProps = {
title: string;
titleHash: string;
level?: 'h2' | 'h3' | 'h4';
defaultLayout: ApiDisplayOptions;
layoutStorageKey: string;
displayClassKeys: boolean;
styleOverridesLink: string;
};
Expand All @@ -64,10 +66,12 @@ export default function ClassesSection(props: ClassesSectionProps) {
level: Level = 'h2',
displayClassKeys,
styleOverridesLink,
defaultLayout,
layoutStorageKey,
} = props;
const t = useTranslate();

const [displayOption, setDisplayOption] = useApiPageOption(API_LAYOUT_STORAGE_KEYS.classes);
const [displayOption, setDisplayOption] = useApiPageOption(layoutStorageKey, defaultLayout);

if (!componentClasses || componentClasses.length === 0) {
return null;
Expand Down Expand Up @@ -101,7 +105,11 @@ export default function ClassesSection(props: ClassesSectionProps) {
</svg>
</a>
</Level>
<ToggleDisplayOption displayOption={displayOption} setDisplayOption={setDisplayOption} />
<ToggleDisplayOption
displayOption={displayOption}
setDisplayOption={setDisplayOption}
sectionType="classes"
/>
</Box>
{spreadHint && <p dangerouslySetInnerHTML={{ __html: spreadHint }} />}
{displayOption === 'table' ? (
Expand Down
13 changes: 10 additions & 3 deletions docs/src/modules/components/ApiPage/sections/PropertiesSection.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
import Box from '@mui/material/Box';
import { useTranslate } from 'docs/src/modules/utils/i18n';
import ToggleDisplayOption, {
API_LAYOUT_STORAGE_KEYS,
useApiPageOption,
} from 'docs/src/modules/components/ApiPage/sections/ToggleDisplayOption';
import PropertiesList, { getHash } from 'docs/src/modules/components/ApiPage/list/PropertiesList';
Expand Down Expand Up @@ -51,10 +50,12 @@ export default function PropertiesSection(props) {
spreadHint,
hooksParameters = false,
hooksReturnValue = false,
defaultLayout,
layoutStorageKey,
} = props;
const t = useTranslate();

const [displayOption, setDisplayOption] = useApiPageOption(API_LAYOUT_STORAGE_KEYS.props);
const [displayOption, setDisplayOption] = useApiPageOption(layoutStorageKey, defaultLayout);
const formatedProperties = Object.entries(properties)
.filter(([, propData]) => propData.description !== '@ignore')
.map(([propName, propData]) => {
Expand Down Expand Up @@ -131,7 +132,11 @@ export default function PropertiesSection(props) {
</svg>
</a>
</Level>
<ToggleDisplayOption displayOption={displayOption} setDisplayOption={setDisplayOption} />
<ToggleDisplayOption
displayOption={displayOption}
setDisplayOption={setDisplayOption}
sectionType="props"
/>
</Box>
{spreadHint && <p dangerouslySetInnerHTML={{ __html: spreadHint }} />}
{displayOption === 'table' ? (
Expand All @@ -145,8 +150,10 @@ export default function PropertiesSection(props) {

PropertiesSection.propTypes = {
componentName: PropTypes.string,
defaultLayout: PropTypes.oneOf(['collapsed', 'expanded', 'table']).isRequired,
hooksParameters: PropTypes.bool,
hooksReturnValue: PropTypes.bool,
layoutStorageKey: PropTypes.string.isRequired,
level: PropTypes.string,
properties: PropTypes.object.isRequired,
propertiesDescriptions: PropTypes.object.isRequired,
Expand Down
14 changes: 11 additions & 3 deletions docs/src/modules/components/ApiPage/sections/SlotsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as React from 'react';
import Box from '@mui/material/Box';
import { useTranslate } from 'docs/src/modules/utils/i18n';
import ToggleDisplayOption, {
API_LAYOUT_STORAGE_KEYS,
ApiDisplayOptions,
useApiPageOption,
} from 'docs/src/modules/components/ApiPage/sections/ToggleDisplayOption';
import SlotsList from 'docs/src/modules/components/ApiPage/list/SlotsList';
Expand All @@ -16,6 +16,8 @@ export type SlotsSectionProps = {
title?: string;
titleHash?: string;
level?: 'h2' | 'h3' | 'h4';
defaultLayout: ApiDisplayOptions;
layoutStorageKey: string;
spreadHint?: string;
};

Expand All @@ -28,10 +30,12 @@ export default function SlotsSection(props: SlotsSectionProps) {
titleHash = 'slots',
level: Level = 'h2',
spreadHint,
defaultLayout,
layoutStorageKey,
} = props;
const t = useTranslate();

const [displayOption, setDisplayOption] = useApiPageOption(API_LAYOUT_STORAGE_KEYS.slots);
const [displayOption, setDisplayOption] = useApiPageOption(layoutStorageKey, defaultLayout);

if (!componentSlots || componentSlots.length === 0) {
return null;
Expand Down Expand Up @@ -63,7 +67,11 @@ export default function SlotsSection(props: SlotsSectionProps) {
</svg>
</a>
</Level>
<ToggleDisplayOption displayOption={displayOption} setDisplayOption={setDisplayOption} />
<ToggleDisplayOption
displayOption={displayOption}
setDisplayOption={setDisplayOption}
sectionType="slots"
/>
</Box>
{spreadHint && <p dangerouslySetInnerHTML={{ __html: spreadHint }} />}
{displayOption === 'table' ? (
Expand Down
104 changes: 41 additions & 63 deletions docs/src/modules/components/ApiPage/sections/ToggleDisplayOption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,87 +7,54 @@ import TableChartRoundedIcon from '@mui/icons-material/TableChartRounded';
import ReorderRoundedIcon from '@mui/icons-material/ReorderRounded';
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';

type ApiDisplayOptions = 'collapsed' | 'expanded' | 'table';
export type ApiDisplayOptions = 'collapsed' | 'expanded' | 'table';

const options: ApiDisplayOptions[] = ['collapsed', 'expanded', 'table'];
const DEFAULT_LAYOUT: ApiDisplayOptions = 'expanded';

export const API_LAYOUT_STORAGE_KEYS = {
default: 'apiPage_default',
export const DEFAULT_API_LAYOUT_STORAGE_KEYS = {
slots: 'apiPage_slots',
props: 'apiPage_props',
css: 'apiPage_css',
classes: 'apiPage_classes',
} as const;

// https://stackoverflow.com/a/20084661
function isBot() {
return /bot|googlebot|crawler|spider|robot|crawling/i.test(navigator.userAgent);
}

function getRandomOption() {
if (isBot()) {
// When crawlers visit the page, they should not have to expand items
return DEFAULT_LAYOUT;
}
// A default layout is saved in localstorage at first render to make sure all section start with the same layout.
const savedDefaultOption = localStorage.getItem(
API_LAYOUT_STORAGE_KEYS.default,
) as null | ApiDisplayOptions;

if (savedDefaultOption !== null && options.includes(savedDefaultOption)) {
return savedDefaultOption;
}

const randomOption = options[Math.floor(options.length * Math.random())];
try {
localStorage.setItem(API_LAYOUT_STORAGE_KEYS.default, randomOption);
} catch (error) {
// Do nothing
}
return randomOption;
}

let neverHydrated = true;

function getOption(storageKey: string) {
function getOption(storageKey: string, defaultValue: ApiDisplayOptions): ApiDisplayOptions {
if (neverHydrated) {
return DEFAULT_LAYOUT;
return defaultValue;
}
try {
const savedOption = localStorage.getItem(storageKey);

if (savedOption !== null && options.includes(savedOption as ApiDisplayOptions)) {
return savedOption as ApiDisplayOptions;
}

const randomOption = getRandomOption();

return randomOption;
} catch (error) {
return DEFAULT_LAYOUT;
return defaultValue;
}
return defaultValue;
}

export function useApiPageOption(
storageKey: string,
defaultValue: ApiDisplayOptions,
): [ApiDisplayOptions, (newOption: ApiDisplayOptions) => void] {
const [option, setOption] = React.useState(getOption(storageKey));
const [option, setOption] = React.useState(getOption(storageKey, defaultValue));

useEnhancedEffect(() => {
neverHydrated = false;
const newOption = getOption(storageKey);
const newOption = getOption(storageKey, defaultValue);
setOption(newOption);
}, [storageKey]);
}, [storageKey, defaultValue]);

React.useEffect(() => {
if (option !== DEFAULT_LAYOUT) {
if (option !== defaultValue) {
const id = document.location.hash.slice(1);
const element = document.getElementById(id);
element?.scrollIntoView();
}
return undefined;
}, [option]);
}, [option, defaultValue]);

const updateOption = React.useCallback(
(newOption: ApiDisplayOptions) => {
Expand All @@ -104,20 +71,6 @@ export function useApiPageOption(
return [option, updateOption];
}

export function getApiPageLayout() {
const rep: { [key: string]: string } = {};

Object.values(API_LAYOUT_STORAGE_KEYS).forEach((localStorageKey) => {
try {
const savedOption = localStorage.getItem(localStorageKey);
rep[localStorageKey] = savedOption || 'none';
} catch {
rep[localStorageKey] = 'none';
}
});
return rep;
}

// Fix Toggle buton highlight (taken from https://github.com/mui/material-ui/issues/18091)
type TooltipToggleButtonProps = ToggleButtonProps & {
/**
Expand All @@ -141,10 +94,14 @@ const TooltipToggleButton = React.forwardRef<HTMLButtonElement, TooltipToggleBut
interface ToggleDisplayOptionProps {
displayOption: ApiDisplayOptions;
setDisplayOption: (newValue: ApiDisplayOptions) => void;
/**
* The type of section. This value is used to send correct event to Google Analytics.
*/
sectionType: 'classes' | 'props' | 'slots';
}

export default function ToggleDisplayOption(props: ToggleDisplayOptionProps) {
const { displayOption, setDisplayOption } = props;
const { displayOption, setDisplayOption, sectionType } = props;

const handleAlignment = (
event: React.MouseEvent<HTMLElement>,
Expand Down Expand Up @@ -182,13 +139,34 @@ export default function ToggleDisplayOption(props: ToggleDisplayOptionProps) {
},
}}
>
<TooltipToggleButton value="collapsed" aria-label="colapsed list" title="Collapse list view">
<TooltipToggleButton
value="collapsed"
aria-label="colapsed list"
title="Collapse list view"
data-ga-event-category="layout"
data-ga-event-action={sectionType}
data-ga-event-label="collapsed"
>
<ReorderRoundedIcon size="small" />
</TooltipToggleButton>
<TooltipToggleButton value="expanded" aria-label="expanded list" title="Expand list view">
<TooltipToggleButton
value="expanded"
aria-label="expanded list"
title="Expand list view"
data-ga-event-category="layout"
data-ga-event-action={sectionType}
data-ga-event-label="expanded"
>
<CalendarViewDayRoundedIcon />
</TooltipToggleButton>
<TooltipToggleButton value="table" aria-label="table" title="Table view">
<TooltipToggleButton
value="table"
aria-label="table"
title="Table view"
data-ga-event-category="layout"
data-ga-event-action={sectionType}
data-ga-event-label="table"
>
<TableChartRoundedIcon />
</TooltipToggleButton>
</ToggleButtonGroup>
Expand Down
Loading

0 comments on commit a8563ea

Please sign in to comment.