Bauen
So funktionieren Components
Jede Component folgt demselben Muster. Eine Datei, eine Prop für die Variante, deine Inhalte über Props und ein paar eingebaute Texte in zwei Sprachen.
Auf dieser Seite
Eine Datei je Component#
Eine Component ist eine einzelne .tsx-Datei in src/components/ui. Sie exportiert die Component, ihren Props-Typ und den Typ ihrer Varianten. Ihre eigenen Texte stehen als TEXTS in beiden Sprachen in der Datei.
import { cn, useTexts } from '@/lib/kit';
import { Button } from '@/components/ui/button';
export type FaqVariant = 'accordion' | 'two-column' | 'grid' | …;
const TEXTS = {
en: { search: 'Search questions', … },
de: { search: 'Fragen durchsuchen', … },
};
export interface FaqProps {
variant?: FaqVariant;
title?: React.ReactNode;
items: FaqItem[];
labels?: Partial<(typeof TEXTS)['en']>;
className?: string;
}
export function Faq(props: FaqProps) { … }Importiert wird immer über den Alias, @/components/ui/<name> für Components und @/lib/kit für Helfer wie cn, KitProvider und useInView.
Varianten#
Eine Component, viele Layouts. Die Prop variant wählt eines davon, der Hero kennt 17, das FAQ 7. Deine Inhalte bleiben dieselben, du tauschst nur das Wort.
<Hero variant="centered" title="…" />
<Hero variant="split" title="…" media={<img src="/shop.avif" alt="…" />} />
<Hero variant="with-stats" title="…" stats={[{ value: '1962', label: 'gegründet' }]} />Jede Variante steht mit Live-Vorschau auf ihrer Seite, etwa unter Hero.
Inhalte über Props#
Alles, was auf der Seite steht, kommt über Props. Eine Component trägt keine Marke und keinen festen Text, sie passt in die Kanzlei genauso wie in den Online-Shop.
import { Faq } from '@/components/ui/faq';
<Faq
variant="accordion"
title="Gut zu wissen"
defaultOpen={0}
schema
items={[
{ question: 'Kann ich vor Ort bezahlen?', answer: 'Ja, mit Karte oder bar, direkt bei der Abholung.' },
{ question: 'Wie lange vorher bestellen?', answer: 'Bis 18 Uhr am Vortag, für Torten zwei Tage vorher.' },
]}
/>schema schreibt die strukturierten Daten für Suchmaschinen gleich mit. Die wichtigsten Props des Hero im Überblick:
| Prop | Typ | Standard | Wofür |
|---|---|---|---|
| variant | 'centered' | 'split' | 'left' | 'with-form' | … | 'centered' | Eines von 17 Layouts. |
| title | ReactNode | · | Die Überschrift. Pflicht. |
| description | ReactNode | · | Der Text unter der Überschrift. |
| primaryAction | { label, href } | · | Der Hauptknopf. |
| secondaryAction | { label, href } | · | Der zweite Knopf, ruhiger. |
| media | ReactNode | · | Bild, Screenshot oder Zeichnung neben oder unter dem Text. |
| labels | Partial<Texts> | · | Eigene Worte für eingebaute Texte. |
| className | string | · | Zusätzliche Klassen am äußeren Element. |
Sprache und labels#
Ein paar Texte schreibt eine Component selbst, etwa Schließen, Weiter oder Hinweise im Formular. KitProvider setzt ihre Sprache für alles darunter, Englisch ist der Standard. Für einzelne Stellen überschreibt labels genau die Wörter, die du nennst.
<Faq
variant="with-search"
items={items}
labels={{ search: 'Hilfe durchsuchen', placeholder: 'Zum Beispiel Versand' }}
/>Slots für Bilder und Medien#
Bilder, Logos, Avatare und Medien sind Props vom Typ ReactNode. Du gibst ein <img>, ein Video, ein SVG oder eine ganze Component hinein, die Component setzt es an die richtige Stelle und in den richtigen Rahmen.
<Hero
variant="split"
title="Frisches Brot, jeden Morgen"
media={<img src="/bakery.avif" alt="Theke der Bäckerei Lindner" width={1200} height={900} />}
logos={[<Logo1 key="1" />, <Logo2 key="2" />]}
/>Für Gerätebilder gibt es BrowserFrame und PhoneFrame, gezeichnete Motive findest du unter Visuals.
Interaktiv in Astro#
Components rendern auf dem Server vollständig, ihr Inhalt steht als HTML da. Hat eine Component Zustand, etwa ein Akkordeon, ein Umschalter oder ein Formular, braucht sie in Astro eine client-Direktive. client:visible lädt sie, sobald sie ins Bild kommt, client:load sofort.
---
import { Faq } from '@/components/ui/faq';
import { Home } from '../components/Home';
---
<!-- Ohne Zustand, nur HTML -->
<Faq variant="grid" items={items} />
<!-- Mit Zustand, als Insel -->
<Home client:visible />Gemeinsame Helfer#
Components einer Familie teilen sich eine Datei mit Helfern, damit Formulare gleich prüfen, Diagramme gleich lesen und Szenen gleich scrollen. aiw add holt sie als Abhängigkeit mit, du importierst sie auch selbst für eigene Bausteine.
| Helfer | Import | Wofür |
|---|---|---|
| form-flow | @/components/ui/form-flow | Felder als Daten, Prüfung, Fehlerzusammenfassung, Fokus auf den ersten Fehler, Chips und die Bestätigung aller Formular-Sections. |
| chart | @/components/ui/chart | Skalen, Zahlenformate, Farben, Tastatur und die Datentabelle hinter jedem Diagramm. |
| chart-figure | @/components/ui/chart-figure | Der Rahmen der neueren Diagramme mit Titel, großer Zahl, Veränderung und Quelle. |
| scroll-scene | @/components/ui/scroll-scene | Scroll-Fortschritt als CSS-Variable für Scroll-Geschichten und Scroll-Effekte. |
| motion-scene | @/components/ui/motion-scene | Wiedergabe der animierten Visuals, außerhalb des Bilds pausiert, ruhig bei reduzierter Bewegung. |
| section | @/components/ui/section | Rahmen, Überschriftenblock und Eyebrow, die die meisten Sections teilen. |
Anleitungen mit Beispielen stehen unter Formulare, Diagramme und Scroll-Geschichten.
Anpassen#
className geht an das äußere Element und gewinnt bei Konflikten, so passt du Abstände oder Hintergrund an, ohne die Datei zu öffnen.
<Pricing variant="cards" plans={plans} className="py-32" />Für alles Weitere öffnest du die Datei. Sie gehört dir, du änderst sie wie deinen eigenen Code.