From f0a55af2796a8f99ba39f37bd2214c43687b1044 Mon Sep 17 00:00:00 2001 From: Rodrigo Pombo Date: Sat, 4 Dec 2021 15:07:02 +0100 Subject: [PATCH] Make tabs clickable --- packages/mdx/src/client/code.tsx | 52 ++++++++++++++++++- packages/mdx/src/client/scrollycoding.tsx | 32 +++++++++--- packages/mdx/src/client/section.tsx | 37 +++++-------- packages/mdx/src/client/spotlight.tsx | 33 +++++++++--- packages/mini-editor/src/editor-frame.tsx | 7 +++ .../playground/content/scrollycoding-demo.mdx | 10 ++++ packages/playground/content/section.mdx | 47 +++++++---------- packages/playground/content/simple-editor.mdx | 2 +- .../playground/content/spotlight-demo.mdx | 10 ++++ 9 files changed, 164 insertions(+), 66 deletions(-) diff --git a/packages/mdx/src/client/code.tsx b/packages/mdx/src/client/code.tsx index e34c7672..360d9737 100644 --- a/packages/mdx/src/client/code.tsx +++ b/packages/mdx/src/client/code.tsx @@ -3,9 +3,26 @@ import { CodeSpring } from "@code-hike/smooth-code" import { EditorSpring, EditorProps, + EditorStep, } from "@code-hike/mini-editor" export function Code(props: EditorProps) { + const [step, setStep] = React.useState(props) + + function onTabClick(filename: string) { + const newStep = updateEditorStep(step, filename, null) + setStep({ ...step, ...newStep }) + } + + return +} + +export function InnerCode({ + onTabClick, + ...props +}: EditorProps & { + onTabClick?: (filename: string) => void +}) { if ( !props.southPanel && props.files.length === 1 && @@ -19,6 +36,39 @@ export function Code(props: EditorProps) { /> ) } else { - return + const frameProps = { + ...props?.frameProps, + onTabClick, + } + return ( + + ) + } +} + +export function updateEditorStep( + step: EditorStep, + filename: string | undefined, + focus: string | null +): EditorStep { + const name = filename || step.northPanel.active + const newFiles = step.files.map((file: any) => + file.name === name + ? { + ...file, + focus: focus === null ? file.focus : focus, + } + : file + ) + + let northPanel = { ...step.northPanel } + let southPanel = step.southPanel && { + ...step.southPanel, + } + if (step.northPanel.tabs.includes(name)) { + northPanel.active = name + } else if (southPanel) { + southPanel.active = name } + return { files: newFiles, northPanel, southPanel } } diff --git a/packages/mdx/src/client/scrollycoding.tsx b/packages/mdx/src/client/scrollycoding.tsx index 930a6e86..5320e102 100644 --- a/packages/mdx/src/client/scrollycoding.tsx +++ b/packages/mdx/src/client/scrollycoding.tsx @@ -3,7 +3,7 @@ import { EditorProps, EditorStep, } from "@code-hike/mini-editor" -import { Code } from "./code" +import { InnerCode, updateEditorStep } from "./code" import { Scroller, Step as ScrollerStep, @@ -25,12 +25,26 @@ export function Scrollycoding({ }) { const stepsChildren = React.Children.toArray(children) - const [stepIndex, setIndex] = React.useState(start) - const tab = editorSteps[stepIndex] + const [state, setState] = React.useState({ + stepIndex: start, + step: editorSteps[start], + }) + + const tab = state.step function onStepChange(index: number) { - setIndex(index) + setState({ stepIndex: index, step: editorSteps[index] }) + } + + function onTabClick(filename: string) { + const newStep = updateEditorStep( + state.step, + filename, + null + ) + setState({ ...state, step: newStep }) } + return (
setIndex(i)} + onClick={() => onStepChange(i)} className="ch-scrollycoding-step-content" data-selected={ - i === stepIndex ? "true" : undefined + i === state.stepIndex ? "true" : undefined } > {children} @@ -56,7 +70,11 @@ export function Scrollycoding({
- + {presetConfig && ( void resetFocus: () => void @@ -33,30 +33,14 @@ export function Section({ id, }: { fileName?: string - focus: string + focus: string | null id: string }) => { - const name = fileName || state.northPanel.active - - const newFiles = state.files.map((file: any) => - file.name === name ? { ...file, focus } : file - ) - - let northPanel = { ...state.northPanel } - let southPanel = state.southPanel && { - ...state.northPanel, - } - if (state.northPanel.tabs.includes(name)) { - northPanel.active = name - } else if (southPanel) { - southPanel.active = name - } + const newStep = updateEditorStep(state, fileName, focus) setState({ ...state, - files: newFiles, - northPanel, - southPanel, + ...newStep, selectedId: id, }) } @@ -78,8 +62,15 @@ export function Section({ } export function SectionCode() { - const { props } = React.useContext(SectionContext) - return + const { props, setFocus } = React.useContext( + SectionContext + ) + + const onTabClick = (filename: string) => { + setFocus({ fileName: filename, focus: null, id: "" }) + } + + return } export function SectionLink({ diff --git a/packages/mdx/src/client/spotlight.tsx b/packages/mdx/src/client/spotlight.tsx index a03ae058..18cdf746 100644 --- a/packages/mdx/src/client/spotlight.tsx +++ b/packages/mdx/src/client/spotlight.tsx @@ -3,7 +3,7 @@ import { EditorProps, EditorStep, } from "@code-hike/mini-editor" -import { Code } from "./code" +import { InnerCode, updateEditorStep } from "./code" import { Preview, PresetConfig } from "./preview" export function Spotlight({ @@ -21,8 +21,20 @@ export function Spotlight({ }) { const stepsChildren = React.Children.toArray(children) - const [stepIndex, setIndex] = React.useState(start) - const tab = editorSteps[stepIndex] + const [state, setState] = React.useState({ + stepIndex: start, + step: editorSteps[start], + }) + const tab = state.step + + function onTabClick(filename: string) { + const newStep = updateEditorStep( + state.step, + filename, + null + ) + setState({ ...state, step: newStep }) + } const headerElement = stepsChildren[0] as React.ReactElement @@ -40,10 +52,15 @@ export function Spotlight({ i === 0 ? null : (
setIndex(i)} + onClick={() => + setState({ + stepIndex: i, + step: editorSteps[i], + }) + } className="ch-spotlight-tab" data-selected={ - i === stepIndex ? "true" : undefined + i === state.stepIndex ? "true" : undefined } > {children} @@ -52,7 +69,11 @@ export function Spotlight({ )}
- + {presetConfig && ( void } & React.PropsWithoutRef export const EditorFrame = React.forwardRef< @@ -51,6 +52,7 @@ export const EditorFrame = React.forwardRef< button, theme, className, + onTabClick, ...rest }, ref @@ -76,6 +78,7 @@ export const EditorFrame = React.forwardRef< button={button} panel="north" theme={theme} + onTabClick={onTabClick} /> } {...rest} @@ -105,6 +108,7 @@ export const EditorFrame = React.forwardRef< topBorder={true} panel="south" theme={theme} + onTabClick={onTabClick} />
void } function TabsContainer({ tabs, @@ -138,6 +143,7 @@ function TabsContainer({ topBorder, panel, theme, + onTabClick, }: TabsContainerProps) { const c = useClasser("ch-editor-tab") return ( @@ -189,6 +195,7 @@ function TabsContainer({ : ColorName.InactiveTabBackground ), }} + onClick={onTabClick && (() => onTabClick(title))} >
{title}
diff --git a/packages/playground/content/scrollycoding-demo.mdx b/packages/playground/content/scrollycoding-demo.mdx index ae852e9d..0ef58add 100644 --- a/packages/playground/content/scrollycoding-demo.mdx +++ b/packages/playground/content/scrollycoding-demo.mdx @@ -16,6 +16,8 @@ Lorem ipsum dolor sit amet, consectetur adipiscing something about points, sed d Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus. + + ```js app.js focus=3:10 const { lorem, ipsum } = dolor({ sit: { @@ -53,6 +55,14 @@ const { lorem, ipsum } = dolor({ }) ``` +```css styles.css +.lorem { + color: red; +} +``` + + + --- ## Step 2 diff --git a/packages/playground/content/section.mdx b/packages/playground/content/section.mdx index 5ed517b4..13fdc784 100644 --- a/packages/playground/content/section.mdx +++ b/packages/playground/content/section.mdx @@ -1,57 +1,48 @@ -# Sections +# Code Links -Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +Lorem ipsum dolor sit amet. -Lorem [ipsum](focus://1[16:20]) dolor sit amet, [consectetur](focus://5[7:17]) adipiscing elit, sed do eiusmod [tempor](https://google.com) incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +Consectetur adipiscing elit, sed do eiusmod tempor [incididunt](focus://4:7) ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. ```js -function lorem(ipsum, dolor = 1) { - const sit = ipsum == null ? 0 : ipsum.sit - dolor = sit - amet(dolor) - return sit - ? consectetur(ipsum, 0, dolor < 0 ? 0 : dolor) - : [] +function lorem(ipsum, dolor) { + const sit = "lorem ipsum" + dolor = elit(dolor, 3) + while (++consectetur < amet) { + sit.eiusmod(150) + tempor(ipsum, adipiscing) + } } ``` -Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +Duis aute irure dolor in reprehenderit in voluptate velit esse cillum [dolore](focus://1[23:27],3) eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident. ---- +## With multiple files -Lorem dolor sit amet, [consectetur](focus://styles.css#3[8:22]) adipiscing elit, sed do eiusmod [tempor](focus://index.js#1:3) incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +Lorem dolor sit amet, [javascript](focus://index.js#2:3) adipiscing elit, sed do eiusmod [styles](focus://styles.css#2:3) incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ```js index.js -function () { - return 3 +function lorem(ipsum, dolor) { + const sit = ipsum - amet(dolor) + return sit + "lorem ipsum" } ``` ```css styles.css -html, -body, -body > div:first-child, -div#__next, -div#__next > div { - margin: 0; - height: 100%; - max-height: 100%; - display: flex; - flex-direction: column; - font-family: sans-serif; - background-color: #444; +.lorem-ipsum > .dolor pre { + background-color: var(--color-bg); + padding: 1em 0px 10vh 300px; } ``` -Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - diff --git a/packages/playground/content/simple-editor.mdx b/packages/playground/content/simple-editor.mdx index fac1b22b..bbebfb82 100644 --- a/packages/playground/content/simple-editor.mdx +++ b/packages/playground/content/simple-editor.mdx @@ -15,7 +15,7 @@ console.log(1) ``` ```js app.js -console.log(1) +console.log("app") ``` --- diff --git a/packages/playground/content/spotlight-demo.mdx b/packages/playground/content/spotlight-demo.mdx index fa2be3e5..d783d969 100644 --- a/packages/playground/content/spotlight-demo.mdx +++ b/packages/playground/content/spotlight-demo.mdx @@ -4,6 +4,8 @@ This is how to use the `` component. Lorem ipsum dolor sit amet co + + ```js app.js function lorem(ipsum, dolor = 1) { const sit = ipsum == null && 0 @@ -12,6 +14,14 @@ function lorem(ipsum, dolor = 1) { } ``` +```css styles.css +.lorem { + color: red; +} +``` + + + --- Change focus