MultiSelectDropdown

ui filteroverlayform

Mehrfach-Checkbox-Filter mit Einschluss-Logik: leere Auswahl = „alles sichtbar", sonst nur die gewählten Keys. „Alle anzeigen" oben setzt zurück. MultiSelectList ist die wiederverwendbare Checkbox-Liste ohne Trigger.

alle sichtbar

Barrierefreiheit

  • Native Checkboxen in <label> — Tastatur/Screenreader nativ; accent-color = --accent.

Beispiele

Buch-Filter
const [sel, setSel] = useState<Set<string>>(new Set());
<MultiSelectDropdown
  ariaLabel="Buch" placeholder="Buch"
  options={[{ key: 'gen', label: 'Genesis' }, { key: 'ex', label: 'Exodus' }]}
  selected={sel} onChange={setSel}
/>

Genutzte Tokens · 6

--accent--bg--border--muted--radius-sm--space-2

Quelldateien

components/ui/MultiSelectDropdown.tsx tsx
import { type ReactNode } from 'react';
import { FilterDropdown } from './FilterDropdown';
import styles from './MultiSelectDropdown.module.css';

export interface MultiSelectOption {
  key: string;
  label: ReactNode;
}

interface Props {
  ariaLabel: string;
  /** Triggertext ohne Auswahl, z. B. „Buch". Bei Auswahl wird „ · N" angehängt. */
  placeholder: string;
  options: MultiSelectOption[];
  /** Einschluss-Logik: leeres Set = alles sichtbar, sonst nur die gewählten Keys. */
  selected: Set<string>;
  onChange: (next: Set<string>) => void;
  align?: 'left' | 'right';
  /** Text der „Alle anzeigen"-Reset-Zeile (i18n). */
  showAllLabel?: string | undefined;
}

/** Dropdown mit Mehrfach-Checkbox-Auswahl. „Alle anzeigen" oben setzt die
 *  Auswahl zurück (leer = alles sichtbar). */
export function MultiSelectDropdown({
  ariaLabel,
  placeholder,
  options,
  selected,
  onChange,
  align = 'left',
  showAllLabel,
}: Props) {
  return (
    <FilterDropdown ariaLabel={ariaLabel} label={placeholder} count={selected.size} align={align}>
      <MultiSelectList
        options={options}
        selected={selected}
        onChange={onChange}
        showAllLabel={showAllLabel}
      />
    </FilterDropdown>
  );
}

interface MultiSelectListProps {
  options: MultiSelectOption[];
  /** Einschluss-Logik: leeres Set = alles sichtbar, sonst nur die gewählten Keys. */
  selected: Set<string>;
  onChange: (next: Set<string>) => void;
  showAllLabel?: string | undefined;
}

/** Reine Checkbox-Liste (ohne Trigger/Popover) für Mehrfachauswahl mit
 *  „Alle anzeigen"-Reset. Geteilt vom `MultiSelectDropdown` und von
 *  kombinierten Filter-Popovern. */
export function MultiSelectList({
  options,
  selected,
  onChange,
  showAllLabel = 'Alle anzeigen',
}: MultiSelectListProps) {
  const toggle = (key: string) => {
    const next = new Set(selected);
    if (next.has(key)) next.delete(key);
    else next.add(key);
    onChange(next);
  };

  return (
    <div className={styles.list}>
      <label className={styles.option}>
        <input
          type="checkbox"
          checked={selected.size === 0}
          onChange={() => onChange(new Set())}
        />
        <span className={styles.muted}>{showAllLabel}</span>
      </label>
      <div className={styles.separator} role="separator" />
      {options.map((opt) => (
        <label key={opt.key} className={styles.option}>
          <input
            type="checkbox"
            checked={selected.has(opt.key)}
            onChange={() => toggle(opt.key)}
          />
          {opt.label}
        </label>
      ))}
    </div>
  );
}
components/ui/MultiSelectDropdown.module.css css
.list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 180px;
  max-height: 320px;
  overflow-y: auto;
}

.option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  user-select: none;
}

.option:hover {
  background: var(--bg);
}

.option input {
  margin: 0;
  accent-color: var(--accent);
  flex-shrink: 0;
}

.muted {
  color: var(--muted);
}

.separator {
  height: 1px;
  margin: 4px 2px;
  background: var(--border);
}

Holen

# MCP (Claude Code / Cursor)
get_component({ name: "multi-select-dropdown" })

# Registry direkt
https://www.ekklesi.tools/design/registry/components/multi-select-dropdown.json