Code Snippet

Dynamically import and display code from your project files or external URLs without duplicating content in your documentation.

Overview

The ProseCodeSnippet component allows you to reference actual source files from your project or external URLs, ensuring your documentation always shows the latest code without manual updates. Perfect for keeping docs in sync with your codebase.

Features
  • Dynamic Imports - Load code directly from your project files
  • External URLs - Fetch code from GitHub, GitLab, or any URL
  • Line Extraction - Show specific line ranges from large files
  • Syntax Highlighting - Full language support via Shiki
  • Auto-sync - Documentation updates automatically when source code changes
  • Performance - Lazy loads files only when needed
Build Consideration
Files must match the import.meta.glob patterns in the component. The current setup includes all .vue, .ts, .css, and .json files from /app/** (excluding test files). Adjust patterns as needed for your use case.

Basic Usage

Import a component from your project:

vue

Button Component

<template>
  <component
    :is="elementType"
    :class="
      buttonStyles({
        hasIcon: !!icon,
        disabled: disabled || loading,
        variant: variant,
        size: size,
        class: props.class,
        effect: props.effect,
      })
    "
    :disabled="disabled || loading"
    v-bind="forwarded"
  >
    <slot name="iconLeft">
      <div
        v-if="icon && iconPlacement == 'left'"
        class="flex w-0 translate-x-[0%] pr-0 opacity-0 transition-all duration-200 group-hover:w-5 group-hover:translate-x-[0%] group-hover:pr-2 group-hover:opacity-100"
      >
        <Icon :name="icon" class="size-4" />
      </div>
    </slot>
    <slot name="loading">
      <Icon v-if="loading" class="size-4 shrink-0" :name="loadingIcon" />
    </slot>
    <slot>
      <span v-if="text">{{ text }}</span>
    </slot>
    <slot name="iconRight">
      <div
        v-if="icon && iconPlacement == 'right'"
        class="flex w-0 translate-x-[100%] pl-0 opacity-0 transition-all duration-200 group-hover:w-5 group-hover:translate-x-0 group-hover:pl-2 group-hover:opacity-100"
      >
        <Icon :name="icon" class="size-4" />
      </div>
    </slot>
  </component>
</template>

<script lang="ts">
  import { reactiveOmit } from "@vueuse/core";
  import { useForwardProps } from "reka-ui";
  import type { NuxtLinkProps } from "#app/components";
  import type { HtmlHTMLAttributes } from "vue";

  /**
   * Exported button styles that can be used by other components
   */
  export const buttonStyles = tv({
    base: "group inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
        destructive:
          "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
        outline:
          "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
        secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
        ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
        link: "text-primary underline-offset-4 hover:underline",
      },
      effect: {
        expandIcon: "group relative gap-0",
        ringHover: "transition-all duration-300 hover:ring-3 hover:ring-ring/50",
        shine:
          "relative overflow-hidden [background-position:0s_ease] before:absolute before:inset-0 before:animate-shine before:rounded-[inherit] before:bg-[linear-gradient(45deg,transparent_25%,rgba(255,255,255,0.5)_50%,transparent_75%,transparent_100%)] before:bg-[length:250%_250%,100%_100%] before:bg-no-repeat",
        shineHover:
          "relative overflow-hidden before:absolute before:inset-0 before:rounded-[inherit] before:bg-[linear-gradient(45deg,transparent_25%,rgba(255,255,255,0.5)_50%,transparent_75%,transparent_100%)] before:bg-[length:250%_250%,100%_100%] before:bg-[position:200%_0,0_0] before:bg-no-repeat before:transition-[background-position_0s_ease] before:duration-1000 hover:before:bg-[position:-100%_0,0_0]",
        gooeyRight:
          "relative z-0 overflow-hidden duration-500 before:absolute before:inset-0 before:-z-10 before:translate-x-[150%] before:translate-y-[150%] before:scale-[2.5] before:rounded-[100%] before:bg-gradient-to-r before:from-white/40 before:transition-transform before:duration-1000 hover:before:translate-x-[0%] hover:before:translate-y-[0%]",
        gooeyLeft:
          "relative z-0 overflow-hidden duration-500 after:absolute after:inset-0 after:-z-10 after:translate-x-[-150%] after:translate-y-[150%] after:scale-[2.5] after:rounded-[100%] after:bg-gradient-to-l after:from-white/40 after:transition-transform after:duration-1000 hover:after:translate-x-[0%] hover:after:translate-y-[0%]",
        underline:
          "relative !no-underline after:absolute after:bottom-2 after:h-[1px] after:w-2/3 after:origin-bottom-left after:scale-x-100 after:bg-primary after:transition-transform after:duration-300 after:ease-in-out hover:after:origin-bottom-right hover:after:scale-x-0",
        hoverUnderline:
          "relative !no-underline after:absolute after:bottom-2 after:h-[1px] after:w-2/3 after:origin-bottom-right after:scale-x-0 after:bg-primary after:transition-transform after:duration-300 after:ease-in-out hover:after:origin-bottom-left hover:after:scale-x-100",
        gradientSlideShow:
          "animate-gradient-flow bg-[linear-gradient(-45deg,var(--gradient-lime),var(--gradient-ocean),var(--gradient-wine),var(--gradient-rust))] bg-[size:400%] text-white",
      },
      size: {
        xs: "h-7 gap-1 px-2.5 text-xs has-[>svg]:px-2",
        sm: "h-8 gap-1.5 px-3 has-[>svg]:px-2.5",
        default: "h-9 px-4 py-2 has-[>svg]:px-3",
        lg: "h-10 px-6 has-[>svg]:px-4",
        "icon-xs": "size-7",
        "icon-sm": "size-8",
        icon: "size-9",
        "icon-lg": "size-10",
      },
      disabled: {
        true: "pointer-events-none opacity-50",
      },
      hasIcon: {
        false: "gap-2",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  });
  export type ButtonVariants = VariantProps<typeof buttonStyles>;
  export type ButtonProps = NuxtLinkProps & {
    /** The type for the button */
    type?: "button" | "submit" | "reset";
    /** Whether the button is disabled */
    disabled?: boolean;
    /** Whether the button is loading */
    loading?: boolean;
    /** The action to perform when the button is clicked */
    onClick?: any;
    /** The element to render the button as */
    as?: string;
    /** Custom class(es) to add to parent element */
    class?: HtmlHTMLAttributes["class"];
    /** The variant of the button */
    variant?: ButtonVariants["variant"];
    /** The size of the button */
    size?: ButtonVariants["size"];
    /**
     * The effect to apply to the button.
     */
    effect?: ButtonVariants["effect"];
    /** The text to display in the button */
    text?: string;
    /** Should the icon be displayed on the `left` or the `right`? */
    iconPlacement?: "left" | "right";
    /** The icon to display in the button */
    icon?: string;
    /** The icon to display when the button is loading */
    loadingIcon?: string;
  };
</script>

<script setup lang="ts">
  const props = withDefaults(defineProps<ButtonProps>(), {
    type: "button",
    loadingIcon: "line-md:loading-loop",
    iconPlacement: "left",
    loading: false,
  });

  const elementType = computed(() => {
    if (props.as) return props.as;
    if (props.href || props.to || props.target) return resolveComponent("NuxtLink");
    return "button";
  });

  const forwarded = useForwardProps(
    reactiveOmit(
      props,
      "class",
      "text",
      "icon",
      "iconPlacement",
      "size",
      "variant",
      "as",
      "loading",
      "disabled",
      "loadingIcon",
      "effect"
    )
  );
</script>

Import Project Files

Vue Components

Show your actual component code:

vue

Card

<template>
  <Primitive data-slot="card" :as="as" :as-child="asChild" :class="styles({ class: props.class })">
    <slot>
      <slot name="header">
        <UiCardHeader>
          <slot name="title">
            <UiCardTitle v-if="title || $slots.title" :title="title" />
          </slot>
          <slot name="description">
            <UiCardDescription
              v-if="description || $slots.description"
              :description="description"
            />
          </slot>
        </UiCardHeader>
      </slot>
      <slot v-if="content || $slots.content" name="content">
        <UiCardContent>
          <div v-html="content" />
        </UiCardContent>
      </slot>
      <slot name="footer" />
    </slot>
  </Primitive>
</template>

<script lang="ts" setup>
  import { Primitive } from "reka-ui";
  import type { PrimitiveProps } from "reka-ui";
  import type { HTMLAttributes } from "vue";

  const props = withDefaults(
    defineProps<
      PrimitiveProps & {
        /** Title that should be displayed. Passed to the `CardTitle` component */
        title?: string;
        /** Description that should be displayed. Passed to the `CardDescription` component */
        description?: string;
        /** Content that should be displayed. Passed to the `CardContent` component */
        content?: string;
        /** Custom class(es) to add to the element */
        class?: HTMLAttributes["class"];
      }
    >(),
    { as: "div" }
  );

  const styles = tv({
    base: "flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm",
  });
</script>

TypeScript Utilities

Reference utility functions:

ts

Color Utilities

export const colors = {
  inherit: "inherit",
  current: "currentColor",
  transparent: "transparent",
  black: {
    hex: "#000000",
    rgb: "rgb(0,0,0)",
    hsl: "hsl(0,0%,0%)",
  },
  white: {
    hex: "#ffffff",
    rgb: "rgb(255,255,255)",
    hsl: "hsl(0,0%,100%)",
  },
  slate: [
    {
      scale: 50,
      hex: "#f8fafc",
      rgb: "rgb(248,250,252)",
      hsl: "hsl(210,40%,98%)",
    },
    {
      scale: 100,
      hex: "#f1f5f9",
      rgb: "rgb(241,245,249)",
      hsl: "hsl(210,40%,96.1%)",
    },
    {
      scale: 200,
      hex: "#e2e8f0",
      rgb: "rgb(226,232,240)",
      hsl: "hsl(214.3,31.8%,91.4%)",
    },
    {
      scale: 300,
      hex: "#cbd5e1",
      rgb: "rgb(203,213,225)",
      hsl: "hsl(212.7,26.8%,83.9%)",
    },
    {
      scale: 400,
      hex: "#94a3b8",
      rgb: "rgb(148,163,184)",
      hsl: "hsl(215,20.2%,65.1%)",
    },
    {
      scale: 500,
      hex: "#64748b",
      rgb: "rgb(100,116,139)",
      hsl: "hsl(215.4,16.3%,46.9%)",
    },
    {
      scale: 600,
      hex: "#475569",
      rgb: "rgb(71,85,105)",
      hsl: "hsl(215.3,19.3%,34.5%)",
    },
    {
      scale: 700,
      hex: "#334155",
      rgb: "rgb(51,65,85)",
      hsl: "hsl(215.3,25%,26.7%)",
    },
    {
      scale: 800,
      hex: "#1e293b",
      rgb: "rgb(30,41,59)",
      hsl: "hsl(217.2,32.6%,17.5%)",
    },
    {
      scale: 900,
      hex: "#0f172a",
      rgb: "rgb(15,23,42)",
      hsl: "hsl(222.2,47.4%,11.2%)",
    },
    {
      scale: 950,
      hex: "#020617",
      rgb: "rgb(2,6,23)",
      hsl: "hsl(222.2,84%,4.9%)",
    },
  ],
  gray: [
    {
      scale: 50,
      hex: "#f9fafb",
      rgb: "rgb(249,250,251)",
      hsl: "hsl(210,20%,98%)",
    },
    {
      scale: 100,
      hex: "#f3f4f6",
      rgb: "rgb(243,244,246)",
      hsl: "hsl(220,14.3%,95.9%)",
    },
    {
      scale: 200,
      hex: "#e5e7eb",
      rgb: "rgb(229,231,235)",
      hsl: "hsl(220,13%,91%)",
    },
    {
      scale: 300,
      hex: "#d1d5db",
      rgb: "rgb(209,213,219)",
      hsl: "hsl(216,12.2%,83.9%)",
    },
    {
      scale: 400,
      hex: "#9ca3af",
      rgb: "rgb(156,163,175)",
      hsl: "hsl(217.9,10.6%,64.9%)",
    },
    {
      scale: 500,
      hex: "#6b7280",
      rgb: "rgb(107,114,128)",
      hsl: "hsl(220,8.9%,46.1%)",
    },
    {
      scale: 600,
      hex: "#4b5563",
      rgb: "rgb(75,85,99)",
      hsl: "hsl(215,13.8%,34.1%)",
    },
    {
      scale: 700,
      hex: "#374151",
      rgb: "rgb(55,65,81)",
      hsl: "hsl(216.9,19.1%,26.7%)",
    },
    {
      scale: 800,
      hex: "#1f2937",
      rgb: "rgb(31,41,55)",
      hsl: "hsl(215,27.9%,16.9%)",
    },
    {
      scale: 900,
      hex: "#111827",
      rgb: "rgb(17,24,39)",
      hsl: "hsl(220.9,39.3%,11%)",
    },
    {
      scale: 950,
      hex: "#030712",
      rgb: "rgb(3,7,18)",
      hsl: "hsl(224,71.4%,4.1%)",
    },
  ],
  zinc: [
    {
      scale: 50,
      hex: "#fafafa",
      rgb: "rgb(250,250,250)",
      hsl: "hsl(0,0%,98%)",
    },
    {
      scale: 100,
      hex: "#f4f4f5",
      rgb: "rgb(244,244,245)",
      hsl: "hsl(240,4.8%,95.9%)",
    },
    {
      scale: 200,
      hex: "#e4e4e7",
      rgb: "rgb(228,228,231)",
      hsl: "hsl(240,5.9%,90%)",
    },
    {
      scale: 300,
      hex: "#d4d4d8",
      rgb: "rgb(212,212,216)",
      hsl: "hsl(240,4.9%,83.9%)",
    },
    {
      scale: 400,
      hex: "#a1a1aa",
      rgb: "rgb(161,161,170)",
      hsl: "hsl(240,5%,64.9%)",
    },
    {
      scale: 500,
      hex: "#71717a",
      rgb: "rgb(113,113,122)",
      hsl: "hsl(240,3.8%,46.1%)",
    },
    {
      scale: 600,
      hex: "#52525b",
      rgb: "rgb(82,82,91)",
      hsl: "hsl(240,5.2%,33.9%)",
    },
    {
      scale: 700,
      hex: "#3f3f46",
      rgb: "rgb(63,63,70)",
      hsl: "hsl(240,5.3%,26.1%)",
    },
    {
      scale: 800,
      hex: "#27272a",
      rgb: "rgb(39,39,42)",
      hsl: "hsl(240,3.7%,15.9%)",
    },
    {
      scale: 900,
      hex: "#18181b",
      rgb: "rgb(24,24,27)",
      hsl: "hsl(240,5.9%,10%)",
    },
    {
      scale: 950,
      hex: "#09090b",
      rgb: "rgb(9,9,11)",
      hsl: "hsl(240,10%,3.9%)",
    },
  ],
  neutral: [
    {
      scale: 50,
      hex: "#fafafa",
      rgb: "rgb(250,250,250)",
      hsl: "hsl(0,0%,98%)",
    },
    {
      scale: 100,
      hex: "#f5f5f5",
      rgb: "rgb(245,245,245)",
      hsl: "hsl(0,0%,96.1%)",
    },
    {
      scale: 200,
      hex: "#e5e5e5",
      rgb: "rgb(229,229,229)",
      hsl: "hsl(0,0%,89.8%)",
    },
    {
      scale: 300,
      hex: "#d4d4d4",
      rgb: "rgb(212,212,212)",
      hsl: "hsl(0,0%,83.1%)",
    },
    {
      scale: 400,
      hex: "#a3a3a3",
      rgb: "rgb(163,163,163)",
      hsl: "hsl(0,0%,63.9%)",
    },
    {
      scale: 500,
      hex: "#737373",
      rgb: "rgb(115,115,115)",
      hsl: "hsl(0,0%,45.1%)",
    },
    {
      scale: 600,
      hex: "#525252",
      rgb: "rgb(82,82,82)",
      hsl: "hsl(0,0%,32.2%)",
    },
    {
      scale: 700,
      hex: "#404040",
      rgb: "rgb(64,64,64)",
      hsl: "hsl(0,0%,25.1%)",
    },
    {
      scale: 800,
      hex: "#262626",
      rgb: "rgb(38,38,38)",
      hsl: "hsl(0,0%,14.9%)",
    },
    {
      scale: 900,
      hex: "#171717",
      rgb: "rgb(23,23,23)",
      hsl: "hsl(0,0%,9%)",
    },
    {
      scale: 950,
      hex: "#0a0a0a",
      rgb: "rgb(10,10,10)",
      hsl: "hsl(0,0%,3.9%)",
    },
  ],
  stone: [
    {
      scale: 50,
      hex: "#fafaf9",
      rgb: "rgb(250,250,249)",
      hsl: "hsl(60,9.1%,97.8%)",
    },
    {
      scale: 100,
      hex: "#f5f5f4",
      rgb: "rgb(245,245,244)",
      hsl: "hsl(60,4.8%,95.9%)",
    },
    {
      scale: 200,
      hex: "#e7e5e4",
      rgb: "rgb(231,229,228)",
      hsl: "hsl(20,5.9%,90%)",
    },
    {
      scale: 300,
      hex: "#d6d3d1",
      rgb: "rgb(214,211,209)",
      hsl: "hsl(24,5.7%,82.9%)",
    },
    {
      scale: 400,
      hex: "#a8a29e",
      rgb: "rgb(168,162,158)",
      hsl: "hsl(24,5.4%,63.9%)",
    },
    {
      scale: 500,
      hex: "#78716c",
      rgb: "rgb(120,113,108)",
      hsl: "hsl(25,5.3%,44.7%)",
    },
    {
      scale: 600,
      hex: "#57534e",
      rgb: "rgb(87,83,78)",
      hsl: "hsl(33.3,5.5%,32.4%)",
    },
    {
      scale: 700,
      hex: "#44403c",
      rgb: "rgb(68,64,60)",
      hsl: "hsl(30,6.3%,25.1%)",
    },
    {
      scale: 800,
      hex: "#292524",
      rgb: "rgb(41,37,36)",
      hsl: "hsl(12,6.5%,15.1%)",
    },
    {
      scale: 900,
      hex: "#1c1917",
      rgb: "rgb(28,25,23)",
      hsl: "hsl(24,9.8%,10%)",
    },
    {
      scale: 950,
      hex: "#0c0a09",
      rgb: "rgb(12,10,9)",
      hsl: "hsl(20,14.3%,4.1%)",
    },
  ],
  red: [
    {
      scale: 50,
      hex: "#fef2f2",
      rgb: "rgb(254,242,242)",
      hsl: "hsl(0,85.7%,97.3%)",
    },
    {
      scale: 100,
      hex: "#fee2e2",
      rgb: "rgb(254,226,226)",
      hsl: "hsl(0,93.3%,94.1%)",
    },
    {
      scale: 200,
      hex: "#fecaca",
      rgb: "rgb(254,202,202)",
      hsl: "hsl(0,96.3%,89.4%)",
    },
    {
      scale: 300,
      hex: "#fca5a5",
      rgb: "rgb(252,165,165)",
      hsl: "hsl(0,93.5%,81.8%)",
    },
    {
      scale: 400,
      hex: "#f87171",
      rgb: "rgb(248,113,113)",
      hsl: "hsl(0,90.6%,70.8%)",
    },
    {
      scale: 500,
      hex: "#ef4444",
      rgb: "rgb(239,68,68)",
      hsl: "hsl(0,84.2%,60.2%)",
    },
    {
      scale: 600,
      hex: "#dc2626",
      rgb: "rgb(220,38,38)",
      hsl: "hsl(0,72.2%,50.6%)",
    },
    {
      scale: 700,
      hex: "#b91c1c",
      rgb: "rgb(185,28,28)",
      hsl: "hsl(0,73.7%,41.8%)",
    },
    {
      scale: 800,
      hex: "#991b1b",
      rgb: "rgb(153,27,27)",
      hsl: "hsl(0,70%,35.3%)",
    },
    {
      scale: 900,
      hex: "#7f1d1d",
      rgb: "rgb(127,29,29)",
      hsl: "hsl(0,62.8%,30.6%)",
    },
    {
      scale: 950,
      hex: "#450a0a",
      rgb: "rgb(69,10,10)",
      hsl: "hsl(0,74.7%,15.5%)",
    },
  ],
  orange: [
    {
      scale: 50,
      hex: "#fff7ed",
      rgb: "rgb(255,247,237)",
      hsl: "hsl(33.3,100%,96.5%)",
    },
    {
      scale: 100,
      hex: "#ffedd5",
      rgb: "rgb(255,237,213)",
      hsl: "hsl(34.3,100%,91.8%)",
    },
    {
      scale: 200,
      hex: "#fed7aa",
      rgb: "rgb(254,215,170)",
      hsl: "hsl(32.1,97.7%,83.1%)",
    },
    {
      scale: 300,
      hex: "#fdba74",
      rgb: "rgb(253,186,116)",
      hsl: "hsl(30.7,97.2%,72.4%)",
    },
    {
      scale: 400,
      hex: "#fb923c",
      rgb: "rgb(251,146,60)",
      hsl: "hsl(27,96%,61%)",
    },
    {
      scale: 500,
      hex: "#f97316",
      rgb: "rgb(249,115,22)",
      hsl: "hsl(24.6,95%,53.1%)",
    },
    {
      scale: 600,
      hex: "#ea580c",
      rgb: "rgb(234,88,12)",
      hsl: "hsl(20.5,90.2%,48.2%)",
    },
    {
      scale: 700,
      hex: "#c2410c",
      rgb: "rgb(194,65,12)",
      hsl: "hsl(17.5,88.3%,40.4%)",
    },
    {
      scale: 800,
      hex: "#9a3412",
      rgb: "rgb(154,52,18)",
      hsl: "hsl(15,79.1%,33.7%)",
    },
    {
      scale: 900,
      hex: "#7c2d12",
      rgb: "rgb(124,45,18)",
      hsl: "hsl(15.3,74.6%,27.8%)",
    },
    {
      scale: 950,
      hex: "#431407",
      rgb: "rgb(67,20,7)",
      hsl: "hsl(13,81.1%,14.5%)",
    },
  ],
  amber: [
    {
      scale: 50,
      hex: "#fffbeb",
      rgb: "rgb(255,251,235)",
      hsl: "hsl(48,100%,96.1%)",
    },
    {
      scale: 100,
      hex: "#fef3c7",
      rgb: "rgb(254,243,199)",
      hsl: "hsl(48,96.5%,88.8%)",
    },
    {
      scale: 200,
      hex: "#fde68a",
      rgb: "rgb(253,230,138)",
      hsl: "hsl(48,96.6%,76.7%)",
    },
    {
      scale: 300,
      hex: "#fcd34d",
      rgb: "rgb(252,211,77)",
      hsl: "hsl(45.9,96.7%,64.5%)",
    },
    {
      scale: 400,
      hex: "#fbbf24",
      rgb: "rgb(251,191,36)",
      hsl: "hsl(43.3,96.4%,56.3%)",
    },
    {
      scale: 500,
      hex: "#f59e0b",
      rgb: "rgb(245,158,11)",
      hsl: "hsl(37.7,92.1%,50.2%)",
    },
    {
      scale: 600,
      hex: "#d97706",
      rgb: "rgb(217,119,6)",
      hsl: "hsl(32.1,94.6%,43.7%)",
    },
    {
      scale: 700,
      hex: "#b45309",
      rgb: "rgb(180,83,9)",
      hsl: "hsl(26,90.5%,37.1%)",
    },
    {
      scale: 800,
      hex: "#92400e",
      rgb: "rgb(146,64,14)",
      hsl: "hsl(22.7,82.5%,31.4%)",
    },
    {
      scale: 900,
      hex: "#78350f",
      rgb: "rgb(120,53,15)",
      hsl: "hsl(21.7,77.8%,26.5%)",
    },
    {
      scale: 950,
      hex: "#451a03",
      rgb: "rgb(69,26,3)",
      hsl: "hsl(20.9,91.7%,14.1%)",
    },
  ],
  yellow: [
    {
      scale: 50,
      hex: "#fefce8",
      rgb: "rgb(254,252,232)",
      hsl: "hsl(54.5,91.7%,95.3%)",
    },
    {
      scale: 100,
      hex: "#fef9c3",
      rgb: "rgb(254,249,195)",
      hsl: "hsl(54.9,96.7%,88%)",
    },
    {
      scale: 200,
      hex: "#fef08a",
      rgb: "rgb(254,240,138)",
      hsl: "hsl(52.8,98.3%,76.9%)",
    },
    {
      scale: 300,
      hex: "#fde047",
      rgb: "rgb(253,224,71)",
      hsl: "hsl(50.4,97.8%,63.5%)",
    },
    {
      scale: 400,
      hex: "#facc15",
      rgb: "rgb(250,204,21)",
      hsl: "hsl(47.9,95.8%,53.1%)",
    },
    {
      scale: 500,
      hex: "#eab308",
      rgb: "rgb(234,179,8)",
      hsl: "hsl(45.4,93.4%,47.5%)",
    },
    {
      scale: 600,
      hex: "#ca8a04",
      rgb: "rgb(202,138,4)",
      hsl: "hsl(40.6,96.1%,40.4%)",
    },
    {
      scale: 700,
      hex: "#a16207",
      rgb: "rgb(161,98,7)",
      hsl: "hsl(35.5,91.7%,32.9%)",
    },
    {
      scale: 800,
      hex: "#854d0e",
      rgb: "rgb(133,77,14)",
      hsl: "hsl(31.8,81%,28.8%)",
    },
    {
      scale: 900,
      hex: "#713f12",
      rgb: "rgb(113,63,18)",
      hsl: "hsl(28.4,72.5%,25.7%)",
    },
    {
      scale: 950,
      hex: "#422006",
      rgb: "rgb(66,32,6)",
      hsl: "hsl(26,83.3%,14.1%)",
    },
  ],
  lime: [
    {
      scale: 50,
      hex: "#f7fee7",
      rgb: "rgb(247,254,231)",
      hsl: "hsl(78.3,92%,95.1%)",
    },
    {
      scale: 100,
      hex: "#ecfccb",
      rgb: "rgb(236,252,203)",
      hsl: "hsl(79.6,89.1%,89.2%)",
    },
    {
      scale: 200,
      hex: "#d9f99d",
      rgb: "rgb(217,249,157)",
      hsl: "hsl(80.9,88.5%,79.6%)",
    },
    {
      scale: 300,
      hex: "#bef264",
      rgb: "rgb(190,242,100)",
      hsl: "hsl(82,84.5%,67.1%)",
    },
    {
      scale: 400,
      hex: "#a3e635",
      rgb: "rgb(163,230,53)",
      hsl: "hsl(82.7,78%,55.5%)",
    },
    {
      scale: 500,
      hex: "#84cc16",
      rgb: "rgb(132,204,22)",
      hsl: "hsl(83.7,80.5%,44.3%)",
    },
    {
      scale: 600,
      hex: "#65a30d",
      rgb: "rgb(101,163,13)",
      hsl: "hsl(84.8,85.2%,34.5%)",
    },
    {
      scale: 700,
      hex: "#4d7c0f",
      rgb: "rgb(77,124,15)",
      hsl: "hsl(85.9,78.4%,27.3%)",
    },
    {
      scale: 800,
      hex: "#3f6212",
      rgb: "rgb(63,98,18)",
      hsl: "hsl(86.3,69%,22.7%)",
    },
    {
      scale: 900,
      hex: "#365314",
      rgb: "rgb(54,83,20)",
      hsl: "hsl(87.6,61.2%,20.2%)",
    },
    {
      scale: 950,
      hex: "#1a2e05",
      rgb: "rgb(26,46,5)",
      hsl: "hsl(89.3,80.4%,10%)",
    },
  ],
  green: [
    {
      scale: 50,
      hex: "#f0fdf4",
      rgb: "rgb(240,253,244)",
      hsl: "hsl(138.5,76.5%,96.7%)",
    },
    {
      scale: 100,
      hex: "#dcfce7",
      rgb: "rgb(220,252,231)",
      hsl: "hsl(140.6,84.2%,92.5%)",
    },
    {
      scale: 200,
      hex: "#bbf7d0",
      rgb: "rgb(187,247,208)",
      hsl: "hsl(141,78.9%,85.1%)",
    },
    {
      scale: 300,
      hex: "#86efac",
      rgb: "rgb(134,239,172)",
      hsl: "hsl(141.7,76.6%,73.1%)",
    },
    {
      scale: 400,
      hex: "#4ade80",
      rgb: "rgb(74,222,128)",
      hsl: "hsl(141.9,69.2%,58%)",
    },
    {
      scale: 500,
      hex: "#22c55e",
      rgb: "rgb(34,197,94)",
      hsl: "hsl(142.1,70.6%,45.3%)",
    },
    {
      scale: 600,
      hex: "#16a34a",
      rgb: "rgb(22,163,74)",
      hsl: "hsl(142.1,76.2%,36.3%)",
    },
    {
      scale: 700,
      hex: "#15803d",
      rgb: "rgb(21,128,61)",
      hsl: "hsl(142.4,71.8%,29.2%)",
    },
    {
      scale: 800,
      hex: "#166534",
      rgb: "rgb(22,101,52)",
      hsl: "hsl(142.8,64.2%,24.1%)",
    },
    {
      scale: 900,
      hex: "#14532d",
      rgb: "rgb(20,83,45)",
      hsl: "hsl(143.8,61.2%,20.2%)",
    },
    {
      scale: 950,
      hex: "#052e16",
      rgb: "rgb(5,46,22)",
      hsl: "hsl(144.9,80.4%,10%)",
    },
  ],
  emerald: [
    {
      scale: 50,
      hex: "#ecfdf5",
      rgb: "rgb(236,253,245)",
      hsl: "hsl(151.8,81%,95.9%)",
    },
    {
      scale: 100,
      hex: "#d1fae5",
      rgb: "rgb(209,250,229)",
      hsl: "hsl(149.3,80.4%,90%)",
    },
    {
      scale: 200,
      hex: "#a7f3d0",
      rgb: "rgb(167,243,208)",
      hsl: "hsl(152.4,76%,80.4%)",
    },
    {
      scale: 300,
      hex: "#6ee7b7",
      rgb: "rgb(110,231,183)",
      hsl: "hsl(156.2,71.6%,66.9%)",
    },
    {
      scale: 400,
      hex: "#34d399",
      rgb: "rgb(52,211,153)",
      hsl: "hsl(158.1,64.4%,51.6%)",
    },
    {
      scale: 500,
      hex: "#10b981",
      rgb: "rgb(16,185,129)",
      hsl: "hsl(160.1,84.1%,39.4%)",
    },
    {
      scale: 600,
      hex: "#059669",
      rgb: "rgb(5,150,105)",
      hsl: "hsl(161.4,93.5%,30.4%)",
    },
    {
      scale: 700,
      hex: "#047857",
      rgb: "rgb(4,120,87)",
      hsl: "hsl(162.9,93.5%,24.3%)",
    },
    {
      scale: 800,
      hex: "#065f46",
      rgb: "rgb(6,95,70)",
      hsl: "hsl(163.1,88.1%,19.8%)",
    },
    {
      scale: 900,
      hex: "#064e3b",
      rgb: "rgb(6,78,59)",
      hsl: "hsl(164.2,85.7%,16.5%)",
    },
    {
      scale: 950,
      hex: "#022c22",
      rgb: "rgb(2,44,34)",
      hsl: "hsl(165.7,91.3%,9%)",
    },
  ],
  teal: [
    {
      scale: 50,
      hex: "#f0fdfa",
      rgb: "rgb(240,253,250)",
      hsl: "hsl(166.2,76.5%,96.7%)",
    },
    {
      scale: 100,
      hex: "#ccfbf1",
      rgb: "rgb(204,251,241)",
      hsl: "hsl(167.2,85.5%,89.2%)",
    },
    {
      scale: 200,
      hex: "#99f6e4",
      rgb: "rgb(153,246,228)",
      hsl: "hsl(168.4,83.8%,78.2%)",
    },
    {
      scale: 300,
      hex: "#5eead4",
      rgb: "rgb(94,234,212)",
      hsl: "hsl(170.6,76.9%,64.3%)",
    },
    {
      scale: 400,
      hex: "#2dd4bf",
      rgb: "rgb(45,212,191)",
      hsl: "hsl(172.5,66%,50.4%)",
    },
    {
      scale: 500,
      hex: "#14b8a6",
      rgb: "rgb(20,184,166)",
      hsl: "hsl(173.4,80.4%,40%)",
    },
    {
      scale: 600,
      hex: "#0d9488",
      rgb: "rgb(13,148,136)",
      hsl: "hsl(174.7,83.9%,31.6%)",
    },
    {
      scale: 700,
      hex: "#0f766e",
      rgb: "rgb(15,118,110)",
      hsl: "hsl(175.3,77.4%,26.1%)",
    },
    {
      scale: 800,
      hex: "#115e59",
      rgb: "rgb(17,94,89)",
      hsl: "hsl(176.1,69.4%,21.8%)",
    },
    {
      scale: 900,
      hex: "#134e4a",
      rgb: "rgb(19,78,74)",
      hsl: "hsl(175.9,60.8%,19%)",
    },
    {
      scale: 950,
      hex: "#042f2e",
      rgb: "rgb(4,47,46)",
      hsl: "hsl(178.6,84.3%,10%)",
    },
  ],
  cyan: [
    {
      scale: 50,
      hex: "#ecfeff",
      rgb: "rgb(236,254,255)",
      hsl: "hsl(183.2,100%,96.3%)",
    },
    {
      scale: 100,
      hex: "#cffafe",
      rgb: "rgb(207,250,254)",
      hsl: "hsl(185.1,95.9%,90.4%)",
    },
    {
      scale: 200,
      hex: "#a5f3fc",
      rgb: "rgb(165,243,252)",
      hsl: "hsl(186.2,93.5%,81.8%)",
    },
    {
      scale: 300,
      hex: "#67e8f9",
      rgb: "rgb(103,232,249)",
      hsl: "hsl(187,92.4%,69%)",
    },
    {
      scale: 400,
      hex: "#22d3ee",
      rgb: "rgb(34,211,238)",
      hsl: "hsl(187.9,85.7%,53.3%)",
    },
    {
      scale: 500,
      hex: "#06b6d4",
      rgb: "rgb(6,182,212)",
      hsl: "hsl(188.7,94.5%,42.7%)",
    },
    {
      scale: 600,
      hex: "#0891b2",
      rgb: "rgb(8,145,178)",
      hsl: "hsl(191.6,91.4%,36.5%)",
    },
    {
      scale: 700,
      hex: "#0e7490",
      rgb: "rgb(14,116,144)",
      hsl: "hsl(192.9,82.3%,31%)",
    },
    {
      scale: 800,
      hex: "#155e75",
      rgb: "rgb(21,94,117)",
      hsl: "hsl(194.4,69.6%,27.1%)",
    },
    {
      scale: 900,
      hex: "#164e63",
      rgb: "rgb(22,78,99)",
      hsl: "hsl(196.4,63.6%,23.7%)",
    },
    {
      scale: 950,
      hex: "#083344",
      rgb: "rgb(8,51,68)",
      hsl: "hsl(197,78.9%,14.9%)",
    },
  ],
  sky: [
    {
      scale: 50,
      hex: "#f0f9ff",
      rgb: "rgb(240,249,255)",
      hsl: "hsl(204,100%,97.1%)",
    },
    {
      scale: 100,
      hex: "#e0f2fe",
      rgb: "rgb(224,242,254)",
      hsl: "hsl(204,93.8%,93.7%)",
    },
    {
      scale: 200,
      hex: "#bae6fd",
      rgb: "rgb(186,230,253)",
      hsl: "hsl(200.6,94.4%,86.1%)",
    },
    {
      scale: 300,
      hex: "#7dd3fc",
      rgb: "rgb(125,211,252)",
      hsl: "hsl(199.4,95.5%,73.9%)",
    },
    {
      scale: 400,
      hex: "#38bdf8",
      rgb: "rgb(56,189,248)",
      hsl: "hsl(198.4,93.2%,59.6%)",
    },
    {
      scale: 500,
      hex: "#0ea5e9",
      rgb: "rgb(14,165,233)",
      hsl: "hsl(198.6,88.7%,48.4%)",
    },
    {
      scale: 600,
      hex: "#0284c7",
      rgb: "rgb(2,132,199)",
      hsl: "hsl(200.4,98%,39.4%)",
    },
    {
      scale: 700,
      hex: "#0369a1",
      rgb: "rgb(3,105,161)",
      hsl: "hsl(201.3,96.3%,32.2%)",
    },
    {
      scale: 800,
      hex: "#075985",
      rgb: "rgb(7,89,133)",
      hsl: "hsl(201,90%,27.5%)",
    },
    {
      scale: 900,
      hex: "#0c4a6e",
      rgb: "rgb(12,74,110)",
      hsl: "hsl(202,80.3%,23.9%)",
    },
    {
      scale: 950,
      hex: "#082f49",
      rgb: "rgb(8,47,73)",
      hsl: "hsl(204,80.2%,15.9%)",
    },
  ],
  blue: [
    {
      scale: 50,
      hex: "#eff6ff",
      rgb: "rgb(239,246,255)",
      hsl: "hsl(213.8,100%,96.9%)",
    },
    {
      scale: 100,
      hex: "#dbeafe",
      rgb: "rgb(219,234,254)",
      hsl: "hsl(214.3,94.6%,92.7%)",
    },
    {
      scale: 200,
      hex: "#bfdbfe",
      rgb: "rgb(191,219,254)",
      hsl: "hsl(213.3,96.9%,87.3%)",
    },
    {
      scale: 300,
      hex: "#93c5fd",
      rgb: "rgb(147,197,253)",
      hsl: "hsl(211.7,96.4%,78.4%)",
    },
    {
      scale: 400,
      hex: "#60a5fa",
      rgb: "rgb(96,165,250)",
      hsl: "hsl(213.1,93.9%,67.8%)",
    },
    {
      scale: 500,
      hex: "#3b82f6",
      rgb: "rgb(59,130,246)",
      hsl: "hsl(217.2,91.2%,59.8%)",
    },
    {
      scale: 600,
      hex: "#2563eb",
      rgb: "rgb(37,99,235)",
      hsl: "hsl(221.2,83.2%,53.3%)",
    },
    {
      scale: 700,
      hex: "#1d4ed8",
      rgb: "rgb(29,78,216)",
      hsl: "hsl(224.3,76.3%,48%)",
    },
    {
      scale: 800,
      hex: "#1e40af",
      rgb: "rgb(30,64,175)",
      hsl: "hsl(225.9,70.7%,40.2%)",
    },
    {
      scale: 900,
      hex: "#1e3a8a",
      rgb: "rgb(30,58,138)",
      hsl: "hsl(224.4,64.3%,32.9%)",
    },
    {
      scale: 950,
      hex: "#172554",
      rgb: "rgb(23,37,84)",
      hsl: "hsl(226.2,57%,21%)",
    },
  ],
  indigo: [
    {
      scale: 50,
      hex: "#eef2ff",
      rgb: "rgb(238,242,255)",
      hsl: "hsl(225.9,100%,96.7%)",
    },
    {
      scale: 100,
      hex: "#e0e7ff",
      rgb: "rgb(224,231,255)",
      hsl: "hsl(226.5,100%,93.9%)",
    },
    {
      scale: 200,
      hex: "#c7d2fe",
      rgb: "rgb(199,210,254)",
      hsl: "hsl(228,96.5%,88.8%)",
    },
    {
      scale: 300,
      hex: "#a5b4fc",
      rgb: "rgb(165,180,252)",
      hsl: "hsl(229.7,93.5%,81.8%)",
    },
    {
      scale: 400,
      hex: "#818cf8",
      rgb: "rgb(129,140,248)",
      hsl: "hsl(234.5,89.5%,73.9%)",
    },
    {
      scale: 500,
      hex: "#6366f1",
      rgb: "rgb(99,102,241)",
      hsl: "hsl(238.7,83.5%,66.7%)",
    },
    {
      scale: 600,
      hex: "#4f46e5",
      rgb: "rgb(79,70,229)",
      hsl: "hsl(243.4,75.4%,58.6%)",
    },
    {
      scale: 700,
      hex: "#4338ca",
      rgb: "rgb(67,56,202)",
      hsl: "hsl(244.5,57.9%,50.6%)",
    },
    {
      scale: 800,
      hex: "#3730a3",
      rgb: "rgb(55,48,163)",
      hsl: "hsl(243.7,54.5%,41.4%)",
    },
    {
      scale: 900,
      hex: "#312e81",
      rgb: "rgb(49,46,129)",
      hsl: "hsl(242.2,47.4%,34.3%)",
    },
    {
      scale: 950,
      hex: "#1e1b4b",
      rgb: "rgb(30,27,75)",
      hsl: "hsl(243.8,47.1%,20%)",
    },
  ],
  violet: [
    {
      scale: 50,
      hex: "#f5f3ff",
      rgb: "rgb(245,243,255)",
      hsl: "hsl(250,100%,97.6%)",
    },
    {
      scale: 100,
      hex: "#ede9fe",
      rgb: "rgb(237,233,254)",
      hsl: "hsl(251.4,91.3%,95.5%)",
    },
    {
      scale: 200,
      hex: "#ddd6fe",
      rgb: "rgb(221,214,254)",
      hsl: "hsl(250.5,95.2%,91.8%)",
    },
    {
      scale: 300,
      hex: "#c4b5fd",
      rgb: "rgb(196,181,253)",
      hsl: "hsl(252.5,94.7%,85.1%)",
    },
    {
      scale: 400,
      hex: "#a78bfa",
      rgb: "rgb(167,139,250)",
      hsl: "hsl(255.1,91.7%,76.3%)",
    },
    {
      scale: 500,
      hex: "#8b5cf6",
      rgb: "rgb(139,92,246)",
      hsl: "hsl(258.3,89.5%,66.3%)",
    },
    {
      scale: 600,
      hex: "#7c3aed",
      rgb: "rgb(124,58,237)",
      hsl: "hsl(262.1,83.3%,57.8%)",
    },
    {
      scale: 700,
      hex: "#6d28d9",
      rgb: "rgb(109,40,217)",
      hsl: "hsl(263.4,70%,50.4%)",
    },
    {
      scale: 800,
      hex: "#5b21b6",
      rgb: "rgb(91,33,182)",
      hsl: "hsl(263.4,69.3%,42.2%)",
    },
    {
      scale: 900,
      hex: "#4c1d95",
      rgb: "rgb(76,29,149)",
      hsl: "hsl(263.5,67.4%,34.9%)",
    },
    {
      scale: 950,
      hex: "#1e1b4b",
      rgb: "rgb(46,16,101)",
      hsl: "hsl(261.2,72.6%,22.9%)",
    },
  ],
  purple: [
    {
      scale: 50,
      hex: "#faf5ff",
      rgb: "rgb(250,245,255)",
      hsl: "hsl(270,100%,98%)",
    },
    {
      scale: 100,
      hex: "#f3e8ff",
      rgb: "rgb(243,232,255)",
      hsl: "hsl(268.7,100%,95.5%)",
    },
    {
      scale: 200,
      hex: "#e9d5ff",
      rgb: "rgb(233,213,255)",
      hsl: "hsl(268.6,100%,91.8%)",
    },
    {
      scale: 300,
      hex: "#d8b4fe",
      rgb: "rgb(216,180,254)",
      hsl: "hsl(269.2,97.4%,85.1%)",
    },
    {
      scale: 400,
      hex: "#c084fc",
      rgb: "rgb(192,132,252)",
      hsl: "hsl(270,95.2%,75.3%)",
    },
    {
      scale: 500,
      hex: "#a855f7",
      rgb: "rgb(168,85,247)",
      hsl: "hsl(270.7,91%,65.1%)",
    },
    {
      scale: 600,
      hex: "#9333ea",
      rgb: "rgb(147,51,234)",
      hsl: "hsl(271.5,81.3%,55.9%)",
    },
    {
      scale: 700,
      hex: "#7e22ce",
      rgb: "rgb(126,34,206)",
      hsl: "hsl(272.1,71.7%,47.1%)",
    },
    {
      scale: 800,
      hex: "#6b21a8",
      rgb: "rgb(107,33,168)",
      hsl: "hsl(272.9,67.2%,39.4%)",
    },
    {
      scale: 900,
      hex: "#581c87",
      rgb: "rgb(88,28,135)",
      hsl: "hsl(273.6,65.6%,32%)",
    },
    {
      scale: 950,
      hex: "#3b0764",
      rgb: "rgb(59,7,100)",
      hsl: "hsl(273.5,86.9%,21%)",
    },
  ],
  fuchsia: [
    {
      scale: 50,
      hex: "#fdf4ff",
      rgb: "rgb(253,244,255)",
      hsl: "hsl(289.1,100%,97.8%)",
    },
    {
      scale: 100,
      hex: "#fae8ff",
      rgb: "rgb(250,232,255)",
      hsl: "hsl(287,100%,95.5%)",
    },
    {
      scale: 200,
      hex: "#f5d0fe",
      rgb: "rgb(245,208,254)",
      hsl: "hsl(288.3,95.8%,90.6%)",
    },
    {
      scale: 300,
      hex: "#f0abfc",
      rgb: "rgb(240,171,252)",
      hsl: "hsl(291.1,93.1%,82.9%)",
    },
    {
      scale: 400,
      hex: "#e879f9",
      rgb: "rgb(232,121,249)",
      hsl: "hsl(292,91.4%,72.5%)",
    },
    {
      scale: 500,
      hex: "#d946ef",
      rgb: "rgb(217,70,239)",
      hsl: "hsl(292.2,84.1%,60.6%)",
    },
    {
      scale: 600,
      hex: "#c026d3",
      rgb: "rgb(192,38,211)",
      hsl: "hsl(293.4,69.5%,48.8%)",
    },
    {
      scale: 700,
      hex: "#a21caf",
      rgb: "rgb(162,28,175)",
      hsl: "hsl(294.7,72.4%,39.8%)",
    },
    {
      scale: 800,
      hex: "#86198f",
      rgb: "rgb(134,25,143)",
      hsl: "hsl(295.4,70.2%,32.9%)",
    },
    {
      scale: 900,
      hex: "#701a75",
      rgb: "rgb(112,26,117)",
      hsl: "hsl(296.7,63.6%,28%)",
    },
    {
      scale: 950,
      hex: "#4a044e",
      rgb: "rgb(74,4,78)",
      hsl: "hsl(296.8,90.2%,16.1%)",
    },
  ],
  pink: [
    {
      scale: 50,
      hex: "#fdf2f8",
      rgb: "rgb(253,242,248)",
      hsl: "hsl(327.3,73.3%,97.1%)",
    },
    {
      scale: 100,
      hex: "#fce7f3",
      rgb: "rgb(252,231,243)",
      hsl: "hsl(325.7,77.8%,94.7%)",
    },
    {
      scale: 200,
      hex: "#fbcfe8",
      rgb: "rgb(251,207,232)",
      hsl: "hsl(325.9,84.6%,89.8%)",
    },
    {
      scale: 300,
      hex: "#f9a8d4",
      rgb: "rgb(249,168,212)",
      hsl: "hsl(327.4,87.1%,81.8%)",
    },
    {
      scale: 400,
      hex: "#f472b6",
      rgb: "rgb(244,114,182)",
      hsl: "hsl(328.6,85.5%,70.2%)",
    },
    {
      scale: 500,
      hex: "#ec4899",
      rgb: "rgb(236,72,153)",
      hsl: "hsl(330.4,81.2%,60.4%)",
    },
    {
      scale: 600,
      hex: "#db2777",
      rgb: "rgb(219,39,119)",
      hsl: "hsl(333.3,71.4%,50.6%)",
    },
    {
      scale: 700,
      hex: "#be185d",
      rgb: "rgb(190,24,93)",
      hsl: "hsl(335.1,77.6%,42%)",
    },
    {
      scale: 800,
      hex: "#9d174d",
      rgb: "rgb(157,23,77)",
      hsl: "hsl(335.8,74.4%,35.3%)",
    },
    {
      scale: 900,
      hex: "#831843",
      rgb: "rgb(131,24,67)",
      hsl: "hsl(335.9,69%,30.4%)",
    },
    {
      scale: 950,
      hex: "#500724",
      rgb: "rgb(80,7,36)",
      hsl: "hsl(336.2,83.9%,17.1%)",
    },
  ],
  rose: [
    {
      scale: 50,
      hex: "#fff1f2",
      rgb: "rgb(255,241,242)",
      hsl: "hsl(355.7,100%,97.3%)",
    },
    {
      scale: 100,
      hex: "#ffe4e6",
      rgb: "rgb(255,228,230)",
      hsl: "hsl(355.6,100%,94.7%)",
    },
    {
      scale: 200,
      hex: "#fecdd3",
      rgb: "rgb(254,205,211)",
      hsl: "hsl(352.7,96.1%,90%)",
    },
    {
      scale: 300,
      hex: "#fda4af",
      rgb: "rgb(253,164,175)",
      hsl: "hsl(352.6,95.7%,81.8%)",
    },
    {
      scale: 400,
      hex: "#fb7185",
      rgb: "rgb(251,113,133)",
      hsl: "hsl(351.3,94.5%,71.4%)",
    },
    {
      scale: 500,
      hex: "#f43f5e",
      rgb: "rgb(244,63,94)",
      hsl: "hsl(349.7,89.2%,60.2%)",
    },
    {
      scale: 600,
      hex: "#e11d48",
      rgb: "rgb(225,29,72)",
      hsl: "hsl(346.8,77.2%,49.8%)",
    },
    {
      scale: 700,
      hex: "#be123c",
      rgb: "rgb(190,18,60)",
      hsl: "hsl(345.3,82.7%,40.8%)",
    },
    {
      scale: 800,
      hex: "#9f1239",
      rgb: "rgb(159,18,57)",
      hsl: "hsl(343.4,79.7%,34.7%)",
    },
    {
      scale: 900,
      hex: "#881337",
      rgb: "rgb(136,19,55)",
      hsl: "hsl(341.5,75.5%,30.4%)",
    },
    {
      scale: 950,
      hex: "#4c0519",
      rgb: "rgb(76,5,25)",
      hsl: "hsl(343.1,87.7%,15.9%)",
    },
  ],
};

export const colorMapping = {
  light: {
    background: "white",
    foreground: "{{base}}-950",
    card: "white",
    "card-foreground": "{{base}}-950",
    popover: "white",
    "popover-foreground": "{{base}}-950",
    primary: "{{base}}-900",
    "primary-foreground": "{{base}}-50",
    secondary: "{{base}}-100",
    "secondary-foreground": "{{base}}-900",
    muted: "{{base}}-100",
    "muted-foreground": "{{base}}-500",
    accent: "{{base}}-100",
    "accent-foreground": "{{base}}-900",
    destructive: "red-500",
    "destructive-foreground": "{{base}}-50",
    border: "{{base}}-200",
    input: "{{base}}-200",
    ring: "{{base}}-950",
  },
  dark: {
    background: "{{base}}-950",
    foreground: "{{base}}-50",
    card: "{{base}}-950",
    "card-foreground": "{{base}}-50",
    popover: "{{base}}-950",
    "popover-foreground": "{{base}}-50",
    primary: "{{base}}-50",
    "primary-foreground": "{{base}}-900",
    secondary: "{{base}}-800",
    "secondary-foreground": "{{base}}-50",
    muted: "{{base}}-800",
    "muted-foreground": "{{base}}-400",
    accent: "{{base}}-800",
    "accent-foreground": "{{base}}-50",
    destructive: "red-900",
    "destructive-foreground": "{{base}}-50",
    border: "{{base}}-800",
    input: "{{base}}-800",
    ring: "{{base}}-300",
  },
} as const;

export type Color =
  | "zinc"
  | "slate"
  | "stone"
  | "gray"
  | "neutral"
  | "red"
  | "rose"
  | "orange"
  | "green"
  | "blue"
  | "yellow"
  | "violet";

Composables

Display your composable logic:

ts

usePm Composable

/**
 * Package manager name type
 */
export type PackageManagerName = "npm" | "pnpm" | "bun" | "yarn";

/**
 * Package manager interface
 */
export interface PackageManager {
  name: PackageManagerName;
  command: string;
  install: string;
  installEmpty: string;
  run: string;
  x: string;
  saveDev: string;
  icon: string;
}

/**
 * List of supported package managers
 */
const PACKAGE_MANAGERS: readonly PackageManager[] = [
  {
    name: "npm",
    command: "npm ",
    install: "i ",
    installEmpty: "install",
    run: "run ",
    x: "npx ",
    saveDev: "-D ",
    icon: "material-icon-theme:npm",
  },
  {
    name: "pnpm",
    command: "pnpm ",
    install: "i ",
    installEmpty: "install",
    run: "run ",
    x: "pnpm dlx ",
    saveDev: "-D ",
    icon: "material-icon-theme:pnpm",
  },
  {
    name: "bun",
    command: "bun ",
    install: "add ",
    installEmpty: "install",
    run: "run ",
    x: "bun x ",
    saveDev: "-d ",
    icon: "material-icon-theme:bun",
  },
  {
    name: "yarn",
    command: "yarn ",
    install: "add ",
    installEmpty: "install",
    run: "run ",
    x: "yarn dlx ",
    saveDev: "-D ",
    icon: "material-icon-theme:yarn",
  },
] as const;

/**
 * Composable to access package manager data
 */
export function usePm() {
  return {
    packageManagers: PACKAGE_MANAGERS,
  };
}

Extract Specific Lines

Use start and offset to show only relevant portions of large files:

vue

Button Props

<script setup lang="ts">
  const props = withDefaults(defineProps<ButtonProps>(), {
    type: "button",
    loadingIcon: "line-md:loading-loop",
    iconPlacement: "left",
    loading: false,
  });

  const elementType = computed(() => {
    if (props.as) return props.as;
    if (props.href || props.to || props.target) return resolveComponent("NuxtLink");
    return "button";
  });

  const forwarded = useForwardProps(
    reactiveOmit(
      props,
      "class",
      "text",
      "icon",
      "iconPlacement",
      "size",
      "variant",
      "as",
      "loading",
      "disabled",
      "loadingIcon",
      "effect"
    )
  );
</script>

The example above starts at line 137 and shows the next 31 lines.

Highlight Lines

Combine with the highlights prop to emphasize important code:

vue

Button Props

<script setup lang="ts">
  const props = withDefaults(defineProps<ButtonProps>(), {
    type: "button",
    loadingIcon: "line-md:loading-loop",
    iconPlacement: "left",
    loading: false,
  });

  const elementType = computed(() => {
    if (props.as) return props.as;
    if (props.href || props.to || props.target) return resolveComponent("NuxtLink");
    return "button";
  });

  const forwarded = useForwardProps(
    reactiveOmit(
      props,
      "class",
      "text",
      "icon",
      "iconPlacement",
      "size",
      "variant",
      "as",
      "loading",
      "disabled",
      "loadingIcon",
      "effect"
    )
  );
</script>

External URLs

GitHub Raw Content

Load code directly from GitHub:

ts

Nuxt useState Source

import { isRef, toRef } from 'vue'
import type { Ref } from 'vue'
import { useNuxtApp } from '../nuxt'
import { toArray } from '../utils'

const useStateKeyPrefix = '$s'
/**
 * Create a global reactive ref that will be hydrated but not shared across ssr requests
 * @since 3.0.0
 * @param key a unique key ensuring that data fetching can be properly de-duplicated across requests
 * @param init a function that provides initial value for the state when it's not initiated
 */
export function useState<T> (key?: string, init?: (() => T | Ref<T>)): Ref<T>
export function useState<T> (init?: (() => T | Ref<T>)): Ref<T>
export function useState<T> (...args: any): Ref<T> {
  const autoKey = typeof args[args.length - 1] === 'string' ? args.pop() : undefined
  if (typeof args[0] !== 'string') { args.unshift(autoKey) }
  const [_key, init] = args as [string, (() => T | Ref<T>)]
  if (!_key || typeof _key !== 'string') {
    throw new TypeError('[nuxt] [useState] key must be a string: ' + _key)
  }
  if (init !== undefined && typeof init !== 'function') {
    throw new Error('[nuxt] [useState] init must be a function: ' + init)
  }
  const key = useStateKeyPrefix + _key

  const nuxtApp = useNuxtApp()
  const state = toRef(nuxtApp.payload.state, key)
  if (state.value === undefined && init) {
    const initialValue = init()
    if (isRef(initialValue)) {
      // vue will unwrap the ref for us
      nuxtApp.payload.state[key] = initialValue
      return initialValue as Ref<T>
    }
    state.value = initialValue
  }
  return state
}

/** @since 3.6.0 */
export function clearNuxtState (
  keys?: string | string[] | ((key: string) => boolean),
): void {
  const nuxtApp = useNuxtApp()
  const _allKeys = Object.keys(nuxtApp.payload.state)
    .map(key => key.substring(useStateKeyPrefix.length))

  const _keys: string[] = !keys
    ? _allKeys
    : typeof keys === 'function'
      ? _allKeys.filter(keys)
      : toArray(keys)

  for (const _key of _keys) {
    const key = useStateKeyPrefix + _key
    if (key in nuxtApp.payload.state) {
      nuxtApp.payload.state[key] = undefined
    }
  }
}

External Examples

Pull examples from documentation sites or CDNs.

This example fetches the Vue 3 ESM build from a CDN and displays lines 1-20:

js

Vue 3 ESM Build

/**
* vue v3.5.22
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/
// @__NO_SIDE_EFFECTS__
function makeMap(str) {
  const map = /* @__PURE__ */ Object.create(null);
  for (const key of str.split(",")) map[key] = 1;
  return (val) => val in map;
}

const EMPTY_OBJ = Object.freeze({}) ;
const EMPTY_ARR = Object.freeze([]) ;
const NOOP = () => {
};
const NO = () => false;
const isOn = (key) => key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && // uppercase letter
(key.charCodeAt(2) > 122 || key.charCodeAt(2) < 97);
const isModelListener = (key) => key.startsWith("onUpdate:");

Style Guide

Show your actual CSS/Tailwind configuration:

css

Tailwind Base Styles

@import "tailwindcss";
@import "tw-animate-css";

@source "../../../content/";

@config "../../../tailwind.config.js";

@plugin "@tailwindcss/typography";

@plugin "@tailwindcss/forms" {
  strategy: "class";
}

@custom-variant dark (&:is(.dark *));

@custom-variant hover (&:hover);

@utility container {
  margin-inline: auto;
  padding-inline: 2rem;
}

@theme inline {
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);

  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-accent: var(--accent);
  --color-accent-foreground: var(--accent-foreground);
  --color-destructive: var(--destructive);
  --color-destructive-foreground: var(--destructive-foreground);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);

  --color-sidebar-background: var(--sidebar-background);
  --color-sidebar-foreground: var(--sidebar-foreground);
  --color-sidebar-primary: var(--sidebar-primary);
  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
  --color-sidebar-accent: var(--sidebar-accent);
  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
  --color-sidebar-border: var(--sidebar-border);
  --color-sidebar-ring: var(--sidebar-ring);
  --color-sidebar-input: var(--sidebar-input);

  --color-gradient-lime: var(--gradient-lime);
  --color-gradient-ocean: var(--gradient-ocean);
  --color-gradient-wine: var(--gradient-wine);
  --color-gradient-rust: var(--gradient-rust);

  --color-surface: var(--surface);
  --color-surface-foreground: var(--surface-foreground);
  --color-code: var(--code);
  --color-code-foreground: var(--code-foreground);
  --color-code-highlight: var(--code-highlight);
  --color-code-number: var(--code-number);
  --color-selection: var(--selection);
  --color-selection-foreground: var(--selection-foreground);

  --font-sans:
    "Geist", "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
    "Segoe UI Symbol", "Noto Color Emoji";
  --font-mono:
    "Geist Mono", "Fira Code", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
    "Liberation Mono", "Courier New", monospace;
  --font-display--font-feature-settings: "cv02", "cv03", "cv04", "cv11";

  --animate-shine: shine 3s ease-out infinite;
  --animate-gradient-flow: gradientFlow 10s ease 0s infinite normal none running;
  --animate-meteor: meteor 5s linear infinite;
  --animate-background-position-spin: background-position-spin 3000ms infinite alternate;
  --animate-grid: grid 15s linear infinite;

  @keyframes grid {
    0% {
      transform: translateY(-50%);
    }
    100% {
      transform: translateY(0);
    }
  }

  @keyframes shine {
    0% {
      background-position: 200% 0;
    }
    25%,
    100% {
      background-position: -200% 0;
    }
  }

  @keyframes gradientFlow {
    50% {
      background-position: 100% 50%;
    }
    0%,
    100% {
      background-position: 0% 50%;
    }
  }

  @keyframes meteor {
    0% {
      transform: rotate(var(--angle)) translateX(0);
      opacity: 1;
    }
    70% {
      opacity: 1;
    }
    100% {
      transform: rotate(var(--angle)) translateX(-500px);
      opacity: 0;
    }
  }

  @keyframes background-position-spin {
    0% {
      background-position: top center;
    }
    100% {
      background-position: bottom center;
    }
  }
}

@layer base {
  :root {
    --radius: 0.625rem;
    --background: oklch(1 0 0);
    --foreground: oklch(0.141 0.005 285.823);
    --card: oklch(1 0 0);
    --card-foreground: oklch(0.141 0.005 285.823);
    --popover: oklch(1 0 0);
    --popover-foreground: oklch(0.141 0.005 285.823);
    --primary: oklch(0.21 0.006 285.885);
    --primary-foreground: oklch(0.985 0 0);
    --secondary: oklch(0.967 0.001 286.375);
    --secondary-foreground: oklch(0.21 0.006 285.885);
    --muted: oklch(0.967 0.001 286.375);
    --muted-foreground: oklch(0.552 0.016 285.938);
    --accent: oklch(0.967 0.001 286.375);
    --accent-foreground: oklch(0.21 0.006 285.885);
    --destructive: oklch(0.577 0.245 27.325);
    --border: oklch(0.92 0.004 286.32);
    --input: oklch(0.92 0.004 286.32);
    --ring: oklch(0.705 0.015 286.067);
    --chart-1: oklch(0.646 0.222 41.116);
    --chart-2: oklch(0.6 0.118 184.704);
    --chart-3: oklch(0.398 0.07 227.392);
    --chart-4: oklch(0.828 0.189 84.429);
    --chart-5: oklch(0.769 0.188 70.08);
    --sidebar: oklch(0.985 0 0);
    --sidebar-foreground: oklch(0.141 0.005 285.823);
    --sidebar-primary: oklch(0.21 0.006 285.885);
    --sidebar-primary-foreground: oklch(0.985 0 0);
    --sidebar-accent: oklch(0.967 0.001 286.375);
    --sidebar-accent-foreground: oklch(0.21 0.006 285.885);
    --sidebar-border: oklch(0.92 0.004 286.32);
    --sidebar-ring: oklch(0.705 0.015 286.067);

    /* Gradient slide show Colors */
    --gradient-lime: oklch(67.287% 0.1546 116.644);
    --gradient-ocean: oklch(44.56% 0.10114 242.813);
    --gradient-wine: oklch(32.332% 0.12034 5.266);
    --gradient-rust: oklch(55.695% 0.19944 34.155);

    --surface: oklch(100% 0.00011 271.152);
    --surface-foreground: var(--foreground);
    --code: var(--surface);
    --code-foreground: var(--surface-foreground);
    --code-highlight: oklch(0.96 0 0);
    --code-number: oklch(0.56 0 0);
    --selection: oklch(0.145 0 0);
    --selection-foreground: oklch(1 0 0);
  }

  .dark {
    --background: oklch(0.141 0.005 285.823);
    --foreground: oklch(0.985 0 0);
    --card: oklch(0.21 0.006 285.885);
    --card-foreground: oklch(0.985 0 0);
    --popover: oklch(0.21 0.006 285.885);
    --popover-foreground: oklch(0.985 0 0);
    --primary: oklch(0.92 0.004 286.32);
    --primary-foreground: oklch(0.21 0.006 285.885);
    --secondary: oklch(0.274 0.006 286.033);
    --secondary-foreground: oklch(0.985 0 0);
    --muted: oklch(0.274 0.006 286.033);
    --muted-foreground: oklch(0.705 0.015 286.067);
    --accent: oklch(0.274 0.006 286.033);
    --accent-foreground: oklch(0.985 0 0);
    --destructive: oklch(0.704 0.191 22.216);
    --border: oklch(1 0 0 / 10%);
    --input: oklch(1 0 0 / 15%);
    --ring: oklch(0.552 0.016 285.938);
    --chart-1: oklch(0.488 0.243 264.376);
    --chart-2: oklch(0.696 0.17 162.48);
    --chart-3: oklch(0.769 0.188 70.08);
    --chart-4: oklch(0.627 0.265 303.9);
    --chart-5: oklch(0.645 0.246 16.439);
    --sidebar: oklch(0.21 0.006 285.885);
    --sidebar-foreground: oklch(0.985 0 0);
    --sidebar-primary: oklch(0.488 0.243 264.376);
    --sidebar-primary-foreground: oklch(0.985 0 0);
    --sidebar-accent: oklch(0.274 0.006 286.033);
    --sidebar-accent-foreground: oklch(0.985 0 0);
    --sidebar-border: oklch(1 0 0 / 10%);
    --sidebar-ring: oklch(0.552 0.016 285.938);

    --surface: oklch(0.2 0 0);
    --surface-foreground: oklch(0.708 0 0);
    --code: var(--surface);
    --code-foreground: var(--surface-foreground);
    --code-highlight: oklch(0.27 0 0);
    --code-number: oklch(0.72 0 0);
    --selection: oklch(0.922 0 0);
    --selection-foreground: oklch(0.205 0 0);
  }
}

@layer base {
  *,
  ::after,
  ::before,
  ::backdrop,
  ::file-selector-button {
    border-color: var(--color-border, currentColor);
  }
  button:not(:disabled),
  [role="button"]:not(:disabled) {
    cursor: pointer;
  }
  * {
    @apply border-border outline-ring/50;
  }
  html {
    @apply antialiased;
  }
  body {
    @apply bg-background text-foreground;
  }
}

html {
  color-scheme: light dark;
}
html.dark {
  color-scheme: dark;
}
html.light {
  color-scheme: light;
}

h1 > a,
h2 > a,
h3 > a,
h4 > a,
h5 > a,
h6 > a {
  @apply font-bold! no-underline! hover:text-foreground! hover:decoration-wavy!;
}

code {
  @apply block rounded py-px font-mono;
  > span {
    @apply px-3;
  }
}

code:not(pre code):not(a > code) {
  @apply inline-block rounded-sm border bg-muted px-1 py-1 leading-none;
}

a > code {
  @apply inline-block border border-dashed border-primary/40 bg-primary/5 px-1 transition hover:border-primary;
}

pre::-webkit-scrollbar {
  @apply h-2.5 w-2.5;
}
pre::-webkit-scrollbar-track {
  @apply bg-transparent;
}
pre::-webkit-scrollbar-corner {
  @apply bg-transparent;
}
pre::-webkit-scrollbar-thumb {
  @apply rounded-full bg-muted-foreground/60;
}
pre {
  max-height: 400px;
  scrollbar-width: thin;
  scrollbar-color: --alpha(var(--muted) / 40%) transparent;
  @variant dark {
    scrollbar-color: var(--muted) transparent;
  }
}

.shiki .line {
  display: block;
  &.highlight {
    background-color: var(--muted);
  }
}

Migration Guides

Show before and after by referencing different file versions or branches:

## Migration from v1 to v2

### Old API (v1)

::prose-code-snippet{url="https://raw.githubusercontent.com/yourorg/yourrepo/v1/src/api.ts" language="typescript" title="Old API"}
::

### New API (v2)

::prose-code-snippet{file="/app/utils/api.ts" language="typescript" title="New API"}
::

### Changes

The new API uses fetch instead of axios and includes better error handling.

Tutorial Series

Create step-by-step tutorials showing progressive code changes:

## Step 1: Create Basic Component

::prose-code-snippet{file="/app/components/Tutorial/Step1.vue" language="vue" title="Step 1: Basic Setup"}
::

## Step 2: Add Props

::prose-code-snippet{file="/app/components/Tutorial/Step2.vue" language="vue" title="Step 2: With Props"}
::

## Step 3: Add State Management

::prose-code-snippet{file="/app/components/Tutorial/Step3.vue" language="vue" title="Step 3: Complete"}
::

Advanced Meta Options

Use the meta prop to pass additional options to the code block:

useDocPage Composable

import { kebabCase } from "lodash-es";

export const useDocPage = async () => {
  const route = useRoute();
  const { data } = await useAsyncData(kebabCase(route.path) + "-page", async () => {
    const content = await queryCollection("content").path(route.path).first();
    return { content };
  });
  return { contentPage: data.value?.content };
};

Available meta options:

  • icon=<name> - Custom file icon
  • noFormat - Disable code formatting
  • lines - Show line numbers
  • noHeader - Hide title header

Extract Function Definitions

Show just a specific function from a large file:

ts

Hex To Rgb Function

    },
    {
      scale: 500,
      hex: "#64748b",
      rgb: "rgb(100,116,139)",
      hsl: "hsl(215.4,16.3%,46.9%)",
    },
    {

Multiple File Comparison

Compare related files side by side using tabs:

vue

Button Component

<template>
  <component
    :is="elementType"
    :class="
      buttonStyles({
        hasIcon: !!icon,
        disabled: disabled || loading,
        variant: variant,
        size: size,
        class: props.class,
        effect: props.effect,
      })
    "
    :disabled="disabled || loading"
    v-bind="forwarded"
  >
    <slot name="iconLeft">
      <div
        v-if="icon && iconPlacement == 'left'"
        class="flex w-0 translate-x-[0%] pr-0 opacity-0 transition-all duration-200 group-hover:w-5 group-hover:translate-x-[0%] group-hover:pr-2 group-hover:opacity-100"
      >
        <Icon :name="icon" class="size-4" />
      </div>
    </slot>
    <slot name="loading">
      <Icon v-if="loading" class="size-4 shrink-0" :name="loadingIcon" />
    </slot>
    <slot>
      <span v-if="text">{{ text }}</span>
    </slot>
    <slot name="iconRight">
      <div
        v-if="icon && iconPlacement == 'right'"
        class="flex w-0 translate-x-[100%] pl-0 opacity-0 transition-all duration-200 group-hover:w-5 group-hover:translate-x-0 group-hover:pl-2 group-hover:opacity-100"
      >
        <Icon :name="icon" class="size-4" />
      </div>
    </slot>
  </component>
</template>

<script lang="ts">
  import { reactiveOmit } from "@vueuse/core";
  import { useForwardProps } from "reka-ui";
  import type { NuxtLinkProps } from "#app/components";
  import type { HtmlHTMLAttributes } from "vue";

  /**
   * Exported button styles that can be used by other components
   */
  export const buttonStyles = tv({
    base: "group inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
        destructive:
          "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
        outline:
          "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
        secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
        ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
        link: "text-primary underline-offset-4 hover:underline",
      },
      effect: {
        expandIcon: "group relative gap-0",
        ringHover: "transition-all duration-300 hover:ring-3 hover:ring-ring/50",
        shine:
          "relative overflow-hidden [background-position:0s_ease] before:absolute before:inset-0 before:animate-shine before:rounded-[inherit] before:bg-[linear-gradient(45deg,transparent_25%,rgba(255,255,255,0.5)_50%,transparent_75%,transparent_100%)] before:bg-[length:250%_250%,100%_100%] before:bg-no-repeat",
        shineHover:
          "relative overflow-hidden before:absolute before:inset-0 before:rounded-[inherit] before:bg-[linear-gradient(45deg,transparent_25%,rgba(255,255,255,0.5)_50%,transparent_75%,transparent_100%)] before:bg-[length:250%_250%,100%_100%] before:bg-[position:200%_0,0_0] before:bg-no-repeat before:transition-[background-position_0s_ease] before:duration-1000 hover:before:bg-[position:-100%_0,0_0]",
        gooeyRight:
          "relative z-0 overflow-hidden duration-500 before:absolute before:inset-0 before:-z-10 before:translate-x-[150%] before:translate-y-[150%] before:scale-[2.5] before:rounded-[100%] before:bg-gradient-to-r before:from-white/40 before:transition-transform before:duration-1000 hover:before:translate-x-[0%] hover:before:translate-y-[0%]",
        gooeyLeft:
          "relative z-0 overflow-hidden duration-500 after:absolute after:inset-0 after:-z-10 after:translate-x-[-150%] after:translate-y-[150%] after:scale-[2.5] after:rounded-[100%] after:bg-gradient-to-l after:from-white/40 after:transition-transform after:duration-1000 hover:after:translate-x-[0%] hover:after:translate-y-[0%]",
        underline:
          "relative !no-underline after:absolute after:bottom-2 after:h-[1px] after:w-2/3 after:origin-bottom-left after:scale-x-100 after:bg-primary after:transition-transform after:duration-300 after:ease-in-out hover:after:origin-bottom-right hover:after:scale-x-0",
        hoverUnderline:
          "relative !no-underline after:absolute after:bottom-2 after:h-[1px] after:w-2/3 after:origin-bottom-right after:scale-x-0 after:bg-primary after:transition-transform after:duration-300 after:ease-in-out hover:after:origin-bottom-left hover:after:scale-x-100",
        gradientSlideShow:
          "animate-gradient-flow bg-[linear-gradient(-45deg,var(--gradient-lime),var(--gradient-ocean),var(--gradient-wine),var(--gradient-rust))] bg-[size:400%] text-white",
      },
      size: {
        xs: "h-7 gap-1 px-2.5 text-xs has-[>svg]:px-2",
        sm: "h-8 gap-1.5 px-3 has-[>svg]:px-2.5",
        default: "h-9 px-4 py-2 has-[>svg]:px-3",
        lg: "h-10 px-6 has-[>svg]:px-4",
        "icon-xs": "size-7",
        "icon-sm": "size-8",
        icon: "size-9",
        "icon-lg": "size-10",
      },
      disabled: {
        true: "pointer-events-none opacity-50",
      },
      hasIcon: {
        false: "gap-2",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  });
  export type ButtonVariants = VariantProps<typeof buttonStyles>;
  export type ButtonProps = NuxtLinkProps & {
    /** The type for the button */
    type?: "button" | "submit" | "reset";
    /** Whether the button is disabled */
    disabled?: boolean;
    /** Whether the button is loading */
    loading?: boolean;
    /** The action to perform when the button is clicked */
    onClick?: any;
    /** The element to render the button as */
    as?: string;
    /** Custom class(es) to add to parent element */
    class?: HtmlHTMLAttributes["class"];
    /** The variant of the button */
    variant?: ButtonVariants["variant"];
    /** The size of the button */
    size?: ButtonVariants["size"];
    /**
     * The effect to apply to the button.
     */
    effect?: ButtonVariants["effect"];
    /** The text to display in the button */
    text?: string;
    /** Should the icon be displayed on the `left` or the `right`? */
    iconPlacement?: "left" | "right";
    /** The icon to display in the button */
    icon?: string;
    /** The icon to display when the button is loading */
    loadingIcon?: string;
  };
</script>

<script setup lang="ts">
  const props = withDefaults(defineProps<ButtonProps>(), {
    type: "button",
    loadingIcon: "line-md:loading-loop",
    iconPlacement: "left",
    loading: false,
  });

  const elementType = computed(() => {
    if (props.as) return props.as;
    if (props.href || props.to || props.target) return resolveComponent("NuxtLink");
    return "button";
  });

  const forwarded = useForwardProps(
    reactiveOmit(
      props,
      "class",
      "text",
      "icon",
      "iconPlacement",
      "size",
      "variant",
      "as",
      "loading",
      "disabled",
      "loadingIcon",
      "effect"
    )
  );
</script>

Props

PropTypeDefaultDescription
filestring-Relative path to a file in your project (must match glob patterns)
urlstring-External URL to fetch code from
languagestringrequiredProgramming language for syntax highlighting
titlestring-Optional title displayed above the code block
highlightsstring-Line numbers or ranges to highlight (e.g., "1,3-5,10")
metastring-Additional metadata passed to ProsePre (e.g., "icon=vue noFormat")
startnumber-Starting line number to extract (1-indexed)
offsetnumber-Number of lines to extract from the starting line

Syntax

Basic Import

::prose-code-snippet{file="/app/components/Button.vue" language="vue"}
::

With Title

::prose-code-snippet{file="/app/utils/helpers.ts" language="typescript" title="Helper Functions"}
::

With Line Extraction

::prose-code-snippet{file="/app/app.vue" language="vue" start="10" offset="5"}
::

From URL

::prose-code-snippet{url="https://example.com/code.js" language="javascript" title="External Example"}
::
Extending Patterns
To include more directories, edit the import.meta.glob array in ProseCodeSnippet.global.vue.

Performance Considerations

Bundle Size Impact

The import.meta.glob pattern includes files in your build. Be strategic:

✅ Good Practices:

  • Use specific file extensions: *.{vue,ts} instead of *
  • Exclude test files: !**/*.test.ts
  • Only include directories you'll reference in docs
  • Use eager: false for lazy loading (already configured)

❌ Avoid:

  • Overly broad patterns like /app/**/* (includes everything)
  • Including asset files (images, videos)
  • Globbing node_modules or build outputs

Current Configuration Impact

With the default patterns (/app/**/*.{vue,ts,css,json}), expect:

  • Small projects (<100 files): ~100-200KB added to bundle
  • Medium projects (100-500 files): ~200KB-1MB added to bundle
  • Large projects (500+ files): 1MB+ added to bundle

Files are lazy-loaded, so only referenced snippets are downloaded to the client.

URL Fetching for Large Files

For very large files or files outside your project:

::prose-code-snippet{url="/api/files/large-schema.json" language="json"}
::

This avoids bundling and fetches on-demand.

Error Handling

The component handles errors gracefully:

File Not Found

::prose-code-snippet{file="/app/nonexistent.ts" language="typescript"}
::

Shows error callout: "Cannot load code: /app/nonexistent.ts"

Code Snippet Error
Cannot load code: /app/nonexistent.ts

Invalid URL

::prose-code-snippet{url="https://invalid-url-404.com/code.js" language="javascript"}
::

Shows error callout with the URL.

Code Snippet Error
Cannot load code: https://invalid-url-404.com/code.js

Best Practices

Documentation Tips
  1. Keep Docs in Sync - Reference actual source files instead of copying code
  2. Show Relevant Code - Use start and offset to show only what matters
  3. Add Context - Always use title to explain what the code does
  4. Highlight Key Lines - Use highlights to draw attention to important parts
  5. Version Control - Reference specific branches/tags in URLs for stable examples
  6. Test Paths - Ensure file paths match your glob patterns
  7. Performance - For large apps, consider creating a /docs-examples/ directory with curated files

Common Patterns

Tutorial with Progressive Examples

## Build a User Card

### 1. Basic Structure

::prose-code-snippet{file="/app/examples/tutorial/UserCard-1.vue" language="vue" title="Step 1: Basic HTML"}
::

### 2. Add Styling

::prose-code-snippet{file="/app/examples/tutorial/UserCard-2.vue" language="vue" title="Step 2: With Tailwind"}
::

### 3. Make Interactive

::prose-code-snippet{file="/app/examples/tutorial/UserCard-3.vue" language="vue" title="Step 3: Complete Component"}
::

API Endpoint Documentation

## Users API

### List Users

::prose-code-snippet{file="/server/api/users/index.get.ts" language="typescript" title="GET /api/users"}
::

**Response:**

```json
{
"data": [...],
"total": 100,
"page": 1,
"limit": 10
}
```

### Get Single User

::prose-code-snippet{file="/server/api/users/[id].get.ts" language="typescript" title="GET /api/users/:id"}
::

Component Anatomy

## Understanding the Button Component

The button component consists of three main files:

::prose-code-snippet{file="/app/components/Ui/Button/Button.vue" language="vue" title="Component Implementation"}
::

::prose-code-snippet{file="/app/components/Ui/Button/types.ts" language="typescript" title="TypeScript Types"}
::

::prose-code-snippet{file="/app/components/Ui/Button/index.ts" language="typescript" title="Public API"}
::