Kalas (muted) design spec with final tokens, components and every screen S-1 to S-22 in all states; 80-frame screen catalogue with 155 PNGs in docs/ux/screens/; strings.csv with D-017 module prefixes (558 rows, en and sv); colour tokens renamed to the landed contract names slate and amber; fixed category ids; proposed-decisions.md with the final §9.7 hex values and UX-9. Supersedes tokens.md, components.md, screens.md and the U1 Kalas PNGs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U2TeboHB8AtnzTrt3bWFzY
10 KiB
Kvitt: information architecture
Status: U1 (2026-10-17), updated in U2 (2026-10-18) for the owner's decisions (proposed-decisions.md: three tabs kept, UX-2; category suggestion, UX-3; 14 default categories, UX-8). Look and states of each screen: design-spec.md. Binding inputs: SPEC §13.2 (navigation model), §13.3 (screens S-1 to S-22), §14.2.4 (UI contract), §6.2 (module ownership). Screen ids are the spec's (S-1 … S-22), not renumbered.
1. Bottom navigation
Decided (owner, 2026-10-18, UX-2): the spec's three destinations.
| Destination | sv | en | Icon (Material Symbols) | Start screen |
|---|---|---|---|---|
| Home | Översikt | Home | home (filled when selected) |
S-4 |
| Analytics | Statistik | Analytics | bar_chart |
S-11 |
| Settings | Inställningar | Settings | settings |
S-13 |
Plus one floating action button, "Lägg till utgift" / "Add expense", on S-4 and S-5 only (SPEC §13.2).
Why three and not four:
- Home already is the account list. The second most important question ("who owes whom", §13.1) is answered per account on Home (AC-10.2). A separate "Accounts" destination would split the global balance from its breakdown and add a tap to the most common path (Home → account → expense).
- The add flow is the FAB, not a tab. A tab "Add" would be a navigation item that is really an action; Material 3 discourages that, and the FAB is reachable with the thumb on both phones.
- No fourth destination exists in the spec. The only candidate that would earn the slot is an Activity feed (the other person's latest changes across all accounts, i.e. the audit log as a list). It would be useful together with push notifications (US-13), but it is a new feature, out of scope for the UX sprint (§13.5). The owner did not take it for v1 (UX-2).
- Three items keep Swedish labels whole: "Inställningar" (13 characters) fits at 200 % font scale in a three-item bar but not in a four- or five-item bar of 411 dp.
Navigation bar style: Expressive ShortNavigationBar (64 dp; fallback NavigationBar), design-spec.md §3.11.
2. Screen inventory
Kind: top = bottom-nav destination; pushed = full screen with top app bar and back (§13.2); flow = onboarding screen without bottom nav; dialog / banner as named.
| Id | Screen (sv / en) | Kind | Feature module (§6.2) | Reached from | State from (§14.2.4) |
|---|---|---|---|---|---|
| S-1 | Para ihop / Pair | flow, start when Unpaired or Unrecognised |
:feature:onboarding |
app start; deep link kvitt://invite?… or https://…/i/<CODE> (AC-2.6); S-18 |
SessionRepository |
| S-2 | Din profil (partner step) / Your profile | flow | :feature:onboarding |
S-1 after a partner pairing (AC-2.10) |
SessionRepository, ProfileRepository |
| S-3 | Väntar på din partner / Waiting for your partner | top (replaces S-4 content) | :feature:onboarding |
Home while partner == null (AC-5.1) |
SessionRepository, InviteRepository |
| S-4 | Översikt / Home | top | :feature:home |
bottom nav; notification for deletions and sync_batch |
HomeRepository → HomeState |
| S-5 | Konto (account detail) | pushed | :feature:account |
S-4 account row | AccountRepository.detail → AccountDetailState |
| S-6 | Nytt konto / Ändra konto | pushed | :feature:account |
S-4 "Nytt konto"; S-5 overflow "Ändra konto" | AccountRepository |
| S-7 | Ny utgift / Ändra utgift | pushed, full screen (§13.2) | :feature:expense |
FAB on S-4 or S-5; S-8 "Ändra"; S-19 editor reuses its fields | ExpenseRepository.editorOptions, preview, save, suggestCategory (UX-3) |
| S-8 | Utgift (expense detail) | pushed | :feature:expense |
ledger rows (S-5, S-12, S-16); notification | ExpenseRepository.detail → ExpenseDetailState |
| S-9 | Gör upp / Settle up | pushed | :feature:settle |
S-4 "Gör upp" (global); S-5 "Gör upp det här kontot" (per account); S-10 "Ändra" | SettlementRepository.start, recompute, save → SettleState |
| S-10 | Betalning (settlement detail) | pushed | :feature:settle |
settlement rows; notification | SettlementRepository.detail |
| S-11 | Statistik / Analytics | top | :feature:analytics |
bottom nav | AnalyticsRepository.analytics → AnalyticsState |
| S-12 | Statistik, urval (drill-down) | pushed | :feature:analytics |
tap on a bar or a breakdown row in S-11 (AC-14.8) | AnalyticsRepository.drillDown |
| S-13 | Inställningar / Settings | top | :feature:settings |
bottom nav | ProfileRepository.household, SessionRepository (role) |
| S-14 | Profil | pushed | :feature:settings |
S-13 | ProfileRepository |
| S-15 | Kategorier (list + editor; 14 default categories, UX-8) | pushed (editor pushed from list) | :feature:settings |
S-13 | CategoryRepository |
| S-16 | Synkstatus / Sync status | pushed | :feature:home |
S-4 sync line; S-13 "Synkstatus" | SyncRepository.status |
| S-17 | Uppdatering (banner + dialogs) | banner on S-4, dialogs | :feature:home |
S-4 when UpdateState != None; S-22 "Sök efter uppdatering" |
UpdateRepository |
| S-18 | Telefonen har tagits bort / Device removed | flow, start when Revoked |
:feature:onboarding |
any 401 device_revoked (AC-3.3) |
SessionRepository.acknowledgeRevoked |
| S-19 | Återkommande utgifter (list + editor) | pushed | :feature:settings |
S-13 | RecurringRepository |
| S-20 | Enheter / Devices | pushed | :feature:settings |
S-13 | DeviceRepository |
| S-21 | Inbjudningar (Bjud in partner / Para ihop en enhet) | pushed | :feature:settings |
S-13 (admin only); S-3 "Bjud in partner" | InviteRepository |
| S-22 | Om Kvitt / About | pushed | :feature:settings |
S-13 | AboutRepository, UpdateRepository.check |
System notifications (SPEC §13.3 table, §14.6) are not screens; they open S-8, S-10 or S-4 (AC-13.6).
3. Start destination and session routing
The app shell (:app) chooses the root from SessionRepository.session:
SessionState |
Root | Notes |
|---|---|---|
Unpaired |
S-1 | Fields filled when opened from an invite link. |
Paired, partner == null |
S-4 showing the S-3 content | Bottom nav visible; Statistik shows its empty state; FAB hidden (AC-5.1). For the member this state cannot occur. |
Paired, just paired as partner |
S-2, then S-4 | AC-2.10. Notification permission is asked after the first full sync (AC-2.9), i.e. on arriving at S-4. |
Paired |
S-4 | First sync after pairing shows the S-4 loading state. |
Revoked |
S-18 | Local data already wiped (AC-3.3). |
Unrecognised |
S-1 with "Para ihop telefonen igen" header | Local data kept (§14.4.8). |
Back from a top destination exits the app (Home) or returns to Home (Statistik, Inställningar). Each top destination keeps its own back stack and scroll position when switching tabs.
4. Navigation map
┌──────────────── bottom nav ─────────────────┐
S-4 Översikt S-11 Statistik S-13 Inställningar
│ ├ sync line → S-16 └ bar/row → S-12 ├ S-14 Profil
│ ├ banner → S-17 └ row → S-8 ├ S-15 Kategorier → editor
│ ├ Gör upp → S-9 (global) ├ S-19 Återkommande → editor (S-7 fields)
│ ├ Nytt konto → S-6 ├ S-20 Enheter
│ ├ FAB → S-7 ├ S-21 Inbjudningar (admin)
│ └ account → S-5 ├ S-16 Synkstatus
│ ├ FAB → S-7 └ S-22 Om Kvitt → S-17
│ ├ Gör upp det här kontot → S-9 (one account)
│ ├ overflow: Ändra konto → S-6, Arkivera, Ta bort
│ ├ expense row → S-8 → Ändra → S-7
│ └ settlement row → S-10 → Ändra → S-9
Onboarding: S-1 → (partner) S-2 → S-4 ; S-1 → (admin) S-4 with S-3 content → S-21
Anywhere: 401 device_revoked → S-18 → S-1
After saving in S-7 the app returns to where the editor was opened from (S-4 or S-5, or S-8 when editing). After confirming S-9 it returns to S-4 or S-5.
5. Which screen owns which data
"Owns" = the only place where the data is created or edited. Every other screen only reads it. Offline column per AC-15.2 and §9.9.
| Data | Owned (edited) by | Read by | Offline edit |
|---|---|---|---|
| Session, pairing, device token | S-1, S-18 | :app routing |
no (pairing needs the server) |
| Own display name and picture | S-14 (and S-2 once for the partner) | S-4 hero, S-13, all avatars, timelines | no ("Kräver anslutning") |
| Partner's name and picture | partner's own S-14 | everywhere | — |
| Accounts (name, default ratio, archived, deleted) | S-6 (create, edit), S-5 overflow (archive, unarchive, delete) | S-4, S-7 picker (active only), S-9 rows and "Lägg till konto" (all), S-11/S-12, S-19 picker | no |
| Categories | S-15 | S-7 quick row and "Alla" sheet (active only; selected by the suggestion of UX-3 for new expenses), S-8, ledger rows, S-11/S-12, S-19 | no |
| Recurring templates | S-19 | S-8 ("Återkommande: Hyra") | no |
| Expenses | S-7 (create, edit), S-8 (delete) | S-4 (counts, balances), S-5, S-11/S-12, S-16 (pending) | yes |
| Settlements | S-9 (create, edit), S-10 (delete) | S-4/S-5 balances and rows, S-16 (pending) | yes |
| Audit timeline | server only (never edited) | S-8, S-10 | — |
| Balances, proposals, analytics | computed, never stored (§5.5) | S-4, S-5, S-9, S-11, S-12 | always available |
| Devices | S-20 (revoke) | — | no |
| Invites | S-21 (create, share, cancel), S-3 shortcut | S-3 (expiry of the pending invite) | no |
| Sync state, rejections | system; S-16 dismisses rejections | S-4 sync line | dismiss works offline |
| App update | S-17 | S-4 banner, S-22 | no |
6. Role differences (admin vs member)
| Where | Admin (Jacob) | Member (Anna) |
|---|---|---|
| S-13 | row "Bjud in partner" (before the partner joins) or "Para ihop en enhet" | row "Para ihop en enhet" is not shown (AC-2.2: only the admin creates invites). |
| S-20 | all devices of both users; revoke any except the current | own devices only; revoke own except the current (AC-3.2) |
| S-21 | available | not reachable |
| S-3 | shown until the partner joins | never |
Everything else is identical for both users (§3.1).