@micha.bigler/ui-core-micha 3.14.3 → 4.0.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/CHANGELOG.md +31 -0
- package/README.md +7 -0
- package/dist/auth/UserMenu.js +1 -1
- package/dist/auth/apiClient.js +7 -6
- package/dist/chat/ChatList.js +1 -1
- package/dist/chat/ChatThread.js +2 -1
- package/dist/chat/ChatWorkspace.js +1 -1
- package/dist/chat/ModelPicker.js +2 -5
- package/dist/chat/kitSxRegistry.js +9 -0
- package/dist/chat/useChatSocket.js +1 -1
- package/dist/components/LoginForm.js +1 -1
- package/dist/components/SecurityComponent.js +1 -1
- package/dist/components/UserListComponent.js +2 -8
- package/dist/components/charts/ChartFrame.js +1 -1
- package/dist/components/charts/ScatterChart.js +2 -1
- 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/layout/SectionNav.js +1 -1
- package/dist/messaging/AttachmentList.js +2 -2
- package/dist/messaging/Composer.js +2 -1
- package/dist/messaging/ConversationLaunchers.js +1 -4
- package/dist/messaging/ConversationList.js +1 -1
- package/dist/messaging/DirectMessageLauncher.js +1 -1
- package/dist/messaging/MessagingProvider.js +0 -0
- package/dist/messaging/PollCard.js +7 -5
- package/dist/messaging/ReadTicks.js +2 -2
- package/dist/messaging/Thread.js +5 -3
- package/dist/notifications/NotificationBell.js +4 -7
- package/dist/notifications/NotificationSettings.js +1 -1
- package/dist/onboarding/OnboardingProvider.js +3 -6
- package/dist/pages/AccountPage.js +1 -2
- package/dist/pages/LoginPage.js +2 -3
- package/dist/pages/PasswordChangePage.js +2 -3
- package/dist/pages/PasswordInvitePage.js +2 -3
- package/dist/pages/PasswordResetRequestPage.js +2 -3
- package/dist/pages/SignUpPage.js +2 -3
- package/dist/pages/SignupConfirmPage.js +2 -3
- package/dist/theme/createAppTheme.js +5 -4
- package/dist/theme/kitSxEntry.js +11 -0
- package/dist/theme/kitSxRegistry.js +2 -15
- package/dist/theme/themeCompleteness.js +3 -12
- package/dist/utils/auth-errors.js +4 -3
- package/package.json +41 -16
- package/.github/workflows/publish.yml +0 -126
- package/DESIGN.md +0 -60
- package/WORK_ORDERS.md +0 -148
- 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-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,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// src/auth/pages/PasswordInvitePage.jsx
|
|
3
3
|
import React, { useState, useEffect } from 'react';
|
|
4
4
|
import { useNavigate, useParams, useLocation } from 'react-router-dom';
|
|
5
|
-
import { Helmet } from 'react-helmet';
|
|
6
5
|
import { Button, Typography } from '@mui/material';
|
|
7
6
|
import { useTranslation } from 'react-i18next';
|
|
8
7
|
import { NarrowPage } from '../layout/PageLayout';
|
|
@@ -116,5 +115,5 @@ export function PasswordInvitePage() {
|
|
|
116
115
|
if (!checked && !errorKey) {
|
|
117
116
|
return (_jsx(NarrowPage, { title: t('Auth.PAGE_CHECKING_LINK_TITLE'), children: _jsx(Typography, { children: t('Auth.PAGE_CHECKING_LINK_TEXT') }) }));
|
|
118
117
|
}
|
|
119
|
-
return (_jsxs(NarrowPage, { title: t(pageTitleKey), subtitle: t(pageSubtitleKey), children: [_jsx(
|
|
118
|
+
return (_jsxs(NarrowPage, { title: t(pageTitleKey), subtitle: t(pageSubtitleKey), children: [_jsx("title", { children: `${t('App.NAME')} – ${t(pageTitleKey)}` }), errorKey && (_jsx(Typography, { color: "error", gutterBottom: true, children: errorKey })), successKey && (_jsxs(_Fragment, { children: [_jsx(Typography, { color: "primary", gutterBottom: true, children: t(successKey) }), _jsx(Button, { variant: "contained", onClick: () => navigate(continueTarget), children: t('Auth.SIGNUP_GO_TO_LOGIN') })] })), submitErrorKey && !successKey && (_jsx(Typography, { color: "error", gutterBottom: true, children: submitErrorKey })), !successKey && !errorKey && (_jsx(PasswordSetForm, { onSubmit: handleSubmit, submitting: submitting }))] }));
|
|
120
119
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// src/auth/pages/PasswordResetRequestPage.jsx
|
|
3
3
|
import React, { useState } from 'react';
|
|
4
|
-
import { Helmet } from 'react-helmet';
|
|
5
4
|
import { Typography } from '@mui/material';
|
|
6
5
|
import { useTranslation } from 'react-i18next';
|
|
7
6
|
import { NarrowPage } from '../layout/PageLayout';
|
|
@@ -33,5 +32,5 @@ export function PasswordResetRequestPage() {
|
|
|
33
32
|
setSubmitting(false);
|
|
34
33
|
}
|
|
35
34
|
};
|
|
36
|
-
return (_jsxs(NarrowPage, { title: t('Auth.PAGE_RESET_PASSWORD_TITLE'), subtitle: t('Auth.PAGE_RESET_REQUEST_SUBTITLE'), children: [_jsx(
|
|
35
|
+
return (_jsxs(NarrowPage, { title: t('Auth.PAGE_RESET_PASSWORD_TITLE'), subtitle: t('Auth.PAGE_RESET_REQUEST_SUBTITLE'), children: [_jsx("title", { children: `${t('App.NAME')} – ${t('Auth.PAGE_RESET_PASSWORD_TITLE')}` }), successKey && (_jsx(Typography, { color: "primary", gutterBottom: true, children: t(successKey) })), errorKey && (_jsx(Typography, { color: "error", gutterBottom: true, children: errorKey })), _jsx(PasswordResetRequestForm, { onSubmit: handleSubmit, submitting: submitting })] }));
|
|
37
36
|
}
|
package/dist/pages/SignUpPage.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React, { useContext, useEffect, useMemo, useRef, useState, } from 'react';
|
|
3
3
|
import { useNavigate, useLocation } from 'react-router-dom';
|
|
4
4
|
import { Alert, Box, Button, Stack, TextField, Typography, } from '@mui/material';
|
|
5
|
-
import { Helmet } from 'react-helmet';
|
|
6
5
|
import { useTranslation } from 'react-i18next';
|
|
7
6
|
import { NarrowPage } from '../layout/PageLayout';
|
|
8
7
|
import { AuthContext } from '../auth/AuthContext';
|
|
@@ -118,7 +117,7 @@ export function SignUpPage() {
|
|
|
118
117
|
const handleGoToLogin = () => {
|
|
119
118
|
navigate('/login');
|
|
120
119
|
};
|
|
121
|
-
return (_jsxs(NarrowPage, { title: t('Auth.LOGIN_SIGNUP_BUTTON'), subtitle: pageSubtitle, children: [_jsx(
|
|
120
|
+
return (_jsxs(NarrowPage, { title: t('Auth.LOGIN_SIGNUP_BUTTON'), subtitle: pageSubtitle, children: [_jsx("title", { children: `${t('App.NAME')} – ${t('Auth.LOGIN_SIGNUP_BUTTON')}` }), signupModes.length === 0 ? (_jsx(Alert, { severity: "info", sx: SIGN_UP_PAGE_ALERT_SX, children: t('Auth.SELF_SIGNUP_DISABLED', 'Self sign-up is currently disabled.') })) : (_jsxs(_Fragment, { children: [successKey && (_jsx(Alert, { severity: "success", sx: SIGN_UP_PAGE_ALERT_SX, children: t(successKey, { email }) })), errorKey && (_jsx(Alert, { severity: "error", sx: SIGN_UP_PAGE_ALERT_SX, children: errorKey })), signupModes.length > 1 && (_jsx(Stack, { spacing: 1, sx: { mb: 2 }, children: _jsx(Stack, { spacing: 1, children: signupModes.map((entry) => (_jsx(Button, { variant: mode === entry ? 'contained' : 'outlined', onClick: () => setMode(entry), disabled: submitting, fullWidth: true, children: t(MODE_LABELS[entry] || entry, entry) }, entry))) }) })), _jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx(TextField, { label: t('Auth.EMAIL_LABEL'), type: "email", required: true, fullWidth: true, value: email, onChange: (e) => setEmail(e.target.value), disabled: submitting }), mode === 'self_signup_access_code' && (_jsx(TextField, { label: t('Auth.ACCESS_CODE_LABEL'), type: "text", required: true, fullWidth: true, value: accessCode, onChange: (e) => setAccessCode(e.target.value), disabled: submitting })), turnstileRequired && (_jsx(TurnstileWidget, { ref: turnstileWidgetRef, siteKey: authMethods.turnstile_site_key, onToken: setTurnstileToken })), _jsx(Button, { type: "submit", variant: "contained", disabled: submitting || (turnstileRequired && !turnstileToken), children: submitting
|
|
122
121
|
? t('Auth.SIGNUP_SUBMITTING')
|
|
123
122
|
: t('Auth.SIGNUP_SUBMIT') })] })] })), _jsx(Box, { sx: { mt: 3 }, children: _jsxs(Typography, { variant: "body2", children: [t('Auth.SIGNUP_ALREADY_HAVE_ACCOUNT'), ' ', _jsx(Button, { onClick: handleGoToLogin, variant: "text", size: "small", children: t('Auth.SIGNUP_GO_TO_LOGIN') })] }) })] }));
|
|
124
123
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// src/pages/SignupConfirmPage.jsx
|
|
3
3
|
//
|
|
4
4
|
// S13: Completes a pending registration. Reads the signed pending-token from
|
|
@@ -9,7 +9,6 @@ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-run
|
|
|
9
9
|
import React, { useMemo, useState } from 'react';
|
|
10
10
|
import { useLocation, useNavigate } from 'react-router-dom';
|
|
11
11
|
import { Alert, Box, Button, Stack, TextField, Typography, } from '@mui/material';
|
|
12
|
-
import { Helmet } from 'react-helmet';
|
|
13
12
|
import { useTranslation } from 'react-i18next';
|
|
14
13
|
import { NarrowPage } from '../layout/PageLayout';
|
|
15
14
|
import { confirmRegistration } from '../auth/authApi';
|
|
@@ -59,7 +58,7 @@ export function SignupConfirmPage() {
|
|
|
59
58
|
}
|
|
60
59
|
};
|
|
61
60
|
const tokenMissing = !tokenFromUrl;
|
|
62
|
-
return (_jsxs(NarrowPage, { title: t('Auth.SIGNUP_CONFIRM_TITLE', 'Confirm your registration'), subtitle: t('Auth.SIGNUP_CONFIRM_SUBTITLE', 'Choose a password to finish creating your account.'), children: [_jsx(
|
|
61
|
+
return (_jsxs(NarrowPage, { title: t('Auth.SIGNUP_CONFIRM_TITLE', 'Confirm your registration'), subtitle: t('Auth.SIGNUP_CONFIRM_SUBTITLE', 'Choose a password to finish creating your account.'), children: [_jsx("title", { children: `${t('App.NAME')} – ${t('Auth.SIGNUP_CONFIRM_TITLE', 'Confirm your registration')}` }), tokenMissing ? (_jsxs(_Fragment, { children: [_jsx(Alert, { severity: "error", sx: SIGNUP_CONFIRM_PAGE_ALERT_SX, children: t('Auth.PENDING_TOKEN_INVALID', 'This confirmation link is invalid or expired.') }), _jsxs(Stack, { direction: "row", spacing: 1, sx: { mt: 1 }, children: [_jsx(Button, { onClick: () => navigate('/signup'), variant: "contained", children: t('Auth.SIGNUP_REQUEST_NEW', 'Request a new invitation') }), _jsx(Button, { onClick: () => navigate('/login'), variant: "text", children: t('Auth.SIGNUP_GO_TO_LOGIN', 'Go to login') })] })] })) : (_jsxs(_Fragment, { children: [errorKey && (_jsx(Alert, { severity: "error", sx: SIGNUP_CONFIRM_PAGE_ALERT_SX, children: errorKey })), _jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx(TextField, { label: t('Auth.NEW_PASSWORD_LABEL', 'New password'), type: "password", required: true, fullWidth: true, value: password, onChange: (e) => setPassword(e.target.value), disabled: submitting, autoComplete: "new-password" }), _jsx(TextField, { label: t('Auth.PASSWORD_CONFIRM_LABEL', 'Confirm new password'), type: "password", required: true, fullWidth: true, value: confirmPassword, onChange: (e) => setConfirmPassword(e.target.value), disabled: submitting, autoComplete: "new-password" }), _jsx(Button, { type: "submit", variant: "contained", disabled: submitting, children: submitting
|
|
63
62
|
? t('Auth.SIGNUP_CONFIRM_SUBMITTING', 'Confirming…')
|
|
64
63
|
: t('Auth.SIGNUP_CONFIRM_SUBMIT', 'Confirm registration') })] }), _jsxs(Stack, { direction: "row", spacing: 1, sx: { mt: 3 }, children: [_jsx(Typography, { variant: "body2", children: t('Auth.SIGNUP_ALREADY_HAVE_ACCOUNT', 'Already have an account?') }), _jsx(Button, { onClick: () => navigate('/login'), variant: "text", size: "small", children: t('Auth.SIGNUP_GO_TO_LOGIN', 'Go to login') })] })] }))] }));
|
|
65
64
|
}
|
|
@@ -266,7 +266,8 @@ function createPaletteAwareComponents(palette, isDark) {
|
|
|
266
266
|
* objects are created, so runtime app/site overrides cannot leave stale values.
|
|
267
267
|
*/
|
|
268
268
|
export function createAppTheme(appConfig = {}) {
|
|
269
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q
|
|
269
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
270
|
+
var _r, _s;
|
|
270
271
|
if (!((_a = appConfig === null || appConfig === void 0 ? void 0 : appConfig.palette) === null || _a === void 0 ? void 0 : _a.primary)) {
|
|
271
272
|
throw new TypeError('createAppTheme: appConfig.palette.primary is required.');
|
|
272
273
|
}
|
|
@@ -327,16 +328,16 @@ export function createAppTheme(appConfig = {}) {
|
|
|
327
328
|
? finalPalette.dataSeries.categorical.map((colour) => (deriveLightenedPageColour(colour, [finalPalette.background.paper], 3)))
|
|
328
329
|
: finalPalette.dataSeries.categorical;
|
|
329
330
|
const computedPalette = Object.assign(Object.assign({}, derivedStatusEntries), { controlBorder: Object.assign(Object.assign(Object.assign({}, finalPalette.controlBorder), derivedControlBorderEntries), { focus: isDark
|
|
330
|
-
? ((
|
|
331
|
+
? ((_r = (_m = (_l = appConfig.palette) === null || _l === void 0 ? void 0 : _l.controlBorder) === null || _m === void 0 ? void 0 : _m.focus) !== null && _r !== void 0 ? _r : deriveLightenedColour(primaryMain, contrastSurfaces))
|
|
331
332
|
: deriveFocusColour(finalPalette.primary.main, contrastSurfaces) }), primary: Object.assign(Object.assign(Object.assign({}, finalPalette.primary), (isDark && primaryMain !== finalPalette.primary.main
|
|
332
333
|
? withMainShades(primaryMain, primaryContrastText)
|
|
333
334
|
: { main: primaryMain })), { contrastText: primaryContrastText }), dataSeries: { categorical: derivedSeries } });
|
|
334
335
|
const resolvedPalette = Object.assign(Object.assign({}, finalPalette), computedPalette);
|
|
335
|
-
const fontFamily = ((
|
|
336
|
+
const fontFamily = ((_o = appConfig.typography) === null || _o === void 0 ? void 0 : _o.fontFamily) || BASELINE_STATIC.typography.fontFamily;
|
|
336
337
|
// The h4 step below `sm` follows the app's own `sm` if it overrides the breakpoint,
|
|
337
338
|
// so the step always ends where theme.breakpoints.down('sm') ends.
|
|
338
339
|
const _t = BASELINE_STATIC.typography.h4, _u = breakpointDownQuery(BREAKPOINT_SM), h4Mobile = _t[_u], h4Base = __rest(_t, [typeof _u === "symbol" ? _u : _u + ""]);
|
|
339
|
-
const smValue = (_s = (
|
|
340
|
+
const smValue = (_s = (_q = (_p = appConfig.breakpoints) === null || _p === void 0 ? void 0 : _p.values) === null || _q === void 0 ? void 0 : _q.sm) !== null && _s !== void 0 ? _s : BREAKPOINT_SM;
|
|
340
341
|
return createTheme(Object.assign(Object.assign({}, BASELINE_STATIC), { typography: Object.assign(Object.assign({}, BASELINE_STATIC.typography), { fontFamily, h4: Object.assign(Object.assign({}, h4Base), { [breakpointDownQuery(smValue)]: h4Mobile }) }), fontLoading: Object.assign(Object.assign({}, BASELINE_STATIC.fontLoading), { weights: [...BASELINE_STATIC.fontLoading.weights] }), shadow: isDark ? Object.assign(Object.assign({}, BASELINE_STATIC.shadow), { overlay: DARK_OVERLAY_SHADOW }) : BASELINE_STATIC.shadow, palette: resolvedPalette, themeCompleteness: {
|
|
341
342
|
baseline: true,
|
|
342
343
|
exemptions: (isDark
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One registry entry: a kit-owned sx object paired with the baseline-styled MUI key it targets.
|
|
3
|
+
* Lives apart from kitSxRegistry so a sub-path registry can build entries without importing every kit component.
|
|
4
|
+
*/
|
|
5
|
+
export const createKitSxEntry = (component, muiComponent, sx, exportName, slots) => ({
|
|
6
|
+
component,
|
|
7
|
+
muiComponent,
|
|
8
|
+
sx,
|
|
9
|
+
slots,
|
|
10
|
+
exportName,
|
|
11
|
+
});
|
|
@@ -16,7 +16,6 @@ import { SOFT_CHIP_CAVEAT_SX, SOFT_CHIP_ROOT_SX, SOFT_CHIP_STATUS_SX, } from '..
|
|
|
16
16
|
import { SUPPORT_RECOVERY_AGENT_BUTTON_SX, SUPPORT_RECOVERY_AGENT_PAPER_SX, SUPPORT_RECOVERY_ALERT_SX, } from '../components/SupportRecoveryRequestsTab';
|
|
17
17
|
import { USER_INVITE_ACTION_SX, USER_INVITE_ALERT_SX } from '../components/UserInviteComponent';
|
|
18
18
|
import { USER_LIST_ACTION_SX, USER_LIST_ALERT_SX, USER_LIST_BODY_CELL_SX, USER_LIST_EMPTY_CELL_SX, USER_LIST_HEADER_CELL_SX, } from '../components/UserListComponent';
|
|
19
|
-
import { CHART_FRAME_ALERT_SX, CHART_FRAME_ROOT_SX } from '../components/charts/ChartFrame';
|
|
20
19
|
import { PAGE_LAYOUT_CONTAINER_SX } from '../layout/PageLayout';
|
|
21
20
|
import { SECTION_NAV_DRAWER_PAPER_SX, SECTION_NAV_GROUP_PAPER_SX, } from '../layout/SectionNav';
|
|
22
21
|
import { ATTACHMENT_LIST_ALERT_SX, ATTACHMENT_LIST_LIGHTBOX_ACTION_SX, } from '../messaging/AttachmentList';
|
|
@@ -33,8 +32,7 @@ import { LOGIN_PAGE_ALERT_SX } from '../pages/LoginPage';
|
|
|
33
32
|
import { SIGN_UP_PAGE_ALERT_SX } from '../pages/SignUpPage';
|
|
34
33
|
import { SIGNUP_CONFIRM_PAGE_ALERT_SX } from '../pages/SignupConfirmPage';
|
|
35
34
|
import { REAUTH_MODAL_ALERT_SX, REAUTH_MODAL_TEXT_FIELD_SX } from '../auth/ReauthModal';
|
|
36
|
-
import {
|
|
37
|
-
import { CHAT_THREAD_NOTICE_SX, CHAT_THREAD_TOOL_CHIP_SX } from '../chat/ChatThread';
|
|
35
|
+
import { createKitSxEntry } from './kitSxEntry';
|
|
38
36
|
const SX_EXPORTS = {
|
|
39
37
|
ACCESS_CODE_ACTION_SX,
|
|
40
38
|
ACCESS_CODE_ALERT_SX,
|
|
@@ -50,8 +48,6 @@ const SX_EXPORTS = {
|
|
|
50
48
|
BROWSER_PUSH_FORM_CONTROL_LABEL_SX,
|
|
51
49
|
BULK_INVITE_ACTION_SX,
|
|
52
50
|
BULK_INVITE_ALERT_SX,
|
|
53
|
-
CHART_FRAME_ALERT_SX,
|
|
54
|
-
CHART_FRAME_ROOT_SX,
|
|
55
51
|
COMPOSER_EMOJI_BUTTON_SX,
|
|
56
52
|
COMPOSER_MESSAGE_FIELD_SX,
|
|
57
53
|
COMPOSER_SEND_BUTTON_SX,
|
|
@@ -105,10 +101,6 @@ const SX_EXPORTS = {
|
|
|
105
101
|
SUPPORT_RECOVERY_AGENT_PAPER_SX,
|
|
106
102
|
SUPPORT_RECOVERY_ALERT_SX,
|
|
107
103
|
THREAD_DAY_SEPARATOR_SX,
|
|
108
|
-
CHAT_LIST_ARCHIVED_ACTION_SX,
|
|
109
|
-
CHAT_LIST_ROW_ACTION_SX,
|
|
110
|
-
CHAT_THREAD_NOTICE_SX,
|
|
111
|
-
CHAT_THREAD_TOOL_CHIP_SX,
|
|
112
104
|
USER_INVITE_ACTION_SX,
|
|
113
105
|
USER_INVITE_ALERT_SX,
|
|
114
106
|
USER_LIST_ACTION_SX,
|
|
@@ -125,6 +117,7 @@ const entry = (component, muiComponent, sx, slots) => ({
|
|
|
125
117
|
slots,
|
|
126
118
|
exportName: SX_EXPORT_NAMES.get(sx),
|
|
127
119
|
});
|
|
120
|
+
export { createKitSxEntry };
|
|
128
121
|
/**
|
|
129
122
|
* Kit-owned, top-level sx objects paired with the baseline-styled MUI key they
|
|
130
123
|
* target. Conditional and nested sx remain a documented lower bound in the
|
|
@@ -176,8 +169,6 @@ export const KIT_COMPONENT_SX_REGISTRY = [
|
|
|
176
169
|
entry('UserListComponent.headerCell', 'MuiTableCell', USER_LIST_HEADER_CELL_SX),
|
|
177
170
|
entry('UserListComponent.emptyCell', 'MuiTableCell', USER_LIST_EMPTY_CELL_SX),
|
|
178
171
|
entry('UserListComponent.bodyCell', 'MuiTableCell', USER_LIST_BODY_CELL_SX),
|
|
179
|
-
entry('ChartFrame.root', 'MuiPaper', CHART_FRAME_ROOT_SX),
|
|
180
|
-
entry('ChartFrame.alert', 'MuiAlert', CHART_FRAME_ALERT_SX),
|
|
181
172
|
entry('PageLayout.container', 'MuiContainer', PAGE_LAYOUT_CONTAINER_SX),
|
|
182
173
|
entry('SectionNav.drawerPaper', 'MuiDrawer', SECTION_NAV_DRAWER_PAPER_SX, ['paper']),
|
|
183
174
|
entry('SectionNav.drawerPaperBase', 'MuiPaper', SECTION_NAV_DRAWER_PAPER_SX),
|
|
@@ -208,8 +199,4 @@ export const KIT_COMPONENT_SX_REGISTRY = [
|
|
|
208
199
|
entry('SignupConfirmPage.alert', 'MuiAlert', SIGNUP_CONFIRM_PAGE_ALERT_SX),
|
|
209
200
|
entry('ReauthModal.alert', 'MuiAlert', REAUTH_MODAL_ALERT_SX),
|
|
210
201
|
entry('ReauthModal.field', 'MuiTextField', REAUTH_MODAL_TEXT_FIELD_SX),
|
|
211
|
-
entry('ChatList.rowAction', 'MuiIconButton', CHAT_LIST_ROW_ACTION_SX),
|
|
212
|
-
entry('ChatList.archivedAction', 'MuiButton', CHAT_LIST_ARCHIVED_ACTION_SX),
|
|
213
|
-
entry('ChatThread.toolChip', 'MuiChip', CHAT_THREAD_TOOL_CHIP_SX),
|
|
214
|
-
entry('ChatThread.notice', 'MuiAlert', CHAT_THREAD_NOTICE_SX),
|
|
215
202
|
];
|
|
@@ -22,10 +22,7 @@ const TYPOGRAPHY_SURFACES = TYPOGRAPHY_VARIANTS.flatMap((variant) => ['fontSize'
|
|
|
22
22
|
const componentPath = (component, path) => pathSurface(`components.${component}.${path}`);
|
|
23
23
|
const componentKeyLeaf = (component, path, key, leaf) => keyedSurface(`components.${component}.${path}.${key}.${leaf}`, (theme) => { var _a, _b; return (_b = (_a = getPath(theme, `components.${component}.${path}`)) === null || _a === void 0 ? void 0 : _a[key]) === null || _b === void 0 ? void 0 : _b[leaf]; });
|
|
24
24
|
const COMPONENT_SURFACES = [
|
|
25
|
-
keyedSurface('components.MuiCssBaseline.reduced-motion.transitionDuration', (theme) => {
|
|
26
|
-
var _a, _b, _c, _d, _e;
|
|
27
|
-
return (_e = (_d = (_c = (_b = (_a = theme.components) === null || _a === void 0 ? void 0 : _a.MuiCssBaseline) === null || _b === void 0 ? void 0 : _b.styleOverrides) === null || _c === void 0 ? void 0 : _c['@media (prefers-reduced-motion: reduce)']) === null || _d === void 0 ? void 0 : _d['*, *::before, *::after']) === null || _e === void 0 ? void 0 : _e.transitionDuration;
|
|
28
|
-
}),
|
|
25
|
+
keyedSurface('components.MuiCssBaseline.reduced-motion.transitionDuration', (theme) => { var _a, _b, _c, _d, _e; return (_e = (_d = (_c = (_b = (_a = theme.components) === null || _a === void 0 ? void 0 : _a.MuiCssBaseline) === null || _b === void 0 ? void 0 : _b.styleOverrides) === null || _c === void 0 ? void 0 : _c['@media (prefers-reduced-motion: reduce)']) === null || _d === void 0 ? void 0 : _d['*, *::before, *::after']) === null || _e === void 0 ? void 0 : _e.transitionDuration; }),
|
|
29
26
|
componentPath('MuiButton', 'defaultProps.disableElevation'),
|
|
30
27
|
componentPath('MuiButton', 'styleOverrides.root.minHeight'),
|
|
31
28
|
componentPath('MuiButton', 'styleOverrides.root.borderRadius'),
|
|
@@ -69,10 +66,7 @@ const COMPONENT_SURFACES = [
|
|
|
69
66
|
componentPath('MuiChip', 'styleOverrides.root.height'),
|
|
70
67
|
componentPath('MuiChip', 'styleOverrides.root.borderRadius'),
|
|
71
68
|
componentPath('MuiChip', 'styleOverrides.root.fontSize'),
|
|
72
|
-
keyedSurface('components.MuiChip.styleOverrides.root.coarse-hit-area.inset', (theme) => {
|
|
73
|
-
var _a, _b, _c, _d, _e, _f;
|
|
74
|
-
return (_f = (_e = (_d = (_c = (_b = (_a = theme.components) === null || _a === void 0 ? void 0 : _a.MuiChip) === null || _b === void 0 ? void 0 : _b.styleOverrides) === null || _c === void 0 ? void 0 : _c.root) === null || _d === void 0 ? void 0 : _d['@media (any-pointer: coarse)']) === null || _e === void 0 ? void 0 : _e['&::after']) === null || _f === void 0 ? void 0 : _f.inset;
|
|
75
|
-
}),
|
|
69
|
+
keyedSurface('components.MuiChip.styleOverrides.root.coarse-hit-area.inset', (theme) => { var _a, _b, _c, _d, _e, _f; return (_f = (_e = (_d = (_c = (_b = (_a = theme.components) === null || _a === void 0 ? void 0 : _a.MuiChip) === null || _b === void 0 ? void 0 : _b.styleOverrides) === null || _c === void 0 ? void 0 : _c.root) === null || _d === void 0 ? void 0 : _d['@media (any-pointer: coarse)']) === null || _e === void 0 ? void 0 : _e['&::after']) === null || _f === void 0 ? void 0 : _f.inset; }),
|
|
76
70
|
componentPath('MuiBottomNavigation', 'styleOverrides.root.boxShadow'),
|
|
77
71
|
componentPath('MuiBottomNavigation', 'styleOverrides.root.backgroundColor'),
|
|
78
72
|
componentPath('MuiBottomNavigationAction', 'styleOverrides.root.padding'),
|
|
@@ -95,10 +89,7 @@ const COMPONENT_SURFACES = [
|
|
|
95
89
|
componentKeyLeaf('MuiTextField', 'styleOverrides.root', '@media (any-pointer: coarse)', 'minWidth'),
|
|
96
90
|
componentPath('MuiOutlinedInput', 'styleOverrides.root.minHeight'),
|
|
97
91
|
componentPath('MuiOutlinedInput', 'styleOverrides.root.borderRadius'),
|
|
98
|
-
keyedSurface('components.MuiOutlinedInput.variants.non-multiline-height', (theme) => {
|
|
99
|
-
var _a, _b, _c, _d, _e;
|
|
100
|
-
return (_e = (_d = (_c = (_b = (_a = theme.components) === null || _a === void 0 ? void 0 : _a.MuiOutlinedInput) === null || _b === void 0 ? void 0 : _b.variants) === null || _c === void 0 ? void 0 : _c.find(({ props }) => (props === null || props === void 0 ? void 0 : props.multiline) === false)) === null || _d === void 0 ? void 0 : _d.style) === null || _e === void 0 ? void 0 : _e.height;
|
|
101
|
-
}),
|
|
92
|
+
keyedSurface('components.MuiOutlinedInput.variants.non-multiline-height', (theme) => { var _a, _b, _c, _d, _e; return (_e = (_d = (_c = (_b = (_a = theme.components) === null || _a === void 0 ? void 0 : _a.MuiOutlinedInput) === null || _b === void 0 ? void 0 : _b.variants) === null || _c === void 0 ? void 0 : _c.find(({ props }) => (props === null || props === void 0 ? void 0 : props.multiline) === false)) === null || _d === void 0 ? void 0 : _d.style) === null || _e === void 0 ? void 0 : _e.height; }),
|
|
102
93
|
componentKeyLeaf('MuiOutlinedInput', 'styleOverrides.root', '@media (any-pointer: coarse)', 'minHeight'),
|
|
103
94
|
componentKeyLeaf('MuiOutlinedInput', 'styleOverrides.root', '@media (any-pointer: coarse)', 'minWidth'),
|
|
104
95
|
componentKeyLeaf('MuiOutlinedInput', 'styleOverrides.root', '& .MuiOutlinedInput-notchedOutline', 'borderColor'),
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// src/utils/auth-errors.js
|
|
2
2
|
export function extractErrorInfo(error) {
|
|
3
|
-
var _a, _b
|
|
4
|
-
|
|
5
|
-
const
|
|
3
|
+
var _a, _b;
|
|
4
|
+
var _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
5
|
+
const status = (_c = (_a = error.response) === null || _a === void 0 ? void 0 : _a.status) !== null && _c !== void 0 ? _c : null;
|
|
6
|
+
const data = (_d = (_b = error.response) === null || _b === void 0 ? void 0 : _b.data) !== null && _d !== void 0 ? _d : null;
|
|
6
7
|
if (!data) {
|
|
7
8
|
return {
|
|
8
9
|
status,
|
package/package.json
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@micha.bigler/ui-core-micha",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./dist/index.js",
|
|
8
|
+
"./charts": "./dist/entries/charts.js",
|
|
9
|
+
"./chat": "./dist/entries/chat.js",
|
|
10
|
+
"./markdown": "./dist/entries/markdown.js",
|
|
11
|
+
"./package.json": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md",
|
|
16
|
+
"CHANGELOG.md"
|
|
17
|
+
],
|
|
6
18
|
"sideEffects": [
|
|
7
19
|
"./src/index.js",
|
|
8
20
|
"./dist/index.js",
|
|
@@ -21,23 +33,34 @@
|
|
|
21
33
|
},
|
|
22
34
|
"private": false,
|
|
23
35
|
"dependencies": {
|
|
24
|
-
"@fontsource/dm-sans": "^5.
|
|
25
|
-
"react-markdown": "^10.1.0",
|
|
26
|
-
"remark-gfm": "^4.0.1"
|
|
36
|
+
"@fontsource/dm-sans": "^5.3.0"
|
|
27
37
|
},
|
|
28
38
|
"peerDependencies": {
|
|
29
39
|
"@emotion/react": "^11.14.0",
|
|
30
40
|
"@emotion/styled": "^11.14.1",
|
|
41
|
+
"@mui/icons-material": "^7.3.11",
|
|
31
42
|
"@mui/material": "^7.3.11",
|
|
32
43
|
"@mui/x-charts": "^8.0.0",
|
|
33
44
|
"axios": "^1.16.1",
|
|
34
|
-
"i18next": "
|
|
45
|
+
"i18next": ">= 26.2.0",
|
|
35
46
|
"qrcode.react": "^4.2.0",
|
|
36
47
|
"react": "^19.2.6",
|
|
37
48
|
"react-dom": "^19.2.6",
|
|
38
|
-
"react-helmet": "^6.1.0",
|
|
39
49
|
"react-i18next": "^16.3.5 || ^17.0.0",
|
|
40
|
-
"react-
|
|
50
|
+
"react-markdown": "^10.1.0",
|
|
51
|
+
"react-router-dom": "^7.15.1",
|
|
52
|
+
"remark-gfm": "^4.0.1"
|
|
53
|
+
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"@mui/x-charts": {
|
|
56
|
+
"optional": true
|
|
57
|
+
},
|
|
58
|
+
"react-markdown": {
|
|
59
|
+
"optional": true
|
|
60
|
+
},
|
|
61
|
+
"remark-gfm": {
|
|
62
|
+
"optional": true
|
|
63
|
+
}
|
|
41
64
|
},
|
|
42
65
|
"scripts": {
|
|
43
66
|
"build": "tsc -p tsconfig.build.json",
|
|
@@ -46,14 +69,16 @@
|
|
|
46
69
|
},
|
|
47
70
|
"devDependencies": {
|
|
48
71
|
"@mui/icons-material": "^7.3.11",
|
|
49
|
-
"@mui/x-charts": "^8.
|
|
50
|
-
"@testing-library/react": "^16.3.
|
|
51
|
-
"@vitejs/plugin-react": "^6.
|
|
52
|
-
"i18next": "^26.2
|
|
53
|
-
"jsdom": "^
|
|
54
|
-
"react-i18next": "^17.0.
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
72
|
+
"@mui/x-charts": "^8.29.3",
|
|
73
|
+
"@testing-library/react": "^16.3.3",
|
|
74
|
+
"@vitejs/plugin-react": "^6.1.2",
|
|
75
|
+
"i18next": "^26.4.2",
|
|
76
|
+
"jsdom": "^30.1.2",
|
|
77
|
+
"react-i18next": "^17.0.16",
|
|
78
|
+
"react-markdown": "^10.1.0",
|
|
79
|
+
"remark-gfm": "^4.0.1",
|
|
80
|
+
"typescript": "^7.0.2",
|
|
81
|
+
"vite": "^8.3.4",
|
|
82
|
+
"vitest": "^5.0.3"
|
|
58
83
|
}
|
|
59
84
|
}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
name: Publish ui-core-micha to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
paths:
|
|
8
|
-
- "package.json"
|
|
9
|
-
- "pnpm-lock.yaml"
|
|
10
|
-
- "src/**"
|
|
11
|
-
- "tsconfig.build.json"
|
|
12
|
-
workflow_dispatch:
|
|
13
|
-
|
|
14
|
-
jobs:
|
|
15
|
-
publish:
|
|
16
|
-
runs-on: ubuntu-latest
|
|
17
|
-
permissions:
|
|
18
|
-
id-token: write
|
|
19
|
-
contents: read
|
|
20
|
-
|
|
21
|
-
steps:
|
|
22
|
-
- name: Check out code
|
|
23
|
-
uses: actions/checkout@v6
|
|
24
|
-
with:
|
|
25
|
-
fetch-depth: 2
|
|
26
|
-
|
|
27
|
-
- name: Set up Node
|
|
28
|
-
uses: actions/setup-node@v6
|
|
29
|
-
with:
|
|
30
|
-
node-version: '24.15.0'
|
|
31
|
-
registry-url: 'https://registry.npmjs.org'
|
|
32
|
-
|
|
33
|
-
- name: Decide whether to publish
|
|
34
|
-
id: version_check
|
|
35
|
-
run: |
|
|
36
|
-
node <<'NODE'
|
|
37
|
-
const fs = require('fs');
|
|
38
|
-
const cp = require('child_process');
|
|
39
|
-
|
|
40
|
-
const outputPath = process.env.GITHUB_OUTPUT;
|
|
41
|
-
const githubEvent = process.env.GITHUB_EVENT_NAME || '';
|
|
42
|
-
|
|
43
|
-
function writeOutput(value) {
|
|
44
|
-
fs.appendFileSync(outputPath, `should_publish=${value}\n`, 'utf8');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (githubEvent === 'workflow_dispatch') {
|
|
48
|
-
console.log('Manual dispatch: publish enabled.');
|
|
49
|
-
writeOutput('true');
|
|
50
|
-
process.exit(0);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const current = JSON.parse(fs.readFileSync('package.json', 'utf8')).version;
|
|
54
|
-
let published;
|
|
55
|
-
try {
|
|
56
|
-
published = cp.execFileSync(
|
|
57
|
-
'npm',
|
|
58
|
-
['view', '@micha.bigler/ui-core-micha', 'version'],
|
|
59
|
-
{ encoding: 'utf8' }
|
|
60
|
-
).trim();
|
|
61
|
-
} catch (error) {
|
|
62
|
-
console.log(
|
|
63
|
-
'Could not fetch the published npm version (the package may not exist yet or the registry is unavailable). Publishing.'
|
|
64
|
-
);
|
|
65
|
-
writeOutput('true');
|
|
66
|
-
process.exit(0);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
console.log(`Published version: ${published}`);
|
|
70
|
-
console.log(`Current version: ${current}`);
|
|
71
|
-
|
|
72
|
-
function parse(version) {
|
|
73
|
-
return version.split('.').map((part) => Number.parseInt(part, 10) || 0);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function greaterThan(a, b) {
|
|
77
|
-
const left = parse(a);
|
|
78
|
-
const right = parse(b);
|
|
79
|
-
const maxLength = Math.max(left.length, right.length);
|
|
80
|
-
for (let index = 0; index < maxLength; index += 1) {
|
|
81
|
-
const lv = left[index] || 0;
|
|
82
|
-
const rv = right[index] || 0;
|
|
83
|
-
if (lv > rv) return true;
|
|
84
|
-
if (lv < rv) return false;
|
|
85
|
-
}
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (greaterThan(current, published)) {
|
|
90
|
-
console.log('Version increased. Publishing.');
|
|
91
|
-
writeOutput('true');
|
|
92
|
-
} else {
|
|
93
|
-
console.log('Version did not increase. Skipping publish.');
|
|
94
|
-
writeOutput('false');
|
|
95
|
-
}
|
|
96
|
-
NODE
|
|
97
|
-
|
|
98
|
-
- name: Set up pnpm
|
|
99
|
-
if: steps.version_check.outputs.should_publish == 'true'
|
|
100
|
-
uses: pnpm/action-setup@v6
|
|
101
|
-
with:
|
|
102
|
-
version: 11.1.2
|
|
103
|
-
|
|
104
|
-
- name: Show version from package.json
|
|
105
|
-
if: steps.version_check.outputs.should_publish == 'true'
|
|
106
|
-
run: node -e "console.log('Version from package.json:', require('./package.json').version);"
|
|
107
|
-
|
|
108
|
-
- name: Install dependencies (pnpm)
|
|
109
|
-
if: steps.version_check.outputs.should_publish == 'true'
|
|
110
|
-
run: pnpm install --frozen-lockfile
|
|
111
|
-
|
|
112
|
-
- name: Build
|
|
113
|
-
if: steps.version_check.outputs.should_publish == 'true'
|
|
114
|
-
run: pnpm run build
|
|
115
|
-
|
|
116
|
-
- name: Run tests
|
|
117
|
-
if: steps.version_check.outputs.should_publish == 'true'
|
|
118
|
-
run: pnpm run test
|
|
119
|
-
|
|
120
|
-
- name: Ensure recent npm for trusted publishing
|
|
121
|
-
if: steps.version_check.outputs.should_publish == 'true'
|
|
122
|
-
run: npm install -g npm@latest
|
|
123
|
-
|
|
124
|
-
- name: Publish to npm (Trusted Publishing)
|
|
125
|
-
if: steps.version_check.outputs.should_publish == 'true'
|
|
126
|
-
run: npm publish --access public
|
package/DESIGN.md
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# Frontend Design Principles
|
|
2
|
-
|
|
3
|
-
How we design app frontends across the estate. **Consistency here is consistency of METHOD, not one identical look** — every app starts from the shared `createAppTheme` baseline and owns its identity overrides (principle 1); the shared surface (`ui-core-micha` theme, components, charts, layout) carries the structural consistency. hram is the worked example throughout, not a look other apps must copy.
|
|
4
|
-
|
|
5
|
-
These principles are the spec a **prototype** encodes and the implementation matches. `frontend-engineering` (build) and `ui_reviewer` (review) point here; the prototype workflow is the `frontend-design` skill.
|
|
6
|
-
|
|
7
|
-
## Identity
|
|
8
|
-
|
|
9
|
-
### Dark mode
|
|
10
|
-
|
|
11
|
-
Opt in with `createAppTheme({ palette: { mode: 'dark', primary } })`. The factory keeps a primary that
|
|
12
|
-
already clears 4.5:1 on the dark page and lightens one that does not; its button text is whichever of
|
|
13
|
-
`#FFFFFF` and the page colour has the stronger contrast. Baseline status colours and control borders are
|
|
14
|
-
lightened only when a baseline-owned value fails on an app's dark page; app-supplied values remain owned by
|
|
15
|
-
the app. Dialogs, menus, popovers, and drawers use the dark overlay surface and shadow, while resting
|
|
16
|
-
surfaces remain outlined and shadowless. Data-series colours are lightened until they clear 3:1 on the
|
|
17
|
-
theme's own paper, so an app-owned dark paper adapts without changing its supplied series. Apps own their
|
|
18
|
-
dark primary and may own reviewed dark surfaces and ink; the baseline owns the remaining dark tokens.
|
|
19
|
-
|
|
20
|
-
The baseline's page-derived colours are `success.main`, `warning.main`, `error.main`, `info.main`,
|
|
21
|
-
`controlBorder.main`, `controlBorder.hover`, and `controlBorder.error`, alongside the existing
|
|
22
|
-
`controlBorder.focus`: a fixed colour cannot promise WCAG contrast on every page background. The baseline therefore
|
|
23
|
-
tries for a passing colour rather than a fixed hex that must appear unchanged on every site — derivation is capped
|
|
24
|
-
(the same bounded darken/alpha steps `controlBorder.focus` already used) and can still leave a contrast finding on a
|
|
25
|
-
page extreme enough that no derived shade clears the threshold; values that already pass remain byte-identical,
|
|
26
|
-
while baseline values that fail are derived against the theme's own page.
|
|
27
|
-
|
|
28
|
-
1. **Honor the shared baseline and the app's identity; don't invent a parallel system.** `ui-core-micha`'s `createAppTheme` deliberately owns the complete visual baseline. Each app supplies its identity through `palette.primary` and `fontFamily`, plus reviewed overrides where its real design requires them (hram: primary blue `#468AB2`). **Match first, then elevate.** Never invent a parallel language — a made-up teal / pills / breadcrumb vocabulary was the v1 mistake.
|
|
29
|
-
2. **One accent, deliberately placed.** Interactive = the app's one accent colour. **Data colours are a separate layer with a shared default that apps may override.** Status (green / amber / red) is semantic and is NEVER repurposed as a series colour. Restraint over decoration.
|
|
30
|
-
3. **Commit to the app's theme reality — with intent.** If the app is single-theme (hram is light-only), commit to that deliberately rather than bolting on dark mode as an afterthought — a decision, not an omission. The estate does NOT mandate light-only; it is per-app — but whichever it is, it is on purpose.
|
|
31
|
-
|
|
32
|
-
## Information design (it's a tool, not a document)
|
|
33
|
-
|
|
34
|
-
4. **Scan and operate, not read.** Summary before detail; state encoded in form (chips, knee-markers); interactive things look interactive.
|
|
35
|
-
5. **The user's language, not the system's.** Humanize labels (`incidence_scale` → "Incidence scale"); keep the raw name reachable on hover for the technicians — readability without losing traceability. Words are design material.
|
|
36
|
-
6. **Reduce help to the minimum, don't remove it.** Explanation lives in on-demand affordances (ⓘ-popover, provisional-chip), never in permanent banners or helper sentences — in doubt a chip, not a sentence; less noise, same information.
|
|
37
|
-
7. **Design the edge-states, not just the happy path.** An empty / "no frontier" state gets a real design (statement + CTA), never a bare alert.
|
|
38
|
-
|
|
39
|
-
## Charts (read by humans, executed by code)
|
|
40
|
-
|
|
41
|
-
8. **Every chart earns:** axis labels (with units), a legend only when >1 series, a tooltip, theme-token colours, container-responsive sizing, and empty/loading states. **Single-hue for magnitude; diverging (blue/red around zero) ONLY for signed data.** The concrete data palette is a separate layer with a shared `ui-core-micha` default that apps override when their domain calls for it.
|
|
42
|
-
**Dual-axis is a default-off exception, opt-in only** (CHART-5, operator decision): the shared `TimeSeriesChart` preset supports a second y-axis via a per-series `axis: 'secondary'` field specifically for two series sharing one axis at very different scales/units (e.g. a user count vs. hours) where series-toggles alone leave one series unreadable. Reach for it only under that same condition, not as a general layout choice — a single shared axis (or toggles) stays the default everywhere else.
|
|
43
|
-
8a. **Axis titles: categorical axis gets none by default; numeric axis carries the quantity and unit, once.** A categorical axis' ticks are names (`"Session 1"`, ward names) — a title only restates their type; add one only when the ticks are codes or abbreviations whose kind is not self-evident. A numeric axis is meaningless without a title naming the quantity and its unit — unless the ticks already show the unit (`%`, a currency symbol) and the panel heading already names the quantity, in which case a title repeats both. **The unit belongs in the title once, never in every tick** (`"Accessibility (minutes) (min)"` over ticks `"0.0 min"` was measured live — the unit three times on one axis). This is a decision the caller makes per axis, not something the chart preset silently applies or suppresses (THEME-9) — a label the caller deliberately set is never auto-dropped.
|
|
44
|
-
8b. **Scatter: neutral by default; colour only when it encodes a real dimension.** An undifferentiated point cloud is one neutral mass (the role register's neutral, not a series/KPI-identity hue) — colour is earned by a genuine data dimension (a category, a continuous measure), never applied just to look intentional. `ScatterChart` (THEME-10, drawn from three real consumers — hram's allocation-performance, access-gap, and optimization-results panels) supports three modes: neutral (default, single series, no colour set), categorical (multiple series, one colour per series, discrete legend — draw the colours from the app's own family/role register, not a hand-indexed array), and continuous (the caller resolves a per-point colour from its own scale and applies it via `getPointStyle`; this package does not ship a colour-scale/legend component). Bubble sizing (`sizeAccessor`) always draws largest-first — an unordered bubble chart with no defined draw order is silently wrong, not a stylistic choice. Individually marked points (a hollow status-quo point against filled candidates) go through the same `getPointStyle` hook. Reference geometry (a computed curve, a labelled reference line) is composed as `children`, reading the chart's own live scale (`ScatterReferenceCurve`/`ScatterReferenceLine`) rather than a second, hand-rolled pixel mapping. **Not this preset:** row-based dot plots (a forest plot, a tornado) — categorical y-axis, 150–220px of row labels, row-density as the layout problem — are a different chart family with their own preset, not a scatter with a tall left margin.
|
|
45
|
-
9. **Ground it in the real subject matter.** Faithful structures from the real panels (hram: Morris-tornado, Pareto/knee, CI-strip, allocation-scatter with shape-encoded sources) — no lorem, no generic charts. Hence: **scout the real subject before building.**
|
|
46
|
-
|
|
47
|
-
## Craft
|
|
48
|
-
|
|
49
|
-
10. **Prototype = spec, parity = guardrail — both directions, within a DECLARED coverage.** Purely visual/UX — function stays; **"No behaviour / permission / data-contract change"** is the hard condition in the WO. Prototypes are routinely **partial** (tabs undrawn, flows stubbed), and nobody downstream can tell a deliberate omission from a required removal — so **prototype silence never authorizes a removal; the Envelope's "Replaces / removes" list does.** Every prototype therefore **declares what it covers and what it leaves untouched**. Inside the covered area each omission is resolved at authoring time into *removes* or *deliberately keeps*, leaving nothing ambiguous; outside it the prototype says nothing. Parity is then checked both ways **within that coverage**: everything drawn is present, and nothing listed as removed survives. **Inventory is not enough.** Presence and absence say nothing about weight, density or colour — an implementation can pass this check completely and still read heavier and older than the prototype. Parity therefore also requires a **rendered side-by-side at two widths** before the change lands (the Orchestrator's — `AGENTS.md` → Reviews), and the token values themselves come from the artifact's `<style>` block via the Envelope's token delta list. **A redesign that ends up net-additive has failed**, however good its new parts — shipping MORE UI than before is the estate's recurring cleanup failure (status bands, duplicated badges, tip text layered on top of the very legacy the redesign was meant to replace).
|
|
50
|
-
11. **Align to the shipped reality.** When related features land, pull the prototype onto them so it is a truthful spec, not a contradicting vision.
|
|
51
|
-
12. **Avoid the generic "AI look"; take details seriously.** No cream / serif / neon default; embed the real font (CSP-safe as a data-URI, not a silent-fallback risk); `tabular-nums` for aligned numbers; a11y (role/aria on chart regions, focusable info). **Template tells to CUT** (unless the app's design system genuinely specifies them): monospace-uppercase **eyebrow / kicker labels** (e.g. `IMARA · ADVANCING RESILIENT HEALTH SYSTEMS`), decorative **pills / badges**, `FIG. 01 ·` / `F.01` **figure captions**, `↳`-prefixed **micro-links**, **oversized display** headlines, **sketchy / hand-drawn** styling, and **explanatory paragraphs that restate the UI** (help is on-demand — see #6). Restraint is the default; each of these is added only with a real reason.
|
|
52
|
-
|
|
53
|
-
For the **design craft** of a prototype (an HTML artifact) and its charts, load Claude's built-in **`artifact-design`** (design fundamentals) and **`dataviz`** (charts) skills and apply them WITHIN these principles — this doc adds the estate method (honor the app's OWN tokens, restraint), it does not replace that craft, and it must not crowd it out (load both). Do NOT default to **`swisstph-design`**: it imposes the Swiss-TPH house brand and conflicts with #1 (honor the app's own tokens).
|
|
54
|
-
|
|
55
|
-
## Also — structural dimensions
|
|
56
|
-
|
|
57
|
-
13. **Spacing / density = tool density, not document width.** A defined spacing rhythm, dense enough to scan and operate — not airy like a reading document. Use the theme's spacing scale; don't hand-pick pixel gaps.
|
|
58
|
-
14. **Responsive = container-sized, not fixed px.** Layouts and charts size to their container; define breakpoint behaviour deliberately (what stacks, what hides, what scrolls) — the same container-responsive rule the charts already follow.
|
|
59
|
-
15. **Motion = restrained and functional.** Transitions serve orientation/feedback (state change, reveal), never decoration. Short, few, purposeful; respect `prefers-reduced-motion`.
|
|
60
|
-
16. **Prefer icons for secondary actions where the meaning is conventional.** A dense action row reads better as one labelled primary action plus **icon buttons** (preview, download, edit, delete, overflow) than as a row of text buttons — and a labelled `Button` is simply the cheapest thing to type, so implementations drift toward text-heavy rows the prototype never had. Conditions: use an **established glyph** (never invented iconography); always pair it with a **`Tooltip` AND an `aria-label`**, since an icon-only control otherwise has no accessible name; and **keep the text label** when the action is primary, destructive without a confirm step, or app-specific enough that no conventional icon exists. A tooltip may NAME an action — if it has to explain a concept, the control needs a label, or on-demand help (#6).
|