feat: new blocks page#142
Conversation
|
Note
|
| Cohort / File(s) | Summary |
|---|---|
Block Documentation Pages apps/www/content/docs/blocks/linear-player.mdx, apps/www/content/docs/blocks/youtube-music.mdx |
New docs pages with YAML frontmatter (component/preview/registry/status), install commands, interaction behavior, TSX usage examples, and attribution/license notes. |
Documentation Configuration apps/www/content/docs/blocks/meta.json |
Adds blocks docs metadata (title, description, defaultOpen). |
Registry Validation apps/www/registry/collection/index.ts |
Replaces manual registry object assignment with registrySchema.safeParse({ homepage, items, name }); logs result.error.format() on failure and exports result.data on success. |
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~20 minutes
Poem
🐰 I nibble docs in moonlit code,
I hop through props and metadata road.
A player hums, the registry gleams,
I tuck in changes like tiny dreams. 🥕✨
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Title check | ❓ Inconclusive | The title 'feat: new blocks page' is vague and does not clearly convey what the actual changes entail—it could refer to creating UI blocks, documentation blocks, or registry changes. | Consider a more specific title such as 'feat: add Linear Player and YouTube Music documentation blocks' or 'feat: add media player documentation pages with registry schema validation' to better communicate the primary changes. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Commit unit tests in branch
feat/blocks
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/www/content/docs/blocks/youtube-music.mdx`:
- Around line 40-43: The Architecture section claims "three dense layers" but
only lists the first layer, MediaProvider; update the text to either enumerate
the missing two layers (e.g., Playback/Timeline layer and UI/Control layer or
whatever the design uses) with brief descriptions, or change the sentence to
reflect a single layer (e.g., "The block is composed around a primary
MediaProvider container..."); edit the Architecture paragraph in the
youtube-music.mdx content so the heading and list are consistent with the chosen
option and include the existing MediaProvider entry.
- Line 2: Title uses incorrect casing "Youtube Music"; change it to the
canonical product casing "YouTube Music" to match product naming and the
component name YouTubeMusicPlayer—update the title field in
apps/www/content/docs/blocks/youtube-music.mdx from "Youtube Music" to "YouTube
Music".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 5502c1be-5e99-444e-801d-230870fa684c
⛔ Files ignored due to path filters (23)
apps/www/app/(home)/blocks/page.tsxis excluded by none and included by noneapps/www/app/blocks/[[...slug]]/page.tsxis excluded by none and included by noneapps/www/app/blocks/blocks.cssis excluded by none and included by noneapps/www/app/blocks/layout.tsxis excluded by none and included by noneapps/www/app/docs/layout.tsxis excluded by none and included by noneapps/www/app/global.cssis excluded by none and included by noneapps/www/app/limeplay.cssis excluded by none and included by noneapps/www/app/shadcn.cssis excluded by none and included by noneapps/www/components/blocks/block-info-pane.tsxis excluded by none and included by noneapps/www/components/blocks/block-preview-pane.tsxis excluded by none and included by noneapps/www/components/blocks/blocks-sidebar.tsxis excluded by none and included by noneapps/www/components/ui/breadcrumb.tsxis excluded by none and included by noneapps/www/components/ui/resizable.tsxis excluded by none and included by noneapps/www/components/ui/sheet.tsxis excluded by none and included by noneapps/www/components/ui/sidebar.tsxis excluded by none and included by noneapps/www/components/ui/tooltip.tsxis excluded by none and included by noneapps/www/components/youtube-music-hover-player.tsxis excluded by none and included by noneapps/www/hooks/use-mobile.tsis excluded by none and included by noneapps/www/lib/block-showcase.tsxis excluded by none and included by noneapps/www/lib/blocks-source.tsis excluded by none and included by noneapps/www/package.jsonis excluded by none and included by noneapps/www/source.config.tsis excluded by none and included by nonebun.lockis excluded by!**/*.lockand included by none
📒 Files selected for processing (3)
apps/www/content/docs/blocks/linear-player.mdxapps/www/content/docs/blocks/meta.jsonapps/www/content/docs/blocks/youtube-music.mdx
| @@ -0,0 +1,50 @@ | |||
| --- | |||
| title: Youtube Music | |||
There was a problem hiding this comment.
Use canonical product casing in title.
Line 2 should use YouTube capitalization for consistency with product naming and the component name (YouTubeMusicPlayer).
✏️ Suggested fix
-title: Youtube Music
+title: YouTube Music📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| title: Youtube Music | |
| title: YouTube Music |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/www/content/docs/blocks/youtube-music.mdx` at line 2, Title uses
incorrect casing "Youtube Music"; change it to the canonical product casing
"YouTube Music" to match product naming and the component name
YouTubeMusicPlayer—update the title field in
apps/www/content/docs/blocks/youtube-music.mdx from "Youtube Music" to "YouTube
Music".
There was a problem hiding this comment.
Pull request overview
Adds a new /blocks section to the apps/www Next.js app, powered by a dedicated Fumadocs collection, to render “block” documentation alongside interactive previews.
Changes:
- Introduces a new
blocksdocs collection + loader and a new/blocksroute with layout, sidebar navigation, and resizable preview/info panes. - Adds initial block MDX pages (
linear-player,youtube-music) and supporting UI components for browsing and rendering. - Updates dependencies (Fumadocs,
lucide-react,react-resizable-panels) and migrates some UI primitives toradix-ui.
Reviewed changes
Copilot reviewed 25 out of 26 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| bun.lock | Dependency lock updates for new blocks feature + library upgrades. |
| apps/www/package.json | Bumps Fumadocs + adds radix-ui, updates related UI deps. |
| apps/www/source.config.ts | Defines a new blocks Fumadocs collection with Zod frontmatter schema. |
| apps/www/lib/blocks-source.ts | Adds a Fumadocs loader for blocks content under /blocks. |
| apps/www/lib/block-showcase.tsx | Adds a preview/showcase registry and icon lookup for blocks. |
| apps/www/hooks/use-mobile.ts | Minor cleanup of effect cleanup function. |
| apps/www/components/youtube-music-hover-player.tsx | Updates CTA link to point to the new blocks page. |
| apps/www/components/ui/tooltip.tsx | Switches tooltip primitive import and tweaks styling. |
| apps/www/components/ui/sidebar.tsx | Updates Slot usage via radix-ui and adds reserveSpace option. |
| apps/www/components/ui/sheet.tsx | Switches dialog primitive import and adds optional close button. |
| apps/www/components/ui/resizable.tsx | Updates for react-resizable-panels@4 and refactors panel wrappers. |
| apps/www/components/ui/breadcrumb.tsx | Adds a new breadcrumb component implementation. |
| apps/www/components/blocks/blocks-sidebar.tsx | Adds the blocks sidebar UI + toggle/dismiss behavior. |
| apps/www/components/blocks/block-preview-pane.tsx | Adds preview pane wrapper for block showcase content. |
| apps/www/components/blocks/block-info-pane.tsx | Adds documentation/info pane wrapper for block content. |
| apps/www/app/shadcn.css | Removes redundant Tailwind imports. |
| apps/www/app/limeplay.css | Removes redundant Tailwind imports. |
| apps/www/app/global.css | Adjusts global imports and moves @custom-variant dark here. |
| apps/www/app/docs/layout.tsx | Changes docs CSS import path to be relative. |
| apps/www/app/blocks/layout.tsx | Adds blocks route layout wiring sidebar + theme provider. |
| apps/www/app/blocks/blocks.css | Adds blocks-specific CSS imports/theme overrides. |
| apps/www/app/blocks/[[...slug]]/page.tsx | Implements the main blocks page renderer (MDX + preview) + metadata/static params. |
| apps/www/content/docs/blocks/meta.json | Adds folder metadata for blocks docs section. |
| apps/www/content/docs/blocks/linear-player.mdx | Adds initial “Linear Player” block docs page. |
| apps/www/content/docs/blocks/youtube-music.mdx | Adds initial “YouTube Music” block docs page. |
| apps/www/app/(home)/blocks/page.tsx | Removes the old home-group blocks page in favor of the new /blocks route. |
Comments suppressed due to low confidence (1)
apps/www/components/ui/resizable.tsx:55
ResizableHandleno longer applies any focus-visible styles to the resize handle. This makes the handle hard/impossible to see when keyboard-focused, which is an accessibility regression. Consider restoring a visible focus ring (or another clear focus indicator) onPanelResizeHandle.
<ResizablePrimitive.PanelResizeHandle
className={cn(
`
relative flex w-px items-center justify-center
after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2
data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0
data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full
data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2
[&[data-panel-group-direction=vertical]>div]:rotate-90
`,
| return blockShowcaseRegistry[preview as keyof typeof blockShowcaseRegistry] | ||
| .icon |
There was a problem hiding this comment.
getBlockIcon will throw at runtime if preview is not a key in blockShowcaseRegistry (e.g. a typo in frontmatter), because the index access can return undefined and then .icon is dereferenced. Consider guarding the lookup (optional chaining / in check) and returning undefined when not found (or throwing a clearer error).
| return blockShowcaseRegistry[preview as keyof typeof blockShowcaseRegistry] | |
| .icon | |
| const entry = blockShowcaseRegistry[preview as keyof typeof blockShowcaseRegistry] | |
| return entry?.icon |
| } satisfies Record<string, BlockShowcaseDefinition> | ||
|
|
||
| export function getBlockIcon(preview: string): ReactNode | undefined { | ||
| return blockShowcaseRegistry[preview as keyof typeof blockShowcaseRegistry] | ||
| .icon | ||
| } | ||
|
|
||
| export function getBlockShowcase(preview: string) { | ||
| return blockShowcaseRegistry[preview as keyof typeof blockShowcaseRegistry] |
There was a problem hiding this comment.
getBlockShowcase can return undefined for unknown preview keys, but the function currently has no explicit return type and callers assume it always exists. Please either narrow the input type to known keys or add a runtime guard and return type (BlockShowcaseDefinition | undefined) so call sites can handle missing showcases safely.
| } satisfies Record<string, BlockShowcaseDefinition> | |
| export function getBlockIcon(preview: string): ReactNode | undefined { | |
| return blockShowcaseRegistry[preview as keyof typeof blockShowcaseRegistry] | |
| .icon | |
| } | |
| export function getBlockShowcase(preview: string) { | |
| return blockShowcaseRegistry[preview as keyof typeof blockShowcaseRegistry] | |
| } satisfies Record<string, BlockShowcaseDefinition | undefined> | |
| export function getBlockIcon(preview: string): ReactNode | undefined { | |
| const entry = blockShowcaseRegistry[preview] | |
| return entry?.icon | |
| } | |
| export function getBlockShowcase( | |
| preview: string, | |
| ): BlockShowcaseDefinition | undefined { | |
| return blockShowcaseRegistry[preview] |
| const params = await props.params | ||
| const slug = params.slug ?? [] | ||
| const page = blocksSource.getPage(slug) | ||
|
|
||
| if (!page) { | ||
| notFound() | ||
| } |
There was a problem hiding this comment.
slug defaults to [], which means the route /blocks will call blocksSource.getPage([]) and likely 404 unless there is an index page in content/docs/blocks. If /blocks is intended to be a valid landing page, handle the empty-slug case explicitly (redirect to a default block or render an index/list page).
| const showcase = getBlockShowcase(page.data.preview) | ||
|
|
||
| const MDXContent = page.data.body | ||
| const PreviewComponent = showcase.component | ||
| const content = ( |
There was a problem hiding this comment.
getBlockShowcase(page.data.preview) is used without validating the return value; if a block’s frontmatter preview doesn’t exist in the showcase registry, showcase.component will throw. Add a guard (and likely notFound() or a fallback) when no showcase is registered for the page.
| return ( | ||
| <motion.span | ||
| animate={{ | ||
| height: isExpanded && !isMobile ? "42px" : "32px", | ||
| width: isExpanded && !isMobile ? "42px" : "32px", | ||
| x: isExpanded && !isMobile ? "-10px" : "0px", | ||
| y: isExpanded && !isMobile ? "-10px" : "0px", | ||
| }} | ||
| className="fixed top-0 left-10 z-[21] mt-[35.5px] flex items-center justify-center rounded-xl bg-background" | ||
| initial={false} | ||
| onClick={toggleSidebar} | ||
| transition={{ | ||
| duration: SIDEBAR_DURATION, | ||
| ease: SIDEBAR_EASE, | ||
| }} | ||
| > | ||
| <button | ||
| className={` |
There was a problem hiding this comment.
FloatingSidebarToggle attaches onClick to a span while also rendering a nested <button>. This creates nested interactive elements and the clickable container itself isn’t keyboard-accessible. Consider making the motion element a motion.button (single interactive element) or moving the click handler onto the button and using a non-interactive wrapper.
| @@ -0,0 +1,7 @@ | |||
| @import "tailwindcss"; | |||
There was a problem hiding this comment.
blocks.css re-imports tailwindcss even though app/global.css already imports it. This will generate duplicate base/utilities CSS (and can affect ordering). Consider removing the Tailwind import here and only importing the fumadocs CSS/theme overrides.
| @import "tailwindcss"; |
c5d5751 to
cb89da7
Compare
Summary by CodeRabbit