fix(welcome): concept cards speak everyday language first
Some checks are pending
Security / Security check (push) Waiting to run
Some checks are pending
Security / Security check (push) Waiting to run
The Hub/Module/Flow cards explained the basics in the very vocabulary they were supposed to introduce (Rust binary, WASM, YAML, hash-chained). Each card now leads with a plain-language explanation; the technical wording moved behind a per-card 'for the technically curious' toggle. DE and EN. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
cc1618f512
commit
3e1ce6e1fd
6 changed files with 163 additions and 28 deletions
|
|
@ -22,11 +22,15 @@
|
||||||
"welcomeHeroTitle": "Ch∆In Platform",
|
"welcomeHeroTitle": "Ch∆In Platform",
|
||||||
"welcomeHeroSubtitle": "Deterministische Workflow-Engine für KI-gestützte Datenverarbeitung in regulierten Umgebungen.",
|
"welcomeHeroSubtitle": "Deterministische Workflow-Engine für KI-gestützte Datenverarbeitung in regulierten Umgebungen.",
|
||||||
"welcomePillarHubTitle": "Hub",
|
"welcomePillarHubTitle": "Hub",
|
||||||
"welcomePillarHubBody": "Ein Rust-Binary, das Module lädt und Flows ausführt. SQLite für den State. Kein Docker, kein Message-Broker, keine Hintergrunddienste, die gepflegt werden müssen.",
|
"welcomePillarHubBody": "Das Programm, das alles ausführt. Es läuft direkt auf Ihrem Rechner, braucht keine Zusatzsoftware und speichert alles Wichtige in einer einzigen Datei.",
|
||||||
|
"welcomePillarHubTech": "Ein Rust-Binary, das Module lädt und Flows ausführt. SQLite für den Zustand. Kein Docker, kein Message-Broker, keine Hintergrunddienste, die gepflegt werden müssen.",
|
||||||
"welcomePillarModuleTitle": "Modul",
|
"welcomePillarModuleTitle": "Modul",
|
||||||
"welcomePillarModuleBody": "Eine kleine WebAssembly-Komponente, die eine Sache macht. Deklariert Netzwerk-Endpunkte, Dateien und Umgebungsvariablen, auf die sie zugreift; der Hub setzt die Liste durch.",
|
"welcomePillarModuleBody": "Ein Baustein, der genau eine Aufgabe erledigt — zum Beispiel Text aus Dokumenten lesen. Jedes Modul sagt vorab, worauf es zugreifen will; mehr erlaubt der Hub nicht.",
|
||||||
|
"welcomePillarModuleTech": "Eine kleine WebAssembly-Komponente in einer Sandbox. Deklariert Netzwerk-Endpunkte, Dateien und Umgebungsvariablen, auf die sie zugreift; der Hub setzt die Liste durch.",
|
||||||
"welcomePillarFlowTitle": "Flow",
|
"welcomePillarFlowTitle": "Flow",
|
||||||
"welcomePillarFlowBody": "Eine YAML-Datei, die Module verkettet. Eingaben rein, Module laufen in der deklarierten Reihenfolge, Ausgaben raus — jeder Schritt in einem hash-verketteten Audit-Log festgehalten.",
|
"welcomePillarFlowBody": "Ein Ablaufplan, der Module zu festen Schritten verbindet. Eingaben rein, Schritte laufen der Reihe nach, Ergebnis raus — und jeder Schritt wird fälschungssicher protokolliert.",
|
||||||
|
"welcomePillarFlowTech": "Eine YAML-Datei, die Module verkettet; jeder Schritt wird in einem hash-verketteten Audit-Log festgehalten, das die Diagnose-Seite komplett verifiziert.",
|
||||||
|
"welcomePillarTechToggle": "Für Technik-Interessierte",
|
||||||
"welcomeTrustHeader": "TRUST-POSTURE",
|
"welcomeTrustHeader": "TRUST-POSTURE",
|
||||||
"welcomeTrustSandboxTitle": "Sandbox von Anfang an",
|
"welcomeTrustSandboxTitle": "Sandbox von Anfang an",
|
||||||
"welcomeTrustSandboxBody": "Jedes Modul bringt eine explizite Berechtigungsliste mit — Netzwerk-Endpunkte, Dateien, Umgebungsvariablen. Der Hub setzt sie durch; ohne Operator-Freigabe verlässt nichts die Sandbox.",
|
"welcomeTrustSandboxBody": "Jedes Modul bringt eine explizite Berechtigungsliste mit — Netzwerk-Endpunkte, Dateien, Umgebungsvariablen. Der Hub setzt sie durch; ohne Operator-Freigabe verlässt nichts die Sandbox.",
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,15 @@
|
||||||
"welcomeHeroTitle": "Ch∆In Platform",
|
"welcomeHeroTitle": "Ch∆In Platform",
|
||||||
"welcomeHeroSubtitle": "Deterministic workflow engine for AI-assisted data processing in regulated environments.",
|
"welcomeHeroSubtitle": "Deterministic workflow engine for AI-assisted data processing in regulated environments.",
|
||||||
"welcomePillarHubTitle": "Hub",
|
"welcomePillarHubTitle": "Hub",
|
||||||
"welcomePillarHubBody": "One Rust binary that loads modules and runs flows. SQLite for state. No Docker, no message broker, no background services to babysit.",
|
"welcomePillarHubBody": "The program that runs everything. It works right on your machine, needs no extra software, and keeps everything important in a single file.",
|
||||||
|
"welcomePillarHubTech": "One Rust binary that loads modules and runs flows. SQLite for state. No Docker, no message broker, no background services to babysit.",
|
||||||
"welcomePillarModuleTitle": "Module",
|
"welcomePillarModuleTitle": "Module",
|
||||||
"welcomePillarModuleBody": "A small WebAssembly component that does one thing. Declares the network endpoints, files, and environment variables it touches; the hub enforces the list.",
|
"welcomePillarModuleBody": "A building block that does exactly one job — reading text out of documents, say. Every module states up front what it wants to touch; the hub allows nothing more.",
|
||||||
|
"welcomePillarModuleTech": "A small, sandboxed WebAssembly component. Declares the network endpoints, files, and environment variables it touches; the hub enforces the list.",
|
||||||
"welcomePillarFlowTitle": "Flow",
|
"welcomePillarFlowTitle": "Flow",
|
||||||
"welcomePillarFlowBody": "A YAML file that chains modules together. Inputs go in, modules run in declared order, outputs come out — every step recorded in a hash-chained audit log.",
|
"welcomePillarFlowBody": "A recipe that connects modules into fixed steps. Inputs go in, steps run in order, the result comes out — and every step is recorded tamper-evidently.",
|
||||||
|
"welcomePillarFlowTech": "A YAML file that chains modules together; every step is recorded in a hash-chained audit log that the Diagnostics page verifies in full.",
|
||||||
|
"welcomePillarTechToggle": "For the technically curious",
|
||||||
"welcomeTrustHeader": "TRUST POSTURE",
|
"welcomeTrustHeader": "TRUST POSTURE",
|
||||||
"welcomeTrustSandboxTitle": "Sandbox by default",
|
"welcomeTrustSandboxTitle": "Sandbox by default",
|
||||||
"welcomeTrustSandboxBody": "Every module ships with an explicit permission list — network endpoints, files, environment variables. The hub enforces it; nothing reaches outside the sandbox without operator approval.",
|
"welcomeTrustSandboxBody": "Every module ships with an explicit permission list — network endpoints, files, environment variables. The hub enforces it; nothing reaches outside the sandbox without operator approval.",
|
||||||
|
|
|
||||||
|
|
@ -233,9 +233,15 @@ abstract class AppLocalizations {
|
||||||
/// No description provided for @welcomePillarHubBody.
|
/// No description provided for @welcomePillarHubBody.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'One Rust binary that loads modules and runs flows. SQLite for state. No Docker, no message broker, no background services to babysit.'**
|
/// **'The program that runs everything. It works right on your machine, needs no extra software, and keeps everything important in a single file.'**
|
||||||
String get welcomePillarHubBody;
|
String get welcomePillarHubBody;
|
||||||
|
|
||||||
|
/// No description provided for @welcomePillarHubTech.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'One Rust binary that loads modules and runs flows. SQLite for state. No Docker, no message broker, no background services to babysit.'**
|
||||||
|
String get welcomePillarHubTech;
|
||||||
|
|
||||||
/// No description provided for @welcomePillarModuleTitle.
|
/// No description provided for @welcomePillarModuleTitle.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
@ -245,9 +251,15 @@ abstract class AppLocalizations {
|
||||||
/// No description provided for @welcomePillarModuleBody.
|
/// No description provided for @welcomePillarModuleBody.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'A small WebAssembly component that does one thing. Declares the network endpoints, files, and environment variables it touches; the hub enforces the list.'**
|
/// **'A building block that does exactly one job — reading text out of documents, say. Every module states up front what it wants to touch; the hub allows nothing more.'**
|
||||||
String get welcomePillarModuleBody;
|
String get welcomePillarModuleBody;
|
||||||
|
|
||||||
|
/// No description provided for @welcomePillarModuleTech.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'A small, sandboxed WebAssembly component. Declares the network endpoints, files, and environment variables it touches; the hub enforces the list.'**
|
||||||
|
String get welcomePillarModuleTech;
|
||||||
|
|
||||||
/// No description provided for @welcomePillarFlowTitle.
|
/// No description provided for @welcomePillarFlowTitle.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
@ -257,9 +269,21 @@ abstract class AppLocalizations {
|
||||||
/// No description provided for @welcomePillarFlowBody.
|
/// No description provided for @welcomePillarFlowBody.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'A YAML file that chains modules together. Inputs go in, modules run in declared order, outputs come out — every step recorded in a hash-chained audit log.'**
|
/// **'A recipe that connects modules into fixed steps. Inputs go in, steps run in order, the result comes out — and every step is recorded tamper-evidently.'**
|
||||||
String get welcomePillarFlowBody;
|
String get welcomePillarFlowBody;
|
||||||
|
|
||||||
|
/// No description provided for @welcomePillarFlowTech.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'A YAML file that chains modules together; every step is recorded in a hash-chained audit log that the Diagnostics page verifies in full.'**
|
||||||
|
String get welcomePillarFlowTech;
|
||||||
|
|
||||||
|
/// No description provided for @welcomePillarTechToggle.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'For the technically curious'**
|
||||||
|
String get welcomePillarTechToggle;
|
||||||
|
|
||||||
/// No description provided for @welcomeTrustHeader.
|
/// No description provided for @welcomeTrustHeader.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
@ -5056,15 +5080,21 @@ abstract class AppLocalizations {
|
||||||
/// No description provided for @runsEmptyTitle.
|
/// No description provided for @runsEmptyTitle.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'No detached runs'**
|
/// **'No background runs'**
|
||||||
String get runsEmptyTitle;
|
String get runsEmptyTitle;
|
||||||
|
|
||||||
/// No description provided for @runsEmptyHint.
|
/// No description provided for @runsEmptyHint.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Runs submitted with detach stay here until they finish. Detached invocations are opt-in — enable detached.enabled in the operator config to use them.'**
|
/// **'Runs that keep working in the background while you do something else appear here. The feature is optional and off by default — the guide shows step by step how to turn it on.'**
|
||||||
String get runsEmptyHint;
|
String get runsEmptyHint;
|
||||||
|
|
||||||
|
/// No description provided for @runsEmptyGuideButton.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Open the guide'**
|
||||||
|
String get runsEmptyGuideButton;
|
||||||
|
|
||||||
/// No description provided for @runsCancelButton.
|
/// No description provided for @runsCancelButton.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
|
||||||
|
|
@ -83,21 +83,36 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomePillarHubBody =>
|
String get welcomePillarHubBody =>
|
||||||
'Ein Rust-Binary, das Module lädt und Flows ausführt. SQLite für den State. Kein Docker, kein Message-Broker, keine Hintergrunddienste, die gepflegt werden müssen.';
|
'Das Programm, das alles ausführt. Es läuft direkt auf Ihrem Rechner, braucht keine Zusatzsoftware und speichert alles Wichtige in einer einzigen Datei.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get welcomePillarHubTech =>
|
||||||
|
'Ein Rust-Binary, das Module lädt und Flows ausführt. SQLite für den Zustand. Kein Docker, kein Message-Broker, keine Hintergrunddienste, die gepflegt werden müssen.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomePillarModuleTitle => 'Modul';
|
String get welcomePillarModuleTitle => 'Modul';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomePillarModuleBody =>
|
String get welcomePillarModuleBody =>
|
||||||
'Eine kleine WebAssembly-Komponente, die eine Sache macht. Deklariert Netzwerk-Endpunkte, Dateien und Umgebungsvariablen, auf die sie zugreift; der Hub setzt die Liste durch.';
|
'Ein Baustein, der genau eine Aufgabe erledigt — zum Beispiel Text aus Dokumenten lesen. Jedes Modul sagt vorab, worauf es zugreifen will; mehr erlaubt der Hub nicht.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get welcomePillarModuleTech =>
|
||||||
|
'Eine kleine WebAssembly-Komponente in einer Sandbox. Deklariert Netzwerk-Endpunkte, Dateien und Umgebungsvariablen, auf die sie zugreift; der Hub setzt die Liste durch.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomePillarFlowTitle => 'Flow';
|
String get welcomePillarFlowTitle => 'Flow';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomePillarFlowBody =>
|
String get welcomePillarFlowBody =>
|
||||||
'Eine YAML-Datei, die Module verkettet. Eingaben rein, Module laufen in der deklarierten Reihenfolge, Ausgaben raus — jeder Schritt in einem hash-verketteten Audit-Log festgehalten.';
|
'Ein Ablaufplan, der Module zu festen Schritten verbindet. Eingaben rein, Schritte laufen der Reihe nach, Ergebnis raus — und jeder Schritt wird fälschungssicher protokolliert.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get welcomePillarFlowTech =>
|
||||||
|
'Eine YAML-Datei, die Module verkettet; jeder Schritt wird in einem hash-verketteten Audit-Log festgehalten, das die Diagnose-Seite komplett verifiziert.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get welcomePillarTechToggle => 'Für Technik-Interessierte';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomeTrustHeader => 'TRUST-POSTURE';
|
String get welcomeTrustHeader => 'TRUST-POSTURE';
|
||||||
|
|
@ -2980,11 +2995,14 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
String get runsReloadTooltip => 'Lauf-Liste neu laden';
|
String get runsReloadTooltip => 'Lauf-Liste neu laden';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get runsEmptyTitle => 'Keine abgekoppelten Läufe';
|
String get runsEmptyTitle => 'Keine Läufe im Hintergrund';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get runsEmptyHint =>
|
String get runsEmptyHint =>
|
||||||
'Mit detach gestartete Läufe stehen hier, bis sie fertig sind. Abgekoppelte Aufrufe sind optional — dazu detached.enabled in der Betreiber-Konfiguration aktivieren.';
|
'Hier erscheinen Läufe, die im Hintergrund weiterlaufen, während Sie anderes tun. Diese Funktion ist optional und standardmäßig ausgeschaltet — die Anleitung zeigt Schritt für Schritt, wie sie eingeschaltet wird.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get runsEmptyGuideButton => 'Anleitung öffnen';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get runsCancelButton => 'Abbrechen';
|
String get runsCancelButton => 'Abbrechen';
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,10 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomePillarHubBody =>
|
String get welcomePillarHubBody =>
|
||||||
|
'The program that runs everything. It works right on your machine, needs no extra software, and keeps everything important in a single file.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get welcomePillarHubTech =>
|
||||||
'One Rust binary that loads modules and runs flows. SQLite for state. No Docker, no message broker, no background services to babysit.';
|
'One Rust binary that loads modules and runs flows. SQLite for state. No Docker, no message broker, no background services to babysit.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -91,14 +95,25 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomePillarModuleBody =>
|
String get welcomePillarModuleBody =>
|
||||||
'A small WebAssembly component that does one thing. Declares the network endpoints, files, and environment variables it touches; the hub enforces the list.';
|
'A building block that does exactly one job — reading text out of documents, say. Every module states up front what it wants to touch; the hub allows nothing more.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get welcomePillarModuleTech =>
|
||||||
|
'A small, sandboxed WebAssembly component. Declares the network endpoints, files, and environment variables it touches; the hub enforces the list.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomePillarFlowTitle => 'Flow';
|
String get welcomePillarFlowTitle => 'Flow';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomePillarFlowBody =>
|
String get welcomePillarFlowBody =>
|
||||||
'A YAML file that chains modules together. Inputs go in, modules run in declared order, outputs come out — every step recorded in a hash-chained audit log.';
|
'A recipe that connects modules into fixed steps. Inputs go in, steps run in order, the result comes out — and every step is recorded tamper-evidently.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get welcomePillarFlowTech =>
|
||||||
|
'A YAML file that chains modules together; every step is recorded in a hash-chained audit log that the Diagnostics page verifies in full.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get welcomePillarTechToggle => 'For the technically curious';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get welcomeTrustHeader => 'TRUST POSTURE';
|
String get welcomeTrustHeader => 'TRUST POSTURE';
|
||||||
|
|
@ -2981,11 +2996,14 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
String get runsReloadTooltip => 'Reload the runs list';
|
String get runsReloadTooltip => 'Reload the runs list';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get runsEmptyTitle => 'No detached runs';
|
String get runsEmptyTitle => 'No background runs';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get runsEmptyHint =>
|
String get runsEmptyHint =>
|
||||||
'Runs submitted with detach stay here until they finish. Detached invocations are opt-in — enable detached.enabled in the operator config to use them.';
|
'Runs that keep working in the background while you do something else appear here. The feature is optional and off by default — the guide shows step by step how to turn it on.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get runsEmptyGuideButton => 'Open the guide';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get runsCancelButton => 'Cancel';
|
String get runsCancelButton => 'Cancel';
|
||||||
|
|
|
||||||
|
|
@ -310,17 +310,24 @@ class _PillarRow extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final l = AppLocalizations.of(context)!;
|
final l = AppLocalizations.of(context)!;
|
||||||
final pillars = <(IconData, String, String)>[
|
final pillars = <(IconData, String, String, String)>[
|
||||||
(Icons.hub_outlined, l.welcomePillarHubTitle, l.welcomePillarHubBody),
|
(
|
||||||
|
Icons.hub_outlined,
|
||||||
|
l.welcomePillarHubTitle,
|
||||||
|
l.welcomePillarHubBody,
|
||||||
|
l.welcomePillarHubTech,
|
||||||
|
),
|
||||||
(
|
(
|
||||||
Icons.extension_outlined,
|
Icons.extension_outlined,
|
||||||
l.welcomePillarModuleTitle,
|
l.welcomePillarModuleTitle,
|
||||||
l.welcomePillarModuleBody,
|
l.welcomePillarModuleBody,
|
||||||
|
l.welcomePillarModuleTech,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Icons.account_tree_outlined,
|
Icons.account_tree_outlined,
|
||||||
l.welcomePillarFlowTitle,
|
l.welcomePillarFlowTitle,
|
||||||
l.welcomePillarFlowBody,
|
l.welcomePillarFlowBody,
|
||||||
|
l.welcomePillarFlowTech,
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
|
|
@ -333,7 +340,7 @@ class _PillarRow extends StatelessWidget {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
for (final p in pillars) ...[
|
for (final p in pillars) ...[
|
||||||
_Pillar(icon: p.$1, title: p.$2, body: p.$3),
|
_Pillar(icon: p.$1, title: p.$2, body: p.$3, tech: p.$4),
|
||||||
const SizedBox(height: ChainSpace.md),
|
const SizedBox(height: ChainSpace.md),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
@ -356,6 +363,7 @@ class _PillarRow extends StatelessWidget {
|
||||||
icon: pillars[i].$1,
|
icon: pillars[i].$1,
|
||||||
title: pillars[i].$2,
|
title: pillars[i].$2,
|
||||||
body: pillars[i].$3,
|
body: pillars[i].$3,
|
||||||
|
tech: pillars[i].$4,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -367,16 +375,34 @@ class _PillarRow extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _Pillar extends StatelessWidget {
|
/// Concept card in everyday language; the technical wording
|
||||||
|
/// (Rust, WASM, YAML, hash chain) lives behind a per-card
|
||||||
|
/// "for the technically curious" toggle so the first read
|
||||||
|
/// never requires developer vocabulary.
|
||||||
|
class _Pillar extends StatefulWidget {
|
||||||
final IconData icon;
|
final IconData icon;
|
||||||
final String title;
|
final String title;
|
||||||
final String body;
|
final String body;
|
||||||
|
final String tech;
|
||||||
|
|
||||||
const _Pillar({required this.icon, required this.title, required this.body});
|
const _Pillar({
|
||||||
|
required this.icon,
|
||||||
|
required this.title,
|
||||||
|
required this.body,
|
||||||
|
required this.tech,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_Pillar> createState() => _PillarState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PillarState extends State<_Pillar> {
|
||||||
|
bool _techOpen = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
final l = AppLocalizations.of(context)!;
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(ChainSpace.lg),
|
padding: const EdgeInsets.all(ChainSpace.lg),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|
@ -387,22 +413,57 @@ class _Pillar extends StatelessWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Icon(icon, size: 28, color: theme.colorScheme.primary),
|
Icon(widget.icon, size: 28, color: theme.colorScheme.primary),
|
||||||
const SizedBox(height: ChainSpace.md),
|
const SizedBox(height: ChainSpace.md),
|
||||||
Text(
|
Text(
|
||||||
title,
|
widget.title,
|
||||||
style: theme.textTheme.titleLarge?.copyWith(
|
style: theme.textTheme.titleLarge?.copyWith(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: ChainSpace.sm),
|
const SizedBox(height: ChainSpace.sm),
|
||||||
Text(
|
Text(
|
||||||
body,
|
widget.body,
|
||||||
style: theme.textTheme.bodyMedium?.copyWith(
|
style: theme.textTheme.bodyMedium?.copyWith(
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
height: 1.45,
|
height: 1.45,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: ChainSpace.sm),
|
||||||
|
InkWell(
|
||||||
|
onTap: () => setState(() => _techOpen = !_techOpen),
|
||||||
|
borderRadius: BorderRadius.circular(ChainRadius.sm),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
_techOpen ? Icons.expand_less : Icons.expand_more,
|
||||||
|
size: 16,
|
||||||
|
color: theme.colorScheme.primary,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Text(
|
||||||
|
l.welcomePillarTechToggle,
|
||||||
|
style: theme.textTheme.labelMedium?.copyWith(
|
||||||
|
color: theme.colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_techOpen) ...[
|
||||||
|
const SizedBox(height: ChainSpace.xs),
|
||||||
|
Text(
|
||||||
|
widget.tech,
|
||||||
|
style: theme.textTheme.bodySmall?.copyWith(
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
height: 1.45,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue