IconButton
ui actionicon
Quadratischer Icon-Button für Zeilen-Aktionen. Trägt IMMER ein Label — es wird zu aria-label und title, weil nur ein Glyph sichtbar ist. Tonlagen: neutral · accent (primäre Aktion) · danger (destruktiv); `pressed` macht daraus einen Toggle.
Keine interaktive Live-Demo — siehe Code & Beispiele unten.
Abhängigkeiten
Barrierefreiheit
- Pflicht-`label` wird als aria-label UND title gesetzt — ein Icon allein ist kein Name.
- `pressed` schaltet aria-pressed für Toggle-Aktionen (z. B. „Favorit").
Beispiele
Zeilen-Aktionen
<IconButton label="Umbenennen" onClick={rename}><RenameIcon /></IconButton>
<IconButton label="Löschen" tone="danger" onClick={remove}><TrashIcon /></IconButton> Toggle
<IconButton label="Favorit" pressed={fav} onClick={toggle}>
{fav ? <StarFilledIcon /> : <StarIcon />}
</IconButton> Genutzte Tokens · 10
--accent-fg--accent-soft--ease-standard--fg--focus-ring--motion-fast--muted--radius-sm--tag-danger-fg--tag-warn-fg
Quelldateien
components/ui/IconButton.tsx tsx
import type { ReactNode } from 'react';
import styles from './IconButton.module.css';
/**
* Quadratischer Icon-Button (aus dem mga-scores `icon-btn`-Muster, auf die
* Familien-Tokens gehoben). Trägt IMMER ein Label — es wird als `aria-label`
* und `title` gesetzt, weil der Button nur ein Glyph zeigt.
*
* `tone`: neutral (Default) · accent (primäre Aktion einer Zeile) · danger
* (destruktiv). `pressed` schaltet `aria-pressed` (Toggle wie „Favorit").
*/
export interface IconButtonProps {
label: string;
children: ReactNode;
onClick?: () => void;
tone?: 'neutral' | 'accent' | 'danger';
size?: 'sm' | 'md';
pressed?: boolean;
disabled?: boolean;
className?: string;
}
export function IconButton({
label,
children,
onClick,
tone = 'neutral',
size = 'md',
pressed,
disabled,
className,
}: IconButtonProps) {
const cls = [styles.btn, styles[tone], styles[size], className].filter(Boolean).join(' ');
return (
<button
type="button"
className={cls}
aria-label={label}
title={label}
onClick={onClick}
disabled={disabled}
{...(pressed === undefined ? {} : { 'aria-pressed': pressed })}
>
{children}
</button>
);
}
components/ui/IconButton.module.css css
.btn {
display: inline-grid;
place-items: center;
flex: 0 0 auto;
border: 1px solid transparent;
border-radius: var(--radius-sm);
background: transparent;
color: var(--muted);
cursor: pointer;
font: inherit;
transition:
color var(--motion-fast) var(--ease-standard),
background var(--motion-fast) var(--ease-standard),
border-color var(--motion-fast) var(--ease-standard);
}
.btn:hover:not(:disabled) {
color: var(--fg);
background: color-mix(in oklab, var(--fg), transparent 92%);
}
.btn:focus-visible {
outline: none;
box-shadow: var(--focus-ring);
}
.btn:disabled {
opacity: 0.45;
cursor: default;
}
.sm {
width: 26px;
height: 26px;
}
.md {
width: 32px;
height: 32px;
}
.accent {
color: var(--accent-fg);
}
.accent:hover:not(:disabled) {
color: var(--accent-fg);
background: var(--accent-soft);
}
.danger:hover:not(:disabled) {
color: var(--tag-danger-fg);
background: color-mix(in oklab, var(--tag-danger-fg), transparent 90%);
}
/* Aktiver Toggle (z. B. gesetzter Favorit). */
.btn[aria-pressed='true'] {
color: var(--tag-warn-fg);
}
Holen
# MCP (Claude Code / Cursor)
get_component({ name: "icon-button" })
# Registry direkt
https://www.ekklesi.tools/design/registry/components/icon-button.json