primitives
Icon Expand Button
A compact gradient button that expands on hover: resting at scale 0.89 it scales to full size on hover while hidden CSS-anatomy annotation elements — padding indicators, background and border-radius callouts, and decorative dots and curves around the icon — fade and pop in. All annotations are aria-hidden; the always-visible label provides the accessible name. Keyboardable, focus-visible ring, reduced-motion degrades to opacity-only reveal with no scale.
Ported from barisdogansutcu (MIT)
Install
1. Register the namespace (once per project):
json
// components.json — register the @bottega namespace once
{
"registries": {
"@bottega": { "url": "https://bottega.ariacode.ca/r/{name}.json" }
}
}2. Add the component:
bash
npx shadcn add @bottega/icon-expand-buttonUsage
Usagetsx
<IconExpandButton />Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | Anatomy | The visible button label that always provides the accessible name. Default "Anatomy". |
Source
icon-expand-button.tsxtsx
"use client";
import type React from "react";
import styles from "./icon-expand-button.module.css";
export interface IconExpandButtonProps extends React.ComponentProps<"button"> {
/** The visible button label that always provides the accessible name. Default "Anatomy". */
label?: string;
}
export function IconExpandButton({
label = "Anatomy",
className,
...props
}: IconExpandButtonProps) {
return (
<button
type="button"
className={[styles.button, className].filter(Boolean).join(" ")}
{...props}
>
{/* Icon wrapper with decorative ::before dot + ::after curved-line annotation.
The whole group is aria-hidden because it's decorative anatomy markup. */}
<div className={styles.icon} aria-hidden="true">
{/* "Icon" annotation label — in DOM for AT consistency, visually hidden at rest. */}
<span className={`${styles.textIcon} ${styles.hide}`}>Icon</span>
{/* Pencil/edit SVG icon — decorative, aria-hidden */}
<svg
aria-hidden="true"
strokeLinejoin="round"
strokeLinecap="round"
fill="none"
strokeWidth="2"
stroke="currentColor"
height="20"
width="20"
viewBox="0 0 24 24"
>
<path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z" />
</svg>
</div>
{/* Always-visible label — provides the accessible name for the button */}
<span className={styles.title}>{label}</span>
{/* Decorative anatomy annotations — all aria-hidden, reveal on hover */}
<div className={`${styles.paddingLeft} ${styles.hide}`} aria-hidden="true">
<div className={styles.paddingLeftLine}>
<span className={styles.paddingLeftText}>Left Padding</span>
</div>
</div>
<div className={`${styles.paddingRight} ${styles.hide}`} aria-hidden="true">
<div className={styles.paddingRightLine}>
<span className={styles.paddingRightText}>Right Padding</span>
</div>
</div>
<div className={`${styles.background} ${styles.hide}`} aria-hidden="true">
<span className={styles.backgroundText}>Background</span>
</div>
<div className={`${styles.border} ${styles.hide}`} aria-hidden="true">
<span className={styles.borderText}>Border Radius</span>
</div>
</button>
);
}
Dependencies
- @bottega/tokens