docs(editor): interactive playground and tutorial system#139
Open
johnleider wants to merge 42 commits intomasterfrom
Open
docs(editor): interactive playground and tutorial system#139johnleider wants to merge 42 commits intomasterfrom
johnleider wants to merge 42 commits intomasterfrom
Conversation
Vue REPL with Monaco editor, @vuetify/v0 import map, and fullscreen layout. Initial working layout with h-screen + absolute positioning for proper sizing.
Set up multi-file REPL matching Vuetify Play's v0 template: main.ts with createThemePlugin, uno.config.ts with presetWind4 runtime and v0 color token mapping. Updated default example to use UnoCSS utility classes. Added scrollbar-gutter override for fullscreen layout.
Move pt-[72px] padding from App.vue to default/home layouts so fullscreen layout stays flush. Reset preview iframe body margin and widen default stepper example.
Lazy-load example files in EditorExamples to reduce editor chunk size. Prefetch @vue/repl and Monaco from docs layout during idle time so the editor page loads from HTTP cache. Fix flash of unstyled content by hiding #app until after mount and setting theme-aware body background. Add tab close buttons, sync nested file edits to flat aliases, fix kebab-case component names, and replace header with Vuetify Play logo.
- Add draggable resize handle for file panel using v0 useToggleScope/useEventListener - Persist sidebar width to localStorage via useStorage - Add Ctrl+B hotkey to toggle file panel (useHotkey) - Allow closing all tabs, show "Open file" button when empty - Hide breadcrumbs and REPL when no tabs open - Use vuetify-play icon for "Open in Editor" buttons - Skip hidden alias files from project folder in file tree - Add lang="ts" to new .vue file boilerplate - Double-click resize handle resets to default width - Stabilize previewOptions as computed to prevent re-renders during resize - Preserve URL hash for shareable editor links - Fix editor-container height to fill available space
Extract useEditorFiles and useFileTreeCrud composables to reduce component complexity. Lazy-load fflate to remove ~13KB from the shared docs bundle. Replace backdrop overlay with useClickOutside + Escape key support. Consolidate infrastructure file constants, deduplicate generateAppWrapper, alphabetize file tree, and guard activeFile access.
Replace Vuetify Play references with v0 Editor, add editor/examples icons, pass fileName prop to code panes, and delete unused playground.ts.
Add Scrim to fullscreen layout for stack coordination. On mobile, file tree opens as a fixed overlay with proper z-index from useStack. Syncs sidebar state with breakpoint changes.
…n hydration Replace CSS Grid with nested flexbox and add three draggable resize handles (markdown width, editor/preview split, file tree width) with persistent storage. Optimize step transitions by preloading all tutorial steps in background and using RAF-throttled pointer events. Hydrate v-html code fences and callouts into DocsMarkup/DocsCallout components matching the docs site styling.
- Consolidate tutorial route into skillz.tutorial.[id].vue - Remove deprecated getting-started tutorial - Add vue-basics, vue-intermediate, vue-advanced, and v0-basics tutorial content - Improve editor file tree, tabs, and markdown panel - Add SkillzBadge and SkillzComplete components - Update typed-router and component declarations
Add carousel view mode for skill card decks with drag-to-scroll, CSS fade masks on edges, and right-edge viewport bleed. Persisted via carousel setting in useSettings.
…rovements Add hover arrows for click-to-scroll, left/right keyboard navigation between cards, reactive fade masks based on scroll position, and focus-visible styles. Replace querySelector usage with useTemplateRef, add immediate option to useResizeObserver.
Replace store.setFiles() with incremental in-place file mutations.
store.setFiles() writes to import-map.json, which triggers @vue/repl's
getImportMap() watch → createSandbox() → iframe recreation → volar
language worker restart on every Next/Prev click.
The incremental approach mutates files reactively:
- existing files: update .code in-place, compile only if changed
- new files: store.files[filename] = new ReplFile then pass the Proxy
(not the raw instance) to compileFile — compileFile destructures
{ compiled } and writes compiled.js; going through the Proxy makes
the write reactive so updatePreview re-runs correctly
- deleted files: removed from store.files without touching the protected
import-map.json or tsconfig.json
- Save step progress to skillz store as user navigates (begin, record, setLastStep) - Add ?step=N query param support for bookmark, share, and resume - Resume notification (SkillzResume) now handles tutorial mode with step param - Back button navigates to /skillz/:id instead of /skillz - Hide sidebar toggle when stepOptions.hideFiles is true - Export begin, record, setLastStep from skillz store; extend pendingTour to match tutorials - Fix SVG width/height lint errors in 5 tutorial step files
- Rename editor → playground (/playground route, nav item at order 1.15) - Add EditorIntroPanel with markdown content, DocsCallout/DocsMarkup mounting, close button, and useStorage persistence - Extract useMarkdownMount composable shared by intro and tutorial panels - Fix useMarkdown table/callout renderers to parse inline markdown (backticks, links, bold) via a separate sync Marked instance - Add TOUR callout support to useMarkdown + useMarkdownMount - Encode editor state (files + active file) to URL hash on change; restore active file on load; backwards-compat with legacy hash format - Patch @vue/repl to suppress Symbol(props) injection warn and skip internal Sandbox when store.showOutput is false (removes duplicate iframe and allow-scripts+allow-same-origin browser warning) - Back button navigates to previous in-app route via history.state.back - Replace large DEFAULT_CODE stepper example with simpler tabs demo
- Move snoozedUntil/dismissed out of TourProgress into a separate skillz-prefs localStorage key (LocalSkillzPrefs) — keeps TourProgress a clean, server-syncable DTO - dismiss() now hides the resume popup without wiping progress; reset() remains the only way to delete tour data - Extract SkillzAdapter interface with createLocalAdapter() as the seam for future Vuetify One API integration - Fix: use spread-reassignment (clearPrefs) instead of delete to ensure Vue's deep watch persists prefs removals to localStorage
|
commit: |
Mirrors the tours directory structure by adding beginner/intermediate/advanced level folders under skillz/tutorials/. Updates glob patterns and path parsing in index.ts to handle the extra folder depth.
Renames all files, components, composables, storage keys, and CSS classes from the "editor" naming to "playground" to match the final feature name. Also renames editorLink composable to usePlaygroundLink per conventions.
- New stores/playground.ts — Pinia store managing panel/sidebar/examples UI state with namespaced control objects (playground.panel.open(), etc.) - Rename usePlaygroundStore composable → usePlaygroundRepl to avoid collision; add PlaygroundContext interface; default showOutput to false - PlaygroundWorkspace absorbs mobile file-browser overlay (useStack) and emits update:sidebarOpen - playground.vue always renders PlaygroundWorkspace (no more dual Repl/WorkSpace mode); all UI state delegated to Pinia store - skillz.[id].vue passes playground store in tour context - using-the-playground tour handlers implemented
- PlaygroundWorkspace: dual layout branches — panel mode (file tree + editor top, preview full-width below) vs standard mode (file tree full-height sidebar, togglable vertical/horizontal split) - Add vertical/horizontal layout toggle button to tab bar in standard mode - defaultLayout prop pins layout without touching user's stored preference - Add layout-horizontal/layout-vertical icons (mdiViewSplitVertical/Horizontal) - PlaygroundFileTree: fix template ref name collision (tree → tree-el) - PlaygroundBreadcrumbs: move divider style to class prop - playground.vue: intro panel open/close watcher, panel resize handle - router.ts: guard querySelector against invalid hash selectors (base64) - skillz tutorial: misc fixes
- Add mobile editor/preview toggle (Code/Preview buttons) with mobileView state - Mobile intro panel via Teleport + useStack overlay with proper z-index - File panel starts closed on mobile (immediate watcher on isDesktop) - Fix tour step order: sidebar-toggle → file-tree → editor → preview → panel/examples - Add welcome preamble steps to all four beginner tours - Force center placement for first and last tour steps (DiscoveryContent) - Delay resume popup 3s to avoid immediate flash - Remove discovery watches that prevented panel closing on welcome step - Reset button hidden unless devmode is active (skillz/[id]) - Hide Duration/Reset on mobile; Next button truncates gracefully - Add padding to skill title when completed medal is shown - Global grabbing cursor during resize (useResizeHandle) - Clean up abandoned UnoCSS runtime style elements on recompile
- Track latest pointermove position in RAF instead of dropping events; reset latestPos on each drag start to prevent stale carryover - Remove contain-strict toggling during drag (expensive containment context churn on every frame) - Disable Monaco auto-resize during drag to prevent ResizeObserver layout thrashing - Lock overflow-y: scroll on intro panel during panel resize to skip browser scrollbar double-pass layout
Split 420-line PlaygroundWorkspace.vue into four new components: - PlaygroundEditor — Repl pane with scoped REPL CSS - PlaygroundPreview — Sandbox pane with scoped preview CSS - PlaygroundMobileSidebar — mobile file browser overlay - PlaygroundTabBar — tabs row with Code/Preview and layout toggle WorkSpace is now structural scaffolding only.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/playground) with file tree, tab management, resizable panels, and live preview/skillz/tutorial/[id]) with markdown instruction panels, step preloading, URL routing, and resume supportTest plan
/playground— editor loads with file tree, tabs, and live preview/skillz/tutorial/vue-basics— tutorial loads at the correct step