Four design directions for the unified document editing experience. The goal: make the enrich page the single entry point for both enrichment and editing, while reducing the friction of filling in metadata. Each concept attacks a different root cause of friction.
| Element | Concepts | Tailwind / Code | Notes |
|---|---|---|---|
| Section stepper tab bar | A | flex border-b border-line bg-surface |
Each tab: flex-1 py-2 text-center text-[10px] font-bold uppercase tracking-widest. Active: text-ink border-b-2 border-brand-navy. Done: text-green-700. |
| Completed section summary row | A | flex items-center justify-between px-3 py-2.5 bg-surface border border-line rounded-sm text-xs |
Label: font-bold uppercase tracking-widest text-green-700. Summary: text-ink-2 truncate max-w-[180px]. Clicking jumps to that section. |
| "Weiter →" primary button | A | btn-primary (existing class) |
Label changes: "Weiter → Beschreibung" → "Weiter → Inhalt" → "Speichern & Geprüft". Driven by currentSection state. |
| Required-fields progress bar | B | h-0.5 rounded-full bg-brand-navy transition-all inside h-0.5 flex-1 rounded-full bg-line |
Width: style="width: {(filledRequired / totalRequired) * 100}%". Bar lives in its own strip between top bar and split pane. |
| Optional divider | B | flex items-center gap-2 my-5 |
Lines: flex-1 border-t border-line. Label: text-[9px] font-bold uppercase tracking-widest text-ink-3. |
| Locked primary button | B D | opacity-40 cursor-not-allowed pointer-events-none on existing btn-primary |
Or: distinct disabled class bg-line text-ink-3. Reactive: const canReview = $derived(requiredFilled === requiredCount). |
| Compact rail field height | C | h-6 py-0 px-2 text-xs on inputs |
Real pixel height: 24 px. Standard is 36 px. Only use compact height inside the 35%-width rail to preserve minimum 44 px touch target via larger click zone around label + input. |
| Keyboard shortcut badge | C | <kbd class="inline-flex items-center h-4 px-1 bg-surface border border-line rounded text-[10px] font-mono font-bold text-ink-2"> |
Use native <kbd> element for screen-reader semantics. Announce via aria-label on the button too. |
| OCR banner | D | bg-mint/10 border border-brand-mint rounded-sm p-3 flex items-start gap-2 text-xs |
Only rendered when data.ocrSuggestions is non-empty. Icon: w-4 h-4 rounded-full bg-brand-mint flex items-center justify-center text-brand-navy font-bold text-[10px]. |
| Suggested / prefill field | D | border-brand-mint bg-mint/10 text-teal-700 font-medium |
Add data-suggested="true" attribute. On Tab: remove mint styles, set value. On input: clear suggestion immediately. Server populates suggestedDateIso, suggestedSenderName props (already exist on WhoWhenSection). |
| Completion ring SVG | D | SVG with two <circle> elements |
Circumference at r=8: ≈50.3 px. Filled arc: stroke-dasharray="{(filled/total)*50.3} {50.3}". Rotate −90° so arc starts at top. Color: stroke="currentColor" text-brand-navy. |
| Unlocked "Geprüft" button | D | bg-green-700 hover:bg-green-800 text-white |
State: const canReview = $derived(confirmedFields.size >= requiredFields.length). Animate transition: transition-colors duration-200. |
| Action bar (shared) | A B C D | flex items-center gap-3 border-t border-line bg-surface px-4 min-h-[44px] |
Skip: ghost left (text-ink-2 text-sm font-medium). Save: outline right. Primary: filled rightmost. Min 44 px height per WCAG 2.2 touch target. |