@hoag/ui — UI components built with shadcn, Radix UI & Tailwind CSS
Components
Sheet Wrapper

Sheet Wrapper

SheetWrapper is a convenience component built on top of Radix UI's Sheet. It provides structured header, scrollable content, and optional footer slots so you don't have to wire them manually.

Installation

pnpm --filter @hoag/ui build

Usage

import { SheetWrapper } from "@hoag/ui/sheet-wrapper";
import { Button } from "@hoag/ui/components/button";
 
export default function Demo() {
  return (
    <SheetWrapper
      trigger={<Button>Open Sheet</Button>}
      title="Settings"
      description="Manage your preferences"
    >
      <div>Sheet content goes here.</div>
    </SheetWrapper>
  );
}

Default

<SheetWrapper
  trigger={<Button variant="outline">Open Sheet</Button>}
  title="Sheet Title"
  description="This is the sheet description."
>
  <div>Sheet content goes here.</div>
</SheetWrapper>

Sides

<SheetWrapper trigger={<Button>Top</Button>} title="Top Sheet" side="top">
  <p>Sheet slides from the top.</p>
</SheetWrapper>
<SheetWrapper trigger={<Button>Right</Button>} title="Right Sheet" side="right">
  <p>Sheet slides from the right.</p>
</SheetWrapper>
<SheetWrapper trigger={<Button>Bottom</Button>} title="Bottom Sheet" side="bottom">
  <p>Sheet slides from the bottom.</p>
</SheetWrapper>
<SheetWrapper trigger={<Button>Left</Button>} title="Left Sheet" side="left">
  <p>Sheet slides from the left.</p>
</SheetWrapper>

With Footer

<SheetWrapper
  trigger={<Button>Open with Footer</Button>}
  title="Edit Profile"
  description="Update your profile details below."
  showFooter
  footerContent={
    <div className="flex gap-2">
      <Button size="sm">Save changes</Button>
      <Button variant="outline" size="sm">
        Cancel
      </Button>
    </div>
  }
>
  <div>Edit form fields go here.</div>
</SheetWrapper>

API Reference

Props

PropTypeDefaultDescription
triggerReactNodeElement that opens the sheet when clicked
titlestringSheet header title
descriptionstringSheet header description
side"top" | "bottom" | "left" | "right""right"Which side the sheet slides from
showFooterbooleanfalseWhether to render the footer section
footerContentReactNodeContent placed in the footer
openbooleanControlled open state
onOpenChange(open: boolean) => voidCallback when open state changes
childrenReactNodeScrollable main content area