Designsystem
Alle Ordo-Oberflächen — Ordo Betrieb, Ordo Portal, Ordo Partner, Ordo Kontrolle, die mobilen Apps,
diese Website und die technische Präsentation — laufen auf einem Designsystem. Seine Quelle ist das
Paket tfs-frontend/packages/ui-kit; die Token-Tabellen dieser Seite werden zur Build-Zeit aus
dessen tokens.css gelesen, und die Komponentenbeispiele werden mit denselben Custom Properties
gezeichnet. Die Seite kann dem Code nicht hinterherhinken: Ändert sich ein Token, ändert sich die Tabelle.
Der technische Codename der Plattform ist TFS; URLs (tfs-*.karyabilisim.com), Paketnamen
(@tfs/*), Repository-Namen und Umgebungsvariablen tragen ihn. Überall, wo ein Mensch liest,
heißt das Produkt Ordo.
Grundsätze
Abschnitt betitelt „Grundsätze“- Hierarchie durch Schrift und Raum, nicht durch Farbe oder Kästen. Ein Akzent je Ansicht.
- Flache Flächen, Haarlinien. Ein 1-px-Trenner vor einer Karte; nie eine Karte in der Karte.
- Dicht, aber ruhig. 8-px-Raster; Abschnittsabstände 32/48 px; Seitenränder 24 px Desktop, 16 px Telefon.
- Keine Verläufe, kein Leuchten, kein Glas. Die schlichte, halbtransparente Fläche des Sticky-Headers ist die einzige Ausnahme.
- Icons mit 1,5 px Strich, currentColor, 16/20 px. Keine Emoji; keine Icon-im-Farbkreis-Raster.
- Tabellen sind die Hauptfläche des Betriebs. Sticky-Kopf, rechtsbündige tabulare Zahlen, Mono-IDs, Zeilen-Hover auf
--tfs-surface-hover, kein Zebra. - Formulare reservieren eine Hilfszeile. Label 13 px/500; Control 32 px; Masken für Geld, Telefon, E-Mail, TCKN, IBAN und Datum. Fehlertext in
--tfs-danger-text; ein roter Rand allein genügt nicht. - Das Seitenkopf-Muster ist auf jeder Seite gleich. Bereichslabel → h1 (24 px/600) → einzeilige Beschreibung → Aktionen rechts; Breadcrumbs darüber bei Tiefe > 1.
- Leer-, Lade- und Fehlerzustände sind gestaltet. Skeletons spiegeln das endgültige Layout.
- Bei 390 px läuft nichts über. Tabellen scrollen in ihrem Container; die Seite scrollt nie horizontal.
- Simulationen und Live-Vorschauen haben feste Größe.
scrollHeightund dasgetBoundingClientRect()des Containers sind vor und nach einem Lauf identisch. - Das dunkle Theme ist erstklassig. Jedes Token hat ein dunkles Gegenstück; jeder berührte Bildschirm wird in beiden Themes geprüft.
- Kontrastgepaarte Tokens. Jede gefüllte Fläche hat ein
*-contrast, jede weiche Fläche ein*-text(WCAG AA). Fließtext steht nie auf einer farbigen Fläche. - Regulierungshinweise leben in
InfoPopoverundReferenceShelf. Inline-Hinweise nur dort, wo freigegeben (Finanzlage).
Farbe — neutral (kühle Tinte)
Abschnitt betitelt „Farbe — neutral (kühle Tinte)“Seitengrund gray-100, Flächen weiß (dunkles Theme gray-950 / gray-900), Ränder gray-200.
- gray-50
- #f7f8fa
- gray-100
- #f0f2f5
- gray-200
- #e1e4ea
- gray-300
- #c9ced7
- gray-400
- #9aa2af
- gray-500
- #6d7585
- gray-600
- #525a69
- gray-700
- #3c4350
- gray-800
- #282d37
- gray-900
- #181c24
- gray-950
- #0e1116
Farbe — primär (Marine-Tinte)
Abschnitt betitelt „Farbe — primär (Marine-Tinte)“Die primäre Füllung ist primary-800 im hellen und primary-500 im dunklen Theme; Links und das aktive Element nutzen --tfs-primary-text.
- primary-50
- #f1f5fa
- primary-100
- #dfe8f2
- primary-200
- #c0d2e6
- primary-300
- #94b1d2
- primary-400
- #6189b8
- primary-500
- #3d679c
- primary-600
- #2c5082
- primary-700
- #24416a
- primary-800
- #1c3454
- primary-900
- #152741
- primary-950
- #0c1829
Farbe — semantisch
Abschnitt betitelt „Farbe — semantisch“Die linke Hälfte jedes Swatches ist der helle, die rechte der dunkle Wert.
- bg
- #f0f2f5
- #0e1116
- surface
- #ffffff
- #181c24
- surface-raised
- #ffffff
- #282d37
- surface-sunken
- #f7f8fa
- #0b0e13
- surface-hover
- #f0f2f5
- #282d37
- surface-tint
- color-mix(in srgb, #1c3454 6%, #ffffff)
- color-mix(in srgb, #3d679c 12%, #181c24)
- border
- #e1e4ea
- #282d37
- border-strong
- #c9ced7
- #3c4350
- text
- #181c24
- #f0f2f5
- text-muted
- #525a69
- #9aa2af
- text-subtle
- #6d7585
- #9aa2af
- primary
- #1c3454
- #3d679c
- primary-hover
- #152741
- #6189b8
- primary-soft
- #f1f5fa
- rgb(97 137 184 / 0.16)
- primary-contrast
- #ffffff
- primary-text
- #24416a
- #94b1d2
- focus-ring
- #3d679c
- #94b1d2
- focus-ring-soft
- rgb(61 103 156 / 0.28)
- rgb(148 177 210 / 0.32)
- overlay
- rgb(14 17 22 / 0.55)
- rgb(8 10 14 / 0.72)
- tooltip-bg
- #181c24
- #f0f2f5
- tooltip-text
- #f7f8fa
- #181c24
Farbe — Akzent (Messing)
Abschnitt betitelt „Farbe — Akzent (Messing)“Die eine warme Note im System: die Marke, eine hervorgehobene Zahl, die Haarlinie unter einem Abschnittstitel, der „gezogene“ Anteil eines Zyklus. Nie eine Button-Füllung, nie ein Status.
- accent
- #a97f2c
- #c9a24f
- accent-contrast
- #231a06
- accent-soft
- #f7f0df
- rgb(201 162 79 / 0.16)
- accent-text
- #7a5a1a
- #e2c27a
Farbe — Status
Abschnitt betitelt „Farbe — Status“Eine Stufe unter voller Sättigung. Paarungsregel: gefüllt + -contrast, weich + -text. Amber trägt nie weißen Text.
- danger
- #c0392f
- danger-hover
- #a22f27
- danger-soft
- #fbeeec
- rgb(192 57 47 / 0.16)
- danger-contrast
- #ffffff
- danger-text
- #a12d25
- #f2a39c
- success
- #1f7a4d
- success-soft
- #e9f5ee
- rgb(31 122 77 / 0.16)
- success-contrast
- #ffffff
- success-text
- #1b6b43
- #6fcf97
- warning
- #b8791f
- warning-soft
- #fbf3e3
- rgb(184 121 31 / 0.16)
- warning-contrast
- #1f1400
- warning-text
- #8a5a12
- #e8b45a
- info
- #2a6db3
- info-soft
- #eaf2fb
- rgb(42 109 179 / 0.16)
- info-contrast
- #ffffff
- info-text
- #245f9c
- #7fb3ea
Farbe — Chart-Palette
Abschnitt betitelt „Farbe — Chart-Palette“Die Reihenfolge ist fest; Konsumenten indizieren über chartPalette. Die ersten beiden sind das Hauspaar
(Marine, Messing); das Cashflow-Paar nutzt dieselben beiden für Geldeingang und -ausgang, damit Statusgrün und -rot dem Zustand vorbehalten bleiben.
- chart-1
- #2c5082
- #7fa6d6
- chart-2
- #a97f2c
- #d6b36a
- chart-3
- #1f8a7a
- #5cc3b2
- chart-4
- #6b7fb3
- #a3b1dc
- chart-5
- #c0392f
- #ef8d84
- chart-6
- #7d4e8c
- #c493d2
- chart-7
- #3f8f4f
- #85c98f
- chart-8
- #b5536d
- #e295aa
- chart-flow-in
- #2c5082
- #6189b8
- chart-flow-out
- #a97f2c
- #c9a24f
- chart-grid
- #e1e4ea
- #282d37
- chart-axis
- #6d7585
- #9aa2af
- chart-cursor
- rgb(24 28 36 / 0.06)
- rgb(154 162 175 / 0.1)
Typografie
Abschnitt betitelt „Typografie“IBM Plex Sans für Text und Überschriften, IBM Plex Mono für IDs und Zahlen, die ausgerichtet sein müssen.
Auf der Website, in der Dokumentation und in der Präsentation werden Display-Überschriften ab 28 px in
Newsreader (Serif, variabel) gesetzt; der Fließtext bleibt Plex. Bereichslabels sind 11–12 px, Versalien,
0,06 em Laufweite, --tfs-text-subtle. Zahlen in tabular-nums.
| Token | Wert | Beispiel | Verwendung |
|---|---|---|---|
--tfs-text-muted | var(--tfs-gray-600) · var(--tfs-gray-600) | Pool-Saldo ₺48.200.000,00 | |
--tfs-text-subtle | var(--tfs-gray-500) · var(--tfs-gray-500) | Pool-Saldo ₺48.200.000,00 | |
--tfs-text-xs | 0.75rem · 12px | Pool-Saldo ₺48.200.000,00 | Meta, Badges, Tabellenkopf, Hilfszeile |
--tfs-text-sm | 0.8125rem · 13px | Pool-Saldo ₺48.200.000,00 | Formularlabel, Tabellenzelle, Button |
--tfs-text-md | 0.875rem · 14px | Pool-Saldo ₺48.200.000,00 | Fließtext (Apps) |
--tfs-text-lg | 1rem · 16px | Pool-Saldo ₺48.200.000,00 | Dialogtitel |
--tfs-text-xl | 1.25rem · 20px | Pool-Saldo ₺48.200.000,00 | Seitentitel (h1, 600) |
--tfs-text-2xl | 1.5rem · 24px | Pool-Saldo ₺48.200.000,00 | KPI-Wert (tabular) |
--tfs-text-3xl | 1.875rem · 30px | Pool-Saldo ₺48.200.000,00 | Dashboard-Titel |
--tfs-text-4xl | 2.25rem · 36px | Pool-Saldo ₺48.200.000,00 | Nur Marketing/Doku — Newsreader |
--tfs-font-sans | "IBM Plex Sans Variable", "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif | ||
--tfs-font-mono | "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace | ||
--tfs-tracking-tight | -0.01em | ||
--tfs-tracking-tighter | -0.02em | ||
--tfs-tracking-wide | 0.06em | ||
--tfs-leading-tight | 1.2 | ||
--tfs-leading-normal | 1.5 | ||
Bewusst scharf. Alles-abgerundet liest sich wie Consumer-Software; ein Journal muss exakt wirken, nicht freundlich. Pillenformen nur beim Statuspunkt und beim Avatar.
| Token | Wert | Beispiel |
|---|---|---|
--tfs-radius-sm | 0.125rem · 2px | |
--tfs-radius-md | 0.25rem · 4px | |
--tfs-radius-lg | 0.375rem · 6px | |
--tfs-radius-xl | 0.5rem · 8px | |
--tfs-radius-2xl | 0.75rem · 12px | |
--tfs-radius-full | 9999px · 9999px |
Abstände und Dichte
Abschnitt betitelt „Abstände und Dichte“| Token | Wert | Beispiel |
|---|---|---|
--tfs-space-1 | 0.25rem · 4px | |
--tfs-space-2 | 0.5rem · 8px | |
--tfs-space-3 | 0.75rem · 12px | |
--tfs-space-4 | 1rem · 16px | |
--tfs-space-5 | 1.25rem · 20px | |
--tfs-space-6 | 1.5rem · 24px | |
--tfs-space-8 | 2rem · 32px |
Die Dichte wird unter [data-density="compact"] enger; die Präferenz bleibt erhalten.
| Token | comfortable | compact |
|---|---|---|
--tfs-row-py | 0.375rem | 0.1875rem |
--tfs-cell-px | 0.75rem | 0.5rem |
Schatten
Abschnitt betitelt „Schatten“xs ist eine Haarlinien-Anhebung, sm eine Karte, md ein Popover, lg ein Dialog. Auf Markenflächen höchstens sm.
| Token | Wert | Beispiel |
|---|---|---|
--tfs-shadow-xs | 0 1px 1px 0 rgb(24 28 36 / 0.04)Dunkles Theme: 0 1px 1px 0 rgb(0 0 0 / 0.3) | |
--tfs-shadow-sm | 0 1px 2px 0 rgb(24 28 36 / 0.06)Dunkles Theme: 0 1px 2px 0 rgb(0 0 0 / 0.4) | |
--tfs-shadow-md | 0 4px 12px -2px rgb(24 28 36 / 0.12)Dunkles Theme: 0 4px 12px -2px rgb(0 0 0 / 0.5) | |
--tfs-shadow-lg | 0 12px 32px -8px rgb(24 28 36 / 0.24)Dunkles Theme: 0 12px 32px -8px rgb(0 0 0 / 0.65) | |
--tfs-shadow-pinned | 4px 0 8px -4px rgb(24 28 36 / 0.12)Dunkles Theme: 4px 0 8px -4px rgb(0 0 0 / 0.5) |
Bewegung
Abschnitt betitelt „Bewegung“Drei Dauern, drei Kurven: standard für Zustandswechsel, emphasized für Elemente, die auf den Bildschirm kommen, exit für das Verlassen. Kein Bounce, keine Skalierung beim Hover, kein Parallax. Bei reduzierter Bewegung alles 0,01 ms.
| Token | Wert |
|---|---|
--tfs-duration-fast | 120ms |
--tfs-duration-base | 200ms |
--tfs-duration-slow | 320ms |
--tfs-ease-standard | cubic-bezier(0.4, 0, 0.2, 1) |
--tfs-ease-emphasized | cubic-bezier(0.2, 0, 0, 1) |
--tfs-ease-exit | cubic-bezier(0.4, 0, 1, 1) |
--tfs-transition-fast | var(--tfs-duration-fast) var(--tfs-ease-standard) |
Komponenteninventar
Abschnitt betitelt „Komponenteninventar“Jedes Beispiel ist eine statische Zeichnung der Komponente unter packages/ui-kit/src/components,
gemalt mit denselben Tokens; es zeichnet sich beim Theme-Wechsel neu. Die Status-Badge ist Punkt + Label
und wählt ihren Ton nie selbst — sie nutzt die Zuordnung im Plattform-Statusregister
(active → success, pending-approval → warning, refused → danger).
Buttoncomponents/button.tsx
Formularfeldcomponents/form-field.tsx · input.tsx · masked-input.tsx
Als Ganzzahl in Minor Units gespeichert
IBAN hat die Mod-97-Prüfung nicht bestanden
Status-Badgecomponents/status-badge.tsx · badge.tsx
Stat-Kartecomponents/stat-card.tsx
Datentabellecomponents/table.tsx
| Vertrag | Kunde | Produkt | Betrag | Gespart | Status |
|---|---|---|---|---|---|
| SZL-2026-0418 | E. Kaya | KONUT-STD | ₺1.250.000,00 | 36,7 % | Freigabe offen |
| SZL-2026-0102 | M. Demir | KONUT-STD | ₺1.500.000,00 | 41,0 % | Aktiv |
| SZL-2026-0423 | A. Yılmaz | ARAC-STD | ₺2.400.000,00 | 12,5 % | Abgelehnt |
| SZL-2025-0310 | S. Çelik | KONUT-STD | ₺900.000,00 | 58,3 % | Zugeteilt |
Seitenkopfcomponents/page-header.tsx · breadcrumbs.tsx
SZL-2026-0418 · Standard Wohnen
Erstellt von demo-admin · 22.09.2026 · Regelwerk v3
Tabscomponents/tabs.tsx
Leer- und Fehlerzuständecomponents/empty-state.tsx · error-state.tsx
Toastcomponents/toast.tsx
Info-Popover und Tooltipcomponents/info-popover.tsx · tooltip.tsx · regulatory-note.tsx
Bestätigungsdialogcomponents/confirm-dialog.tsx · dialog.tsx
Drawercomponents/drawer.tsx
Skeletoncomponents/skeleton.tsx
Fortschritt und Schwellenanzeigecomponents/progress.tsx · threshold-gauge.tsx
Steppercomponents/stepper.tsx · timeline.tsx
- 01Antrag
- 02Identität
- 03Vertrag
- 04Signatur
Avatarcomponents/avatar.tsx
App-Shellcomponents/app-shell.tsx · command-palette.tsx
Layoutmuster
Abschnitt betitelt „Layoutmuster“Seitenmuster: Breadcrumbs → Bereichslabel → h1 → Beschreibung → Aktionen → KPI-Zeile → Tabelleops-web · treasury
Zuteilungskapazität
Periode 2026-10 · Regelwerk v3 · Datenstand 22.09.2026 09:40
| Rang | Vertrag | Gespart | Bedarf | Ergebnis |
|---|---|---|---|---|
| 1 | SZL-0181 | 60 % | ₺260.000,00 | Zugeteilt |
| 2 | SZL-0101 | 52 % | ₺720.000,00 | Zugeteilt |
| 3 | SZL-0148 | 41 % | ₺708.000,00 | Kapazität reicht nicht |
Formularmuster: zwei Spalten, 32-px-Controls, jedes Feld reserviert eine Hilfszeile, Aktionen unten rechtscomponents/form-field.tsx · FieldRow · FormActions
Die Abschlussgebühr wird aus dem Regelwerk gelesen: 7 %
Der Tabellenbereich scrollt in seinem Container und sein Kopf ist darin sticky; die Seite scrollt nie
horizontal. Die KPI-Zeile ist ein StatCard-Raster: Wert text-2xl tabular, Delta und Hinweis text-xs.
White-Label-Vertrag
Abschnitt betitelt „White-Label-Vertrag“Markendifferenzierung lebt ausschließlich in der Mandantenkonfiguration; es gibt keinen Code- oder Asset-Fork,
derselbe Build bedient jeden Mandanten. Die Konfiguration erfolgt über PUT /api/v1/tenant/branding
(siehe Branding-API):
| Was ein Mandant ändert | Wie |
|---|---|
| Logo | logo.type: "svg" Inline-Marke (url(#id)-Verlaufsreferenzen im selben Dokument erlaubt; externe URLs und skriptführende SVGs abgelehnt) oder logo.type: "initials" |
| Primär-Tripel | primary / primarySoft / accent — die Ableitungen --tfs-primary, --tfs-primary-soft, --tfs-primary-text und --tfs-accent werden daraus berechnet |
| Locale | defaultLocale, availableLocales |
| Supportkanäle | supportEmail, supportPhone |
| Was ein Mandant nicht ändern kann | Warum |
|---|---|
| Neutrale Grauskala, Statusfarben, Radien, Typografie, Abstände, Bewegung | Die eigene Stimme der Plattform; unabhängig vom Marken-Tripel |
| Komponentenverhalten, Dichte, Barrierefreiheits-Paarungen | Kontrastpaare werden auf Token-Ebene gelöst; eine Marke kann sie nicht brechen |
| Die Status-→-Ton-Zuordnung | Eine Statusfarbe gilt plattformweit |
Die Standard-Demomarke ist Demo Tasarruf Finansman (Örnek Kurulum), kurz „Demo TF“, Initiale „D“. Ein Demoname, der einem lizenzierten Institut ähnelt, wird nie verwendet.
So und nicht so
Abschnitt betitelt „So und nicht so“Weißer oder gray-50-Grund, Serifenüberschrift, ein Satz.
Kein Verlaufsband, kein Leuchten. Hierarchie entsteht aus Schrift und Raum.
Punkt + Label; die Tonzuordnung kommt aus dem Statusregister.
Keine frei gefärbten Pillen; eine Badge-Farbe wird nie geraten.
- Pool-Saldo₺48.200.000,00
- MADDE 30/15 %
Haarlinienzeilen; Begriff links, Beschreibung rechts.
Keine Icon-im-Farbkreis-Raster. Icons sind 1,5 px Strich, 16/20 px, currentColor.
Flache Fläche, 1 px Rand, höchstens shadow-sm.
Keine Karte in der Karte, kein Schatten überall, kein rounded-2xl.
Ein Akzent je Ansicht: eine Messinglinie oder eine hervorgehobene Zahl.
Messing ist nie eine Button-Füllung und nie eine Statusfarbe.
| SZL-2026-0418 | ₺1.250.000,00 |
| SZL-2026-0102 | ₺900.000,00 |
Tabellenzahlen rechtsbündig, tabular-nums, IDs in Mono.
| SZL-2026-0418 | ₺1.250.000 |
| SZL-2026-0102 | ₺900.000 |
Zahlen werden nie proportional linksbündig gesetzt; Minor Units werden nie abgeschnitten.
Marke und Wortmarke
Abschnitt betitelt „Marke und Wortmarke“Die Marke ist ein Ring in Marine-Tinte mit einem Messingviertel: der Pool und der daraus gezogene Anteil.
Auf dunklen Flächen darf der Ring weiß werden (currentColor); das Messingviertel bleibt immer Messing.
Die Wortmarke ist „Ordo“ in der Display-Schrift (Newsreader) in Gewicht 500–600 mit −0,02 em Laufweite.
Kein Slogan im Lockup außer der Descriptor-Zeile: TR „Tasarruf Finansmanı Platformu“,
EN „Savings Finance Platform“, DE „Plattform für Sparfinanzierung“.
Oberflächennamen: Ordo Betrieb (ops-web), Ordo Portal (customer-web), Ordo Partner (partner-web), Ordo Kontrolle (Control Plane), Ordo (Website).
Regeln der Statusvisualisierung
Abschnitt betitelt „Regeln der Statusvisualisierung“- Geldwerte werden immer aus Minor Units formatiert (siehe Geld und Minor Units); Minor Units werden nie abgeschnitten.
- Status-Badges wählen nie beliebige Farben; sie verwenden die Ton-Zuordnung im Plattform-Statusregister.
- Leer- und Fehlerzustände sind nie stumm: Jede Listenkomponente definiert einen Leertext und eine Wiederholen-Aktion.
- Jeder benutzerseitige Text wird als en/tr/de-Tripel ausgeliefert; eine fehlende Übersetzung lässt den Build über Tests fehlschlagen.
ui-kithängt nicht voni18nab: Jeder Text, den eine Komponente zeigt, wird vom Aufrufer injiziert.