From 16c9fbf4270785438ad056fe2f6a30caea0bdd58 Mon Sep 17 00:00:00 2001 From: dav-is Date: Fri, 10 Apr 2026 21:53:58 -0400 Subject: [PATCH 01/44] Add `lintJavascriptDemoFocus` eslint plugin --- .circleci/orbs/code-infra.yml | 3 + .../code-highlighter/demos/CodeContent.tsx | 2 + .../demos/CodeContentLoading.tsx | 2 + .../code-highlighter/demos/code/page.tsx | 2 + .../demos/code-editor/CodeController.tsx | 2 + .../demos/code-editor/CodeEditor.tsx | 2 + .../demos/code-editor/CodeEditorContent.tsx | 2 + .../demos/demo-live/DemoController.tsx | 2 + .../demos/demo-live/DemoLive.tsx | 2 + .../demos/demo-live/DemoLiveContent.tsx | 2 + .../demo-live/demo-basic/CheckboxBasic.tsx | 2 + .../demos/multi-file/MultiFileContent.tsx | 2 + .../demos/multi-file/MultiFileEditor.tsx | 2 + .../code-highlighter/demos/CodeBlock.tsx | 2 + .../code-highlighter/demos/CodeContent.tsx | 2 + .../code-highlighter/demos/DemoContent.tsx | 2 + .../demos/code-basic/BasicCode.tsx | 5 +- .../demos/code-highlight-idle/BasicCode.tsx | 5 +- .../demos/code-highlight-idle/Code.tsx | 2 + .../demos/code-highlight-init/BasicCode.tsx | 5 +- .../demos/code-highlight-init/Code.tsx | 2 + .../demos/code-transformed/BasicCode.tsx | 1 + .../demos/code-transformed/Code.tsx | 2 + .../DemoContentLoading.tsx | 2 + .../demo-red/CheckboxRed.tsx | 5 +- .../DemoContentLoading.tsx | 2 + .../demo-red/css-modules/CheckboxRed.tsx | 5 +- .../demo-red/tailwind/CheckboxRed.tsx | 5 +- .../demo-fallback/DemoContentLoading.tsx | 2 + .../demo-fallback/demo-red/CheckboxRed.tsx | 5 +- .../demo-basic/CheckboxBasic.tsx | 5 +- .../demo-default/css-modules/CheckboxRed.tsx | 5 +- .../demo-default/tailwind/CheckboxRed.tsx | 5 +- .../demos/demo/demo-basic/CheckboxBasic.tsx | 5 +- .../components/code-provider/demos/Code.tsx | 2 + .../code-provider/demos/base/BasicCode.tsx | 2 + .../demos/fetch-demo/CodeProviderGitHub.tsx | 2 + .../code-provider/demos/fetch-demo/Docs.tsx | 2 + .../fetch-demo/demo-basic/CheckboxBasic.tsx | 5 +- .../demos/text-input-copy/TextInputCopy.tsx | 2 + .../variant-selector/VariantSelector.tsx | 2 + .../hooks/use-types/demos/TypesTable.tsx | 2 + .../hooks/use-types/demos/basic/Component.tsx | 2 + .../Component/Part/ComponentPart.tsx | 2 + .../Component/Root/ComponentRoot.tsx | 2 + .../demos/blocks-data-attr/TypesComponent.tsx | 2 + .../AlertDialog/AlertDialogTrigger.tsx | 5 +- .../blocks-inherited/Dialog/DialogClose.tsx | 2 + .../blocks-inherited/Dialog/DialogTrigger.tsx | 2 + .../blocks-inherited/TypesAlertDialog.tsx | 2 + .../demos/blocks/Component/ComponentPart.tsx | 2 + .../demos/blocks/Component/ComponentRoot.tsx | 2 + .../use-types/demos/blocks/TypesComponent.tsx | 2 + .../use-types/demos/data-attr/Component.tsx | 2 + .../demos/tab-navigation/TabNavigation.tsx | 2 + .../demos/CodeIndent.tsx | 2 + .../demos/CollapsibleContent.tsx | 2 + .../demos/IndentContent.tsx | 2 + .../lint-javascript-demo-focus/page.mdx | 200 +++++++ .../lint-javascript-demo-focus/types.md | 51 ++ .../lint-javascript-demo-focus/types.ts | 4 + docs/app/docs-infra/pipeline/page.mdx | 26 + eslint.config.mjs | 10 + package.json | 1 + packages/docs-infra/package.json | 2 + .../pipeline/lintJavascriptDemoFocus/index.ts | 1 + .../lintJavascriptDemoFocus.test.ts | 485 +++++++++++++++++ .../lintJavascriptDemoFocus.ts | 488 ++++++++++++++++++ pnpm-lock.yaml | 6 + 69 files changed, 1416 insertions(+), 13 deletions(-) create mode 100644 docs/app/docs-infra/pipeline/lint-javascript-demo-focus/page.mdx create mode 100644 docs/app/docs-infra/pipeline/lint-javascript-demo-focus/types.md create mode 100644 docs/app/docs-infra/pipeline/lint-javascript-demo-focus/types.ts create mode 100644 packages/docs-infra/src/pipeline/lintJavascriptDemoFocus/index.ts create mode 100644 packages/docs-infra/src/pipeline/lintJavascriptDemoFocus/lintJavascriptDemoFocus.test.ts create mode 100644 packages/docs-infra/src/pipeline/lintJavascriptDemoFocus/lintJavascriptDemoFocus.ts diff --git a/.circleci/orbs/code-infra.yml b/.circleci/orbs/code-infra.yml index 7a9972903..b5212fa79 100644 --- a/.circleci/orbs/code-infra.yml +++ b/.circleci/orbs/code-infra.yml @@ -82,6 +82,9 @@ commands: eslint: description: 'Runs ESLint on the codebase' steps: + - run: + name: Build docs-infra for ESLint plugins + command: pnpm run docs:lib - restore_cache: keys: - eslint-cache-{{ checksum "pnpm-lock.yaml" }} diff --git a/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContent.tsx b/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContent.tsx index dd99934a1..fb73829ff 100644 --- a/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContent.tsx +++ b/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContent.tsx @@ -10,7 +10,9 @@ import styles from './CodeContent.module.css'; import '@wooorm/starry-night/style/light'; export function CodeContent(props: ContentProps<{}>) { + // @highlight-start @focus const code = useCode(props, { preClassName: styles.codeBlock }); return
{code.selectedFile}
; + // @highlight-end } diff --git a/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContentLoading.tsx b/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContentLoading.tsx index 8d15dfde8..051462704 100644 --- a/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContentLoading.tsx +++ b/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContentLoading.tsx @@ -9,9 +9,11 @@ import '@wooorm/starry-night/style/light'; export function CodeContentLoading(props: ContentLoadingProps<{}>) { return (
+ {/* @highlight-start @focus */}
{props.source}
+ {/* @highlight-end */}
); } diff --git a/docs/app/bench/docs-infra/components/code-highlighter/demos/code/page.tsx b/docs/app/bench/docs-infra/components/code-highlighter/demos/code/page.tsx index f61f0f8fc..4f30b08f5 100644 --- a/docs/app/bench/docs-infra/components/code-highlighter/demos/code/page.tsx +++ b/docs/app/bench/docs-infra/components/code-highlighter/demos/code/page.tsx @@ -11,6 +11,7 @@ const sourceParser = createParseSource(); export default function Page() { return ( + // @highlight-start @focus {code} + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeController.tsx b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeController.tsx index bb2436740..1fa4b43ae 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeController.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeController.tsx @@ -5,6 +5,7 @@ import { CodeControllerContext } from '@mui/internal-docs-infra/CodeControllerCo import type { ControlledCode } from '@mui/internal-docs-infra/CodeHighlighter/types'; export function CodeController({ children }: { children: React.ReactNode }) { + // @highlight-start @focus const [code, setCode] = React.useState(undefined); const contextValue = React.useMemo(() => ({ code, setCode }), [code, setCode]); @@ -12,4 +13,5 @@ export function CodeController({ children }: { children: React.ReactNode }) { return ( {children} ); + // @highlight-end } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditor.tsx b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditor.tsx index d3dbee261..87790c3d3 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditor.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditor.tsx @@ -20,6 +20,7 @@ function greet(name) { export function CodeEditor() { return ( + // @highlight-start @focus + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditorContent.tsx b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditorContent.tsx index 2f9972650..2fc5bdeef 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditorContent.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditorContent.tsx @@ -10,6 +10,7 @@ import styles from './CodeEditorContent.module.css'; import '@wooorm/starry-night/style/light'; // load the light theme for syntax highlighting export function CodeEditorContent(props: ContentProps) { + // @highlight-start @focus const preRef = React.useRef(null); const code = useCode(props, { preClassName: styles.codeBlock, preRef }); @@ -47,4 +48,5 @@ export function CodeEditorContent(props: ContentProps) {
{code.selectedFile}
); + // @highlight-end } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoController.tsx b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoController.tsx index b42c1ca94..c3bb22508 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoController.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoController.tsx @@ -27,6 +27,7 @@ function Runner({ code }: { code: string }) { } export function DemoController({ children }: { children: React.ReactNode }) { + // @highlight-start @focus const [code, setCode] = React.useState(undefined); const components = React.useMemo( @@ -56,4 +57,5 @@ export function DemoController({ children }: { children: React.ReactNode }) { return ( {children} ); + // @highlight-end } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLive.tsx b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLive.tsx index e634b8568..b0b3103ec 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLive.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLive.tsx @@ -5,10 +5,12 @@ import { DemoCheckboxBasic } from './demo-basic'; export function DemoLive() { return ( + // @highlight-start @focus + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLiveContent.tsx b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLiveContent.tsx index 167c91925..a72cab791 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLiveContent.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLiveContent.tsx @@ -16,6 +16,7 @@ const variantNames: Record = { }; export function DemoLiveContent(props: ContentProps) { + // @highlight-start @focus const preRef = React.useRef(null); const demo = useDemo(props, { preClassName: styles.codeBlock, preRef }); @@ -85,4 +86,5 @@ export function DemoLiveContent(props: ContentProps) { ); + // @highlight-end } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/demo-basic/CheckboxBasic.tsx b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/demo-basic/CheckboxBasic.tsx index 5f008e747..545677549 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/demo-basic/CheckboxBasic.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/demo-basic/CheckboxBasic.tsx @@ -4,8 +4,10 @@ import { Checkbox } from '@/components/Checkbox'; export default function CheckboxBasic() { return (
+ {/* @highlight-start @focus */}

Type Whatever You Want Below

+ {/* @highlight-end */}
); } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileContent.tsx b/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileContent.tsx index a447eebe9..561f3fdc6 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileContent.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileContent.tsx @@ -10,6 +10,7 @@ import styles from '../code-editor/CodeEditorContent.module.css'; import '@wooorm/starry-night/style/light'; export function MultiFileContent(props: ContentProps) { + // @highlight-start @focus const preRef = React.useRef(null); const code = useCode(props, { preClassName: styles.codeBlock, preRef }); @@ -43,4 +44,5 @@ export function MultiFileContent(props: ContentProps) {
{code.selectedFile}
); + // @highlight-end } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileEditor.tsx b/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileEditor.tsx index 8f5affceb..ae0a21e80 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileEditor.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileEditor.tsx @@ -43,6 +43,7 @@ p { export function MultiFileEditor() { return ( + // @highlight-start @focus + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/CodeBlock.tsx b/docs/app/docs-infra/components/code-highlighter/demos/CodeBlock.tsx index 29e0e1a90..c48a91b17 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/CodeBlock.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/CodeBlock.tsx @@ -19,6 +19,7 @@ export function Code({ fileName?: string; }) { return ( + // @highlight-start @focus {children} + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/CodeContent.tsx b/docs/app/docs-infra/components/code-highlighter/demos/CodeContent.tsx index ff6339ce5..b148d9dac 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/CodeContent.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/CodeContent.tsx @@ -16,6 +16,7 @@ const variantNames: Record = { }; export function CodeContent(props: ContentProps) { + // @highlight-start @focus const code = useCode(props, { preClassName: styles.codeBlock }); const hasJsTransform = code.availableTransforms.includes('js'); @@ -85,4 +86,5 @@ export function CodeContent(props: ContentProps) { ); + // @highlight-end } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/DemoContent.tsx b/docs/app/docs-infra/components/code-highlighter/demos/DemoContent.tsx index 294339889..a6bbc87a4 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/DemoContent.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/DemoContent.tsx @@ -16,6 +16,7 @@ const variantNames: Record = { }; export function DemoContent(props: ContentProps) { + // @highlight-start @focus const demo = useDemo(props, { preClassName: styles.codeBlock }); const hasJsTransform = demo.availableTransforms.includes('js'); @@ -82,4 +83,5 @@ export function DemoContent(props: ContentProps) { ); + // @highlight-end } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-basic/BasicCode.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-basic/BasicCode.tsx index 093206112..4c2fadb7c 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-basic/BasicCode.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-basic/BasicCode.tsx @@ -2,5 +2,8 @@ import * as React from 'react'; import { Code } from '../CodeBlock'; export function BasicCode() { - return {`console.log('Hello, world!');`}; + return ( + // @highlight @focus + {`console.log('Hello, world!');`} + ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/BasicCode.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/BasicCode.tsx index a75d04ead..58ed4229f 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/BasicCode.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/BasicCode.tsx @@ -2,5 +2,8 @@ import * as React from 'react'; import { Code } from './Code'; export function BasicCode() { - return {`console.log('Hello, world!');`}; + return ( + // @highlight @focus + {`console.log('Hello, world!');`} + ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/Code.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/Code.tsx index 72b75b3ce..535f2155b 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/Code.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/Code.tsx @@ -10,6 +10,7 @@ const sourceParser = createParseSource(); export function Code({ children, fileName }: { children: string; fileName?: string }) { return ( + // @highlight-start @focus {children} + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/BasicCode.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/BasicCode.tsx index a75d04ead..58ed4229f 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/BasicCode.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/BasicCode.tsx @@ -2,5 +2,8 @@ import * as React from 'react'; import { Code } from './Code'; export function BasicCode() { - return {`console.log('Hello, world!');`}; + return ( + // @highlight @focus + {`console.log('Hello, world!');`} + ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/Code.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/Code.tsx index 72b75b3ce..535f2155b 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/Code.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/Code.tsx @@ -10,6 +10,7 @@ const sourceParser = createParseSource(); export function Code({ children, fileName }: { children: string; fileName?: string }) { return ( + // @highlight-start @focus {children} + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/BasicCode.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/BasicCode.tsx index 5fc1eefda..3e7874e6b 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/BasicCode.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/BasicCode.tsx @@ -3,6 +3,7 @@ import { Code } from './Code'; export function BasicCode() { return ( + // @highlight @focus {`const x: number = 1;\ninterface Props { name: string; }`} ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/Code.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/Code.tsx index da1ff3de1..c2993c64e 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/Code.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/Code.tsx @@ -10,6 +10,7 @@ const sourceTransformers = [TypescriptToJavascriptTransformer]; export function Code({ children, fileName }: { children: string; fileName?: string }) { return ( + // @highlight-start @focus {children} + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/DemoContentLoading.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/DemoContentLoading.tsx index 936980ce8..05b382f6d 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/DemoContentLoading.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/DemoContentLoading.tsx @@ -9,6 +9,7 @@ import loadingStyles from './DemoContentLoading.module.css'; import '@wooorm/starry-night/style/light'; export function DemoContentLoading(props: ContentLoadingProps) { + // @highlight-start @focus const tabs = React.useMemo( () => props.fileNames?.map((name) => ({ @@ -57,4 +58,5 @@ export function DemoContentLoading(props: ContentLoadingProps) { ); + // @highlight-end } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/demo-red/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/demo-red/CheckboxRed.tsx index adc5f88e6..8322e4428 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/demo-red/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/demo-red/CheckboxRed.tsx @@ -3,5 +3,8 @@ import { Checkbox } from '@/components/Checkbox'; import styles from './CheckboxRed.module.css'; export function CheckboxRed() { - return ; + return ( + // @highlight @focus + + ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/DemoContentLoading.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/DemoContentLoading.tsx index 069c8d4aa..78c2658fd 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/DemoContentLoading.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/DemoContentLoading.tsx @@ -14,6 +14,7 @@ const variantNames: Record = { }; export function DemoContentLoading(props: ContentLoadingProps) { + // @highlight-start @focus const tabs = React.useMemo( () => props.fileNames?.map((name) => ({ @@ -89,4 +90,5 @@ export function DemoContentLoading(props: ContentLoadingProps) { ); + // @highlight-end } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/css-modules/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/css-modules/CheckboxRed.tsx index 1df8d8c02..03a0be5a8 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/css-modules/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/css-modules/CheckboxRed.tsx @@ -4,5 +4,8 @@ import { Checkbox } from '@/components/Checkbox'; import styles from './CheckboxRed.module.css'; export function CheckboxRed() { - return ; + return ( + // @highlight @focus + + ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/tailwind/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/tailwind/CheckboxRed.tsx index 6ae30479a..7dfbea8d1 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/tailwind/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/tailwind/CheckboxRed.tsx @@ -2,5 +2,8 @@ import * as React from 'react'; import { Checkbox } from '@/components/Checkbox'; export function CheckboxRed() { - return ; + return ( + // @highlight @focus + + ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/DemoContentLoading.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/DemoContentLoading.tsx index c9f806ced..faa341b65 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/DemoContentLoading.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/DemoContentLoading.tsx @@ -8,6 +8,7 @@ import styles from '../DemoContent.module.css'; import '@wooorm/starry-night/style/light'; export function DemoContentLoading(props: ContentLoadingProps) { + // @highlight-start @focus const tabs = React.useMemo( () => props.fileNames?.map((name) => ({ @@ -51,4 +52,5 @@ export function DemoContentLoading(props: ContentLoadingProps) { ); + // @highlight-end } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/demo-red/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/demo-red/CheckboxRed.tsx index adc5f88e6..8322e4428 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/demo-red/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/demo-red/CheckboxRed.tsx @@ -3,5 +3,8 @@ import { Checkbox } from '@/components/Checkbox'; import styles from './CheckboxRed.module.css'; export function CheckboxRed() { - return ; + return ( + // @highlight @focus + + ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-server-loaded/demo-basic/CheckboxBasic.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-server-loaded/demo-basic/CheckboxBasic.tsx index adcf3533a..74d562e6d 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-server-loaded/demo-basic/CheckboxBasic.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-server-loaded/demo-basic/CheckboxBasic.tsx @@ -2,5 +2,8 @@ import * as React from 'react'; import { Checkbox } from '@/components/Checkbox'; export function CheckboxBasic() { - return ; + return ( + // @highlight @focus + + ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/css-modules/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/css-modules/CheckboxRed.tsx index 1df8d8c02..03a0be5a8 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/css-modules/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/css-modules/CheckboxRed.tsx @@ -4,5 +4,8 @@ import { Checkbox } from '@/components/Checkbox'; import styles from './CheckboxRed.module.css'; export function CheckboxRed() { - return ; + return ( + // @highlight @focus + + ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/tailwind/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/tailwind/CheckboxRed.tsx index f1c788638..de96d696e 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/tailwind/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/tailwind/CheckboxRed.tsx @@ -2,5 +2,8 @@ import * as React from 'react'; import { Checkbox } from '@/components/Checkbox'; export function CheckboxRed() { - return ; + return ( + // @highlight @focus + + ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo/demo-basic/CheckboxBasic.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo/demo-basic/CheckboxBasic.tsx index adcf3533a..74d562e6d 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo/demo-basic/CheckboxBasic.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo/demo-basic/CheckboxBasic.tsx @@ -2,5 +2,8 @@ import * as React from 'react'; import { Checkbox } from '@/components/Checkbox'; export function CheckboxBasic() { - return ; + return ( + // @highlight @focus + + ); } diff --git a/docs/app/docs-infra/components/code-provider/demos/Code.tsx b/docs/app/docs-infra/components/code-provider/demos/Code.tsx index ed07a0a6c..815b257f3 100644 --- a/docs/app/docs-infra/components/code-provider/demos/Code.tsx +++ b/docs/app/docs-infra/components/code-provider/demos/Code.tsx @@ -5,8 +5,10 @@ import { CodeContent } from '../../code-highlighter/demos/CodeContent'; export function Code({ children, fileName }: { children: string; fileName?: string }) { return ( + // @highlight-start @focus {children} + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-provider/demos/base/BasicCode.tsx b/docs/app/docs-infra/components/code-provider/demos/base/BasicCode.tsx index 9f15cdb0e..a84ee1eea 100644 --- a/docs/app/docs-infra/components/code-provider/demos/base/BasicCode.tsx +++ b/docs/app/docs-infra/components/code-provider/demos/base/BasicCode.tsx @@ -4,8 +4,10 @@ import { Code } from '../../../code-highlighter/demos/CodeBlock'; export function BasicCode() { return ( + // @highlight-start @focus {`console.log('Hello, world!');`} + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/CodeProviderGitHub.tsx b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/CodeProviderGitHub.tsx index 456030894..27a43d362 100644 --- a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/CodeProviderGitHub.tsx +++ b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/CodeProviderGitHub.tsx @@ -90,6 +90,7 @@ const loadSource: LoadSource = async (url: string) => { export function CodeProviderGitHub({ children }: { children: React.ReactNode }) { return ( + // @highlight-start @focus {children} + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/Docs.tsx b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/Docs.tsx index 813c0aa53..5bdcc5b71 100644 --- a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/Docs.tsx +++ b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/Docs.tsx @@ -4,8 +4,10 @@ import { DemoCheckboxBasic } from './demo-basic'; export function Docs() { return ( + // @highlight-start @focus + // @highlight-end ); } diff --git a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/demo-basic/CheckboxBasic.tsx b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/demo-basic/CheckboxBasic.tsx index adcf3533a..74d562e6d 100644 --- a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/demo-basic/CheckboxBasic.tsx +++ b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/demo-basic/CheckboxBasic.tsx @@ -2,5 +2,8 @@ import * as React from 'react'; import { Checkbox } from '@/components/Checkbox'; export function CheckboxBasic() { - return ; + return ( + // @highlight @focus + + ); } diff --git a/docs/app/docs-infra/hooks/use-copier/demos/text-input-copy/TextInputCopy.tsx b/docs/app/docs-infra/hooks/use-copier/demos/text-input-copy/TextInputCopy.tsx index a9e2719bc..e0498b5e3 100644 --- a/docs/app/docs-infra/hooks/use-copier/demos/text-input-copy/TextInputCopy.tsx +++ b/docs/app/docs-infra/hooks/use-copier/demos/text-input-copy/TextInputCopy.tsx @@ -4,6 +4,7 @@ import { useCopier } from '@mui/internal-docs-infra/useCopier'; import styles from './TextInputCopy.module.css'; export function TextInputCopy() { + // @highlight-start @focus const [text, setText] = React.useState('Hello, copy me!'); const { copy, recentlySuccessful } = useCopier(() => text); @@ -21,4 +22,5 @@ export function TextInputCopy() { ); + // @highlight-end } diff --git a/docs/app/docs-infra/hooks/use-preference/demos/variant-selector/VariantSelector.tsx b/docs/app/docs-infra/hooks/use-preference/demos/variant-selector/VariantSelector.tsx index 448c6e43c..cbff74e19 100644 --- a/docs/app/docs-infra/hooks/use-preference/demos/variant-selector/VariantSelector.tsx +++ b/docs/app/docs-infra/hooks/use-preference/demos/variant-selector/VariantSelector.tsx @@ -4,6 +4,7 @@ import { usePreference } from '@mui/internal-docs-infra/usePreference'; import styles from './VariantSelector.module.css'; export function VariantSelector() { + // @highlight-start @focus const variants = ['contained', 'outlined', 'text']; const [variant, setVariant] = usePreference('variant', variants, () => 'contained'); @@ -30,4 +31,5 @@ export function VariantSelector() { ); + // @highlight-end } diff --git a/docs/app/docs-infra/hooks/use-types/demos/TypesTable.tsx b/docs/app/docs-infra/hooks/use-types/demos/TypesTable.tsx index 3768c8299..0b57a1b57 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/TypesTable.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/TypesTable.tsx @@ -20,6 +20,7 @@ export type TypesTableProps = BaseTypesTableProps<{}>; export function TypesTable(props: TypesTableProps) { // Get the main type and additional types for this export + // @highlight-start @focus const { type, additionalTypes } = useTypes(props); return ( @@ -37,6 +38,7 @@ export function TypesTable(props: TypesTableProps) { ))} ); + // @highlight-end } function TypeMetaDoc(props: { typeMeta: EnhancedTypesMeta }) { diff --git a/docs/app/docs-infra/hooks/use-types/demos/basic/Component.tsx b/docs/app/docs-infra/hooks/use-types/demos/basic/Component.tsx index 5fba658f6..176722c09 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/basic/Component.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/basic/Component.tsx @@ -13,6 +13,7 @@ interface Props { * A simple component that displays a title and optional children. */ export function Component(props: Props) { + // @highlight-start @focus const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event); }; @@ -23,4 +24,5 @@ export function Component(props: Props) { {!props.disabled ? props.children : null} ); + // @highlight-end } diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Part/ComponentPart.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Part/ComponentPart.tsx index 4c9842d22..9a4981349 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Part/ComponentPart.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Part/ComponentPart.tsx @@ -22,6 +22,7 @@ export interface ComponentPartProps { * A simple component that displays a title and optional children. */ export function ComponentPart(props: ComponentPartProps) { + // @highlight-start @focus const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event, props.input); }; @@ -32,6 +33,7 @@ export function ComponentPart(props: ComponentPartProps) { {!props.disabled ? props.children : null} ); + // @highlight-end } // eslint-disable-next-line @typescript-eslint/no-namespace -- Using namespace for type grouping as per Base UI convention diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Root/ComponentRoot.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Root/ComponentRoot.tsx index 6b62cb924..e41e7dfc1 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Root/ComponentRoot.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Root/ComponentRoot.tsx @@ -38,6 +38,7 @@ export interface ComponentRootProps { * A simple component that displays a title and optional children. */ export function ComponentRoot(props: ComponentRootProps) { + // @highlight-start @focus const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event); @@ -59,6 +60,7 @@ export function ComponentRoot(props: ComponentRootProps) { {!props.disabled ? props.children : null} ); + // @highlight-end } // eslint-disable-next-line @typescript-eslint/no-namespace -- Using namespace for type grouping as per Base UI convention diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/TypesComponent.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/TypesComponent.tsx index 3aa3e79b9..f4dd9933d 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/TypesComponent.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/TypesComponent.tsx @@ -4,6 +4,7 @@ import { TypesComponent as ComponentTypes, TypesComponentAdditional } from './ty export function TypesComponent() { return (
+ {/* @highlight-start @focus */}

Component API

Root

@@ -11,6 +12,7 @@ export function TypesComponent() {

Additional Types

+ {/* @highlight-end */}
); } diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/AlertDialog/AlertDialogTrigger.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/AlertDialog/AlertDialogTrigger.tsx index 049f9c178..bc2104450 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/AlertDialog/AlertDialogTrigger.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/AlertDialog/AlertDialogTrigger.tsx @@ -33,7 +33,10 @@ export const AlertDialogTrigger = React.forwardRef(function AlertDialogTrigger( props: AlertDialogTriggerProps, ref: React.ForwardedRef, ) { - return ; + return ( + // @highlight @focus + + ); }); // eslint-disable-next-line @typescript-eslint/no-namespace, import/export diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogClose.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogClose.tsx index 9a2544ad4..5bf0617c1 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogClose.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogClose.tsx @@ -22,6 +22,7 @@ export const DialogClose = React.forwardRef(function DialogClose( props: DialogCloseProps, ref: React.ForwardedRef, ) { + // @highlight-start @focus const { render, children, ...other } = props; // In a real implementation, triggerState would come from context @@ -32,6 +33,7 @@ export const DialogClose = React.forwardRef(function DialogClose( {render ? render(triggerState) : children} ); + // @highlight-end }); // eslint-disable-next-line @typescript-eslint/no-namespace, import/export diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogTrigger.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogTrigger.tsx index a52b109af..91d110c30 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogTrigger.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogTrigger.tsx @@ -36,6 +36,7 @@ export const DialogTrigger = React.forwardRef(function DialogTrigger( props: DialogTriggerProps, ref: React.ForwardedRef, ) { + // @highlight-start @focus const { className, disabled, children, ...other } = props; const state: DialogTriggerState = React.useMemo( @@ -53,6 +54,7 @@ export const DialogTrigger = React.forwardRef(function DialogTrigger( {children} ); + // @highlight-end }); // eslint-disable-next-line @typescript-eslint/no-namespace, import/export diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/TypesAlertDialog.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/TypesAlertDialog.tsx index fa7299d73..54670f3d9 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/TypesAlertDialog.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/TypesAlertDialog.tsx @@ -4,11 +4,13 @@ import { TypesAlertDialog as AlertDialogTypes } from './types'; export function TypesAlertDialog() { return (
+ {/* @highlight-start @focus */}

Alert Dialog API

Trigger

Close

+ {/* @highlight-end */}
); } diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentPart.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentPart.tsx index 64e9069b6..202a260ac 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentPart.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentPart.tsx @@ -13,6 +13,7 @@ interface Props { * A simple component that displays a title and optional children. */ export function ComponentPart(props: Props) { + // @highlight-start @focus const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event); }; @@ -23,4 +24,5 @@ export function ComponentPart(props: Props) { {!props.disabled ? props.children : null} ); + // @highlight-end } diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentRoot.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentRoot.tsx index 2c6d2cc0d..44f210999 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentRoot.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentRoot.tsx @@ -13,6 +13,7 @@ interface Props { * A simple component that displays a title and optional children. */ export function ComponentRoot(props: Props) { + // @highlight-start @focus const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event); }; @@ -23,4 +24,5 @@ export function ComponentRoot(props: Props) { {!props.disabled ? props.children : null} ); + // @highlight-end } diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks/TypesComponent.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks/TypesComponent.tsx index 6793b2638..c5d396fdc 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks/TypesComponent.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks/TypesComponent.tsx @@ -4,10 +4,12 @@ import { TypesComponent as ComponentTypes } from './types'; export function TypesComponent() { return (
+ {/* @highlight-start @focus */}

ComponentRoot

ComponentPart

+ {/* @highlight-end */}
); } diff --git a/docs/app/docs-infra/hooks/use-types/demos/data-attr/Component.tsx b/docs/app/docs-infra/hooks/use-types/demos/data-attr/Component.tsx index 43daa6cbd..ef2f76921 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/data-attr/Component.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/data-attr/Component.tsx @@ -14,6 +14,7 @@ interface Props { * A simple component that displays a title and optional children. */ export function Component(props: Props) { + // @highlight-start @focus const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event); }; @@ -24,4 +25,5 @@ export function Component(props: Props) { {!props.disabled ? props.children : null} ); + // @highlight-end } diff --git a/docs/app/docs-infra/hooks/use-url-hash-state/demos/tab-navigation/TabNavigation.tsx b/docs/app/docs-infra/hooks/use-url-hash-state/demos/tab-navigation/TabNavigation.tsx index e3e6ef39b..abe05d012 100644 --- a/docs/app/docs-infra/hooks/use-url-hash-state/demos/tab-navigation/TabNavigation.tsx +++ b/docs/app/docs-infra/hooks/use-url-hash-state/demos/tab-navigation/TabNavigation.tsx @@ -14,6 +14,7 @@ const tabs = [ ]; export function TabNavigation() { + // @highlight-start @focus const [hash, setHash] = useUrlHashState(); const activeTab = hash || 'overview'; @@ -39,4 +40,5 @@ export function TabNavigation() { ); + // @highlight-end } diff --git a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CodeIndent.tsx b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CodeIndent.tsx index 6eed34a39..9a0e02ad0 100644 --- a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CodeIndent.tsx +++ b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CodeIndent.tsx @@ -20,11 +20,13 @@ const sourceEnhancers = [enhanceCodeEmphasis]; */ export function CodeIndent({ code }: { code: CodeType }) { return ( + // @highlight-start @focus + // @highlight-end ); } diff --git a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.tsx b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.tsx index 79df021aa..4c6c3a19d 100644 --- a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.tsx +++ b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.tsx @@ -8,6 +8,7 @@ import styles from './CollapsibleContent.module.css'; import '@wooorm/starry-night/style/light'; export function CollapsibleContent(props: ContentProps) { + // @highlight-start @focus const code = useCode(props, { preClassName: styles.codeBlock }); const id = React.useId(); const checkboxId = `${id}-expand`; @@ -23,4 +24,5 @@ export function CollapsibleContent(props: ContentProps) { ); + // @highlight-end } diff --git a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.tsx b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.tsx index d26fa2223..2e51765ca 100644 --- a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.tsx +++ b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.tsx @@ -8,6 +8,7 @@ import styles from './IndentContent.module.css'; import '@wooorm/starry-night/style/light'; export function IndentContent(props: ContentProps) { + // @highlight-start @focus const code = useCode(props, { preClassName: styles.codeBlock }); const [expanded, setExpanded] = React.useState(false); @@ -19,4 +20,5 @@ export function IndentContent(props: ContentProps) { ); + // @highlight-end } diff --git a/docs/app/docs-infra/pipeline/lint-javascript-demo-focus/page.mdx b/docs/app/docs-infra/pipeline/lint-javascript-demo-focus/page.mdx new file mode 100644 index 000000000..c15a840ae --- /dev/null +++ b/docs/app/docs-infra/pipeline/lint-javascript-demo-focus/page.mdx @@ -0,0 +1,200 @@ +# Lint JavaScript Demo Focus + +An ESLint rule that automatically inserts `@highlight` and `@focus` comments around the preview section of demo files. These comments control which parts of the code are highlighted and focused when rendered in documentation. + +## Overview + +Demo files in `docs/app/**/demos/**` need `@highlight` / `@focus` comments so the docs infrastructure knows which code to emphasize. Writing these by hand is tedious and error-prone. This ESLint rule detects the preview section of each demo and auto-fixes the comments in. + +### Key Features + +- **Auto-fixable**: Run `eslint --fix` to insert all comments automatically +- **Smart comment style**: Uses JSX comments (`{/* */}`) inside wrapper elements and JS comments (`//`) elsewhere +- **Single vs multi-line**: Uses `@highlight @focus` for single-line previews and `@highlight-start @focus` / `@highlight-end` for multi-line +- **Named export detection**: Supports both `export default` and named exports (filename match or single-export fallback) +- **Function body highlighting**: Wraps the entire body when hooks or setup statements are present +- **Skip when present**: Files that already contain `@highlight` anywhere are left untouched + +## Installation & Usage + +Import the rule and wire it into your ESLint flat config: + +```js +// eslint.config.mjs +import { lintJavascriptDemoFocus } from '@mui/internal-docs-infra/pipeline/lintJavascriptDemoFocus'; + +export default [ + { + files: ['docs/app/**/demos/**/*.tsx', 'docs/app/**/demos/**/*.jsx'], + plugins: { + 'docs-infra': { rules: { 'require-demo-focus': lintJavascriptDemoFocus } }, + }, + rules: { + 'docs-infra/require-demo-focus': 'error', + }, + }, +]; +``` + +### With `wrapReturn` + +Enable the `wrapReturn` option to wrap bare `return ` statements in parentheses so the highlight comment can be placed inside: + +```js +rules: { + 'docs-infra/require-demo-focus': ['error', { wrapReturn: true }], +}, +``` + +## How It Works + +The rule identifies the main component export of a demo file and inserts comments based on the structure of its return value. + +### 1. Wrapper elements + +When the return contains a wrapper (`div`, `Box`, `Stack`, or `React.Fragment`), JSX comments are inserted inside the wrapper around its children: + +```tsx +// Before +export default function Demo() { + return ( +
+ + +
+ ); +} + +// After fix +export default function Demo() { + return ( +
+ {/* @highlight-start @focus */} + + + {/* @highlight-end */} +
+ ); +} +``` + +For a single child inside a wrapper: + +```tsx +// After fix +export default function Demo() { + return ( +
+ {/* @highlight @focus */} + +
+ ); +} +``` + +### 2. Non-wrapper returns + +When the return is a bare element (not wrapped in `div`, `Box`, `Stack`, or a fragment), JS comments are inserted before the return line: + +```tsx +// Before +export default function Demo() { + return ; +} + +// After fix +export default function Demo() { + // @highlight @focus + return ; +} +``` + +When the return already has parentheses, the comment is placed inside them: + +```tsx +// Before +export default function Demo() { + return ; +} + +// After fix +export default function Demo() { + return ( + // @highlight @focus + + ); +} +``` + +With `wrapReturn: true`, bare returns without parentheses are wrapped so the comment appears inside: + +```tsx +// Before +export default function Demo() { + return ; +} + +// After fix (wrapReturn: true) +export default function Demo() { + return ( + // @highlight @focus + + ); +} +``` + +### 3. Function body highlighting + +When the component has setup code (hooks, variables, etc.) before the return, the entire function body is wrapped: + +```tsx +// Before +export default function Demo() { + const code = useCode(); + return ; +} + +// After fix +export default function Demo() { + // @highlight-start @focus + const code = useCode(); + return ; + // @highlight-end +} +``` + +## Named Export Detection + +Not all demos use `export default`. The rule handles named exports with two strategies: + +1. **Filename match** (preferred): If a named export matches the filename (e.g., `export function CodeEditor` in `CodeEditor.tsx`), that export is used. +2. **Single export fallback**: If there is exactly one named component export and no filename match, that export is used. + +All common export forms are recognized: `export function`, `export const` with arrow or function expressions, and call-wrapped patterns like `React.forwardRef` or `React.memo`. + +```tsx +// CodeEditor.tsx — filename match +export function CodeEditor() { + return ; +} + +// Also exports helpers — only CodeEditor is processed +export function getEditorConfig() { + return {}; +} +``` + +Call-wrapped components work the same way: + +```tsx +// DialogTrigger.tsx — React.forwardRef with filename match +export const DialogTrigger = React.forwardRef(function DialogTrigger(props, ref) { + return ; +}`, + output: `export default function Demo() { + // @highlight @focus + return ; +}`, + errors: [{ messageId: 'missingDemoFocusJsSingle' }], + }, + // Wrapper div with multiple children: {/* start/end */} fix + { + code: `export default function Demo() { + return ( +
+ + +
+ ); +}`, + output: `export default function Demo() { + return ( +
+ {/* @highlight-start @focus */} + + + {/* @highlight-end */} +
+ ); +}`, + errors: [{ messageId: 'missingDemoFocusJsx' }], + }, + // Wrapper Box with single child: {/* single */} fix + { + code: `export default function Demo() { + return ( + + + + ); +}`, + output: `export default function Demo() { + return ( + + {/* @highlight @focus */} + + + ); +}`, + errors: [{ messageId: 'missingDemoFocusJsxSingle' }], + }, + // Wrapper Stack with multiple children: {/* start/end */} fix + { + code: `export default function Demo() { + return ( + + + + + ); +}`, + output: `export default function Demo() { + return ( + <> + {/* @highlight @focus */} + + + ); +}`, + errors: [{ messageId: 'missingDemoFocusJsxSingle' }], + }, + // Arrow function with block body returning bare element: // comment fix + { + code: `export default () => { + return ; +}`, + output: `export default () => { + // @highlight @focus + return ; +}`, + errors: [{ messageId: 'missingDemoFocusJsSingle' }], + }, + // Arrow function with implicit return of bare element: // comment fix + { + code: `export default () => `, + output: `// @highlight @focus\nexport default () => `, + errors: [{ messageId: 'missingDemoFocusJsSingle' }], + }, + // Non-wrapper element inside parentheses: // comment fix + { + code: `export default function Demo() { + return ( + + ); +}`, + output: `export default function Demo() { + return ( + // @highlight @focus + + ); +}`, + errors: [{ messageId: 'missingDemoFocusJsSingle' }], + }, + // Arrow function with wrapper div single child: {/* single */} fix + { + code: `export default () => { + return ( +
+ +
+ ); +}`, + output: `export default () => { + return ( +
+ {/* @highlight @focus */} + +
+ ); +}`, + errors: [{ messageId: 'missingDemoFocusJsxSingle' }], + }, + // Named export function matching filename + { + filename: 'CodeEditor.tsx', + code: `export function CodeEditor() { + return ( +
+ +
+ ); +}`, + output: `export function CodeEditor() { + return ( +
+ {/* @highlight-start @focus */} + +
+ ); +}`, + errors: [{ messageId: 'missingDemoFocusJsx' }], + }, + // Named export const arrow matching filename + { + filename: 'MyDemo.tsx', + code: `export const MyDemo = () => { + return ; +}`, + output: `export const MyDemo = () => { + // @highlight @focus + return ; +}`, + errors: [{ messageId: 'missingDemoFocusJsSingle' }], + }, + // Single named export fallback (no filename match) + { + filename: 'Other.tsx', + code: `export function Demo() { + return ; +}`, + output: `export function Demo() { + // @highlight @focus + return ; +}`, + errors: [{ messageId: 'missingDemoFocusJsSingle' }], + }, + // Named export with filename match preferred over other exports + { + filename: 'Primary.tsx', + code: `export function Helper() { + return helper; +} +export function Primary() { + return ( +
+ +
+ ); +}`, + output: `export function Helper() { + return helper; +} +export function Primary() { + return ( +
+ {/* @highlight-start @focus */} + +
+ ); +}`, + errors: [{ messageId: 'missingDemoFocusJsx' }], + }, + // Function with hooks: highlight entire body + { + code: `export default function Demo() { + const code = useCode(); + return ( +
+ {code.file} +
+ ); +}`, + output: `export default function Demo() { + // @highlight-start @focus + const code = useCode(); + return ( +
+ {code.file} +
+ ); + // @highlight-end +}`, + errors: [{ messageId: 'missingDemoFocusBody' }], + }, + // Named export with hooks: highlight entire body + { + filename: 'CodeContent.tsx', + code: `export function CodeContent(props) { + const code = useCode(props); + return ( +
{code.file}
+ ); +}`, + output: `export function CodeContent(props) { + // @highlight-start @focus + const code = useCode(props); + return ( +
{code.file}
+ ); + // @highlight-end +}`, + errors: [{ messageId: 'missingDemoFocusBody' }], + }, + // Call-wrapped named export: React.forwardRef with filename match + { + filename: 'DialogTrigger.tsx', + code: `export const DialogTrigger = React.forwardRef(function DialogTrigger(props, ref) { + const { disabled, children, ...other } = props; + return ( + + ); +});`, + output: `export const DialogTrigger = React.forwardRef(function DialogTrigger(props, ref) { + // @highlight-start @focus + const { disabled, children, ...other } = props; + return ( + + ); + // @highlight-end +});`, + errors: [{ messageId: 'missingDemoFocusBody' }], + }, + // Call-wrapped named export: React.memo with arrow function + { + filename: 'MemoDemo.tsx', + code: `export const MemoDemo = React.memo(() => { + return ; +});`, + output: `export const MemoDemo = React.memo(() => { + // @highlight @focus + return ; +});`, + errors: [{ messageId: 'missingDemoFocusJsSingle' }], + }, + // Call-wrapped default export: export default React.forwardRef(...) + { + code: `export default React.forwardRef(function Demo(props, ref) { + return ; +});`, + output: `export default React.forwardRef(function Demo(props, ref) { + // @highlight @focus + return ; +});`, + errors: [{ messageId: 'missingDemoFocusJsSingle' }], + }, + ], + }); + }); + + // eslint-disable-next-line vitest/expect-expect -- RuleTester uses its own assertion library + it('should handle wrapReturn option', () => { + ruleTester.run('require-demo-focus', lintJavascriptDemoFocus, { + valid: [], + invalid: [ + // wrapReturn: bare return single-line -> wrap in parens + { + options: [{ wrapReturn: true }], + code: `export default function Demo() { + return ; +}`, + output: `export default function Demo() { + return ( + // @highlight @focus + + ); +}`, + errors: [{ messageId: 'missingDemoFocusJsSingle' }], + }, + // wrapReturn: already has parens, single-line -> just insert comment + { + options: [{ wrapReturn: true }], + code: `export default function Demo() { + return ( + + ); +}`, + output: `export default function Demo() { + return ( + // @highlight @focus + + ); +}`, + errors: [{ messageId: 'missingDemoFocusJsSingle' }], + }, + // wrapReturn: bare return multi-line -> wrap in parens with start/end + { + options: [{ wrapReturn: true }], + code: `export default function Demo() { + return + + ; +}`, + output: `export default function Demo() { + return ( + // @highlight-start @focus + + + + // @highlight-end + ); +}`, + errors: [{ messageId: 'missingDemoFocusJs' }], + }, + // wrapReturn: wrapper elements are unaffected (still use JSX comments) + { + options: [{ wrapReturn: true }], + code: `export default function Demo() { + return ( +
+ +
+ ); +}`, + output: `export default function Demo() { + return ( +
+ {/* @highlight @focus */} + +
+ ); +}`, + errors: [{ messageId: 'missingDemoFocusJsxSingle' }], + }, + // wrapReturn: named export bare return + { + options: [{ wrapReturn: true }], + filename: 'CheckboxRed.tsx', + code: `export function CheckboxRed() { + return ; +}`, + output: `export function CheckboxRed() { + return ( + // @highlight @focus + + ); +}`, + errors: [{ messageId: 'missingDemoFocusJsSingle' }], + }, + ], + }); + }); +}); diff --git a/packages/docs-infra/src/pipeline/lintJavascriptDemoFocus/lintJavascriptDemoFocus.ts b/packages/docs-infra/src/pipeline/lintJavascriptDemoFocus/lintJavascriptDemoFocus.ts new file mode 100644 index 000000000..2fcca7928 --- /dev/null +++ b/packages/docs-infra/src/pipeline/lintJavascriptDemoFocus/lintJavascriptDemoFocus.ts @@ -0,0 +1,488 @@ +import * as path from 'node:path'; +import type { Rule } from 'eslint'; +import type { ExportDefaultDeclaration, ExportNamedDeclaration, Node } from 'estree'; +import type { TSESTree } from '@typescript-eslint/utils'; + +type FunctionLikeNode = ExportDefaultDeclaration['declaration'] | Node; + +const WRAPPER_TAGS = ['div', 'Box', 'Stack']; + +function getTagName(openingElement: TSESTree.JSXOpeningElement): string | null { + if (openingElement.name.type === 'JSXIdentifier') { + return openingElement.name.name; + } + if ( + openingElement.name.type === 'JSXMemberExpression' && + openingElement.name.object.type === 'JSXIdentifier' && + openingElement.name.object.name === 'React' && + openingElement.name.property.name === 'Fragment' + ) { + return 'React.Fragment'; + } + return null; +} + +function isBlankJSXText(child: TSESTree.JSXChild): child is TSESTree.JSXText { + return child.type === 'JSXText' && !/\S/.test(child.value); +} + +function trimBlankJSXText(children: TSESTree.JSXChild[]): TSESTree.JSXChild[] { + return children.filter((child, index, arr) => { + const isSurrounding = index === 0 || index === arr.length - 1; + return !(isSurrounding && isBlankJSXText(child)); + }); +} + +function isWrapperTag(node: TSESTree.JSXElement): boolean { + const tagName = getTagName(node.openingElement); + return tagName !== null && WRAPPER_TAGS.includes(tagName); +} + +function isFragmentTag(node: TSESTree.JSXElement): boolean { + return getTagName(node.openingElement) === 'React.Fragment'; +} + +function isJSXElement(node: unknown): node is TSESTree.JSXElement { + return (node as TSESTree.BaseNode).type === 'JSXElement'; +} + +function isJSXFragment(node: unknown): node is TSESTree.JSXFragment { + return (node as TSESTree.BaseNode).type === 'JSXFragment'; +} + +/** + * Resolves the function body statements from a function-like declaration. + * Handles FunctionDeclaration, ArrowFunctionExpression, and FunctionExpression. + */ +function getFunctionBody(declaration: FunctionLikeNode): Node[] | null { + if (declaration.type === 'FunctionDeclaration' && declaration.body) { + return declaration.body.body; + } + if (declaration.type === 'ArrowFunctionExpression' || declaration.type === 'FunctionExpression') { + if (declaration.body.type === 'BlockStatement') { + return declaration.body.body; + } + return null; + } + return null; +} + +/** + * Gets the implicit return expression from an arrow function with expression body. + */ +function getImplicitReturn(declaration: FunctionLikeNode): Node | null { + if ( + declaration.type === 'ArrowFunctionExpression' && + declaration.body.type !== 'BlockStatement' + ) { + return declaration.body; + } + return null; +} + +/** + * Gets the name of a function-like node. + * For FunctionDeclaration, returns the id name. + */ +function getFunctionName(node: Node): string | null { + if (node.type === 'FunctionDeclaration' && node.id) { + return node.id.name; + } + return null; +} + +/** + * Unwraps call expressions (e.g. React.forwardRef, React.memo) to find the + * inner function argument. Returns the node itself if it is already a function. + */ +function unwrapCallExpression(node: Node): Node | null { + if ( + node.type === 'ArrowFunctionExpression' || + node.type === 'FunctionExpression' || + node.type === 'FunctionDeclaration' + ) { + return node; + } + if (node.type === 'CallExpression') { + for (const arg of node.arguments) { + if (arg.type !== 'SpreadElement') { + const inner = unwrapCallExpression(arg); + if (inner) { + return inner; + } + } + } + } + return null; +} + +interface NamedExportFunction { + name: string | null; + node: FunctionLikeNode; +} + +interface PreviewResult { + nodes: TSESTree.JSXChild[]; + /** Whether the preview nodes are inside a wrapper element (fix can insert JSX comments) */ + insideWrapper: boolean; +} + +/** + * Determines the preview nodes from a returned JSX value. + * Wrappers (div, Box, Stack, fragments) are unwrapped to their trimmed children. + * Non-wrapper elements are returned as-is. + */ +function getPreviewNodes(returnedJSX: unknown): PreviewResult | null { + if (isJSXElement(returnedJSX)) { + if ( + (isWrapperTag(returnedJSX) || isFragmentTag(returnedJSX)) && + returnedJSX.children.length > 0 + ) { + const trimmed = trimBlankJSXText(returnedJSX.children); + if (trimmed.length > 0) { + return { nodes: trimmed, insideWrapper: true }; + } + } + return { nodes: [returnedJSX], insideWrapper: false }; + } + if (isJSXFragment(returnedJSX) && returnedJSX.children.length > 0) { + const trimmed = trimBlankJSXText(returnedJSX.children); + if (trimmed.length > 0) { + return { nodes: trimmed, insideWrapper: true }; + } + } + return null; +} + +/** + * ESLint rule requiring demo files to have highlight-focus comments around the preview section. + */ +export const lintJavascriptDemoFocus = { + meta: { + type: 'suggestion', + docs: { + description: + 'Require demo files to have @highlight-start @focus / @highlight-end comments around the preview section.', + }, + fixable: 'code', + messages: { + missingDemoFocusJsx: + 'Demo file is missing {/* @highlight-start @focus */} and {/* @highlight-end */} comments around the preview section. Run with --fix to add them automatically.', + missingDemoFocusJsxSingle: + 'Demo file is missing {/* @highlight @focus */} comment on the preview line. Run with --fix to add it automatically.', + missingDemoFocusJs: + 'Demo file is missing // @highlight-start @focus and // @highlight-end comments around the preview section. Run with --fix to add them automatically.', + missingDemoFocusJsSingle: + 'Demo file is missing // @highlight @focus comment on the preview line. Run with --fix to add it automatically.', + missingDemoFocusBody: + 'Demo file is missing // @highlight-start @focus and // @highlight-end comments around the function body. Run with --fix to add them automatically.', + } as const, + schema: [ + { + type: 'object', + properties: { + wrapReturn: { + type: 'boolean', + description: + 'When true, bare return statements without parentheses are wrapped in return (...) and the highlight comment is placed inside the parentheses.', + }, + }, + additionalProperties: false, + }, + ], + } as const, + create(context) { + const sourceCode = context.sourceCode; + const sourceText = sourceCode.getText(); + + const options = (context.options[0] ?? {}) as { wrapReturn?: boolean }; + + if (sourceText.includes('@highlight')) { + return {}; + } + + function processFunctionNode(declaration: FunctionLikeNode): void { + const implicitReturn = getImplicitReturn(declaration); + if (implicitReturn) { + const result = getPreviewNodes(implicitReturn); + if (result) { + reportPreview(context, sourceCode, result, null, options); + } + return; + } + + const body = getFunctionBody(declaration); + if (!body || body.length === 0) { + return; + } + + // If the body has more than just a return (e.g. hooks, variables), + // highlight the entire function body + const hasSetupStatements = body.length > 1 || body[0].type !== 'ReturnStatement'; + if (hasSetupStatements) { + const firstStatement = body[0]; + const lastStatement = body[body.length - 1]; + reportFunctionBody(context, sourceCode, firstStatement, lastStatement); + return; + } + + const lastReturn = body[0] as Node & { argument: Node | null }; + if (!lastReturn.argument) { + return; + } + + const result = getPreviewNodes(lastReturn.argument); + if (result) { + reportPreview(context, sourceCode, result, lastReturn, options); + } + } + + let handled = false; + const namedExportFunctions: NamedExportFunction[] = []; + + return { + ExportDefaultDeclaration(node: ExportDefaultDeclaration & Rule.NodeParentExtension) { + handled = true; + const inner = unwrapCallExpression(node.declaration as Node); + processFunctionNode(inner ?? node.declaration); + }, + + ExportNamedDeclaration(node: ExportNamedDeclaration & Rule.NodeParentExtension) { + const { declaration } = node; + if (!declaration) { + return; + } + if (declaration.type === 'FunctionDeclaration') { + namedExportFunctions.push({ name: getFunctionName(declaration), node: declaration }); + return; + } + // Handle `export const Demo = () => ...`, `export const Demo = function() ...`, + // and call-wrapped patterns like `export const Demo = React.forwardRef(function() ...)` + if (declaration.type === 'VariableDeclaration') { + for (const declarator of declaration.declarations) { + if (declarator.init) { + const inner = unwrapCallExpression(declarator.init); + if (inner) { + const name = declarator.id.type === 'Identifier' ? declarator.id.name : null; + namedExportFunctions.push({ name, node: inner }); + } + } + } + } + }, + + 'Program:exit'() { + if (handled || namedExportFunctions.length === 0) { + return; + } + + const filename = path.basename(context.filename, path.extname(context.filename)); + + // Strategy 1: find an exported function whose name matches the filename + const filenameMatch = namedExportFunctions.find((fn) => fn.name === filename); + if (filenameMatch) { + processFunctionNode(filenameMatch.node); + return; + } + + // Strategy 2: if there's exactly one exported function, use it + if (namedExportFunctions.length === 1) { + processFunctionNode(namedExportFunctions[0].node); + } + }, + }; + }, +} satisfies Rule.RuleModule; + +function reportPreview( + context: Rule.RuleContext, + sourceCode: Rule.RuleContext['sourceCode'], + { nodes: previewNodes, insideWrapper }: PreviewResult, + returnStatement: Node | null, + options: { wrapReturn?: boolean }, +): void { + const firstNode = previewNodes[0]; + const lastNode = previewNodes[previewNodes.length - 1]; + const isSingleLine = firstNode.loc.start.line === lastNode.loc.end.line; + + const firstLine = sourceCode.lines[firstNode.loc.start.line - 1]; + const indentation = firstLine.match(/^\s*/)?.[0] ?? ''; + + let messageId: string; + if (insideWrapper) { + messageId = isSingleLine ? 'missingDemoFocusJsxSingle' : 'missingDemoFocusJsx'; + } else { + messageId = isSingleLine ? 'missingDemoFocusJsSingle' : 'missingDemoFocusJs'; + } + + context.report({ + loc: { + start: firstNode.loc.start, + end: lastNode.loc.end, + }, + messageId, + fix(fixer) { + if (insideWrapper && isSingleLine) { + return fixer.insertTextBeforeRange( + firstNode.range, + `{/* @highlight @focus */}\n${indentation}`, + ); + } + if (insideWrapper) { + return [ + fixer.insertTextBeforeRange( + firstNode.range, + `{/* @highlight-start @focus */}\n${indentation}`, + ), + fixer.insertTextAfterRange(lastNode.range, `\n${indentation}{/* @highlight-end */}`), + ]; + } + + // Non-wrapper: wrapReturn wraps bare `return ` in `return (\n // comment\n \n)` + if (options.wrapReturn && returnStatement) { + const hasParens = hasReturnParens(sourceCode, returnStatement); + + if (hasParens) { + // Already `return (...)` — just insert the comment inside + const lineStartOffset = sourceCode.getIndexFromLoc({ + line: firstNode.loc.start.line, + column: 0, + }); + if (isSingleLine) { + return fixer.insertTextBeforeRange( + [lineStartOffset, lineStartOffset], + `${indentation}// @highlight @focus\n`, + ); + } + const lastLineStartOffset = sourceCode.getIndexFromLoc({ + line: lastNode.loc.end.line, + column: 0, + }); + const lastLine = sourceCode.lines[lastNode.loc.end.line - 1]; + const lastIndentation = lastLine.match(/^\s*/)?.[0] ?? ''; + return [ + fixer.insertTextBeforeRange( + [lineStartOffset, lineStartOffset], + `${indentation}// @highlight-start @focus\n`, + ), + fixer.insertTextAfterRange( + [lastLineStartOffset, lastLineStartOffset + lastLine.length], + `\n${lastIndentation}// @highlight-end`, + ), + ]; + } + + // No parens — wrap `return ` into `return (\n // comment\n \n)` + const returnKeywordEnd = returnStatement.range![0] + 'return'.length; + const returnIndentation = + sourceCode.lines[returnStatement.loc!.start.line - 1].match(/^\s*/)?.[0] ?? ''; + const innerIndentation = `${returnIndentation} `; + + if (isSingleLine) { + return [ + fixer.replaceTextRange( + [returnKeywordEnd, firstNode.range[0]], + ` (\n${innerIndentation}// @highlight @focus\n${innerIndentation}`, + ), + fixer.insertTextAfterRange(lastNode.range, `\n${returnIndentation})`), + ]; + } + return [ + fixer.replaceTextRange( + [returnKeywordEnd, firstNode.range[0]], + ` (\n${innerIndentation}// @highlight-start @focus\n${innerIndentation}`, + ), + fixer.insertTextAfterRange( + lastNode.range, + `\n${innerIndentation}// @highlight-end\n${returnIndentation})`, + ), + ]; + } + + // Default non-wrapper: insert JS comment at the start of the line + const lineStartOffset = sourceCode.getIndexFromLoc({ + line: firstNode.loc.start.line, + column: 0, + }); + if (isSingleLine) { + return fixer.insertTextBeforeRange( + [lineStartOffset, lineStartOffset], + `${indentation}// @highlight @focus\n`, + ); + } + const lastLineStartOffset = sourceCode.getIndexFromLoc({ + line: lastNode.loc.end.line, + column: 0, + }); + const lastLine = sourceCode.lines[lastNode.loc.end.line - 1]; + const lastIndentation = lastLine.match(/^\s*/)?.[0] ?? ''; + return [ + fixer.insertTextBeforeRange( + [lineStartOffset, lineStartOffset], + `${indentation}// @highlight-start @focus\n`, + ), + fixer.insertTextAfterRange( + [lastLineStartOffset, lastLineStartOffset + lastLine.length], + `\n${lastIndentation}// @highlight-end`, + ), + ]; + }, + }); +} + +/** + * Checks whether a return statement's argument is wrapped in parentheses. + */ +function hasReturnParens( + sourceCode: Rule.RuleContext['sourceCode'], + returnStatement: Node, +): boolean { + const text = sourceCode.getText(returnStatement as Rule.Node); + const afterReturn = text.slice('return'.length).trimStart(); + return afterReturn.startsWith('('); +} + +/** + * Reports when the entire function body should be highlighted (e.g. when there are hooks/setup). + */ +function reportFunctionBody( + context: Rule.RuleContext, + sourceCode: Rule.RuleContext['sourceCode'], + firstStatement: Node, + lastStatement: Node, +): void { + const firstLine = sourceCode.lines[firstStatement.loc!.start.line - 1]; + const indentation = firstLine.match(/^\s*/)?.[0] ?? ''; + + const lastLine = sourceCode.lines[lastStatement.loc!.end.line - 1]; + const lastIndentation = lastLine.match(/^\s*/)?.[0] ?? ''; + + const lineStartOffset = sourceCode.getIndexFromLoc({ + line: firstStatement.loc!.start.line, + column: 0, + }); + const lastLineStartOffset = sourceCode.getIndexFromLoc({ + line: lastStatement.loc!.end.line, + column: 0, + }); + + context.report({ + loc: { + start: firstStatement.loc!.start, + end: lastStatement.loc!.end, + }, + messageId: 'missingDemoFocusBody', + fix(fixer) { + return [ + fixer.insertTextBeforeRange( + [lineStartOffset, lineStartOffset], + `${indentation}// @highlight-start @focus\n`, + ), + fixer.insertTextAfterRange( + [lastLineStartOffset, lastLineStartOffset + lastLine.length], + `\n${lastIndentation}// @highlight-end`, + ), + ]; + }, + }); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4be53bfb1..10c68ea21 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,6 +28,9 @@ importers: '@mui/internal-code-infra': specifier: workspace:* version: link:packages/code-infra + '@mui/internal-docs-infra': + specifier: workspace:* + version: link:packages/docs-infra/build '@mui/internal-netlify-cache': specifier: workspace:* version: link:packages/netlify-cache @@ -907,6 +910,9 @@ importers: '@types/yargs': specifier: 17.0.35 version: 17.0.35 + '@typescript-eslint/utils': + specifier: ^8.57.1 + version: 8.57.1(eslint@10.0.3(jiti@2.6.1))(typescript@5.9.3) estree-util-to-js: specifier: 2.0.0 version: 2.0.0 From e8eff01a117ac4985798524591d721953dca20a9 Mon Sep 17 00:00:00 2001 From: dav-is Date: Tue, 14 Apr 2026 21:42:50 -0400 Subject: [PATCH 02/44] Add `@focus-start`, `@focus-end` --- .../code-highlighter/demos/CodeContent.tsx | 4 +- .../demos/CodeContentLoading.tsx | 4 +- .../code-highlighter/demos/code/page.tsx | 4 +- .../demos/code-editor/CodeController.tsx | 4 +- .../demos/code-editor/CodeEditor.tsx | 4 +- .../demos/code-editor/CodeEditorContent.tsx | 4 +- .../demos/demo-live/DemoController.tsx | 4 +- .../demos/demo-live/DemoLive.tsx | 4 +- .../demos/demo-live/DemoLiveContent.tsx | 4 +- .../demo-live/demo-basic/CheckboxBasic.tsx | 4 +- .../demos/multi-file/MultiFileContent.tsx | 4 +- .../demos/multi-file/MultiFileEditor.tsx | 4 +- .../code-highlighter/demos/CodeBlock.tsx | 4 +- .../code-highlighter/demos/CodeContent.tsx | 4 +- .../code-highlighter/demos/DemoContent.tsx | 4 +- .../demos/code-basic/BasicCode.tsx | 2 +- .../demos/code-highlight-idle/BasicCode.tsx | 2 +- .../demos/code-highlight-idle/Code.tsx | 4 +- .../demos/code-highlight-init/BasicCode.tsx | 2 +- .../demos/code-highlight-init/Code.tsx | 4 +- .../demos/code-transformed/BasicCode.tsx | 2 +- .../demos/code-transformed/Code.tsx | 4 +- .../DemoContentLoading.tsx | 4 +- .../demo-red/CheckboxRed.tsx | 2 +- .../DemoContentLoading.tsx | 4 +- .../demo-red/css-modules/CheckboxRed.tsx | 2 +- .../demo-red/tailwind/CheckboxRed.tsx | 2 +- .../demo-fallback/DemoContentLoading.tsx | 4 +- .../demo-fallback/demo-red/CheckboxRed.tsx | 2 +- .../demo-basic/CheckboxBasic.tsx | 2 +- .../demo-default/css-modules/CheckboxRed.tsx | 2 +- .../demo-default/tailwind/CheckboxRed.tsx | 2 +- .../demos/demo/demo-basic/CheckboxBasic.tsx | 2 +- .../components/code-provider/demos/Code.tsx | 4 +- .../code-provider/demos/base/BasicCode.tsx | 4 +- .../demos/fetch-demo/CodeProviderGitHub.tsx | 4 +- .../code-provider/demos/fetch-demo/Docs.tsx | 4 +- .../fetch-demo/demo-basic/CheckboxBasic.tsx | 2 +- .../demos/text-input-copy/TextInputCopy.tsx | 4 +- .../variant-selector/VariantSelector.tsx | 4 +- .../hooks/use-types/demos/TypesTable.tsx | 4 +- .../hooks/use-types/demos/basic/Component.tsx | 4 +- .../Component/Part/ComponentPart.tsx | 4 +- .../Component/Root/ComponentRoot.tsx | 4 +- .../demos/blocks-data-attr/TypesComponent.tsx | 4 +- .../AlertDialog/AlertDialogTrigger.tsx | 2 +- .../blocks-inherited/Dialog/DialogClose.tsx | 4 +- .../blocks-inherited/Dialog/DialogTrigger.tsx | 4 +- .../blocks-inherited/TypesAlertDialog.tsx | 4 +- .../demos/blocks/Component/ComponentPart.tsx | 4 +- .../demos/blocks/Component/ComponentRoot.tsx | 4 +- .../use-types/demos/blocks/TypesComponent.tsx | 4 +- .../use-types/demos/data-attr/Component.tsx | 4 +- .../demos/tab-navigation/TabNavigation.tsx | 4 +- .../demos/CodeIndent.tsx | 4 +- .../demos/CollapsibleContent.module.css | 8 +- .../demos/CollapsibleContent.tsx | 4 +- .../demos/IndentContent.module.css | 40 ++++-- .../demos/IndentContent.tsx | 4 +- .../demos/focus-code/FocusCode.tsx | 15 ++- .../demos/indent-code/IndentCode.tsx | 15 ++- .../pipeline/enhance-code-emphasis/page.mdx | 78 +++++++---- .../pipeline/enhance-code-emphasis/types.md | 18 ++- .../lint-javascript-demo-focus/page.mdx | 24 ++-- docs/app/docs-infra/pipeline/page.mdx | 3 +- .../enhanceCodeEmphasis.test.ts | 107 +++++++++++++-- .../enhanceCodeEmphasis.ts | 122 +++++++++++------- .../lintJavascriptDemoFocus.test.ts | 108 ++++++++++------ .../lintJavascriptDemoFocus.ts | 63 ++++----- .../loadPrecomputedCodeHighlighter.ts | 3 + .../parseSource/calculateFrameRanges.test.ts | 98 ++++++++------ .../parseSource/calculateFrameRanges.ts | 34 ++++- .../src/pipeline/parseSource/createFrame.ts | 7 +- .../pipeline/parseSource/restructureFrames.ts | 19 ++- .../transformHtmlCodeBlock.ts | 5 +- 75 files changed, 623 insertions(+), 344 deletions(-) diff --git a/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContent.tsx b/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContent.tsx index fb73829ff..21a4e94e1 100644 --- a/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContent.tsx +++ b/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContent.tsx @@ -10,9 +10,9 @@ import styles from './CodeContent.module.css'; import '@wooorm/starry-night/style/light'; export function CodeContent(props: ContentProps<{}>) { - // @highlight-start @focus + // @focus-start const code = useCode(props, { preClassName: styles.codeBlock }); return
{code.selectedFile}
; - // @highlight-end + // @focus-end } diff --git a/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContentLoading.tsx b/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContentLoading.tsx index 051462704..0eb128a2d 100644 --- a/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContentLoading.tsx +++ b/docs/app/bench/docs-infra/components/code-highlighter/demos/CodeContentLoading.tsx @@ -9,11 +9,11 @@ import '@wooorm/starry-night/style/light'; export function CodeContentLoading(props: ContentLoadingProps<{}>) { return (
- {/* @highlight-start @focus */} + {/* @focus-start */}
{props.source}
- {/* @highlight-end */} + {/* @focus-end */}
); } diff --git a/docs/app/bench/docs-infra/components/code-highlighter/demos/code/page.tsx b/docs/app/bench/docs-infra/components/code-highlighter/demos/code/page.tsx index 4f30b08f5..94910edd0 100644 --- a/docs/app/bench/docs-infra/components/code-highlighter/demos/code/page.tsx +++ b/docs/app/bench/docs-infra/components/code-highlighter/demos/code/page.tsx @@ -11,7 +11,7 @@ const sourceParser = createParseSource(); export default function Page() { return ( - // @highlight-start @focus + // @focus-start {code} - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeController.tsx b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeController.tsx index 1fa4b43ae..8af4ab665 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeController.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeController.tsx @@ -5,7 +5,7 @@ import { CodeControllerContext } from '@mui/internal-docs-infra/CodeControllerCo import type { ControlledCode } from '@mui/internal-docs-infra/CodeHighlighter/types'; export function CodeController({ children }: { children: React.ReactNode }) { - // @highlight-start @focus + // @focus-start const [code, setCode] = React.useState(undefined); const contextValue = React.useMemo(() => ({ code, setCode }), [code, setCode]); @@ -13,5 +13,5 @@ export function CodeController({ children }: { children: React.ReactNode }) { return ( {children} ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditor.tsx b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditor.tsx index 87790c3d3..171e4a180 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditor.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditor.tsx @@ -20,7 +20,7 @@ function greet(name) { export function CodeEditor() { return ( - // @highlight-start @focus + // @focus-start - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditorContent.tsx b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditorContent.tsx index 2fc5bdeef..92e8ec567 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditorContent.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/code-editor/CodeEditorContent.tsx @@ -10,7 +10,7 @@ import styles from './CodeEditorContent.module.css'; import '@wooorm/starry-night/style/light'; // load the light theme for syntax highlighting export function CodeEditorContent(props: ContentProps) { - // @highlight-start @focus + // @focus-start const preRef = React.useRef(null); const code = useCode(props, { preClassName: styles.codeBlock, preRef }); @@ -48,5 +48,5 @@ export function CodeEditorContent(props: ContentProps) {
{code.selectedFile}
); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoController.tsx b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoController.tsx index c3bb22508..e737e9f2c 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoController.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoController.tsx @@ -27,7 +27,7 @@ function Runner({ code }: { code: string }) { } export function DemoController({ children }: { children: React.ReactNode }) { - // @highlight-start @focus + // @focus-start const [code, setCode] = React.useState(undefined); const components = React.useMemo( @@ -57,5 +57,5 @@ export function DemoController({ children }: { children: React.ReactNode }) { return ( {children} ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLive.tsx b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLive.tsx index b0b3103ec..bdeaa435b 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLive.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLive.tsx @@ -5,12 +5,12 @@ import { DemoCheckboxBasic } from './demo-basic'; export function DemoLive() { return ( - // @highlight-start @focus + // @focus-start - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLiveContent.tsx b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLiveContent.tsx index a72cab791..129dfc5cc 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLiveContent.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/DemoLiveContent.tsx @@ -16,7 +16,7 @@ const variantNames: Record = { }; export function DemoLiveContent(props: ContentProps) { - // @highlight-start @focus + // @focus-start const preRef = React.useRef(null); const demo = useDemo(props, { preClassName: styles.codeBlock, preRef }); @@ -86,5 +86,5 @@ export function DemoLiveContent(props: ContentProps) { ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/demo-basic/CheckboxBasic.tsx b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/demo-basic/CheckboxBasic.tsx index 545677549..68a44a51b 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/demo-live/demo-basic/CheckboxBasic.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/demo-live/demo-basic/CheckboxBasic.tsx @@ -4,10 +4,10 @@ import { Checkbox } from '@/components/Checkbox'; export default function CheckboxBasic() { return (
- {/* @highlight-start @focus */} + {/* @focus-start */}

Type Whatever You Want Below

- {/* @highlight-end */} + {/* @focus-end */}
); } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileContent.tsx b/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileContent.tsx index 561f3fdc6..925b3dcf0 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileContent.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileContent.tsx @@ -10,7 +10,7 @@ import styles from '../code-editor/CodeEditorContent.module.css'; import '@wooorm/starry-night/style/light'; export function MultiFileContent(props: ContentProps) { - // @highlight-start @focus + // @focus-start const preRef = React.useRef(null); const code = useCode(props, { preClassName: styles.codeBlock, preRef }); @@ -44,5 +44,5 @@ export function MultiFileContent(props: ContentProps) {
{code.selectedFile}
); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileEditor.tsx b/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileEditor.tsx index ae0a21e80..9552bc272 100644 --- a/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileEditor.tsx +++ b/docs/app/docs-infra/components/code-controller-context/demos/multi-file/MultiFileEditor.tsx @@ -43,7 +43,7 @@ p { export function MultiFileEditor() { return ( - // @highlight-start @focus + // @focus-start - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/CodeBlock.tsx b/docs/app/docs-infra/components/code-highlighter/demos/CodeBlock.tsx index c48a91b17..051be9fe5 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/CodeBlock.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/CodeBlock.tsx @@ -19,7 +19,7 @@ export function Code({ fileName?: string; }) { return ( - // @highlight-start @focus + // @focus-start {children} - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/CodeContent.tsx b/docs/app/docs-infra/components/code-highlighter/demos/CodeContent.tsx index b148d9dac..69019e0e9 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/CodeContent.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/CodeContent.tsx @@ -16,7 +16,7 @@ const variantNames: Record = { }; export function CodeContent(props: ContentProps) { - // @highlight-start @focus + // @focus-start const code = useCode(props, { preClassName: styles.codeBlock }); const hasJsTransform = code.availableTransforms.includes('js'); @@ -86,5 +86,5 @@ export function CodeContent(props: ContentProps) { ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/DemoContent.tsx b/docs/app/docs-infra/components/code-highlighter/demos/DemoContent.tsx index a6bbc87a4..28c5ef380 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/DemoContent.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/DemoContent.tsx @@ -16,7 +16,7 @@ const variantNames: Record = { }; export function DemoContent(props: ContentProps) { - // @highlight-start @focus + // @focus-start const demo = useDemo(props, { preClassName: styles.codeBlock }); const hasJsTransform = demo.availableTransforms.includes('js'); @@ -83,5 +83,5 @@ export function DemoContent(props: ContentProps) { ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-basic/BasicCode.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-basic/BasicCode.tsx index 4c2fadb7c..bf4d23d95 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-basic/BasicCode.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-basic/BasicCode.tsx @@ -3,7 +3,7 @@ import { Code } from '../CodeBlock'; export function BasicCode() { return ( - // @highlight @focus + // @focus {`console.log('Hello, world!');`} ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/BasicCode.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/BasicCode.tsx index 58ed4229f..e54933609 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/BasicCode.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/BasicCode.tsx @@ -3,7 +3,7 @@ import { Code } from './Code'; export function BasicCode() { return ( - // @highlight @focus + // @focus {`console.log('Hello, world!');`} ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/Code.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/Code.tsx index 535f2155b..e3fa7f597 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/Code.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-idle/Code.tsx @@ -10,7 +10,7 @@ const sourceParser = createParseSource(); export function Code({ children, fileName }: { children: string; fileName?: string }) { return ( - // @highlight-start @focus + // @focus-start {children} - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/BasicCode.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/BasicCode.tsx index 58ed4229f..e54933609 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/BasicCode.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/BasicCode.tsx @@ -3,7 +3,7 @@ import { Code } from './Code'; export function BasicCode() { return ( - // @highlight @focus + // @focus {`console.log('Hello, world!');`} ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/Code.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/Code.tsx index 535f2155b..e3fa7f597 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/Code.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-highlight-init/Code.tsx @@ -10,7 +10,7 @@ const sourceParser = createParseSource(); export function Code({ children, fileName }: { children: string; fileName?: string }) { return ( - // @highlight-start @focus + // @focus-start {children} - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/BasicCode.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/BasicCode.tsx index 3e7874e6b..dc2573e5d 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/BasicCode.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/BasicCode.tsx @@ -3,7 +3,7 @@ import { Code } from './Code'; export function BasicCode() { return ( - // @highlight @focus + // @focus {`const x: number = 1;\ninterface Props { name: string; }`} ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/Code.tsx b/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/Code.tsx index c2993c64e..3b519dbdd 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/Code.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/code-transformed/Code.tsx @@ -10,7 +10,7 @@ const sourceTransformers = [TypescriptToJavascriptTransformer]; export function Code({ children, fileName }: { children: string; fileName?: string }) { return ( - // @highlight-start @focus + // @focus-start {children} - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/DemoContentLoading.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/DemoContentLoading.tsx index 05b382f6d..73329fef5 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/DemoContentLoading.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/DemoContentLoading.tsx @@ -9,7 +9,7 @@ import loadingStyles from './DemoContentLoading.module.css'; import '@wooorm/starry-night/style/light'; export function DemoContentLoading(props: ContentLoadingProps) { - // @highlight-start @focus + // @focus-start const tabs = React.useMemo( () => props.fileNames?.map((name) => ({ @@ -58,5 +58,5 @@ export function DemoContentLoading(props: ContentLoadingProps) { ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/demo-red/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/demo-red/CheckboxRed.tsx index 8322e4428..86db42ccc 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/demo-red/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-files/demo-red/CheckboxRed.tsx @@ -4,7 +4,7 @@ import styles from './CheckboxRed.module.css'; export function CheckboxRed() { return ( - // @highlight @focus + // @focus ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/DemoContentLoading.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/DemoContentLoading.tsx index 78c2658fd..6482adb9a 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/DemoContentLoading.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/DemoContentLoading.tsx @@ -14,7 +14,7 @@ const variantNames: Record = { }; export function DemoContentLoading(props: ContentLoadingProps) { - // @highlight-start @focus + // @focus-start const tabs = React.useMemo( () => props.fileNames?.map((name) => ({ @@ -90,5 +90,5 @@ export function DemoContentLoading(props: ContentLoadingProps) { ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/css-modules/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/css-modules/CheckboxRed.tsx index 03a0be5a8..c38da79d1 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/css-modules/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/css-modules/CheckboxRed.tsx @@ -5,7 +5,7 @@ import styles from './CheckboxRed.module.css'; export function CheckboxRed() { return ( - // @highlight @focus + // @focus ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/tailwind/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/tailwind/CheckboxRed.tsx index 7dfbea8d1..bfe6e82c4 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/tailwind/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback-all-variants/demo-red/tailwind/CheckboxRed.tsx @@ -3,7 +3,7 @@ import { Checkbox } from '@/components/Checkbox'; export function CheckboxRed() { return ( - // @highlight @focus + // @focus ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/DemoContentLoading.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/DemoContentLoading.tsx index faa341b65..493d2cc3a 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/DemoContentLoading.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/DemoContentLoading.tsx @@ -8,7 +8,7 @@ import styles from '../DemoContent.module.css'; import '@wooorm/starry-night/style/light'; export function DemoContentLoading(props: ContentLoadingProps) { - // @highlight-start @focus + // @focus-start const tabs = React.useMemo( () => props.fileNames?.map((name) => ({ @@ -52,5 +52,5 @@ export function DemoContentLoading(props: ContentLoadingProps) { ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/demo-red/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/demo-red/CheckboxRed.tsx index 8322e4428..86db42ccc 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/demo-red/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-fallback/demo-red/CheckboxRed.tsx @@ -4,7 +4,7 @@ import styles from './CheckboxRed.module.css'; export function CheckboxRed() { return ( - // @highlight @focus + // @focus ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-server-loaded/demo-basic/CheckboxBasic.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-server-loaded/demo-basic/CheckboxBasic.tsx index 74d562e6d..30e1d8fa8 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-server-loaded/demo-basic/CheckboxBasic.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-server-loaded/demo-basic/CheckboxBasic.tsx @@ -3,7 +3,7 @@ import { Checkbox } from '@/components/Checkbox'; export function CheckboxBasic() { return ( - // @highlight @focus + // @focus ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/css-modules/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/css-modules/CheckboxRed.tsx index 03a0be5a8..c38da79d1 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/css-modules/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/css-modules/CheckboxRed.tsx @@ -5,7 +5,7 @@ import styles from './CheckboxRed.module.css'; export function CheckboxRed() { return ( - // @highlight @focus + // @focus ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/tailwind/CheckboxRed.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/tailwind/CheckboxRed.tsx index de96d696e..6804e9994 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/tailwind/CheckboxRed.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo-variants/demo-default/tailwind/CheckboxRed.tsx @@ -3,7 +3,7 @@ import { Checkbox } from '@/components/Checkbox'; export function CheckboxRed() { return ( - // @highlight @focus + // @focus ); } diff --git a/docs/app/docs-infra/components/code-highlighter/demos/demo/demo-basic/CheckboxBasic.tsx b/docs/app/docs-infra/components/code-highlighter/demos/demo/demo-basic/CheckboxBasic.tsx index 74d562e6d..30e1d8fa8 100644 --- a/docs/app/docs-infra/components/code-highlighter/demos/demo/demo-basic/CheckboxBasic.tsx +++ b/docs/app/docs-infra/components/code-highlighter/demos/demo/demo-basic/CheckboxBasic.tsx @@ -3,7 +3,7 @@ import { Checkbox } from '@/components/Checkbox'; export function CheckboxBasic() { return ( - // @highlight @focus + // @focus ); } diff --git a/docs/app/docs-infra/components/code-provider/demos/Code.tsx b/docs/app/docs-infra/components/code-provider/demos/Code.tsx index 815b257f3..61b1b6db3 100644 --- a/docs/app/docs-infra/components/code-provider/demos/Code.tsx +++ b/docs/app/docs-infra/components/code-provider/demos/Code.tsx @@ -5,10 +5,10 @@ import { CodeContent } from '../../code-highlighter/demos/CodeContent'; export function Code({ children, fileName }: { children: string; fileName?: string }) { return ( - // @highlight-start @focus + // @focus-start {children} - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-provider/demos/base/BasicCode.tsx b/docs/app/docs-infra/components/code-provider/demos/base/BasicCode.tsx index a84ee1eea..6d4e98758 100644 --- a/docs/app/docs-infra/components/code-provider/demos/base/BasicCode.tsx +++ b/docs/app/docs-infra/components/code-provider/demos/base/BasicCode.tsx @@ -4,10 +4,10 @@ import { Code } from '../../../code-highlighter/demos/CodeBlock'; export function BasicCode() { return ( - // @highlight-start @focus + // @focus-start {`console.log('Hello, world!');`} - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/CodeProviderGitHub.tsx b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/CodeProviderGitHub.tsx index 27a43d362..401c1fc46 100644 --- a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/CodeProviderGitHub.tsx +++ b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/CodeProviderGitHub.tsx @@ -90,7 +90,7 @@ const loadSource: LoadSource = async (url: string) => { export function CodeProviderGitHub({ children }: { children: React.ReactNode }) { return ( - // @highlight-start @focus + // @focus-start {children} - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/Docs.tsx b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/Docs.tsx index 5bdcc5b71..e22a98b84 100644 --- a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/Docs.tsx +++ b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/Docs.tsx @@ -4,10 +4,10 @@ import { DemoCheckboxBasic } from './demo-basic'; export function Docs() { return ( - // @highlight-start @focus + // @focus-start - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/demo-basic/CheckboxBasic.tsx b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/demo-basic/CheckboxBasic.tsx index 74d562e6d..30e1d8fa8 100644 --- a/docs/app/docs-infra/components/code-provider/demos/fetch-demo/demo-basic/CheckboxBasic.tsx +++ b/docs/app/docs-infra/components/code-provider/demos/fetch-demo/demo-basic/CheckboxBasic.tsx @@ -3,7 +3,7 @@ import { Checkbox } from '@/components/Checkbox'; export function CheckboxBasic() { return ( - // @highlight @focus + // @focus ); } diff --git a/docs/app/docs-infra/hooks/use-copier/demos/text-input-copy/TextInputCopy.tsx b/docs/app/docs-infra/hooks/use-copier/demos/text-input-copy/TextInputCopy.tsx index e0498b5e3..b4c4737bb 100644 --- a/docs/app/docs-infra/hooks/use-copier/demos/text-input-copy/TextInputCopy.tsx +++ b/docs/app/docs-infra/hooks/use-copier/demos/text-input-copy/TextInputCopy.tsx @@ -4,7 +4,7 @@ import { useCopier } from '@mui/internal-docs-infra/useCopier'; import styles from './TextInputCopy.module.css'; export function TextInputCopy() { - // @highlight-start @focus + // @focus-start const [text, setText] = React.useState('Hello, copy me!'); const { copy, recentlySuccessful } = useCopier(() => text); @@ -22,5 +22,5 @@ export function TextInputCopy() { ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/hooks/use-preference/demos/variant-selector/VariantSelector.tsx b/docs/app/docs-infra/hooks/use-preference/demos/variant-selector/VariantSelector.tsx index cbff74e19..c6ab15c29 100644 --- a/docs/app/docs-infra/hooks/use-preference/demos/variant-selector/VariantSelector.tsx +++ b/docs/app/docs-infra/hooks/use-preference/demos/variant-selector/VariantSelector.tsx @@ -4,7 +4,7 @@ import { usePreference } from '@mui/internal-docs-infra/usePreference'; import styles from './VariantSelector.module.css'; export function VariantSelector() { - // @highlight-start @focus + // @focus-start const variants = ['contained', 'outlined', 'text']; const [variant, setVariant] = usePreference('variant', variants, () => 'contained'); @@ -31,5 +31,5 @@ export function VariantSelector() { ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/hooks/use-types/demos/TypesTable.tsx b/docs/app/docs-infra/hooks/use-types/demos/TypesTable.tsx index 0b57a1b57..2815f853b 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/TypesTable.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/TypesTable.tsx @@ -20,7 +20,7 @@ export type TypesTableProps = BaseTypesTableProps<{}>; export function TypesTable(props: TypesTableProps) { // Get the main type and additional types for this export - // @highlight-start @focus + // @focus-start const { type, additionalTypes } = useTypes(props); return ( @@ -38,7 +38,7 @@ export function TypesTable(props: TypesTableProps) { ))} ); - // @highlight-end + // @focus-end } function TypeMetaDoc(props: { typeMeta: EnhancedTypesMeta }) { diff --git a/docs/app/docs-infra/hooks/use-types/demos/basic/Component.tsx b/docs/app/docs-infra/hooks/use-types/demos/basic/Component.tsx index 176722c09..02aee0661 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/basic/Component.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/basic/Component.tsx @@ -13,7 +13,7 @@ interface Props { * A simple component that displays a title and optional children. */ export function Component(props: Props) { - // @highlight-start @focus + // @focus-start const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event); }; @@ -24,5 +24,5 @@ export function Component(props: Props) { {!props.disabled ? props.children : null} ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Part/ComponentPart.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Part/ComponentPart.tsx index 9a4981349..f2ffc24e5 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Part/ComponentPart.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Part/ComponentPart.tsx @@ -22,7 +22,7 @@ export interface ComponentPartProps { * A simple component that displays a title and optional children. */ export function ComponentPart(props: ComponentPartProps) { - // @highlight-start @focus + // @focus-start const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event, props.input); }; @@ -33,7 +33,7 @@ export function ComponentPart(props: ComponentPartProps) { {!props.disabled ? props.children : null} ); - // @highlight-end + // @focus-end } // eslint-disable-next-line @typescript-eslint/no-namespace -- Using namespace for type grouping as per Base UI convention diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Root/ComponentRoot.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Root/ComponentRoot.tsx index e41e7dfc1..d6db3e094 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Root/ComponentRoot.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/Component/Root/ComponentRoot.tsx @@ -38,7 +38,7 @@ export interface ComponentRootProps { * A simple component that displays a title and optional children. */ export function ComponentRoot(props: ComponentRootProps) { - // @highlight-start @focus + // @focus-start const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event); @@ -60,7 +60,7 @@ export function ComponentRoot(props: ComponentRootProps) { {!props.disabled ? props.children : null} ); - // @highlight-end + // @focus-end } // eslint-disable-next-line @typescript-eslint/no-namespace -- Using namespace for type grouping as per Base UI convention diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/TypesComponent.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/TypesComponent.tsx index f4dd9933d..a174bc693 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/TypesComponent.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-data-attr/TypesComponent.tsx @@ -4,7 +4,7 @@ import { TypesComponent as ComponentTypes, TypesComponentAdditional } from './ty export function TypesComponent() { return (
- {/* @highlight-start @focus */} + {/* @focus-start */}

Component API

Root

@@ -12,7 +12,7 @@ export function TypesComponent() {

Additional Types

- {/* @highlight-end */} + {/* @focus-end */}
); } diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/AlertDialog/AlertDialogTrigger.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/AlertDialog/AlertDialogTrigger.tsx index bc2104450..366ead7e3 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/AlertDialog/AlertDialogTrigger.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/AlertDialog/AlertDialogTrigger.tsx @@ -34,7 +34,7 @@ export const AlertDialogTrigger = React.forwardRef(function AlertDialogTrigger( ref: React.ForwardedRef, ) { return ( - // @highlight @focus + // @focus ); }); diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogClose.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogClose.tsx index 5bf0617c1..4b531db15 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogClose.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogClose.tsx @@ -22,7 +22,7 @@ export const DialogClose = React.forwardRef(function DialogClose( props: DialogCloseProps, ref: React.ForwardedRef, ) { - // @highlight-start @focus + // @focus-start const { render, children, ...other } = props; // In a real implementation, triggerState would come from context @@ -33,7 +33,7 @@ export const DialogClose = React.forwardRef(function DialogClose( {render ? render(triggerState) : children} ); - // @highlight-end + // @focus-end }); // eslint-disable-next-line @typescript-eslint/no-namespace, import/export diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogTrigger.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogTrigger.tsx index 91d110c30..92db61860 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogTrigger.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/Dialog/DialogTrigger.tsx @@ -36,7 +36,7 @@ export const DialogTrigger = React.forwardRef(function DialogTrigger( props: DialogTriggerProps, ref: React.ForwardedRef, ) { - // @highlight-start @focus + // @focus-start const { className, disabled, children, ...other } = props; const state: DialogTriggerState = React.useMemo( @@ -54,7 +54,7 @@ export const DialogTrigger = React.forwardRef(function DialogTrigger( {children} ); - // @highlight-end + // @focus-end }); // eslint-disable-next-line @typescript-eslint/no-namespace, import/export diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/TypesAlertDialog.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/TypesAlertDialog.tsx index 54670f3d9..8bf4d14e0 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/TypesAlertDialog.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks-inherited/TypesAlertDialog.tsx @@ -4,13 +4,13 @@ import { TypesAlertDialog as AlertDialogTypes } from './types'; export function TypesAlertDialog() { return (
- {/* @highlight-start @focus */} + {/* @focus-start */}

Alert Dialog API

Trigger

Close

- {/* @highlight-end */} + {/* @focus-end */}
); } diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentPart.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentPart.tsx index 202a260ac..d2c081591 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentPart.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentPart.tsx @@ -13,7 +13,7 @@ interface Props { * A simple component that displays a title and optional children. */ export function ComponentPart(props: Props) { - // @highlight-start @focus + // @focus-start const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event); }; @@ -24,5 +24,5 @@ export function ComponentPart(props: Props) { {!props.disabled ? props.children : null} ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentRoot.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentRoot.tsx index 44f210999..520cb3949 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentRoot.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks/Component/ComponentRoot.tsx @@ -13,7 +13,7 @@ interface Props { * A simple component that displays a title and optional children. */ export function ComponentRoot(props: Props) { - // @highlight-start @focus + // @focus-start const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event); }; @@ -24,5 +24,5 @@ export function ComponentRoot(props: Props) { {!props.disabled ? props.children : null} ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/hooks/use-types/demos/blocks/TypesComponent.tsx b/docs/app/docs-infra/hooks/use-types/demos/blocks/TypesComponent.tsx index c5d396fdc..f4e049c8a 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/blocks/TypesComponent.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/blocks/TypesComponent.tsx @@ -4,12 +4,12 @@ import { TypesComponent as ComponentTypes } from './types'; export function TypesComponent() { return (
- {/* @highlight-start @focus */} + {/* @focus-start */}

ComponentRoot

ComponentPart

- {/* @highlight-end */} + {/* @focus-end */}
); } diff --git a/docs/app/docs-infra/hooks/use-types/demos/data-attr/Component.tsx b/docs/app/docs-infra/hooks/use-types/demos/data-attr/Component.tsx index ef2f76921..2fc2e774c 100644 --- a/docs/app/docs-infra/hooks/use-types/demos/data-attr/Component.tsx +++ b/docs/app/docs-infra/hooks/use-types/demos/data-attr/Component.tsx @@ -14,7 +14,7 @@ interface Props { * A simple component that displays a title and optional children. */ export function Component(props: Props) { - // @highlight-start @focus + // @focus-start const handleClick = (event: React.MouseEvent) => { console.warn('Clicked', event); }; @@ -25,5 +25,5 @@ export function Component(props: Props) { {!props.disabled ? props.children : null} ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/hooks/use-url-hash-state/demos/tab-navigation/TabNavigation.tsx b/docs/app/docs-infra/hooks/use-url-hash-state/demos/tab-navigation/TabNavigation.tsx index abe05d012..cea894043 100644 --- a/docs/app/docs-infra/hooks/use-url-hash-state/demos/tab-navigation/TabNavigation.tsx +++ b/docs/app/docs-infra/hooks/use-url-hash-state/demos/tab-navigation/TabNavigation.tsx @@ -14,7 +14,7 @@ const tabs = [ ]; export function TabNavigation() { - // @highlight-start @focus + // @focus-start const [hash, setHash] = useUrlHashState(); const activeTab = hash || 'overview'; @@ -40,5 +40,5 @@ export function TabNavigation() { ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CodeIndent.tsx b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CodeIndent.tsx index 9a0e02ad0..f262e1d4f 100644 --- a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CodeIndent.tsx +++ b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CodeIndent.tsx @@ -20,13 +20,13 @@ const sourceEnhancers = [enhanceCodeEmphasis]; */ export function CodeIndent({ code }: { code: CodeType }) { return ( - // @highlight-start @focus + // @focus-start - // @highlight-end + // @focus-end ); } diff --git a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.module.css b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.module.css index eec6babd9..f2eb0eadc 100644 --- a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.module.css +++ b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.module.css @@ -103,9 +103,10 @@ /* ---- Collapsible frame behavior ---- */ -/* Normal frames and unfocused highlighted frames are hidden by default (collapsed) */ +/* Normal frames and unfocused highlighted/focus frames are hidden by default (collapsed) */ .codeBlock :global(.frame:not([data-frame-type])), -.codeBlock :global(.frame[data-frame-type='highlighted-unfocused']) { +.codeBlock :global(.frame[data-frame-type='highlighted-unfocused']), +.codeBlock :global(.frame[data-frame-type='focus-unfocused']) { max-height: 0; overflow: hidden; opacity: 0; @@ -123,7 +124,8 @@ /* When checkbox is checked (expanded), show all frames */ .checkbox:checked ~ .code .codeBlock :global(.frame:not([data-frame-type])), -.checkbox:checked ~ .code .codeBlock :global(.frame[data-frame-type='highlighted-unfocused']) { +.checkbox:checked ~ .code .codeBlock :global(.frame[data-frame-type='highlighted-unfocused']), +.checkbox:checked ~ .code .codeBlock :global(.frame[data-frame-type='focus-unfocused']) { max-height: 500px; overflow: visible; opacity: 1; diff --git a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.tsx b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.tsx index 4c6c3a19d..e48a0e786 100644 --- a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.tsx +++ b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/CollapsibleContent.tsx @@ -8,7 +8,7 @@ import styles from './CollapsibleContent.module.css'; import '@wooorm/starry-night/style/light'; export function CollapsibleContent(props: ContentProps) { - // @highlight-start @focus + // @focus-start const code = useCode(props, { preClassName: styles.codeBlock }); const id = React.useId(); const checkboxId = `${id}-expand`; @@ -24,5 +24,5 @@ export function CollapsibleContent(props: ContentProps) { ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.module.css b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.module.css index 7d9b0efde..031de83b3 100644 --- a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.module.css +++ b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.module.css @@ -70,9 +70,10 @@ /* ---- Collapsible frame behavior (no padding, just highlighted vs normal) ---- */ -/* Normal frames and unfocused highlighted frames are hidden by default */ +/* Normal frames and unfocused highlighted/focus frames are hidden by default */ .codeBlock :global(.frame:not([data-frame-type])), -.codeBlock :global(.frame[data-frame-type='highlighted-unfocused']) { +.codeBlock :global(.frame[data-frame-type='highlighted-unfocused']), +.codeBlock :global(.frame[data-frame-type='focus-unfocused']) { max-height: 0; overflow: hidden; opacity: 0; @@ -83,51 +84,62 @@ /* When expanded, show all frames */ .expanded .codeBlock :global(.frame:not([data-frame-type])), -.expanded .codeBlock :global(.frame[data-frame-type='highlighted-unfocused']) { +.expanded .codeBlock :global(.frame[data-frame-type='highlighted-unfocused']), +.expanded .codeBlock :global(.frame[data-frame-type='focus-unfocused']) { max-height: 500px; overflow: visible; opacity: 1; } -/* ---- Indent shifting: move highlighted frame left by its indent level ---- */ +/* ---- Indent shifting: move highlighted/focus frame left by its indent level ---- */ -.codeBlock :global(.frame[data-frame-type='highlighted']) { +.codeBlock :global(.frame[data-frame-type='highlighted']), +.codeBlock :global(.frame[data-frame-type='focus']) { transition: margin-left 0.3s ease; } -.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='1']) { +.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='1']), +.codeBlock :global(.frame[data-frame-type='focus'][data-frame-indent='1']) { margin-left: -2ch; } -.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='2']) { +.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='2']), +.codeBlock :global(.frame[data-frame-type='focus'][data-frame-indent='2']) { margin-left: -4ch; } -.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='3']) { +.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='3']), +.codeBlock :global(.frame[data-frame-type='focus'][data-frame-indent='3']) { margin-left: -6ch; } -.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='4']) { +.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='4']), +.codeBlock :global(.frame[data-frame-type='focus'][data-frame-indent='4']) { margin-left: -8ch; } -.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='5']) { +.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='5']), +.codeBlock :global(.frame[data-frame-type='focus'][data-frame-indent='5']) { margin-left: -10ch; } -.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='6']) { +.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='6']), +.codeBlock :global(.frame[data-frame-type='focus'][data-frame-indent='6']) { margin-left: -12ch; } -.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='7']) { +.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='7']), +.codeBlock :global(.frame[data-frame-type='focus'][data-frame-indent='7']) { margin-left: -14ch; } -.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='8']) { +.codeBlock :global(.frame[data-frame-type='highlighted'][data-frame-indent='8']), +.codeBlock :global(.frame[data-frame-type='focus'][data-frame-indent='8']) { margin-left: -16ch; } /* Reset indent shift when expanded */ -.expanded .codeBlock :global(.frame[data-frame-type='highlighted']) { +.expanded .codeBlock :global(.frame[data-frame-type='highlighted']), +.expanded .codeBlock :global(.frame[data-frame-type='focus']) { margin-left: 0; } diff --git a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.tsx b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.tsx index 2e51765ca..b9cfb1b36 100644 --- a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.tsx +++ b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/IndentContent.tsx @@ -8,7 +8,7 @@ import styles from './IndentContent.module.css'; import '@wooorm/starry-night/style/light'; export function IndentContent(props: ContentProps) { - // @highlight-start @focus + // @focus-start const code = useCode(props, { preClassName: styles.codeBlock }); const [expanded, setExpanded] = React.useState(false); @@ -20,5 +20,5 @@ export function IndentContent(props: ContentProps) { ); - // @highlight-end + // @focus-end } diff --git a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/focus-code/FocusCode.tsx b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/focus-code/FocusCode.tsx index 0852a0eef..1cc9100ca 100644 --- a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/focus-code/FocusCode.tsx +++ b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/focus-code/FocusCode.tsx @@ -1,7 +1,10 @@ import * as React from 'react'; import type { Code as CodeType } from '@mui/internal-docs-infra/CodeHighlighter/types'; import { parseImportsAndComments } from '@mui/internal-docs-infra/pipeline/loaderUtils'; -import { EMPHASIS_COMMENT_PREFIX } from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis'; +import { + EMPHASIS_COMMENT_PREFIX, + FOCUS_COMMENT_PREFIX, +} from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis'; import { Code } from '../Code'; const source = `import * as React from 'react'; @@ -13,11 +16,11 @@ const today = formatDate(new Date()); // @highlight export function Calendar() { const [events, setEvents] = React.useState([]); - // @highlight-start @focus + // @focus-start React.useEffect(() => { fetchEvents(today).then(setEvents); }, []); - // @highlight-end + // @focus-end return (
@@ -32,9 +35,10 @@ export function Calendar() { }`; export async function FocusCode() { + // @focus-start const { code: strippedSource, comments } = await parseImportsAndComments(source, '/demo.tsx', { - removeCommentsWithPrefix: [EMPHASIS_COMMENT_PREFIX], - notableCommentsPrefix: [EMPHASIS_COMMENT_PREFIX], + removeCommentsWithPrefix: [EMPHASIS_COMMENT_PREFIX, FOCUS_COMMENT_PREFIX], + notableCommentsPrefix: [EMPHASIS_COMMENT_PREFIX, FOCUS_COMMENT_PREFIX], }); const code: CodeType = { @@ -46,4 +50,5 @@ export async function FocusCode() { }; return ; + // @focus-end } diff --git a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/indent-code/IndentCode.tsx b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/indent-code/IndentCode.tsx index e6b27cfed..47169eed8 100644 --- a/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/indent-code/IndentCode.tsx +++ b/docs/app/docs-infra/pipeline/enhance-code-emphasis/demos/indent-code/IndentCode.tsx @@ -1,7 +1,10 @@ import * as React from 'react'; import type { Code as CodeType } from '@mui/internal-docs-infra/CodeHighlighter/types'; import { parseImportsAndComments } from '@mui/internal-docs-infra/pipeline/loaderUtils'; -import { EMPHASIS_COMMENT_PREFIX } from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis'; +import { + EMPHASIS_COMMENT_PREFIX, + FOCUS_COMMENT_PREFIX, +} from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis'; import { CodeIndent } from '../CodeIndent'; const source = `import * as React from 'react'; @@ -18,7 +21,7 @@ export function ScheduleView() {
- {/* @highlight-start @focus */} + {/* @focus-start */} - {/* @highlight-end */} + {/* @focus-end */}