Skip to content

Conversation

YarikDrago
Copy link

@YarikDrago YarikDrago commented Aug 14, 2025

The app currently uses two chevron styles: one from the lucide-react library and one custom. The custom variant is better suited to the 8-bit arcade style, so I standardize on it and replace existing usages accordingly.

Summary by CodeRabbit

  • Style

    • Updated chevron icons to 8‑bit raster style across Breadcrumbs, Calendar, Context Menu, Menubar, Dropdowns, and Pagination for a consistent retro look. Minor alignment/spacing adjustments in some menus and triggers.
  • Refactor

    • Centralized chevron icons as shared components used across multiple UI elements, reducing duplication and ensuring consistent sizing and appearance.
  • Chores

    • Normalized line endings across many 8‑bit components and styles. No functional or API changes.

@YarikDrago YarikDrago requested a review from TheOrcDev as a code owner August 14, 2025 20:18
Copy link

vercel bot commented Aug 14, 2025

@YarikDrago is attempting to deploy a commit to the 8bitcn Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

coderabbitai bot commented Aug 14, 2025

Walkthrough

Introduces two new chevron icon asset components and updates multiple UI components to use them instead of inline SVGs or lucide-react icons. Numerous registry JSON files were normalized to CRLF line endings. One registry item removes a Button import while still using Button in login-form-with-image.

Changes

Cohort / File(s) Summary
New icon assets
components/ui/8bit/assets/chevronLeftIcon.tsx, components/ui/8bit/assets/chevronRightIcon.tsx
Added static React SVG icon components: ChevronLeftIcon and ChevronRightIcon (named exports).
8bit components switch to local chevrons
components/ui/8bit/breadcrumb.tsx, components/ui/8bit/calendar.tsx, components/ui/8bit/context-menu.tsx, components/ui/8bit/menubar.tsx, components/ui/8bit/pagination.tsx
Replaced inline or lucide-react chevrons with local ChevronLeftIcon/ChevronRightIcon components. No public API changes.
Shared/standard components switch to local chevrons
components/ui/breadcrumb.tsx, components/ui/calendar.tsx, components/ui/dropdown-menu.tsx, components/ui/pagination.tsx
Switched left/right chevrons from lucide-react to local assets; retained other imports (e.g., MoreHorizontal/ChevronDown). No public API changes.
Registry JSONs reflecting icon swaps
public/r/8bit-breadcrumb.json, public/r/8bit-calendar.json, public/r/8bit-context-menu.json, public/r/8bit-menubar.json, public/r/8bit-pagination.json
Registry content updated to use ChevronLeftIcon/ChevronRightIcon where applicable; plus formatting updates.
Registry JSON with potential missing import
public/r/8bit-login-form-with-image.json
Removed Button import while Button is still used in the TSX block. Other files show formatting-only changes.
Registry JSON minor code formatting
public/r/8bit-skeleton.json
Added semicolon to CSS import; line-ending normalization.
Formatting-only (CRLF normalization)
public/r/8bit-accordion.json, .../8bit-alert*.json, .../8bit-audio-settings.json, .../8bit-avatar.json, .../8bit-badge.json, .../8bit-button.json, .../8bit-card.json, .../8bit-carousel.json, .../8bit-chart*.json, .../8bit-cheat-code.json, .../8bit-checkbox.json, .../8bit-collapsible.json, .../8bit-combo-box.json, .../8bit-command.json, .../8bit-dialog*.json, .../8bit-drawer.json, .../8bit-dropdown-menu.json, .../8bit-game-*.json, .../8bit-health-bar.json, .../8bit-hover-card.json, .../8bit-input*.json, .../8bit-label.json, .../8bit-login-*.json, .../8bit-main-menu.json, .../8bit-mana-bar.json, .../8bit-navigation-menu.json, .../8bit-popover.json, .../8bit-profile-card.json, .../8bit-progress.json, .../8bit-radio-group.json, .../8bit-resizable.json, .../8bit-scroll-area.json, .../8bit-select.json, .../8bit-sheet.json, .../8bit-sidebar.json, .../8bit-slider.json, .../8bit-switch.json, .../8bit-table.json, .../8bit-tabs.json, .../8bit-textarea.json, .../8bit-toast.json, .../8bit-toggle*.json, .../8bit-tooltip.json
No functional changes; only line endings updated.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • TheOrcDev

Poem

In pixels neat, two chevrons gleam,
I hop between each UI seam.
Left, right—icons take their place,
Inline gone without a trace.
New lines flip, CR to LF’s delight—
Carrot raised, I ship tonight! 🥕✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 52

🔭 Outside diff range comments (3)
components/ui/8bit/pagination.tsx (2)

132-155: Accessibility: Provide an accessible name for “Previous” on small screens.

On small viewports the “Previous” text is hidden (hidden sm:block), leaving only the icon with no accessible name. Add aria-label to the link and keep the text available to screen readers.

-  return (
-    <PaginationLink
+  return (
+    <PaginationLink
+      aria-label="Previous"
       className={cn(
         "relative group",
         "flex flex-row w/full text-sm",
         ...
       )}
       {...props}
     >
-      <ChevronLeftIcon />
-      <span className="hidden sm:block">Previous</span>
+      <ChevronLeftIcon aria-hidden="true" />
+      <span className="sr-only sm:not-sr-only">Previous</span>
     </PaginationLink>
   );

157-181: Accessibility + minor cleanup: add aria-label and remove duplicate classes.

  • The label is hidden on small screens; add aria-label and sr-only text.
  • flex flex-row w-full text-sm appears twice; remove the duplicate.
-  return (
-    <PaginationLink
+  return (
+    <PaginationLink
+      aria-label="Next"
       className={cn(
         "relative group",
-        "flex flex-row w-full text-sm",
+        "flex flex-row w-full text-sm",
         "bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent",
         "rounded-none border-dashed border-y-4 border-transparent",
         "hover:border-foreground focus:border-foreground active:border-transparent",
         "dark:hover:border-ring dark:focus:border-ring",
         "data-[active=true]:border-none aria-[current=page]:border-none",
-        "flex flex-row text-sm w-full",
         font !== "normal" && "retro",
         className
       )}
       {...props}
     >
-      <span className="hidden sm:block">Next</span>
-      <ChevronRightIcon />
+      <span className="sr-only sm:not-sr-only">Next</span>
+      <ChevronRightIcon aria-hidden="true" />
     </PaginationLink>
   );
components/ui/calendar.tsx (1)

137-146: Don’t drop DayPicker-provided props; forward className/props and fix a11y on chevrons

The Chevron render function receives className and props from DayPicker. These are currently ignored for left/right chevrons, which can break theming, sizing, and a11y. Also, the asset icons include an aria-label, which can leak into the button’s accessible name.

  • Forward className and props to the icon.
  • Ensure the icon is decorative: aria-hidden="true" focusable="false".
  • This requires the asset components to accept and spread SVG props.

Apply in components/ui/calendar.tsx:

-          if (orientation === "left") {
-            return <ChevronLeftIcon />;
-          }
+          if (orientation === "left") {
+            return (
+              <ChevronLeftIcon
+                className={cn("size-4", className)}
+                aria-hidden="true"
+                focusable="false"
+                {...props}
+              />
+            );
+          }
...
-          if (orientation === "right") {
-            return <ChevronRightIcon />;
-          }
+          if (orientation === "right") {
+            return (
+              <ChevronRightIcon
+                className={cn("size-4", className)}
+                aria-hidden="true"
+                focusable="false"
+                {...props}
+              />
+            );
+          }

Update the assets to accept props and default to aria-hidden:

// components/ui/8bit/assets/chevronLeftIcon.tsx
import { cn } from "@/lib/utils";

export const ChevronLeftIcon: React.FC<React.SVGProps<SVGSVGElement>> = ({
  className,
  ...props
}) => (
  <svg
    viewBox="0 0 256 256"
    fill="currentColor"
    stroke="currentColor"
    strokeWidth="0.25"
    className={cn(className)}
    aria-hidden="true"
    focusable="false"
    {...props}
  >
    {/* rects */}
  </svg>
);

// components/ui/8bit/assets/chevronRightIcon.tsx
import { cn } from "@/lib/utils";

export const ChevronRightIcon: React.FC<React.SVGProps<SVGSVGElement>> = ({
  className,
  ...props
}) => (
  <svg
    viewBox="0 0 256 256"
    fill="currentColor"
    stroke="currentColor"
    strokeWidth="0.25"
    className={cn(className)}
    aria-hidden="true"
    focusable="false"
    {...props}
  >
    {/* rects */}
  </svg>
);
♻️ Duplicate comments (1)
public/r/8bit-card.json (1)

13-13: Same note as 8bit-card in login-form: verify double className usage.

The wrapper and inner ShadcnCard both receive className. Confirm this is intentional for the 8-bit wrapper pattern; otherwise, consider omitting it from one layer as suggested earlier.

🧹 Nitpick comments (55)
public/r/8bit-alert-dialog.json (2)

13-13: alertDialogVariants is defined but not used; either remove it or apply it to compose classes.

Right now cva is only used for typing (VariantProps) while runtime class composition is manual. Prefer one source of truth.

Apply cva for class composition:

- export const alertDialogVariants = cva("", {
+ export const alertDialogVariants = cva("", {
   variants: {
     font: {
       normal: "",
       retro: "retro",
     },
   },
   defaultVariants: {
     font: "retro",
   },
 });

 interface BitAlertDialogContentProps
   extends React.ComponentProps<typeof AlertDialogPrimitive.Content>,
     VariantProps<typeof alertDialogVariants> {}

 function AlertDialogContent({
   className,
   children,
   font,
   ...props
 }: BitAlertDialogContentProps) {
   return (
     <AlertDialogPortal>
       <AlertDialogOverlay />
-      <>
-        <ShadcnAlertDialogContent
-          className={cn(
-            "rounded-none border-y-6 border-foreground dark:border-ring",
-            font !== "normal" && "retro",
-            className
-          )}
-          {...props}
-        >
+      <ShadcnAlertDialogContent
+        className={cn(
+          "rounded-none border-y-6 border-foreground dark:border-ring",
+          alertDialogVariants({ font }),
+          className
+        )}
+        {...props}
+      >
           {children}
           <div
             className="absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none"
             aria-hidden="true"
           />
-        </ShadcnAlertDialogContent>
-      </>
+      </ShadcnAlertDialogContent>
     </AlertDialogPortal>
   );
 }

13-13: Remove redundant React fragment around ShadcnAlertDialogContent.

The empty fragment inside AlertDialogPortal serves no purpose.

-    <AlertDialogPortal>
-      <AlertDialogOverlay />
-      <>
-        <ShadcnAlertDialogContent
+    <AlertDialogPortal>
+      <AlertDialogOverlay />
+      <ShadcnAlertDialogContent
           className={cn(
             "rounded-none border-y-6 border-foreground dark:border-ring",
             font !== "normal" && "retro",
             className
           )}
           {...props}
         >
           {children}
           <div
             className="absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none"
             aria-hidden="true"
           />
-        </ShadcnAlertDialogContent>
-      </>
+      </ShadcnAlertDialogContent>
     </AlertDialogPortal>
public/r/8bit-sidebar.json (1)

19-19: Consider replacing CSS @import Google Fonts with next/font (self-hosted) for performance and CSP resilience

Using @import to pull Google Fonts can be render-blocking and brittle under strict CSP. If this is a Next.js app (common with shadcn setups), prefer next/font/google to self-host and automatically preload.

Example (outside this JSON, in the TSX that consumes the font):

import { Press_Start_2P } from "next/font/google";

const pressStart2P = Press_Start_2P({ weight: "400", subsets: ["latin"], display: "swap" });

// then use: className={cn(pressStart2P.className, "retro ...")}

Optional repo hygiene: to avoid churn from CRLF/LF flips in registry content, ensure .gitattributes or .editorconfig normalizes line endings consistently across platforms.

public/r/8bit-drawer.json (3)

13-13: Remove unnecessary Fragment in DrawerTrigger.

The empty Fragment adds no value here.

Patch:

 function DrawerTrigger({
   className,
   children,
   ...props
 }: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
   return (
-    <>
       <ShadcnDrawerTrigger
         className={cn(
           "border-foreground dark:border-ring hover:bg-transparent active:bg-transparent focus:bg-transparent rounded-none border-4 focus:border-foreground hover:border-foreground dark:focus:border-ring bg-transparent data-[state=open]:bg-transparent data-[state=open]:border-foreground dark:data-[state=open]:border-ring",
           className,
           "retro"
         )}
         {...props}
       >
         {children}
       </ShadcnDrawerTrigger>
-    </>
   );
 }

13-13: Minor className cleanup in Header/Footer.

cn("", className, "retro") includes a redundant empty string. Not harmful, but noisy.

Patch:

-  return (
-    <ShadcnDrawerHeader className={cn("", className, "retro")} {...props}>
+  return (
+    <ShadcnDrawerHeader className={cn(className, "retro")} {...props}>
       {children}
     </ShadcnDrawerHeader>
   );
-  return (
-    <ShadcnDrawerFooter className={cn("", className, "retro")} {...props}>
+  return (
+    <ShadcnDrawerFooter className={cn(className, "retro")} {...props}>
       {children}
     </ShadcnDrawerFooter>
   );

19-19: Prefer self-hosted or next/font for Google Fonts; avoid @import in component CSS.

Using @import inside component-scoped CSS can trigger additional blocking requests and duplicates across components. Consider:

  • Load the font once via next/font/google (preferred) or a top-level <link> in your Document/head.
  • Self-host fonts for privacy/compliance and reliability.

Example with next/font:

// app/fonts.ts
import { Press_Start_2P } from "next/font/google";
export const pressStart = Press_Start_2P({ weight: "400", subsets: ["latin"], display: "swap" });

// usage
// <div className={`${pressStart.className} retro`}>...</div>

If keeping the CSS file, move the @import to a global stylesheet that is included once, and have .retro only set font-family.

public/r/8bit-alert.json (2)

13-13: Optional: forwardRef for consistency with shadcn/ui patterns

Align with shadcn components by forwarding refs from your wrapper to the root element. This improves composability (e.g., focusing, anchoring portals/popovers).

Apply this diff to components/ui/8bit/alert.tsx:

-import type React from "react";
+import type React from "react";
 import { type VariantProps, cva } from "class-variance-authority";
@@
-function Alert({
-  children,
-  className,
-  font,
-  variant,
-  ...rest
-}: BitAlertProps) {
-  return (
-    <div className={cn("relative", className)}>
+const Alert = React.forwardRef<HTMLDivElement, BitAlertProps>(function Alert(
+  { children, className, font, variant, ...rest },
+  ref
+) {
+  return (
+    <div ref={ref} className={cn("relative", className)}>
       <ShadcnAlert
         {...rest}
         variant={variant}
         className={cn(
           "relative rounded-none border-none bg-background",
           alertVariants({ font })
         )}
       >
         {children}
       </ShadcnAlert>
@@
-}
+});
+Alert.displayName = "Alert";

19-19: Nit: Prefer next/font or self-hosted fonts over CSS @import

Using @import for Google Fonts is less performant and can be render-blocking. Since this is a Next.js app, consider next/font (with Press_Start_2P) or self-hosting. You already use display=swap, which is good.

Example (Next.js):

import { Press_Start_2P } from "next/font/google";

export const pressStart2P = Press_Start_2P({
  subsets: ["latin"],
  weight: "400",
  display: "swap",
  variable: "--font-retro",
});

Then apply className={pressStart2P.className} or use the CSS variable for your .retro class.

public/r/8bit-health-bar.json (1)

11-11: Confirm CRLF normalization policy to avoid cross-platform churn.

These content entries switched to CRLF. Ensure your repo’s .gitattributes intentionally enforces CRLF for these files (or globally) to prevent future churn and inconsistent diffs across platforms.

Also applies to: 17-17, 23-23

public/r/8bit-command.json (1)

19-19: Optional: Avoid CSS @import for Google Fonts; prefer next/font or self-hosting for performance

Using @import to load fonts can block rendering and is discouraged. Consider migrating to next/font (or self-hosting the font files) to improve performance and avoid FOUC/CLS.

If you want, I can provide a next/font-based version of the retro font setup that preserves the same styling.

public/r/8bit-skeleton.json (1)

19-19: CSS is fine; note that Google Fonts @import can be suboptimal for performance

The .retro scoping and display=swap are good. If this component appears frequently, consider moving the Google Font loading to a global <link> in the app shell or self-hosting to reduce duplicate fetch overhead and improve caching.

public/r/8bit-sheet.json (1)

13-13: Tidy up the close SVG: drop empty attr, avoid conflicting sizing, remove duplicate rect.

Small cleanups to the inline SVG improve readability and avoid redundant DOM attrs.

Apply this diff to the embedded TSX (components/ui/8bit/sheet.tsx):

-          <svg
-            width={50}
-            height={50}
+          <svg
             viewBox="0 0 256 256"
             fill="currentColor"
             xmlns="http://www.w3.org/2000/svg"
             stroke="currentColor"
             strokeWidth={0.25}
-            color=""
             className="w-6 h-6"
             aria-label="x"
           >
@@
-            <rect
-              width={14}
-              height={14}
-              rx={1}
-              transform="matrix(0 -1 -1 0 136 136)"
-            />
+            {/* (duplicate rect at 136,136 removed) */}
public/r/8bit-toast.json (1)

13-13: Avoid shadowing and simplify classes in toast helper.

Rename the parameter to reduce confusion with the exported toast and simplify the className literal; also mark the unused callback id with a leading underscore.

Apply this diff to components/ui/8bit/toast.tsx:

-export function toast(toast: string) {
-  return sonnerToast.custom((id) => <Toast id={id} title={toast} />);
+export function toast(message: string) {
+  return sonnerToast.custom((_id) => <Toast id={_id} title={message} />);
 }
@@
-  return (
-    <div className={`relative ${"retro"}`}>
+  return (
+    <div className="relative retro">
public/r/8bit-table.json (1)

13-13: Trim redundant padding classes.

p-4 py-2.5 is overlapping; prefer px-4 py-2.5 for clarity.

Apply this diff to components/ui/8bit/table.tsx:

-      default: "p-4 py-2.5 border-y-6 border-foreground dark:border-ring",
+      default: "px-4 py-2.5 border-y-6 border-foreground dark:border-ring",
public/r/8bit-login-form.json (3)

16-16: Replace placeholder “#” link with a button to avoid accidental navigation.

Using href="#" can cause undesired scroll/navigation. Use a button for the placeholder action.

Apply this diff to components/ui/8bit/blocks/login-form.tsx:

-                  <a
-                    href="#"
-                    className="inline-block text-xs underline-offset-4 hover:underline"
-                  >
-                    Forgot password?
-                  </a>
+                  <button
+                    type="button"
+                    className="inline-block text-left text-xs underline-offset-4 hover:underline"
+                    aria-label="Forgot password"
+                  >
+                    Forgot password?
+                  </button>

28-28: Double-application of className (wrapper and inner). Confirm intent.

className is applied to both the outer wrapper and the inner ShadcnCard. This can lead to unexpected styling cascades. If this is intentional for the 8-bit wrappers, ignore. Otherwise, omit className from one of them.

If you want to restrict className to the inner card only, adjust like:

-function Card({ ...props }: BitCardProps) {
-  const { className, font } = props;
+function Card({ ...props }: BitCardProps) {
+  const { className, font, ...rest } = props as any;
@@
-      <ShadcnCard
-        {...props}
+      <ShadcnCard
+        {...rest}
         className={cn(
           "rounded-none border-0 !w-full",
           font !== "normal" && "retro",
           className
         )}
       />

40-40: Rename inputVariants to labelVariants for clarity in Label.

Minor naming mismatch; improves readability.

Apply this diff to components/ui/8bit/label.tsx:

-export const inputVariants = cva("", {
+export const labelVariants = cva("", {
@@
-interface BitLabelProps
-  extends React.ComponentProps<typeof LabelPrimitive.Root>,
-    VariantProps<typeof inputVariants> {
+interface BitLabelProps
+  extends React.ComponentProps<typeof LabelPrimitive.Root>,
+    VariantProps<typeof labelVariants> {
public/r/8bit-radio-group.json (1)

13-13: Avoid duplicating className on both wrapper and Item

The same className is applied to the outer wrapper and the inner Item, which can lead to conflicting styles and unexpected specificity. Apply user className only to the interactive root (Item) and keep the wrapper stable.

Apply this minimal change (if you don’t adopt the forwardRef diff above, adjust accordingly):

-  return (
-    <div className={cn("relative", className)}>
+  return (
+    <div className="relative">
       <RadioGroupPrimitive.Item
         ref={ref}
         className={cn(
           "...",
-          className
+          className
         )}
         {...props}
       >
public/r/8bit-select.json (2)

13-13: Don’t reuse the same className for both wrapper and SelectTrigger

Passing className to both the wrapper div and the Shadcn trigger can cause styling collisions. Keep the wrapper’s styling stable and apply custom className to the trigger only.

Apply this diff to components/ui/8bit/select.tsx:

-function SelectTrigger({ children, ...props }: BitSelectTriggerProps) {
-  const { className, font } = props;
+function SelectTrigger({ children, ...props }: BitSelectTriggerProps) {
+  const { className, font } = props;
 
   return (
-    <div
-      className={cn(
-        "relative border-y-6 border-foreground dark:border-ring",
-        className,
-        font !== "normal" && "retro"
-      )}
-    >
+    <div className={cn("relative border-y-6 border-foreground dark:border-ring", font !== "normal" && "retro")}>
       <ShadcnSelectTrigger
         {...props}
         className={cn("rounded-none ring-0 w-full border-0", className)}
       >
         {children}
       </ShadcnSelectTrigger>
 
       <div
         className="absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none"
         aria-hidden="true"
       />
     </div>
   );
 }

13-13: Type consistency: use the same source for ScrollDown/Up button prop types

SelectScrollDownButton uses SelectPrimitive.ScrollDownButton for its prop type, while SelectScrollUpButton uses the Shadcn alias. Align them to avoid subtle mismatches.

-function SelectScrollDownButton({
-  className,
-  ...props
-}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
+function SelectScrollDownButton({
+  className,
+  ...props
+}: React.ComponentProps<typeof ShadcnSelectScrollDownButton>) {
   return <ShadcnSelectScrollDownButton className={cn(className)} {...props} />;
 }
public/r/8bit-dropdown-menu.json (1)

13-13: Fix typo in type name: BitDropdownMenuContentProps

The type is spelled BitDropownMenuContentProps. Rename to BitDropdownMenuContentProps and update usages for clarity and consistency.

Apply this diff to components/ui/8bit/dropdown-menu.tsx:

-export interface BitDropownMenuContentProps
+export interface BitDropdownMenuContentProps
   extends React.ComponentProps<typeof DropdownMenuPrimitive.Content>,
     VariantProps<typeof dropDownVariants> {}
 
 function DropdownMenuContent({
   children,
   font,
   className,
   ...props
-}: BitDropownMenuContentProps) {
+}: BitDropdownMenuContentProps) {
   return (
     <ShadcnDropdownMenuContent
       className={cn("mt-1 py-2", font !== "normal" && "retro", className)}
       {...props}
     >
       {children}
@@
 function DropdownMenuSubContent({
   children,
   className,
   font,
   ...props
-}: BitDropownMenuContentProps) {
+}: BitDropdownMenuContentProps) {
   return (
     <ShadcnDropdownMenuSubContent
       {...props}
       className={cn("bg-popover", font !== "normal" && "retro", className)}
     >
       {children}
public/r/8bit-badge.json (1)

13-13: Nit: className splitting is brittle

className.split(" ") can produce empty tokens and fails on multiple spaces/newlines. Consider a more robust tokenization or use a whitelist approach for spacing vs visual classes.

Possible minimal hardening:

-  const classes = className.split(" ");
+  const classes = className.trim().split(/\s+/).filter(Boolean);
public/r/8bit-slider.json (2)

11-11: Avoid embedding CRLF sequences in registry “content”; prefer LF to prevent cross‑platform churn

The embedded file content now uses CRLF escape sequences (e.g., "\r\n"). When these registry items are consumed to generate files, this can cause noisy diffs and inconsistent line-endings across OSes/editors. Unless there’s a hard requirement for CRLF in the generated artifacts, keep the embedded content on LF.

  • Action: Normalize embedded content newlines to "\n".
  • Repo hygiene: Enforce LF via .gitattributes/.editorconfig to prevent future flips.

Example .gitattributes (repo root):

+*.ts     text eol=lf
+*.tsx    text eol=lf
+*.css    text eol=lf
+public/r/*.json text eol=lf

17-17: Same CRLF issue in retro.css content block

Line endings inside the embedded CSS are CRLF. Recommend normalizing to "\n" for consistency and to avoid noisy diffs when files are materialized from the registry.

public/r/8bit-button.json (2)

13-13: Normalize embedded TS content to LF line endings

The “content” payload contains "\r\n". Prefer "\n" to keep generated files consistent across environments.


19-19: Normalize embedded CSS content to LF

Same as above—avoid CRLF in embedded content strings to reduce cross‑platform churn.

public/r/8bit-navigation-menu.json (1)

19-19: Normalize embedded CSS content to LF

The content string uses CRLF. Prefer LF to keep downstream generated files consistent and avoid noisy diffs.

public/r/8bit-audio-settings.json (1)

15-15: CRLF line endings embedded across multiple content blocks; recommend LF

The following embedded files use "\r\n" newlines in their content strings:

  • Line 15: components/ui/8bit/blocks/audio-settings.tsx
  • Line 21: components/ui/8bit/styles/retro.css
  • Line 27: components/ui/8bit/switch.tsx
  • Line 33: components/ui/8bit/card.tsx
  • Line 39: components/ui/8bit/slider.tsx
  • Line 45: components/ui/8bit/label.tsx

Unless you intentionally want CRLF in the generated artifacts, standardize on "\n". This reduces churn when the registry emits files on different platforms and editors.

Repo hygiene suggestion (root .gitattributes):

+*.ts     text eol=lf
+*.tsx    text eol=lf
+*.css    text eol=lf
+public/r/*.json text eol=lf

Also applies to: 21-21, 27-27, 33-33, 39-39, 45-45

public/r/8bit-cheat-code.json (2)

14-14: CRLF embedded in multiple content strings; standardize to LF

The embedded contents for:

  • Line 14: components/ui/8bit/blocks/cheat-code.tsx
  • Line 21: components/ui/8bit/alert.tsx
  • Line 26: components/ui/8bit/card.tsx
  • Line 32: components/ui/8bit/styles/retro.css

all use "\r\n". Recommend normalizing to "\n" to avoid noisy diffs when these registry entries are used to generate files.

Also applies to: 21-21, 26-26, 32-32


14-14: Optional: consider 8‑bit styled arrows for consistency with the chevron refactor scope

Cheat code visuals still use lucide-react Arrow icons. This is fine (PR targets chevrons), but if visual consistency across all directional glyphs is desired, consider swapping to 8‑bit styled arrow assets in a follow-up, similar to the chevron standardization.

public/r/8bit-textarea.json (2)

13-13: Avoid duplicating className on wrapper and textarea; introduce wrapperClassName

Passing the same className prop to both the wrapper <div> and the inner <ShadcnTextarea> can cause unintended style leakage and specificity conflicts. Prefer a distinct prop for the wrapper.

Apply this diff to components/ui/8bit/textarea.tsx:

-import { type VariantProps, cva } from "class-variance-authority";
+import { type VariantProps, cva } from "class-variance-authority";

 import { cn } from "@/lib/utils";

 import { Textarea as ShadcnTextarea } from "@/components/ui/textarea";

 import "./styles/retro.css";

 export const inputVariants = cva("", {
   variants: {
     font: {
       normal: "",
       retro: "retro",
     },
   },
   defaultVariants: {
     font: "retro",
   },
 });

 export interface BitTextareaProps
   extends React.TextareaHTMLAttributes<HTMLTextAreaElement>,
     VariantProps<typeof inputVariants> {
   asChild?: boolean;
+  wrapperClassName?: string;
 }

-function Textarea({ ...props }: BitTextareaProps) {
-  const { className, font } = props;
+function Textarea({ wrapperClassName, ...props }: BitTextareaProps) {
+  const { className, font } = props;

   return (
-    <div className={cn("relative w-full", className)}>
+    <div className={cn("relative w-full", wrapperClassName)}>
       <ShadcnTextarea
         {...props}
         className={cn(
-          "rounded-none transition-transform ring-0 border-0",
-          font !== "normal" && "retro",
-          className
+          "rounded-none transition-transform ring-0 border-0",
+          font !== "normal" && "retro",
+          className
         )}
       />

       <div
         className="absolute inset-0 border-y-6 -my-1.5 border-foreground dark:border-ring pointer-events-none"
         aria-hidden="true"
       />

       <div
         className="absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none"
         aria-hidden="true"
       />
     </div>
   );
 }

 export { Textarea };

13-13: Optional: Use inputVariants instead of manual font checks

You already define inputVariants; using it will centralize styling logic and reduce drift.

Apply this localized change in components/ui/8bit/textarea.tsx:

-        className={cn(
-          "rounded-none transition-transform ring-0 border-0",
-          font !== "normal" && "retro",
-          className
-        )}
+        className={cn(
+          "rounded-none transition-transform ring-0 border-0",
+          inputVariants({ font }),
+          className
+        )}
public/r/8bit-resizable.json (1)

11-11: Add aria-label to the resize handle for accessibility

The handle is focusable and visually indicated; adding an aria-label improves screen reader discoverability.

Apply this diff to components/ui/8bit/resizable.tsx:

   <ResizablePrimitive.PanelResizeHandle
     className={cn(
       `relative flex w-[1px] items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-[6px] 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-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90 focus:dark:outline-ring`,
       "bg-foreground dark:bg-ring",
       className
     )}
+    aria-label="Resize panel"
     {...props}
   >
public/r/8bit-input-otp.json (1)

13-13: Avoid duplicating className on wrapper and input; add wrapperClassName and reuse variants

className is applied to both wrapper <div> and <ShadcnInputOTP>. Separate the concerns to prevent style conflicts. Also, reuse inputVariants for consistency.

Apply this diff to components/ui/8bit/input-otp.tsx:

-import { type VariantProps, cva } from "class-variance-authority";
+import { type VariantProps, cva } from "class-variance-authority";

 import { cn } from "@/lib/utils";

 import {
   InputOTP as ShadcnInputOTP,
   InputOTPGroup as ShadcnInputOTPGroup,
   InputOTPSeparator as ShadcnInputOTPSeparator,
   InputOTPSlot as ShadcnInputOTPSlot,
 } from "@/components/ui/input-otp";

 import "./styles/retro.css";

 export const inputVariants = cva("", {
   variants: {
     font: {
       normal: "",
       retro: "retro",
     },
   },
   defaultVariants: {
     font: "retro",
   },
 });

 interface SharedProps
   extends React.ComponentProps<"div">,
     VariantProps<typeof inputVariants> {
   className?: string;
   children?: React.ReactNode;
 }

-interface InputOTPProps {
+interface InputOTPProps extends VariantProps<typeof inputVariants> {
   maxLength: number;
   value?: string;
   onChange?: (value: string) => unknown;
   children?: React.ReactNode;
   className?: string;
-  font?: "normal" | "retro";
+  wrapperClassName?: string;
 }

-export const InputOTP = ({
-  className,
-  font,
-  maxLength,
-  value,
-  onChange,
-  children,
-  ...otherProps
-}: InputOTPProps) => {
+export const InputOTP = ({
+  className,
+  font,
+  wrapperClassName,
+  maxLength,
+  value,
+  onChange,
+  children,
+  ...otherProps
+}: InputOTPProps) => {
   return (
-    <div className={cn("relative w-fit", className)}>
+    <div className={cn("relative w-fit", wrapperClassName)}>
       <ShadcnInputOTP
         maxLength={maxLength}
         value={value}
         onChange={onChange}
         {...otherProps}
-        className={cn(font !== "normal" && "retro", className)}
+        className={cn(inputVariants({ font }), className)}
       >
         {children}
       </ShadcnInputOTP>
     </div>
   );
 };
public/r/8bit-toggle-group.json (2)

13-13: Remove stray whitespace text nodes ({" "}) around children

These produce unnecessary text nodes and can complicate layout. Safe to remove.

Apply this diff to components/ui/8bit/toggle-group.tsx:

 function ToggleGroup({ ...props }: BitToggleGroupProps) {
   const { className, font, children } = props;

   return (
     <ShadcnToggleGroup
       className={cn("gap-3", className, font !== "normal" && "retro")}
       {...props}
     >
-      {" "}
-      {children}{" "}
+      {children}
     </ShadcnToggleGroup>
   );
 }
 function ToggleGroupItem({ ...props }: BitToggleGroupItemProps) {
   const { className, font, children, variant } = props;
   return (
     <ShadcnToggleGroupItem
       className={cn(
         "relative transition-transform active:translate-x-1 active:translate-y-1",
         className,
         font !== "normal" && "retro"
       )}
       {...props}
     >
-      {" "}
-      {children}{" "}
+      {children}
       {variant === "outline" && (
         <>
-          {" "}
           <div
             className="absolute inset-0 -my-1.5 border-y-6 border-foreground dark:border-ring pointer-events-none"
             aria-hidden="true"
-          />{" "}
+          />
           <div
             className="absolute inset-0 -mx-1.5 border-x-6 border-foreground dark:border-ring pointer-events-none"
             aria-hidden="true"
-          />{" "}
+          />
         </>
       )}
     </ShadcnToggleGroupItem>
   );
 }

13-13: Either use the declared toggleGroupVariants or remove it to avoid confusion

toggleGroupVariants defines size and variant styles but isn’t applied in either ToggleGroup or ToggleGroupItem. This is dead/ambiguous config; consider splitting into groupVariants and itemVariants, or wire it properly.

Option A (preferable): Split CVAs and apply them where they belong (item: size/variant; group: font).

Option B: If keeping a single CVA, at least use it on ToggleGroupItem:

-    <ShadcnToggleGroupItem
-      className={cn(
-        "relative transition-transform active:translate-x-1 active:translate-y-1",
-        className,
-        font !== "normal" && "retro"
-      )}
+    <ShadcnToggleGroupItem
+      className={cn(
+        "relative transition-transform active:translate-x-1 active:translate-y-1",
+        toggleGroupVariants({ font, variant }),
+        className
+      )}

Note: If size should apply to items too, include it in the call and ensure defaults are correct.

public/r/8bit-combo-box.json (1)

15-15: Deduplicate the repeated pixel-border markup (DRY).

The same border/shadow fragments are duplicated in both the asChild and non-asChild branches. Extract a tiny internal component (e.g., BorderChrome) or a function returning that JSX to improve maintainability and reduce diff noise on future changes.

public/r/8bit-chart-area-step.json (1)

11-11: Nit: Consider replacing lucide icon Activity with an 8‑bit-styled asset for consistency.

While out of scope for the chevron refactor, swapping Activity for a local 8‑bit icon would better align with the visual direction.

public/r/8bit-mana-bar.json (1)

17-17: Micro-optimization: compute filledSquares once per render, not per iteration

In Progress, filledSquares is recalculated inside the map callback 20 times. It’s cheap, but easy to move out for clarity and minor perf.

Apply this diff inside components/ui/8bit/progress.tsx:

-          {variant === "retro" && (
-            <div className="flex w-full">
-              {Array.from({ length: 20 }).map((_, i) => {
-                const filledSquares = Math.round(((value || 0) / 100) * 20);
-                return (
-                  <div
-                    key={i}
-                    className={cn(
-                      "size-2 mx-[1px] w-full",
-                      i < filledSquares ? progressBg : "bg-transparent"
-                    )}
-                  />
-                );
-              })}
-            </div>
-          )}
+          {variant === "retro" && (
+            <div className="flex w-full">
+              {(() => {
+                const filledSquares = Math.round(((value || 0) / 100) * 20);
+                return Array.from({ length: 20 }).map((_, i) => (
+                  <div
+                    key={i}
+                    className={cn(
+                      "size-2 mx-[1px] w-full",
+                      i < filledSquares ? progressBg : "bg-transparent"
+                    )}
+                  />
+                ));
+              })()}
+            </div>
+          )}
public/r/8bit-popover.json (1)

13-13: Consistent naming: prefer popoverVariants over popOverVariants

Minor nit: keep naming consistent with other components (progressVariants, tabsVariants). Rename popOverVariants to popoverVariants and update usages.

Apply this diff inside components/ui/8bit/popover.tsx:

-export const popOverVariants = cva("", {
+export const popoverVariants = cva("", {
   variants: {
     font: {
       normal: "",
       retro: "retro",
     },
   },
   defaultVariants: {
     font: "retro",
   },
 });
 
 export interface BitPopoverProps
-  extends React.ComponentProps<typeof PopoverPrimitive.Content>,
-    VariantProps<typeof popOverVariants> {}
+  extends React.ComponentProps<typeof PopoverPrimitive.Content>,
+    VariantProps<typeof popoverVariants> {}
 
 function PopoverContent({
   children,
-  font,
+  font,
   className,
   ...props
 }: BitPopoverProps) {
public/r/8bit-game-progress.json (1)

29-29: Apply the same filledSquares micro-optimization as in ManaBar registry

See comment in 8bit-mana-bar.json; identical Progress body here benefits from computing filledSquares once.

Apply the same diff in components/ui/8bit/progress.tsx within this registry entry.

public/r/8bit-carousel.json (4)

13-13: Remove leftover console.debug logs in handlers

The console.log("scrolled prev/next") calls are noisy in production.

Apply this diff inside components/ui/8bit/carousel.tsx:

-    const scrollPrev = React.useCallback(() => {
-      console.log("scrolled prev");
-      api?.scrollPrev();
-    }, [api]);
+    const scrollPrev = React.useCallback(() => {
+      api?.scrollPrev();
+    }, [api]);
 
-    const scrollNext = React.useCallback(() => {
-      console.log("scrolled next");
-      api?.scrollNext();
-    }, [api]);
+    const scrollNext = React.useCallback(() => {
+      api?.scrollNext();
+    }, [api]);

13-13: Simplify orientation value provided via context

Given the default parameter orientation = "horizontal", the fallback using opts?.axis is effectively unreachable. Provide the prop’s resolved value directly.

Apply this diff inside components/ui/8bit/carousel.tsx:

       <CarouselContext.Provider
         value={{
           carouselRef,
           api: api,
           opts,
-          orientation:
-            orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
+          orientation,
           scrollPrev,
           scrollNext,
           canScrollPrev,
           canScrollNext,
         }}
       >

13-13: Accessibility: hide decorative SVGs and avoid redundant aria-labels

If you keep SVGs (before switching to assets), set aria-hidden="true" on SVG and rely on the <span className="sr-only">…</span> for accessible labels. Avoid aria-label on SVGs which can cause duplicate announcements.

Apply this diff inside components/ui/8bit/carousel.tsx:

-      <svg
+      <svg
         width="50"
         height="50"
         viewBox="0 0 256 256"
         fill="currentColor"
-        xmlns="http://www.w3.org/2000/svg"
+        xmlns="http://www.w3.org/2000/svg"
         stroke="currentColor"
         strokeWidth="0.25"
         color="currentColor"
-        aria-label="arrow-left"
+        aria-hidden="true"
       >
@@
-      <svg
+      <svg
         width="50"
         height="50"
         viewBox="0 0 256 256"
         fill="currentColor"
         className="block"
-        xmlns="http://www.w3.org/2000/svg"
+        xmlns="http://www.w3.org/2000/svg"
         stroke="currentColor"
         strokeWidth="0.25"
         color="currentColor"
-        aria-label="arrow-right"
+        aria-hidden="true"
       >

13-13: Remove duplicated aspect-square class

aspect-square is declared both in the orientation-specific class and the base class string. Keep it once in the base for consistency.

Apply this diff inside components/ui/8bit/carousel.tsx:

-      className={cn(
-        orientation === "horizontal"
-          ? "top-1/2 -left-10 md:-left-14 -translate-y-1/2 active:-translate-y-1 w-8 h-9 md:w-9 md:h-10 "
-          : "-top-12 left-1/2 -translate-x-1/2 rotate-90 w-8 h-10 md:w-9 md:h-11",
-        "absolute rounded-none aspect-square grid place-items-center",
-        className
-      )}
+      className={cn(
+        orientation === "horizontal"
+          ? "top-1/2 -left-10 md:-left-14 -translate-y-1/2 active:-translate-y-1 w-8 h-9 md:w-9 md:h-10"
+          : "-top-12 left-1/2 -translate-x-1/2 rotate-90 w-8 h-10 md:w-9 md:h-11",
+        "absolute rounded-none aspect-square grid place-items-center",
+        className
+      )}
@@
-      className={cn(
-        orientation === "horizontal"
-          ? "top-1/2 -right-10 md:-right-14 -translate-y-1/2 active:-translate-y-1 aspect-square shrink-0 w-8 h-9 md:w-9 md:h-10 "
-          : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90 w-8 h-10 md:w-9 md:h-11",
-        "absolute rounded-none aspect-square grid place-items-center",
-        className
-      )}
+      className={cn(
+        orientation === "horizontal"
+          ? "top-1/2 -right-10 md:-right-14 -translate-y-1/2 active:-translate-y-1 shrink-0 w-8 h-9 md:w-9 md:h-10"
+          : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90 w-8 h-10 md:w-9 md:h-11",
+        "absolute rounded-none aspect-square grid place-items-center",
+        className
+      )}
components/ui/8bit/assets/chevronLeftIcon.tsx (1)

12-13: Ensure consistency with ChevronRightIcon default classes

The right chevron reportedly uses className "raster-icon size-7" while the left uses only "size-7". Standardize both to the same default classes to avoid subtle layout/antialiasing differences.

If you keep "raster-icon" on the right icon, mirror it here (included in the diff above). Otherwise, remove it from the right icon for parity. Do you want me to prepare a follow-up patch for ChevronRightIcon as well?

components/ui/8bit/menubar.tsx (1)

343-343: Typo in displayName (non-blocking).

MenubarShortcut.displayname should be displayName to show correctly in DevTools.

-MenubarShortcut.displayname = "MenubarShortcut";
+MenubarShortcut.displayName = "MenubarShortcut";
components/ui/pagination.tsx (2)

79-81: Consider sizing/semantics on the left chevron (optional).

The asset uses a relatively large default size. For tighter pagination buttons, a smaller icon often reads better, and decorative icons should be hidden from a11y trees.

After making the icon accept props, consider:

-      <ChevronLeftIcon />
+      <ChevronLeftIcon className="size-4" aria-hidden="true" />

96-98: Consider sizing/semantics on the right chevron (optional).

Same rationale as for the left chevron: use smaller size and mark as decorative.

-      <ChevronRightIcon />
+      <ChevronRightIcon className="size-4" aria-hidden="true" />
components/ui/8bit/breadcrumb.tsx (1)

137-142: Separator renders the new chevron correctly; consider avoiding double sizing and noisy aria-labels

  • The parent adds "[&>svg]:size-7" while the asset’s SVG already has "size-7". This redundancy is harmless but noisy. Prefer one source of truth for sizing to avoid future specificity issues.
  • The asset includes aria-label="chevron-right". The ShadcnBreadcrumbSeparator wrapper from components/ui/breadcrumb sets aria-hidden on the container, so it’s fine here, but in other contexts the label could be read unnecessarily.

Two follow-ups:

  • Optional nit: remove one of the size declarations (either keep the parent utility or make the asset size-agnostic).
  • Consider updating the asset to accept className/props and omit the fixed size. Example:
// components/ui/8bit/assets/chevronRightIcon.tsx (suggested signature)
export const ChevronRightIcon = (props: React.SVGProps<SVGSVGElement>) => {
  const { className, ...rest } = props
  return (
    <svg
      viewBox="0 0 256 256"
      fill="currentColor"
      stroke="currentColor"
      strokeWidth="0.25"
      className={cn("raster-icon", className)}
      aria-hidden="true"
      {...rest}
    >
      {/* rects... */}
    </svg>
  )
}
public/r/8bit-menubar.json (1)

11-11: Typo: displayName property is misspelled.

MenubarShortcut.displayname = "MenubarShortcut"; should be displayName (capital N). The current typo prevents DevTools/component names from being set correctly.

-MenubarShortcut.displayname = "MenubarShortcut";
+MenubarShortcut.displayName = "MenubarShortcut";
public/r/8bit-login-form-with-image.json (1)

16-16: Nit: unnecessary template literal for a constant class.

className={\${"retro"} ...`}` can be simplified to a literal string.

-      <p
-        className={`${"retro"} text-balance text-center text-xs text-muted-foreground [&_a]:underline [&_a]:underline-offset-4 hover:[&_a]:text-primary`}
-      >
+      <p className="retro text-balance text-center text-xs text-muted-foreground [&_a]:underline [&_a]:underline-offset-4 hover:[&_a]:text-primary">
public/r/8bit-breadcrumb.json (1)

13-13: Make icon assets unopinionated and props-friendly

BreadcrumbSeparator enforces size via "[&>svg]:size-7", but the asset also hard-codes "size-7". Prefer unopinionated assets that accept className and spread props so callers can size/style them consistently.

Proposed asset shape (components/ui/8bit/assets/chevronRightIcon.tsx):

import { cn } from "@/lib/utils";

export const ChevronRightIcon: React.FC<React.SVGProps<SVGSVGElement>> = ({
  className,
  ...props
}) => {
  return (
    <svg
      width="50"
      height="50"
      viewBox="0 0 256 256"
      fill="currentColor"
      xmlns="http://www.w3.org/2000/svg"
      stroke="currentColor"
      strokeWidth="0.25"
      className={cn("raster-icon", className)}
      aria-hidden="true"
      focusable="false"
      {...props}
    >
      {/* rects */}
    </svg>
  );
};
public/r/8bit-pagination.json (2)

13-13: Remove duplicate classes in PaginationNext

"flex flex-row w/full text-sm" is duplicated, adding noise.

-        "relative group",
-        "flex flex-row w-full text-sm",
+        "relative group",
+        "flex flex-row w-full text-sm",
         "bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent",
         "rounded-none border-dashed border-y-4 border-transparent",
         "hover:border-foreground focus:border-foreground active:border-transparent",
         "dark:hover:border-ring dark:focus:border-ring",
         "data-[active=true]:border-none aria-[current=page]:border-none",
-        "flex flex-row text-sm w-full",
         font !== "normal" && "retro",
         className

13-13: Minor: prefer consistent import style for Button

Elsewhere you use "@/components/ui/button". Consider replacing import { Button } from "../button" with the alias for consistency.

Comment on lines +1 to +59
export const ChevronLeftIcon = () => {
return (
<svg
width="50"
height="50"
viewBox="0 0 256 256"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
strokeWidth="0.25"
color=""
className="size-7"
aria-label="chevron-left"
>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 128 136)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 144 152)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 160 72)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 160 168)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 112 120)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 128 104)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 144 88)"
></rect>
</svg>
);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Make the icon truly reusable: accept SVG props, fix a11y defaults, and remove invalid attribute

Forwarding standard SVG props (className, aria-label, etc.) and merging classes makes this asset versatile. Also remove the empty color="" attribute and default to decorative a11y unless a label is provided.

Apply this diff:

+import type { SVGProps } from "react";
-
-export const ChevronLeftIcon = () => {
+export function ChevronLeftIcon({
+  className,
+  "aria-label": ariaLabel,
+  ...props
+}: SVGProps<SVGSVGElement>) {
   return (
     <svg
-      width="50"
-      height="50"
       viewBox="0 0 256 256"
       fill="currentColor"
       xmlns="http://www.w3.org/2000/svg"
       stroke="currentColor"
       strokeWidth="0.25"
-      color=""
-      className="size-7"
-      aria-label="chevron-left"
+      shapeRendering="crispEdges"
+      aria-hidden={ariaLabel ? undefined : true}
+      aria-label={ariaLabel}
+      className={["raster-icon size-7", className].filter(Boolean).join(" ")}
+      {...props}
     >
       <rect
         width="14"
         height="14"
         rx="1"
         transform="matrix(-1 0 0 1 128 136)"
       ></rect>
       <rect
         width="14"
         height="14"
         rx="1"
         transform="matrix(-1 0 0 1 144 152)"
       ></rect>
       <rect
         width="14"
         height="14"
         rx="1"
         transform="matrix(-1 0 0 1 160 72)"
       ></rect>
       <rect
         width="14"
         height="14"
         rx="1"
         transform="matrix(-1 0 0 1 160 168)"
       ></rect>
       <rect
         width="14"
         height="14"
         rx="1"
         transform="matrix(-1 0 0 1 112 120)"
       ></rect>
       <rect
         width="14"
         height="14"
         rx="1"
         transform="matrix(-1 0 0 1 128 104)"
       ></rect>
       <rect
         width="14"
         height="14"
         rx="1"
         transform="matrix(-1 0 0 1 144 88)"
       ></rect>
     </svg>
   );
-};
+}

Notes:

  • Allowing users to pass className means they can override the default Tailwind size; default listed first so user-specified classes win on conflicts.
  • aria-hidden defaults to true unless an aria-label is provided, which is the typical pattern for decorative icons.
  • shapeRendering="crispEdges" helps preserve the blocky 8‑bit look for the rects.
📝 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.

Suggested change
export const ChevronLeftIcon = () => {
return (
<svg
width="50"
height="50"
viewBox="0 0 256 256"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
strokeWidth="0.25"
color=""
className="size-7"
aria-label="chevron-left"
>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 128 136)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 144 152)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 160 72)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 160 168)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 112 120)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 128 104)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 144 88)"
></rect>
</svg>
);
};
import type { SVGProps } from "react";
export function ChevronLeftIcon({
className,
"aria-label": ariaLabel,
...props
}: SVGProps<SVGSVGElement>) {
return (
<svg
viewBox="0 0 256 256"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
strokeWidth="0.25"
shapeRendering="crispEdges"
aria-hidden={ariaLabel ? undefined : true}
aria-label={ariaLabel}
className={["raster-icon size-7", className].filter(Boolean).join(" ")}
{...props}
>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 128 136)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 144 152)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 160 72)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 160 168)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 112 120)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 128 104)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 144 88)"
></rect>
</svg>
);
}
🤖 Prompt for AI Agents
In components/ui/8bit/assets/chevronLeftIcon.tsx around lines 1 to 59, the
component should accept and forward standard SVG props, remove the invalid empty
color attribute, and default accessibility to decorative unless an aria-label is
provided; update the SVG to accept props (e.g. function signature
ChevronLeftIcon(props: React.SVGProps<SVGSVGElement>)), spread props onto the
<svg> (placing the default className "size-7" first so user className in props
can override), remove color="", set aria-hidden to true when no aria-label is
present (and do not override if aria-label exists), and add
shapeRendering="crispEdges" to the rect elements to preserve the 8‑bit look.

>
{children}
<ChevronRight className="ml-auto size-4" />
<ChevronRightIcon />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Restore right-align spacing for submenu chevron.

The lucide chevron previously had ml-auto to push it to the end of the row. The new <ChevronRightIcon /> lacks that, causing alignment regressions.

Minimal fix in-place:

-    <ChevronRightIcon />
+    <span className="ml-auto">
+      <ChevronRightIcon />
+    </span>

Optional (after enabling props on the asset icon): also match previous size and a11y semantics.

-    <ChevronRightIcon />
+    <ChevronRightIcon className="ml-auto size-4" aria-hidden="true" />
📝 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.

Suggested change
<ChevronRightIcon />
<span className="ml-auto">
<ChevronRightIcon />
</span>
🤖 Prompt for AI Agents
In components/ui/8bit/context-menu.tsx around line 42, the submenu chevron lost
its right-alignment because the new <ChevronRightIcon /> is missing the previous
ml-auto spacing; restore the right alignment by adding the same right-margin
utility (e.g. ml-auto) to the ChevronRightIcon element, and optionally restore
prior sizing and accessibility semantics by passing the previous size props and
an appropriate aria-hidden or aria-label as needed.

<rect x="128" y="104" width="14" height="14" rx="1"></rect>
<rect x="112" y="88" width="14" height="14" rx="1"></rect>
</svg>
<ChevronRightIcon />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Restore right-align spacing for submenu chevron.

Previous implementation aligned the chevron to the far right (typically via ml-auto). The new <ChevronRightIcon /> lacks that spacing, so the icon will sit next to the text.

Minimal fix in-place:

-    <ChevronRightIcon />
+    <span className="ml-auto">
+      <ChevronRightIcon />
+    </span>

Optional (after making the icon accept props): shrink and right-align the icon for consistency with previous lucide size:

-    <ChevronRightIcon />
+    <ChevronRightIcon className="ml-auto size-4" aria-hidden="true" />
📝 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.

Suggested change
<ChevronRightIcon />
<span className="ml-auto">
<ChevronRightIcon />
</span>
🤖 Prompt for AI Agents
In components/ui/8bit/menubar.tsx around line 115 the submenu chevron
<ChevronRightIcon /> lost its right-align spacing and now sits next to the menu
text; restore the previous right alignment by giving the icon an auto-left
margin (e.g., add className="ml-auto" to the icon or wrap it in a span/div with
className="ml-auto") so it’s pushed to the far right, and optionally update the
icon usage to pass a smaller size prop (matching the previous lucide size) once
the icon accepts props.

{
"path": "components/ui/8bit/accordion.tsx",
"content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport {\n Accordion as ShadcnAccordion,\n AccordionContent as ShadcnAccordionContent,\n AccordionItem as ShadcnAccordionItem,\n AccordionTrigger as ShadcnAccordionTrigger,\n} from \"@/components/ui/accordion\";\n\nimport \"./styles/retro.css\";\n\nexport interface BitAccordionItemProps\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> {\n asChild?: boolean;\n}\n\nfunction AccordionItem({\n className,\n children,\n ...props\n}: BitAccordionItemProps) {\n return (\n <ShadcnAccordionItem\n className={cn(\n \"border-dashed border-b-4 border-foreground dark:border-ring relative\",\n className\n )}\n {...props}\n >\n {children}\n </ShadcnAccordionItem>\n );\n}\n\nexport interface BitAccordionTriggerProps\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger> {\n font?: \"normal\" | \"retro\";\n}\n\nfunction AccordionTrigger({\n className,\n children,\n font,\n ...props\n}: BitAccordionTriggerProps) {\n return (\n <ShadcnAccordionTrigger\n className={cn(font !== \"normal\" && \"retro\", className)}\n {...props}\n >\n {children}\n </ShadcnAccordionTrigger>\n );\n}\n\nexport interface BitAccordionContentProps\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content> {\n font?: \"normal\" | \"retro\";\n}\n\nfunction AccordionContent({\n className,\n children,\n font,\n ...props\n}: BitAccordionContentProps) {\n return (\n <div className=\"relative\">\n <ShadcnAccordionContent\n className={cn(\n \"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\",\n font !== \"normal\" && \"retro\",\n className\n )}\n {...props}\n >\n <div className=\"pb-4 pt-0 relative z-10 p-1\">{children}</div>\n </ShadcnAccordionContent>\n\n <AccordionPrimitive.Content asChild forceMount />\n </div>\n );\n}\n\nconst Accordion = ShadcnAccordion;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
"content": "\"use client\";\r\n\r\nimport * as React from \"react\";\r\n\r\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n Accordion as ShadcnAccordion,\r\n AccordionContent as ShadcnAccordionContent,\r\n AccordionItem as ShadcnAccordionItem,\r\n AccordionTrigger as ShadcnAccordionTrigger,\r\n} from \"@/components/ui/accordion\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport interface BitAccordionItemProps\r\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> {\r\n asChild?: boolean;\r\n}\r\n\r\nfunction AccordionItem({\r\n className,\r\n children,\r\n ...props\r\n}: BitAccordionItemProps) {\r\n return (\r\n <ShadcnAccordionItem\r\n className={cn(\r\n \"border-dashed border-b-4 border-foreground dark:border-ring relative\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n </ShadcnAccordionItem>\r\n );\r\n}\r\n\r\nexport interface BitAccordionTriggerProps\r\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger> {\r\n font?: \"normal\" | \"retro\";\r\n}\r\n\r\nfunction AccordionTrigger({\r\n className,\r\n children,\r\n font,\r\n ...props\r\n}: BitAccordionTriggerProps) {\r\n return (\r\n <ShadcnAccordionTrigger\r\n className={cn(font !== \"normal\" && \"retro\", className)}\r\n {...props}\r\n >\r\n {children}\r\n </ShadcnAccordionTrigger>\r\n );\r\n}\r\n\r\nexport interface BitAccordionContentProps\r\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content> {\r\n font?: \"normal\" | \"retro\";\r\n}\r\n\r\nfunction AccordionContent({\r\n className,\r\n children,\r\n font,\r\n ...props\r\n}: BitAccordionContentProps) {\r\n return (\r\n <div className=\"relative\">\r\n <ShadcnAccordionContent\r\n className={cn(\r\n \"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\",\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <div className=\"pb-4 pt-0 relative z-10 p-1\">{children}</div>\r\n </ShadcnAccordionContent>\r\n\r\n <AccordionPrimitive.Content asChild forceMount />\r\n </div>\r\n );\r\n}\r\n\r\nconst Accordion = ShadcnAccordion;\r\n\r\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\r\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove stray <AccordionPrimitive.Content asChild forceMount />

Rendering AccordionPrimitive.Content with asChild and no children is a no-op at best and potentially problematic. It creates an empty content node unrelated to the Shadcn content above and can cause unexpected behavior.

Apply this diff to components/ui/8bit/accordion.tsx:

       </ShadcnAccordionContent>
-
-      <AccordionPrimitive.Content asChild forceMount />
     </div>
   );
 }
📝 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.

Suggested change
"content": "\"use client\";\r\n\r\nimport * as React from \"react\";\r\n\r\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n Accordion as ShadcnAccordion,\r\n AccordionContent as ShadcnAccordionContent,\r\n AccordionItem as ShadcnAccordionItem,\r\n AccordionTrigger as ShadcnAccordionTrigger,\r\n} from \"@/components/ui/accordion\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport interface BitAccordionItemProps\r\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> {\r\n asChild?: boolean;\r\n}\r\n\r\nfunction AccordionItem({\r\n className,\r\n children,\r\n ...props\r\n}: BitAccordionItemProps) {\r\n return (\r\n <ShadcnAccordionItem\r\n className={cn(\r\n \"border-dashed border-b-4 border-foreground dark:border-ring relative\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n </ShadcnAccordionItem>\r\n );\r\n}\r\n\r\nexport interface BitAccordionTriggerProps\r\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger> {\r\n font?: \"normal\" | \"retro\";\r\n}\r\n\r\nfunction AccordionTrigger({\r\n className,\r\n children,\r\n font,\r\n ...props\r\n}: BitAccordionTriggerProps) {\r\n return (\r\n <ShadcnAccordionTrigger\r\n className={cn(font !== \"normal\" && \"retro\", className)}\r\n {...props}\r\n >\r\n {children}\r\n </ShadcnAccordionTrigger>\r\n );\r\n}\r\n\r\nexport interface BitAccordionContentProps\r\n extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content> {\r\n font?: \"normal\" | \"retro\";\r\n}\r\n\r\nfunction AccordionContent({\r\n className,\r\n children,\r\n font,\r\n ...props\r\n}: BitAccordionContentProps) {\r\n return (\r\n <div className=\"relative\">\r\n <ShadcnAccordionContent\r\n className={cn(\r\n \"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\",\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <div className=\"pb-4 pt-0 relative z-10 p-1\">{children}</div>\r\n </ShadcnAccordionContent>\r\n\r\n <AccordionPrimitive.Content asChild forceMount />\r\n </div>\r\n );\r\n}\r\n\r\nconst Accordion = ShadcnAccordion;\r\n\r\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\r\n",
export interface BitAccordionContentProps
extends React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content> {
font?: "normal" | "retro";
}
function AccordionContent({
className,
children,
font,
...props
}: BitAccordionContentProps) {
return (
<div className="relative">
<ShadcnAccordionContent
className={cn(
"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
font !== "normal" && "retro",
className
)}
{...props}
>
<div className="pb-4 pt-0 relative z-10 p-1">{children}</div>
</ShadcnAccordionContent>
</div>
);
}
🤖 Prompt for AI Agents
In public/r/8bit-accordion.json around line 13 (source component located at
components/ui/8bit/accordion.tsx), there is a stray self-closing
<AccordionPrimitive.Content asChild forceMount /> rendered after the
ShadcnAccordionContent; remove that empty AccordionPrimitive.Content node so the
component only renders the ShadcnAccordionContent wrapper (delete the lone line)
and adjust imports if AccordionPrimitive.Content becomes unused.

{
"path": "components/ui/8bit/alert-dialog.tsx",
"content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport {\n AlertDialog as ShadcnAlertDialog,\n AlertDialogAction as ShadcnAlertDialogAction,\n AlertDialogCancel as ShadcnAlertDialogCancel,\n AlertDialogContent as ShadcnAlertDialogContent,\n AlertDialogDescription as ShadcnAlertDialogDescription,\n AlertDialogFooter as ShadcnAlertDialogFooter,\n AlertDialogHeader as ShadcnAlertDialogHeader,\n AlertDialogOverlay as ShadcnAlertDialogOverlay,\n AlertDialogPortal as ShadcnAlertDialogPortal,\n AlertDialogTitle as ShadcnAlertDialogTitle,\n AlertDialogTrigger as ShadcnAlertDialogTrigger,\n} from \"@/components/ui/alert-dialog\";\n\nimport \"./styles/retro.css\";\n\nexport const alertDialogVariants = cva(\"\", {\n variants: {\n font: {\n normal: \"\",\n retro: \"retro\",\n },\n },\n defaultVariants: {\n font: \"retro\",\n },\n});\n\nexport interface BitAlertDialogProps\n extends React.ComponentProps<typeof AlertDialogPrimitive.Root>,\n VariantProps<typeof alertDialogVariants> {}\n\nfunction AlertDialog({ ...props }: BitAlertDialogProps) {\n return <ShadcnAlertDialog {...props} />;\n}\n\nfunction AlertDialogTrigger({\n className,\n asChild = true,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {\n return (\n <ShadcnAlertDialogTrigger\n className={cn(className)}\n asChild={asChild}\n {...props}\n />\n );\n}\n\nfunction AlertDialogPortal({\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {\n return <ShadcnAlertDialogPortal {...props} />;\n}\n\nfunction AlertDialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {\n return <ShadcnAlertDialogOverlay className={cn(className)} {...props} />;\n}\n\ninterface BitAlertDialogContentProps\n extends React.ComponentProps<typeof AlertDialogPrimitive.Content>,\n VariantProps<typeof alertDialogVariants> {}\n\nfunction AlertDialogContent({\n className,\n children,\n font,\n ...props\n}: BitAlertDialogContentProps) {\n return (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <>\n <ShadcnAlertDialogContent\n className={cn(\n \"rounded-none border-y-6 border-foreground dark:border-ring\",\n font !== \"normal\" && \"retro\",\n className\n )}\n {...props}\n >\n {children}\n\n <div\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n </ShadcnAlertDialogContent>\n </>\n </AlertDialogPortal>\n );\n}\n\nfunction AlertDialogHeader({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return <ShadcnAlertDialogHeader className={cn(className)} {...props} />;\n}\n\nfunction AlertDialogFooter({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <ShadcnAlertDialogFooter\n className={cn(\"flex flex-col-reverse sm:flex-row gap-4\", className)}\n {...props}\n />\n );\n}\n\nfunction AlertDialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {\n return <ShadcnAlertDialogTitle className={cn(className)} {...props} />;\n}\n\nfunction AlertDialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {\n return <ShadcnAlertDialogDescription className={cn(className)} {...props} />;\n}\n\nfunction AlertDialogAction({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {\n return (\n <ShadcnAlertDialogAction\n className={cn(\n \"rounded-none active:translate-y-1 transition-transform relative bg-primary\",\n \"ring-0 border-none\",\n className\n )}\n {...props}\n >\n {props.children}\n {/* Pixelated border */}\n <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute top-0 left-0 size-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute top-0 right-0 size-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute top-1.5 -left-1.5 h-2/3 w-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute top-1.5 -right-1.5 h-2/3 w-1.5 bg-foreground dark:bg-ring\" />\n {/* Top shadow */}\n <div className=\"absolute top-0 left-0 w-full h-1.5 bg-foreground/20\" />\n <div className=\"absolute top-1.5 left-0 w-3 h-1.5 bg-foreground/20\" />\n {/* Bottom shadow */}\n <div className=\"absolute bottom-0 left-0 w-full h-1.5 bg-foreground/20\" />\n <div className=\"absolute bottom-1.5 right-0 w-3 h-1.5 bg-foreground/20\" />\n </ShadcnAlertDialogAction>\n );\n}\n\nfunction AlertDialogCancel({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {\n return (\n <ShadcnAlertDialogCancel\n className={cn(\n \"rounded-none active:translate-y-1 transition-transform relative bg-background\",\n \"ring-0 border-none\",\n className\n )}\n {...props}\n >\n {props.children}\n <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute top-0 left-0 size-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute top-0 right-0 size-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute top-1.5 -left-1.5 h-2/3 w-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute top-1.5 -right-1.5 h-2/3 w-1.5 bg-foreground dark:bg-ring\" />\n </ShadcnAlertDialogCancel>\n );\n}\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
"content": "\"use client\";\r\n\r\nimport * as React from \"react\";\r\n\r\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\r\nimport { type VariantProps, cva } from \"class-variance-authority\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n AlertDialog as ShadcnAlertDialog,\r\n AlertDialogAction as ShadcnAlertDialogAction,\r\n AlertDialogCancel as ShadcnAlertDialogCancel,\r\n AlertDialogContent as ShadcnAlertDialogContent,\r\n AlertDialogDescription as ShadcnAlertDialogDescription,\r\n AlertDialogFooter as ShadcnAlertDialogFooter,\r\n AlertDialogHeader as ShadcnAlertDialogHeader,\r\n AlertDialogOverlay as ShadcnAlertDialogOverlay,\r\n AlertDialogPortal as ShadcnAlertDialogPortal,\r\n AlertDialogTitle as ShadcnAlertDialogTitle,\r\n AlertDialogTrigger as ShadcnAlertDialogTrigger,\r\n} from \"@/components/ui/alert-dialog\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport const alertDialogVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n },\r\n defaultVariants: {\r\n font: \"retro\",\r\n },\r\n});\r\n\r\nexport interface BitAlertDialogProps\r\n extends React.ComponentProps<typeof AlertDialogPrimitive.Root>,\r\n VariantProps<typeof alertDialogVariants> {}\r\n\r\nfunction AlertDialog({ ...props }: BitAlertDialogProps) {\r\n return <ShadcnAlertDialog {...props} />;\r\n}\r\n\r\nfunction AlertDialogTrigger({\r\n className,\r\n asChild = true,\r\n ...props\r\n}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {\r\n return (\r\n <ShadcnAlertDialogTrigger\r\n className={cn(className)}\r\n asChild={asChild}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction AlertDialogPortal({\r\n ...props\r\n}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {\r\n return <ShadcnAlertDialogPortal {...props} />;\r\n}\r\n\r\nfunction AlertDialogOverlay({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {\r\n return <ShadcnAlertDialogOverlay className={cn(className)} {...props} />;\r\n}\r\n\r\ninterface BitAlertDialogContentProps\r\n extends React.ComponentProps<typeof AlertDialogPrimitive.Content>,\r\n VariantProps<typeof alertDialogVariants> {}\r\n\r\nfunction AlertDialogContent({\r\n className,\r\n children,\r\n font,\r\n ...props\r\n}: BitAlertDialogContentProps) {\r\n return (\r\n <AlertDialogPortal>\r\n <AlertDialogOverlay />\r\n <>\r\n <ShadcnAlertDialogContent\r\n className={cn(\r\n \"rounded-none border-y-6 border-foreground dark:border-ring\",\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n\r\n <div\r\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n </ShadcnAlertDialogContent>\r\n </>\r\n </AlertDialogPortal>\r\n );\r\n}\r\n\r\nfunction AlertDialogHeader({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"div\">) {\r\n return <ShadcnAlertDialogHeader className={cn(className)} {...props} />;\r\n}\r\n\r\nfunction AlertDialogFooter({\r\n className,\r\n ...props\r\n}: React.ComponentProps<\"div\">) {\r\n return (\r\n <ShadcnAlertDialogFooter\r\n className={cn(\"flex flex-col-reverse sm:flex-row gap-4\", className)}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction AlertDialogTitle({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {\r\n return <ShadcnAlertDialogTitle className={cn(className)} {...props} />;\r\n}\r\n\r\nfunction AlertDialogDescription({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {\r\n return <ShadcnAlertDialogDescription className={cn(className)} {...props} />;\r\n}\r\n\r\nfunction AlertDialogAction({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {\r\n return (\r\n <ShadcnAlertDialogAction\r\n className={cn(\r\n \"rounded-none active:translate-y-1 transition-transform relative bg-primary\",\r\n \"ring-0 border-none\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {props.children}\r\n {/* Pixelated border */}\r\n <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute top-0 left-0 size-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute top-0 right-0 size-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute top-1.5 -left-1.5 h-2/3 w-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute top-1.5 -right-1.5 h-2/3 w-1.5 bg-foreground dark:bg-ring\" />\r\n {/* Top shadow */}\r\n <div className=\"absolute top-0 left-0 w-full h-1.5 bg-foreground/20\" />\r\n <div className=\"absolute top-1.5 left-0 w-3 h-1.5 bg-foreground/20\" />\r\n {/* Bottom shadow */}\r\n <div className=\"absolute bottom-0 left-0 w-full h-1.5 bg-foreground/20\" />\r\n <div className=\"absolute bottom-1.5 right-0 w-3 h-1.5 bg-foreground/20\" />\r\n </ShadcnAlertDialogAction>\r\n );\r\n}\r\n\r\nfunction AlertDialogCancel({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {\r\n return (\r\n <ShadcnAlertDialogCancel\r\n className={cn(\r\n \"rounded-none active:translate-y-1 transition-transform relative bg-background\",\r\n \"ring-0 border-none\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {props.children}\r\n <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute top-0 left-0 size-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute top-0 right-0 size-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute top-1.5 -left-1.5 h-2/3 w-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute top-1.5 -right-1.5 h-2/3 w-1.5 bg-foreground dark:bg-ring\" />\r\n </ShadcnAlertDialogCancel>\r\n );\r\n}\r\n\r\nexport {\r\n AlertDialog,\r\n AlertDialogPortal,\r\n AlertDialogOverlay,\r\n AlertDialogTrigger,\r\n AlertDialogContent,\r\n AlertDialogHeader,\r\n AlertDialogFooter,\r\n AlertDialogTitle,\r\n AlertDialogDescription,\r\n AlertDialogAction,\r\n AlertDialogCancel,\r\n};\r\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Formatting-only change to CRLF looks fine; ensure EOL is pinned to avoid churn across OS.

No functional differences in the embedded TSX; only newlines normalized to CRLF. To keep future diffs clean on non-Windows dev machines/CI, pin EOL via .gitattributes for registry JSON (and/or generated component targets).

Run this script to verify .gitattributes has an explicit CRLF rule and that it covers public/r and/or the generated component paths:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate .gitattributes
fd -H -a '^\.gitattributes$' | while read -r attr; do
  echo "Found: $attr"
  echo "---- Contents ($attr) ----"
  nl -ba "$attr"
  echo "--------------------------"
  echo
done

# Show any CRLF rules
rg -n --fixed-strings 'eol=crlf' || echo "No explicit eol=crlf rules found."

# Check if there are rules targeting registry or generated component files
echo
echo "Rules targeting registry or 8bit component files (heuristic):"
rg -n 'public/r/|components/ui/8bit' .gitattributes || echo "No path-specific rules found for registry or 8bit components."

Length of output: 558


Add .gitattributes to pin CRLF for generated registry files

Verification: no .gitattributes was found and there are no 'eol=crlf' rules — the change in public/r/8bit-alert-dialog.json is CRLF-only, so pinning EOL will avoid future churn.

Please add a .gitattributes at the repo root (or update it) with rules like:

# Pin EOL for generated registry JSON and generated UI outputs
/public/r/*       text eol=crlf
/components/ui/** text eol=crlf

Adjust patterns as needed for other generated targets.

🤖 Prompt for AI Agents
In public/r/8bit-alert-dialog.json around line 13 the file change is CRLF-only
and the repository lacks a .gitattributes entry to pin generated registry/UI
outputs to CRLF, causing future churn; add or update a .gitattributes at the
repo root and include rules that target generated registry JSON and generated UI
outputs (e.g., patterns for /public/r/* and /components/ui/**) setting text
eol=crlf so those files are normalized to CRLF on checkout.

{
"path": "components/ui/8bit/blocks/sidebar.tsx",
"content": "import { Calendar, Home, Inbox, Search, Settings } from \"lucide-react\";\n\nimport {\n Sidebar,\n SidebarContent,\n SidebarGroup,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n} from \"@/components/ui/sidebar\";\n\nimport \"./styles/retro.css\";\n\n// Menu items.\nconst items = [\n {\n title: \"Home\",\n url: \"#\",\n icon: Home,\n },\n {\n title: \"Inbox\",\n url: \"#\",\n icon: Inbox,\n },\n {\n title: \"Calendar\",\n url: \"#\",\n icon: Calendar,\n },\n {\n title: \"Search\",\n url: \"#\",\n icon: Search,\n },\n {\n title: \"Settings\",\n url: \"#\",\n icon: Settings,\n },\n];\n\nexport function AppSidebar() {\n return (\n <Sidebar\n className={`${\"retro\"} border-r-4 border-foreground dark:border-ring`}\n >\n <SidebarContent>\n <SidebarGroup>\n <SidebarGroupLabel>Application</SidebarGroupLabel>\n <SidebarGroupContent>\n <SidebarMenu>\n {items.map((item) => (\n <SidebarMenuItem key={item.title}>\n <SidebarMenuButton asChild>\n <a href={item.url}>\n <item.icon />\n <span>{item.title}</span>\n </a>\n </SidebarMenuButton>\n </SidebarMenuItem>\n ))}\n </SidebarMenu>\n </SidebarGroupContent>\n </SidebarGroup>\n </SidebarContent>\n </Sidebar>\n );\n}\n",
"content": "import { Calendar, Home, Inbox, Search, Settings } from \"lucide-react\";\r\n\r\nimport {\r\n Sidebar,\r\n SidebarContent,\r\n SidebarGroup,\r\n SidebarGroupContent,\r\n SidebarGroupLabel,\r\n SidebarMenu,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n} from \"@/components/ui/sidebar\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\n// Menu items.\r\nconst items = [\r\n {\r\n title: \"Home\",\r\n url: \"#\",\r\n icon: Home,\r\n },\r\n {\r\n title: \"Inbox\",\r\n url: \"#\",\r\n icon: Inbox,\r\n },\r\n {\r\n title: \"Calendar\",\r\n url: \"#\",\r\n icon: Calendar,\r\n },\r\n {\r\n title: \"Search\",\r\n url: \"#\",\r\n icon: Search,\r\n },\r\n {\r\n title: \"Settings\",\r\n url: \"#\",\r\n icon: Settings,\r\n },\r\n];\r\n\r\nexport function AppSidebar() {\r\n return (\r\n <Sidebar\r\n className={`${\"retro\"} border-r-4 border-foreground dark:border-ring`}\r\n >\r\n <SidebarContent>\r\n <SidebarGroup>\r\n <SidebarGroupLabel>Application</SidebarGroupLabel>\r\n <SidebarGroupContent>\r\n <SidebarMenu>\r\n {items.map((item) => (\r\n <SidebarMenuItem key={item.title}>\r\n <SidebarMenuButton asChild>\r\n <a href={item.url}>\r\n <item.icon />\r\n <span>{item.title}</span>\r\n </a>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n ))}\r\n </SidebarMenu>\r\n </SidebarGroupContent>\r\n </SidebarGroup>\r\n </SidebarContent>\r\n </Sidebar>\r\n );\r\n}\r\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect relative import to retro.css in embedded sidebar.tsx

In the embedded TSX, sidebar.tsx lives at components/ui/8bit/blocks/sidebar.tsx, while the stylesheet target is components/ui/8bit/styles/retro.css. The current import "./styles/retro.css" points to components/ui/8bit/blocks/styles/retro.css (non-existent). It should be one directory up.

Also, minor cleanup: the template literal around the static "retro" class is unnecessary.

Apply this diff within the content string:

-import "./styles/retro.css";
+import "../styles/retro.css";

Optionally simplify the className:

-    <Sidebar
-      className={`${"retro"} border-r-4 border-foreground dark:border-ring`}
-    >
+    <Sidebar className="retro border-r-4 border-foreground dark:border-ring">
📝 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.

Suggested change
"content": "import { Calendar, Home, Inbox, Search, Settings } from \"lucide-react\";\r\n\r\nimport {\r\n Sidebar,\r\n SidebarContent,\r\n SidebarGroup,\r\n SidebarGroupContent,\r\n SidebarGroupLabel,\r\n SidebarMenu,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n} from \"@/components/ui/sidebar\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\n// Menu items.\r\nconst items = [\r\n {\r\n title: \"Home\",\r\n url: \"#\",\r\n icon: Home,\r\n },\r\n {\r\n title: \"Inbox\",\r\n url: \"#\",\r\n icon: Inbox,\r\n },\r\n {\r\n title: \"Calendar\",\r\n url: \"#\",\r\n icon: Calendar,\r\n },\r\n {\r\n title: \"Search\",\r\n url: \"#\",\r\n icon: Search,\r\n },\r\n {\r\n title: \"Settings\",\r\n url: \"#\",\r\n icon: Settings,\r\n },\r\n];\r\n\r\nexport function AppSidebar() {\r\n return (\r\n <Sidebar\r\n className={`${\"retro\"} border-r-4 border-foreground dark:border-ring`}\r\n >\r\n <SidebarContent>\r\n <SidebarGroup>\r\n <SidebarGroupLabel>Application</SidebarGroupLabel>\r\n <SidebarGroupContent>\r\n <SidebarMenu>\r\n {items.map((item) => (\r\n <SidebarMenuItem key={item.title}>\r\n <SidebarMenuButton asChild>\r\n <a href={item.url}>\r\n <item.icon />\r\n <span>{item.title}</span>\r\n </a>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n ))}\r\n </SidebarMenu>\r\n </SidebarGroupContent>\r\n </SidebarGroup>\r\n </SidebarContent>\r\n </Sidebar>\r\n );\r\n}\r\n",
import { Calendar, Home, Inbox, Search, Settings } from "lucide-react";
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from "@/components/ui/sidebar";
import "../styles/retro.css";
// Menu items.
const items = [
{
title: "Home",
url: "#",
icon: Home,
},
{
title: "Inbox",
url: "#",
icon: Inbox,
},
{
title: "Calendar",
url: "#",
icon: Calendar,
},
{
title: "Search",
url: "#",
icon: Search,
},
{
title: "Settings",
url: "#",
icon: Settings,
},
];
export function AppSidebar() {
return (
<Sidebar className="retro border-r-4 border-foreground dark:border-ring">
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Application</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild>
<a href={item.url}>
<item.icon />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
);
}
🤖 Prompt for AI Agents
In public/r/8bit-sidebar.json around line 13, the embedded TSX imports the
stylesheet with import "./styles/retro.css" which points to a non-existent
blocks/styles path; change it to import "../styles/retro.css" so it references
components/ui/8bit/styles/retro.css, and simplify the Sidebar className by
removing the unnecessary template literal so it becomes a plain string with
"retro" plus the existing classes (e.g. "retro border-r-4 border-foreground
dark:border-ring").

{
"path": "components/ui/8bit/skeleton.tsx",
"content": "import { cn } from \"@/lib/utils\";\n\nimport { Skeleton as ShadcnSkeleton } from \"@/components/ui/skeleton\";\n\nimport \"./styles/retro.css\";\n\nexport interface BitSkeletonProp extends React.ComponentProps<\"div\"> {\n asChild?: boolean;\n}\n\nfunction Skeleton({ children, ...props }: BitSkeletonProp) {\n const { className } = props;\n\n return (\n <div className={cn(\"relative animate-pulse\", className)}>\n <ShadcnSkeleton\n {...props}\n className={cn(\"rounded-none border-none bg-accent\", \"retro\", className)}\n >\n {children}\n </ShadcnSkeleton>\n\n <div className=\"opacity-60\">\n <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n </div>\n <div className=\"opacity-60\">\n <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\n </div>\n <div className=\"absolute top-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\n <div className=\"absolute top-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\n <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\n <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\n <div className=\"opacity-60\">\n <div className=\"absolute top-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute bottom-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\n </div>\n <div className=\"opacity-60\">\n <div className=\"absolute top-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\n <div className=\"absolute bottom-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\n </div>\n </div>\n );\n}\n\nexport { Skeleton };\n",
"content": "import { cn } from \"@/lib/utils\";\r\n\r\nimport { Skeleton as ShadcnSkeleton } from \"@/components/ui/skeleton\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport interface BitSkeletonProp extends React.ComponentProps<\"div\"> {\r\n asChild?: boolean;\r\n}\r\n\r\nfunction Skeleton({ children, ...props }: BitSkeletonProp) {\r\n const { className } = props;\r\n\r\n return (\r\n <div className={cn(\"relative animate-pulse\", className)}>\r\n <ShadcnSkeleton\r\n {...props}\r\n className={cn(\"rounded-none border-none bg-accent\", \"retro\", className)}\r\n >\r\n {children}\r\n </ShadcnSkeleton>\r\n\r\n <div className=\"opacity-60\">\r\n <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n <div className=\"opacity-60\">\r\n <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n <div className=\"absolute top-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n <div className=\"absolute top-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n <div className=\"opacity-60\">\r\n <div className=\"absolute top-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute bottom-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n <div className=\"opacity-60\">\r\n <div className=\"absolute top-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute bottom-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport { Skeleton };\r\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Remove unused asChild prop and avoid leaking it into ShadcnSkeleton; also prefer React type imports and consistent Props naming

Spreading {...props} currently forwards asChild to ShadcnSkeleton, which likely violates its prop type (HTMLAttributes<HTMLDivElement>) and can trip TypeScript. Additionally, applying the consumer className to both the wrapper and the inner Skeleton can cause unintended styling duplication. Recommend:

  • Drop asChild (not used and not supported by Skeleton).
  • Import React types and avoid the React. namespace.
  • Use a single place for consumer className (root), and keep inner styles scoped.

Apply this diff to the content field to reflect the changes:

-      "content": "import { cn } from \"@/lib/utils\";\r\n\r\nimport { Skeleton as ShadcnSkeleton } from \"@/components/ui/skeleton\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport interface BitSkeletonProp extends React.ComponentProps<\"div\"> {\r\n  asChild?: boolean;\r\n}\r\n\r\nfunction Skeleton({ children, ...props }: BitSkeletonProp) {\r\n  const { className } = props;\r\n\r\n  return (\r\n    <div className={cn(\"relative animate-pulse\", className)}>\r\n      <ShadcnSkeleton\r\n        {...props}\r\n        className={cn(\"rounded-none border-none bg-accent\", \"retro\", className)}\r\n      >\r\n        {children}\r\n      </ShadcnSkeleton>\r\n\r\n      <div className=\"opacity-60\">\r\n        <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"opacity-60\">\r\n        <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"absolute top-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n      <div className=\"absolute top-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n      <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n      <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n      <div className=\"opacity-60\">\r\n        <div className=\"absolute top-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute bottom-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"opacity-60\">\r\n        <div className=\"absolute top-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute bottom-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n    </div>\r\n  );\r\n}\r\n\r\nexport { Skeleton };\r\n",
+      "content": "import type { ComponentPropsWithoutRef } from \"react\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { Skeleton as ShadcnSkeleton } from \"@/components/ui/skeleton\";\r\nimport \"./styles/retro.css\";\r\n\r\nexport type BitSkeletonProps = ComponentPropsWithoutRef<\"div\">;\r\n\r\nfunction Skeleton({ children, className, ...props }: BitSkeletonProps) {\r\n  return (\r\n    <div className={cn(\"relative animate-pulse\", className)}>\r\n      <ShadcnSkeleton\r\n        {...props}\r\n        className={cn(\"rounded-none border-none bg-accent\", \"retro\")}\r\n      >\r\n        {children}\r\n      </ShadcnSkeleton>\r\n\r\n      <div className=\"opacity-60\" aria-hidden=\"true\">\r\n        <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"opacity-60\" aria-hidden=\"true\">\r\n        <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"absolute top-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n      <div className=\"absolute top-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n      <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n      <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n      <div className=\"opacity-60\" aria-hidden=\"true\">\r\n        <div className=\"absolute top-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute bottom-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"opacity-60\" aria-hidden=\"true\">\r\n        <div className=\"absolute top-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute bottom-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n    </div>\r\n  );\r\n}\r\n\r\nexport { Skeleton };\r\n",

If you prefer preserving the ability to add styles to the inner element, introduce a dedicated prop (e.g., skeletonClassName) instead of reusing the consumer className.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Searching for 8bit-skeleton file..."
rg -n "8bit-skeleton" || true

echo
echo "Printing public/r/8bit-skeleton.json (if present)..."
if [ -f "public/r/8bit-skeleton.json" ]; then
  sed -n '1,240p' public/r/8bit-skeleton.json || true
else
  echo "public/r/8bit-skeleton.json not found"
fi

echo
echo "Searching for ui skeleton component imports/usages..."
rg -n "@/components/ui/skeleton" || true

echo
echo "Searching for Skeleton component definitions/usages across repo..."
rg -n "function Skeleton" || true
rg -n "export .*Skeleton" || true

echo
echo "Searching for 'asChild' occurrences..."
rg -n "asChild" || true

echo
echo "Searching for React ComponentProps usages..."
rg -n "ComponentProps" || true

Length of output: 304360


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- components/ui/8bit/skeleton.tsx ----"
if [ -f "components/ui/8bit/skeleton.tsx" ]; then
  sed -n '1,240p' components/ui/8bit/skeleton.tsx || true
else
  echo "NOT FOUND: components/ui/8bit/skeleton.tsx"
fi

echo
echo "---- components/ui/skeleton.tsx ----"
if [ -f "components/ui/skeleton.tsx" ]; then
  sed -n '1,240p' components/ui/skeleton.tsx || true
else
  echo "NOT FOUND: components/ui/skeleton.tsx"
fi

Length of output: 2590


Fix: remove unused asChild from 8-bit Skeleton and stop forwarding it into the inner ShadcnSkeleton

Short summary: I verified components/ui/8bit/skeleton.tsx forwards consumer props (including the unused asChild) into the inner ShadcnSkeleton, which then spreads them onto a DOM div (components/ui/skeleton.tsx). That leaks an invalid prop to the DOM and can cause TypeScript/behavioral issues. Remove the asChild prop, use typed React imports, keep consumer className on the outer wrapper only, and mark decorative pixels aria-hidden.

Files to change:

  • components/ui/8bit/skeleton.tsx
  • public/r/8bit-skeleton.json (update the "content" field to match the component change)

Apply this patch to components/ui/8bit/skeleton.tsx:

*** a/components/ui/8bit/skeleton.tsx
--- b/components/ui/8bit/skeleton.tsx
@@
-import { cn } from "@/lib/utils";
-
-import { Skeleton as ShadcnSkeleton } from "@/components/ui/skeleton";
-
-import "./styles/retro.css";
-
-export interface BitSkeletonProp extends React.ComponentProps<"div"> {
-  asChild?: boolean;
-}
-
-function Skeleton({ children, ...props }: BitSkeletonProp) {
-  const { className } = props;
-
-  return (
-    <div className={cn("relative animate-pulse", className)}>
-      <ShadcnSkeleton
-        {...props}
-        className={cn("rounded-none border-none bg-accent", "retro", className)}
-      >
-        {children}
-      </ShadcnSkeleton>
-
-      <div className="opacity-60">
-        <div className="absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring" />
-        <div className="absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring" />
-      </div>
-      <div className="opacity-60">
-        <div className="absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring" />
-        <div className="absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring" />
-      </div>
-      <div className="absolute top-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60" />
-      <div className="absolute top-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60" />
-      <div className="absolute bottom-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60" />
-      <div className="absolute bottom-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60" />
-      <div className="opacity-60">
-        <div className="absolute top-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring" />
-        <div className="absolute bottom-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring" />
-      </div>
-      <div className="opacity-60">
-        <div className="absolute top-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring" />
-        <div className="absolute bottom-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring" />
-      </div>
-    </div>
-  );
-}
-
-export { Skeleton };
+import type { ComponentPropsWithoutRef } from "react";
+import { cn } from "@/lib/utils";
+import { Skeleton as ShadcnSkeleton } from "@/components/ui/skeleton";
+import "./styles/retro.css";
+
+export type BitSkeletonProps = ComponentPropsWithoutRef<"div">;
+
+function Skeleton({ children, className, ...props }: BitSkeletonProps) {
+  return (
+    <div className={cn("relative animate-pulse", className)}>
+      <ShadcnSkeleton
+        {...props}
+        className={cn("rounded-none border-none bg-accent", "retro")}
+      >
+        {children}
+      </ShadcnSkeleton>
+
+      <div className="opacity-60" aria-hidden="true">
+        <div className="absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring" />
+        <div className="absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring" />
+      </div>
+      <div className="opacity-60" aria-hidden="true">
+        <div className="absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring" />
+        <div className="absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring" />
+      </div>
+      <div className="absolute top-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60" aria-hidden="true" />
+      <div className="absolute top-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60" aria-hidden="true" />
+      <div className="absolute bottom-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60" aria-hidden="true" />
+      <div className="absolute bottom-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60" aria-hidden="true" />
+      <div className="opacity-60" aria-hidden="true">
+        <div className="absolute top-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring" />
+        <div className="absolute bottom-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring" />
+      </div>
+      <div className="opacity-60" aria-hidden="true">
+        <div className="absolute top-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring" />
+        <div className="absolute bottom-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring" />
+      </div>
+    </div>
+  );
+}
+
+export { Skeleton };

And update the registry file public/r/8bit-skeleton.json "content" field with the same component source (replace the old string with the new component code). Example content replacement (apply to the "content" value):

-      "content": "import { cn } from \"@/lib/utils\";\r\n\r\nimport { Skeleton as ShadcnSkeleton } from \"@/components/ui/skeleton\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport interface BitSkeletonProp extends React.ComponentProps<\"div\"> {\r\n  asChild?: boolean;\r\n}\r\n\r\nfunction Skeleton({ children, ...props }: BitSkeletonProp) {\r\n  const { className } = props;\r\n\r\n  return (\r\n    <div className={cn(\"relative animate-pulse\", className)}>\r\n      <ShadcnSkeleton\r\n        {...props}\r\n        className={cn(\"rounded-none border-none bg-accent\", \"retro\", className)}\r\n      >\r\n        {children}\r\n      </ShadcnSkeleton>\r\n\r\n      <div className=\"opacity-60\">\r\n        <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"opacity-60\">\r\n        <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"absolute top-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n      <div className=\"absolute top-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n      <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n      <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n      <div className=\"opacity-60\">\r\n        <div className=\"absolute top-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute bottom-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"opacity-60\">\r\n        <div className=\"absolute top-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute bottom-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n    </div>\r\n  );\r\n}\r\n\r\nexport { Skeleton };\r\n",
+      "content": "import type { ComponentPropsWithoutRef } from \"react\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { Skeleton as ShadcnSkeleton } from \"@/components/ui/skeleton\";\r\nimport \"./styles/retro.css\";\r\n\r\nexport type BitSkeletonProps = ComponentPropsWithoutRef<\"div\">;\r\n\r\nfunction Skeleton({ children, className, ...props }: BitSkeletonProps) {\r\n  return (\r\n    <div className={cn(\"relative animate-pulse\", className)}>\r\n      <ShadcnSkeleton\r\n        {...props}\r\n        className={cn(\"rounded-none border-none bg-accent\", \"retro\")}\r\n      >\r\n        {children}\r\n      </ShadcnSkeleton>\r\n\r\n      <div className=\"opacity-60\" aria-hidden=\"true\">\r\n        <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"opacity-60\" aria-hidden=\"true\">\r\n        <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"absolute top-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n      <div className=\"absolute top-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n      <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n      <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n      <div className=\"opacity-60\" aria-hidden=\"true\">\r\n        <div className=\"absolute top-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute bottom-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n      <div className=\"opacity-60\" aria-hidden=\"true\">\r\n        <div className=\"absolute top-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n        <div className=\"absolute bottom-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n      </div>\r\n    </div>\r\n  );\r\n}\r\n\r\nexport { Skeleton };\r\n",

Notes / alternatives:

  • If you want consumers to be able to style the inner skeleton separately, add a dedicated prop (e.g., skeletonClassName) and pass it to the inner ShadcnSkeleton instead of reusing the consumer className.
  • I intentionally removed asChild from the 8-bit props (it wasn't used here). If you intended asChild behavior, implement it explicitly (e.g., conditional Slot usage) rather than letting it leak to the DOM.
📝 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.

Suggested change
"content": "import { cn } from \"@/lib/utils\";\r\n\r\nimport { Skeleton as ShadcnSkeleton } from \"@/components/ui/skeleton\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport interface BitSkeletonProp extends React.ComponentProps<\"div\"> {\r\n asChild?: boolean;\r\n}\r\n\r\nfunction Skeleton({ children, ...props }: BitSkeletonProp) {\r\n const { className } = props;\r\n\r\n return (\r\n <div className={cn(\"relative animate-pulse\", className)}>\r\n <ShadcnSkeleton\r\n {...props}\r\n className={cn(\"rounded-none border-none bg-accent\", \"retro\", className)}\r\n >\r\n {children}\r\n </ShadcnSkeleton>\r\n\r\n <div className=\"opacity-60\">\r\n <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n <div className=\"opacity-60\">\r\n <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n <div className=\"absolute top-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n <div className=\"absolute top-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" />\r\n <div className=\"opacity-60\">\r\n <div className=\"absolute top-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute bottom-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n <div className=\"opacity-60\">\r\n <div className=\"absolute top-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute bottom-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport { Skeleton };\r\n",
"content": "import type { ComponentPropsWithoutRef } from \"react\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { Skeleton as ShadcnSkeleton } from \"@/components/ui/skeleton\";\r\nimport \"./styles/retro.css\";\r\n\r\nexport type BitSkeletonProps = ComponentPropsWithoutRef<\"div\">;\r\n\r\nfunction Skeleton({ children, className, ...props }: BitSkeletonProps) {\r\n return (\r\n <div className={cn(\"relative animate-pulse\", className)}>\r\n <ShadcnSkeleton\r\n {...props}\r\n className={cn(\"rounded-none border-none bg-accent\", \"retro\")}\r\n >\r\n {children}\r\n </ShadcnSkeleton>\r\n\r\n <div className=\"opacity-60\" aria-hidden=\"true\">\r\n <div className=\"absolute -top-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -top-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n <div className=\"opacity-60\" aria-hidden=\"true\">\r\n <div className=\"absolute -bottom-1.5 w-1/2 left-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute -bottom-1.5 w-1/2 right-1.5 h-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n <div className=\"absolute top-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n <div className=\"absolute top-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n <div className=\"absolute bottom-0 left-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n <div className=\"absolute bottom-0 right-0 size-1.5 bg-foreground/60 dark:bg-ring/60\" aria-hidden=\"true\" />\r\n <div className=\"opacity-60\" aria-hidden=\"true\">\r\n <div className=\"absolute top-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute bottom-1 -left-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n <div className=\"opacity-60\" aria-hidden=\"true\">\r\n <div className=\"absolute top-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n <div className=\"absolute bottom-1 -right-1.5 h-1/2 w-1.5 bg-foreground dark:bg-ring\" />\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport { Skeleton };\r\n",
🤖 Prompt for AI Agents
In public/r/8bit-skeleton.json around line 13, the exported component string
still declares and forwards an unused asChild prop into the inner ShadcnSkeleton
which leaks an invalid prop to the DOM; update the component source (and the
registry "content" field) to remove asChild from the BitSkeletonProp, stop
spreading consumer props into ShadcnSkeleton (only pass a dedicated
skeletonClassName or specific safe props), ensure the outer wrapper retains the
consumer className, import React types explicitly (e.g.,
React.ComponentProps<"div">), and add aria-hidden on the decorative pixel divs
so they are ignored by assistive tech.

{
"path": "components/ui/8bit/tabs.tsx",
"content": "import * as TabsPrimitive from \"@radix-ui/react-tabs\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport {\n Tabs as ShadcnTabs,\n TabsContent as ShadcnTabsContent,\n TabsList as ShadcnTabsList,\n TabsTrigger as ShadcnTabsTrigger,\n} from \"@/components/ui/tabs\";\n\nimport \"./styles/retro.css\";\n\nexport const tabsVariants = cva(\"\", {\n variants: {\n variant: {\n default: \"bg-primary\",\n retro: \"retro\",\n },\n font: {\n normal: \"\",\n retro: \"retro\",\n },\n },\n defaultVariants: {\n font: \"retro\",\n },\n});\n\nexport interface BitTabsProps\n extends React.ComponentProps<typeof TabsPrimitive.Root>,\n VariantProps<typeof tabsVariants> {\n asChild?: boolean;\n}\n\nfunction Tabs({ className, ...props }: BitTabsProps) {\n const { font } = props;\n\n return (\n <ShadcnTabs\n {...props}\n className={cn(\"relative\", font !== \"normal\" && \"retro\", className)}\n />\n );\n}\n\nfunction TabsList({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof ShadcnTabsList>) {\n return (\n <ShadcnTabsList\n {...props}\n className={cn(\"relative bg-card rounded-none\", className)}\n >\n <div\n className=\"absolute inset-0 border-y-6 -my-1.5 border-foreground dark:border-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n\n <div\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n {children}\n </ShadcnTabsList>\n );\n}\n\nfunction TabsTrigger({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof ShadcnTabsTrigger>) {\n return (\n <ShadcnTabsTrigger\n className={cn(\n \"border-none data-[state=active]:bg-accent data-[state=active]:text-foreground text-muted-foreground rounded-none\",\n className\n )}\n {...props}\n >\n {children}\n </ShadcnTabsTrigger>\n );\n}\n\nfunction TabsContent({\n className,\n ...props\n}: React.ComponentProps<typeof ShadcnTabsContent>) {\n return <ShadcnTabsContent className={cn(\"\", className)} {...props} />;\n}\n\nexport { Tabs, TabsList, TabsContent, TabsTrigger };\n",
"content": "import * as TabsPrimitive from \"@radix-ui/react-tabs\";\r\nimport { type VariantProps, cva } from \"class-variance-authority\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n Tabs as ShadcnTabs,\r\n TabsContent as ShadcnTabsContent,\r\n TabsList as ShadcnTabsList,\r\n TabsTrigger as ShadcnTabsTrigger,\r\n} from \"@/components/ui/tabs\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport const tabsVariants = cva(\"\", {\r\n variants: {\r\n variant: {\r\n default: \"bg-primary\",\r\n retro: \"retro\",\r\n },\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n },\r\n defaultVariants: {\r\n font: \"retro\",\r\n },\r\n});\r\n\r\nexport interface BitTabsProps\r\n extends React.ComponentProps<typeof TabsPrimitive.Root>,\r\n VariantProps<typeof tabsVariants> {\r\n asChild?: boolean;\r\n}\r\n\r\nfunction Tabs({ className, ...props }: BitTabsProps) {\r\n const { font } = props;\r\n\r\n return (\r\n <ShadcnTabs\r\n {...props}\r\n className={cn(\"relative\", font !== \"normal\" && \"retro\", className)}\r\n />\r\n );\r\n}\r\n\r\nfunction TabsList({\r\n className,\r\n children,\r\n ...props\r\n}: React.ComponentProps<typeof ShadcnTabsList>) {\r\n return (\r\n <ShadcnTabsList\r\n {...props}\r\n className={cn(\"relative bg-card rounded-none\", className)}\r\n >\r\n <div\r\n className=\"absolute inset-0 border-y-6 -my-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n\r\n <div\r\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n {children}\r\n </ShadcnTabsList>\r\n );\r\n}\r\n\r\nfunction TabsTrigger({\r\n className,\r\n children,\r\n ...props\r\n}: React.ComponentProps<typeof ShadcnTabsTrigger>) {\r\n return (\r\n <ShadcnTabsTrigger\r\n className={cn(\r\n \"border-none data-[state=active]:bg-accent data-[state=active]:text-foreground text-muted-foreground rounded-none\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n </ShadcnTabsTrigger>\r\n );\r\n}\r\n\r\nfunction TabsContent({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof ShadcnTabsContent>) {\r\n return <ShadcnTabsContent className={cn(\"\", className)} {...props} />;\r\n}\r\n\r\nexport { Tabs, TabsList, TabsContent, TabsTrigger };\r\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Prevent leaking the custom font prop to the DOM in Tabs

font is read from props but still forwarded via {...props} to ShadcnTabs, which likely forwards to a DOM node. This can cause React unknown-prop warnings and unexpected attributes on the DOM. Destructure font out before spreading the rest.

Apply this diff inside components/ui/8bit/tabs.tsx:

-function Tabs({ className, ...props }: BitTabsProps) {
-  const { font } = props;
+function Tabs({ className, font, ...props }: BitTabsProps) {
   return (
     <ShadcnTabs
-      {...props}
+      {...props}
       className={cn("relative", font !== "normal" && "retro", className)}
     />
   );
}
📝 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.

Suggested change
"content": "import * as TabsPrimitive from \"@radix-ui/react-tabs\";\r\nimport { type VariantProps, cva } from \"class-variance-authority\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n Tabs as ShadcnTabs,\r\n TabsContent as ShadcnTabsContent,\r\n TabsList as ShadcnTabsList,\r\n TabsTrigger as ShadcnTabsTrigger,\r\n} from \"@/components/ui/tabs\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport const tabsVariants = cva(\"\", {\r\n variants: {\r\n variant: {\r\n default: \"bg-primary\",\r\n retro: \"retro\",\r\n },\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n },\r\n defaultVariants: {\r\n font: \"retro\",\r\n },\r\n});\r\n\r\nexport interface BitTabsProps\r\n extends React.ComponentProps<typeof TabsPrimitive.Root>,\r\n VariantProps<typeof tabsVariants> {\r\n asChild?: boolean;\r\n}\r\n\r\nfunction Tabs({ className, ...props }: BitTabsProps) {\r\n const { font } = props;\r\n\r\n return (\r\n <ShadcnTabs\r\n {...props}\r\n className={cn(\"relative\", font !== \"normal\" && \"retro\", className)}\r\n />\r\n );\r\n}\r\n\r\nfunction TabsList({\r\n className,\r\n children,\r\n ...props\r\n}: React.ComponentProps<typeof ShadcnTabsList>) {\r\n return (\r\n <ShadcnTabsList\r\n {...props}\r\n className={cn(\"relative bg-card rounded-none\", className)}\r\n >\r\n <div\r\n className=\"absolute inset-0 border-y-6 -my-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n\r\n <div\r\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n {children}\r\n </ShadcnTabsList>\r\n );\r\n}\r\n\r\nfunction TabsTrigger({\r\n className,\r\n children,\r\n ...props\r\n}: React.ComponentProps<typeof ShadcnTabsTrigger>) {\r\n return (\r\n <ShadcnTabsTrigger\r\n className={cn(\r\n \"border-none data-[state=active]:bg-accent data-[state=active]:text-foreground text-muted-foreground rounded-none\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n </ShadcnTabsTrigger>\r\n );\r\n}\r\n\r\nfunction TabsContent({\r\n className,\r\n ...props\r\n}: React.ComponentProps<typeof ShadcnTabsContent>) {\r\n return <ShadcnTabsContent className={cn(\"\", className)} {...props} />;\r\n}\r\n\r\nexport { Tabs, TabsList, TabsContent, TabsTrigger };\r\n",
function Tabs({ className, font, ...props }: BitTabsProps) {
return (
<ShadcnTabs
{...props}
className={cn("relative", font !== "normal" && "retro", className)}
/>
);
}
🤖 Prompt for AI Agents
In public/r/8bit-tabs.json around line 13 (corresponds to
components/ui/8bit/tabs.tsx Tabs component), the custom prop `font` is read from
props but still forwarded via {...props} to ShadcnTabs which may leak it to the
DOM; fix by destructuring `font` out of props (e.g. const { font, ...rest } =
props) and spread `rest` into <ShadcnTabs> instead of `props`, and keep using
`font` for className logic so the prop is not forwarded to the DOM.

{
"path": "components/ui/8bit/toggle.tsx",
"content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport * as TogglePrimitive from \"@radix-ui/react-toggle\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport { Toggle as ShadcnToggle } from \"@/components/ui/toggle\";\n\nimport \"./styles/retro.css\";\n\nconst toggleVariants = cva(\"\", {\n variants: {\n font: {\n normal: \"\",\n retro: \"retro\",\n },\n variant: {\n default: \"bg-transparent\",\n outline:\n \"bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground\",\n },\n size: {\n default: \"h-9 px-2 min-w-9\",\n sm: \"h-8 px-1.5 min-w-8\",\n lg: \"h-10 px-2.5 min-w-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n font: \"retro\",\n size: \"default\",\n },\n});\n\nexport interface BitToggleProps\n extends React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root>,\n VariantProps<typeof toggleVariants> {}\n\nfunction Toggle({ children, font, ...props }: BitToggleProps) {\n const { variant, className } = props;\n\n return (\n <ShadcnToggle\n {...props}\n className={cn(\n \"rounded-none active:translate-y-1 transition-transform relative border-none active:translate-x-1\",\n \"data-[state=on]:bg-primary data-[state=on]:text-primary-foreground\",\n font !== \"normal\" && \"retro\",\n className\n )}\n >\n {children}\n\n <>\n {variant === \"outline\" && (\n <>\n <div\n className=\"absolute inset-0 border-y-6 -my-1.5 border-foreground dark:border-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n\n <div\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n </>\n )}\n </>\n </ShadcnToggle>\n );\n}\n\nexport { Toggle, toggleVariants };\n",
"content": "\"use client\";\r\n\r\nimport * as React from \"react\";\r\n\r\nimport * as TogglePrimitive from \"@radix-ui/react-toggle\";\r\nimport { type VariantProps, cva } from \"class-variance-authority\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport { Toggle as ShadcnToggle } from \"@/components/ui/toggle\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nconst toggleVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n variant: {\r\n default: \"bg-transparent\",\r\n outline:\r\n \"bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground\",\r\n },\r\n size: {\r\n default: \"h-9 px-2 min-w-9\",\r\n sm: \"h-8 px-1.5 min-w-8\",\r\n lg: \"h-10 px-2.5 min-w-10\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n font: \"retro\",\r\n size: \"default\",\r\n },\r\n});\r\n\r\nexport interface BitToggleProps\r\n extends React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root>,\r\n VariantProps<typeof toggleVariants> {}\r\n\r\nfunction Toggle({ children, font, ...props }: BitToggleProps) {\r\n const { variant, className } = props;\r\n\r\n return (\r\n <ShadcnToggle\r\n {...props}\r\n className={cn(\r\n \"rounded-none active:translate-y-1 transition-transform relative border-none active:translate-x-1\",\r\n \"data-[state=on]:bg-primary data-[state=on]:text-primary-foreground\",\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n >\r\n {children}\r\n\r\n <>\r\n {variant === \"outline\" && (\r\n <>\r\n <div\r\n className=\"absolute inset-0 border-y-6 -my-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n\r\n <div\r\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n </>\r\n )}\r\n </>\r\n </ShadcnToggle>\r\n );\r\n}\r\n\r\nexport { Toggle, toggleVariants };\r\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid leaking non-DOM props and align with shadcn patterns (forwardRef + use your cva or drop it).

  • The current implementation spreads all props into ShadcnToggle, which forwards unknown props like font to the DOM button. This is leaky and can create noisy DOM attributes.
  • toggleVariants is defined/exported but not actually used to compute classes. Either use it to apply variant/size/font or remove it to avoid dead code/config drift.
  • Minor: redundant fragments around the outline overlay can be removed.

Apply this refactor to filter non-DOM props, adopt forwardRef for parity with shadcn components, actually use toggleVariants, and simplify fragments:

-"use client";
-
-import * as React from "react";
-
-import * as TogglePrimitive from "@radix-ui/react-toggle";
-import { type VariantProps, cva } from "class-variance-authority";
-
-import { cn } from "@/lib/utils";
-
-import { Toggle as ShadcnToggle } from "@/components/ui/toggle";
-
-import "./styles/retro.css";
-
-const toggleVariants = cva("", {
+ "use client";
+
+ import * as React from "react";
+
+ import * as TogglePrimitive from "@radix-ui/react-toggle";
+ import { type VariantProps, cva } from "class-variance-authority";
+
+ import { cn } from "@/lib/utils";
+
+ import { Toggle as ShadcnToggle } from "@/components/ui/toggle";
+
+ import "./styles/retro.css";
+
+ const toggleVariants = cva("", {
   variants: {
     font: {
       normal: "",
       retro: "retro",
     },
     variant: {
       default: "bg-transparent",
       outline:
         "bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground",
     },
     size: {
       default: "h-9 px-2 min-w-9",
       sm: "h-8 px-1.5 min-w-8",
       lg: "h-10 px-2.5 min-w-10",
     },
   },
   defaultVariants: {
     variant: "default",
     font: "retro",
     size: "default",
   },
-});
-
-export interface BitToggleProps
-  extends React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root>,
-    VariantProps<typeof toggleVariants> {}
-
-function Toggle({ children, font, ...props }: BitToggleProps) {
-  const { variant, className } = props;
-
-  return (
-    <ShadcnToggle
-      {...props}
-      className={cn(
-        "rounded-none active:translate-y-1 transition-transform relative border-none active:translate-x-1",
-        "data-[state=on]:bg-primary data-[state=on]:text-primary-foreground",
-        font !== "normal" && "retro",
-        className
-      )}
-    >
-      {children}
-
-      <>
-        {variant === "outline" && (
-          <>
-            <div
-              className="absolute inset-0 border-y-6 -my-1.5 border-foreground dark:border-ring pointer-events-none"
-              aria-hidden="true"
-            />
-
-            <div
-              className="absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none"
-              aria-hidden="true"
-            />
-          </>
-        )}
-      </>
-    </ShadcnToggle>
-  );
-}
-
-export { Toggle, toggleVariants };
+ });
+
+ export interface BitToggleProps
+   extends React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root>,
+     VariantProps<typeof toggleVariants> {}
+
+ const Toggle = React.forwardRef<
+   React.ElementRef<typeof ShadcnToggle>,
+   BitToggleProps
+ >(({ children, font, variant, size, className, ...rest }, ref) => {
+   return (
+     <ShadcnToggle
+       ref={ref}
+       {...rest}
+       className={cn(
+         // base 8-bit styles
+         "rounded-none active:translate-y-1 transition-transform relative border-none active:translate-x-1",
+         "data-[state=on]:bg-primary data-[state=on]:text-primary-foreground",
+         // compose variant/size/font classes
+         toggleVariants({ font, variant, size }),
+         className
+       )}
+     >
+       {children}
+       {variant === "outline" && (
+         <>
+           <div
+             className="absolute inset-0 border-y-6 -my-1.5 border-foreground dark:border-ring pointer-events-none"
+             aria-hidden="true"
+           />
+           <div
+             className="absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none"
+             aria-hidden="true"
+           />
+         </>
+       )}
+     </ShadcnToggle>
+   );
+ });
+ Toggle.displayName = "Toggle";
+
+ export { Toggle, toggleVariants };
📝 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.

Suggested change
"content": "\"use client\";\r\n\r\nimport * as React from \"react\";\r\n\r\nimport * as TogglePrimitive from \"@radix-ui/react-toggle\";\r\nimport { type VariantProps, cva } from \"class-variance-authority\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport { Toggle as ShadcnToggle } from \"@/components/ui/toggle\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nconst toggleVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n variant: {\r\n default: \"bg-transparent\",\r\n outline:\r\n \"bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground\",\r\n },\r\n size: {\r\n default: \"h-9 px-2 min-w-9\",\r\n sm: \"h-8 px-1.5 min-w-8\",\r\n lg: \"h-10 px-2.5 min-w-10\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n font: \"retro\",\r\n size: \"default\",\r\n },\r\n});\r\n\r\nexport interface BitToggleProps\r\n extends React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root>,\r\n VariantProps<typeof toggleVariants> {}\r\n\r\nfunction Toggle({ children, font, ...props }: BitToggleProps) {\r\n const { variant, className } = props;\r\n\r\n return (\r\n <ShadcnToggle\r\n {...props}\r\n className={cn(\r\n \"rounded-none active:translate-y-1 transition-transform relative border-none active:translate-x-1\",\r\n \"data-[state=on]:bg-primary data-[state=on]:text-primary-foreground\",\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n >\r\n {children}\r\n\r\n <>\r\n {variant === \"outline\" && (\r\n <>\r\n <div\r\n className=\"absolute inset-0 border-y-6 -my-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n\r\n <div\r\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n </>\r\n )}\r\n </>\r\n </ShadcnToggle>\r\n );\r\n}\r\n\r\nexport { Toggle, toggleVariants };\r\n",
"use client";
import * as React from "react";
import * as TogglePrimitive from "@radix-ui/react-toggle";
import { type VariantProps, cva } from "class-variance-authority";
import { cn } from "@/lib/utils";
import { Toggle as ShadcnToggle } from "@/components/ui/toggle";
import "./styles/retro.css";
const toggleVariants = cva("", {
variants: {
font: {
normal: "",
retro: "retro",
},
variant: {
default: "bg-transparent",
outline:
"bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground",
},
size: {
default: "h-9 px-2 min-w-9",
sm: "h-8 px-1.5 min-w-8",
lg: "h-10 px-2.5 min-w-10",
},
},
defaultVariants: {
variant: "default",
font: "retro",
size: "default",
},
});
export interface BitToggleProps
extends React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root>,
VariantProps<typeof toggleVariants> {}
const Toggle = React.forwardRef<
React.ElementRef<typeof ShadcnToggle>,
BitToggleProps
>(({ children, font, variant, size, className, ...rest }, ref) => {
return (
<ShadcnToggle
ref={ref}
{...rest}
className={cn(
// base 8-bit styles
"rounded-none active:translate-y-1 transition-transform relative border-none active:translate-x-1",
"data-[state=on]:bg-primary data-[state=on]:text-primary-foreground",
// compose variant/size/font classes
toggleVariants({ font, variant, size }),
className
)}
>
{children}
{variant === "outline" && (
<>
<div
className="absolute inset-0 border-y-6 -my-1.5 border-foreground dark:border-ring pointer-events-none"
aria-hidden="true"
/>
<div
className="absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none"
aria-hidden="true"
/>
</>
)}
</ShadcnToggle>
);
});
Toggle.displayName = "Toggle";
export { Toggle, toggleVariants };

{
"path": "components/ui/8bit/tooltip.tsx",
"content": "\"use client\";\n\nimport type * as React from \"react\";\n\nimport { type VariantProps, cva } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport {\n Tooltip as ShadcnTooltip,\n TooltipContent as ShadcnTooltipContent,\n TooltipProvider as ShadcnTooltipProvider,\n TooltipTrigger as ShadcnTooltipTrigger,\n} from \"@/components/ui/tooltip\";\n\nimport \"./styles/retro.css\";\n\nexport const tooltipVariants = cva(\"\", {\n variants: {\n font: {\n normal: \"\",\n retro: \"retro\",\n },\n },\n defaultVariants: {\n font: \"retro\",\n },\n});\n\nexport interface BitTooltipContentProps\n extends React.ComponentPropsWithoutRef<typeof ShadcnTooltipContent>,\n VariantProps<typeof tooltipVariants> {}\n\nfunction TooltipContent({\n className,\n children,\n font,\n ...props\n}: BitTooltipContentProps) {\n const color = tooltipVariants({ font });\n\n return (\n <div className={cn(\"relative inline-flex\", className)}>\n <ShadcnTooltipContent\n {...props}\n data-slot=\"tooltip-content\"\n className={cn(\"rounded-none\", color, className)}\n >\n {children}\n <div\n className={cn(\n \"absolute top-1.5 bottom-1.5 -left-1.5 h-1/2 w-1.5 bg-primary\",\n color\n )}\n />\n <div\n className={cn(\n \"absolute top-1.5 bottom-1.5 -right-1.5 h-1/2 w-1.5 bg-primary \",\n color\n )}\n />\n </ShadcnTooltipContent>\n </div>\n );\n}\n\nexport interface BitTooltipProps\n extends React.ComponentPropsWithoutRef<typeof ShadcnTooltip>,\n VariantProps<typeof tooltipVariants> {}\n\nfunction Tooltip({ children, ...props }: BitTooltipProps) {\n return (\n <ShadcnTooltip data-slot=\"tooltip\" {...props}>\n {children}\n </ShadcnTooltip>\n );\n}\n\nexport interface BitTooltipProviderProps\n extends React.ComponentPropsWithoutRef<typeof ShadcnTooltipProvider> {\n delayDuration?: number;\n}\n\nfunction TooltipProvider({\n children,\n delayDuration = 0,\n ...props\n}: BitTooltipProviderProps) {\n return (\n <ShadcnTooltipProvider delayDuration={delayDuration} {...props}>\n {children}\n </ShadcnTooltipProvider>\n );\n}\n\nfunction TooltipTrigger({\n children,\n asChild = true,\n ...props\n}: React.ComponentPropsWithoutRef<typeof ShadcnTooltipTrigger>) {\n return (\n <ShadcnTooltipTrigger\n data-slot=\"tooltip-trigger\"\n asChild={asChild}\n {...props}\n >\n {children}\n </ShadcnTooltipTrigger>\n );\n}\n\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\n",
"content": "\"use client\";\r\n\r\nimport type * as React from \"react\";\r\n\r\nimport { type VariantProps, cva } from \"class-variance-authority\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n Tooltip as ShadcnTooltip,\r\n TooltipContent as ShadcnTooltipContent,\r\n TooltipProvider as ShadcnTooltipProvider,\r\n TooltipTrigger as ShadcnTooltipTrigger,\r\n} from \"@/components/ui/tooltip\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport const tooltipVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n },\r\n defaultVariants: {\r\n font: \"retro\",\r\n },\r\n});\r\n\r\nexport interface BitTooltipContentProps\r\n extends React.ComponentPropsWithoutRef<typeof ShadcnTooltipContent>,\r\n VariantProps<typeof tooltipVariants> {}\r\n\r\nfunction TooltipContent({\r\n className,\r\n children,\r\n font,\r\n ...props\r\n}: BitTooltipContentProps) {\r\n const color = tooltipVariants({ font });\r\n\r\n return (\r\n <div className={cn(\"relative inline-flex\", className)}>\r\n <ShadcnTooltipContent\r\n {...props}\r\n data-slot=\"tooltip-content\"\r\n className={cn(\"rounded-none\", color, className)}\r\n >\r\n {children}\r\n <div\r\n className={cn(\r\n \"absolute top-1.5 bottom-1.5 -left-1.5 h-1/2 w-1.5 bg-primary\",\r\n color\r\n )}\r\n />\r\n <div\r\n className={cn(\r\n \"absolute top-1.5 bottom-1.5 -right-1.5 h-1/2 w-1.5 bg-primary \",\r\n color\r\n )}\r\n />\r\n </ShadcnTooltipContent>\r\n </div>\r\n );\r\n}\r\n\r\nexport interface BitTooltipProps\r\n extends React.ComponentPropsWithoutRef<typeof ShadcnTooltip>,\r\n VariantProps<typeof tooltipVariants> {}\r\n\r\nfunction Tooltip({ children, ...props }: BitTooltipProps) {\r\n return (\r\n <ShadcnTooltip data-slot=\"tooltip\" {...props}>\r\n {children}\r\n </ShadcnTooltip>\r\n );\r\n}\r\n\r\nexport interface BitTooltipProviderProps\r\n extends React.ComponentPropsWithoutRef<typeof ShadcnTooltipProvider> {\r\n delayDuration?: number;\r\n}\r\n\r\nfunction TooltipProvider({\r\n children,\r\n delayDuration = 0,\r\n ...props\r\n}: BitTooltipProviderProps) {\r\n return (\r\n <ShadcnTooltipProvider delayDuration={delayDuration} {...props}>\r\n {children}\r\n </ShadcnTooltipProvider>\r\n );\r\n}\r\n\r\nfunction TooltipTrigger({\r\n children,\r\n asChild = true,\r\n ...props\r\n}: React.ComponentPropsWithoutRef<typeof ShadcnTooltipTrigger>) {\r\n return (\r\n <ShadcnTooltipTrigger\r\n data-slot=\"tooltip-trigger\"\r\n asChild={asChild}\r\n {...props}\r\n >\r\n {children}\r\n </ShadcnTooltipTrigger>\r\n );\r\n}\r\n\r\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\r\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

TooltipContent applies className to both wrapper and inner content

className is passed to the wrapper div and also to ShadcnTooltipContent, causing duplication that can double margins/padding and complicate overrides.

Simple fix: don’t spread className to the wrapper; keep it only on the inner content.

 function TooltipContent({
   className,
   children,
   font,
   ...props
 }: BitTooltipContentProps) {
   const color = tooltipVariants({ font });
 
   return (
-    <div className={cn("relative inline-flex", className)}>
+    <div className={cn("relative inline-flex")}>
       <ShadcnTooltipContent
         {...props}
         data-slot="tooltip-content"
         className={cn("rounded-none", color, className)}
       >
         {children}

If you need users to style the wrapper separately, introduce a dedicated wrapperClassName prop.

📝 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.

Suggested change
"content": "\"use client\";\r\n\r\nimport type * as React from \"react\";\r\n\r\nimport { type VariantProps, cva } from \"class-variance-authority\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n Tooltip as ShadcnTooltip,\r\n TooltipContent as ShadcnTooltipContent,\r\n TooltipProvider as ShadcnTooltipProvider,\r\n TooltipTrigger as ShadcnTooltipTrigger,\r\n} from \"@/components/ui/tooltip\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport const tooltipVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n },\r\n defaultVariants: {\r\n font: \"retro\",\r\n },\r\n});\r\n\r\nexport interface BitTooltipContentProps\r\n extends React.ComponentPropsWithoutRef<typeof ShadcnTooltipContent>,\r\n VariantProps<typeof tooltipVariants> {}\r\n\r\nfunction TooltipContent({\r\n className,\r\n children,\r\n font,\r\n ...props\r\n}: BitTooltipContentProps) {\r\n const color = tooltipVariants({ font });\r\n\r\n return (\r\n <div className={cn(\"relative inline-flex\", className)}>\r\n <ShadcnTooltipContent\r\n {...props}\r\n data-slot=\"tooltip-content\"\r\n className={cn(\"rounded-none\", color, className)}\r\n >\r\n {children}\r\n <div\r\n className={cn(\r\n \"absolute top-1.5 bottom-1.5 -left-1.5 h-1/2 w-1.5 bg-primary\",\r\n color\r\n )}\r\n />\r\n <div\r\n className={cn(\r\n \"absolute top-1.5 bottom-1.5 -right-1.5 h-1/2 w-1.5 bg-primary \",\r\n color\r\n )}\r\n />\r\n </ShadcnTooltipContent>\r\n </div>\r\n );\r\n}\r\n\r\nexport interface BitTooltipProps\r\n extends React.ComponentPropsWithoutRef<typeof ShadcnTooltip>,\r\n VariantProps<typeof tooltipVariants> {}\r\n\r\nfunction Tooltip({ children, ...props }: BitTooltipProps) {\r\n return (\r\n <ShadcnTooltip data-slot=\"tooltip\" {...props}>\r\n {children}\r\n </ShadcnTooltip>\r\n );\r\n}\r\n\r\nexport interface BitTooltipProviderProps\r\n extends React.ComponentPropsWithoutRef<typeof ShadcnTooltipProvider> {\r\n delayDuration?: number;\r\n}\r\n\r\nfunction TooltipProvider({\r\n children,\r\n delayDuration = 0,\r\n ...props\r\n}: BitTooltipProviderProps) {\r\n return (\r\n <ShadcnTooltipProvider delayDuration={delayDuration} {...props}>\r\n {children}\r\n </ShadcnTooltipProvider>\r\n );\r\n}\r\n\r\nfunction TooltipTrigger({\r\n children,\r\n asChild = true,\r\n ...props\r\n}: React.ComponentPropsWithoutRef<typeof ShadcnTooltipTrigger>) {\r\n return (\r\n <ShadcnTooltipTrigger\r\n data-slot=\"tooltip-trigger\"\r\n asChild={asChild}\r\n {...props}\r\n >\r\n {children}\r\n </ShadcnTooltipTrigger>\r\n );\r\n}\r\n\r\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\r\n",
export interface BitTooltipContentProps
extends React.ComponentPropsWithoutRef<typeof ShadcnTooltipContent>,
VariantProps<typeof tooltipVariants> {}
function TooltipContent({
className,
children,
font,
...props
}: BitTooltipContentProps) {
const color = tooltipVariants({ font });
return (
<div className={cn("relative inline-flex")}>
<ShadcnTooltipContent
{...props}
data-slot="tooltip-content"
className={cn("rounded-none", color, className)}
>
{children}
<div
className={cn(
"absolute top-1.5 bottom-1.5 -left-1.5 h-1/2 w-1.5 bg-primary",
color
)}
/>
<div
className={cn(
"absolute top-1.5 bottom-1.5 -right-1.5 h-1/2 w-1.5 bg-primary ",
color
)}
/>
</ShadcnTooltipContent>
</div>
);
}
🤖 Prompt for AI Agents
public/r/8bit-tooltip.json around line 13: TooltipContent passes the same
className to both the outer wrapper div and the ShadcnTooltipContent, causing
duplicated styles; remove className from the wrapper (leave className applied
only to ShadcnTooltipContent) so the wrapper uses only fixed classes (e.g.,
"relative inline-flex"), and if separate wrapper styling is required add a new
optional wrapperClassName prop to the BitTooltipContentProps and apply that to
the wrapper instead.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review continued from previous batch...

Comment on lines +1 to +24
export const ChevronRightIcon = () => {
return (
<svg
width="50"
height="50"
viewBox="0 0 256 256"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
strokeWidth="0.25"
color=""
className="raster-icon size-7"
aria-label="chevron-right"
>
<rect x="128" y="136" width="14" height="14" rx="1"></rect>
<rect x="112" y="152" width="14" height="14" rx="1"></rect>
<rect x="96" y="72" width="14" height="14" rx="1"></rect>
<rect x="96" y="168" width="14" height="14" rx="1"></rect>
<rect x="144" y="120" width="14" height="14" rx="1"></rect>
<rect x="128" y="104" width="14" height="14" rx="1"></rect>
<rect x="112" y="88" width="14" height="14" rx="1"></rect>
</svg>
);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Make the icon configurable (className/props), remove stray color="", and set sensible a11y defaults.

The icon is hard-coded (no className/props), uses a larger default size than prior lucide usage, and includes a redundant color="". To maximize reuse and preserve layout control in callers, let it accept standard SVG props and default to being decorative.

Apply:

+import * as React from "react"
+import { cn } from "@/lib/utils"
+
-export const ChevronRightIcon = () => {
-  return (
-    <svg
-      width="50"
-      height="50"
-      viewBox="0 0 256 256"
-      fill="currentColor"
-      xmlns="http://www.w3.org/2000/svg"
-      stroke="currentColor"
-      strokeWidth="0.25"
-      color=""
-      className="raster-icon size-7"
-      aria-label="chevron-right"
-    >
+type IconProps = React.SVGProps<SVGSVGElement> & { title?: string }
+
+export const ChevronRightIcon = ({ className, title, ...props }: IconProps) => {
+  return (
+    <svg
+      width="50"
+      height="50"
+      viewBox="0 0 256 256"
+      fill="currentColor"
+      xmlns="http://www.w3.org/2000/svg"
+      stroke="currentColor"
+      strokeWidth="0.25"
+      className={cn("raster-icon size-7", className)}
+      aria-hidden={title ? undefined : true}
+      role={title ? "img" : "presentation"}
+      {...props}
+    >
+      {title ? <title>{title}</title> : null}
       <rect x="128" y="136" width="14" height="14" rx="1"></rect>
       <rect x="112" y="152" width="14" height="14" rx="1"></rect>
       <rect x="96" y="72" width="14" height="14" rx="1"></rect>
       <rect x="96" y="168" width="14" height="14" rx="1"></rect>
       <rect x="144" y="120" width="14" height="14" rx="1"></rect>
       <rect x="128" y="104" width="14" height="14" rx="1"></rect>
       <rect x="112" y="88" width="14" height="14" rx="1"></rect>
     </svg>
   );
 };

This keeps the current default size but allows callers to override (e.g., ml-auto size-4) and ensures the icon is decorative by default.

📝 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.

Suggested change
export const ChevronRightIcon = () => {
return (
<svg
width="50"
height="50"
viewBox="0 0 256 256"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
strokeWidth="0.25"
color=""
className="raster-icon size-7"
aria-label="chevron-right"
>
<rect x="128" y="136" width="14" height="14" rx="1"></rect>
<rect x="112" y="152" width="14" height="14" rx="1"></rect>
<rect x="96" y="72" width="14" height="14" rx="1"></rect>
<rect x="96" y="168" width="14" height="14" rx="1"></rect>
<rect x="144" y="120" width="14" height="14" rx="1"></rect>
<rect x="128" y="104" width="14" height="14" rx="1"></rect>
<rect x="112" y="88" width="14" height="14" rx="1"></rect>
</svg>
);
};
import * as React from "react"
import { cn } from "@/lib/utils"
type IconProps = React.SVGProps<SVGSVGElement> & { title?: string }
export const ChevronRightIcon = ({ className, title, ...props }: IconProps) => {
return (
<svg
width="50"
height="50"
viewBox="0 0 256 256"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
strokeWidth="0.25"
className={cn("raster-icon size-7", className)}
aria-hidden={title ? undefined : true}
role={title ? "img" : "presentation"}
{...props}
>
{title ? <title>{title}</title> : null}
<rect x="128" y="136" width="14" height="14" rx="1"></rect>
<rect x="112" y="152" width="14" height="14" rx="1"></rect>
<rect x="96" y="72" width="14" height="14" rx="1"></rect>
<rect x="96" y="168" width="14" height="14" rx="1"></rect>
<rect x="144" y="120" width="14" height="14" rx="1"></rect>
<rect x="128" y="104" width="14" height="14" rx="1"></rect>
<rect x="112" y="88" width="14" height="14" rx="1"></rect>
</svg>
);
};
🤖 Prompt for AI Agents
In components/ui/8bit/assets/chevronRightIcon.tsx around lines 1 to 24, the SVG
is hard-coded and contains a stray color="" attribute and no way for callers to
override className/props or provide accessibility attributes; update the
component to accept standard SVG props (including className) and spread them
onto the <svg>, remove the color="" attribute, preserve the current default
attributes (width="50" height="50" viewBox and className="raster-icon size-7")
but allow them to be overridden by incoming props, and make the icon decorative
by default by setting aria-hidden=true unless an explicit aria-label or role is
provided by the caller.

Comment on lines 127 to 133
Chevron: ({ className, ...props }) => {
if (props.orientation === "left") {
return (
<svg
viewBox="0 0 256 256"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
strokeWidth="0.25"
color=""
className={cn("size-4 shrink-0", className)}
aria-label="chevron-left"
{...props}
>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 128 136)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 144 152)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 160 72)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 160 168)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 112 120)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 128 104)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 144 88)"
></rect>
</svg>
);
return <ChevronLeftIcon />;
}

return (
<svg
viewBox="0 0 256 256"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
strokeWidth="0.25"
color=""
className={cn("size-4 shrink-0", className)}
aria-label="chevron-right"
{...props}
>
<rect x="128" y="136" width="14" height="14" rx="1"></rect>
<rect x="112" y="152" width="14" height="14" rx="1"></rect>
<rect x="96" y="72" width="14" height="14" rx="1"></rect>
<rect x="96" y="168" width="14" height="14" rx="1"></rect>
<rect x="144" y="120" width="14" height="14" rx="1"></rect>
<rect x="128" y="104" width="14" height="14" rx="1"></rect>
<rect x="112" y="88" width="14" height="14" rx="1"></rect>
</svg>
);
return <ChevronRightIcon />;
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Chevron component no longer forwards className/props; restore sizing and accessibility locally

The previous inline SVG respected incoming className/props. With the asset, className/props are dropped, and the asset enforces size-7, which may not match the nav button’s intent. Wrap and forward the className for predictable sizing and hide the decorative icon from AT:

           Chevron: ({ className, ...props }) => {
             if (props.orientation === "left") {
-              return <ChevronLeftIcon />;
+              return (
+                <span className={cn(className, "[&>svg]:size-4")} aria-hidden="true">
+                  <ChevronLeftIcon />
+                </span>
+              );
             }
 
-            return <ChevronRightIcon />;
+            return (
+              <span className={cn(className, "[&>svg]:size-4")} aria-hidden="true">
+                <ChevronRightIcon />
+              </span>
+            );
           },
  • Preserves styling hooks the DayPicker/Shadcn might pass.
  • Ensures a compact icon size that fits the button.
  • Avoids duplicate announcements by screen readers.

If you prefer removing wrappers, update both Chevron assets to accept and merge className/props and drop hardcoded size.

📝 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.

Suggested change
Chevron: ({ className, ...props }) => {
if (props.orientation === "left") {
return (
<svg
viewBox="0 0 256 256"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
strokeWidth="0.25"
color=""
className={cn("size-4 shrink-0", className)}
aria-label="chevron-left"
{...props}
>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 128 136)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 144 152)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 160 72)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 160 168)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 112 120)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 128 104)"
></rect>
<rect
width="14"
height="14"
rx="1"
transform="matrix(-1 0 0 1 144 88)"
></rect>
</svg>
);
return <ChevronLeftIcon />;
}
return (
<svg
viewBox="0 0 256 256"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
strokeWidth="0.25"
color=""
className={cn("size-4 shrink-0", className)}
aria-label="chevron-right"
{...props}
>
<rect x="128" y="136" width="14" height="14" rx="1"></rect>
<rect x="112" y="152" width="14" height="14" rx="1"></rect>
<rect x="96" y="72" width="14" height="14" rx="1"></rect>
<rect x="96" y="168" width="14" height="14" rx="1"></rect>
<rect x="144" y="120" width="14" height="14" rx="1"></rect>
<rect x="128" y="104" width="14" height="14" rx="1"></rect>
<rect x="112" y="88" width="14" height="14" rx="1"></rect>
</svg>
);
return <ChevronRightIcon />;
},
Chevron: ({ className, ...props }) => {
if (props.orientation === "left") {
return (
<span className={cn(className, "[&>svg]:size-4")} aria-hidden="true">
<ChevronLeftIcon />
</span>
);
}
return (
<span className={cn(className, "[&>svg]:size-4")} aria-hidden="true">
<ChevronRightIcon />
</span>
);
},

Comment on lines +81 to 82
{children ?? <ChevronRightIcon />}
</li>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Force separator size deterministically to avoid Tailwind specificity clashes

The list item sets "[&>svg]:size-3.5", but the asset’s SVG carries "size-7". Depending on generation order, either could win. Make it deterministic at the render site:

-      {children ?? <ChevronRightIcon />}
+      {children ?? (
+        <span className="[&>svg]:!size-3.5">
+          <ChevronRightIcon />
+        </span>
+      )}
  • Uses !important to ensure the breadcrumb’s 3.5 sizing wins locally.
  • Keeps the asset reusable elsewhere at a different size.

Longer-term, consider making the asset size-agnostic (accept className/props) to avoid wrappers.

📝 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.

Suggested change
{children ?? <ChevronRightIcon />}
</li>
{children ?? (
<span className="[&>svg]:!size-3.5">
<ChevronRightIcon />
</span>
)}
</li>
🤖 Prompt for AI Agents
In components/ui/breadcrumb.tsx around lines 81 to 82, the breadcrumb wrapper
sets "[&>svg]:size-3.5" but the passed SVG has "size-7" which can win due to
Tailwind specificity; update the render so the breadcrumb forces the smaller
size locally by applying Tailwind's important variant to the svg-sizing rule
(e.g. use "[&>svg]:!size-3.5" or render the fallback icon with a class that
includes "!size-3.5") so the breadcrumb always enforces 3.5 while keeping the
asset reusable elsewhere.

Comment on lines +10 to +11
import { ChevronRightIcon } from "@/components/ui/8bit/assets/chevronRightIcon";

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Move to local 8‑bit chevron asset — LGTM; scan for any remaining lucide chevrons

The import change aligns with the refactor goal.

Run this quick scan to ensure we didn’t miss any lucide chevron imports:


🏁 Script executed:

#!/bin/bash
# Find any remaining lucide chevron usages
rg -n "(import\\s*\\{[^}]*Chevron(Left|Right)[^}]*\\}\\s*from\\s*['\"]lucide-react['\"])|(<Chevron(Left|Right)\\b)" -S

Length of output: 118


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search: direct lucide-react imports =="
rg -n "from\s+['\"]lucide-react['\"]" -S || true

echo
echo "== Search: import lines mentioning ChevronLeft/ChevronRight =="
rg -n "import.*Chevron(Left|Right)" -S || true

echo
echo "== Search: JSX usage of <ChevronLeft or <ChevronRight =="
rg -n "<Chevron(Left|Right)\\b" -S || true

echo
echo "== Search: any identifier or filename containing 'chevron' (case-insensitive) =="
rg -n -i "chevron" -S || true

echo
echo "== Search: any usage of 'lucide' (case-insensitive) =="
rg -n -i "lucide" -S || true

Length of output: 148845


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== lucide-react imports that mention 'Chevron' =="
rg -n "from\s+['\"]lucide-react['\"].*Chevron" -S || true

echo
echo "== All import lines that mention 'Chevron' (local or external) =="
rg -n "import.*Chevron" -S || true

Length of output: 43339


Move to local 8‑bit chevron asset — LGTM, but repo still contains lucide chevrons

The change in components/ui/dropdown-menu.tsx is correct. I scanned the repo and found these remaining lucide chevron imports that should be reviewed/replaced if the goal is complete migration:

  • components/ui/accordion.tsx — import { ChevronDown } from "lucide-react";
  • components/ui/calendar.tsx — import { ChevronDownIcon } from "lucide-react";
  • components/ui/navigation-menu.tsx — import { ChevronDownIcon } from "lucide-react";
  • components/ui/select.tsx — import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
  • components/examples/combobox.tsx — import { ChevronsUpDown } from "lucide-react";
  • app/docs/components/combo-box/page.tsx — import { ChevronsUpDown } from "lucide-react";
  • components/version-switcher.tsx — import { Check, ChevronsUpDown, GalleryVerticalEnd } from "lucide-react";

Also note generated/public files under public/r/** contain lucide references (if those are regenerated from sources, update the source components).

Please replace these imports with the 8‑bit assets (or confirm they should remain) and re-run the scan.

🤖 Prompt for AI Agents
In components/ui/dropdown-menu.tsx around lines 10-11 and in the other listed
files (components/ui/accordion.tsx, components/ui/calendar.tsx,
components/ui/navigation-menu.tsx, components/ui/select.tsx,
components/examples/combobox.tsx, app/docs/components/combo-box/page.tsx,
components/version-switcher.tsx) replace lucide-react icon imports with the
local 8‑bit icon assets (e.g., import from the project 8‑bit assets module under
components/ui/8bit/assets), update any icon names/usages to match the 8‑bit
exports, ensure type/props compatibility, and then regenerate any public assets
under public/r/** from their sources so they no longer reference lucide; finally
re-run the repo scan to confirm all lucide imports have been removed or
intentionally retained.

Comment on lines 222 to 224
{children}
<ChevronRightIcon className="ml-auto size-4" />
<ChevronRightIcon />
</DropdownMenuPrimitive.SubTrigger>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Sub trigger chevron lost alignment/sizing (ml-auto, size) — reintroduce layout constraints

Previously the chevron sat at the far right (ml-auto) and matched menu icon sizing (size-4). The asset ships with size-7, so the icon is now larger and no longer right-aligned.

Apply a local wrapper to restore layout and avoid changing the asset’s signature:

       {children}
-      <ChevronRightIcon />
+      <span className="ml-auto [&>svg]:size-4" aria-hidden="true">
+        <ChevronRightIcon />
+      </span>
  • Keeps layout consistent without modifying the asset.
  • Hides the decorative icon from AT since the trigger itself is descriptive.

Visually verify the right alignment of submenu chevrons in all dropdown variants after this change.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate dropdown-menu.tsx..."
file=$(fd -H -t f -I "dropdown-menu.tsx" || true)

if [ -z "$file" ]; then
  echo "Not found by filename. Searching for 'DropdownMenuPrimitive.SubTrigger'..."
  file=$(rg --hidden --glob '!*node_modules*' -n "DropdownMenuPrimitive.SubTrigger" -S | sed -n '1p' | cut -d: -f1 || true)
fi

if [ -z "$file" ]; then
  echo "Still not found. Searching for 'components/ui/dropdown-menu' path references..."
  file=$(rg --hidden --glob '!*node_modules*' -n "components/ui/dropdown-menu" -S | sed -n '1p' | cut -d: -f1 || true)
fi

if [ -z "$file" ]; then
  echo "Could not locate dropdown-menu file in the repository."
  exit 0
fi

echo "Found file: $file"
echo "---- Showing file with line numbers (first 400 lines) ----"
nl -ba "$file" | sed -n '1,400p'

echo
echo "---- Searching for ChevronRightIcon usages project-wide ----"
rg --hidden --glob '!*node_modules*' -n "ChevronRightIcon" -S || true

Length of output: 937


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locating dropdown-menu.tsx files..."
mapfile -t files < <(fd -H -t f -I "dropdown-menu.tsx" || true)

if [ ${#files[@]} -eq 0 ]; then
  echo "No dropdown-menu.tsx files found."
  exit 0
fi

for f in "${files[@]}"; do
  echo
  echo "---- FILE: $f ----"
  if [ -f "$f" ]; then
    echo "---- Showing lines 200-240 ----"
    awk 'NR>=200 && NR<=240{printf("%4d: %s\n", NR,$0)}' "$f" || true
    echo
    echo "---- Searching within this file for relevant tokens ----"
    rg --hidden --glob '!*node_modules*' -n -S "ChevronRightIcon|DropdownMenuPrimitive.SubTrigger" "$f" || true
  else
    echo "File not found: $f"
  fi
done

echo
echo "---- Global search for ChevronRightIcon (all files) ----"
rg --hidden --glob '!*node_modules*' -n -S "ChevronRightIcon" || true

Length of output: 263


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Searching for dropdown-menu.tsx files..."
find . -type f -name 'dropdown-menu.tsx' -print > /tmp/dropdown_files.txt 2>/dev/null || true

if [ ! -s /tmp/dropdown_files.txt ]; then
  echo "No dropdown-menu.tsx files found."
  exit 0
fi

while IFS= read -r f; do
  echo
  echo "---- FILE: $f ----"
  if [ -f "$f" ]; then
    echo "---- Showing lines 210-230 ----"
    awk 'NR>=210 && NR<=230{printf("%4d: %s\n", NR,$0)}' "$f" || true
    echo
    echo "---- Showing lines 1-40 (file header/imports) ----"
    awk 'NR>=1 && NR<=40{printf("%4d: %s\n", NR,$0)}' "$f" || true
    echo
    echo "---- Searching this file for relevant tokens ----"
    rg -n --hidden --glob '!*node_modules*' "ChevronRightIcon|DropdownMenuPrimitive.SubTrigger|SubTrigger|SubContent" "$f" || true
  else
    echo "File not found: $f"
  fi
done < /tmp/dropdown_files.txt

echo
echo "---- Global search for ChevronRightIcon occurrences ----"
rg -n --hidden --glob '!*node_modules*' -S "ChevronRightIcon" || true

Length of output: 49273


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- Showing asset: components/ui/8bit/assets/chevronRightIcon.tsx ----"
if [ -f "components/ui/8bit/assets/chevronRightIcon.tsx" ]; then
  awk 'NR<=200{printf("%4d: %s\n", NR,$0)}' components/ui/8bit/assets/chevronRightIcon.tsx || true
else
  echo "File not found: components/ui/8bit/assets/chevronRightIcon.tsx"
fi

echo
echo "---- Showing dropdown SubTrigger in components/ui/dropdown-menu.tsx (lines ~200-232) ----"
if [ -f "components/ui/dropdown-menu.tsx" ]; then
  awk 'NR>=200 && NR<=232{printf("%4d: %s\n", NR,$0)}' components/ui/dropdown-menu.tsx || true
else
  echo "File not found: components/ui/dropdown-menu.tsx"
fi

echo
echo "---- Search repo for '[&>svg]' patterns and 'size-' usages near them ----"
rg -n --hidden --glob '!*node_modules*' '\[&>svg\]' -S || true
rg -n --hidden --glob '!*node_modules*' '\bsize-[0-9]+' -S || true

echo
echo "---- All occurrences of ChevronRightIcon (files + line numbers) ----"
rg -n --hidden --glob '!*node_modules*' 'ChevronRightIcon' -S || true

Length of output: 270242


Restore right-aligned, correctly-sized chevron in SubTrigger

Confirmed: ChevronRightIcon (components/ui/8bit/assets/chevronRightIcon.tsx) ships with class "size-7", and DropdownMenuSubTrigger renders it without layout/sizing overrides — causing an oversized, left-positioned chevron. Wrap locally to restore alignment and size.

Files to change

  • components/ui/dropdown-menu.tsx — DropdownMenuSubTrigger (around lines ~213–224)

Suggested change (apply locally so the asset signature stays untouched):

       {children}
-      <ChevronRightIcon />
+      <span className="ml-auto [&>svg]:size-4" aria-hidden="true">
+        <ChevronRightIcon />
+      </span>
     </DropdownMenuPrimitive.SubTrigger>
  • Keeps the chevron right-aligned (ml-auto) and forces the smaller size (size-4) without modifying the asset.
  • Hides the decorative icon from assistive tech (aria-hidden) since the trigger text is the meaningful label.

Please apply and visually verify chevron alignment/sizing across dropdown variants (including 8bit wrappers / menubar/context-menu where applicable).

📝 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.

Suggested change
{children}
<ChevronRightIcon className="ml-auto size-4" />
<ChevronRightIcon />
</DropdownMenuPrimitive.SubTrigger>
{children}
<span className="ml-auto [&>svg]:size-4" aria-hidden="true">
<ChevronRightIcon />
</span>
</DropdownMenuPrimitive.SubTrigger>

{
"path": "components/ui/8bit/breadcrumb.tsx",
"content": "import { Slot } from \"@radix-ui/react-slot\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport { MoreHorizontal } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport {\n Breadcrumb as ShadcnBreadcrumb,\n BreadcrumbEllipsis as ShadcnBreadcrumbEllipsis,\n BreadcrumbItem as ShadcnBreadcrumbItem,\n BreadcrumbList as ShadcnBreadcrumbList,\n BreadcrumbPage as ShadcnBreadcrumbPage,\n BreadcrumbSeparator as ShadcnBreadcrumbSeparator,\n} from \"@/components/ui/breadcrumb\";\n\nimport \"./styles/retro.css\";\n\nexport const breadcrumbVariants = cva(\"\", {\n variants: {\n font: {\n normal: \"\",\n retro: \"retro\",\n },\n variant: {\n default: \"text-card-foreground\",\n destructive:\n \"text-destructive [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n});\n\ninterface BitBreadcrumbNavigationProps\n extends React.ComponentProps<\"nav\">,\n VariantProps<typeof breadcrumbVariants> {}\n\ninterface BitBreadcrumbOrderedListProps\n extends React.ComponentProps<\"ol\">,\n VariantProps<typeof breadcrumbVariants> {}\n\ninterface BitBreadcrumbSpanProps\n extends React.ComponentProps<\"span\">,\n VariantProps<typeof breadcrumbVariants> {}\n\ninterface BitBreadcrumbListItemProps\n extends React.ComponentProps<\"li\">,\n VariantProps<typeof breadcrumbVariants> {}\n\ninterface BitBreadcrumbLinkProps\n extends React.ComponentProps<\"a\">,\n VariantProps<typeof breadcrumbVariants> {}\n\nconst ChevronRight = () => {\n return (\n <svg\n width=\"50\"\n height=\"50\"\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n xmlns=\"http://www.w3.org/2000/svg\"\n stroke=\"currentColor\"\n strokeWidth=\"0.25\"\n color=\"\"\n className=\"size-7\"\n aria-label=\"chevron-right\"\n >\n <rect x=\"128\" y=\"136\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"112\" y=\"152\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"96\" y=\"72\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"96\" y=\"168\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"144\" y=\"120\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"128\" y=\"104\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"112\" y=\"88\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n </svg>\n );\n};\n\nfunction Breadcrumb({ children, ...props }: BitBreadcrumbNavigationProps) {\n const { variant, className, font } = props;\n\n return (\n <div\n className={cn(\n \"mb-4 flex items-center space-x-1 text-sm leading-none text-muted-foreground\",\n className\n )}\n >\n <ShadcnBreadcrumb\n {...props}\n className={cn(\n \"relative rounded-none border-none bg-background\",\n breadcrumbVariants({ variant }),\n font !== \"normal\" && \"retro\",\n className\n )}\n >\n {children}\n </ShadcnBreadcrumb>\n </div>\n );\n}\n\nfunction BreadcrumbList({ ...props }: BitBreadcrumbOrderedListProps) {\n const { font, className } = props;\n\n return (\n <ShadcnBreadcrumbList\n className={cn(className, font !== \"normal\" && \"retro\")}\n {...props}\n />\n );\n}\n\nfunction BreadcrumbItem({ ...props }: BitBreadcrumbListItemProps) {\n const { font, className } = props;\n\n return (\n <ShadcnBreadcrumbItem\n className={cn(className, font !== \"normal\" && \"retro\")}\n {...props}\n />\n );\n}\n\nfunction BreadcrumbLink({\n asChild,\n ...props\n}: BitBreadcrumbLinkProps & {\n asChild?: boolean;\n}) {\n const { font, className } = props;\n\n const Comp = asChild ? Slot : \"a\";\n\n return (\n <Comp\n data-slot=\"breadcrumb-link\"\n className={cn(className, font !== \"normal\" && \"retro\")}\n {...props}\n />\n );\n}\n\nfunction BreadcrumbPage({ ...props }: BitBreadcrumbSpanProps) {\n const { font, className } = props;\n\n return (\n <ShadcnBreadcrumbPage\n className={cn(className, font !== \"normal\" && \"retro\")}\n {...props}\n />\n );\n}\n\nfunction BreadcrumbSeparator({ ...props }: BitBreadcrumbListItemProps) {\n const { font, children, className } = props;\n\n return (\n <ShadcnBreadcrumbSeparator\n className={cn(className, font !== \"normal\" && \"retro\", \"[&>svg]:size-7\")}\n {...props}\n >\n {children ?? <ChevronRight />}\n </ShadcnBreadcrumbSeparator>\n );\n}\n\nfunction BreadcrumbEllipsis({ ...props }: BitBreadcrumbSpanProps) {\n const { font, className } = props;\n\n return (\n <ShadcnBreadcrumbEllipsis\n className={cn(className, font !== \"normal\" && \"retro\")}\n {...props}\n >\n <MoreHorizontal className={cn(\"size-7\", \"retro\")} />\n <span className=\"sr-only\">More</span>\n </ShadcnBreadcrumbEllipsis>\n );\n}\n\nexport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n BreadcrumbEllipsis,\n};\n",
"content": "import { Slot } from \"@radix-ui/react-slot\";\r\nimport { type VariantProps, cva } from \"class-variance-authority\";\r\nimport { MoreHorizontal } from \"lucide-react\";\r\n\r\nimport { ChevronRightIcon } from \"@/components/ui/8bit/assets/chevronRightIcon\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n Breadcrumb as ShadcnBreadcrumb,\r\n BreadcrumbEllipsis as ShadcnBreadcrumbEllipsis,\r\n BreadcrumbItem as ShadcnBreadcrumbItem,\r\n BreadcrumbList as ShadcnBreadcrumbList,\r\n BreadcrumbPage as ShadcnBreadcrumbPage,\r\n BreadcrumbSeparator as ShadcnBreadcrumbSeparator,\r\n} from \"@/components/ui/breadcrumb\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport const breadcrumbVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n variant: {\r\n default: \"text-card-foreground\",\r\n destructive:\r\n \"text-destructive [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n});\r\n\r\ninterface BitBreadcrumbNavigationProps\r\n extends React.ComponentProps<\"nav\">,\r\n VariantProps<typeof breadcrumbVariants> {}\r\n\r\ninterface BitBreadcrumbOrderedListProps\r\n extends React.ComponentProps<\"ol\">,\r\n VariantProps<typeof breadcrumbVariants> {}\r\n\r\ninterface BitBreadcrumbSpanProps\r\n extends React.ComponentProps<\"span\">,\r\n VariantProps<typeof breadcrumbVariants> {}\r\n\r\ninterface BitBreadcrumbListItemProps\r\n extends React.ComponentProps<\"li\">,\r\n VariantProps<typeof breadcrumbVariants> {}\r\n\r\ninterface BitBreadcrumbLinkProps\r\n extends React.ComponentProps<\"a\">,\r\n VariantProps<typeof breadcrumbVariants> {}\r\n\r\nfunction Breadcrumb({ children, ...props }: BitBreadcrumbNavigationProps) {\r\n const { variant, className, font } = props;\r\n\r\n return (\r\n <div\r\n className={cn(\r\n \"mb-4 flex items-center space-x-1 text-sm leading-none text-muted-foreground\",\r\n className\r\n )}\r\n >\r\n <ShadcnBreadcrumb\r\n {...props}\r\n className={cn(\r\n \"relative rounded-none border-none bg-background\",\r\n breadcrumbVariants({ variant }),\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n >\r\n {children}\r\n </ShadcnBreadcrumb>\r\n </div>\r\n );\r\n}\r\n\r\nfunction BreadcrumbList({ ...props }: BitBreadcrumbOrderedListProps) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <ShadcnBreadcrumbList\r\n className={cn(className, font !== \"normal\" && \"retro\")}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction BreadcrumbItem({ ...props }: BitBreadcrumbListItemProps) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <ShadcnBreadcrumbItem\r\n className={cn(className, font !== \"normal\" && \"retro\")}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction BreadcrumbLink({\r\n asChild,\r\n ...props\r\n}: BitBreadcrumbLinkProps & {\r\n asChild?: boolean;\r\n}) {\r\n const { font, className } = props;\r\n\r\n const Comp = asChild ? Slot : \"a\";\r\n\r\n return (\r\n <Comp\r\n data-slot=\"breadcrumb-link\"\r\n className={cn(className, font !== \"normal\" && \"retro\")}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction BreadcrumbPage({ ...props }: BitBreadcrumbSpanProps) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <ShadcnBreadcrumbPage\r\n className={cn(className, font !== \"normal\" && \"retro\")}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction BreadcrumbSeparator({ ...props }: BitBreadcrumbListItemProps) {\r\n const { font, children, className } = props;\r\n\r\n return (\r\n <ShadcnBreadcrumbSeparator\r\n className={cn(className, font !== \"normal\" && \"retro\", \"[&>svg]:size-7\")}\r\n {...props}\r\n >\r\n {children ?? <ChevronRightIcon/>}\r\n </ShadcnBreadcrumbSeparator>\r\n );\r\n}\r\n\r\nfunction BreadcrumbEllipsis({ ...props }: BitBreadcrumbSpanProps) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <ShadcnBreadcrumbEllipsis\r\n className={cn(className, font !== \"normal\" && \"retro\")}\r\n {...props}\r\n >\r\n <MoreHorizontal className={cn(\"size-7\", \"retro\")} />\r\n <span className=\"sr-only\">More</span>\r\n </ShadcnBreadcrumbEllipsis>\r\n );\r\n}\r\n\r\nexport {\r\n Breadcrumb,\r\n BreadcrumbList,\r\n BreadcrumbItem,\r\n BreadcrumbLink,\r\n BreadcrumbPage,\r\n BreadcrumbSeparator,\r\n BreadcrumbEllipsis,\r\n};\r\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Decorative separator icon should be aria-hidden

The separator chevron is purely decorative. With the current asset having an aria-label, this can pollute the accessible name. Hide it from assistive tech (and consider removing aria-label from the asset).

Apply in components/ui/8bit/breadcrumb.tsx:

-      {children ?? <ChevronRightIcon/>}
+      {children ?? <ChevronRightIcon aria-hidden="true" focusable="false" />}

Additionally, consider updating the icon assets to forward props and default to aria-hidden; see asset suggestion in my Calendar comment.

📝 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.

Suggested change
"content": "import { Slot } from \"@radix-ui/react-slot\";\r\nimport { type VariantProps, cva } from \"class-variance-authority\";\r\nimport { MoreHorizontal } from \"lucide-react\";\r\n\r\nimport { ChevronRightIcon } from \"@/components/ui/8bit/assets/chevronRightIcon\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n Breadcrumb as ShadcnBreadcrumb,\r\n BreadcrumbEllipsis as ShadcnBreadcrumbEllipsis,\r\n BreadcrumbItem as ShadcnBreadcrumbItem,\r\n BreadcrumbList as ShadcnBreadcrumbList,\r\n BreadcrumbPage as ShadcnBreadcrumbPage,\r\n BreadcrumbSeparator as ShadcnBreadcrumbSeparator,\r\n} from \"@/components/ui/breadcrumb\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nexport const breadcrumbVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n variant: {\r\n default: \"text-card-foreground\",\r\n destructive:\r\n \"text-destructive [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n});\r\n\r\ninterface BitBreadcrumbNavigationProps\r\n extends React.ComponentProps<\"nav\">,\r\n VariantProps<typeof breadcrumbVariants> {}\r\n\r\ninterface BitBreadcrumbOrderedListProps\r\n extends React.ComponentProps<\"ol\">,\r\n VariantProps<typeof breadcrumbVariants> {}\r\n\r\ninterface BitBreadcrumbSpanProps\r\n extends React.ComponentProps<\"span\">,\r\n VariantProps<typeof breadcrumbVariants> {}\r\n\r\ninterface BitBreadcrumbListItemProps\r\n extends React.ComponentProps<\"li\">,\r\n VariantProps<typeof breadcrumbVariants> {}\r\n\r\ninterface BitBreadcrumbLinkProps\r\n extends React.ComponentProps<\"a\">,\r\n VariantProps<typeof breadcrumbVariants> {}\r\n\r\nfunction Breadcrumb({ children, ...props }: BitBreadcrumbNavigationProps) {\r\n const { variant, className, font } = props;\r\n\r\n return (\r\n <div\r\n className={cn(\r\n \"mb-4 flex items-center space-x-1 text-sm leading-none text-muted-foreground\",\r\n className\r\n )}\r\n >\r\n <ShadcnBreadcrumb\r\n {...props}\r\n className={cn(\r\n \"relative rounded-none border-none bg-background\",\r\n breadcrumbVariants({ variant }),\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n >\r\n {children}\r\n </ShadcnBreadcrumb>\r\n </div>\r\n );\r\n}\r\n\r\nfunction BreadcrumbList({ ...props }: BitBreadcrumbOrderedListProps) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <ShadcnBreadcrumbList\r\n className={cn(className, font !== \"normal\" && \"retro\")}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction BreadcrumbItem({ ...props }: BitBreadcrumbListItemProps) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <ShadcnBreadcrumbItem\r\n className={cn(className, font !== \"normal\" && \"retro\")}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction BreadcrumbLink({\r\n asChild,\r\n ...props\r\n}: BitBreadcrumbLinkProps & {\r\n asChild?: boolean;\r\n}) {\r\n const { font, className } = props;\r\n\r\n const Comp = asChild ? Slot : \"a\";\r\n\r\n return (\r\n <Comp\r\n data-slot=\"breadcrumb-link\"\r\n className={cn(className, font !== \"normal\" && \"retro\")}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction BreadcrumbPage({ ...props }: BitBreadcrumbSpanProps) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <ShadcnBreadcrumbPage\r\n className={cn(className, font !== \"normal\" && \"retro\")}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction BreadcrumbSeparator({ ...props }: BitBreadcrumbListItemProps) {\r\n const { font, children, className } = props;\r\n\r\n return (\r\n <ShadcnBreadcrumbSeparator\r\n className={cn(className, font !== \"normal\" && \"retro\", \"[&>svg]:size-7\")}\r\n {...props}\r\n >\r\n {children ?? <ChevronRightIcon/>}\r\n </ShadcnBreadcrumbSeparator>\r\n );\r\n}\r\n\r\nfunction BreadcrumbEllipsis({ ...props }: BitBreadcrumbSpanProps) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <ShadcnBreadcrumbEllipsis\r\n className={cn(className, font !== \"normal\" && \"retro\")}\r\n {...props}\r\n >\r\n <MoreHorizontal className={cn(\"size-7\", \"retro\")} />\r\n <span className=\"sr-only\">More</span>\r\n </ShadcnBreadcrumbEllipsis>\r\n );\r\n}\r\n\r\nexport {\r\n Breadcrumb,\r\n BreadcrumbList,\r\n BreadcrumbItem,\r\n BreadcrumbLink,\r\n BreadcrumbPage,\r\n BreadcrumbSeparator,\r\n BreadcrumbEllipsis,\r\n};\r\n",
function BreadcrumbSeparator({ ...props }: BitBreadcrumbListItemProps) {
const { font, children, className } = props;
return (
<ShadcnBreadcrumbSeparator
className={cn(className, font !== "normal" && "retro", "[&>svg]:size-7")}
{...props}
>
{children ?? <ChevronRightIcon aria-hidden="true" focusable="false" />}
</ShadcnBreadcrumbSeparator>
);
}
🤖 Prompt for AI Agents
In public/r/8bit-breadcrumb.json around line 13, the separator chevron used in
BreadcrumbSeparator is decorative and should be hidden from assistive
technology; update the BreadcrumbSeparator component in
components/ui/8bit/breadcrumb.tsx to render the ChevronRightIcon with
aria-hidden="true" (and remove any aria-label on that usage), and also update
the chevron icon asset to forward props and default to aria-hidden so consumers
don't need to repeat it.

⚠️ Potential issue

Retro font applies by default when font is undefined

font !== "normal" will evaluate true when font is undefined, unintentionally applying the retro font unless font="normal" is explicitly passed. Set defaultVariants.font to "normal".

 export const breadcrumbVariants = cva("", {
   variants: {
     font: {
       normal: "",
       retro: "retro",
     },
     variant: {
       default: "text-card-foreground",
       destructive:
         "text-destructive [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
     },
   },
   defaultVariants: {
     variant: "default",
+    font: "normal",
   },
 });

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
public/r/8bit-breadcrumb.json around line 13: the breadcrumbVariants
defaultVariants currently only sets variant and leaves font undefined which
makes font !== "normal" evaluate true and unintentionally apply the retro font;
update breadcrumbVariants.defaultVariants to include font: "normal" so the retro
font only applies when font is explicitly set (i.e., add font: "normal" to the
defaultVariants object).

🛠️ Refactor suggestion

Prevent leaking design-system props (variant, font) to the DOM

variant and font (and className duplicates) are still included in {...props} and end up as invalid attributes on the DOM nodes. Extract them and pass the rest only.

Apply this refactor inside components/ui/8bit/breadcrumb.tsx:

-function Breadcrumb({ children, ...props }: BitBreadcrumbNavigationProps) {
-  const { variant, className, font } = props;
+function Breadcrumb({
+  children,
+  variant,
+  className,
+  font,
+  ...rest
+}: BitBreadcrumbNavigationProps) {
   return (
     <div
       className={cn(
         "mb-4 flex items-center space-x-1 text-sm leading-none text-muted-foreground",
         className
       )}
     >
-      <ShadcnBreadcrumb
-        {...props}
+      <ShadcnBreadcrumb
+        {...rest}
         className={cn(
           "relative rounded-none border-none bg-background",
           breadcrumbVariants({ variant }),
           font !== "normal" && "retro",
           className
         )}
       >
         {children}
       </ShadcnBreadcrumb>
     </div>
   );
 }

-function BreadcrumbList({ ...props }: BitBreadcrumbOrderedListProps) {
-  const { font, className } = props;
+function BreadcrumbList({ font, className, ...rest }: BitBreadcrumbOrderedListProps) {
   return (
     <ShadcnBreadcrumbList
       className={cn(className, font !== "normal" && "retro")}
-      {...props}
+      {...rest}
     />
   );
 }

-function BreadcrumbItem({ ...props }: BitBreadcrumbListItemProps) {
-  const { font, className } = props;
+function BreadcrumbItem({ font, className, ...rest }: BitBreadcrumbListItemProps) {
   return (
     <ShadcnBreadcrumbItem
       className={cn(className, font !== "normal" && "retro")}
-      {...props}
+      {...rest}
     />
   );
 }

 function BreadcrumbLink({
   asChild,
-  ...props
+  ...props
 }: BitBreadcrumbLinkProps & {
   asChild?: boolean;
 }) {
   const { font, className } = props;

   const Comp = asChild ? Slot : "a";

   return (
     <Comp
       data-slot="breadcrumb-link"
       className={cn(className, font !== "normal" && "retro")}
-      {...props}
+      {...props}
     />
   );
 }

-function BreadcrumbPage({ ...props }: BitBreadcrumbSpanProps) {
-  const { font, className } = props;
+function BreadcrumbPage({ font, className, ...rest }: BitBreadcrumbSpanProps) {
   return (
     <ShadcnBreadcrumbPage
       className={cn(className, font !== "normal" && "retro")}
-      {...props}
+      {...rest}
     />
   );
 }

-function BreadcrumbSeparator({ ...props }: BitBreadcrumbListItemProps) {
-  const { font, children, className } = props;
+function BreadcrumbSeparator({ font, children, className, ...rest }: BitBreadcrumbListItemProps) {
   return (
     <ShadcnBreadcrumbSeparator
       className={cn(className, font !== "normal" && "retro", "[&>svg]:size-7")}
-      {...props}
+      {...rest}
     >
       {children ?? <ChevronRightIcon/>}
     </ShadcnBreadcrumbSeparator>
   );
 }

-function BreadcrumbEllipsis({ ...props }: BitBreadcrumbSpanProps) {
-  const { font, className } = props;
+function BreadcrumbEllipsis({ font, className, ...rest }: BitBreadcrumbSpanProps) {
   return (
     <ShadcnBreadcrumbEllipsis
       className={cn(className, font !== "normal\" && \"retro")}
-      {...props}
+      {...rest}
     >
       <MoreHorizontal className={cn("size-7", "retro")} />
       <span className="sr-only">More</span>
     </ShadcnBreadcrumbEllipsis>
   );
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
public/r/8bit-breadcrumb.json lines 13-13: The components leak design-system
props (variant, font and duplicate className) into {...props} which become
invalid DOM attributes; fix by destructuring variant, font, and className (and
any other design props) from props in each component, collect the rest as
...rest, and spread only ...rest onto the underlying element (or Shadcn wrapper)
while composing className manually with cn; ensure BreadcrumbLink handles
asChild correctly by passing ...rest to Comp, and
BreadcrumbSeparator/Ellipsis/others do the same so variant/font are never
forwarded to DOM.

{
"path": "components/ui/8bit/context-menu.tsx",
"content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport * as ContextMenuPrimitive from \"@radix-ui/react-context-menu\";\nimport { ChevronRight, Circle } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport \"./styles/retro.css\";\n\nconst ContextMenu = ContextMenuPrimitive.Root;\n\nconst ContextMenuTrigger = ContextMenuPrimitive.Trigger;\n\nconst ContextMenuGroup = ContextMenuPrimitive.Group;\n\nconst ContextMenuPortal = ContextMenuPrimitive.Portal;\n\nconst ContextMenuSub = ContextMenuPrimitive.Sub;\n\nconst ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;\n\nconst ContextMenuSubTrigger = React.forwardRef<\n React.ComponentRef<typeof ContextMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <ContextMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground\",\n inset && \"pl-8\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" />\n </ContextMenuPrimitive.SubTrigger>\n));\nContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;\n\nconst ContextMenuSubContent = React.forwardRef<\n React.ComponentRef<typeof ContextMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]\",\n className\n )}\n {...props}\n />\n));\nContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;\n\nconst ContextMenuContent = React.forwardRef<\n React.ComponentRef<typeof ContextMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.Portal>\n <div className=\"relative\">\n <ContextMenuPrimitive.Content\n ref={ref}\n className={cn(\n \"z-50 max-h-[--radix-context-menu-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border-x-4 border-y-6 border-foreground dark:border-ring bg-popover p-1 text-popover-foreground animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]\",\n \"retro\",\n className\n )}\n {...props}\n />\n <div\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n </div>\n </ContextMenuPrimitive.Portal>\n));\nContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;\n\nconst ContextMenuItem = React.forwardRef<\n React.ComponentRef<typeof ContextMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <ContextMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n inset && \"pl-8\",\n className\n )}\n {...props}\n />\n));\nContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;\n\nconst ContextMenuCheckboxItem = React.forwardRef<\n React.ComponentRef<typeof ContextMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <ContextMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <svg\n width=\"50\"\n height=\"50\"\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n xmlns=\"http://www.w3.org/2000/svg\"\n stroke=\"currentColor\"\n strokeWidth=\"0.25\"\n aria-label=\"check\"\n className=\"size-9\"\n >\n <rect\n x=\"80\"\n y=\"128\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 80 128)\"\n ></rect>\n <rect\n x=\"96\"\n y=\"144\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 96 144)\"\n ></rect>\n <rect\n x=\"112\"\n y=\"160\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 112 160)\"\n ></rect>\n <rect\n x=\"128\"\n y=\"144\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 128 144)\"\n ></rect>\n <rect\n x=\"144\"\n y=\"128\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 144 128)\"\n ></rect>\n <rect\n x=\"160\"\n y=\"112\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 160 112)\"\n ></rect>\n <rect\n x=\"176\"\n y=\"96\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 176 96)\"\n ></rect>\n <rect\n x=\"192\"\n y=\"80\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 192 80)\"\n ></rect>\n </svg>\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n));\nContextMenuCheckboxItem.displayName =\n ContextMenuPrimitive.CheckboxItem.displayName;\n\nconst ContextMenuRadioItem = React.forwardRef<\n React.ComponentRef<typeof ContextMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <ContextMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <ContextMenuPrimitive.ItemIndicator>\n <Circle className=\"size-2 fill-current\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n));\nContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;\n\nconst ContextMenuLabel = React.forwardRef<\n React.ComponentRef<typeof ContextMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <ContextMenuPrimitive.Label\n ref={ref}\n className={cn(\n \"px-2 py-1.5 text-sm font-semibold text-foreground\",\n inset && \"pl-8\",\n className\n )}\n {...props}\n />\n));\nContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;\n\nconst ContextMenuSeparator = React.forwardRef<\n React.ComponentRef<typeof ContextMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <ContextMenuPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n));\nContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;\n\nconst ContextMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\n className\n )}\n {...props}\n />\n );\n};\nContextMenuShortcut.displayName = \"ContextMenuShortcut\";\n\nexport {\n ContextMenu,\n ContextMenuTrigger,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuCheckboxItem,\n ContextMenuRadioItem,\n ContextMenuLabel,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuGroup,\n ContextMenuPortal,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuRadioGroup,\n};\n",
"content": "\"use client\";\r\n\r\nimport * as React from \"react\";\r\n\r\nimport * as ContextMenuPrimitive from \"@radix-ui/react-context-menu\";\r\nimport { Circle } from \"lucide-react\";\r\n\r\nimport { ChevronRightIcon } from \"@/components/ui/8bit/assets/chevronRightIcon\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nconst ContextMenu = ContextMenuPrimitive.Root;\r\n\r\nconst ContextMenuTrigger = ContextMenuPrimitive.Trigger;\r\n\r\nconst ContextMenuGroup = ContextMenuPrimitive.Group;\r\n\r\nconst ContextMenuPortal = ContextMenuPrimitive.Portal;\r\n\r\nconst ContextMenuSub = ContextMenuPrimitive.Sub;\r\n\r\nconst ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;\r\n\r\nconst ContextMenuSubTrigger = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.SubTrigger>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, children, ...props }, ref) => (\r\n <ContextMenuPrimitive.SubTrigger\r\n ref={ref}\r\n className={cn(\r\n \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n <ChevronRightIcon/>\r\n </ContextMenuPrimitive.SubTrigger>\r\n));\r\nContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;\r\n\r\nconst ContextMenuSubContent = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.SubContent>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>\r\n>(({ className, ...props }, ref) => (\r\n <ContextMenuPrimitive.SubContent\r\n ref={ref}\r\n className={cn(\r\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;\r\n\r\nconst ContextMenuContent = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.Content>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>\r\n>(({ className, ...props }, ref) => (\r\n <ContextMenuPrimitive.Portal>\r\n <div className=\"relative\">\r\n <ContextMenuPrimitive.Content\r\n ref={ref}\r\n className={cn(\r\n \"z-50 max-h-[--radix-context-menu-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border-x-4 border-y-6 border-foreground dark:border-ring bg-popover p-1 text-popover-foreground animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]\",\r\n \"retro\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n <div\r\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n </div>\r\n </ContextMenuPrimitive.Portal>\r\n));\r\nContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;\r\n\r\nconst ContextMenuItem = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.Item>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, ...props }, ref) => (\r\n <ContextMenuPrimitive.Item\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;\r\n\r\nconst ContextMenuCheckboxItem = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.CheckboxItem>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>\r\n>(({ className, children, checked, ...props }, ref) => (\r\n <ContextMenuPrimitive.CheckboxItem\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n className\r\n )}\r\n checked={checked}\r\n {...props}\r\n >\r\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\r\n <ContextMenuPrimitive.ItemIndicator>\r\n <svg\r\n width=\"50\"\r\n height=\"50\"\r\n viewBox=\"0 0 256 256\"\r\n fill=\"currentColor\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"0.25\"\r\n aria-label=\"check\"\r\n className=\"size-9\"\r\n >\r\n <rect\r\n x=\"80\"\r\n y=\"128\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 80 128)\"\r\n ></rect>\r\n <rect\r\n x=\"96\"\r\n y=\"144\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 96 144)\"\r\n ></rect>\r\n <rect\r\n x=\"112\"\r\n y=\"160\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 112 160)\"\r\n ></rect>\r\n <rect\r\n x=\"128\"\r\n y=\"144\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 128 144)\"\r\n ></rect>\r\n <rect\r\n x=\"144\"\r\n y=\"128\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 144 128)\"\r\n ></rect>\r\n <rect\r\n x=\"160\"\r\n y=\"112\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 160 112)\"\r\n ></rect>\r\n <rect\r\n x=\"176\"\r\n y=\"96\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 176 96)\"\r\n ></rect>\r\n <rect\r\n x=\"192\"\r\n y=\"80\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 192 80)\"\r\n ></rect>\r\n </svg>\r\n </ContextMenuPrimitive.ItemIndicator>\r\n </span>\r\n {children}\r\n </ContextMenuPrimitive.CheckboxItem>\r\n));\r\nContextMenuCheckboxItem.displayName =\r\n ContextMenuPrimitive.CheckboxItem.displayName;\r\n\r\nconst ContextMenuRadioItem = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.RadioItem>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>\r\n>(({ className, children, ...props }, ref) => (\r\n <ContextMenuPrimitive.RadioItem\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\r\n <ContextMenuPrimitive.ItemIndicator>\r\n <Circle className=\"size-2 fill-current\" />\r\n </ContextMenuPrimitive.ItemIndicator>\r\n </span>\r\n {children}\r\n </ContextMenuPrimitive.RadioItem>\r\n));\r\nContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;\r\n\r\nconst ContextMenuLabel = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.Label>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, ...props }, ref) => (\r\n <ContextMenuPrimitive.Label\r\n ref={ref}\r\n className={cn(\r\n \"px-2 py-1.5 text-sm font-semibold text-foreground\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;\r\n\r\nconst ContextMenuSeparator = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.Separator>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>\r\n>(({ className, ...props }, ref) => (\r\n <ContextMenuPrimitive.Separator\r\n ref={ref}\r\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\r\n {...props}\r\n />\r\n));\r\nContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;\r\n\r\nconst ContextMenuShortcut = ({\r\n className,\r\n ...props\r\n}: React.HTMLAttributes<HTMLSpanElement>) => {\r\n return (\r\n <span\r\n className={cn(\r\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n );\r\n};\r\nContextMenuShortcut.displayName = \"ContextMenuShortcut\";\r\n\r\nexport {\r\n ContextMenu,\r\n ContextMenuTrigger,\r\n ContextMenuContent,\r\n ContextMenuItem,\r\n ContextMenuCheckboxItem,\r\n ContextMenuRadioItem,\r\n ContextMenuLabel,\r\n ContextMenuSeparator,\r\n ContextMenuShortcut,\r\n ContextMenuGroup,\r\n ContextMenuPortal,\r\n ContextMenuSub,\r\n ContextMenuSubContent,\r\n ContextMenuSubTrigger,\r\n ContextMenuRadioGroup,\r\n};\r\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Chevron alignment likely regressed; restore right alignment and improve a11y.

ContextMenuSubTrigger now renders <ChevronRightIcon /> without ml-auto. Previously, the lucide icon used ml-auto to push the chevron to the far right. As-is, the icon will sit directly after the label, which is a behavioral/visual change. Also, the icon should be decorative for screen readers.

Suggested fix (doesn’t require changing the icon component API):

-    {children}
-    <ChevronRightIcon/>
+    {children}
+    <span className="ml-auto">
+      <ChevronRightIcon aria-hidden="true" />
+    </span>

If you prefer passing classes directly to the icon, make the icon accept className and then use className="ml-auto size-4 shrink-0 opacity-70" here.

📝 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.

Suggested change
"content": "\"use client\";\r\n\r\nimport * as React from \"react\";\r\n\r\nimport * as ContextMenuPrimitive from \"@radix-ui/react-context-menu\";\r\nimport { Circle } from \"lucide-react\";\r\n\r\nimport { ChevronRightIcon } from \"@/components/ui/8bit/assets/chevronRightIcon\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport \"./styles/retro.css\";\r\n\r\nconst ContextMenu = ContextMenuPrimitive.Root;\r\n\r\nconst ContextMenuTrigger = ContextMenuPrimitive.Trigger;\r\n\r\nconst ContextMenuGroup = ContextMenuPrimitive.Group;\r\n\r\nconst ContextMenuPortal = ContextMenuPrimitive.Portal;\r\n\r\nconst ContextMenuSub = ContextMenuPrimitive.Sub;\r\n\r\nconst ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;\r\n\r\nconst ContextMenuSubTrigger = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.SubTrigger>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, children, ...props }, ref) => (\r\n <ContextMenuPrimitive.SubTrigger\r\n ref={ref}\r\n className={cn(\r\n \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n <ChevronRightIcon/>\r\n </ContextMenuPrimitive.SubTrigger>\r\n));\r\nContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;\r\n\r\nconst ContextMenuSubContent = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.SubContent>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>\r\n>(({ className, ...props }, ref) => (\r\n <ContextMenuPrimitive.SubContent\r\n ref={ref}\r\n className={cn(\r\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;\r\n\r\nconst ContextMenuContent = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.Content>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>\r\n>(({ className, ...props }, ref) => (\r\n <ContextMenuPrimitive.Portal>\r\n <div className=\"relative\">\r\n <ContextMenuPrimitive.Content\r\n ref={ref}\r\n className={cn(\r\n \"z-50 max-h-[--radix-context-menu-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border-x-4 border-y-6 border-foreground dark:border-ring bg-popover p-1 text-popover-foreground animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]\",\r\n \"retro\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n <div\r\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n </div>\r\n </ContextMenuPrimitive.Portal>\r\n));\r\nContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;\r\n\r\nconst ContextMenuItem = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.Item>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, ...props }, ref) => (\r\n <ContextMenuPrimitive.Item\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;\r\n\r\nconst ContextMenuCheckboxItem = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.CheckboxItem>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>\r\n>(({ className, children, checked, ...props }, ref) => (\r\n <ContextMenuPrimitive.CheckboxItem\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n className\r\n )}\r\n checked={checked}\r\n {...props}\r\n >\r\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\r\n <ContextMenuPrimitive.ItemIndicator>\r\n <svg\r\n width=\"50\"\r\n height=\"50\"\r\n viewBox=\"0 0 256 256\"\r\n fill=\"currentColor\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"0.25\"\r\n aria-label=\"check\"\r\n className=\"size-9\"\r\n >\r\n <rect\r\n x=\"80\"\r\n y=\"128\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 80 128)\"\r\n ></rect>\r\n <rect\r\n x=\"96\"\r\n y=\"144\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 96 144)\"\r\n ></rect>\r\n <rect\r\n x=\"112\"\r\n y=\"160\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 112 160)\"\r\n ></rect>\r\n <rect\r\n x=\"128\"\r\n y=\"144\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 128 144)\"\r\n ></rect>\r\n <rect\r\n x=\"144\"\r\n y=\"128\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 144 128)\"\r\n ></rect>\r\n <rect\r\n x=\"160\"\r\n y=\"112\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 160 112)\"\r\n ></rect>\r\n <rect\r\n x=\"176\"\r\n y=\"96\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 176 96)\"\r\n ></rect>\r\n <rect\r\n x=\"192\"\r\n y=\"80\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 192 80)\"\r\n ></rect>\r\n </svg>\r\n </ContextMenuPrimitive.ItemIndicator>\r\n </span>\r\n {children}\r\n </ContextMenuPrimitive.CheckboxItem>\r\n));\r\nContextMenuCheckboxItem.displayName =\r\n ContextMenuPrimitive.CheckboxItem.displayName;\r\n\r\nconst ContextMenuRadioItem = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.RadioItem>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>\r\n>(({ className, children, ...props }, ref) => (\r\n <ContextMenuPrimitive.RadioItem\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\r\n <ContextMenuPrimitive.ItemIndicator>\r\n <Circle className=\"size-2 fill-current\" />\r\n </ContextMenuPrimitive.ItemIndicator>\r\n </span>\r\n {children}\r\n </ContextMenuPrimitive.RadioItem>\r\n));\r\nContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;\r\n\r\nconst ContextMenuLabel = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.Label>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, ...props }, ref) => (\r\n <ContextMenuPrimitive.Label\r\n ref={ref}\r\n className={cn(\r\n \"px-2 py-1.5 text-sm font-semibold text-foreground\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;\r\n\r\nconst ContextMenuSeparator = React.forwardRef<\r\n React.ComponentRef<typeof ContextMenuPrimitive.Separator>,\r\n React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>\r\n>(({ className, ...props }, ref) => (\r\n <ContextMenuPrimitive.Separator\r\n ref={ref}\r\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\r\n {...props}\r\n />\r\n));\r\nContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;\r\n\r\nconst ContextMenuShortcut = ({\r\n className,\r\n ...props\r\n}: React.HTMLAttributes<HTMLSpanElement>) => {\r\n return (\r\n <span\r\n className={cn(\r\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n );\r\n};\r\nContextMenuShortcut.displayName = \"ContextMenuShortcut\";\r\n\r\nexport {\r\n ContextMenu,\r\n ContextMenuTrigger,\r\n ContextMenuContent,\r\n ContextMenuItem,\r\n ContextMenuCheckboxItem,\r\n ContextMenuRadioItem,\r\n ContextMenuLabel,\r\n ContextMenuSeparator,\r\n ContextMenuShortcut,\r\n ContextMenuGroup,\r\n ContextMenuPortal,\r\n ContextMenuSub,\r\n ContextMenuSubContent,\r\n ContextMenuSubTrigger,\r\n ContextMenuRadioGroup,\r\n};\r\n",
const ContextMenuSubTrigger = React.forwardRef<
React.ComponentRef<typeof ContextMenuPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {
inset?: boolean;
}
>(({ className, inset, children, ...props }, ref) => (
<ContextMenuPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:border-y-4 focus:border-foreground h-8 focus:dark:border-ring border-dashed focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
inset && "pl-8",
className
)}
{...props}
>
{children}
<span className="ml-auto">
<ChevronRightIcon aria-hidden="true" />
</span>
</ContextMenuPrimitive.SubTrigger>
));
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
🤖 Prompt for AI Agents
In public/r/8bit-context-menu.json around line 11, ContextMenuSubTrigger
currently renders <ChevronRightIcon/> without alignment classes or accessibility
attributes; restore the previous right alignment and mark the icon as decorative
by passing a className (e.g. "ml-auto size-4 shrink-0 opacity-70") to push it to
the far right and set it as aria-hidden. If ChevronRightIcon doesn't accept
className/props, update that icon component to accept and apply a className prop
and support aria-hidden so you can pass both className and aria-hidden="true"
from ContextMenuSubTrigger.

{
"path": "components/ui/8bit/menubar.tsx",
"content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport * as MenubarPrimitive from \"@radix-ui/react-menubar\";\nimport { cva } from \"class-variance-authority\";\nimport { Circle } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport \"./styles/retro.css\";\n\nexport const menubarVariants = cva(\"\", {\n variants: {\n font: {\n normal: \"\",\n retro: \"retro\",\n },\n },\n defaultVariants: {\n font: \"retro\",\n },\n});\n\nfunction MenubarMenu({\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Menu>) {\n return <MenubarPrimitive.Menu {...props} />;\n}\n\nfunction MenubarGroup({\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Group>) {\n return <MenubarPrimitive.Group {...props} />;\n}\n\nfunction MenubarPortal({\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Portal>) {\n return <MenubarPrimitive.Portal {...props} />;\n}\n\nfunction MenubarRadioGroup({\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {\n return <MenubarPrimitive.RadioGroup {...props} />;\n}\n\nfunction MenubarSub({\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Sub>) {\n return <MenubarPrimitive.Sub data-slot=\"menubar-sub\" {...props} />;\n}\n\nconst Menubar = React.forwardRef<\n React.ComponentRef<typeof MenubarPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <div\n className={cn(\n \"relative border-y-6 border-foreground dark:border-ring !p-0\",\n menubarVariants({ font: \"retro\" }),\n className\n )}\n >\n <MenubarPrimitive.Root\n ref={ref}\n className={cn(\n \"flex h-10 items-center space-x-1 rounded-md border bg-background p-1\",\n className\n )}\n {...props}\n />\n <div\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n </div>\n));\nMenubar.displayName = MenubarPrimitive.Root.displayName;\n\nconst MenubarTrigger = React.forwardRef<\n React.ComponentRef<typeof MenubarPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[state=open]:border-b-4 data-[state=open]:border-foreground data-[state=open]:dark:border-ring data-[state=open]:text-accent-foreground data-[state=open]:border-dashed border-b-4 border-transparent pt-2\",\n className\n )}\n {...props}\n />\n));\nMenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;\n\nconst MenubarSubTrigger = React.forwardRef<\n React.ComponentRef<typeof MenubarPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <MenubarPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none h-10 focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[state=open]:border-y-4 data-[state=open]:border-foreground data-[state=open]:dark:border-ring data-[state=open]:text-accent-foreground data-[state=open]:border-dashed\",\n inset && \"pl-8\",\n className\n )}\n {...props}\n >\n {children}\n <svg\n width=\"50\"\n height=\"50\"\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n xmlns=\"http://www.w3.org/2000/svg\"\n stroke=\"currentColor\"\n strokeWidth=\"0.25\"\n aria-label=\"chevron-right\"\n className=\"size-7 ml-auto\"\n >\n <rect x=\"128\" y=\"136\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"112\" y=\"152\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"96\" y=\"72\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"96\" y=\"168\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"144\" y=\"120\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"128\" y=\"104\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"112\" y=\"88\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n </svg>\n </MenubarPrimitive.SubTrigger>\n));\nMenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;\n\nconst MenubarSubContent = React.forwardRef<\n React.ComponentRef<typeof MenubarPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.SubContent\n ref={ref}\n className={cn(\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border-6 border-foreground dark:border-ring bg-popover p-1 text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]\",\n className\n )}\n {...props}\n />\n));\nMenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;\n\nconst MenubarContent = React.forwardRef<\n React.ComponentRef<typeof MenubarPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>\n>(\n (\n { className, align = \"start\", alignOffset = -4, sideOffset = 8, ...props },\n ref\n ) => (\n <MenubarPrimitive.Portal>\n <MenubarPrimitive.Content\n ref={ref}\n align={align}\n alignOffset={alignOffset}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 min-w-[12rem] overflow-hidden rounded-md border-6 mt-1 border-foreground dark:border-ring bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]\",\n menubarVariants({ font: \"retro\" }),\n className\n )}\n {...props}\n />\n </MenubarPrimitive.Portal>\n )\n);\nMenubarContent.displayName = MenubarPrimitive.Content.displayName;\n\nconst MenubarItem = React.forwardRef<\n React.ComponentRef<typeof MenubarPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <MenubarPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:border-y-4 focus:border-foreground focus:dark:border-ring h-9 focus:border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n inset && \"pl-8\",\n className\n )}\n {...props}\n />\n));\nMenubarItem.displayName = MenubarPrimitive.Item.displayName;\n\nconst MenubarCheckboxItem = React.forwardRef<\n React.ComponentRef<typeof MenubarPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <MenubarPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none h-9 focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <svg\n width=\"50\"\n height=\"50\"\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n xmlns=\"http://www.w3.org/2000/svg\"\n stroke=\"currentColor\"\n strokeWidth=\"0.25\"\n aria-label=\"check\"\n className=\"size-7\"\n >\n <rect\n x=\"80\"\n y=\"128\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 80 128)\"\n ></rect>\n <rect\n x=\"96\"\n y=\"144\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 96 144)\"\n ></rect>\n <rect\n x=\"112\"\n y=\"160\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 112 160)\"\n ></rect>\n <rect\n x=\"128\"\n y=\"144\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 128 144)\"\n ></rect>\n <rect\n x=\"144\"\n y=\"128\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 144 128)\"\n ></rect>\n <rect\n x=\"160\"\n y=\"112\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 160 112)\"\n ></rect>\n <rect\n x=\"176\"\n y=\"96\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 176 96)\"\n ></rect>\n <rect\n x=\"192\"\n y=\"80\"\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"rotate(90 192 80)\"\n ></rect>\n </svg>\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.CheckboxItem>\n));\nMenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;\n\nconst MenubarRadioItem = React.forwardRef<\n React.ComponentRef<typeof MenubarPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <MenubarPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 h-9 pl-8 pr-2 text-sm outline-none focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <Circle className=\"h-2 w-2 fill-current\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.RadioItem>\n));\nMenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;\n\nconst MenubarLabel = React.forwardRef<\n React.ComponentRef<typeof MenubarPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <MenubarPrimitive.Label\n ref={ref}\n className={cn(\n \"px-2 py-1.5 text-sm font-semibold\",\n inset && \"pl-8\",\n className\n )}\n {...props}\n />\n));\nMenubarLabel.displayName = MenubarPrimitive.Label.displayName;\n\nconst MenubarSeparator = React.forwardRef<\n React.ComponentRef<typeof MenubarPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\n {...props}\n />\n));\nMenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;\n\nconst MenubarShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\n className\n )}\n {...props}\n />\n );\n};\nMenubarShortcut.displayname = \"MenubarShortcut\";\n\nexport {\n Menubar,\n MenubarMenu,\n MenubarTrigger,\n MenubarContent,\n MenubarItem,\n MenubarSeparator,\n MenubarLabel,\n MenubarCheckboxItem,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarPortal,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarGroup,\n MenubarSub,\n MenubarShortcut,\n};\n",
"content": "\"use client\";\r\n\r\nimport * as React from \"react\";\r\n\r\nimport * as MenubarPrimitive from \"@radix-ui/react-menubar\";\r\nimport { cva } from \"class-variance-authority\";\r\nimport { Circle } from \"lucide-react\";\r\n\r\nimport { ChevronRightIcon } from \"@/components/ui/8bit/assets/chevronRightIcon\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\nimport \"./styles/retro.css\";\r\n\r\nexport const menubarVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n },\r\n defaultVariants: {\r\n font: \"retro\",\r\n },\r\n});\r\n\r\nfunction MenubarMenu({\r\n ...props\r\n}: React.ComponentProps<typeof MenubarPrimitive.Menu>) {\r\n return <MenubarPrimitive.Menu {...props} />;\r\n}\r\n\r\nfunction MenubarGroup({\r\n ...props\r\n}: React.ComponentProps<typeof MenubarPrimitive.Group>) {\r\n return <MenubarPrimitive.Group {...props} />;\r\n}\r\n\r\nfunction MenubarPortal({\r\n ...props\r\n}: React.ComponentProps<typeof MenubarPrimitive.Portal>) {\r\n return <MenubarPrimitive.Portal {...props} />;\r\n}\r\n\r\nfunction MenubarRadioGroup({\r\n ...props\r\n}: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {\r\n return <MenubarPrimitive.RadioGroup {...props} />;\r\n}\r\n\r\nfunction MenubarSub({\r\n ...props\r\n}: React.ComponentProps<typeof MenubarPrimitive.Sub>) {\r\n return <MenubarPrimitive.Sub data-slot=\"menubar-sub\" {...props} />;\r\n}\r\n\r\nconst Menubar = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Root>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n className={cn(\r\n \"relative border-y-6 border-foreground dark:border-ring !p-0\",\r\n menubarVariants({ font: \"retro\" }),\r\n className\r\n )}\r\n >\r\n <MenubarPrimitive.Root\r\n ref={ref}\r\n className={cn(\r\n \"flex h-10 items-center space-x-1 rounded-md border bg-background p-1\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n <div\r\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n </div>\r\n));\r\nMenubar.displayName = MenubarPrimitive.Root.displayName;\r\n\r\nconst MenubarTrigger = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Trigger>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>\r\n>(({ className, ...props }, ref) => (\r\n <MenubarPrimitive.Trigger\r\n ref={ref}\r\n className={cn(\r\n \"flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[state=open]:border-b-4 data-[state=open]:border-foreground data-[state=open]:dark:border-ring data-[state=open]:text-accent-foreground data-[state=open]:border-dashed border-b-4 border-transparent pt-2\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nMenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;\r\n\r\nconst MenubarSubTrigger = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.SubTrigger>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, children, ...props }, ref) => (\r\n <MenubarPrimitive.SubTrigger\r\n ref={ref}\r\n className={cn(\r\n \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none h-10 focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[state=open]:border-y-4 data-[state=open]:border-foreground data-[state=open]:dark:border-ring data-[state=open]:text-accent-foreground data-[state=open]:border-dashed\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n <ChevronRightIcon/>\r\n </MenubarPrimitive.SubTrigger>\r\n));\r\nMenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;\r\n\r\nconst MenubarSubContent = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.SubContent>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>\r\n>(({ className, ...props }, ref) => (\r\n <MenubarPrimitive.SubContent\r\n ref={ref}\r\n className={cn(\r\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border-6 border-foreground dark:border-ring bg-popover p-1 text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nMenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;\r\n\r\nconst MenubarContent = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Content>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>\r\n>(\r\n (\r\n { className, align = \"start\", alignOffset = -4, sideOffset = 8, ...props },\r\n ref\r\n ) => (\r\n <MenubarPrimitive.Portal>\r\n <MenubarPrimitive.Content\r\n ref={ref}\r\n align={align}\r\n alignOffset={alignOffset}\r\n sideOffset={sideOffset}\r\n className={cn(\r\n \"z-50 min-w-[12rem] overflow-hidden rounded-md border-6 mt-1 border-foreground dark:border-ring bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]\",\r\n menubarVariants({ font: \"retro\" }),\r\n className\r\n )}\r\n {...props}\r\n />\r\n </MenubarPrimitive.Portal>\r\n )\r\n);\r\nMenubarContent.displayName = MenubarPrimitive.Content.displayName;\r\n\r\nconst MenubarItem = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Item>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, ...props }, ref) => (\r\n <MenubarPrimitive.Item\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:border-y-4 focus:border-foreground focus:dark:border-ring h-9 focus:border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nMenubarItem.displayName = MenubarPrimitive.Item.displayName;\r\n\r\nconst MenubarCheckboxItem = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.CheckboxItem>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>\r\n>(({ className, children, checked, ...props }, ref) => (\r\n <MenubarPrimitive.CheckboxItem\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none h-9 focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n className\r\n )}\r\n checked={checked}\r\n {...props}\r\n >\r\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\r\n <MenubarPrimitive.ItemIndicator>\r\n <svg\r\n width=\"50\"\r\n height=\"50\"\r\n viewBox=\"0 0 256 256\"\r\n fill=\"currentColor\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"0.25\"\r\n aria-label=\"check\"\r\n className=\"size-7\"\r\n >\r\n <rect\r\n x=\"80\"\r\n y=\"128\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 80 128)\"\r\n ></rect>\r\n <rect\r\n x=\"96\"\r\n y=\"144\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 96 144)\"\r\n ></rect>\r\n <rect\r\n x=\"112\"\r\n y=\"160\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 112 160)\"\r\n ></rect>\r\n <rect\r\n x=\"128\"\r\n y=\"144\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 128 144)\"\r\n ></rect>\r\n <rect\r\n x=\"144\"\r\n y=\"128\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 144 128)\"\r\n ></rect>\r\n <rect\r\n x=\"160\"\r\n y=\"112\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 160 112)\"\r\n ></rect>\r\n <rect\r\n x=\"176\"\r\n y=\"96\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 176 96)\"\r\n ></rect>\r\n <rect\r\n x=\"192\"\r\n y=\"80\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 192 80)\"\r\n ></rect>\r\n </svg>\r\n </MenubarPrimitive.ItemIndicator>\r\n </span>\r\n {children}\r\n </MenubarPrimitive.CheckboxItem>\r\n));\r\nMenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;\r\n\r\nconst MenubarRadioItem = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.RadioItem>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>\r\n>(({ className, children, ...props }, ref) => (\r\n <MenubarPrimitive.RadioItem\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 h-9 pl-8 pr-2 text-sm outline-none focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\r\n <MenubarPrimitive.ItemIndicator>\r\n <Circle className=\"h-2 w-2 fill-current\" />\r\n </MenubarPrimitive.ItemIndicator>\r\n </span>\r\n {children}\r\n </MenubarPrimitive.RadioItem>\r\n));\r\nMenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;\r\n\r\nconst MenubarLabel = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Label>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, ...props }, ref) => (\r\n <MenubarPrimitive.Label\r\n ref={ref}\r\n className={cn(\r\n \"px-2 py-1.5 text-sm font-semibold\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nMenubarLabel.displayName = MenubarPrimitive.Label.displayName;\r\n\r\nconst MenubarSeparator = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Separator>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>\r\n>(({ className, ...props }, ref) => (\r\n <MenubarPrimitive.Separator\r\n ref={ref}\r\n className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\r\n {...props}\r\n />\r\n));\r\nMenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;\r\n\r\nconst MenubarShortcut = ({\r\n className,\r\n ...props\r\n}: React.HTMLAttributes<HTMLSpanElement>) => {\r\n return (\r\n <span\r\n className={cn(\r\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n );\r\n};\r\nMenubarShortcut.displayname = \"MenubarShortcut\";\r\n\r\nexport {\r\n Menubar,\r\n MenubarMenu,\r\n MenubarTrigger,\r\n MenubarContent,\r\n MenubarItem,\r\n MenubarSeparator,\r\n MenubarLabel,\r\n MenubarCheckboxItem,\r\n MenubarRadioGroup,\r\n MenubarRadioItem,\r\n MenubarPortal,\r\n MenubarSubContent,\r\n MenubarSubTrigger,\r\n MenubarGroup,\r\n MenubarSub,\r\n MenubarShortcut,\r\n};\r\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Chevron in MenubarSubTrigger needs right alignment and a11y; fix like ContextMenu.

Same issue as in the context menu: removing ml-auto will change alignment. Also make the icon decorative.

-    {children}
-    <ChevronRightIcon/>
+    {children}
+    <span className="ml-auto">
+      <ChevronRightIcon aria-hidden="true" />
+    </span>

If you updated the icon to accept className, you can instead do:

-    <ChevronRightIcon/>
+    <ChevronRightIcon className="ml-auto size-4 shrink-0 opacity-70" aria-hidden="true" />
📝 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.

Suggested change
"content": "\"use client\";\r\n\r\nimport * as React from \"react\";\r\n\r\nimport * as MenubarPrimitive from \"@radix-ui/react-menubar\";\r\nimport { cva } from \"class-variance-authority\";\r\nimport { Circle } from \"lucide-react\";\r\n\r\nimport { ChevronRightIcon } from \"@/components/ui/8bit/assets/chevronRightIcon\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\nimport \"./styles/retro.css\";\r\n\r\nexport const menubarVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n },\r\n defaultVariants: {\r\n font: \"retro\",\r\n },\r\n});\r\n\r\nfunction MenubarMenu({\r\n ...props\r\n}: React.ComponentProps<typeof MenubarPrimitive.Menu>) {\r\n return <MenubarPrimitive.Menu {...props} />;\r\n}\r\n\r\nfunction MenubarGroup({\r\n ...props\r\n}: React.ComponentProps<typeof MenubarPrimitive.Group>) {\r\n return <MenubarPrimitive.Group {...props} />;\r\n}\r\n\r\nfunction MenubarPortal({\r\n ...props\r\n}: React.ComponentProps<typeof MenubarPrimitive.Portal>) {\r\n return <MenubarPrimitive.Portal {...props} />;\r\n}\r\n\r\nfunction MenubarRadioGroup({\r\n ...props\r\n}: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {\r\n return <MenubarPrimitive.RadioGroup {...props} />;\r\n}\r\n\r\nfunction MenubarSub({\r\n ...props\r\n}: React.ComponentProps<typeof MenubarPrimitive.Sub>) {\r\n return <MenubarPrimitive.Sub data-slot=\"menubar-sub\" {...props} />;\r\n}\r\n\r\nconst Menubar = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Root>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n className={cn(\r\n \"relative border-y-6 border-foreground dark:border-ring !p-0\",\r\n menubarVariants({ font: \"retro\" }),\r\n className\r\n )}\r\n >\r\n <MenubarPrimitive.Root\r\n ref={ref}\r\n className={cn(\r\n \"flex h-10 items-center space-x-1 rounded-md border bg-background p-1\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n <div\r\n className=\"absolute inset-0 border-x-6 -mx-1.5 border-foreground dark:border-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n </div>\r\n));\r\nMenubar.displayName = MenubarPrimitive.Root.displayName;\r\n\r\nconst MenubarTrigger = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Trigger>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>\r\n>(({ className, ...props }, ref) => (\r\n <MenubarPrimitive.Trigger\r\n ref={ref}\r\n className={cn(\r\n \"flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[state=open]:border-b-4 data-[state=open]:border-foreground data-[state=open]:dark:border-ring data-[state=open]:text-accent-foreground data-[state=open]:border-dashed border-b-4 border-transparent pt-2\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nMenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;\r\n\r\nconst MenubarSubTrigger = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.SubTrigger>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, children, ...props }, ref) => (\r\n <MenubarPrimitive.SubTrigger\r\n ref={ref}\r\n className={cn(\r\n \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none h-10 focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[state=open]:border-y-4 data-[state=open]:border-foreground data-[state=open]:dark:border-ring data-[state=open]:text-accent-foreground data-[state=open]:border-dashed\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n <ChevronRightIcon/>\r\n </MenubarPrimitive.SubTrigger>\r\n));\r\nMenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;\r\n\r\nconst MenubarSubContent = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.SubContent>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>\r\n>(({ className, ...props }, ref) => (\r\n <MenubarPrimitive.SubContent\r\n ref={ref}\r\n className={cn(\r\n \"z-50 min-w-[8rem] overflow-hidden rounded-md border-6 border-foreground dark:border-ring bg-popover p-1 text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nMenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;\r\n\r\nconst MenubarContent = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Content>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>\r\n>(\r\n (\r\n { className, align = \"start\", alignOffset = -4, sideOffset = 8, ...props },\r\n ref\r\n ) => (\r\n <MenubarPrimitive.Portal>\r\n <MenubarPrimitive.Content\r\n ref={ref}\r\n align={align}\r\n alignOffset={alignOffset}\r\n sideOffset={sideOffset}\r\n className={cn(\r\n \"z-50 min-w-[12rem] overflow-hidden rounded-md border-6 mt-1 border-foreground dark:border-ring bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]\",\r\n menubarVariants({ font: \"retro\" }),\r\n className\r\n )}\r\n {...props}\r\n />\r\n </MenubarPrimitive.Portal>\r\n )\r\n);\r\nMenubarContent.displayName = MenubarPrimitive.Content.displayName;\r\n\r\nconst MenubarItem = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Item>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, ...props }, ref) => (\r\n <MenubarPrimitive.Item\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:border-y-4 focus:border-foreground focus:dark:border-ring h-9 focus:border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nMenubarItem.displayName = MenubarPrimitive.Item.displayName;\r\n\r\nconst MenubarCheckboxItem = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.CheckboxItem>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>\r\n>(({ className, children, checked, ...props }, ref) => (\r\n <MenubarPrimitive.CheckboxItem\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none h-9 focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n className\r\n )}\r\n checked={checked}\r\n {...props}\r\n >\r\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\r\n <MenubarPrimitive.ItemIndicator>\r\n <svg\r\n width=\"50\"\r\n height=\"50\"\r\n viewBox=\"0 0 256 256\"\r\n fill=\"currentColor\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"0.25\"\r\n aria-label=\"check\"\r\n className=\"size-7\"\r\n >\r\n <rect\r\n x=\"80\"\r\n y=\"128\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 80 128)\"\r\n ></rect>\r\n <rect\r\n x=\"96\"\r\n y=\"144\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 96 144)\"\r\n ></rect>\r\n <rect\r\n x=\"112\"\r\n y=\"160\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 112 160)\"\r\n ></rect>\r\n <rect\r\n x=\"128\"\r\n y=\"144\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 128 144)\"\r\n ></rect>\r\n <rect\r\n x=\"144\"\r\n y=\"128\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 144 128)\"\r\n ></rect>\r\n <rect\r\n x=\"160\"\r\n y=\"112\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 160 112)\"\r\n ></rect>\r\n <rect\r\n x=\"176\"\r\n y=\"96\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 176 96)\"\r\n ></rect>\r\n <rect\r\n x=\"192\"\r\n y=\"80\"\r\n width=\"14\"\r\n height=\"14\"\r\n rx=\"1\"\r\n transform=\"rotate(90 192 80)\"\r\n ></rect>\r\n </svg>\r\n </MenubarPrimitive.ItemIndicator>\r\n </span>\r\n {children}\r\n </MenubarPrimitive.CheckboxItem>\r\n));\r\nMenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;\r\n\r\nconst MenubarRadioItem = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.RadioItem>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>\r\n>(({ className, children, ...props }, ref) => (\r\n <MenubarPrimitive.RadioItem\r\n ref={ref}\r\n className={cn(\r\n \"relative flex cursor-default select-none items-center rounded-sm py-1.5 h-9 pl-8 pr-2 text-sm outline-none focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\r\n <MenubarPrimitive.ItemIndicator>\r\n <Circle className=\"h-2 w-2 fill-current\" />\r\n </MenubarPrimitive.ItemIndicator>\r\n </span>\r\n {children}\r\n </MenubarPrimitive.RadioItem>\r\n));\r\nMenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;\r\n\r\nconst MenubarLabel = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Label>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {\r\n inset?: boolean;\r\n }\r\n>(({ className, inset, ...props }, ref) => (\r\n <MenubarPrimitive.Label\r\n ref={ref}\r\n className={cn(\r\n \"px-2 py-1.5 text-sm font-semibold\",\r\n inset && \"pl-8\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nMenubarLabel.displayName = MenubarPrimitive.Label.displayName;\r\n\r\nconst MenubarSeparator = React.forwardRef<\r\n React.ComponentRef<typeof MenubarPrimitive.Separator>,\r\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>\r\n>(({ className, ...props }, ref) => (\r\n <MenubarPrimitive.Separator\r\n ref={ref}\r\n className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\r\n {...props}\r\n />\r\n));\r\nMenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;\r\n\r\nconst MenubarShortcut = ({\r\n className,\r\n ...props\r\n}: React.HTMLAttributes<HTMLSpanElement>) => {\r\n return (\r\n <span\r\n className={cn(\r\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n );\r\n};\r\nMenubarShortcut.displayname = \"MenubarShortcut\";\r\n\r\nexport {\r\n Menubar,\r\n MenubarMenu,\r\n MenubarTrigger,\r\n MenubarContent,\r\n MenubarItem,\r\n MenubarSeparator,\r\n MenubarLabel,\r\n MenubarCheckboxItem,\r\n MenubarRadioGroup,\r\n MenubarRadioItem,\r\n MenubarPortal,\r\n MenubarSubContent,\r\n MenubarSubTrigger,\r\n MenubarGroup,\r\n MenubarSub,\r\n MenubarShortcut,\r\n};\r\n",
const MenubarSubTrigger = React.forwardRef<
React.ComponentRef<typeof MenubarPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
inset?: boolean;
}
>(({ className, inset, children, ...props }, ref) => (
<MenubarPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none h-10 focus:border-y-4 focus:border-foreground focus:dark:border-ring focus:border-dashed focus:text-accent-foreground data-[state=open]:border-y-4 data-[state=open]:border-foreground data-[state=open]:dark:border-ring data-[state=open]:text-accent-foreground data-[state=open]:border-dashed",
inset && "pl-8",
className
)}
{...props}
>
{children}
<span className="ml-auto">
<ChevronRightIcon aria-hidden="true" />
</span>
</MenubarPrimitive.SubTrigger>
));
MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;
🤖 Prompt for AI Agents
public/r/8bit-menubar.json around line 11: the ChevronRightIcon in
MenubarSubTrigger isn't aligned to the right nor marked decorative; update the
component usage to pass a className that pushes it to the right (e.g. "ml-auto"
or equivalent spacing utility) and mark it as decorative for accessibility (e.g.
aria-hidden="true" and focusable={false} or role="img" set appropriately), or if
ChevronRightIcon doesn't accept className, wrap it in a span with the ml-auto
class and set aria-hidden on the icon element; ensure the icon accepts a
className prop if you choose the direct-prop route.

{
"path": "components/ui/8bit/pagination.tsx",
"content": "import { type VariantProps, cva } from \"class-variance-authority\";\nimport { MoreHorizontal } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport {\n Pagination as ShadcnPagination,\n PaginationContent as ShadcnPaginationContent,\n PaginationEllipsis as ShadcnPaginationEllipsis,\n PaginationItem as ShadcnPaginationItem,\n PaginationLink as ShadcnPaginationLink,\n} from \"@/components/ui/pagination\";\n\nimport { Button } from \"../button\";\nimport \"./styles/retro.css\";\n\nexport const paginationVariants = cva(\"\", {\n variants: {\n font: {\n normal: \"\",\n retro: \"retro\",\n },\n variant: {\n default: \"text-card-foreground\",\n destructive:\n \"text-destructive [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n});\n\nexport type BitPaginationProps<T extends React.ElementType> =\n React.ComponentPropsWithoutRef<T> & VariantProps<typeof paginationVariants>;\n\nfunction Pagination({ ...props }: BitPaginationProps<\"nav\">) {\n const { variant, className, font } = props;\n return (\n <ShadcnPagination\n {...props}\n className={cn(\n paginationVariants({ variant }),\n font !== \"normal\" && \"retro\",\n className\n )}\n />\n );\n}\n\nconst ChevronLeftIcon = () => {\n return (\n <svg\n width=\"50\"\n height=\"50\"\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n xmlns=\"http://www.w3.org/2000/svg\"\n stroke=\"currentColor\"\n strokeWidth=\"0.25\"\n color=\"\"\n className=\"size-7\"\n aria-label=\"chevron-left\"\n >\n <rect\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"matrix(-1 0 0 1 128 136)\"\n ></rect>\n <rect\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"matrix(-1 0 0 1 144 152)\"\n ></rect>\n <rect\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"matrix(-1 0 0 1 160 72)\"\n ></rect>\n <rect\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"matrix(-1 0 0 1 160 168)\"\n ></rect>\n <rect\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"matrix(-1 0 0 1 112 120)\"\n ></rect>\n <rect\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"matrix(-1 0 0 1 128 104)\"\n ></rect>\n <rect\n width=\"14\"\n height=\"14\"\n rx=\"1\"\n transform=\"matrix(-1 0 0 1 144 88)\"\n ></rect>\n </svg>\n );\n};\n\nconst ChevronRightIcon = () => {\n return (\n <svg\n width=\"50\"\n height=\"50\"\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n xmlns=\"http://www.w3.org/2000/svg\"\n stroke=\"currentColor\"\n strokeWidth=\"0.25\"\n color=\"\"\n className=\"raster-icon size-7\"\n aria-label=\"chevron-right\"\n >\n <rect x=\"128\" y=\"136\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"112\" y=\"152\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"96\" y=\"72\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"96\" y=\"168\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"144\" y=\"120\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"128\" y=\"104\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n <rect x=\"112\" y=\"88\" width=\"14\" height=\"14\" rx=\"1\"></rect>\n </svg>\n );\n};\n\nfunction PaginationContent({ ...props }: BitPaginationProps<\"ul\">) {\n const { className, font } = props;\n return (\n <ShadcnPaginationContent\n className={cn(\"gap-2\", font !== \"normal\" && \"retro\", className)}\n {...props}\n />\n );\n}\n\nfunction PaginationItem({ ...props }: BitPaginationProps<\"li\">) {\n const { className, font } = props;\n return (\n <ShadcnPaginationItem\n className={cn(font !== \"normal\" && \"retro\", className)}\n {...props}\n />\n );\n}\n\ntype PaginationLinkProps = {\n isActive?: boolean;\n} & Pick<React.ComponentProps<typeof Button>, \"size\"> &\n BitPaginationProps<\"a\">;\n\nfunction PaginationLink({ ...props }: PaginationLinkProps) {\n const { font, children, isActive, className } = props;\n return (\n <ShadcnPaginationLink\n className={cn(\n font !== \"normal\" && \"retro\",\n className,\n \"relative group\",\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\n \"rounded-none border-dashed border-y-4 border-transparent\",\n \"dark:hover:border-ring dark:focus:border-ring\",\n \"hover:border-foreground focus:border-foreground\",\n \"active:border-transparent\",\n \"data-[active=true]:border-none aria-[current=page]:border-none\"\n )}\n {...props}\n >\n {children}\n\n {isActive && (\n <div\n className=\"absolute inset-0 w-full h-full pointer-events-none\"\n style={{ zIndex: 10 }}\n >\n <div\n className=\"absolute top-0 left-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n <div\n className=\"absolute left-0 bottom-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n <div\n className=\"absolute top-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n <div\n className=\"absolute bottom-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n <div\n className=\"absolute top-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n <div\n className=\"absolute bottom-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\n aria-hidden=\"true\"\n />\n </div>\n )}\n </ShadcnPaginationLink>\n );\n}\n\nfunction PaginationPrevious({\n ...props\n}: React.ComponentProps<typeof PaginationLink>) {\n const { font, className } = props;\n return (\n <PaginationLink\n className={cn(\n \"relative group\",\n \"flex flex-row w-full text-sm\",\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\n \"rounded-none border-dashed border-y-4 border-transparent\",\n \"hover:border-foreground focus:border-foreground active:border-transparent\",\n \"dark:hover:border-ring dark:focus:border-ring\",\n \"data-[active=true]:border-none aria-[current=page]:border-none\",\n font !== \"normal\" && \"retro\",\n className\n )}\n {...props}\n >\n <ChevronLeftIcon />\n <span className=\"hidden sm:block\">Previous</span>\n </PaginationLink>\n );\n}\n\nfunction PaginationNext({\n ...props\n}: React.ComponentProps<typeof PaginationLink>) {\n const { font, className } = props;\n\n return (\n <PaginationLink\n className={cn(\n \"relative group\",\n \"flex flex-row w-full text-sm\",\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\n \"rounded-none border-dashed border-y-4 border-transparent\",\n \"hover:border-foreground focus:border-foreground active:border-transparent\",\n \"dark:hover:border-ring dark:focus:border-ring\",\n \"data-[active=true]:border-none aria-[current=page]:border-none\",\n \"flex flex-row text-sm w-full\",\n font !== \"normal\" && \"retro\",\n className\n )}\n {...props}\n >\n <span className=\"hidden sm:block\">Next</span>\n <ChevronRightIcon />\n </PaginationLink>\n );\n}\n\nfunction PaginationEllipsis({ ...props }: BitPaginationProps<\"span\">) {\n const { font, className } = props;\n\n return (\n <ShadcnPaginationEllipsis\n className={cn(font !== \"normal\" && \"retro\", className)}\n {...props}\n >\n <MoreHorizontal className={cn(\"size-7\", \"retro\")} />\n <span className=\"sr-only\">More pages</span>\n </ShadcnPaginationEllipsis>\n );\n}\n\nexport {\n Pagination,\n PaginationContent,\n PaginationLink,\n PaginationItem,\n PaginationPrevious,\n PaginationNext,\n PaginationEllipsis,\n};\n",
"content": "import { type VariantProps, cva } from \"class-variance-authority\";\r\nimport { MoreHorizontal } from \"lucide-react\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n Pagination as ShadcnPagination,\r\n PaginationContent as ShadcnPaginationContent,\r\n PaginationEllipsis as ShadcnPaginationEllipsis,\r\n PaginationItem as ShadcnPaginationItem,\r\n PaginationLink as ShadcnPaginationLink,\r\n} from \"@/components/ui/pagination\";\r\n\r\nimport { ChevronLeftIcon } from \"@/components/ui/8bit/assets/chevronLeftIcon\";\r\nimport { ChevronRightIcon } from \"@/components/ui/8bit/assets/chevronRightIcon\";\r\nimport { Button } from \"../button\";\r\nimport \"./styles/retro.css\";\r\n\r\nexport const paginationVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n variant: {\r\n default: \"text-card-foreground\",\r\n destructive:\r\n \"text-destructive [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n});\r\n\r\nexport type BitPaginationProps<T extends React.ElementType> =\r\n React.ComponentPropsWithoutRef<T> & VariantProps<typeof paginationVariants>;\r\n\r\nfunction Pagination({ ...props }: BitPaginationProps<\"nav\">) {\r\n const { variant, className, font } = props;\r\n return (\r\n <ShadcnPagination\r\n {...props}\r\n className={cn(\r\n paginationVariants({ variant }),\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n />\r\n );\r\n}\r\n\r\nfunction PaginationContent({ ...props }: BitPaginationProps<\"ul\">) {\r\n const { className, font } = props;\r\n return (\r\n <ShadcnPaginationContent\r\n className={cn(\"gap-2\", font !== \"normal\" && \"retro\", className)}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction PaginationItem({ ...props }: BitPaginationProps<\"li\">) {\r\n const { className, font } = props;\r\n return (\r\n <ShadcnPaginationItem\r\n className={cn(font !== \"normal\" && \"retro\", className)}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\ntype PaginationLinkProps = {\r\n isActive?: boolean;\r\n} & Pick<React.ComponentProps<typeof Button>, \"size\"> &\r\n BitPaginationProps<\"a\">;\r\n\r\nfunction PaginationLink({ ...props }: PaginationLinkProps) {\r\n const { font, children, isActive, className } = props;\r\n return (\r\n <ShadcnPaginationLink\r\n className={cn(\r\n font !== \"normal\" && \"retro\",\r\n className,\r\n \"relative group\",\r\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\r\n \"rounded-none border-dashed border-y-4 border-transparent\",\r\n \"dark:hover:border-ring dark:focus:border-ring\",\r\n \"hover:border-foreground focus:border-foreground\",\r\n \"active:border-transparent\",\r\n \"data-[active=true]:border-none aria-[current=page]:border-none\"\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n\r\n {isActive && (\r\n <div\r\n className=\"absolute inset-0 w-full h-full pointer-events-none\"\r\n style={{ zIndex: 10 }}\r\n >\r\n <div\r\n className=\"absolute top-0 left-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute left-0 bottom-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute top-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute bottom-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute top-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute bottom-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n </div>\r\n )}\r\n </ShadcnPaginationLink>\r\n );\r\n}\r\n\r\nfunction PaginationPrevious({\r\n ...props\r\n}: React.ComponentProps<typeof PaginationLink>) {\r\n const { font, className } = props;\r\n return (\r\n <PaginationLink\r\n className={cn(\r\n \"relative group\",\r\n \"flex flex-row w-full text-sm\",\r\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\r\n \"rounded-none border-dashed border-y-4 border-transparent\",\r\n \"hover:border-foreground focus:border-foreground active:border-transparent\",\r\n \"dark:hover:border-ring dark:focus:border-ring\",\r\n \"data-[active=true]:border-none aria-[current=page]:border-none\",\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <ChevronLeftIcon />\r\n <span className=\"hidden sm:block\">Previous</span>\r\n </PaginationLink>\r\n );\r\n}\r\n\r\nfunction PaginationNext({\r\n ...props\r\n}: React.ComponentProps<typeof PaginationLink>) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <PaginationLink\r\n className={cn(\r\n \"relative group\",\r\n \"flex flex-row w-full text-sm\",\r\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\r\n \"rounded-none border-dashed border-y-4 border-transparent\",\r\n \"hover:border-foreground focus:border-foreground active:border-transparent\",\r\n \"dark:hover:border-ring dark:focus:border-ring\",\r\n \"data-[active=true]:border-none aria-[current=page]:border-none\",\r\n \"flex flex-row text-sm w-full\",\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <span className=\"hidden sm:block\">Next</span>\r\n <ChevronRightIcon />\r\n </PaginationLink>\r\n );\r\n}\r\n\r\nfunction PaginationEllipsis({ ...props }: BitPaginationProps<\"span\">) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <ShadcnPaginationEllipsis\r\n className={cn(font !== \"normal\" && \"retro\", className)}\r\n {...props}\r\n >\r\n <MoreHorizontal className={cn(\"size-7\", \"retro\")} />\r\n <span className=\"sr-only\">More pages</span>\r\n </ShadcnPaginationEllipsis>\r\n );\r\n}\r\n\r\nexport {\r\n Pagination,\r\n PaginationContent,\r\n PaginationLink,\r\n PaginationItem,\r\n PaginationPrevious,\r\n PaginationNext,\r\n PaginationEllipsis,\r\n};\r\n",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Decorative chevrons should be aria-hidden in Previous/Next

The icons are decorative; expose aria-hidden and focusable="false" to avoid polluting accessible names. This assumes the asset components accept SVG props (see asset refactor suggested in Calendar).

-      <ChevronLeftIcon />
+      <ChevronLeftIcon aria-hidden="true" focusable="false" />
...
-      <ChevronRightIcon />
+      <ChevronRightIcon aria-hidden="true" focusable="false" />
📝 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.

Suggested change
"content": "import { type VariantProps, cva } from \"class-variance-authority\";\r\nimport { MoreHorizontal } from \"lucide-react\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n Pagination as ShadcnPagination,\r\n PaginationContent as ShadcnPaginationContent,\r\n PaginationEllipsis as ShadcnPaginationEllipsis,\r\n PaginationItem as ShadcnPaginationItem,\r\n PaginationLink as ShadcnPaginationLink,\r\n} from \"@/components/ui/pagination\";\r\n\r\nimport { ChevronLeftIcon } from \"@/components/ui/8bit/assets/chevronLeftIcon\";\r\nimport { ChevronRightIcon } from \"@/components/ui/8bit/assets/chevronRightIcon\";\r\nimport { Button } from \"../button\";\r\nimport \"./styles/retro.css\";\r\n\r\nexport const paginationVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n variant: {\r\n default: \"text-card-foreground\",\r\n destructive:\r\n \"text-destructive [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n});\r\n\r\nexport type BitPaginationProps<T extends React.ElementType> =\r\n React.ComponentPropsWithoutRef<T> & VariantProps<typeof paginationVariants>;\r\n\r\nfunction Pagination({ ...props }: BitPaginationProps<\"nav\">) {\r\n const { variant, className, font } = props;\r\n return (\r\n <ShadcnPagination\r\n {...props}\r\n className={cn(\r\n paginationVariants({ variant }),\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n />\r\n );\r\n}\r\n\r\nfunction PaginationContent({ ...props }: BitPaginationProps<\"ul\">) {\r\n const { className, font } = props;\r\n return (\r\n <ShadcnPaginationContent\r\n className={cn(\"gap-2\", font !== \"normal\" && \"retro\", className)}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction PaginationItem({ ...props }: BitPaginationProps<\"li\">) {\r\n const { className, font } = props;\r\n return (\r\n <ShadcnPaginationItem\r\n className={cn(font !== \"normal\" && \"retro\", className)}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\ntype PaginationLinkProps = {\r\n isActive?: boolean;\r\n} & Pick<React.ComponentProps<typeof Button>, \"size\"> &\r\n BitPaginationProps<\"a\">;\r\n\r\nfunction PaginationLink({ ...props }: PaginationLinkProps) {\r\n const { font, children, isActive, className } = props;\r\n return (\r\n <ShadcnPaginationLink\r\n className={cn(\r\n font !== \"normal\" && \"retro\",\r\n className,\r\n \"relative group\",\r\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\r\n \"rounded-none border-dashed border-y-4 border-transparent\",\r\n \"dark:hover:border-ring dark:focus:border-ring\",\r\n \"hover:border-foreground focus:border-foreground\",\r\n \"active:border-transparent\",\r\n \"data-[active=true]:border-none aria-[current=page]:border-none\"\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n\r\n {isActive && (\r\n <div\r\n className=\"absolute inset-0 w-full h-full pointer-events-none\"\r\n style={{ zIndex: 10 }}\r\n >\r\n <div\r\n className=\"absolute top-0 left-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute left-0 bottom-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute top-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute bottom-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute top-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute bottom-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n </div>\r\n )}\r\n </ShadcnPaginationLink>\r\n );\r\n}\r\n\r\nfunction PaginationPrevious({\r\n ...props\r\n}: React.ComponentProps<typeof PaginationLink>) {\r\n const { font, className } = props;\r\n return (\r\n <PaginationLink\r\n className={cn(\r\n \"relative group\",\r\n \"flex flex-row w-full text-sm\",\r\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\r\n \"rounded-none border-dashed border-y-4 border-transparent\",\r\n \"hover:border-foreground focus:border-foreground active:border-transparent\",\r\n \"dark:hover:border-ring dark:focus:border-ring\",\r\n \"data-[active=true]:border-none aria-[current=page]:border-none\",\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <ChevronLeftIcon />\r\n <span className=\"hidden sm:block\">Previous</span>\r\n </PaginationLink>\r\n );\r\n}\r\n\r\nfunction PaginationNext({\r\n ...props\r\n}: React.ComponentProps<typeof PaginationLink>) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <PaginationLink\r\n className={cn(\r\n \"relative group\",\r\n \"flex flex-row w-full text-sm\",\r\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\r\n \"rounded-none border-dashed border-y-4 border-transparent\",\r\n \"hover:border-foreground focus:border-foreground active:border-transparent\",\r\n \"dark:hover:border-ring dark:focus:border-ring\",\r\n \"data-[active=true]:border-none aria-[current=page]:border-none\",\r\n \"flex flex-row text-sm w-full\",\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <span className=\"hidden sm:block\">Next</span>\r\n <ChevronRightIcon />\r\n </PaginationLink>\r\n );\r\n}\r\n\r\nfunction PaginationEllipsis({ ...props }: BitPaginationProps<\"span\">) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <ShadcnPaginationEllipsis\r\n className={cn(font !== \"normal\" && \"retro\", className)}\r\n {...props}\r\n >\r\n <MoreHorizontal className={cn(\"size-7\", \"retro\")} />\r\n <span className=\"sr-only\">More pages</span>\r\n </ShadcnPaginationEllipsis>\r\n );\r\n}\r\n\r\nexport {\r\n Pagination,\r\n PaginationContent,\r\n PaginationLink,\r\n PaginationItem,\r\n PaginationPrevious,\r\n PaginationNext,\r\n PaginationEllipsis,\r\n};\r\n",
import { type VariantProps, cva } from "class-variance-authority";
import { MoreHorizontal } from "lucide-react";
import { cn } from "@/lib/utils";
import {
Pagination as ShadcnPagination,
PaginationContent as ShadcnPaginationContent,
PaginationEllipsis as ShadcnPaginationEllipsis,
PaginationItem as ShadcnPaginationItem,
PaginationLink as ShadcnPaginationLink,
} from "@/components/ui/pagination";
import { ChevronLeftIcon } from "@/components/ui/8bit/assets/chevronLeftIcon";
import { ChevronRightIcon } from "@/components/ui/8bit/assets/chevronRightIcon";
import { Button } from "../button";
import "./styles/retro.css";
export const paginationVariants = cva("", {
variants: {
font: {
normal: "",
retro: "retro",
},
variant: {
default: "text-card-foreground",
destructive:
"text-destructive [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
},
},
defaultVariants: {
variant: "default",
},
});
export type BitPaginationProps<T extends React.ElementType> =
React.ComponentPropsWithoutRef<T> & VariantProps<typeof paginationVariants>;
function Pagination({ ...props }: BitPaginationProps<"nav">) {
const { variant, className, font } = props;
return (
<ShadcnPagination
{...props}
className={cn(
paginationVariants({ variant }),
font !== "normal" && "retro",
className
)}
/>
);
}
function PaginationContent({ ...props }: BitPaginationProps<"ul">) {
const { className, font } = props;
return (
<ShadcnPaginationContent
className={cn("gap-2", font !== "normal" && "retro", className)}
{...props}
/>
);
}
function PaginationItem({ ...props }: BitPaginationProps<"li">) {
const { className, font } = props;
return (
<ShadcnPaginationItem
className={cn(font !== "normal" && "retro", className)}
{...props}
/>
);
}
type PaginationLinkProps = {
isActive?: boolean;
} & Pick<React.ComponentProps<typeof Button>, "size"> &
BitPaginationProps<"a">;
function PaginationLink({ ...props }: PaginationLinkProps) {
const { font, children, isActive, className } = props;
return (
<ShadcnPaginationLink
className={cn(
font !== "normal" && "retro",
className,
"relative group",
"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent",
"rounded-none border-dashed border-y-4 border-transparent",
"dark:hover:border-ring dark:focus:border-ring",
"hover:border-foreground focus:border-foreground",
"active:border-transparent",
"data-[active=true]:border-none aria-[current=page]:border-none"
)}
{...props}
>
{children}
{isActive && (
<div
className="absolute inset-0 w-full h-full pointer-events-none"
style={{ zIndex: 10 }}
>
<div
className="absolute top-0 left-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
<div
className="absolute left-0 bottom-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
<div
className="absolute top-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
<div
className="absolute bottom-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
<div
className="absolute top-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
<div
className="absolute bottom-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
</div>
)}
</ShadcnPaginationLink>
);
}
function PaginationPrevious({
...props
}: React.ComponentProps<typeof PaginationLink>) {
const { font, className } = props;
return (
<PaginationLink
className={cn(
"relative group",
"flex flex-row w-full text-sm",
"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent",
"rounded-none border-dashed border-y-4 border-transparent",
"hover:border-foreground focus:border-foreground active:border-transparent",
"dark:hover:border-ring dark:focus:border-ring",
"data-[active=true]:border-none aria-[current=page]:border-none",
font !== "normal" && "retro",
className
)}
{...props}
>
<ChevronLeftIcon aria-hidden="true" focusable="false" />
<span className="hidden sm:block">Previous</span>
</PaginationLink>
);
}
function PaginationNext({
...props
}: React.ComponentProps<typeof PaginationLink>) {
const { font, className } = props;
return (
<PaginationLink
className={cn(
"relative group",
"flex flex-row w-full text-sm",
"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent",
"rounded-none border-dashed border-y-4 border-transparent",
"hover:border-foreground focus:border-foreground active:border-transparent",
"dark:hover:border-ring dark:focus:border-ring",
"data-[active=true]:border-none aria-[current=page]:border-none",
"flex flex-row text-sm w-full",
font !== "normal" && "retro",
className
)}
{...props}
>
<span className="hidden sm:block">Next</span>
<ChevronRightIcon aria-hidden="true" focusable="false" />
</PaginationLink>
);
}
function PaginationEllipsis({ ...props }: BitPaginationProps<"span">) {
const { font, className } = props;
return (
<ShadcnPaginationEllipsis
className={cn(font !== "normal" && "retro", className)}
{...props}
>
<MoreHorizontal className={cn("size-7", "retro")} />
<span className="sr-only">More pages</span>
</ShadcnPaginationEllipsis>
);
}
export {
Pagination,
PaginationContent,
PaginationLink,
PaginationItem,
PaginationPrevious,
PaginationNext,
PaginationEllipsis,
};
🤖 Prompt for AI Agents
In public/r/8bit-pagination.json around lines 13 to 13, the previous/next
chevron icons are decorative but not marked as such; update the ChevronLeftIcon
and ChevronRightIcon usages in PaginationPrevious and PaginationNext to include
accessibility props aria-hidden="true" and focusable="false" (assuming the SVG
asset components accept standard SVG/React props) so they are ignored by
assistive tech and keyboard focus.

🛠️ Refactor suggestion

Prevent leaking design-system props to DOM and set font default

Same pattern as breadcrumb: variant and font flow into {...props}. Also, font defaults to retro when undefined. Extract props and set defaultVariants.font.

 export const paginationVariants = cva("", {
   variants: {
     font: {
       normal: "",
       retro: "retro",
     },
     variant: {
       default: "text-card-foreground",
       destructive:
         "text-destructive [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
     },
   },
   defaultVariants: {
     variant: "default",
+    font: "normal",
   },
 });

-function Pagination({ ...props }: BitPaginationProps<"nav">) {
-  const { variant, className, font } = props;
+function Pagination({ variant, className, font, ...rest }: BitPaginationProps<"nav">) {
   return (
     <ShadcnPagination
-      {...props}
+      {...rest}
       className={cn(
         paginationVariants({ variant }),
         font !== "normal" && "retro",
         className
       )}
     />
   );
 }

-function PaginationContent({ ...props }: BitPaginationProps<"ul">) {
-  const { className, font } = props;
+function PaginationContent({ className, font, ...rest }: BitPaginationProps<"ul">) {
   return (
     <ShadcnPaginationContent
       className={cn("gap-2", font !== "normal" && "retro", className)}
-      {...props}
+      {...rest}
     />
   );
 }

-function PaginationItem({ ...props }: BitPaginationProps<"li">) {
-  const { className, font } = props;
+function PaginationItem({ className, font, ...rest }: BitPaginationProps<"li">) {
   return (
     <ShadcnPaginationItem
       className={cn(font !== "normal" && "retro", className)}
-      {...props}
+      {...rest}
     />
   );
 }
📝 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.

Suggested change
"content": "import { type VariantProps, cva } from \"class-variance-authority\";\r\nimport { MoreHorizontal } from \"lucide-react\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nimport {\r\n Pagination as ShadcnPagination,\r\n PaginationContent as ShadcnPaginationContent,\r\n PaginationEllipsis as ShadcnPaginationEllipsis,\r\n PaginationItem as ShadcnPaginationItem,\r\n PaginationLink as ShadcnPaginationLink,\r\n} from \"@/components/ui/pagination\";\r\n\r\nimport { ChevronLeftIcon } from \"@/components/ui/8bit/assets/chevronLeftIcon\";\r\nimport { ChevronRightIcon } from \"@/components/ui/8bit/assets/chevronRightIcon\";\r\nimport { Button } from \"../button\";\r\nimport \"./styles/retro.css\";\r\n\r\nexport const paginationVariants = cva(\"\", {\r\n variants: {\r\n font: {\r\n normal: \"\",\r\n retro: \"retro\",\r\n },\r\n variant: {\r\n default: \"text-card-foreground\",\r\n destructive:\r\n \"text-destructive [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n});\r\n\r\nexport type BitPaginationProps<T extends React.ElementType> =\r\n React.ComponentPropsWithoutRef<T> & VariantProps<typeof paginationVariants>;\r\n\r\nfunction Pagination({ ...props }: BitPaginationProps<\"nav\">) {\r\n const { variant, className, font } = props;\r\n return (\r\n <ShadcnPagination\r\n {...props}\r\n className={cn(\r\n paginationVariants({ variant }),\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n />\r\n );\r\n}\r\n\r\nfunction PaginationContent({ ...props }: BitPaginationProps<\"ul\">) {\r\n const { className, font } = props;\r\n return (\r\n <ShadcnPaginationContent\r\n className={cn(\"gap-2\", font !== \"normal\" && \"retro\", className)}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\nfunction PaginationItem({ ...props }: BitPaginationProps<\"li\">) {\r\n const { className, font } = props;\r\n return (\r\n <ShadcnPaginationItem\r\n className={cn(font !== \"normal\" && \"retro\", className)}\r\n {...props}\r\n />\r\n );\r\n}\r\n\r\ntype PaginationLinkProps = {\r\n isActive?: boolean;\r\n} & Pick<React.ComponentProps<typeof Button>, \"size\"> &\r\n BitPaginationProps<\"a\">;\r\n\r\nfunction PaginationLink({ ...props }: PaginationLinkProps) {\r\n const { font, children, isActive, className } = props;\r\n return (\r\n <ShadcnPaginationLink\r\n className={cn(\r\n font !== \"normal\" && \"retro\",\r\n className,\r\n \"relative group\",\r\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\r\n \"rounded-none border-dashed border-y-4 border-transparent\",\r\n \"dark:hover:border-ring dark:focus:border-ring\",\r\n \"hover:border-foreground focus:border-foreground\",\r\n \"active:border-transparent\",\r\n \"data-[active=true]:border-none aria-[current=page]:border-none\"\r\n )}\r\n {...props}\r\n >\r\n {children}\r\n\r\n {isActive && (\r\n <div\r\n className=\"absolute inset-0 w-full h-full pointer-events-none\"\r\n style={{ zIndex: 10 }}\r\n >\r\n <div\r\n className=\"absolute top-0 left-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute left-0 bottom-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute top-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute bottom-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute top-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n <div\r\n className=\"absolute bottom-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none\"\r\n aria-hidden=\"true\"\r\n />\r\n </div>\r\n )}\r\n </ShadcnPaginationLink>\r\n );\r\n}\r\n\r\nfunction PaginationPrevious({\r\n ...props\r\n}: React.ComponentProps<typeof PaginationLink>) {\r\n const { font, className } = props;\r\n return (\r\n <PaginationLink\r\n className={cn(\r\n \"relative group\",\r\n \"flex flex-row w-full text-sm\",\r\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\r\n \"rounded-none border-dashed border-y-4 border-transparent\",\r\n \"hover:border-foreground focus:border-foreground active:border-transparent\",\r\n \"dark:hover:border-ring dark:focus:border-ring\",\r\n \"data-[active=true]:border-none aria-[current=page]:border-none\",\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <ChevronLeftIcon />\r\n <span className=\"hidden sm:block\">Previous</span>\r\n </PaginationLink>\r\n );\r\n}\r\n\r\nfunction PaginationNext({\r\n ...props\r\n}: React.ComponentProps<typeof PaginationLink>) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <PaginationLink\r\n className={cn(\r\n \"relative group\",\r\n \"flex flex-row w-full text-sm\",\r\n \"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent\",\r\n \"rounded-none border-dashed border-y-4 border-transparent\",\r\n \"hover:border-foreground focus:border-foreground active:border-transparent\",\r\n \"dark:hover:border-ring dark:focus:border-ring\",\r\n \"data-[active=true]:border-none aria-[current=page]:border-none\",\r\n \"flex flex-row text-sm w-full\",\r\n font !== \"normal\" && \"retro\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <span className=\"hidden sm:block\">Next</span>\r\n <ChevronRightIcon />\r\n </PaginationLink>\r\n );\r\n}\r\n\r\nfunction PaginationEllipsis({ ...props }: BitPaginationProps<\"span\">) {\r\n const { font, className } = props;\r\n\r\n return (\r\n <ShadcnPaginationEllipsis\r\n className={cn(font !== \"normal\" && \"retro\", className)}\r\n {...props}\r\n >\r\n <MoreHorizontal className={cn(\"size-7\", \"retro\")} />\r\n <span className=\"sr-only\">More pages</span>\r\n </ShadcnPaginationEllipsis>\r\n );\r\n}\r\n\r\nexport {\r\n Pagination,\r\n PaginationContent,\r\n PaginationLink,\r\n PaginationItem,\r\n PaginationPrevious,\r\n PaginationNext,\r\n PaginationEllipsis,\r\n};\r\n",
import { type VariantProps, cva } from "class-variance-authority";
import { MoreHorizontal } from "lucide-react";
import { cn } from "@/lib/utils";
import {
Pagination as ShadcnPagination,
PaginationContent as ShadcnPaginationContent,
PaginationEllipsis as ShadcnPaginationEllipsis,
PaginationItem as ShadcnPaginationItem,
PaginationLink as ShadcnPaginationLink,
} from "@/components/ui/pagination";
import { ChevronLeftIcon } from "@/components/ui/8bit/assets/chevronLeftIcon";
import { ChevronRightIcon } from "@/components/ui/8bit/assets/chevronRightIcon";
import { Button } from "../button";
import "./styles/retro.css";
export const paginationVariants = cva("", {
variants: {
font: {
normal: "",
retro: "retro",
},
variant: {
default: "text-card-foreground",
destructive:
"text-destructive [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
},
},
defaultVariants: {
variant: "default",
font: "normal",
},
});
export type BitPaginationProps<T extends React.ElementType> =
React.ComponentPropsWithoutRef<T> & VariantProps<typeof paginationVariants>;
function Pagination({ variant, className, font, ...rest }: BitPaginationProps<"nav">) {
return (
<ShadcnPagination
{...rest}
className={cn(
paginationVariants({ variant }),
font !== "normal" && "retro",
className
)}
/>
);
}
function PaginationContent({ className, font, ...rest }: BitPaginationProps<"ul">) {
return (
<ShadcnPaginationContent
className={cn("gap-2", font !== "normal" && "retro", className)}
{...rest}
/>
);
}
function PaginationItem({ className, font, ...rest }: BitPaginationProps<"li">) {
return (
<ShadcnPaginationItem
className={cn(font !== "normal" && "retro", className)}
{...rest}
/>
);
}
type PaginationLinkProps = {
isActive?: boolean;
} & Pick<React.ComponentProps<typeof Button>, "size"> &
BitPaginationProps<"a">;
function PaginationLink({ ...props }: PaginationLinkProps) {
const { font, children, isActive, className } = props;
return (
<ShadcnPaginationLink
className={cn(
font !== "normal" && "retro",
className,
"relative group",
"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent",
"rounded-none border-dashed border-y-4 border-transparent",
"dark:hover:border-ring dark:focus:border-ring",
"hover:border-foreground focus:border-foreground",
"active:border-transparent",
"data-[active=true]:border-none aria-[current=page]:border-none"
)}
{...props}
>
{children}
{isActive && (
<div
className="absolute inset-0 w-full h-full pointer-events-none"
style={{ zIndex: 10 }}
>
<div
className="absolute top-0 left-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
<div
className="absolute left-0 bottom-0 w-full h-1.5 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
<div
className="absolute top-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
<div
className="absolute bottom-1 -left-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
<div
className="absolute top-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
<div
className="absolute bottom-1 -right-1 w-1.5 h-1/2 bg-foreground dark:bg-ring pointer-events-none"
aria-hidden="true"
/>
</div>
)}
</ShadcnPaginationLink>
);
}
function PaginationPrevious({
...props
}: React.ComponentProps<typeof PaginationLink>) {
const { font, className } = props;
return (
<PaginationLink
className={cn(
"relative group",
"flex flex-row w-full text-sm",
"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent",
"rounded-none border-dashed border-y-4 border-transparent",
"hover:border-foreground focus:border-foreground active:border-transparent",
"dark:hover:border-ring dark:focus:border-ring",
"data-[active=true]:border-none aria-[current=page]:border-none",
font !== "normal" && "retro",
className
)}
{...props}
>
<ChevronLeftIcon />
<span className="hidden sm:block">Previous</span>
</PaginationLink>
);
}
function PaginationNext({
...props
}: React.ComponentProps<typeof PaginationLink>) {
const { font, className } = props;
return (
<PaginationLink
className={cn(
"relative group",
"flex flex-row w-full text-sm",
"bg-transparent hover:bg-transparent active:bg-transparent focus:bg-transparent",
"rounded-none border-dashed border-y-4 border-transparent",
"hover:border-foreground focus:border-foreground active:border-transparent",
"dark:hover:border-ring dark:focus:border-ring",
"data-[active=true]:border-none aria-[current=page]:border-none",
"flex flex-row text-sm w-full",
font !== "normal" && "retro",
className
)}
{...props}
>
<span className="hidden sm:block">Next</span>
<ChevronRightIcon />
</PaginationLink>
);
}
function PaginationEllipsis({ ...props }: BitPaginationProps<"span">) {
const { font, className } = props;
return (
<ShadcnPaginationEllipsis
className={cn(font !== "normal" && "retro", className)}
{...props}
>
<MoreHorizontal className={cn("size-7", "retro")} />
<span className="sr-only">More pages</span>
</ShadcnPaginationEllipsis>
);
}
export {
Pagination,
PaginationContent,
PaginationLink,
PaginationItem,
PaginationPrevious,
PaginationNext,
PaginationEllipsis,
};
🤖 Prompt for AI Agents
In public/r/8bit-pagination.json around line 13, design props "variant" and
"font" are leaking into the DOM because they are included in {...props} and the
paginationVariants has no default font; destructure and remove variant and font
from the rest props before spreading to underlying Shadcn components (e.g.,
function signatures should extract { variant, font, className, ...rest } and
spread {...rest} to avoid passing variant/font to DOM) and update
paginationVariants.defaultVariants to include font: "retro" so font defaults to
retro when undefined.

Copy link
Owner

@TheOrcDev TheOrcDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there! Thanks a lot for your contribution!

Good catch on those chevron icons, really appreciate the attention to detail. There’s just one thing we need to keep in mind: icons shouldn’t be exported from anywhere else in our project, because users of the 8bit components aren’t inside our codebase. Each icon needs to be included directly within its component, since that’s the only part users will be importing.

Your changes look great overall, we’ll just need to duplicate those SVGs in every component where they’re used.

@YarikDrago
Copy link
Author

Hey there! Thanks a lot for your contribution!

Good catch on those chevron icons, really appreciate the attention to detail. There’s just one thing we need to keep in mind: icons shouldn’t be exported from anywhere else in our project, because users of the 8bit components aren’t inside our codebase. Each icon needs to be included directly within its component, since that’s the only part users will be importing.

Your changes look great overall, we’ll just need to duplicate those SVGs in every component where they’re used.

Hey hey!
I'm not really on the topic. But it seems to me that writing the same code in different files is not a good practice. If you cannot import other components into files, but importing from third-party libraries is allowed (for example, from lucide-react), then you can create an additional library with reusable base components and styles so that uniformity is present in all files and when changing the style of a component, these changes are worked in all files.

@TheOrcDev
Copy link
Owner

Hey there! Thanks a lot for your contribution!
Good catch on those chevron icons, really appreciate the attention to detail. There’s just one thing we need to keep in mind: icons shouldn’t be exported from anywhere else in our project, because users of the 8bit components aren’t inside our codebase. Each icon needs to be included directly within its component, since that’s the only part users will be importing.
Your changes look great overall, we’ll just need to duplicate those SVGs in every component where they’re used.

Hey hey! I'm not really on the topic. But it seems to me that writing the same code in different files is not a good practice. If you cannot import other components into files, but importing from third-party libraries is allowed (for example, from lucide-react), then you can create an additional library with reusable base components and styles so that uniformity is present in all files and when changing the style of a component, these changes are worked in all files.

Yeah normally, duplicating code isn’t ideal.

The thing is, this isn’t actually about reusing icons inside our project. The main reason we keep the SVG directly inside each component is so that when a user imports just that one component from the library, it works immediately without pulling in other internal files or extra dependencies.

If we moved icons into a shared internal file, then importing a single component would break unless the user also had access to our internal icon file (which they don’t).

So in short, the duplication here is intentional, just to keep each component fully self contained for the end user.

Working on a UI component library is a little bit different, we must not think locally :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants