V-/Srcv0.1.0beta

// dock

Dock

The signature piece — the brand board's docked nav, in glass.

// install
npx shadcn add @vsrc/dock

Props

Only the vsrc surface is documented here. Everything else passes through to the underlying element.

// Dock

proptypedefaultnotes
glass"subtle" | "regular" | "heavy" | LiquidGlassOptions | falseOptics override for the floating bar. A preset name replaces the tuned values, an object merges over them, `false` disables refraction entirely.

Optics

DOCK_OPTICS: scale −64, chroma 5, border 0.14, mapBlur 10, blur 3 — mid-strength; the bar floats over arbitrary page content, so it needs presence without smearing what scrolls beneath.

Accessibility

  • A nav landmark — give each DockItem link an aria-label; icons alone don't name a destination.
  • Fixed positioning keeps it reachable; it never overlaps focus order.

Source

The exact file the CLI copies into your project — you own it after install.

// registry/vsrc/ui/dock.tsx
"use client";

import * as React from "react";
import { mergeGlass, type GlassPreset, type LiquidGlassOptions } from "vsrc/react";

import { GlassSurface } from "@/registry/vsrc/ui/glass-surface";
import { cn } from "@/lib/utils";

const DOCK_OPTICS: LiquidGlassOptions = {
  scale: -64,
  chroma: 5,
  border: 0.14,
  mapBlur: 10,
  blur: 3,
  saturate: 1.5,
  fallbackBlur: 3,
};

/**
 * The signature piece: a floating glass bar mirroring the brand board's
 * docked nav. Fixed bottom-center by default; unset `position` via className
 * to inline it. Children are DockItems (and anything else glass-free).
 */
function Dock({
  className,
  glass,
  ...props
}: React.ComponentProps<"nav"> & { glass?: LiquidGlassOptions | GlassPreset | false }) {
  return (
    <GlassSurface asChild glass={mergeGlass(DOCK_OPTICS, glass)}>
      <nav
        data-slot="dock"
        className={cn(
          "fixed bottom-6 left-1/2 z-40 -translate-x-1/2",
          "flex items-center gap-1 rounded-full p-2",
          className,
        )}
        {...props}
      />
    </GlassSurface>
  );
}

function DockItem({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="dock-item"
      className={cn(
        "flex items-center [&>a]:flex [&>a]:size-10 [&>a]:items-center [&>a]:justify-center [&>a]:rounded-full",
        "[&>a]:text-foreground [&>a]:transition-[background-color,transform] [&>a]:outline-none",
        "[&>a:hover]:bg-foreground/10 [&>a:hover]:scale-110 [&>a:focus-visible]:ring-2 [&>a:focus-visible]:ring-ring",
        "[&_svg]:size-5 [&_svg]:shrink-0",
        className,
      )}
      {...props}
    />
  );
}

function DockSeparator({ className, ...props }: React.ComponentProps<"div">) {
  return <div data-slot="dock-separator" className={cn("mx-1 h-6 w-px bg-foreground/15", className)} {...props} />;
}

export { Dock, DockItem, DockSeparator };