@micha.bigler/ui-core-micha 2.41.2 → 2.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/WORK_ORDERS.md +4 -3
- package/dist/components/charts/BarChart.js +11 -4
- package/dist/components/charts/ChartFrame.js +12 -3
- package/dist/components/charts/LineChart.js +11 -4
- package/dist/components/charts/ScatterChart.js +11 -4
- package/dist/components/charts/chartDefaults.js +41 -0
- package/dist/i18n/messagingTranslations.js +116 -116
- package/package.json +1 -1
- package/src/components/charts/BarChart.jsx +14 -2
- package/src/components/charts/ChartFrame.jsx +13 -2
- package/src/components/charts/LineChart.jsx +14 -2
- package/src/components/charts/ScatterChart.jsx +14 -2
- package/src/components/charts/chartDefaults.js +43 -0
- package/src/i18n/messagingTranslations.ts +116 -116
- package/tests/BarChart.test.jsx +48 -0
- package/tests/ChartFrame.test.jsx +43 -0
- package/tests/LineChart.test.jsx +46 -1
- package/tests/ScatterChart.test.jsx +38 -1
- package/tests/chartDefaults.test.js +73 -0
- package/tests/i18nAggregate.test.js +1 -4
- package/tests/messagingMsg6.test.jsx +2 -2
- package/work-orders/I18N-3.md +68 -0
- package/work-orders/UCM-CHART-8.md +147 -0
package/work-orders/I18N-3.md
CHANGED
|
@@ -93,6 +93,74 @@ No API, behaviour or visual change for `de`/`fr`/`en` consumers. Purely additive
|
|
|
93
93
|
|
|
94
94
|
*Filled by the Orchestrator on `git pull` — see `AGENTS.md` → "Work Order".*
|
|
95
95
|
|
|
96
|
+
**Files to change (exactly two):**
|
|
97
|
+
- [`src/i18n/messagingTranslations.ts`](../src/i18n/messagingTranslations.ts) — 118 lines, 116 keys
|
|
98
|
+
(`export const messagingTranslations = { 'Key': { de, en, fr }, ... }`), every value currently a
|
|
99
|
+
3-locale object. Add a fourth `sw: '...'` to every one, matching the existing key ordering
|
|
100
|
+
`de, en, fr` → append `sw` last (matches the property order already used in
|
|
101
|
+
`notificationsTranslations.ts`/`onboardingTranslations.ts`, both `de, fr, en, sw`, so put `sw`
|
|
102
|
+
last regardless of the de/en/fr internal order already in this file — do not reorder de/en/fr).
|
|
103
|
+
- [`tests/i18nAggregate.test.js`](../tests/i18nAggregate.test.js) — line 30:
|
|
104
|
+
`const REQUIRED_LOCALES = ['de', 'en', 'fr'];` → `['de', 'en', 'fr', 'sw'];`, and delete the
|
|
105
|
+
explanatory comment at lines 27-29 (`// Scoped to the three locales ... see the Notiz on the
|
|
106
|
+
I18N-1 register row ...`) since it will no longer describe the state. Nothing else in this file
|
|
107
|
+
changes — the other three `it()` blocks (aggregate completeness, no-collision, per-bundle
|
|
108
|
+
availability) are untouched.
|
|
109
|
+
|
|
110
|
+
**Existing Swahili glossary to reuse — do not coin alternate wording for these concepts** (grep
|
|
111
|
+
`sw:` across `src/i18n/*.ts` yourself to see full context; this is not exhaustive, check for any
|
|
112
|
+
other overlap you find):
|
|
113
|
+
- Notification/notify → **Arifa** (`notificationsTranslations.ts`, `onboardingTranslations.ts`)
|
|
114
|
+
- Save → **Hifadhi** (`onboardingTranslations.ts`: `Onboarding.SAVE`)
|
|
115
|
+
- Close → **Funga** (`notificationsTranslations.ts`: `PopupSurface.CLOSE`)
|
|
116
|
+
- Continue → **Endelea** (`onboardingTranslations.ts`: `Onboarding.CONTINUE`)
|
|
117
|
+
- Skip → **Ruka** (`onboardingTranslations.ts`: `Onboarding.SKIP`)
|
|
118
|
+
- Change/switch (section) → **Badilisha** (`sectionNavTranslations.ts`)
|
|
119
|
+
- User menu / profile / logout → **Menyu ya mtumiaji / Wasifu / Toka** (`userMenuTranslations.ts`)
|
|
120
|
+
- "Could not be saved/loaded" error pattern → e.g. **"...haikuweza kuhifadhiwa"** /
|
|
121
|
+
**"...haikuweza kupakiwa"** (`notificationsTranslations.ts` `SAVE_ERROR`/`LOAD_ERROR`) — messaging
|
|
122
|
+
has the same error-string shape repeated ~15 times (`... konnte nicht ... werden: {{message}}`),
|
|
123
|
+
reuse this grammatical pattern rather than inventing a new one per key.
|
|
124
|
+
- "Please try again" → **"Tafadhali jaribu tena"** (`onboardingTranslations.ts`)
|
|
125
|
+
|
|
126
|
+
**None of messaging's specific domain terms (conversation, reply, attachment, reaction, poll,
|
|
127
|
+
announcement, unread, archive, mute) exist in the other bundles' Swahili** — those need fresh
|
|
128
|
+
translation. That is expected and fine; the instruction above is narrower: reuse wording only where
|
|
129
|
+
the *same* concept (save/cancel/close/error phrasing/etc.) already has a Swahili rendering
|
|
130
|
+
elsewhere, don't invent a second one for it.
|
|
131
|
+
|
|
132
|
+
**Do-not-touch:** `de`/`en`/`fr` values in `messagingTranslations.ts` (verify byte-identical before
|
|
133
|
+
and after — a diff review will check this); the other six bundles; `tests/i18nAggregate.test.js`'s
|
|
134
|
+
other three tests, the aggregate export, the directory ratchet, the ordering (`de, en, fr` internal
|
|
135
|
+
order in messaging stays as-is, `sw` only appended).
|
|
136
|
+
|
|
137
|
+
**Progress contract:** `PLAN: …` naming the two files, `PROGRESS: [1/2] backfill sw into
|
|
138
|
+
messagingTranslations.ts … done`, `PROGRESS: [2/2] restore REQUIRED_LOCALES + drop scope-down
|
|
139
|
+
comment in i18nAggregate.test.js … done`, then run the scoped tests named below and report which
|
|
140
|
+
keys (if any) you were unsure of, then `RESULT: DONE`.
|
|
141
|
+
|
|
142
|
+
## Preamble
|
|
143
|
+
|
|
144
|
+
The text above is the COMPLETE spec — the committed WO file's content, not a plan to refine; there is
|
|
145
|
+
no separate plan file. Read the nearest `AGENTS.md`, the relevant `.codex/skills/<role>/SKILL.md`, and
|
|
146
|
+
the app `MEMORY.md` ONLY for conventions. Stay in scope; do not touch auth/permissions/deps/schema/CI
|
|
147
|
+
unless the spec says so; do not update `MEMORY.md`. **Do NOT edit `WORK_ORDERS.md`** — the register row
|
|
148
|
+
and the review verdicts are the orchestrator's alone. Do NOT `git add`/`commit`/`push` — leave every
|
|
149
|
+
change uncommitted in the working tree for the orchestrator's independent review. This WO's "Required
|
|
150
|
+
tests to WRITE" is explicitly **none new** — the restored `REQUIRED_LOCALES` assertion IS the test;
|
|
151
|
+
run it (and the messaging export specs) to confirm your backfill makes it pass — that is the ONLY test
|
|
152
|
+
run you do (NOT the app's affected/full suite, NOT any review). **State plainly in your final report:
|
|
153
|
+
the source of the Swahili translations (e.g. "machine-translated via <tool>, not reviewed by a fluent
|
|
154
|
+
speaker" — say so honestly, do not imply review that didn't happen) and list any specific key you were
|
|
155
|
+
uncertain of**, per the Envelope's explicit disclosure requirement. The orchestrator re-runs the
|
|
156
|
+
authoritative set + does the independent review after you finish — those are the gate; your own run
|
|
157
|
+
does not count as the gate.
|
|
158
|
+
|
|
159
|
+
Narrate continuously: a `PLAN: <step1> | <step2> | …` line up front, then a single-line
|
|
160
|
+
`PROGRESS: [<n>/<total>] <present-tense action>` before every relevant action (and `… done` on
|
|
161
|
+
completion), spaced so no gap exceeds ~2 min, stdout unbuffered, plus exactly one final
|
|
162
|
+
`RESULT: DONE|BLOCKED <reason>`.
|
|
163
|
+
|
|
96
164
|
---
|
|
97
165
|
|
|
98
166
|
## C. Orchestrator only
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# UCM-CHART-8 — Make the chart presets stop producing dead space below the chart
|
|
2
|
+
|
|
3
|
+
- **Repo:** `ui-core-micha`, branch `main` (shared-core; publishes from `main` without a staging step)
|
|
4
|
+
- **Tier:** 3 — shared-core. Every consuming app inherits the behaviour change.
|
|
5
|
+
- **Status:** planned
|
|
6
|
+
- **Workstream:** `CHART-*` (chart presets)
|
|
7
|
+
- **Files:** `src/components/charts/ScatterChart.jsx`, `BarChart.jsx`, `LineChart.jsx`,
|
|
8
|
+
`TimeSeriesChart.jsx`, **`ChartFrame.jsx`** — all five destructure `minHeight` **and** `aspect`
|
|
9
|
+
(verified 2026-08-21) — plus their tests. **Note for the implementer: only `ScatterChart` and
|
|
10
|
+
`TimeSeriesChart` reference `height` at all.** `BarChart`, `LineChart` and `ChartFrame` never
|
|
11
|
+
destructure it, so for them the incoherent "pair" exists only via the rest spread into the MUI
|
|
12
|
+
chart. Do not go looking for a declared `height` prop there.
|
|
13
|
+
|
|
14
|
+
> **Why.** `minHeight` and `height` are two different things on these presets, and the API lets a
|
|
15
|
+
> caller pass both. `minHeight` lands on the **wrapper `Box`** —
|
|
16
|
+
> `sx={{ width: '100%', minHeight, aspectRatio: aspect }}` (`ScatterChart.jsx:260`, same
|
|
17
|
+
> construction in `BarChart.jsx`) — while `height` sizes the **chart**. When `minHeight > height`,
|
|
18
|
+
> the difference is dead space **below the chart**.
|
|
19
|
+
>
|
|
20
|
+
> Measured in `hram` on 2026-08-20:
|
|
21
|
+
>
|
|
22
|
+
> | panel | `minHeight` | `height` | dead space |
|
|
23
|
+
> |---|---|---|---|
|
|
24
|
+
> | `StructuralReachabilityPanel` | 420 | 380 | 40 px |
|
|
25
|
+
> | `ExpertTimelinePanel` | 340 | 280 (×2) | 60 px |
|
|
26
|
+
> | `ResultsTimelinePanel` | 320 | 280 | 40 px |
|
|
27
|
+
> | `GroupMetricsPanel` | 300 | **none** | the whole chart is unsized |
|
|
28
|
+
> | Cost, Ratio, Accessibility, Referral, Total | equal | equal | 0 |
|
|
29
|
+
>
|
|
30
|
+
> **The equal-value majority is why this survived.** Passing both looks like harmless
|
|
31
|
+
> belt-and-braces and costs nothing when the numbers match, so the pattern spread by copy-paste and
|
|
32
|
+
> nobody noticed the cases where they diverge. It has been diagnosed and fixed **pointwise twice**
|
|
33
|
+
> in hram (`AllocationPerformancePanel.jsx:462-478`, `OptimizationResultsPanel.jsx:928-940`, both to
|
|
34
|
+
> `height={420}`) — with the explanation written as a comment **inside those two files**, where no
|
|
35
|
+
> new panel will ever read it.
|
|
36
|
+
>
|
|
37
|
+
> This is not N panel bugs. It is one shared API that permits an incoherent pair, and it will keep
|
|
38
|
+
> recurring for as long as it does. Fixing it here fixes every consumer at once, including the ones
|
|
39
|
+
> nobody sweeps.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Part A — Envelope (authoritative WHAT/WHY)
|
|
44
|
+
|
|
45
|
+
### Goal
|
|
46
|
+
|
|
47
|
+
A caller can no longer produce dead space by passing `minHeight`. The presets resolve the pair
|
|
48
|
+
themselves, and the incoherent combination becomes impossible rather than merely discouraged.
|
|
49
|
+
|
|
50
|
+
### Definition of Done
|
|
51
|
+
|
|
52
|
+
- [ ] **The resolution is three-way, not two-way — `aspect` is the third input and it changes the
|
|
53
|
+
answer.** Amended 2026-08-21; the original two-way rule would have broken four live call sites.
|
|
54
|
+
- **`height` present** → it sizes the chart, and the wrapper reserves no more than that.
|
|
55
|
+
- **No `height`, no `aspect`** → **`minHeight` sizes the chart**, not merely the wrapper.
|
|
56
|
+
This is what a caller in that shape meant (`GroupMetricsPanel`: `minHeight={300}`, no
|
|
57
|
+
`height`, no `aspect` — chart unsized today).
|
|
58
|
+
- **No `height`, but `aspect` present** → **today's behaviour is correct and must not change.**
|
|
59
|
+
The wrapper is `width: 100%` with `aspectRatio`, so its height derives from its width, and
|
|
60
|
+
`minHeight` is the floor that stops it collapsing on a narrow viewport. Here `minHeight`
|
|
61
|
+
means exactly what its name says.
|
|
62
|
+
|
|
63
|
+
**Same prop shape, opposite intent** — which is why the rule cannot be stated on
|
|
64
|
+
`minHeight`/`height` alone.
|
|
65
|
+
- [ ] **`minHeight > height` produces no wrapper padding.** The chart is sized by `height` and the
|
|
66
|
+
wrapper does not reserve more than the chart occupies. The extra space was never intentional.
|
|
67
|
+
- [ ] **Equal values behave exactly as today** — that is the majority of call sites and they must
|
|
68
|
+
not shift by a pixel.
|
|
69
|
+
- [ ] **A dev-mode warning names the offending call site** when both are passed and they disagree.
|
|
70
|
+
Not a throw: a shared package that throws on a prop combination in production breaks a
|
|
71
|
+
consumer's page over a layout nit.
|
|
72
|
+
- [ ] **JSDoc on every preset that takes it** states in one line what `minHeight` now does, so the
|
|
73
|
+
next caller does not have to infer it from a comment in a consumer app.
|
|
74
|
+
|
|
75
|
+
### Deliberately NOT done
|
|
76
|
+
|
|
77
|
+
- **`minHeight` is not removed from the API.** Removing it is a breaking change to a shared package,
|
|
78
|
+
which would make every consumer's pin bump a Tier-3 change with a real chance of unnoticed layout
|
|
79
|
+
regressions — a worse outcome than the defect. Deprecate in the docstring, coerce in the code.
|
|
80
|
+
- No change to chart internals, palettes, axis defaults or `aspect`.
|
|
81
|
+
- No consumer-side sweep in this WO. hram's call-site cleanup is its own follow-up, gated on the pin
|
|
82
|
+
bump — see below.
|
|
83
|
+
|
|
84
|
+
### Preconditions and ordering
|
|
85
|
+
|
|
86
|
+
The fix only reaches hram after **(a)** this lands and publishes and **(b)** hram bumps its
|
|
87
|
+
`@micha.bigler/ui-core-micha` pin. Verify the published version is actually live before the consumer
|
|
88
|
+
bump — this package publishes from `main` with no staging step, so a failed publish is silent until
|
|
89
|
+
a consumer installs it.
|
|
90
|
+
|
|
91
|
+
### Risks
|
|
92
|
+
|
|
93
|
+
- **The consumer check is done, and it found something — 2026-08-21.** It was written here as a
|
|
94
|
+
hypothetical ("a consumer may be relying on the padding as spacing"); the real finding is
|
|
95
|
+
different and larger. **Four live call sites pass `aspect` together with `minHeight` and no
|
|
96
|
+
`height`:**
|
|
97
|
+
|
|
98
|
+
| call site | props |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `hram/AccessGapScatterPanel.jsx:182` | `aspect={1.8}` + `minHeight={320}` |
|
|
101
|
+
| `fitness-monitor/BodyHistoryPage.jsx:~328` | `aspect="960 / 380"` + `minHeight={320}` |
|
|
102
|
+
| `fitness-monitor/BodyHistoryPage.jsx:~355` | `aspect="960 / 380"` + `minHeight={320}` |
|
|
103
|
+
| `fitness-monitor/BodyHistoryPage.jsx:~450` | `aspect="400 / 220"` + `minHeight={220}` |
|
|
104
|
+
|
|
105
|
+
These are not relying on padding-as-spacing. They are using `minHeight` **as a floor under an
|
|
106
|
+
aspect-derived height**, which is legitimate and is what the name promises. The original
|
|
107
|
+
Definition of Done would have turned all four into fixed-height charts and removed their
|
|
108
|
+
responsive behaviour. **That is the reason for the three-way rule above**, and it is the case to
|
|
109
|
+
hold onto when reading the rest of this order.
|
|
110
|
+
|
|
111
|
+
Scope note: `survey-renderer` is named above as a consumer to check. **The standalone repo is
|
|
112
|
+
retired** (2026-07-31); the widget now lives at `survey_app/frontend/packages/survey-renderer`,
|
|
113
|
+
and neither it nor `cockpit` or `jg-ferien` passes `aspect` to a chart preset. jg's one `aspect=`
|
|
114
|
+
hit is an `ImageCropDialog`, unrelated.
|
|
115
|
+
- The dev warning must not fire on the equal-value majority, or it becomes noise that trains people
|
|
116
|
+
to ignore it.
|
|
117
|
+
|
|
118
|
+
### Tests to WRITE — narrow
|
|
119
|
+
|
|
120
|
+
- `minHeight` alone, **no `aspect`** → the chart receives that height.
|
|
121
|
+
- **`minHeight` + `aspect`, no `height` → unchanged from today**: the wrapper keeps its
|
|
122
|
+
`aspectRatio` and `minHeight` stays a floor, and the chart is **not** given a fixed height. This is
|
|
123
|
+
the four-call-site case in Risks and the one a two-way rule would have broken — **it is the test
|
|
124
|
+
that has to fail if someone later re-simplifies the resolution.**
|
|
125
|
+
- `minHeight > height` → the chart receives `height` and the wrapper reserves no more than that.
|
|
126
|
+
- `minHeight === height` → byte-identical to the current output.
|
|
127
|
+
- `height` alone → unchanged.
|
|
128
|
+
- The dev warning fires only on the disagreeing pair, and names the values. It must **not** fire on
|
|
129
|
+
`minHeight` + `aspect` without `height`, which is a legitimate combination.
|
|
130
|
+
|
|
131
|
+
No full suite.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Part B — Implementation map
|
|
136
|
+
|
|
137
|
+
> **TO BE FILLED BY THE ORCHESTRATOR** on `git pull`. Must carry the preset files with `path:line`
|
|
138
|
+
> anchors (`ScatterChart.jsx:173-174, :260` and the equivalents), the absolute working directory,
|
|
139
|
+
> the progress contract, and the preamble. **Do not dispatch while this placeholder stands.**
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Part C — Orchestrator-only
|
|
144
|
+
|
|
145
|
+
> **TO BE FILLED BY THE ORCHESTRATOR.** Review routing (`reviewer` + `ui_reviewer`, full context —
|
|
146
|
+
> Tier 3 shared-core), verification, register maintenance, commit, publish check, and the execution
|
|
147
|
+
> directive with its self-address guard.
|