Frontend: Tech-Stack

Technologien

| Technologie | Version | Zweck |
|---|---|---|
| SolidJS | ~1.x | UI Framework (reaktiv, kein Virtual DOM) |
| TypeScript | ~5.x | Typsicherheit |
| Vite | ~5.x | Build-Tool |
| pnpm | ~8.x | Package Manager |
| Styled System | (Panda CSS) | CSS-in-JS |
| Lingui | ~4.x | i18n (Übersetzungen) |
| solid-dnd-directive | – | Drag & Drop |
| solid-floating-ui | – | Tooltips, Popups |

SolidJS Grundlagen

SolidJS ist React-ähnlich, aber reaktiv ohne Virtual DOM.

import { createSignal, createMemo, createEffect, Show, For } from "solid-js";

// Signal = reaktiver State
const [count, setCount] = createSignal(0);

// Memo = abgeleiteter Wert (cached)
const doubled = createMemo(() => count() * 2);

// Effect = Seiteneffekt bei Änderungen
createEffect(() => {
console.log("Count changed:", count());
});

// Bedingte Darstellung
<Show when={count() > 0}>
<p>Count: {count()}</p>
</Show>

// Listen
<For each={items()}>
{(item) => <div>{item.name}</div>}
</For>

Komponenten-Struktur

// Typische Komponentendefinition
import { Component, createSignal } from "solid-js";

interface Props {
name: string;
onClose: () => void;
}

export function MyComponent(props: Props) {
const [open, setOpen] = createSignal(false);

return (
<div>
<h1>{props.name}</h1>
<button onClick={props.onClose}>Schließen</button>
</div>
);
}

CSS mit css() und styled()

import { css } from "styled-system/css";
import { styled } from "styled-system/jsx";

// Inline CSS (für dynamische Styles)
const dynamicStyle = css({
color: "var(--md-sys-color-primary)",
borderRadius: "8px",
});

// Styled Component
const MyDiv = styled("div", {
base: {
background: "var(--bg)",
padding: "1rem",
},
variants: {
size: {
small: { fontSize: "0.8rem" },
large: { fontSize: "1.2rem" },
}
}
});

Floating-System (Tooltips, Menus)

Das use:floating Direktiv wird für Tooltips, Context-Menus und User-Cards verwendet:

// Tooltip
<div use:floating={{
  tooltip: {
    content: "Hover-Text",
    placement: "right",
  }
}}>
  Hover mich
</div>

// Context Menu (Rechtsklick)
<div use:floating={{
contextMenu: () => (
<ContextMenu>
<ContextMenuButton onClick={doSomething}>
Aktion
</ContextMenuButton>
</ContextMenu>
),
}}>
Rechtsklick mich
</div>

createResource für async Daten

import { createResource } from "solid-js";

// Automatisches Fetching mit Reaktivität
const [data, { mutate, refetch }] = createResource(userId, async (id) => {
const res = await fetch(/api/user/${id});
return res.json();
});

// Zugriff
if (data.loading) return <div>Lädt...</div>;
if (data.error) return <div>Fehler!</div>;
return <div>{data()?.name}</div>;

// Lokal aktualisieren (optimistic update)
mutate({ ...data(), name: "Neuer Name" });