From 7a47cbe9adbf3bf4eb6294f0e7b6401679096044 Mon Sep 17 00:00:00 2001 From: Mark Street Date: Sun, 31 May 2026 15:52:01 +0100 Subject: [PATCH 1/7] Add scratch editor tour --- frontend/package.json | 1 + frontend/src/app/globals.scss | 92 +++ frontend/src/app/layout.tsx | 1 + frontend/src/components/Diff/Diff.tsx | 10 +- frontend/src/components/Diff/ToggleButton.tsx | 3 + frontend/src/components/Editor/CodeMirror.tsx | 3 + frontend/src/components/Scratch/Scratch.tsx | 32 +- .../src/components/Scratch/ScratchToolbar.tsx | 70 ++- .../src/components/Scratch/ScratchTour.tsx | 561 ++++++++++++++++++ .../components/Scratch/panels/AboutPanel.tsx | 2 +- .../Scratch/panels/DecompilePanel.tsx | 2 +- .../components/Scratch/panels/FamilyPanel.tsx | 5 +- .../Scratch/panels/ProblemPanel.tsx | 5 +- frontend/src/components/Tabs.tsx | 5 + .../src/components/compiler/CompilerOpts.tsx | 34 +- frontend/yarn.lock | 5 + 16 files changed, 804 insertions(+), 27 deletions(-) create mode 100644 frontend/src/components/Scratch/ScratchTour.tsx diff --git a/frontend/package.json b/frontend/package.json index 08198b3c6..89d7b1202 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -33,6 +33,7 @@ "@sentry/nextjs": "^10.52.0", "allotment": "^1.20.3", "ansi-to-react": "^6.1.6", + "boarding.js": "^3.7.3", "clsx": "^2.1.1", "codemirror": "^6.0.1", "dotenv": "^16.4.5", diff --git a/frontend/src/app/globals.scss b/frontend/src/app/globals.scss index e9a4a6cbe..7aa665b37 100644 --- a/frontend/src/app/globals.scss +++ b/frontend/src/app/globals.scss @@ -85,3 +85,95 @@ body.no-scroll { height: 100svh; } } + +#boarding-popover-item.scratch-tour-popover { + width: min(22rem, calc(100vw - 2rem)); + border: 1px solid var(--g600); + border-radius: 8px; + background: var(--g200); + box-shadow: 0 18px 48px rgb(0 0 0 / 35%); + color: var(--g1700); + + .boarding-popover-title { + margin-bottom: 0.45rem; + font-weight: 700; + font-size: 0.95rem; + line-height: 1.2; + } + + .boarding-popover-description { + color: var(--g1200); + font-size: 0.875rem; + line-height: 1.35; + + strong { + color: var(--g1700); + font-weight: 700; + } + + a { + color: var(--link); + text-decoration: underline; + } + + a:hover { + color: var(--g1700); + } + } + + .boarding-popover-footer { + display: flex !important; + align-items: center; + justify-content: space-between; + gap: 0.75rem; + margin-top: 1rem; + } + + .boarding-navigation-btns { + display: flex; + align-items: center; + gap: 0.5rem; + margin-left: auto; + } + + button { + display: inline-flex; + min-height: 2rem; + align-items: center; + justify-content: center; + border: 1px solid var(--g700); + border-radius: 6px; + background: var(--g400); + padding: 0.35rem 0.65rem; + color: var(--g1700); + font-weight: 600; + font-size: 0.8125rem; + line-height: 1; + white-space: nowrap; + cursor: pointer; + } + + button:hover { + background: var(--a600); + } + + .boarding-next-btn { + border-color: var(--a900); + background: var(--a400); + color: white; + } + + .boarding-next-btn:hover { + background: var(--a600); + } + + .boarding-disabled { + opacity: 0.45; + cursor: default; + pointer-events: none; + } + + .boarding-popover-tip { + border-color: var(--g200); + } +} diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 800b1f540..808bb503d 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -1,6 +1,7 @@ import ThemeProvider from "./ThemeProvider"; import "allotment/dist/style.css"; +import "boarding.js/styles/main.css"; import "./globals.scss"; export const metadata = { diff --git a/frontend/src/components/Diff/Diff.tsx b/frontend/src/components/Diff/Diff.tsx index 6ac30980c..b6c3c607e 100644 --- a/frontend/src/components/Diff/Diff.tsx +++ b/frontend/src/components/Diff/Diff.tsx @@ -481,7 +481,11 @@ export default function Diff({ {columnCount === 3 && }
{columns.map((col) => ( -
+
{COLUMN_LABELS[col]} setColumn("base", enabled) } + dataTour="scratch-diff-toggle-target" /> setColumn("current", enabled) } + dataTour="scratch-diff-toggle-current" /> } @@ -538,6 +545,7 @@ export default function Diff({ padding="px-1 py-1" enabled={compressionEnabled} setEnabled={setCompressionEnabled} + dataTour="scratch-diff-toggle-compression" /> )} diff --git a/frontend/src/components/Diff/ToggleButton.tsx b/frontend/src/components/Diff/ToggleButton.tsx index 803f870aa..df87a9dba 100644 --- a/frontend/src/components/Diff/ToggleButton.tsx +++ b/frontend/src/components/Diff/ToggleButton.tsx @@ -9,6 +9,7 @@ type ToggleButtonProps = { disabledLabel?: string; enabledLabel?: string; padding?: string; + dataTour?: string; }; export default function ToggleButton({ @@ -19,6 +20,7 @@ export default function ToggleButton({ disabledLabel = "Show ", enabledLabel = "Hide ", padding = "px-2 py-1", + dataTour, }: ToggleButtonProps) { return (
), ]; @@ -343,6 +391,7 @@ export type Props = { saveCallback: () => void; deleteScratch: () => Promise; setDecompilationTabEnabled: (enabled: boolean) => void; + tourTargetsEnabled?: boolean; }; export default function ScratchToolbar(props: Props) { @@ -354,7 +403,7 @@ export default function ScratchToolbar(props: Props) { return ( <>