@micha.bigler/ui-core-micha 3.14.4 → 4.0.1
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/CHANGELOG.md +29 -0
- package/README.md +7 -0
- package/dist/chat/kitSxRegistry.js +9 -0
- package/dist/components/charts/kitSxRegistry.js +6 -0
- package/dist/entries/charts.js +6 -0
- package/dist/entries/chat.js +8 -0
- package/dist/entries/markdown.js +1 -0
- package/dist/index.js +0 -14
- package/dist/pages/AccountPage.js +1 -2
- package/dist/pages/LoginPage.js +1 -2
- package/dist/pages/PasswordChangePage.js +1 -2
- package/dist/pages/PasswordInvitePage.js +1 -2
- package/dist/pages/PasswordResetRequestPage.js +1 -2
- package/dist/pages/SignUpPage.js +1 -2
- package/dist/pages/SignupConfirmPage.js +1 -2
- package/dist/theme/kitSxEntry.js +11 -0
- package/dist/theme/kitSxRegistry.js +2 -15
- package/package.json +31 -7
- package/.github/workflows/ci.yml +0 -35
- package/.github/workflows/publish.yml +0 -126
- package/DESIGN.md +0 -60
- package/WORK_ORDERS.md +0 -150
- package/dev/entries.jsx +0 -721
- package/dev/fixtures.js +0 -26
- package/dev/main.jsx +0 -75
- package/dev/mockTransport.jsx +0 -128
- package/docs/CHART-LAYOUT.md +0 -157
- package/docs/DARK-TOKENS.md +0 -140
- package/docs/TYPE-SCALE.md +0 -111
- package/docs/messaging-deviations.md +0 -118
- package/index.html +0 -12
- package/renovate.json +0 -10
- package/scripts/chart-api-census.mjs +0 -415
- package/src/auth/AuthContext.jsx +0 -158
- package/src/auth/ReauthModal.jsx +0 -82
- package/src/auth/UserMenu.jsx +0 -121
- package/src/auth/apiClient.jsx +0 -232
- package/src/auth/authApi.jsx +0 -539
- package/src/auth/authConfig.jsx +0 -34
- package/src/auth/reauth.js +0 -47
- package/src/chat/ChatComposer.jsx +0 -36
- package/src/chat/ChatList.jsx +0 -87
- package/src/chat/ChatThread.jsx +0 -128
- package/src/chat/ChatWorkspace.jsx +0 -244
- package/src/chat/MarkdownReply.jsx +0 -22
- package/src/chat/ModelPicker.jsx +0 -85
- package/src/chat/api.js +0 -18
- package/src/chat/useChatSocket.js +0 -32
- package/src/chat/wire.js +0 -7
- package/src/components/AccessCodeManager.jsx +0 -288
- package/src/components/AccessCodeSingleUseToggle.jsx +0 -92
- package/src/components/AllowedEmailDomainsManager.jsx +0 -92
- package/src/components/AuthFactorRequirementCard.jsx +0 -95
- package/src/components/BulkInviteCsvTab.jsx +0 -198
- package/src/components/EmptyState.jsx +0 -38
- package/src/components/LoginForm.jsx +0 -159
- package/src/components/MFAComponent.jsx +0 -350
- package/src/components/MfaLoginComponent.jsx +0 -252
- package/src/components/MobileBottomNav.jsx +0 -82
- package/src/components/PasskeysComponent.jsx +0 -252
- package/src/components/PasswordChangeForm.jsx +0 -87
- package/src/components/PasswordResetRequestForm.jsx +0 -43
- package/src/components/PasswordSetForm.jsx +0 -97
- package/src/components/ProfileComponent.jsx +0 -348
- package/src/components/QrSignupManager.jsx +0 -404
- package/src/components/QrSignupValidityManager.jsx +0 -106
- package/src/components/RegistrationMethodsManager.jsx +0 -150
- package/src/components/SecurityComponent.jsx +0 -141
- package/src/components/SocialLoginButtons.jsx +0 -83
- package/src/components/SoftChip.jsx +0 -93
- package/src/components/StatTile.jsx +0 -39
- package/src/components/SupportRecoveryRequestsTab.jsx +0 -482
- package/src/components/TurnstileWidget.jsx +0 -99
- package/src/components/UserInviteComponent.jsx +0 -76
- package/src/components/UserListComponent.jsx +0 -618
- package/src/components/charts/BarChart.jsx +0 -102
- package/src/components/charts/ChartFrame.jsx +0 -214
- package/src/components/charts/LineChart.jsx +0 -126
- package/src/components/charts/ScatterChart.jsx +0 -299
- package/src/components/charts/TimeSeriesChart.jsx +0 -300
- package/src/components/charts/chartDefaults.js +0 -644
- package/src/components/charts/chartLabels.js +0 -36
- package/src/components/charts/exportChart.js +0 -258
- package/src/components/charts/formatters.js +0 -39
- package/src/components/charts/palette.js +0 -33
- package/src/components/charts/yearTickInterval.js +0 -7
- package/src/i18n/authTranslations.ts +0 -2651
- package/src/i18n/chartsTranslations.ts +0 -91
- package/src/i18n/chatTranslations.ts +0 -55
- package/src/i18n/messagingTranslations.ts +0 -120
- package/src/i18n/notificationsTranslations.ts +0 -32
- package/src/i18n/onboardingTranslations.ts +0 -29
- package/src/i18n/sectionNavTranslations.ts +0 -20
- package/src/i18n/uiCoreTranslations.js +0 -29
- package/src/i18n/userMenuTranslations.ts +0 -5
- package/src/index.js +0 -158
- package/src/layout/PageLayout.jsx +0 -36
- package/src/layout/SectionNav.jsx +0 -320
- package/src/messaging/AttachmentList.jsx +0 -145
- package/src/messaging/Composer.jsx +0 -197
- package/src/messaging/ConversationLaunchers.jsx +0 -51
- package/src/messaging/ConversationList.jsx +0 -109
- package/src/messaging/DirectMessageLauncher.jsx +0 -112
- package/src/messaging/MessageBubble.jsx +0 -183
- package/src/messaging/MessagingProvider.jsx +0 -0
- package/src/messaging/MessagingScopeConfig.jsx +0 -24
- package/src/messaging/PollCard.jsx +0 -163
- package/src/messaging/ReactionBar.jsx +0 -43
- package/src/messaging/ReadTicks.jsx +0 -82
- package/src/messaging/Thread.jsx +0 -195
- package/src/messaging/api.js +0 -48
- package/src/messaging/composerImageCompression.js +0 -35
- package/src/messaging/linkifyText.jsx +0 -37
- package/src/notifications/NotificationBell.jsx +0 -84
- package/src/notifications/NotificationSettings.jsx +0 -330
- package/src/notifications/NotificationsProvider.jsx +0 -224
- package/src/notifications/PopupSurface.jsx +0 -105
- package/src/notifications/api.js +0 -55
- package/src/notifications/feedApi.js +0 -18
- package/src/notifications/realtime.jsx +0 -138
- package/src/notifications/serviceWorker/sw.js +0 -50
- package/src/onboarding/OnboardingProvider.jsx +0 -326
- package/src/onboarding/OnboardingWizard.jsx +0 -61
- package/src/onboarding/WizardDialogShell.jsx +0 -51
- package/src/onboarding/api.js +0 -13
- package/src/onboarding/stepSelection.js +0 -16
- package/src/onboarding/steps/BrowserPushStep.jsx +0 -121
- package/src/onboarding/steps/CompleteNameStep.jsx +0 -46
- package/src/onboarding/steps/CookieConsentStep.jsx +0 -133
- package/src/onboarding/steps/PwaInstallStep.jsx +0 -47
- package/src/pages/AccountPage.jsx +0 -394
- package/src/pages/LoginPage.jsx +0 -343
- package/src/pages/PasswordChangePage.jsx +0 -62
- package/src/pages/PasswordInvitePage.jsx +0 -177
- package/src/pages/PasswordResetRequestPage.jsx +0 -68
- package/src/pages/SignUpPage.jsx +0 -268
- package/src/pages/SignupConfirmPage.jsx +0 -155
- package/src/testing/checkKitIntegration.js +0 -233
- package/src/theme/createAppTheme.js +0 -423
- package/src/theme/fonts.js +0 -3
- package/src/theme/index.js +0 -21
- package/src/theme/kitSxRegistry.js +0 -285
- package/src/theme/themeCompleteness.js +0 -1045
- package/src/theme/tokens.js +0 -478
- package/src/utils/auth-errors.js +0 -76
- package/src/utils/authService.js +0 -223
- package/src/utils/resolveErrorText.js +0 -28
- package/src/utils/webauthn.js +0 -51
- package/tests/AccountPage.profileStatements.test.jsx +0 -162
- package/tests/AccountPage.test.jsx +0 -200
- package/tests/AuthContext.test.jsx +0 -129
- package/tests/BarChart.test.jsx +0 -112
- package/tests/BrowserPushStep.test.jsx +0 -110
- package/tests/ChartFrame.test.jsx +0 -336
- package/tests/ConversationList.test.jsx +0 -144
- package/tests/CookieConsentStep.test.jsx +0 -69
- package/tests/EmptyState.test.jsx +0 -62
- package/tests/LineChart.test.jsx +0 -80
- package/tests/MessagingProvider.test.jsx +0 -50
- package/tests/MobileBottomNav.test.jsx +0 -319
- package/tests/NotificationBell.test.jsx +0 -60
- package/tests/NotificationSettings.test.jsx +0 -276
- package/tests/NotificationsProvider.test.jsx +0 -240
- package/tests/OnboardingProvider.test.jsx +0 -294
- package/tests/OnboardingWizard.test.jsx +0 -143
- package/tests/PasswordChangeForm.test.jsx +0 -70
- package/tests/PasswordInvitePage.test.jsx +0 -142
- package/tests/PasswordSetForm.test.jsx +0 -70
- package/tests/PopupSurface.test.jsx +0 -142
- package/tests/ProfileComponent.refresh.test.jsx +0 -194
- package/tests/QrSignupManager.registrationContext.test.jsx +0 -106
- package/tests/QrSignupManagerInfoBox.test.jsx +0 -49
- package/tests/ScatterChart.test.jsx +0 -270
- package/tests/SectionNav.test.jsx +0 -363
- package/tests/SignUpPage.test.jsx +0 -208
- package/tests/SoftChip.test.jsx +0 -105
- package/tests/StatTile.test.jsx +0 -57
- package/tests/Thread.test.jsx +0 -151
- package/tests/TimeSeriesChart.test.jsx +0 -367
- package/tests/UserListComponent.test.jsx +0 -192
- package/tests/UserMenu.test.jsx +0 -171
- package/tests/apiClientLanguage.test.js +0 -33
- package/tests/apiClientPublicPaths.test.js +0 -178
- package/tests/authApiLogin.test.js +0 -42
- package/tests/authApiRegistration.test.js +0 -31
- package/tests/authErrorCodeRendering.test.jsx +0 -77
- package/tests/authErrors.test.js +0 -74
- package/tests/authTranslations.test.js +0 -74
- package/tests/chart-api-census.test.js +0 -366
- package/tests/chartAxisTickBand.test.jsx +0 -95
- package/tests/chartDefaults.test.js +0 -902
- package/tests/chartLabels.test.js +0 -50
- package/tests/chartsPalette.test.js +0 -99
- package/tests/chatApi.test.js +0 -48
- package/tests/chatDriverNames.test.jsx +0 -71
- package/tests/chatExports.test.js +0 -3
- package/tests/chatList.test.jsx +0 -84
- package/tests/chatPicker.test.jsx +0 -82
- package/tests/chatSocket.test.jsx +0 -26
- package/tests/chatThread.test.jsx +0 -116
- package/tests/chatTranslations.test.js +0 -47
- package/tests/chatWorkspace.test.jsx +0 -234
- package/tests/checkKitIntegration.test.jsx +0 -219
- package/tests/createAppTheme.test.js +0 -132
- package/tests/createAppThemeDark.test.js +0 -127
- package/tests/createAppThemeLightGuard.test.js +0 -40
- package/tests/createAppThemePageContrast.test.js +0 -108
- package/tests/createAppThemeTypography.test.js +0 -53
- package/tests/errorCallSiteGuard.test.js +0 -32
- package/tests/exportChart.test.js +0 -313
- package/tests/feedApi.test.js +0 -46
- package/tests/fixtures/light-theme-baseline.json +0 -2234
- package/tests/i18nAggregate.test.js +0 -120
- package/tests/i18nGermanVariant.test.js +0 -65
- package/tests/loginPageErrorResolution.test.jsx +0 -102
- package/tests/messagingApi.test.js +0 -32
- package/tests/messagingChunk6.test.jsx +0 -116
- package/tests/messagingCompactBubble.test.jsx +0 -64
- package/tests/messagingComposer.test.jsx +0 -136
- package/tests/messagingComposerChunk5.test.jsx +0 -113
- package/tests/messagingContractConformance.test.js +0 -69
- package/tests/messagingDirectMessageLauncher.test.jsx +0 -151
- package/tests/messagingExports.test.js +0 -21
- package/tests/messagingInteractions.test.jsx +0 -136
- package/tests/messagingLastMessagePreview.test.jsx +0 -93
- package/tests/messagingLinkify.test.jsx +0 -51
- package/tests/messagingMessageActions.test.jsx +0 -163
- package/tests/messagingMsg6.test.jsx +0 -105
- package/tests/messagingMsg6f.test.jsx +0 -155
- package/tests/messagingMsg6g.test.jsx +0 -166
- package/tests/messagingMsg6h.test.jsx +0 -136
- package/tests/messagingMsg6i.test.jsx +0 -129
- package/tests/messagingPollRendering.test.jsx +0 -142
- package/tests/messagingReactionMerge.test.jsx +0 -77
- package/tests/messagingReadTicksTooltip.test.jsx +0 -36
- package/tests/messagingThreadReceipts.test.jsx +0 -178
- package/tests/messagingThreadingQuoting.test.jsx +0 -87
- package/tests/messagingUnreadLifecycle.test.jsx +0 -78
- package/tests/notificationsApi.test.js +0 -41
- package/tests/notificationsExports.test.js +0 -34
- package/tests/onboardingDescriptors.test.js +0 -132
- package/tests/packageTreeShaking.test.js +0 -126
- package/tests/realtime.test.jsx +0 -219
- package/tests/resolveErrorText.test.js +0 -72
- package/tests/stepSelection.test.js +0 -53
- package/tests/themeCompleteness.test.js +0 -626
- package/tests/timeSeriesLegend.test.js +0 -99
- package/tests/userScreenTranslations.test.jsx +0 -218
- package/tsconfig.build.json +0 -18
- package/vite.config.mjs +0 -6
- package/work-orders/AUTH-1.md +0 -74
- package/work-orders/AUTH-2.md +0 -74
- package/work-orders/AUTH-4.md +0 -183
- package/work-orders/AUTH-5.md +0 -154
- package/work-orders/AUTH-7.md +0 -181
- package/work-orders/AUTH-8.md +0 -184
- package/work-orders/CHART-1.md +0 -285
- package/work-orders/CHART-2.md +0 -222
- package/work-orders/CHART-3.md +0 -163
- package/work-orders/CHART-4.md +0 -203
- package/work-orders/CHART-5.md +0 -226
- package/work-orders/CHART-6.md +0 -428
- package/work-orders/CHART-7.md +0 -175
- package/work-orders/DX-1.md +0 -169
- package/work-orders/DX-2.md +0 -188
- package/work-orders/DX-3.md +0 -195
- package/work-orders/I18N-1.md +0 -254
- package/work-orders/I18N-3.md +0 -207
- package/work-orders/MSG-3.md +0 -375
- package/work-orders/MSG-3b.md +0 -1002
- package/work-orders/MSG-3c.md +0 -378
- package/work-orders/MSG-3d.md +0 -268
- package/work-orders/MSG-3e.md +0 -164
- package/work-orders/MSG-3f.md +0 -391
- package/work-orders/MSG-6e.md +0 -308
- package/work-orders/MSG-6f.md +0 -214
- package/work-orders/MSG-6g.md +0 -244
- package/work-orders/MSG-6h.md +0 -238
- package/work-orders/MSG-6i.md +0 -271
- package/work-orders/MSG-6j.md +0 -117
- package/work-orders/NOTIF-12.md +0 -214
- package/work-orders/NOTIF-13.md +0 -142
- package/work-orders/NOTIF-14.md +0 -151
- package/work-orders/PRIM-1.md +0 -177
- package/work-orders/SHELL-1.md +0 -255
- package/work-orders/SHELL-2.md +0 -197
- package/work-orders/SHELL-3.md +0 -359
- package/work-orders/SHELL-4.md +0 -351
- package/work-orders/SHELL-5.md +0 -345
- package/work-orders/SHELL-6.md +0 -210
- package/work-orders/THEME-1.md +0 -587
- package/work-orders/THEME-10.md +0 -303
- package/work-orders/THEME-11.md +0 -208
- package/work-orders/THEME-2.md +0 -339
- package/work-orders/THEME-3.md +0 -210
- package/work-orders/THEME-4.md +0 -271
- package/work-orders/THEME-5.md +0 -341
- package/work-orders/THEME-6.md +0 -247
- package/work-orders/THEME-7.md +0 -82
- package/work-orders/THEME-8.md +0 -211
- package/work-orders/THEME-9.md +0 -194
- package/work-orders/UCM-AUTH-10.md +0 -490
- package/work-orders/UCM-AUTH-11.md +0 -185
- package/work-orders/UCM-AUTH-12.md +0 -98
- package/work-orders/UCM-AUTH-13.md +0 -47
- package/work-orders/UCM-AUTH-9.md +0 -207
- package/work-orders/UCM-CHART-10.md +0 -150
- package/work-orders/UCM-CHART-11.md +0 -132
- package/work-orders/UCM-CHART-12.md +0 -348
- package/work-orders/UCM-CHART-13.md +0 -122
- package/work-orders/UCM-CHART-14.md +0 -198
- package/work-orders/UCM-CHART-15.md +0 -187
- package/work-orders/UCM-CHART-16.md +0 -169
- package/work-orders/UCM-CHART-17.md +0 -195
- package/work-orders/UCM-CHART-18.md +0 -200
- package/work-orders/UCM-CHART-8.md +0 -147
- package/work-orders/UCM-CHART-9.md +0 -265
- package/work-orders/UCM-CHAT-1.md +0 -190
- package/work-orders/UCM-CHAT-2.md +0 -75
- package/work-orders/UCM-CI-1.md +0 -65
- package/work-orders/UCM-DEP-1.md +0 -63
- package/work-orders/UCM-I18N-4.md +0 -226
- package/work-orders/UCM-I18N-5.md +0 -211
- package/work-orders/UCM-MSG-20.md +0 -192
- package/work-orders/UCM-PRIM-2.md +0 -114
- package/work-orders/UCM-SHELL-7.md +0 -134
- package/work-orders/UCM-SHELL-8.md +0 -125
- package/work-orders/UCM-TEST-1.md +0 -304
- package/work-orders/UCM-THEME-13.md +0 -69
- package/work-orders/UCM-THEME-14.md +0 -312
- package/work-orders/UCM-THEME-15.md +0 -356
- package/work-orders/UCM-THEME-16.md +0 -80
- package/work-orders/UCM-THEME-17.md +0 -111
- package/work-orders/UCM-THEME-18.md +0 -184
- package/work-orders/assets/AUTH-4-user-list-card.html +0 -407
- package/work-orders/assets/PRIM-1-dashboard-primitives.html +0 -624
- package/work-orders/assets/SHELL-2-account-navigation.html +0 -1159
- package/work-orders/assets/THEME-1-baseline-reference-sheet.html +0 -1352
- package/work-orders/assets/UCM-CHAT-1-ai-chat.html +0 -447
- package/work-orders/assets/UCM-THEME-13-dark-prototype.html +0 -390
- package/work-orders/assets/UCM-THEME-17-type-scale.html +0 -391
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
# UCM-MSG-20 — Message composer collapses on narrow screens
|
|
2
|
-
|
|
3
|
-
# A. Envelope — authored by the Expertenchat
|
|
4
|
-
|
|
5
|
-
## Goal & expected outcome
|
|
6
|
-
|
|
7
|
-
- Goal: on a 375 px phone a person can type and send a message in every conversation type.
|
|
8
|
-
- Expected outcome:
|
|
9
|
-
- The text field keeps a usable width (at least most of the row) next to the action icons; the send
|
|
10
|
-
button is fully visible.
|
|
11
|
-
- URLs in messages are clickable links.
|
|
12
|
-
- The read marker next to the time explains itself (label or tooltip), or is not shown where it
|
|
13
|
-
carries no information.
|
|
14
|
-
|
|
15
|
-
## Context — measured 2026-09-29 in jg-ferien's local browser test (ucm 3.5.0 installed there)
|
|
16
|
-
|
|
17
|
-
- jg-ferien, event announcement conversation, 375 px: next to four icon buttons (attach, emoji, poll,
|
|
18
|
-
announce) the textarea is **16 px** wide (its field 44 px), "Senden" is clipped (44 px), the row
|
|
19
|
-
overflows (315 of 295 px).
|
|
20
|
-
- Component: `src/messaging/Composer.jsx` (row layout incl. the four icon buttons,
|
|
21
|
-
`allowAnnouncement` prop); `src/messaging/MessageBubble.jsx` shows a bare "0/0" next to the time.
|
|
22
|
-
- Long words and URLs wrap correctly inside the bubble; URLs are plain text.
|
|
23
|
-
- The dcm register is canonical for `MSG-*`; this is the ucm-side row.
|
|
24
|
-
|
|
25
|
-
## Scope + non-goals
|
|
26
|
-
|
|
27
|
-
- In scope: composer layout at narrow widths (e.g. actions collapse into one menu, or wrap to their
|
|
28
|
-
own row), linkified URLs, an explained or hidden read marker.
|
|
29
|
-
- Explicit non-goals / do-not-touch:
|
|
30
|
-
- No change to message sending, polls or announcements behaviour.
|
|
31
|
-
|
|
32
|
-
## Tier · gates
|
|
33
|
-
|
|
34
|
-
- **Tier 3** — shared-core component.
|
|
35
|
-
- Reviewer: `reviewer` (all lenses; linkify is new logic) · `ui_reviewer` · `sec_reviewer` (linkify
|
|
36
|
-
must not create script or `javascript:` links).
|
|
37
|
-
- **Done means released and jg-ferien's pin bumped.**
|
|
38
|
-
|
|
39
|
-
## Risks
|
|
40
|
-
|
|
41
|
-
- Linkify is an injection surface: only `http(s)` URLs, `rel="noopener noreferrer"`, no HTML from
|
|
42
|
-
message text.
|
|
43
|
-
|
|
44
|
-
## Required tests to WRITE (you write them and run YOUR OWN new ones; the orchestrator's run is the gate)
|
|
45
|
-
|
|
46
|
-
1. At 375 px width the textarea has at least a defined minimum width and the send button is not
|
|
47
|
-
clipped, with all four actions enabled.
|
|
48
|
-
2. `https://…` in a message renders as a link; `javascript:…` does not.
|
|
49
|
-
3. The read marker has an accessible label or is absent.
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
# B. Implementation map — filled by the Orchestrator — ADDRESSED TO THE IMPLEMENTER
|
|
54
|
-
|
|
55
|
-
## Context package — three independent fixes, same file family
|
|
56
|
-
|
|
57
|
-
### 1. Composer overflow at narrow widths — `src/messaging/Composer.jsx`
|
|
58
|
-
|
|
59
|
-
- The single overflowing row is at line 139:
|
|
60
|
-
`<Stack direction="row" spacing={1} alignItems="flex-end">` — it holds, in order: the hidden file
|
|
61
|
-
`<input>`, 4 `IconButton`s (attach `:141`, emoji `:142`, poll `:143`, announce `:144` conditional
|
|
62
|
-
on `canAnnounce`), the `TextField` (`:145`, `fullWidth multiline minRows={2}`), and the Send
|
|
63
|
-
`Button` (`:146`).
|
|
64
|
-
- **Fix: split into two stacked rows, not one collapsing menu** (the WO's "or wrap to their own
|
|
65
|
-
row" option — simplest, lowest-risk, no new interaction pattern to test):
|
|
66
|
-
1. First row: a `<Stack direction="row" spacing={1}>` containing only the icon buttons (attach,
|
|
67
|
-
emoji, poll, and the conditional announce button) — 3–4 icon buttons at ~40px each comfortably
|
|
68
|
-
fit 375px on their own.
|
|
69
|
-
2. Second row: `<Stack direction="row" spacing={1} alignItems="flex-end">` containing only the
|
|
70
|
-
`TextField` and the Send `Button`.
|
|
71
|
-
3. Give the `TextField` `sx={{ flex: 1, minWidth: 120 }}` (so it never collapses to near-zero
|
|
72
|
-
width when squeezed) and the Send `Button` `sx={{ flexShrink: 0 }}` (so it is never the thing
|
|
73
|
-
that gets clipped — it should shrink last, if at all).
|
|
74
|
-
4. Everything else in the file (state, handlers, the poll/announcement dialogs, the emoji
|
|
75
|
-
popover) is unchanged — this is a pure JSX layout restructure of one `Stack`.
|
|
76
|
-
- Test file: extend `tests/messagingComposer.test.jsx` (existing — read it first for the render
|
|
77
|
-
harness/mock-provider pattern already in use, follow it exactly rather than inventing a new one).
|
|
78
|
-
Add: render the `Composer`, resize the test's container is not meaningful in jsdom (no real
|
|
79
|
-
layout), so instead assert via computed style: the `TextField`'s wrapping element has
|
|
80
|
-
`minWidth: '120px'` (or your chosen value) and the Send button's element has `flexShrink: '0'` —
|
|
81
|
-
both readable via `window.getComputedStyle`, same technique as
|
|
82
|
-
`tests/StatTile.test.jsx`'s `accent` test. Also assert all four action buttons
|
|
83
|
-
(`MessagingComposer.ADD_ATTACHMENT`/`ADD_EMOJI`/`MessagingPoll.CREATE`/
|
|
84
|
-
`MessagingAnnouncement.CREATE` — pass `allowAnnouncement` + a non-`direct` `conversation` prop to
|
|
85
|
-
exercise the fourth) are present and not `disabled` (aside from the poll button's existing
|
|
86
|
-
`pollOpen || files.some(isImage)` guard, unrelated to this WO).
|
|
87
|
-
|
|
88
|
-
### 2. Linkify `http(s)` URLs — new file `src/messaging/linkifyText.jsx`
|
|
89
|
-
|
|
90
|
-
- No linkify library exists in this repo's dependencies today (checked — do not add one; a
|
|
91
|
-
dependency addition needs separate approval this WO does not have, and the requirement is narrow
|
|
92
|
-
enough not to need one).
|
|
93
|
-
- Export a pure function `linkifyText(text)` returning an array of strings and `<a>` React elements
|
|
94
|
-
(a `key`ed fragment-safe array, the same shape `.map()` output must have). URL matching: a strict
|
|
95
|
-
**`http://` or `https://` prefix only** — e.g.
|
|
96
|
-
`/(https?:\/\/[^\s<>"']+)/g` — so a `javascript:`, `data:`, or any other scheme can never match
|
|
97
|
-
the pattern in the first place (that is the actual security property the sec_reviewer will check
|
|
98
|
-
for — not an escaping step, an inclusion-list pattern that structurally cannot match anything
|
|
99
|
-
else). Split `text` on that pattern; for each URL match render
|
|
100
|
-
`<a href={url} target="_blank" rel="noopener noreferrer">{url}</a>`; non-matching segments pass
|
|
101
|
-
through as plain strings (React renders an array of strings/elements fine as children).
|
|
102
|
-
- Trim likely trailing punctuation that is prose, not part of the URL (a trailing `.`, `,`, `)`,
|
|
103
|
-
`!`, `?` immediately followed by a word boundary or end of string) so `"see https://x.com."` does
|
|
104
|
-
not link the sentence-ending period — check `tests/` for whether any existing kit code already
|
|
105
|
-
does this trimming (grep `messagingContractConformance` / `messagingApi` tests for a URL-trimming
|
|
106
|
-
precedent) before inventing your own rule; if none exists, a simple trailing-punctuation strip is
|
|
107
|
-
sufficient, name it in your `PROGRESS` narration.
|
|
108
|
-
- Wire it into `src/messaging/MessageBubble.jsx:149` — the `<Typography sx={{ whiteSpace:
|
|
109
|
-
'pre-wrap', overflowWrap: 'anywhere' }}>{...}</Typography>` that renders the message body: replace
|
|
110
|
-
the raw string child with `linkifyText(<same expression>)` for the non-deleted, non-empty case
|
|
111
|
-
(deleted messages keep rendering `t('MessagingThread.DELETED')` as plain text, unlinkified).
|
|
112
|
-
- Test file: new `tests/messagingLinkify.test.jsx` (or extend an existing `MessageBubble` test if
|
|
113
|
-
one already covers body rendering — check `tests/messagingChunk6.test.jsx` and
|
|
114
|
-
`tests/messagingCompactBubble.test.jsx` first).
|
|
115
|
-
1. A message body containing `https://example.com/path` renders an `<a>` with that exact `href`,
|
|
116
|
-
`target="_blank"`, and `rel="noopener noreferrer"`.
|
|
117
|
-
2. A message body containing the literal text `javascript:alert(1)` renders it as plain text —
|
|
118
|
-
assert `screen.queryByRole('link')` is `null` and the literal string is present as text.
|
|
119
|
-
3. A message body containing both a URL and surrounding prose renders the prose as plain text
|
|
120
|
-
and only the URL portion as a link (i.e. the split doesn't eat the surrounding words).
|
|
121
|
-
|
|
122
|
-
### 3. Read marker explains itself — `src/messaging/ReadTicks.jsx`
|
|
123
|
-
|
|
124
|
-
- Both existing branches already set `aria-label` (line 74's `<span role="img">`/`<ButtonBase>` for
|
|
125
|
-
the counted case, line 80's `<StatusIcon role="img">` for the DM case) — that covers screen
|
|
126
|
-
readers, but `aria-label` is invisible to a SIGHTED user looking at a bare "0/0", which is the
|
|
127
|
-
Envelope's actual complaint ("explains itself (**label or tooltip**)" — the current label is
|
|
128
|
-
ARIA-only, not a visible one).
|
|
129
|
-
- Fix, at the `hasCounts` branch (line 56 onward): wrap the returned ratio element in MUI's
|
|
130
|
-
`Tooltip` (already imported patterns exist elsewhere in the kit, e.g. `UserListComponent.jsx`'s
|
|
131
|
-
`<Tooltip title={...}>`) using the same `label` text as the `title`, so hovering explains it
|
|
132
|
-
visually too. Import `Tooltip` from `@mui/material` at the top of the file (currently only
|
|
133
|
-
imports `List, ListItem, Popover, Typography, ButtonBase`).
|
|
134
|
-
- Additionally: when `status.recipient_count === 0` (a message with literally nobody to read it —
|
|
135
|
-
"0/0" carries no information per the Envelope's alternative: "or is not shown where it carries no
|
|
136
|
-
information"), return `null` before rendering the ratio, same early-return style already used at
|
|
137
|
-
line 41 (`if (!status) return null;`) and line 50 (`if (!hasCounts && conversation?.kind !==
|
|
138
|
-
'direct') return null;`).
|
|
139
|
-
- Do NOT change the DM branch (line 78–80) — it already carries a real icon-shape + colour +
|
|
140
|
-
aria-label signal (not a bare number), out of this fix's actual complaint.
|
|
141
|
-
- Test file: extend `tests/messagingReadTicks*.test.*` if one exists (grep `tests/` for
|
|
142
|
-
`ReadTicks`); otherwise create `tests/messagingReadTicksTooltip.test.jsx`.
|
|
143
|
-
1. With `read_count: 2, recipient_count: 5`, assert a `title` attribute (MUI `Tooltip` renders
|
|
144
|
-
one on the wrapped element before hover, or use `@testing-library/user-event` to hover and
|
|
145
|
-
assert the tooltip text appears — follow whatever pattern this repo's other `Tooltip` tests
|
|
146
|
-
already use, grep for one) explaining the ratio is present.
|
|
147
|
-
2. With `recipient_count: 0`, assert the component renders nothing (e.g. `container.textContent`
|
|
148
|
-
is empty, or the specific test id/role used elsewhere for "renders null" assertions in this
|
|
149
|
-
test suite).
|
|
150
|
-
|
|
151
|
-
## Do-not-touch / invariants
|
|
152
|
-
|
|
153
|
-
- No change to message sending, polls, or announcements behaviour (Envelope non-goal) — items 1–3
|
|
154
|
-
above are the complete scope; do not touch `submit`/`submitPoll`/`submitAnnouncement`.
|
|
155
|
-
- `sec_reviewer` will specifically check the linkify regex cannot match a non-`http(s)` scheme —
|
|
156
|
-
keep the pattern an explicit `https?://` prefix, never a generic "looks like a URL" heuristic.
|
|
157
|
-
|
|
158
|
-
## Target repo working directory (absolute)
|
|
159
|
-
|
|
160
|
-
`C:\Users\biglmi\Documents\webapps\ui-core-micha` (branch `main`)
|
|
161
|
-
|
|
162
|
-
## Preamble — a REQUIRED block IN this file, not something appended at invocation
|
|
163
|
-
|
|
164
|
-
> The text above is the COMPLETE spec — the committed WO file's content, not a plan to refine; there
|
|
165
|
-
> is no separate plan file. Read the nearest `AGENTS.md`, the relevant `.codex/skills/<role>/SKILL.md`, and the
|
|
166
|
-
> app `MEMORY.md` ONLY for conventions. Stay in scope; do not touch auth/permissions/deps/schema/CI
|
|
167
|
-
> unless the spec says so; do not update `MEMORY.md`. **Do NOT edit `WORK_ORDERS.md` — the register
|
|
168
|
-
> row and the review verdicts are the orchestrator's alone.** **Your tools are for editing source
|
|
169
|
-
> and test files and for running the tests you wrote — nothing else.** Do NOT install dependencies,
|
|
170
|
-
> touch a lockfile, run a package manager, or tidy up stray files; if something in the repo state
|
|
171
|
-
> blocks you, stop and report it as `RESULT: BLOCKED <reason>` instead of fixing it. Do NOT
|
|
172
|
-
> `git add`/`commit`/`push` — leave every
|
|
173
|
-
> change uncommitted in the working tree for the orchestrator's independent review. WRITE the tests
|
|
174
|
-
> the `Required tests` section calls for AND **RUN the tests you just wrote** to confirm they execute
|
|
175
|
-
> and pass — that is the ONLY test run you do (NOT the app's affected/full suite, NOT any review).
|
|
176
|
-
> The orchestrator re-runs the authoritative set + does the independent review after you finish —
|
|
177
|
-
> those are the gate; your own run does not count as the gate.
|
|
178
|
-
>
|
|
179
|
-
> Narrate continuously: a `PLAN: <step1> | <step2> | …` line up front, then a single-line
|
|
180
|
-
> `PROGRESS: [<n>/<total>] <present-tense action>` before every relevant action (and `… done` on
|
|
181
|
-
> completion), spaced so no gap exceeds ~2 min, stdout unbuffered, plus exactly one final
|
|
182
|
-
> `RESULT: DONE|BLOCKED <reason>`.
|
|
183
|
-
|
|
184
|
-
---
|
|
185
|
-
|
|
186
|
-
# C. Orchestrator only — NOT ADDRESSED TO THE IMPLEMENTER
|
|
187
|
-
|
|
188
|
-
> **If you are the implementer reading this work order as your own specification: STOP at this line.
|
|
189
|
-
> Everything below describes what the Orchestrator does AFTER you finish. You do none of it — no
|
|
190
|
-
> reviewers, no verification run, no register edit, no commit.**
|
|
191
|
-
|
|
192
|
-
*(to be filled by the Orchestrator: execution directive; `reviewer` (all lenses) + `ui_reviewer` + `sec_reviewer`; release; jg-ferien pin bump and 375 px check in an event conversation; register rows here, in dcm (MSG canonical) and in jg (`JG-UX-14`).)*
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
# UCM-PRIM-2 — A shared empty-state primitive
|
|
2
|
-
|
|
3
|
-
# A. Envelope — authored by the Expertenchat
|
|
4
|
-
|
|
5
|
-
## Goal & expected outcome
|
|
6
|
-
|
|
7
|
-
- Goal: every "nothing here yet" in a consuming app looks and reads the same.
|
|
8
|
-
- Expected outcome: `EmptyState` in the kit — an optional icon, one line of text, an optional secondary
|
|
9
|
-
line and an optional action — built from theme tokens, accessible (text reachable by screen
|
|
10
|
-
readers, action a real button).
|
|
11
|
-
|
|
12
|
-
## Context — measured 2026-09-29 in jg-ferien's local browser test (ucm 3.5.0 installed there)
|
|
13
|
-
|
|
14
|
-
- jg-ferien's 15 event sections show "empty" in **seven** ways (plain text, card, blue info alert,
|
|
15
|
-
card with title, filled green card, alert inside a green card, nothing at all). No shared component
|
|
16
|
-
exists in jg or ucm; jg has only a song-search special case.
|
|
17
|
-
- **Operator decision 2026-09-29: generic goes to ucm.** jg adopts it in `JG-UX-9`.
|
|
18
|
-
- `PRIM-1` promoted `StatTile`/`SoftChip` along the same lines.
|
|
19
|
-
|
|
20
|
-
## Scope + non-goals
|
|
21
|
-
|
|
22
|
-
- In scope: the component, its export, a story or docs entry, tests.
|
|
23
|
-
- Explicit non-goals / do-not-touch: no adoption in consumers here; no change to `Alert` styling.
|
|
24
|
-
|
|
25
|
-
## Tier · gates
|
|
26
|
-
|
|
27
|
-
- **Tier 3** — new public export in shared-core (additive).
|
|
28
|
-
- Reviewer: `reviewer` (all lenses) · `ui_reviewer`.
|
|
29
|
-
- **Done means released; jg adoption is `JG-UX-9`.**
|
|
30
|
-
|
|
31
|
-
## Risks
|
|
32
|
-
|
|
33
|
-
- A too-flexible API reintroduces the seven variants; keep the props minimal.
|
|
34
|
-
|
|
35
|
-
## Required tests to WRITE (you write them and run YOUR OWN new ones; the orchestrator's run is the gate)
|
|
36
|
-
|
|
37
|
-
1. Renders text only; with secondary line; with action (button with accessible name).
|
|
38
|
-
2. Uses theme tokens (no literal colours; the kit's literal guard passes).
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
# B. Implementation map — filled by the Orchestrator — ADDRESSED TO THE IMPLEMENTER
|
|
43
|
-
|
|
44
|
-
## Context package
|
|
45
|
-
|
|
46
|
-
- New file `src/components/EmptyState.jsx`. Model it on the existing primitives
|
|
47
|
-
`src/components/StatTile.jsx` and `src/components/SoftChip.jsx` — a small functional component,
|
|
48
|
-
default export, built from `Box`/`Typography`/`Button` (MUI), theme tokens only (no literal
|
|
49
|
-
colours — `reportOffPaletteColours` in `src/theme/themeCompleteness.js` scans every source file
|
|
50
|
-
for off-palette hex/rgb/named colours and is part of the kit's literal guard the Required Tests
|
|
51
|
-
reference).
|
|
52
|
-
- Props (keep minimal per the Risk note — do not over-generalise):
|
|
53
|
-
`icon` (optional, a rendered MUI icon element, e.g. `<InboxOutlinedIcon />`), `title` (string,
|
|
54
|
-
required — the one line of text), `description` (optional secondary line), `action` (optional
|
|
55
|
-
`{ label, onClick }` — rendered as a real `<Button variant="outlined">`, not a link, so it is
|
|
56
|
-
reachable and operable like `StatTile`'s children slot), `sx` (optional passthrough, MUI
|
|
57
|
-
convention used throughout the kit, e.g. `Composer.jsx`'s `COMPOSER_EMOJI_BUTTON_SX` pattern).
|
|
58
|
-
- Export it from `src/index.js` next to the other components section (`--- 5. Components ---`,
|
|
59
|
-
after `SoftChip` at line 65): `export { default as EmptyState } from './components/EmptyState';`.
|
|
60
|
-
- Accessibility: `title` must be real text content (not just an `aria-label`), so a screen reader
|
|
61
|
-
reads it as part of document flow; if `icon` is passed, it must not need its own label (decorative
|
|
62
|
-
— rely on the adjacent text, matching how `StatTile` treats its icon-less design).
|
|
63
|
-
- Test file: `tests/EmptyState.test.jsx`, following `tests/StatTile.test.jsx`'s pattern exactly —
|
|
64
|
-
`@vitest-environment jsdom`, wrap in `<ThemeProvider theme={createAppTheme(...)}>`, `cleanup()`
|
|
65
|
-
in `afterEach`.
|
|
66
|
-
- Render text-only, with `description`, with `action` (assert the button has an accessible name
|
|
67
|
-
matching the label and that clicking it calls the passed `onClick`).
|
|
68
|
-
- The "theme tokens only" requirement: either call `reportOffPaletteColours([{ path: 'src/components/EmptyState.jsx', source: fs.readFileSync(...) }])` (see how `themeCompleteness.js` self-tests, or grep existing callers of `reportOffPaletteColours` in `tests/` for the established pattern) and assert `findings` is empty, or (simpler, sufficient) just don't use any hex/rgb/named-colour literal in the component at all and note in a comment that the guard is structural, not a runtime assertion in this test. Prefer calling `reportOffPaletteColours` directly if an existing test already does — grep `tests/*.test.*` for `reportOffPaletteColours` to find the precedent and match its call shape exactly.
|
|
69
|
-
|
|
70
|
-
## Do-not-touch / invariants
|
|
71
|
-
|
|
72
|
-
- Do not add `EmptyState` to `kitSxRegistry.js` unless you export a top-level `sx` object constant
|
|
73
|
-
from the component (only needed if the root element gets kit-owned baked-in styling beyond plain
|
|
74
|
-
`sx` passthrough — for this minimal component you likely don't need one; only add a registry entry
|
|
75
|
-
if you do add such a constant).
|
|
76
|
-
- No adoption anywhere in this repo's own consumers (`AccountPage`, etc.) — out of scope per the
|
|
77
|
-
Envelope's non-goals.
|
|
78
|
-
- Do not touch `Alert` styling anywhere.
|
|
79
|
-
|
|
80
|
-
## Target repo working directory (absolute)
|
|
81
|
-
|
|
82
|
-
`C:\Users\biglmi\Documents\webapps\ui-core-micha` (branch `main`)
|
|
83
|
-
|
|
84
|
-
## Preamble — a REQUIRED block IN this file, not something appended at invocation
|
|
85
|
-
|
|
86
|
-
> The text above is the COMPLETE spec — the committed WO file's content, not a plan to refine; there
|
|
87
|
-
> is no separate plan file. Read the nearest `AGENTS.md`, the relevant `.codex/skills/<role>/SKILL.md`, and the
|
|
88
|
-
> app `MEMORY.md` ONLY for conventions. Stay in scope; do not touch auth/permissions/deps/schema/CI
|
|
89
|
-
> unless the spec says so; do not update `MEMORY.md`. **Do NOT edit `WORK_ORDERS.md` — the register
|
|
90
|
-
> row and the review verdicts are the orchestrator's alone.** **Your tools are for editing source
|
|
91
|
-
> and test files and for running the tests you wrote — nothing else.** Do NOT install dependencies,
|
|
92
|
-
> touch a lockfile, run a package manager, or tidy up stray files; if something in the repo state
|
|
93
|
-
> blocks you, stop and report it as `RESULT: BLOCKED <reason>` instead of fixing it. Do NOT
|
|
94
|
-
> `git add`/`commit`/`push` — leave every
|
|
95
|
-
> change uncommitted in the working tree for the orchestrator's independent review. WRITE the tests
|
|
96
|
-
> the `Required tests` section calls for AND **RUN the tests you just wrote** to confirm they execute
|
|
97
|
-
> and pass — that is the ONLY test run you do (NOT the app's affected/full suite, NOT any review).
|
|
98
|
-
> The orchestrator re-runs the authoritative set + does the independent review after you finish —
|
|
99
|
-
> those are the gate; your own run does not count as the gate.
|
|
100
|
-
>
|
|
101
|
-
> Narrate continuously: a `PLAN: <step1> | <step2> | …` line up front, then a single-line
|
|
102
|
-
> `PROGRESS: [<n>/<total>] <present-tense action>` before every relevant action (and `… done` on
|
|
103
|
-
> completion), spaced so no gap exceeds ~2 min, stdout unbuffered, plus exactly one final
|
|
104
|
-
> `RESULT: DONE|BLOCKED <reason>`.
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
# C. Orchestrator only — NOT ADDRESSED TO THE IMPLEMENTER
|
|
109
|
-
|
|
110
|
-
> **If you are the implementer reading this work order as your own specification: STOP at this line.
|
|
111
|
-
> Everything below describes what the Orchestrator does AFTER you finish. You do none of it — no
|
|
112
|
-
> reviewers, no verification run, no register edit, no commit.**
|
|
113
|
-
|
|
114
|
-
*(to be filled by the Orchestrator: execution directive; `reviewer` (all lenses) + `ui_reviewer`; release; register row here and cross-reference in jg (`JG-UX-9`).)*
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
# UCM-SHELL-7 — User-menu avatar initials fail contrast
|
|
2
|
-
|
|
3
|
-
# A. Envelope — authored by the Expertenchat
|
|
4
|
-
|
|
5
|
-
## Goal & expected outcome
|
|
6
|
-
|
|
7
|
-
- Goal: the initials in the header avatar are readable.
|
|
8
|
-
- Expected outcome: initials reach at least 4.5:1 against the avatar background, using the consuming
|
|
9
|
-
app's theme tokens rather than MUI's default grey.
|
|
10
|
-
|
|
11
|
-
## Context — measured 2026-09-29 in jg-ferien's local browser test (ucm 3.5.0 installed there)
|
|
12
|
-
|
|
13
|
-
- `UserMenu` (imported in jg-ferien's `Header.jsx`) renders the MUI default avatar: white initials on
|
|
14
|
-
light grey, **1.83:1**, on every page of the app.
|
|
15
|
-
|
|
16
|
-
## Scope + non-goals
|
|
17
|
-
|
|
18
|
-
- In scope: avatar colours in `UserMenu` from theme tokens (e.g. primary surface with its
|
|
19
|
-
contrastText), with a fallback that passes when a consumer defines nothing.
|
|
20
|
-
- Explicit non-goals / do-not-touch: no layout change of the user menu.
|
|
21
|
-
|
|
22
|
-
## Tier · gates
|
|
23
|
-
|
|
24
|
-
- **Tier 3** — shared-core component (small).
|
|
25
|
-
- Reviewer: `ui_reviewer` (no new logic beyond the colour choice).
|
|
26
|
-
- **Done means released and jg-ferien's pin bumped.**
|
|
27
|
-
|
|
28
|
-
## Risks
|
|
29
|
-
|
|
30
|
-
- `createAppTheme` baseline: if the chosen token is optional, `assertThemeComplete` must require it or
|
|
31
|
-
the fallback must pass on its own.
|
|
32
|
-
|
|
33
|
-
## Required tests to WRITE (you write them and run YOUR OWN new ones; the orchestrator's run is the gate)
|
|
34
|
-
|
|
35
|
-
1. With jg-ferien's theme values the avatar pair is at least 4.5:1.
|
|
36
|
-
2. With a theme defining nothing extra the fallback pair is at least 4.5:1.
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
# B. Implementation map — filled by the Orchestrator — ADDRESSED TO THE IMPLEMENTER
|
|
41
|
-
|
|
42
|
-
## Context package
|
|
43
|
-
|
|
44
|
-
- File: `src/auth/UserMenu.jsx`. The avatar is rendered at line 60:
|
|
45
|
-
`<Avatar src={avatarSrc} sx={{ width: 32, height: 32, fontSize: '0.8rem' }}>` — no `bgcolor`/`color`
|
|
46
|
-
is set today, so it falls through to MUI's default grey Avatar styling (1.83:1, the measured
|
|
47
|
-
defect). Only this one JSX element changes; nothing else in the file.
|
|
48
|
-
- **Pitfall — do not just reach for `theme.palette.primary.contrastText`.** MUI's own
|
|
49
|
-
`createTheme`/`augmentColor` computes `contrastText` with `contrastThreshold: 3` (tuned for large
|
|
50
|
-
text/graphics, AA), not the 4.5:1 this WO requires for normal-size initials text. A consumer's
|
|
51
|
-
`primary.main` that legitimately passes MUI's own 3:1 threshold can still fail 4.5:1, and nothing
|
|
52
|
-
here re-validates it — so `contrastText` alone is not a fallback that "passes when a consumer
|
|
53
|
-
defines nothing", it is a fallback that USUALLY passes.
|
|
54
|
-
- **Design to implement instead** (uses the kit's own exported contrast helper, satisfies both
|
|
55
|
-
required tests meaningfully since both actually depend on the consumer's `primary.main`):
|
|
56
|
-
1. Import `{ calculateContrastRatio }` from `'../theme'` (already exported from
|
|
57
|
-
`src/theme/index.js` → re-exported at `src/index.js`) and `useTheme` from
|
|
58
|
-
`'@mui/material/styles'`.
|
|
59
|
-
2. Inside `UserMenu`, read `const theme = useTheme();`.
|
|
60
|
-
3. Background: `theme.palette.primary.main` (the "primary surface" the Envelope names).
|
|
61
|
-
4. Text colour: compute
|
|
62
|
-
`calculateContrastRatio(theme.palette.background.paper, theme.palette.primary.main) >= 4.5
|
|
63
|
-
? theme.palette.background.paper : theme.palette.ink.primary`.
|
|
64
|
-
This is not an arbitrary heuristic: for any background colour, the higher of
|
|
65
|
-
(contrast against white) and (contrast against near-black) is mathematically always ≥ √21 ≈
|
|
66
|
-
4.58 — i.e. picking whichever of the kit's own light (`background.paper`, white) or dark
|
|
67
|
-
(`ink.primary`, near-black) ink token has the higher measured contrast against
|
|
68
|
-
`primary.main` is GUARANTEED to clear 4.5:1 for every possible `primary.main`, including one
|
|
69
|
-
a consumer hasn't customised at all (the untouched baseline `primary.main` MUI ships). That is
|
|
70
|
-
what makes this "a fallback that passes when a consumer defines nothing" instead of "usually
|
|
71
|
-
passes".
|
|
72
|
-
5. Apply as `sx={{ ..., bgcolor: theme.palette.primary.main, color: <computed> }}` on the same
|
|
73
|
-
`Avatar` element — keep the existing `width`/`height`/`fontSize` untouched.
|
|
74
|
-
6. Do NOT introduce a new literal hex/rgb anywhere — `theme.palette.background.paper` and
|
|
75
|
-
`theme.palette.ink.primary` are both resolved theme values, and referencing them via
|
|
76
|
-
`theme.palette.<path>` (not writing their hex value as a string literal) keeps
|
|
77
|
-
`reportOffPaletteColours` clean, same as every other component in the kit.
|
|
78
|
-
- Test file: new `tests/UserMenu.test.jsx` (none exists yet — check with `Glob` before assuming;
|
|
79
|
-
if a `UserMenu` test already exists under a different name, extend it instead of creating a
|
|
80
|
-
duplicate). Pattern after `tests/StatTile.test.jsx`: `@vitest-environment jsdom`,
|
|
81
|
-
`createAppTheme(...)`, wrap `UserMenu` in the theme provider AND `AuthContext.Provider` (it reads
|
|
82
|
-
`user`/`logout` via `useContext(AuthContext)` at line 32 — a minimal `{ user: { username: 'ab' },
|
|
83
|
-
logout: () => {} }` value is enough to render the avatar).
|
|
84
|
-
1. With a theme built from jg-ferien's actual `primary.main` — `#367964` (measured directly from
|
|
85
|
-
`jg-ferien/frontend/src/theme.js:25`, a mid-brightness teal-green), assert
|
|
86
|
-
`calculateContrastRatio(<resolved avatar text colour>, <resolved avatar bg colour>) >= 4.5`
|
|
87
|
-
by reading the rendered `Avatar`'s computed `backgroundColor`/`color` via
|
|
88
|
-
`window.getComputedStyle` (see `tests/StatTile.test.jsx`'s `accent` border test for the
|
|
89
|
-
`getComputedStyle` pattern) and feeding both into `calculateContrastRatio` directly — do not
|
|
90
|
-
hardcode an expected hex, assert the ratio.
|
|
91
|
-
2. With `createAppTheme({})` (no consumer overrides — MUI's own baseline `primary.main`), assert
|
|
92
|
-
the same ≥4.5 computed-style contrast check.
|
|
93
|
-
|
|
94
|
-
## Do-not-touch / invariants
|
|
95
|
-
|
|
96
|
-
- No layout change to the user menu (Envelope non-goal) — only the two `sx` colour values change.
|
|
97
|
-
- Do not touch `assertThemeComplete`/`THEME_COMPLETENESS_SURFACES` — this fix reads existing
|
|
98
|
-
required surfaces (`primary.main`, `background.paper`, `ink.primary`), it does not need a new one.
|
|
99
|
-
|
|
100
|
-
## Target repo working directory (absolute)
|
|
101
|
-
|
|
102
|
-
`C:\Users\biglmi\Documents\webapps\ui-core-micha` (branch `main`)
|
|
103
|
-
|
|
104
|
-
## Preamble — a REQUIRED block IN this file, not something appended at invocation
|
|
105
|
-
|
|
106
|
-
> The text above is the COMPLETE spec — the committed WO file's content, not a plan to refine; there
|
|
107
|
-
> is no separate plan file. Read the nearest `AGENTS.md`, the relevant `.codex/skills/<role>/SKILL.md`, and the
|
|
108
|
-
> app `MEMORY.md` ONLY for conventions. Stay in scope; do not touch auth/permissions/deps/schema/CI
|
|
109
|
-
> unless the spec says so; do not update `MEMORY.md`. **Do NOT edit `WORK_ORDERS.md` — the register
|
|
110
|
-
> row and the review verdicts are the orchestrator's alone.** **Your tools are for editing source
|
|
111
|
-
> and test files and for running the tests you wrote — nothing else.** Do NOT install dependencies,
|
|
112
|
-
> touch a lockfile, run a package manager, or tidy up stray files; if something in the repo state
|
|
113
|
-
> blocks you, stop and report it as `RESULT: BLOCKED <reason>` instead of fixing it. Do NOT
|
|
114
|
-
> `git add`/`commit`/`push` — leave every
|
|
115
|
-
> change uncommitted in the working tree for the orchestrator's independent review. WRITE the tests
|
|
116
|
-
> the `Required tests` section calls for AND **RUN the tests you just wrote** to confirm they execute
|
|
117
|
-
> and pass — that is the ONLY test run you do (NOT the app's affected/full suite, NOT any review).
|
|
118
|
-
> The orchestrator re-runs the authoritative set + does the independent review after you finish —
|
|
119
|
-
> those are the gate; your own run does not count as the gate.
|
|
120
|
-
>
|
|
121
|
-
> Narrate continuously: a `PLAN: <step1> | <step2> | …` line up front, then a single-line
|
|
122
|
-
> `PROGRESS: [<n>/<total>] <present-tense action>` before every relevant action (and `… done` on
|
|
123
|
-
> completion), spaced so no gap exceeds ~2 min, stdout unbuffered, plus exactly one final
|
|
124
|
-
> `RESULT: DONE|BLOCKED <reason>`.
|
|
125
|
-
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
# C. Orchestrator only — NOT ADDRESSED TO THE IMPLEMENTER
|
|
129
|
-
|
|
130
|
-
> **If you are the implementer reading this work order as your own specification: STOP at this line.
|
|
131
|
-
> Everything below describes what the Orchestrator does AFTER you finish. You do none of it — no
|
|
132
|
-
> reviewers, no verification run, no register edit, no commit.**
|
|
133
|
-
|
|
134
|
-
*(to be filled by the Orchestrator: execution directive; `ui_reviewer`; release; jg-ferien pin bump; register rows here and in jg (`JG-DL-12`).)*
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
# UCM-SHELL-8: Valid SectionNav list items
|
|
2
|
-
|
|
3
|
-
# A. Envelope — operator-approved scope
|
|
4
|
-
|
|
5
|
-
## Goal and expected outcome
|
|
6
|
-
|
|
7
|
-
SectionNav navigation entries are genuine list items containing the existing buttons.
|
|
8
|
-
The account capture in innoservice reports three serious axe list violations at 1280 px;
|
|
9
|
-
these remain in ui-core-micha 3.13.0. The correction removes their structural cause.
|
|
10
|
-
|
|
11
|
-
## Scope and non-goals
|
|
12
|
-
|
|
13
|
-
- Correct grouped and optional overview entries in SectionNav's shared list renderer.
|
|
14
|
-
- Keep selection, aria-current, labels, remembered entry, keyboard operation, callbacks,
|
|
15
|
-
controlled/uncontrolled drawer behavior and appearance unchanged.
|
|
16
|
-
- Release the correction as patch 3.13.1 and update innoservice's exact package pin.
|
|
17
|
-
- No navigation redesign, new text, token delta, authentication, permissions, data contract,
|
|
18
|
-
other component, CI configuration or dependency changes beyond that release/pin.
|
|
19
|
-
- No new visual design or prototype: retain the existing presentation.
|
|
20
|
-
|
|
21
|
-
## Tier, risk and required tests to write
|
|
22
|
-
|
|
23
|
-
Tier 3: shared-core source with a rendered DOM correction used by consumers.
|
|
24
|
-
Risk: wrapper defaults could alter spacing or interrupt existing button interaction.
|
|
25
|
-
Write focused assertions that every grouped and overview list has li children containing
|
|
26
|
-
the existing button controls, on desktop and inside the mobile drawer. Preserve existing
|
|
27
|
-
selection and drawer tests; prove overview selection still passes null and closes the drawer.
|
|
28
|
-
|
|
29
|
-
# B. Implementation map — ADDRESSED TO THE IMPLEMENTER
|
|
30
|
-
|
|
31
|
-
## Target and ownership
|
|
32
|
-
|
|
33
|
-
Target: `C:/Users/Micha Bigler/Documents/webapps/ui-core-micha`.
|
|
34
|
-
Native bootstrap retains workspace-root cwd; use absolute paths and explicit workdirs.
|
|
35
|
-
You are not alone in the codebase; preserve other agents' changes. Own only:
|
|
36
|
-
- `src/layout/SectionNav.jsx`
|
|
37
|
-
- `tests/SectionNav.test.jsx`
|
|
38
|
-
|
|
39
|
-
## Context package
|
|
40
|
-
|
|
41
|
-
`src/layout/SectionNav.jsx:120`, SectionNavList, is shared by the desktop nav and mobile
|
|
42
|
-
drawer. The overview List currently directly contains ListItemButton; grouped Lists at
|
|
43
|
-
159 map item keys to direct ListItemButton children. MUI List defaults to ul and the
|
|
44
|
-
button defaults to div. Correct list containment while preserving the interactive button.
|
|
45
|
-
The overview handler passes null; grouped handlers pass item.key. Selected buttons carry
|
|
46
|
-
aria-current=page; remembered secondary text is shown only on its unselected entry.
|
|
47
|
-
Keep exported sx constants, drawer state handlers, prop defaults and group label IDs.
|
|
48
|
-
Use existing MUI primitives; prevent wrapper padding from changing the presentation.
|
|
49
|
-
|
|
50
|
-
`tests/SectionNav.test.jsx` renders the real named SectionNav with ThemeProvider and a
|
|
51
|
-
translation mock. Existing labels: Profile, Security, Users, Invite, Support, Notifications;
|
|
52
|
-
optional Overview; trigger accessible name matches /Section Profile/i; drawer title
|
|
53
|
-
Switch section. Existing tests cover selection, remembered text, controlled/uncontrolled
|
|
54
|
-
drawer, theme tokens and grid. Extend this file without mocking SectionNav or changing
|
|
55
|
-
existing tests to accept weaker behavior. Work from these two files, no broad exploration.
|
|
56
|
-
|
|
57
|
-
## Preamble and progress contract
|
|
58
|
-
|
|
59
|
-
> This committed WO is the COMPLETE spec. You are the initial implementer, not the reviewer.
|
|
60
|
-
> Edit only the owned source/test paths using explicit UTF-8 I/O. Preserve other changes.
|
|
61
|
-
> Do not edit dependencies, lockfiles, package/version/changelog/register/README/governance,
|
|
62
|
-
> settings, environment, other repos or memory. Never read .env or dump environment/settings.
|
|
63
|
-
> Your tools are for editing source/test files and running the tests you wrote, nothing else.
|
|
64
|
-
> No installs, package-manager commands, containers, git operations, self-review or subagents.
|
|
65
|
-
> Run your newly written SectionNav cases ONCE with the existing Node/Vitest runtime,
|
|
66
|
-
> maxWorkers=2, selected by test names; no affected/full suite, build or app startup.
|
|
67
|
-
> If blocked, report it rather than changing repo state. Leave all changes uncommitted.
|
|
68
|
-
> The orchestrator's tests and independent reviews are the acceptance gate, not your run.
|
|
69
|
-
> Start PLAN, emit PROGRESS before relevant actions with no silence over two minutes,
|
|
70
|
-
> then exactly one final RESULT: DONE or RESULT: BLOCKED.
|
|
71
|
-
|
|
72
|
-
# C. Orchestrator only — NOT ADDRESSED TO THE IMPLEMENTER
|
|
73
|
-
|
|
74
|
-
> IMPLEMENTER STOP HERE. You ARE the initial implementation instance. No steps below belong to you.
|
|
75
|
-
|
|
76
|
-
Gate #1: operator explicitly approved this exact structural correction, preserved behavior
|
|
77
|
-
and appearance, tests/review, release and innoservice pin bump on 2026-10-13.
|
|
78
|
-
No source approval was inferred from the earlier registration or clarification question.
|
|
79
|
-
|
|
80
|
-
Dispatch: fresh native plain worker, requested codex/gpt-6-luna, full WO inline; inherited
|
|
81
|
-
cwd is workspace root, target is the absolute core repo above. Record accepted identity
|
|
82
|
-
and only exposed effective metadata. Assigned ownership is not technical containment.
|
|
83
|
-
Parent owns repo state, package version, changelog, README/register and release/pin.
|
|
84
|
-
|
|
85
|
-
Independent envelope/regression/duplication/tests lenses plus UI run concurrently on the
|
|
86
|
-
same frozen diff via fresh read-only codex/gpt-6-luna processes. Security reviewer is not
|
|
87
|
-
required: no auth/security behavior changes. Parent also checks exposure/permission parity.
|
|
88
|
-
Parent runs SectionNav and both existing AccountPage test files, then build. Existing main
|
|
89
|
-
publish workflow supplies the full shared-core regression suite and publishing evidence;
|
|
90
|
-
normal reviewed main push, no manual publish dispatch. Confirm successful publication of
|
|
91
|
-
3.13.1 before innoservice exact pin and lockfile update. Keep all app capture/axe checks.
|
|
92
|
-
Fresh app capture at 375/1280 must verify navigation and absence of the three list violations.
|
|
93
|
-
Finalize register with named reviews, deduplicated dispositions and actual test/release proof.
|
|
94
|
-
|
|
95
|
-
Accepted native implementer: `/root/kit_sectionnav`, explicit requested gpt-6-luna, high
|
|
96
|
-
reasoning, fresh context. Effective native provider/model metadata was not exposed and
|
|
97
|
-
remains unverified. Only the two assigned files changed; no author git/review/repo-state
|
|
98
|
-
operations. Author's single permitted test run failed before collection with temporary-file
|
|
99
|
-
EPERM (zero tests). Parent runs the authoritative gate through the normal runtime path.
|
|
100
|
-
|
|
101
|
-
Core acceptance: five fresh concurrent CLI reviews (envelope, regression, duplication,
|
|
102
|
-
tests, UI), all exit 0, banners confirm codex/gpt-6-luna, provider openai, read-only.
|
|
103
|
-
Deduplicated disposition: 1 raised, 0 accepted, worst accepted none. Tests lens R1 proposed
|
|
104
|
-
proving the MUI implementation identity against a fabricated class-bearing stub. Rejected:
|
|
105
|
-
the structural assertion fails against the actual pre-change direct div children, existing
|
|
106
|
-
selection/theme/drawer tests retain their behavior checks, and the source still directly
|
|
107
|
-
imports and renders the real MUI ListItemButton. No behavior or identity abstraction is added.
|
|
108
|
-
Other lenses report no findings. Parent targeted pass confirms callbacks/permission filtering,
|
|
109
|
-
labels and selected/remembered state unchanged; wrappers use disablePadding.
|
|
110
|
-
Parent gate: 21 tests in SectionNav.test.jsx, AccountPage.test.jsx and
|
|
111
|
-
AccountPage.profileStatements.test.jsx passed with maxWorkers=2; TypeScript build exit 0.
|
|
112
|
-
Publish workflow's full suite is justified by shared-core consumer ripple. App pin and fresh
|
|
113
|
-
consumer capture remain pending after the reviewed core source/release lands.
|
|
114
|
-
|
|
115
|
-
Closing consumer proof: published3.13.1 verified by workflow38435441867,
|
|
116
|
-
744tests89files plus build and npm Trusted Publishing successful. Innoservice
|
|
117
|
-
exact pin3.13.1 is in sourcec527918, CI38444366349. Both source-matching account
|
|
118
|
-
captures375/1280 have no axe failures, no console/network failures, and all11
|
|
119
|
-
rubric items yes (22answers). Parent inspected both actual account images: same
|
|
120
|
-
profile/security/admin/help navigation and consent controls, readable at both
|
|
121
|
-
widths. Three previous kit list violations are gone. This completes the scoped
|
|
122
|
-
consumer gate; unrelated Organisation-policy axe failures in that app candidate
|
|
123
|
-
remain owned by INNO-FIX-11 and do not reopen the kit list correction.
|
|
124
|
-
Review remains the named five independent readonly Luna source passes above,
|
|
125
|
-
1deduplicated raised0accepted,worst accepted none; no source changes afterward.
|