From 0f238145457d47c126f5eb409914cd7da64d2e54 Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Thu, 4 Dec 2025 16:26:26 -0800 Subject: [PATCH 01/15] Added first implementation, dropdown --- .../DetailedCode/DetailedCodeBody/index.tsx | 19 +++++ .../DetailedCode/DetailedCodeButton/index.tsx | 60 ++++++++++++++++ packages/gamut/src/DetailedCode/elements.tsx | 45 ++++++++++++ packages/gamut/src/DetailedCode/index.tsx | 36 ++++++++++ packages/gamut/src/DetailedCode/types.ts | 18 +++++ packages/gamut/src/index.tsx | 1 + .../ConnectedForm/ConnectedForm.mdx | 72 +------------------ .../ConnectedForm/codeExample.ts | 68 ++++++++++++++++++ 8 files changed, 250 insertions(+), 69 deletions(-) create mode 100644 packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx create mode 100644 packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx create mode 100644 packages/gamut/src/DetailedCode/elements.tsx create mode 100644 packages/gamut/src/DetailedCode/index.tsx create mode 100644 packages/gamut/src/DetailedCode/types.ts create mode 100644 packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/codeExample.ts diff --git a/packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx b/packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx new file mode 100644 index 00000000000..4a5658d0694 --- /dev/null +++ b/packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx @@ -0,0 +1,19 @@ +import { Source } from '@storybook/blocks'; +import { ComponentProps } from 'react'; +import * as React from 'react'; + +import { DetailedCodeBodyWrapper } from '../elements'; +import { DetailedCodeBodyProps } from '../types'; + +type SourceLanguage = ComponentProps['language']; + +export const DetailedCodeBody: React.FC = ({ + code, + language, +}) => { + return ( + + + + ); +}; diff --git a/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx b/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx new file mode 100644 index 00000000000..cb2dd575ad9 --- /dev/null +++ b/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx @@ -0,0 +1,60 @@ +import { MiniChevronDownIcon } from '@codecademy/gamut-icons'; +import * as React from 'react'; + +import { Rotation } from '../../Animation'; +import { Box, FlexBox } from '../../Box'; +import { Text } from '../../Typography'; +import { DetailedCodeButtonWrapper } from '../elements'; +import { DetailedCodeButtonProps } from '../types'; + +export const DetailedCodeButton: React.FC = ({ + heading, + isExpanded, + language, + setIsExpanded, +}) => { + const handleClick = () => { + if (setIsExpanded) { + setIsExpanded((prev: boolean) => !prev); + } + }; + + return ( + + + + + {heading && ( + + {heading} + + )} + + {language} + + + + + + + + + + + + ); +}; diff --git a/packages/gamut/src/DetailedCode/elements.tsx b/packages/gamut/src/DetailedCode/elements.tsx new file mode 100644 index 00000000000..769476a0b13 --- /dev/null +++ b/packages/gamut/src/DetailedCode/elements.tsx @@ -0,0 +1,45 @@ +import { css } from '@codecademy/gamut-styles'; +import styled from '@emotion/styled'; + +import { Anchor } from '../Anchor'; +import { FlexBox } from '../Box'; + +export const DetailedCodeWrapper = styled(FlexBox)( + css({ + width: '100%', + maxHeight: 'fit-content', + borderRadius: 'md', + border: 1, + bg: 'background', + }) +); + +export const DetailedCodeButtonWrapper = styled(Anchor)( + css({ + borderRadius: 'md', + bg: 'inherit', + '&:hover': { + color: 'text', + bg: 'background-hover', + }, + '&:focus': { + color: 'text', + bg: 'background-selected', + }, + }) +); + +export const DetailedCodeBodyWrapper = styled(FlexBox)({ + overflow: 'hidden', + '& pre': { + margin: 0, + }, + '& > div': { + borderRadius: 0, + padding: 0, + }, + // Remove margin from storybook source block, override default margin (25 top, 40 bottom) + '& .docblock-source': { + margin: 0, + }, +}); diff --git a/packages/gamut/src/DetailedCode/index.tsx b/packages/gamut/src/DetailedCode/index.tsx new file mode 100644 index 00000000000..93456a845fd --- /dev/null +++ b/packages/gamut/src/DetailedCode/index.tsx @@ -0,0 +1,36 @@ +import { AnimatePresence } from 'framer-motion'; +import { useState } from 'react'; +import * as React from 'react'; + +import { ExpandInCollapseOut } from '../Animation'; +import { DetailedCodeBody } from './DetailedCodeBody'; +import { DetailedCodeButton } from './DetailedCodeButton'; +import { DetailedCodeWrapper } from './elements'; +import { DetailedCodeProps } from './types'; + +export const DetailedCode: React.FC = ({ + code, + heading, + initiallyExpanded = false, + language, +}) => { + const [isExpanded, setIsExpanded] = useState(initiallyExpanded); + + return ( + + + + {isExpanded && ( + + + + )} + + + ); +}; diff --git a/packages/gamut/src/DetailedCode/types.ts b/packages/gamut/src/DetailedCode/types.ts new file mode 100644 index 00000000000..92198171275 --- /dev/null +++ b/packages/gamut/src/DetailedCode/types.ts @@ -0,0 +1,18 @@ +export interface DetailedCodeProps { + code: string; + heading?: string; + language: string; + initiallyExpanded?: boolean; +} + +export interface DetailedCodeButtonProps { + heading?: string; + isExpanded?: boolean; + language: string; + setIsExpanded?: React.Dispatch>; +} + +export interface DetailedCodeBodyProps { + code: string; + language: string; +} diff --git a/packages/gamut/src/index.tsx b/packages/gamut/src/index.tsx index 0537494d5db..13d7c10c139 100644 --- a/packages/gamut/src/index.tsx +++ b/packages/gamut/src/index.tsx @@ -16,6 +16,7 @@ export * from './Coachmark'; export * from './ConnectedForm'; export * from './ContentContainer'; export * from './DelayedRenderWrapper'; +export * from './DetailedCode'; export * from './Disclosure'; export * from './DataList'; export * from './Drawer'; diff --git a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx index b71619aed57..da323ae10d8 100644 --- a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx +++ b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx @@ -1,7 +1,9 @@ +import { DetailedCode } from '@codecademy/gamut'; import { Canvas, Controls, Meta } from '@storybook/blocks'; import { ComponentHeader, LinkTo } from '~styleguide/blocks'; +import { codeExample } from './codeExample'; import * as ConnectedFormStories from './ConnectedForm.stories'; export const parameters = { @@ -40,75 +42,7 @@ This hook also returns the `FormRequiredText` component - include this before yo ### Example code -```tsx -import { - ConnectedCheckbox, - ConnectedInput, - ConnectedSelect, - useConnectedForm, -} from '@codecademy/gamut'; - -import { TerminalIcon } from '@codecademy/gamut-icons'; - -export const GoodForm = () => { - const { - ConnectedFormGroup, - ConnectedForm, - connectedFormProps, - FormRequiredText, - } = useConnectedForm({ - defaultValues: { - thisField: true, - thatField: 'zero', - anotherField: 'state your name.', - }, - validationRules: { - thisField: { required: 'you need to check this.' }, - thatField: { - pattern: { - value: /^(?:(?!zero).)*$/, - message: 'literally anything but zero', - }, - }, - }, - }); - - return ( - console.log(thisField)} - resetOnSubmit - {...connectedFormProps} - > - submit this form. - - - - - - ); -}; -``` + ## Variants diff --git a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/codeExample.ts b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/codeExample.ts new file mode 100644 index 00000000000..07ac5cd1497 --- /dev/null +++ b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/codeExample.ts @@ -0,0 +1,68 @@ +export const codeExample = `import { + ConnectedCheckbox, + ConnectedInput, + ConnectedSelect, + useConnectedForm, +} from '@codecademy/gamut'; + +import { TerminalIcon } from '@codecademy/gamut-icons'; + +export const GoodForm = () => { + const { + ConnectedFormGroup, + ConnectedForm, + connectedFormProps, + FormRequiredText, + } = useConnectedForm({ + defaultValues: { + thisField: true, + thatField: 'zero', + anotherField: 'state your name.', + }, + validationRules: { + thisField: { required: 'you need to check this.' }, + thatField: { + pattern: { + value: /^(?:(?!zero).)*$/, + message: 'literally anything but zero', + }, + }, + }, + }); + + return ( + console.log(thisField)} + resetOnSubmit + {...connectedFormProps} + > + submit this form. + + + + + + ); +};`; + From a95a191a06cbe5876829a806612988b29682c00f Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Fri, 5 Dec 2025 09:54:29 -0800 Subject: [PATCH 02/15] Try preview --- packages/gamut/src/DetailedCode/index.tsx | 25 +++++++++++++++++++ packages/gamut/src/DetailedCode/types.ts | 2 ++ .../ConnectedForm/ConnectedForm.mdx | 2 +- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/gamut/src/DetailedCode/index.tsx b/packages/gamut/src/DetailedCode/index.tsx index 93456a845fd..cafb1e90d65 100644 --- a/packages/gamut/src/DetailedCode/index.tsx +++ b/packages/gamut/src/DetailedCode/index.tsx @@ -8,14 +8,36 @@ import { DetailedCodeButton } from './DetailedCodeButton'; import { DetailedCodeWrapper } from './elements'; import { DetailedCodeProps } from './types'; +const DEFAULT_PREVIEW_LINES = 10; + +const getPreviewCode = (code: string, previewLines: number) => { + const trimmedLines = code.split('\n'); + + if (trimmedLines.length <= previewLines) { + return code; + } + + return `${trimmedLines.slice(0, previewLines).join('\n')}\n...`; +}; + export const DetailedCode: React.FC = ({ code, heading, initiallyExpanded = false, language, + preview = false, + previewLines = DEFAULT_PREVIEW_LINES, }) => { const [isExpanded, setIsExpanded] = useState(initiallyExpanded); + + const normalizedPreviewLines = Math.max(0, previewLines); + const previewEnabled = preview && normalizedPreviewLines > 0; + const shouldShowPreview = previewEnabled && !isExpanded; + const previewCode = previewEnabled + ? getPreviewCode(code, normalizedPreviewLines) + : code; + return ( = ({ language={language} setIsExpanded={setIsExpanded} /> + {shouldShowPreview && ( + + )} {isExpanded && ( diff --git a/packages/gamut/src/DetailedCode/types.ts b/packages/gamut/src/DetailedCode/types.ts index 92198171275..fcf528d3e79 100644 --- a/packages/gamut/src/DetailedCode/types.ts +++ b/packages/gamut/src/DetailedCode/types.ts @@ -3,6 +3,8 @@ export interface DetailedCodeProps { heading?: string; language: string; initiallyExpanded?: boolean; + preview?: boolean; + previewLines?: number; } export interface DetailedCodeButtonProps { diff --git a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx index da323ae10d8..6d1bba28b06 100644 --- a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx +++ b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx @@ -42,7 +42,7 @@ This hook also returns the `FormRequiredText` component - include this before yo ### Example code - + ## Variants From ac512c6fbce60ff8cdb460aeab483ca9e0da5c23 Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Tue, 20 Jan 2026 01:17:20 -0800 Subject: [PATCH 03/15] move button to bottom and remove weird styling visual issue --- packages/gamut/src/DetailedCode/elements.tsx | 8 ---- packages/gamut/src/DetailedCode/index.tsx | 39 ++++++++------------ 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/packages/gamut/src/DetailedCode/elements.tsx b/packages/gamut/src/DetailedCode/elements.tsx index 769476a0b13..0498368fe6b 100644 --- a/packages/gamut/src/DetailedCode/elements.tsx +++ b/packages/gamut/src/DetailedCode/elements.tsx @@ -18,14 +18,6 @@ export const DetailedCodeButtonWrapper = styled(Anchor)( css({ borderRadius: 'md', bg: 'inherit', - '&:hover': { - color: 'text', - bg: 'background-hover', - }, - '&:focus': { - color: 'text', - bg: 'background-selected', - }, }) ); diff --git a/packages/gamut/src/DetailedCode/index.tsx b/packages/gamut/src/DetailedCode/index.tsx index cafb1e90d65..5ce1657973b 100644 --- a/packages/gamut/src/DetailedCode/index.tsx +++ b/packages/gamut/src/DetailedCode/index.tsx @@ -1,8 +1,6 @@ -import { AnimatePresence } from 'framer-motion'; import { useState } from 'react'; import * as React from 'react'; -import { ExpandInCollapseOut } from '../Animation'; import { DetailedCodeBody } from './DetailedCodeBody'; import { DetailedCodeButton } from './DetailedCodeButton'; import { DetailedCodeWrapper } from './elements'; @@ -11,13 +9,13 @@ import { DetailedCodeProps } from './types'; const DEFAULT_PREVIEW_LINES = 10; const getPreviewCode = (code: string, previewLines: number) => { - const trimmedLines = code.split('\n'); + const lines = code.split('\n'); - if (trimmedLines.length <= previewLines) { + if (lines.length <= previewLines) { return code; } - return `${trimmedLines.slice(0, previewLines).join('\n')}\n...`; + return lines.slice(0, previewLines).join('\n'); }; export const DetailedCode: React.FC = ({ @@ -29,33 +27,28 @@ export const DetailedCode: React.FC = ({ previewLines = DEFAULT_PREVIEW_LINES, }) => { const [isExpanded, setIsExpanded] = useState(initiallyExpanded); - - const normalizedPreviewLines = Math.max(0, previewLines); const previewEnabled = preview && normalizedPreviewLines > 0; - const shouldShowPreview = previewEnabled && !isExpanded; const previewCode = previewEnabled ? getPreviewCode(code, normalizedPreviewLines) : code; + // Show the button to expand the code if there is more code than the preview lines, and hide the button if there is no more code + const hasMoreCode = previewEnabled && code.split('\n').length > normalizedPreviewLines; + + const displayedCode = isExpanded ? code : previewCode; + return ( - - {shouldShowPreview && ( - + + {hasMoreCode && ( + )} - - {isExpanded && ( - - - - )} - ); }; From 51d159d24f26ecfdf942fa5d1f74888d038e4a77 Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Tue, 20 Jan 2026 11:34:11 -0800 Subject: [PATCH 04/15] update for linter --- .../src/DetailedCode/DetailedCodeButton/index.tsx | 14 ++++++++++++-- packages/gamut/src/DetailedCode/index.tsx | 3 ++- .../ConnectedForm/ConnectedForm/ConnectedForm.mdx | 2 +- .../ConnectedForm/ConnectedForm/codeExample.ts | 1 - 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx b/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx index cb2dd575ad9..0c9e7496679 100644 --- a/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx +++ b/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx @@ -39,11 +39,21 @@ export const DetailedCodeButton: React.FC = ({ > {heading && ( - + {heading} )} - + {language} diff --git a/packages/gamut/src/DetailedCode/index.tsx b/packages/gamut/src/DetailedCode/index.tsx index 5ce1657973b..75bf2554a90 100644 --- a/packages/gamut/src/DetailedCode/index.tsx +++ b/packages/gamut/src/DetailedCode/index.tsx @@ -34,7 +34,8 @@ export const DetailedCode: React.FC = ({ : code; // Show the button to expand the code if there is more code than the preview lines, and hide the button if there is no more code - const hasMoreCode = previewEnabled && code.split('\n').length > normalizedPreviewLines; + const hasMoreCode = + previewEnabled && code.split('\n').length > normalizedPreviewLines; const displayedCode = isExpanded ? code : previewCode; diff --git a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx index 6d1bba28b06..957a5afddc1 100644 --- a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx +++ b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx @@ -42,7 +42,7 @@ This hook also returns the `FormRequiredText` component - include this before yo ### Example code - + ## Variants diff --git a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/codeExample.ts b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/codeExample.ts index 07ac5cd1497..ba57103c289 100644 --- a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/codeExample.ts +++ b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/codeExample.ts @@ -65,4 +65,3 @@ export const GoodForm = () => { ); };`; - From d0a7dad2efe811969ce7547b5172b2f9908f9c9e Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Tue, 20 Jan 2026 11:50:22 -0800 Subject: [PATCH 05/15] update test snapshot --- packages/gamut/__tests__/__snapshots__/gamut.test.ts.snap | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/gamut/__tests__/__snapshots__/gamut.test.ts.snap b/packages/gamut/__tests__/__snapshots__/gamut.test.ts.snap index 8511c5708f6..44fc7b19873 100644 --- a/packages/gamut/__tests__/__snapshots__/gamut.test.ts.snap +++ b/packages/gamut/__tests__/__snapshots__/gamut.test.ts.snap @@ -33,6 +33,7 @@ exports[`Gamut Exported Keys 1`] = ` "DataList", "DataTable", "DelayedRenderWrapper", + "DetailedCode", "Dialog", "Disclosure", "Drawer", From 2711ba71356fce1e8a297a92a690ad6fca32d740 Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Tue, 20 Jan 2026 13:31:19 -0800 Subject: [PATCH 06/15] add helper in inconsistent styling --- packages/gamut/src/DetailedCode/elements.tsx | 29 ++++++++++---------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/gamut/src/DetailedCode/elements.tsx b/packages/gamut/src/DetailedCode/elements.tsx index 0498368fe6b..30005c6196a 100644 --- a/packages/gamut/src/DetailedCode/elements.tsx +++ b/packages/gamut/src/DetailedCode/elements.tsx @@ -21,17 +21,18 @@ export const DetailedCodeButtonWrapper = styled(Anchor)( }) ); -export const DetailedCodeBodyWrapper = styled(FlexBox)({ - overflow: 'hidden', - '& pre': { - margin: 0, - }, - '& > div': { - borderRadius: 0, - padding: 0, - }, - // Remove margin from storybook source block, override default margin (25 top, 40 bottom) - '& .docblock-source': { - margin: 0, - }, -}); +export const DetailedCodeBodyWrapper = styled(FlexBox)( + css({ + overflow: 'hidden', + '& pre': { + margin: 0, + }, + '& > div': { + borderRadius: 'none', + padding: 0, + }, + '& .docblock-source': { + margin: 0, + }, + }) +); From ccc004e433adbf126f7ad9db63dba349814eb71a Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Tue, 3 Feb 2026 01:12:38 -0800 Subject: [PATCH 07/15] Incorporate feedback --- .../DetailedCode/DetailedCodeBody/index.tsx | 2 +- .../DetailedCode/DetailedCodeButton/index.tsx | 69 ++++++------------- packages/gamut/src/DetailedCode/elements.tsx | 21 ++---- packages/gamut/src/DetailedCode/index.tsx | 12 ++-- packages/gamut/src/DetailedCode/types.ts | 3 - .../ConnectedForm/ConnectedForm.mdx | 4 +- .../{codeExample.ts => example.ts} | 2 +- 7 files changed, 33 insertions(+), 80 deletions(-) rename packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/{codeExample.ts => example.ts} (97%) diff --git a/packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx b/packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx index 4a5658d0694..35f9492d238 100644 --- a/packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx +++ b/packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx @@ -12,7 +12,7 @@ export const DetailedCodeBody: React.FC = ({ language, }) => { return ( - + ); diff --git a/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx b/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx index 0c9e7496679..54042c1ec21 100644 --- a/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx +++ b/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx @@ -1,16 +1,14 @@ import { MiniChevronDownIcon } from '@codecademy/gamut-icons'; import * as React from 'react'; +import { Anchor } from '../../Anchor'; import { Rotation } from '../../Animation'; -import { Box, FlexBox } from '../../Box'; +import { FlexBox } from '../../Box'; import { Text } from '../../Typography'; -import { DetailedCodeButtonWrapper } from '../elements'; import { DetailedCodeButtonProps } from '../types'; export const DetailedCodeButton: React.FC = ({ - heading, isExpanded, - language, setIsExpanded, }) => { const handleClick = () => { @@ -20,51 +18,26 @@ export const DetailedCodeButton: React.FC = ({ }; return ( - - + - - - {heading && ( - - {heading} - - )} - - {language} - - - - - - - - - - - + {isExpanded ? 'Show Less Code' : 'Show More Code'} + + + + + ); }; diff --git a/packages/gamut/src/DetailedCode/elements.tsx b/packages/gamut/src/DetailedCode/elements.tsx index 30005c6196a..8297bf95e1b 100644 --- a/packages/gamut/src/DetailedCode/elements.tsx +++ b/packages/gamut/src/DetailedCode/elements.tsx @@ -1,37 +1,24 @@ import { css } from '@codecademy/gamut-styles'; import styled from '@emotion/styled'; -import { Anchor } from '../Anchor'; import { FlexBox } from '../Box'; export const DetailedCodeWrapper = styled(FlexBox)( css({ width: '100%', - maxHeight: 'fit-content', + flexDirection: 'column', borderRadius: 'md', border: 1, bg: 'background', }) ); -export const DetailedCodeButtonWrapper = styled(Anchor)( - css({ - borderRadius: 'md', - bg: 'inherit', - }) -); - export const DetailedCodeBodyWrapper = styled(FlexBox)( css({ - overflow: 'hidden', - '& pre': { - margin: 0, - }, - '& > div': { - borderRadius: 'none', - padding: 0, - }, + flexDirection: 'column', + /* Override Storybook's Source component default styles to remove unwanted spacing and borders in the container */ '& .docblock-source': { + borderRadius: 'none', margin: 0, }, }) diff --git a/packages/gamut/src/DetailedCode/index.tsx b/packages/gamut/src/DetailedCode/index.tsx index 75bf2554a90..3696643c8f2 100644 --- a/packages/gamut/src/DetailedCode/index.tsx +++ b/packages/gamut/src/DetailedCode/index.tsx @@ -1,5 +1,4 @@ -import { useState } from 'react'; -import * as React from 'react'; +import React, { useState } from 'react'; import { DetailedCodeBody } from './DetailedCodeBody'; import { DetailedCodeButton } from './DetailedCodeButton'; @@ -7,6 +6,7 @@ import { DetailedCodeWrapper } from './elements'; import { DetailedCodeProps } from './types'; const DEFAULT_PREVIEW_LINES = 10; +const DEFAULT_LANGUAGE = 'tsx'; const getPreviewCode = (code: string, previewLines: number) => { const lines = code.split('\n'); @@ -20,9 +20,8 @@ const getPreviewCode = (code: string, previewLines: number) => { export const DetailedCode: React.FC = ({ code, - heading, initiallyExpanded = false, - language, + language = DEFAULT_LANGUAGE, preview = false, previewLines = DEFAULT_PREVIEW_LINES, }) => { @@ -33,20 +32,17 @@ export const DetailedCode: React.FC = ({ ? getPreviewCode(code, normalizedPreviewLines) : code; - // Show the button to expand the code if there is more code than the preview lines, and hide the button if there is no more code const hasMoreCode = previewEnabled && code.split('\n').length > normalizedPreviewLines; const displayedCode = isExpanded ? code : previewCode; return ( - + {hasMoreCode && ( )} diff --git a/packages/gamut/src/DetailedCode/types.ts b/packages/gamut/src/DetailedCode/types.ts index fcf528d3e79..1af22b7babb 100644 --- a/packages/gamut/src/DetailedCode/types.ts +++ b/packages/gamut/src/DetailedCode/types.ts @@ -1,6 +1,5 @@ export interface DetailedCodeProps { code: string; - heading?: string; language: string; initiallyExpanded?: boolean; preview?: boolean; @@ -8,9 +7,7 @@ export interface DetailedCodeProps { } export interface DetailedCodeButtonProps { - heading?: string; isExpanded?: boolean; - language: string; setIsExpanded?: React.Dispatch>; } diff --git a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx index 957a5afddc1..ba5869182dd 100644 --- a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx +++ b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx @@ -3,8 +3,8 @@ import { Canvas, Controls, Meta } from '@storybook/blocks'; import { ComponentHeader, LinkTo } from '~styleguide/blocks'; -import { codeExample } from './codeExample'; import * as ConnectedFormStories from './ConnectedForm.stories'; +import { example } from './example'; export const parameters = { title: 'ConnectedForm', @@ -42,7 +42,7 @@ This hook also returns the `FormRequiredText` component - include this before yo ### Example code - + ## Variants diff --git a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/codeExample.ts b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/example.ts similarity index 97% rename from packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/codeExample.ts rename to packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/example.ts index ba57103c289..ec23ed91564 100644 --- a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/codeExample.ts +++ b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/example.ts @@ -1,4 +1,4 @@ -export const codeExample = `import { +export const example = `import { ConnectedCheckbox, ConnectedInput, ConnectedSelect, From ade841a4ce8dbbfd36248ee88459456ce5c9fe7d Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Wed, 18 Feb 2026 23:15:40 -0800 Subject: [PATCH 08/15] move component into folder, add floating button, small type safety tweak --- .../__snapshots__/gamut.test.ts.snap | 1 - .../DetailedCode/DetailedCodeBody/index.tsx | 19 ---------- packages/gamut/src/index.tsx | 1 - .../DetailedCode/DetailedCodeBody/index.tsx | 36 +++++++++++++++++++ .../DetailedCode/DetailedCodeButton/index.tsx | 5 +-- .../Elements}/DetailedCode/elements.tsx | 20 +++++++++-- .../Elements}/DetailedCode/index.tsx | 14 +++++--- .../Elements}/DetailedCode/types.ts | 10 +++++- .../.storybook/components/index.tsx | 1 + .../ConnectedForm/ConnectedForm.mdx | 3 +- 10 files changed, 75 insertions(+), 35 deletions(-) delete mode 100644 packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx create mode 100644 packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx rename packages/{gamut/src => styleguide/.storybook/components/Elements}/DetailedCode/DetailedCodeButton/index.tsx (85%) rename packages/{gamut/src => styleguide/.storybook/components/Elements}/DetailedCode/elements.tsx (54%) rename packages/{gamut/src => styleguide/.storybook/components/Elements}/DetailedCode/index.tsx (81%) rename packages/{gamut/src => styleguide/.storybook/components/Elements}/DetailedCode/types.ts (53%) diff --git a/packages/gamut/__tests__/__snapshots__/gamut.test.ts.snap b/packages/gamut/__tests__/__snapshots__/gamut.test.ts.snap index 44fc7b19873..8511c5708f6 100644 --- a/packages/gamut/__tests__/__snapshots__/gamut.test.ts.snap +++ b/packages/gamut/__tests__/__snapshots__/gamut.test.ts.snap @@ -33,7 +33,6 @@ exports[`Gamut Exported Keys 1`] = ` "DataList", "DataTable", "DelayedRenderWrapper", - "DetailedCode", "Dialog", "Disclosure", "Drawer", diff --git a/packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx b/packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx deleted file mode 100644 index 35f9492d238..00000000000 --- a/packages/gamut/src/DetailedCode/DetailedCodeBody/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { Source } from '@storybook/blocks'; -import { ComponentProps } from 'react'; -import * as React from 'react'; - -import { DetailedCodeBodyWrapper } from '../elements'; -import { DetailedCodeBodyProps } from '../types'; - -type SourceLanguage = ComponentProps['language']; - -export const DetailedCodeBody: React.FC = ({ - code, - language, -}) => { - return ( - - - - ); -}; diff --git a/packages/gamut/src/index.tsx b/packages/gamut/src/index.tsx index 13d7c10c139..0537494d5db 100644 --- a/packages/gamut/src/index.tsx +++ b/packages/gamut/src/index.tsx @@ -16,7 +16,6 @@ export * from './Coachmark'; export * from './ConnectedForm'; export * from './ContentContainer'; export * from './DelayedRenderWrapper'; -export * from './DetailedCode'; export * from './Disclosure'; export * from './DataList'; export * from './Drawer'; diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx new file mode 100644 index 00000000000..99590907b47 --- /dev/null +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx @@ -0,0 +1,36 @@ +import { Source } from '@storybook/blocks'; +import { ComponentProps } from 'react'; +import * as React from 'react'; + +import { DetailedCodeBodyWrapper, FloatingExpandButton } from '../elements'; +import { DetailedCodeBodyProps } from '../types'; + +type SourceLanguage = ComponentProps['language']; + +export const DetailedCodeBody: React.FC = ({ + code, + language, + showFloatingBadge = false, + isExpanded = false, + setIsExpanded, +}) => { + const handleClick = () => { + if (setIsExpanded) { + setIsExpanded((prev) => !prev); + } + }; + + return ( + + + {showFloatingBadge && ( + + {isExpanded ? 'Show less code' : 'Show more code'} + + )} + + ); +}; \ No newline at end of file diff --git a/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx similarity index 85% rename from packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx rename to packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx index 54042c1ec21..7b0e28d5053 100644 --- a/packages/gamut/src/DetailedCode/DetailedCodeButton/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx @@ -1,10 +1,7 @@ import { MiniChevronDownIcon } from '@codecademy/gamut-icons'; import * as React from 'react'; +import { Anchor, Rotation, FlexBox, Text } from '@codecademy/gamut'; -import { Anchor } from '../../Anchor'; -import { Rotation } from '../../Animation'; -import { FlexBox } from '../../Box'; -import { Text } from '../../Typography'; import { DetailedCodeButtonProps } from '../types'; export const DetailedCodeButton: React.FC = ({ diff --git a/packages/gamut/src/DetailedCode/elements.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx similarity index 54% rename from packages/gamut/src/DetailedCode/elements.tsx rename to packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx index 8297bf95e1b..c8121a405e3 100644 --- a/packages/gamut/src/DetailedCode/elements.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx @@ -1,7 +1,6 @@ import { css } from '@codecademy/gamut-styles'; import styled from '@emotion/styled'; - -import { FlexBox } from '../Box'; +import { FlexBox, TextButton } from '@codecademy/gamut'; export const DetailedCodeWrapper = styled(FlexBox)( css({ @@ -13,13 +12,28 @@ export const DetailedCodeWrapper = styled(FlexBox)( }) ); -export const DetailedCodeBodyWrapper = styled(FlexBox)( +export const DetailedCodeBodyWrapper = styled(FlexBox)<{ + hasFloatingBadge?: boolean; +}>(({ hasFloatingBadge }) => css({ + position: 'relative', flexDirection: 'column', /* Override Storybook's Source component default styles to remove unwanted spacing and borders in the container */ '& .docblock-source': { borderRadius: 'none', margin: 0, + pb: hasFloatingBadge ? 48 : 0, }, }) ); + +export const FloatingExpandButton = styled(TextButton)( + css({ + position: 'absolute', + bottom: 16, + left: '50%', + transform: 'translateX(-50%)', + zIndex: 1, + bg: 'white', + }) +); \ No newline at end of file diff --git a/packages/gamut/src/DetailedCode/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx similarity index 81% rename from packages/gamut/src/DetailedCode/index.tsx rename to packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx index 3696643c8f2..893f35fe306 100644 --- a/packages/gamut/src/DetailedCode/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { DetailedCodeBody } from './DetailedCodeBody'; -import { DetailedCodeButton } from './DetailedCodeButton'; +// import { DetailedCodeButton } from './DetailedCodeButton'; import { DetailedCodeWrapper } from './elements'; import { DetailedCodeProps } from './types'; @@ -39,13 +39,19 @@ export const DetailedCode: React.FC = ({ return ( - - {hasMoreCode && ( + + {/* {hasMoreCode && ( - )} + )} */} ); }; diff --git a/packages/gamut/src/DetailedCode/types.ts b/packages/styleguide/.storybook/components/Elements/DetailedCode/types.ts similarity index 53% rename from packages/gamut/src/DetailedCode/types.ts rename to packages/styleguide/.storybook/components/Elements/DetailedCode/types.ts index 1af22b7babb..7ebed5f6588 100644 --- a/packages/gamut/src/DetailedCode/types.ts +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/types.ts @@ -1,6 +1,11 @@ +import { Source } from '@storybook/blocks'; +import { ComponentProps } from 'react'; + +type SourceLanguage = ComponentProps['language']; + export interface DetailedCodeProps { code: string; - language: string; + language?: SourceLanguage; initiallyExpanded?: boolean; preview?: boolean; previewLines?: number; @@ -14,4 +19,7 @@ export interface DetailedCodeButtonProps { export interface DetailedCodeBodyProps { code: string; language: string; + showFloatingBadge?: boolean; + isExpanded?: boolean; + setIsExpanded?: React.Dispatch>; } diff --git a/packages/styleguide/.storybook/components/index.tsx b/packages/styleguide/.storybook/components/index.tsx index 86b39cc1bbb..4be3198b4ab 100644 --- a/packages/styleguide/.storybook/components/index.tsx +++ b/packages/styleguide/.storybook/components/index.tsx @@ -2,6 +2,7 @@ export * from './ImageWrapper'; export * from './TokenTable'; export * from './Headers'; export * from './Elements/Callout'; +export * from './Elements/DetailedCode'; export * from './Elements/KeyboardKey'; export * from './Elements/Markdown'; export * from './Elements/ImageGallery'; diff --git a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx index ba5869182dd..d8d1f129834 100644 --- a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx +++ b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx @@ -1,7 +1,6 @@ -import { DetailedCode } from '@codecademy/gamut'; import { Canvas, Controls, Meta } from '@storybook/blocks'; -import { ComponentHeader, LinkTo } from '~styleguide/blocks'; +import { ComponentHeader, DetailedCode, LinkTo } from '~styleguide/blocks'; import * as ConnectedFormStories from './ConnectedForm.stories'; import { example } from './example'; From b7cff3f31bc49216286dea5aac679f6fdfb17a1d Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Thu, 19 Feb 2026 16:26:28 -0800 Subject: [PATCH 09/15] update badge to ellipses, update some typings, add anchor back --- .../DetailedCode/DetailedCodeBody/index.tsx | 24 ++++--------------- .../DetailedCode/DetailedCodeButton/index.tsx | 16 +++++++++---- .../Elements/DetailedCode/elements.tsx | 15 ++++++++---- .../Elements/DetailedCode/index.tsx | 13 +++++----- .../components/Elements/DetailedCode/types.ts | 9 ++++--- .../ConnectedForm/ConnectedForm.mdx | 2 +- 6 files changed, 37 insertions(+), 42 deletions(-) diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx index 99590907b47..49643296f75 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx @@ -1,36 +1,20 @@ import { Source } from '@storybook/blocks'; -import { ComponentProps } from 'react'; import * as React from 'react'; -import { DetailedCodeBodyWrapper, FloatingExpandButton } from '../elements'; +import { DetailedCodeBodyWrapper, FloatingIndicator } from '../elements'; import { DetailedCodeBodyProps } from '../types'; -type SourceLanguage = ComponentProps['language']; - export const DetailedCodeBody: React.FC = ({ code, language, showFloatingBadge = false, - isExpanded = false, - setIsExpanded, }) => { - const handleClick = () => { - if (setIsExpanded) { - setIsExpanded((prev) => !prev); - } - }; - return ( - + {showFloatingBadge && ( - - {isExpanded ? 'Show less code' : 'Show more code'} - + ... )} ); -}; \ No newline at end of file +}; diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx index 7b0e28d5053..7a2c75eadd5 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx @@ -7,10 +7,11 @@ import { DetailedCodeButtonProps } from '../types'; export const DetailedCodeButton: React.FC = ({ isExpanded, setIsExpanded, + language, }) => { const handleClick = () => { if (setIsExpanded) { - setIsExpanded((prev: boolean) => !prev); + setIsExpanded((prev) => !prev); } }; @@ -30,10 +31,15 @@ export const DetailedCodeButton: React.FC = ({ justifyContent="space-between" width="100%" > - {isExpanded ? 'Show Less Code' : 'Show More Code'} - - - + {language} + + + {isExpanded ? 'Show Less Code' : 'Show More Code'} + + + + + ); diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx index c8121a405e3..84d7e4ff5fc 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx @@ -1,6 +1,6 @@ import { css } from '@codecademy/gamut-styles'; import styled from '@emotion/styled'; -import { FlexBox, TextButton } from '@codecademy/gamut'; +import { FlexBox } from '@codecademy/gamut'; export const DetailedCodeWrapper = styled(FlexBox)( css({ @@ -27,13 +27,20 @@ export const DetailedCodeBodyWrapper = styled(FlexBox)<{ }) ); -export const FloatingExpandButton = styled(TextButton)( +export const FloatingIndicator = styled(FlexBox)( css({ position: 'absolute', bottom: 16, left: '50%', transform: 'translateX(-50%)', zIndex: 1, - bg: 'white', + bg: 'inherit', + px: 12, + py: 4, + borderRadius: 'lg', + fontSize: 26, + fontWeight: 700, + color: 'white', + letterSpacing: '0.1em', }) -); \ No newline at end of file +); diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx index 893f35fe306..7ec1a3e2a7d 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx @@ -1,11 +1,11 @@ import React, { useState } from 'react'; import { DetailedCodeBody } from './DetailedCodeBody'; -// import { DetailedCodeButton } from './DetailedCodeButton'; +import { DetailedCodeButton } from './DetailedCodeButton'; import { DetailedCodeWrapper } from './elements'; import { DetailedCodeProps } from './types'; -const DEFAULT_PREVIEW_LINES = 10; +const DEFAULT_PREVIEW_LINES = 20; const DEFAULT_LANGUAGE = 'tsx'; const getPreviewCode = (code: string, previewLines: number) => { @@ -42,16 +42,15 @@ export const DetailedCode: React.FC = ({ - {/* {hasMoreCode && ( + {hasMoreCode && ( - )} */} + )} ); }; diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/types.ts b/packages/styleguide/.storybook/components/Elements/DetailedCode/types.ts index 7ebed5f6588..a449dd70c2c 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/types.ts +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/types.ts @@ -12,14 +12,13 @@ export interface DetailedCodeProps { } export interface DetailedCodeButtonProps { - isExpanded?: boolean; - setIsExpanded?: React.Dispatch>; + isExpanded: boolean; + setIsExpanded: React.Dispatch>; + language: SourceLanguage; } export interface DetailedCodeBodyProps { code: string; - language: string; + language: SourceLanguage; showFloatingBadge?: boolean; - isExpanded?: boolean; - setIsExpanded?: React.Dispatch>; } diff --git a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx index d8d1f129834..618a0850d45 100644 --- a/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx +++ b/packages/styleguide/src/lib/Organisms/ConnectedForm/ConnectedForm/ConnectedForm.mdx @@ -41,7 +41,7 @@ This hook also returns the `FormRequiredText` component - include this before yo ### Example code - + ## Variants From 0394239c922fe5de4f475ceeb9928b794114d76f Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Mon, 16 Mar 2026 01:55:58 -0700 Subject: [PATCH 10/15] remove prop drill, duplicate line count, and extra styles --- .../DetailedCode/DetailedCodeBody/index.tsx | 3 +-- .../DetailedCode/DetailedCodeButton/index.tsx | 17 ++++----------- .../Elements/DetailedCode/index.tsx | 21 ++++++------------- .../components/Elements/DetailedCode/types.ts | 2 +- 4 files changed, 12 insertions(+), 31 deletions(-) diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx index 49643296f75..fba68ec927c 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx @@ -1,5 +1,4 @@ import { Source } from '@storybook/blocks'; -import * as React from 'react'; import { DetailedCodeBodyWrapper, FloatingIndicator } from '../elements'; import { DetailedCodeBodyProps } from '../types'; @@ -17,4 +16,4 @@ export const DetailedCodeBody: React.FC = ({ )} ); -}; +}; \ No newline at end of file diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx index 7a2c75eadd5..285518759f5 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx @@ -6,37 +6,28 @@ import { DetailedCodeButtonProps } from '../types'; export const DetailedCodeButton: React.FC = ({ isExpanded, - setIsExpanded, + onToggle, language, }) => { - const handleClick = () => { - if (setIsExpanded) { - setIsExpanded((prev) => !prev); - } - }; - return ( {language} - + {isExpanded ? 'Show Less Code' : 'Show More Code'} - + diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx index 7ec1a3e2a7d..4eadbb64fc7 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx @@ -8,16 +8,6 @@ import { DetailedCodeProps } from './types'; const DEFAULT_PREVIEW_LINES = 20; const DEFAULT_LANGUAGE = 'tsx'; -const getPreviewCode = (code: string, previewLines: number) => { - const lines = code.split('\n'); - - if (lines.length <= previewLines) { - return code; - } - - return lines.slice(0, previewLines).join('\n'); -}; - export const DetailedCode: React.FC = ({ code, initiallyExpanded = false, @@ -28,13 +18,14 @@ export const DetailedCode: React.FC = ({ const [isExpanded, setIsExpanded] = useState(initiallyExpanded); const normalizedPreviewLines = Math.max(0, previewLines); const previewEnabled = preview && normalizedPreviewLines > 0; + + const codeLines = code.split('\n'); + const hasMoreCode = previewEnabled && codeLines.length > normalizedPreviewLines; + const previewCode = previewEnabled - ? getPreviewCode(code, normalizedPreviewLines) + ? codeLines.slice(0, normalizedPreviewLines).join('\n') : code; - const hasMoreCode = - previewEnabled && code.split('\n').length > normalizedPreviewLines; - const displayedCode = isExpanded ? code : previewCode; return ( @@ -47,7 +38,7 @@ export const DetailedCode: React.FC = ({ {hasMoreCode && ( setIsExpanded((prev) => !prev)} language={language} /> )} diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/types.ts b/packages/styleguide/.storybook/components/Elements/DetailedCode/types.ts index a449dd70c2c..829868c4f3f 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/types.ts +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/types.ts @@ -13,7 +13,7 @@ export interface DetailedCodeProps { export interface DetailedCodeButtonProps { isExpanded: boolean; - setIsExpanded: React.Dispatch>; + onToggle: () => void; language: SourceLanguage; } From 9a5276809cd4a50d175f6162a79e883f1012f9f6 Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Mon, 16 Mar 2026 02:08:12 -0700 Subject: [PATCH 11/15] prettier again for the 100th time --- .../Elements/DetailedCode/DetailedCodeBody/index.tsx | 2 +- .../Elements/DetailedCode/DetailedCodeButton/index.tsx | 9 ++------- .../components/Elements/DetailedCode/index.tsx | 7 ++++--- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx index fba68ec927c..be9279023e8 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx @@ -16,4 +16,4 @@ export const DetailedCodeBody: React.FC = ({ )} ); -}; \ No newline at end of file +}; diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx index 285518759f5..28ef8cefded 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx @@ -18,15 +18,10 @@ export const DetailedCodeButton: React.FC = ({ width="100%" onClick={onToggle} > - + {language} - - {isExpanded ? 'Show Less Code' : 'Show More Code'} - + {isExpanded ? 'Show Less Code' : 'Show More Code'} diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx index 4eadbb64fc7..773732e9357 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx @@ -18,10 +18,11 @@ export const DetailedCode: React.FC = ({ const [isExpanded, setIsExpanded] = useState(initiallyExpanded); const normalizedPreviewLines = Math.max(0, previewLines); const previewEnabled = preview && normalizedPreviewLines > 0; - + const codeLines = code.split('\n'); - const hasMoreCode = previewEnabled && codeLines.length > normalizedPreviewLines; - + const hasMoreCode = + previewEnabled && codeLines.length > normalizedPreviewLines; + const previewCode = previewEnabled ? codeLines.slice(0, normalizedPreviewLines).join('\n') : code; From da8b65f171d0f644301e6910cbbc7d4fd7446e45 Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Tue, 17 Mar 2026 17:08:53 -0700 Subject: [PATCH 12/15] feedback + code lines? --- .../DetailedCode/DetailedCodeBody/index.tsx | 11 ++++++---- .../Elements/DetailedCode/elements.tsx | 21 +++++++++---------- .../Elements/DetailedCode/index.tsx | 5 +++-- .../components/Elements/DetailedCode/types.ts | 3 ++- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx index be9279023e8..b89bd284685 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx @@ -6,13 +6,16 @@ import { DetailedCodeBodyProps } from '../types'; export const DetailedCodeBody: React.FC = ({ code, language, - showFloatingBadge = false, + showEllipses = false, + codeLines, }) => { return ( - + - {showFloatingBadge && ( - ... + {showEllipses && ( + + ...{codeLines} more lines + )} ); diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx index 84d7e4ff5fc..fa7c69619b5 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx @@ -1,6 +1,6 @@ import { css } from '@codecademy/gamut-styles'; import styled from '@emotion/styled'; -import { FlexBox } from '@codecademy/gamut'; +import { FlexBox, Box } from '@codecademy/gamut'; export const DetailedCodeWrapper = styled(FlexBox)( css({ @@ -13,8 +13,8 @@ export const DetailedCodeWrapper = styled(FlexBox)( ); export const DetailedCodeBodyWrapper = styled(FlexBox)<{ - hasFloatingBadge?: boolean; -}>(({ hasFloatingBadge }) => + hasShowCodeButton?: boolean; +}>(({ hasShowCodeButton }) => css({ position: 'relative', flexDirection: 'column', @@ -22,25 +22,24 @@ export const DetailedCodeBodyWrapper = styled(FlexBox)<{ '& .docblock-source': { borderRadius: 'none', margin: 0, - pb: hasFloatingBadge ? 48 : 0, + pb: hasShowCodeButton ? 32 : 0, }, }) ); -export const FloatingIndicator = styled(FlexBox)( +export const FloatingIndicator = styled(Box)( css({ position: 'absolute', bottom: 16, - left: '50%', - transform: 'translateX(-50%)', + left: 16, zIndex: 1, bg: 'inherit', px: 12, py: 4, - borderRadius: 'lg', - fontSize: 26, - fontWeight: 700, - color: 'white', + fontSize: 14, + fontFamily: 'monospace', letterSpacing: '0.1em', + /* Color to match the text color in the Source component */ + textColor: '#C9CDCF', }) ); diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx index 773732e9357..6cfc17f84bd 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx @@ -19,7 +19,7 @@ export const DetailedCode: React.FC = ({ const normalizedPreviewLines = Math.max(0, previewLines); const previewEnabled = preview && normalizedPreviewLines > 0; - const codeLines = code.split('\n'); + const codeLines = code.trimEnd().split('\n'); const hasMoreCode = previewEnabled && codeLines.length > normalizedPreviewLines; @@ -34,7 +34,8 @@ export const DetailedCode: React.FC = ({ {hasMoreCode && ( Date: Tue, 7 Apr 2026 00:38:04 -0700 Subject: [PATCH 13/15] update to sb10, fix moved overlay, address line count --- .../Elements/DetailedCode/DetailedCodeBody/index.tsx | 4 ++-- .../Elements/DetailedCode/DetailedCodeButton/index.tsx | 2 +- .../components/Elements/DetailedCode/elements.tsx | 7 ++++--- .../.storybook/components/Elements/DetailedCode/index.tsx | 6 +++++- .../.storybook/components/Elements/DetailedCode/types.ts | 2 +- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx index b89bd284685..64dc2c07856 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx @@ -1,4 +1,4 @@ -import { Source } from '@storybook/blocks'; +import { Source } from '@storybook/addon-docs/blocks'; import { DetailedCodeBodyWrapper, FloatingIndicator } from '../elements'; import { DetailedCodeBodyProps } from '../types'; @@ -14,7 +14,7 @@ export const DetailedCodeBody: React.FC = ({ {showEllipses && ( - ...{codeLines} more lines + ... {codeLines} more line{codeLines === 1 ? '' : 's'} )} diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx index 28ef8cefded..2e0a9a4b434 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeButton/index.tsx @@ -20,7 +20,7 @@ export const DetailedCodeButton: React.FC = ({ > {language} - + {isExpanded ? 'Show Less Code' : 'Show More Code'} diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx index fa7c69619b5..77f5f912b27 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx @@ -4,7 +4,6 @@ import { FlexBox, Box } from '@codecademy/gamut'; export const DetailedCodeWrapper = styled(FlexBox)( css({ - width: '100%', flexDirection: 'column', borderRadius: 'md', border: 1, @@ -22,7 +21,10 @@ export const DetailedCodeBodyWrapper = styled(FlexBox)<{ '& .docblock-source': { borderRadius: 'none', margin: 0, - pb: hasShowCodeButton ? 32 : 0, + }, + /* Reserves space under the text for the overlay. */ + '& .docblock-source pre': { + pb: hasShowCodeButton ? 48 : 12, }, }) ); @@ -39,7 +41,6 @@ export const FloatingIndicator = styled(Box)( fontSize: 14, fontFamily: 'monospace', letterSpacing: '0.1em', - /* Color to match the text color in the Source component */ textColor: '#C9CDCF', }) ); diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx index 6cfc17f84bd..282aa59d865 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx @@ -35,7 +35,11 @@ export const DetailedCode: React.FC = ({ code={displayedCode} language={language} showEllipses={hasMoreCode && !isExpanded} - codeLines={codeLines.length} + codeLines={ + previewEnabled + ? Math.max(0, codeLines.length - normalizedPreviewLines) + : 0 + } /> {hasMoreCode && ( ['language']; From 2d619146ffb40aa4bc827ead46acd982c46988e4 Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Tue, 7 Apr 2026 01:54:58 -0700 Subject: [PATCH 14/15] clean up stylings --- .../components/Elements/DetailedCode/elements.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx index 77f5f912b27..23ddd3dd842 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/elements.tsx @@ -22,9 +22,9 @@ export const DetailedCodeBodyWrapper = styled(FlexBox)<{ borderRadius: 'none', margin: 0, }, - /* Reserves space under the text for the overlay. */ + /* Reserves space under the text for the overlay */ '& .docblock-source pre': { - pb: hasShowCodeButton ? 48 : 12, + pb: hasShowCodeButton ? 48 : 20, }, }) ); @@ -34,13 +34,9 @@ export const FloatingIndicator = styled(Box)( position: 'absolute', bottom: 16, left: 16, - zIndex: 1, - bg: 'inherit', px: 12, - py: 4, fontSize: 14, fontFamily: 'monospace', - letterSpacing: '0.1em', textColor: '#C9CDCF', }) ); From 5d10a0ad469e1496d362c802bf4d1c8e63609eda Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Tue, 7 Apr 2026 10:55:23 -0700 Subject: [PATCH 15/15] updated slightly confusing variable names and add an extra example --- .../DetailedCode/DetailedCodeBody/index.tsx | 4 ++-- .../Elements/DetailedCode/index.tsx | 20 +++++++++---------- .../components/Elements/DetailedCode/types.ts | 2 +- .../ConnectedForm/ConnectedForm.mdx | 4 ++++ 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx index 64dc2c07856..72fee5ade8d 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/DetailedCodeBody/index.tsx @@ -7,14 +7,14 @@ export const DetailedCodeBody: React.FC = ({ code, language, showEllipses = false, - codeLines, + hiddenLineCount, }) => { return ( {showEllipses && ( - ... {codeLines} more line{codeLines === 1 ? '' : 's'} + ... {hiddenLineCount} more line{hiddenLineCount === 1 ? '' : 's'} )} diff --git a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx index 282aa59d865..64abd4f0f64 100644 --- a/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx +++ b/packages/styleguide/.storybook/components/Elements/DetailedCode/index.tsx @@ -19,15 +19,17 @@ export const DetailedCode: React.FC = ({ const normalizedPreviewLines = Math.max(0, previewLines); const previewEnabled = preview && normalizedPreviewLines > 0; - const codeLines = code.trimEnd().split('\n'); - const hasMoreCode = - previewEnabled && codeLines.length > normalizedPreviewLines; + const allLines = code.trimEnd().split('\n'); + const hiddenLineCount = previewEnabled + ? Math.max(0, allLines.length - normalizedPreviewLines) + : 0; + const hasMoreCode = hiddenLineCount > 0; - const previewCode = previewEnabled - ? codeLines.slice(0, normalizedPreviewLines).join('\n') + const codeSnippet = previewEnabled + ? allLines.slice(0, normalizedPreviewLines).join('\n') : code; - const displayedCode = isExpanded ? code : previewCode; + const displayedCode = isExpanded ? code : codeSnippet; return ( @@ -35,11 +37,7 @@ export const DetailedCode: React.FC = ({ code={displayedCode} language={language} showEllipses={hasMoreCode && !isExpanded} - codeLines={ - previewEnabled - ? Math.max(0, codeLines.length - normalizedPreviewLines) - : 0 - } + hiddenLineCount={hiddenLineCount} /> {hasMoreCode && ( +### Example Code Preview False + + + ## Variants ### `watchedFields`