# Glass

A translucent variant of Button, Tooltip, Popover, Menu, Context Menu and Card for surfaces over a picture.

Glass is a variant of the components on this page, not a component of its own. Set `variant="glass"` and the surface shows a darkened, blurred view of what lies behind it, with light text. It looks the same in Light and Dark. Shape, spacing, states and motion stay those of the component.

Glass needs something behind it. Use it over a photo, a video, a map or a color surface; on a plain page it shows almost nothing, so keep the default surface there. The gradient in these examples only makes the glass visible. It is not part of any component.

## Installation

Glass comes with each component. To install every component on this page together with what its example uses:

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/button @siteplane/tooltip @siteplane/popover @siteplane/menu @siteplane/context-menu @siteplane/card @siteplane/label @siteplane/switch
```

## Button

Install and API: [Button](/docs/components/button/#glass).

Glass buttons

[Complete TSX file](/examples/button/glass.tsx)

```tsx
"use client";

import { PlayIcon, ShareIcon } from "lucide-react";
import { Button, IconButton } from "@/siteplane/components/button";

export default function Example() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-3">
      <Button variant="glass">
        <PlayIcon />
        Watch trailer
      </Button>
      <Button variant="glass">Add to list</Button>
      <IconButton icon={<ShareIcon />} label="Share" variant="glass" />
    </div>
  );
}
```

## Tooltip

Install and API: [Tooltip](/docs/components/tooltip/#glass).

Glass tooltip

[Complete TSX file](/examples/tooltip/glass.tsx)

```tsx
"use client";

import { CopyIcon } from "lucide-react";
import { Button } from "@/siteplane/components/button";
import {
  Tooltip,
  TooltipPopup,
  TooltipProvider,
  TooltipTrigger,
} from "@/siteplane/components/tooltip";

export default function Example() {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger
          render={
            <Button aria-label="Copy link" shape="square" variant="glass" />
          }
        >
          <CopyIcon />
        </TooltipTrigger>
        <TooltipPopup variant="glass">Copy link</TooltipPopup>
      </Tooltip>
    </TooltipProvider>
  );
}
```

## Popover

Install and API: [Popover](/docs/components/popover/#glass).

Glass popover

[Complete TSX file](/examples/popover/glass.tsx)

```tsx
"use client";

import { Button } from "@/siteplane/components/button";
import {
  Popover,
  PopoverDescription,
  PopoverPopup,
  PopoverTitle,
  PopoverTrigger,
} from "@/siteplane/components/popover";

export default function Example() {
  return (
    <Popover>
      <PopoverTrigger render={<Button variant="glass" />}>Share</PopoverTrigger>
      <PopoverPopup className="w-72" variant="glass">
        <PopoverTitle>Share link</PopoverTitle>
        <PopoverDescription>
          Anyone with the link can view this page.
        </PopoverDescription>
      </PopoverPopup>
    </Popover>
  );
}
```

## Menu

Install and API: [Menu](/docs/components/menu/#glass). [Dropdown Menu](/docs/components/dropdown-menu/#glass) takes the same variant on `DropdownMenuContent`.

Glass menu

[Complete TSX file](/examples/menu/glass.tsx)

```tsx
"use client";

import { CopyIcon, PencilIcon, ShareIcon, Trash2Icon } from "lucide-react";
import { Button } from "@/siteplane/components/button";
import {
  Menu,
  MenuItem,
  MenuPopup,
  MenuSeparator,
  MenuTrigger,
} from "@/siteplane/components/menu";

export default function Example() {
  return (
    <Menu>
      <MenuTrigger render={<Button variant="glass" />}>Options</MenuTrigger>
      <MenuPopup variant="glass">
        <MenuItem>
          <PencilIcon aria-hidden="true" />
          Edit
        </MenuItem>
        <MenuItem>
          <CopyIcon aria-hidden="true" />
          Duplicate
        </MenuItem>
        <MenuItem>
          <ShareIcon aria-hidden="true" />
          Share
        </MenuItem>
        <MenuSeparator />
        <MenuItem variant="destructive">
          <Trash2Icon aria-hidden="true" />
          Delete
        </MenuItem>
      </MenuPopup>
    </Menu>
  );
}
```

## Context Menu

Install and API: [Context Menu](/docs/components/context-menu/#glass).

Glass context menu

[Complete TSX file](/examples/context-menu/glass.tsx)

```tsx
"use client";

import { CopyIcon, PencilIcon, ShareIcon, Trash2Icon } from "lucide-react";
import { Card } from "@/siteplane/components/card";
import {
  ContextMenu,
  ContextMenuItem,
  ContextMenuPopup,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from "@/siteplane/components/context-menu";

export default function Example() {
  return (
    <ContextMenu>
      <ContextMenuTrigger
        className="h-28 w-full max-w-sm items-center justify-center text-sm"
        render={<Card variant="glass" />}
        tabIndex={0}
      >
        Right-click or long-press here
      </ContextMenuTrigger>
      <ContextMenuPopup variant="glass">
        <ContextMenuItem>
          <PencilIcon aria-hidden="true" />
          Edit
        </ContextMenuItem>
        <ContextMenuItem>
          <CopyIcon aria-hidden="true" />
          Copy
        </ContextMenuItem>
        <ContextMenuItem>
          <ShareIcon aria-hidden="true" />
          Share
        </ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenuItem variant="destructive">
          <Trash2Icon aria-hidden="true" />
          Delete
        </ContextMenuItem>
      </ContextMenuPopup>
    </ContextMenu>
  );
}
```

## Card

Install and API: [Card](/docs/components/card/#glass).

Glass card

[Complete TSX file](/examples/card/glass.tsx)

```tsx
"use client";

import {
  Card,
  CardDescription,
  CardHeader,
  CardPanel,
  CardTitle,
} from "@/siteplane/components/card";
import { Label } from "@/siteplane/components/label";
import { Switch } from "@/siteplane/components/switch";

export default function Example() {
  return (
    <Card className="w-full max-w-md" variant="glass">
      <CardHeader>
        <CardTitle>Notifications</CardTitle>
        <CardDescription>Choose what reaches you.</CardDescription>
      </CardHeader>
      <CardPanel className="grid gap-3">
        <Label className="w-full cursor-pointer justify-between">
          Live presence
          <Switch defaultChecked />
        </Label>
        <Label className="w-full cursor-pointer justify-between">
          Weekly digest
          <Switch />
        </Label>
      </CardPanel>
    </Card>
  );
}
```

## Card and text

Glass is a dark card with light text by default. It reads on dark and colorful backgrounds and on most light ones. Secondary text and icons take shares of the text color, and destructive items use the lighter red of Dark.

For a lighter card, set `data-glass-tone="light"`. For dark text, set `data-glass-ink="dark"`. Set them on a glass component, or on any element to change every glass component inside it. A popup renders outside its trigger, so set them on the popup itself.

```tsx
<section data-glass-tone="light" data-glass-ink="dark">
  <Card variant="glass">…</Card>
</section>

<MenuPopup data-glass-tone="light" data-glass-ink="dark" variant="glass">
  …
</MenuPopup>
```

How well text reads still depends on what lies behind the glass. Check the contrast on your own content, especially on very light pictures, and keep longer text on the default surface.
