feat: add live preview side panel with debounced markdown rendering - #974
Open
BettyXu2001 wants to merge 4 commits into
Open
feat: add live preview side panel with debounced markdown rendering#974BettyXu2001 wants to merge 4 commits into
BettyXu2001 wants to merge 4 commits into
Conversation
Add 21 vitest + RTL test cases covering MiniMarkdownPreview (13) and MarkdownPreview (8): MiniMarkdownPreview: - Rendering: paragraphs, h1/h2/h3, links, lists, GFM tables, code, blockquotes, horizontal rules - Image sizing branches (width=40 icon vs natural size) - XSS sanitization (script tags stripped via rehypeSanitize) - a11y: role=document, no copy/download buttons (lightweight variant) - React.memo instance stability across identical props MarkdownPreview: - Title rendering, default preview mode, raw markdown toggle - aria-pressed state synchronization on view mode switch - Clipboard copy via navigator.clipboard.writeText - File download: object URL creation, anchor click, download attr, revokeObjectURL cleanup - a11y: role=region + role=toolbar - XSS sanitization parity with MiniMarkdownPreview Test isolation via afterEach(vi.restoreAllMocks + useRealTimers). Clipboard stubbed with Object.defineProperty (configurable). Anchor click captured via prototype wrapper with try/finally restore.
Run \ pm run format\ to fix formatting drift caught by \ pm run format:check\. No logic changes — only whitespace, line wrapping, and class attribute ordering adjustments to satisfy prettier configuration (including prettier-plugin-tailwindcss). Files: - src/app/page.tsx - src/components/sections/links-section.tsx - src/components/ui/markdown-preview.tsx - src/lib/storage.ts - src/styles/tailwind.css
Apply prettier formatting to the newly added test file missed in the previous test commit. No content changes.
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.
🔄 Pull Request
📋 Type of Change (check all applicable)
lgbreakpoint)📖 Description
What changed?
Adds a persistent Live Preview side panel that renders the README in real time as the user fills in the profile form, eliminating the need to navigate to the final "Preview" step to see the result.
New feature (
c335414):src/components/ui/markdown-preview.tsx— newMiniMarkdownPreviewexport, a lightweight preview variant (no copy/download buttons, no view-mode toggle, compact typography) purpose-built for the side panel.src/app/page.tsx—flex-colon mobile,lg:flex-row~48/52 split on desktop).Maximize2/Minimize2) and Hide (EyeOff).lg): floating "Preview" FAB opens a bottom-sheet preview with grab handle and dismissible backdrop.MarkdownPreviewalready lives).Tests (
c90b5d0):src/components/ui/__tests__/markdown-preview.test.tsx— 21 vitest + React Testing Library cases covering bothMiniMarkdownPreview(13) andMarkdownPreview(8): rendering of all markdown node types, image sizing branches, GFM tables, XSS sanitization, view-mode toggle, clipboard copy, file download, ARIA roles, andReact.memoinstance stability.Formatting (
1b40c78,c3edfe6):npm run formatto fix prettier drift in 6 files (5 historical + the new test file). No logic changes — only whitespace, line wrapping, and Tailwind class ordering viaprettier-plugin-tailwindcss.Why was this change made?
Previously, users had to complete all 5 form steps and navigate to the final "Preview & Generate" step to see what their README looked like. This broke the edit→review loop and required frequent back-and-forth when iterating on wording, section ordering, and layout — especially painful when tweaking skill badges or social links.
How does this change help users?
MiniMarkdownPreviewcomponent keep typing smooth even on long documents.🔗 Related Issues
🧪 Testing & Quality Assurance
Testing Done (check all applicable)
Test Instructions
npm install && npm run dev, open http://localhost:3000MarkdownPreviewalready lives).npm test— all 34 tests should pass.npm run build— static export should succeed (9/9 pages prerendered).Expected Behavior
📸 Screenshots/Recordings
Before
Before: form-only layout, no preview until user reaches the final "Preview & Generate" step


After
After: side-by-side layout on desktop with sticky left preview; floating bottom sheet on mobile; Show/Hide toggle button in the toolbar

![Uploading image.png…]()
📋 Checklist
Code Quality
npm run type-check) ✅ 0 errorsnpm run lint) ✅ 0 errors / 42 warnings (4react-hooks/exhaustive-depswarnings onJSON.stringifydeps in the auto-saveuseEffect— an existing pattern in the codebase, suppressed witheslint-disable-next-line)npm run format) ✅format:checkreports "All matched files use Prettier code style"npm run build) ✅ 9/9 pages prerendered, static export 2/2MiniMarkdownPreviewcomponent)Accessibility
<button>throughout, natural tab order)<nav aria-label="Form progress">, each step button hasaria-label+aria-current="step".aria-label.sr-onlylive region witharia-live="polite" aria-atomic="true".<nav aria-label="Form navigation">, Previous/Next buttons carry descriptivearia-label.aria-label.title="Live". Consider wrapping the dot + label in<div role="status" aria-live="polite">or adding an explicitaria-label="Live preview status: live"for screen readers. (Non-blocking; happy to address in a follow-up.)Mobile & Responsive
flex flex-col lg:flex-rowmain split; preview drops to an FAB-triggered bottom sheet belowlg.overflow-x-autowithmin-w-maxfor horizontal scroll on small widths.sm:,md:,lg:breakpoints consistently applied.Browser Compatibility
Documentation
MiniMarkdownPreviewJSDoc, section divider comments in page layout, debounce explanation)feat:/test:/style:perCOMMIT_CONVENTION.md)Security & Privacy
zodResolverinuseForm;profileSchema/linksSchema/socialSchemaunchanged frommain)MiniMarkdownPreviewappliesrehypeRaw + rehypeSanitizeidentical to the existingMarkdownPreviewpipeline.<script>tags are stripped from rendered output.trackReadmeGenerated/trackFileExportedpatterns)🚀 Deployment Notes
framer-motion,lucide-react,react-markdown,rehype-raw,rehype-sanitize,remark-gfmalready in the tree)📝 Additional Notes
c335414feat: 更新功能 (main feature; description is Chinese — see note below)c90b5d0test: add markdown preview component tests1b40c78style: apply prettier formattingc3edfe6style: format markdown preview test filec335414uses a Chinese description (feat: 更新功能). The type (feat) and format matchCOMMIT_CONVENTION.md, but the description is not in English. If the maintainers prefer English commit messages, I can amendc335414tofeat(ui): add live preview side panel with debounced markdown renderingand force-push to this branch only (no reviews received yet). Please advise.src/app/page.tsxretains ~15console.log/debugstatements left over from development (auto-save flow, data load, initial state). They don't break anything but will fire in production builds. Recommend removing or gating behind a dev flag (e.g.if (process.env.NODE_ENV === 'development') console.log(...)) before merge. Happy to address in a follow-up commit if desired.anytypes inMiniMarkdownPreview: The custom components map (p,h1…hr) usesanyfor props to mirror the pattern used by the existingMarkdownPreviewin the same file. Consistent with the codebase but not type-strict.MiniMarkdownPreviewandMarkdownPreview. No integration test for the live preview toggle + debounce behavior inpage.tsxyet — would require a heavier setup withreact-hook-formandframer-motionmocking; can be added in a follow-up if requested.👀 Reviewers
By submitting this PR, I confirm that:
https://github.com/rahuldkjain/github-profile-readme-generator/blob/master/CODE_OF_CONDUCT.mdhttps://github.com/rahuldkjain/github-profile-readme-generator/blob/master/CONTRIBUTING.mdhttps://github.com/rahuldkjain/github-profile-readme-generator/blob/master/COMMIT_CONVENTION.mdfor my commit messages (see note about English description forc335414)