@jobber/components-native 0.113.4 → 0.113.5-JOB-174434-1d4c303.10
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/dist/docs/AtlantisThemeContext/AtlantisThemeContext.md +27 -10
- package/dist/docs/Button/Button.md +1 -1
- package/dist/docs/Chip/Chip.md +1 -1
- package/dist/docs/Colors/Colors.md +7 -1
- package/dist/docs/EmptyState/EmptyState.md +1 -1
- package/dist/docs/Icon/Icon.md +69 -35
- package/dist/docs/InputNumber/InputNumber.md +131 -17
- package/dist/docs/InputText/InputText.md +9 -1
- package/dist/docs/Spacing/Spacing.md +1 -1
- package/dist/docs/page-layouts/page-layouts.md +29 -0
- package/dist/docs/settings/settings.md +3 -3
- package/dist/docs/usage-guidelines/usage-guidelines.md +16 -24
- package/dist/package.json +6 -7
- package/dist/src/ActivityIndicator/ActivityIndicator.js +2 -2
- package/dist/src/AtlantisThemeContext/AtlantisThemeContext.js +42 -14
- package/dist/src/AtlantisThemeContext/AtlantisThemeContext.test.js +112 -11
- package/dist/src/AtlantisThemeContext/buildThemedStyles.js +8 -2
- package/dist/src/AtlantisThemeContext/buildThemedStyles.test.js +43 -1
- package/dist/src/AutoLink/hooks/useTokenGenerator.js +2 -2
- package/dist/src/Banner/components/BannerIcon/BannerIcon.js +1 -1
- package/dist/src/BottomSheet/BottomSheet.js +11 -7
- package/dist/src/BottomSheet/BottomSheet.style.js +1 -0
- package/dist/src/BottomSheet/BottomSheet.test.js +16 -0
- package/dist/src/Button/Button.js +1 -1
- package/dist/src/Checkbox/Checkbox.js +1 -1
- package/dist/src/ContentOverlay/ContentOverlay.js +2 -2
- package/dist/src/Disclosure/Disclosure.js +1 -1
- package/dist/src/EmptyState/EmptyState.js +1 -1
- package/dist/src/EmptyState/EmptyState.test.js +2 -1
- package/dist/src/ErrorMessageWrapper/ErrorMessageWrapper.js +5 -5
- package/dist/src/FormatFile/components/ProgressBar/ProgressBar.style.js +1 -1
- package/dist/src/FormatFile/components/_mocks/mockFiles.js +4 -4
- package/dist/src/Glimmer/Glimmer.js +8 -3
- package/dist/src/Glimmer/Glimmer.style.js +9 -1
- package/dist/src/Glimmer/Glimmer.test.js +17 -1
- package/dist/src/Heading/Heading.js +1 -1
- package/dist/src/InputFieldWrapper/CommonInputStyles.style.js +1 -1
- package/dist/src/InputFieldWrapper/InputFieldWrapper.test.js +2 -0
- package/dist/src/InputFieldWrapper/components/Prefix/Prefix.js +3 -1
- package/dist/src/InputFieldWrapper/components/Suffix/Suffix.js +3 -1
- package/dist/src/InputText/context/InputAccessoriesProvider.js +2 -2
- package/dist/src/Switch/components/BaseSwitch/BaseSwitch.js +1 -1
- package/dist/src/Toast/Toast.js +1 -1
- package/dist/src/Toast/Toast.styles.js +2 -2
- package/dist/src/Typography/Typography.js +1 -1
- package/dist/src/hooks/useFormController.js +2 -2
- package/dist/src/primitives/Select/SelectPrimitive.js +12 -2
- package/dist/src/primitives/Select/SelectPrimitive.style.js +6 -0
- package/dist/src/primitives/Select/SelectPrimitive.test.js +47 -4
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/src/AtlantisThemeContext/AtlantisThemeContext.d.ts +1 -1
- package/dist/types/src/AtlantisThemeContext/index.d.ts +1 -1
- package/dist/types/src/AtlantisThemeContext/types.d.ts +19 -4
- package/dist/types/src/BottomSheet/BottomSheet.style.d.ts +1 -0
- package/dist/types/src/Glimmer/Glimmer.d.ts +1 -0
- package/dist/types/src/Glimmer/Glimmer.style.d.ts +9 -1
- package/dist/types/src/primitives/Select/SelectPrimitive.d.ts +1 -1
- package/dist/types/src/primitives/Select/SelectPrimitive.style.d.ts +6 -0
- package/package.json +6 -7
- package/src/ActivityIndicator/ActivityIndicator.stories.tsx +2 -2
- package/src/ActivityIndicator/ActivityIndicator.tsx +2 -2
- package/src/ActivityIndicator/guide.md +7 -5
- package/src/AtlantisThemeContext/AtlantisThemeContext.guide.md +76 -0
- package/src/AtlantisThemeContext/AtlantisThemeContext.test.tsx +193 -11
- package/src/AtlantisThemeContext/AtlantisThemeContext.tsx +66 -13
- package/src/AtlantisThemeContext/buildThemedStyles.test.tsx +63 -1
- package/src/AtlantisThemeContext/buildThemedStyles.ts +11 -2
- package/src/AtlantisThemeContext/docs/AtlantisThemeContextBasicExample.tsx +8 -2
- package/src/AtlantisThemeContext/docs/AtlantisThemeContextForceThemeForProviderExample.tsx +8 -4
- package/src/AtlantisThemeContext/index.ts +1 -0
- package/src/AtlantisThemeContext/types.ts +23 -4
- package/src/AutoLink/hooks/useTokenGenerator.ts +2 -2
- package/src/Banner/components/BannerIcon/BannerIcon.tsx +1 -1
- package/src/BottomSheet/BottomSheet.style.ts +1 -0
- package/src/BottomSheet/BottomSheet.test.tsx +30 -0
- package/src/BottomSheet/BottomSheet.tsx +26 -12
- package/src/Button/Button.tsx +1 -1
- package/src/Checkbox/Checkbox.tsx +1 -1
- package/src/ContentOverlay/ContentOverlay.tsx +2 -2
- package/src/Disclosure/Disclosure.tsx +1 -1
- package/src/EmptyState/EmptyState.test.tsx +2 -1
- package/src/EmptyState/EmptyState.tsx +1 -1
- package/src/ErrorMessageWrapper/ErrorMessageWrapper.tsx +5 -5
- package/src/FormatFile/components/ProgressBar/ProgressBar.style.tsx +1 -1
- package/src/FormatFile/components/_mocks/mockFiles.ts +4 -4
- package/src/Glimmer/Glimmer.style.ts +10 -1
- package/src/Glimmer/Glimmer.test.tsx +35 -1
- package/src/Glimmer/Glimmer.tsx +9 -4
- package/src/Heading/Heading.tsx +1 -1
- package/src/Heading/__snapshots__/Heading.test.tsx.snap +5 -5
- package/src/InputFieldWrapper/CommonInputStyles.style.ts +1 -1
- package/src/InputFieldWrapper/InputFieldWrapper.test.tsx +4 -0
- package/src/InputFieldWrapper/components/Prefix/Prefix.tsx +3 -1
- package/src/InputFieldWrapper/components/Suffix/Suffix.tsx +3 -1
- package/src/InputText/context/InputAccessoriesProvider.tsx +2 -2
- package/src/Select/Select.guide.md +6 -0
- package/src/Switch/components/BaseSwitch/BaseSwitch.tsx +1 -1
- package/src/Toast/Toast.styles.ts +2 -2
- package/src/Toast/Toast.tsx +1 -1
- package/src/Typography/Typography.tsx +1 -1
- package/src/Typography/__snapshots__/Typography.test.tsx.snap +32 -32
- package/src/hooks/useFormController.ts +2 -2
- package/src/primitives/Select/SelectPrimitive.style.ts +8 -0
- package/src/primitives/Select/SelectPrimitive.test.tsx +82 -2
- package/src/primitives/Select/SelectPrimitive.tsx +25 -2
|
@@ -5,16 +5,22 @@ tokens.
|
|
|
5
5
|
|
|
6
6
|
## Design & usage guidelines
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
Web and mobile both expose Atlantis theme context, but the runtime ownership is
|
|
9
|
+
slightly different across platforms.
|
|
10
10
|
|
|
11
11
|
Each platform provides a `useAtlantisTheme` hook that you may use to access the
|
|
12
|
-
|
|
12
|
+
current theme information and design tokens in your components.
|
|
13
13
|
|
|
14
|
-
On mobile,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
On mobile, the hook returns:
|
|
15
|
+
|
|
16
|
+
* `theme`: the selected theme preference (`"system" | "light" | "dark"`)
|
|
17
|
+
* `effectiveTheme`: the resolved theme Atlantis uses for tokens
|
|
18
|
+
(`"light" | "dark"`)
|
|
19
|
+
* `tokens`
|
|
20
|
+
* `setTheme`
|
|
21
|
+
|
|
22
|
+
Typically there will only be a single provider at the root, and the consuming
|
|
23
|
+
app will control `theme` and persist that preference outside Atlantis.
|
|
18
24
|
|
|
19
25
|
On web, you'll need to import the `updateTheme` function and call it with the
|
|
20
26
|
new theme. This is a separate function because it synchronizes the theme update
|
|
@@ -86,7 +92,7 @@ function App() {
|
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
function ThemedComponent() {
|
|
89
|
-
const { theme, tokens, setTheme } = useAtlantisTheme();
|
|
95
|
+
const { theme, effectiveTheme, tokens, setTheme } = useAtlantisTheme();
|
|
90
96
|
return (
|
|
91
97
|
<Content>
|
|
92
98
|
<View
|
|
@@ -96,11 +102,16 @@ function ThemedComponent() {
|
|
|
96
102
|
}}
|
|
97
103
|
>
|
|
98
104
|
<Content>
|
|
99
|
-
<Text>The
|
|
105
|
+
<Text>The selected theme is: {theme}.</Text>
|
|
106
|
+
<Text>The effective theme is: {effectiveTheme}.</Text>
|
|
100
107
|
<Text>
|
|
101
108
|
The javascript tokens can be accessed via the tokens object.
|
|
102
109
|
</Text>
|
|
103
110
|
<Text>The theme can be changed using `setTheme`</Text>
|
|
111
|
+
<Button
|
|
112
|
+
onPress={() => setTheme("system")}
|
|
113
|
+
label="The theme can be changed to system"
|
|
114
|
+
/>
|
|
104
115
|
<Button
|
|
105
116
|
onPress={() => setTheme("light")}
|
|
106
117
|
label="The theme can be changed to light"
|
|
@@ -163,6 +174,10 @@ regardless of the main application theme. This can be done by setting the
|
|
|
163
174
|
`dangerouslyOverrideTheme` prop to `<themeToSet>` on the
|
|
164
175
|
`AtlantisThemeContextProvider`.
|
|
165
176
|
|
|
177
|
+
On mobile, forcing a theme changes the rendered tokens for that subtree, but it
|
|
178
|
+
does not replace the selected theme preference semantics from the nearest
|
|
179
|
+
non-forced provider.
|
|
180
|
+
|
|
166
181
|
Note: If you're using `buildThemedStyles`, any `useStyles` calls must be done
|
|
167
182
|
within a *child component* of the `AtlantisThemeContextProvider`, not in the
|
|
168
183
|
same component that renders the provider. Same goes for `useAtlantisTheme`.
|
|
@@ -293,4 +308,6 @@ Key features:
|
|
|
293
308
|
| Prop | Type | Required | Default | Description |
|
|
294
309
|
|------|------|----------|---------|-------------|
|
|
295
310
|
| `children` | `ReactNode` | Yes | — | The children to render. |
|
|
296
|
-
| `dangerouslyOverrideTheme` | `
|
|
311
|
+
| `dangerouslyOverrideTheme` | `EffectiveTheme` | No | — | Force the theme for this provider to always be the same as the provided theme. Useful for sections that should remain... |
|
|
312
|
+
| `onThemeChange` | `(theme: Theme) => void` | No | — | Called when children request a selected theme change through setTheme. |
|
|
313
|
+
| `theme` | `Theme` | No | — | Control the selected theme for this provider. |
|
|
@@ -388,7 +388,7 @@ A key distinction between subtle buttons and the other variations is that the
|
|
|
388
388
|
primary/secondary/tertiary scale is styled differently, but the conceptual
|
|
389
389
|
hierarchy is the same. Notably, the tertiary subtle button has a transparent
|
|
390
390
|
background, allowing it to be *extra* subtle when placed overtop
|
|
391
|
-
`surface--background` elements such as a
|
|
391
|
+
`surface--background` elements such as a Dialog header.
|
|
392
392
|
|
|
393
393
|
```tsx
|
|
394
394
|
import React from "react";
|
package/dist/docs/Chip/Chip.md
CHANGED
|
@@ -22,7 +22,7 @@ export function ChipWithAvatarExample(
|
|
|
22
22
|
<Chip.Prefix>
|
|
23
23
|
<Avatar
|
|
24
24
|
size="small"
|
|
25
|
-
|
|
25
|
+
src="https://images.unsplash.com/photo-1669475535925-a011d7c31d45?q=80&w=1886&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
|
26
26
|
/>
|
|
27
27
|
</Chip.Prefix>
|
|
28
28
|
<Chip.Suffix>
|
|
@@ -156,7 +156,7 @@ application.
|
|
|
156
156
|
#### Overlay
|
|
157
157
|
|
|
158
158
|
Use to mask an area of the interface to promote focus to a foreground action,
|
|
159
|
-
such as a [
|
|
159
|
+
such as a [Dialog](/components/Dialog)'s appearance. Overlay includes built-in
|
|
160
160
|
opacity values.
|
|
161
161
|
|
|
162
162
|
#### Overlay--Dimmed
|
|
@@ -228,3 +228,9 @@ Use to highlight an element in a way that aligns with our website. Use with
|
|
|
228
228
|
caution, it's *bright!*
|
|
229
229
|
|
|
230
230
|
## Base colors
|
|
231
|
+
|
|
232
|
+
Base blues in light mode do not share the muted saturation of the dark-mode
|
|
233
|
+
overlay. Light `blue--100` through `blue--800` stay in a modest 12–35%
|
|
234
|
+
saturation range; `blue--900`, `blue--950`, and `blue--1000` jump to 90%+ so the
|
|
235
|
+
darkest steps stay distinctly blue. Dark mode remaps `700`–`1000` (including
|
|
236
|
+
`750` and `950`) onto roughly 9–18% saturation instead.
|
|
@@ -66,7 +66,7 @@ reflow to a second line if enough content is provided.
|
|
|
66
66
|
|------|------|----------|---------|-------------|
|
|
67
67
|
| `description` | `string` | No | — | Description of the empty state. |
|
|
68
68
|
| `icon` | `IconNames` | No | — | Icon to display. |
|
|
69
|
-
| `iconColor` | `"task" | "text" | "warning" | "icon" | "iconSecondary" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | ... 35 more ... | "brandHighlight"` | No | `
|
|
69
|
+
| `iconColor` | `"task" | "text" | "warning" | "icon" | "iconSecondary" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | ... 35 more ... | "brandHighlight"` | No | `icon` | Color of Icon to display. |
|
|
70
70
|
| `primaryAction` | `Action` | No | — | Handler for the primary action. |
|
|
71
71
|
| `secondaryAction` | `Action` | No | — | Handler for the secondary action. |
|
|
72
72
|
| `title` | `string` | No | — | Title of the empty state. |
|
package/dist/docs/Icon/Icon.md
CHANGED
|
@@ -192,6 +192,7 @@ export function IconSizesExample() {
|
|
|
192
192
|
|
|
193
193
|
| Icon | `Name` |
|
|
194
194
|
| :--- | :----------------- |
|
|
195
|
+
| | `arrow` |
|
|
195
196
|
| | `arrowDown` |
|
|
196
197
|
| | `arrowLeft` |
|
|
197
198
|
| | `arrowRight` |
|
|
@@ -212,6 +213,7 @@ export function IconSizesExample() {
|
|
|
212
213
|
| | `calendar` |
|
|
213
214
|
| | `calendarCheck` |
|
|
214
215
|
| | `clearFilters` |
|
|
216
|
+
| | `dueDate` |
|
|
215
217
|
| | `event` |
|
|
216
218
|
| | `onlineBooking` |
|
|
217
219
|
| | `orientationHorizontal` |
|
|
@@ -244,22 +246,23 @@ export function IconSizesExample() {
|
|
|
244
246
|
|
|
245
247
|
### Forms
|
|
246
248
|
|
|
247
|
-
| Icon | `Name`
|
|
248
|
-
| :--- |
|
|
249
|
-
| | `checkbox`
|
|
250
|
-
| | `checklist`
|
|
251
|
-
| | `
|
|
252
|
-
| | `
|
|
253
|
-
| | `
|
|
254
|
-
| | `
|
|
255
|
-
| | `
|
|
256
|
-
| | `
|
|
257
|
-
| | `
|
|
258
|
-
| | `
|
|
259
|
-
| | `
|
|
260
|
-
| | `
|
|
261
|
-
| | `
|
|
262
|
-
| | `
|
|
249
|
+
| Icon | `Name` |
|
|
250
|
+
| :--- | :---------------- |
|
|
251
|
+
| | `checkbox` |
|
|
252
|
+
| | `checklist` |
|
|
253
|
+
| | `digestChecklist` |
|
|
254
|
+
| | `edit` |
|
|
255
|
+
| | `editDisabled` |
|
|
256
|
+
| | `radioButton` |
|
|
257
|
+
| | `star` |
|
|
258
|
+
| | `starHalf` |
|
|
259
|
+
| | `starFill` |
|
|
260
|
+
| | `text` |
|
|
261
|
+
| | `textBox` |
|
|
262
|
+
| | `textField` |
|
|
263
|
+
| | `toggle` |
|
|
264
|
+
| | `dropdown` |
|
|
265
|
+
| | `trash` |
|
|
263
266
|
|
|
264
267
|
### Status and support
|
|
265
268
|
|
|
@@ -283,25 +286,26 @@ export function IconSizesExample() {
|
|
|
283
286
|
|
|
284
287
|
### Messaging
|
|
285
288
|
|
|
286
|
-
| Icon | `Name`
|
|
287
|
-
| :--- |
|
|
288
|
-
| | `chat`
|
|
289
|
-
| | `compose`
|
|
290
|
-
| | `conversation`
|
|
291
|
-
| | `email`
|
|
292
|
-
| | `emailInbound`
|
|
293
|
-
| | `emailOutbound`
|
|
294
|
-
| | `markSent`
|
|
295
|
-
| | `marketing`
|
|
296
|
-
| | `reminder`
|
|
297
|
-
| | `sendMessage`
|
|
298
|
-
| | `sms`
|
|
299
|
-
| | `sms2`
|
|
300
|
-
| | `smsInbound`
|
|
301
|
-
| | `smsOutbound`
|
|
302
|
-
| | `smsProgress`
|
|
303
|
-
| | `
|
|
304
|
-
| | `
|
|
289
|
+
| Icon | `Name` |
|
|
290
|
+
| :--- | :---------------------- |
|
|
291
|
+
| | `chat` |
|
|
292
|
+
| | `compose` |
|
|
293
|
+
| | `conversation` |
|
|
294
|
+
| | `email` |
|
|
295
|
+
| | `emailInbound` |
|
|
296
|
+
| | `emailOutbound` |
|
|
297
|
+
| | `markSent` |
|
|
298
|
+
| | `marketing` |
|
|
299
|
+
| | `reminder` |
|
|
300
|
+
| | `sendMessage` |
|
|
301
|
+
| | `sms` |
|
|
302
|
+
| | `sms2` |
|
|
303
|
+
| | `smsInbound` |
|
|
304
|
+
| | `smsOutbound` |
|
|
305
|
+
| | `smsProgress` |
|
|
306
|
+
| | `snoozeRecommendations` |
|
|
307
|
+
| | `webchat` |
|
|
308
|
+
| | `webchatProgress` |
|
|
305
309
|
|
|
306
310
|
### User
|
|
307
311
|
|
|
@@ -346,6 +350,8 @@ export function IconSizesExample() {
|
|
|
346
350
|
| | `contactlessPayment` |
|
|
347
351
|
| | `cheque` |
|
|
348
352
|
| | `cash` |
|
|
353
|
+
| | `coin` |
|
|
354
|
+
| | `handDollarSign` |
|
|
349
355
|
|
|
350
356
|
### Work
|
|
351
357
|
|
|
@@ -425,7 +431,9 @@ export function IconSizesExample() {
|
|
|
425
431
|
| | `future` |
|
|
426
432
|
| | `history` |
|
|
427
433
|
| | `import` |
|
|
434
|
+
| | `maximize` |
|
|
428
435
|
| | `merge` |
|
|
436
|
+
| | `minimize` |
|
|
429
437
|
| | `redo` |
|
|
430
438
|
| | `search` |
|
|
431
439
|
| | `sort` |
|
|
@@ -441,12 +449,14 @@ export function IconSizesExample() {
|
|
|
441
449
|
| | `apps` |
|
|
442
450
|
| | `at` |
|
|
443
451
|
| | `camera` |
|
|
452
|
+
| | `cap` |
|
|
444
453
|
| | `checkmark` |
|
|
445
454
|
| | `checkmarkCircle` |
|
|
446
455
|
| | `circle` |
|
|
447
456
|
| | `cog` |
|
|
448
457
|
| | `dashboard` |
|
|
449
458
|
| | `desktop` |
|
|
459
|
+
| | `cube` |
|
|
450
460
|
| | `website` |
|
|
451
461
|
| | `eye` |
|
|
452
462
|
| | `eyeCrossed` |
|
|
@@ -456,12 +466,14 @@ export function IconSizesExample() {
|
|
|
456
466
|
| | `gift` |
|
|
457
467
|
| | `grid` |
|
|
458
468
|
| | `happyFace` |
|
|
469
|
+
| | `hardHat` |
|
|
459
470
|
| | `headset` |
|
|
460
471
|
| | `home` |
|
|
461
472
|
| | `link` |
|
|
462
473
|
| | `loadingCheck` |
|
|
463
474
|
| | `lock` |
|
|
464
475
|
| | `logout` |
|
|
476
|
+
| | `mcp` |
|
|
465
477
|
| | `measurement` |
|
|
466
478
|
| | `menu` |
|
|
467
479
|
| | `microphone` |
|
|
@@ -471,12 +483,14 @@ export function IconSizesExample() {
|
|
|
471
483
|
| | `number` |
|
|
472
484
|
| | `numpad` |
|
|
473
485
|
| | `offline` |
|
|
486
|
+
| | `outdoor` |
|
|
474
487
|
| | `phone` |
|
|
475
488
|
| | `phoneCall` |
|
|
476
489
|
| | `phoneDisconnected` |
|
|
477
490
|
| | `phoneEnd` |
|
|
478
491
|
| | `phoneIncoming` |
|
|
479
492
|
| | `phoneOutgoing` |
|
|
493
|
+
| | `pieChart` |
|
|
480
494
|
| | `pinned` |
|
|
481
495
|
| | `presentation` |
|
|
482
496
|
| | `priceTag` |
|
|
@@ -489,6 +503,7 @@ export function IconSizesExample() {
|
|
|
489
503
|
| | `soundwave` |
|
|
490
504
|
| | `sparkles` |
|
|
491
505
|
| | `speaker` |
|
|
506
|
+
| | `sprayBottle` |
|
|
492
507
|
| | `sprout` |
|
|
493
508
|
| | `starburst` |
|
|
494
509
|
| | `sun` |
|
|
@@ -496,8 +511,27 @@ export function IconSizesExample() {
|
|
|
496
511
|
| | `thumbsDown` |
|
|
497
512
|
| | `thumbsUp` |
|
|
498
513
|
| | `unPinned` |
|
|
514
|
+
| | `wrenchScrewdriver` |
|
|
499
515
|
| | `xero` |
|
|
500
516
|
|
|
517
|
+
### Weather
|
|
518
|
+
|
|
519
|
+
| Icon | `Name` |
|
|
520
|
+
| :--- | :------------------ |
|
|
521
|
+
| | `clearSunny` |
|
|
522
|
+
| | `foggy` |
|
|
523
|
+
| | `hailStorm` |
|
|
524
|
+
| | `heatWarning` |
|
|
525
|
+
| | `heavyRain` |
|
|
526
|
+
| | `lightRain` |
|
|
527
|
+
| | `mixedSnowShowers` |
|
|
528
|
+
| | `nightClear` |
|
|
529
|
+
| | `overcastCloudy` |
|
|
530
|
+
| | `partlySunny` |
|
|
531
|
+
| | `snow` |
|
|
532
|
+
| | `thunderLightening` |
|
|
533
|
+
| | `windy` |
|
|
534
|
+
|
|
501
535
|
### Legacy
|
|
502
536
|
|
|
503
537
|
| Icon | `Name` |
|
|
@@ -339,17 +339,17 @@ the **Design** tab.
|
|
|
339
339
|
| `Description` | Helper text below the field |
|
|
340
340
|
| `Error` | Styled error message below the field |
|
|
341
341
|
|
|
342
|
-
## Composition
|
|
343
|
-
|
|
344
|
-
The prop-driven component is sugar: it renders exactly the tree you would write
|
|
345
|
-
by hand with `<InputNumber.Wrapper>` and the parts. To customize a single piece,
|
|
346
|
-
compose the tree yourself and swap that one part — the other parts keep their
|
|
347
|
-
defaults. The sugar does not merge consumer-provided parts into its render, so
|
|
348
|
-
there is no per-slot precedence to reason about.
|
|
349
|
-
|
|
350
342
|
`Wrapper` owns the field state and shares it with the parts through context, so
|
|
351
343
|
every part must be rendered inside a `Wrapper` (a part used outside one throws).
|
|
352
344
|
|
|
345
|
+
## Customize one part
|
|
346
|
+
|
|
347
|
+
Pass the content parts you want — `Label`, `Affix`, `Stepper`, `Loading`,
|
|
348
|
+
`Description`, `Error` — straight to `Wrapper`. It builds `Group`, `Input`, and
|
|
349
|
+
`Footer` around them and places each part at the right depth, so you never
|
|
350
|
+
reproduce the skeleton to change one piece. `Wrapper` renders only the parts you
|
|
351
|
+
gave it: leave one out and it is not there.
|
|
352
|
+
|
|
353
353
|
The example below replaces the default stepper icons with `+` / `−` and leaves
|
|
354
354
|
everything else as the default:
|
|
355
355
|
|
|
@@ -361,25 +361,139 @@ export function InputNumberCompositionExample() {
|
|
|
361
361
|
const [value, setValue] = useState<number | null>(3);
|
|
362
362
|
|
|
363
363
|
return (
|
|
364
|
-
<InputNumber.Wrapper
|
|
364
|
+
<InputNumber.Wrapper onValueCommitted={setValue} value={value}>
|
|
365
|
+
<InputNumber.Label>Quantity</InputNumber.Label>
|
|
366
|
+
<InputNumber.Stepper>
|
|
367
|
+
<InputNumber.Increment ariaLabel="Increase Quantity">
|
|
368
|
+
+
|
|
369
|
+
</InputNumber.Increment>
|
|
370
|
+
<InputNumber.Decrement ariaLabel="Decrease Quantity">
|
|
371
|
+
−
|
|
372
|
+
</InputNumber.Decrement>
|
|
373
|
+
</InputNumber.Stepper>
|
|
374
|
+
</InputNumber.Wrapper>
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Omit a part
|
|
380
|
+
|
|
381
|
+
A field with no stepper is the same composition minus the `Stepper`:
|
|
382
|
+
|
|
383
|
+
```tsx
|
|
384
|
+
import React, { useState } from "react";
|
|
385
|
+
import { InputNumber } from "@jobber/components";
|
|
386
|
+
|
|
387
|
+
export function InputNumberCompositionStepperlessExample() {
|
|
388
|
+
const [value, setValue] = useState<number | null>(15);
|
|
389
|
+
|
|
390
|
+
return (
|
|
391
|
+
<InputNumber.Wrapper
|
|
392
|
+
format={{ style: "unit", unit: "percent" }}
|
|
393
|
+
onValueCommitted={setValue}
|
|
394
|
+
value={value}
|
|
395
|
+
>
|
|
396
|
+
<InputNumber.Label>Tax rate</InputNumber.Label>
|
|
397
|
+
</InputNumber.Wrapper>
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Show a part conditionally
|
|
403
|
+
|
|
404
|
+
Presence is ordinary conditional JSX; there is no `show*` prop to reach for:
|
|
405
|
+
|
|
406
|
+
```tsx
|
|
407
|
+
import React, { useState } from "react";
|
|
408
|
+
import { InputNumber } from "@jobber/components";
|
|
409
|
+
|
|
410
|
+
export function InputNumberCompositionConditionalStepperExample() {
|
|
411
|
+
const [unitCost, setUnitCost] = useState<number | null>(0);
|
|
412
|
+
const [markup, setMarkup] = useState<number | null>(20);
|
|
413
|
+
|
|
414
|
+
return (
|
|
415
|
+
<>
|
|
416
|
+
<InputNumber
|
|
417
|
+
label="Unit cost"
|
|
418
|
+
onValueCommitted={setUnitCost}
|
|
419
|
+
prefix={{ label: "$" }}
|
|
420
|
+
value={unitCost}
|
|
421
|
+
/>
|
|
422
|
+
<InputNumber.Wrapper onValueCommitted={setMarkup} value={markup}>
|
|
423
|
+
<InputNumber.Label>Markup</InputNumber.Label>
|
|
424
|
+
<InputNumber.Affix label="%" variation="suffix" />
|
|
425
|
+
{Boolean(unitCost) && <InputNumber.Stepper />}
|
|
426
|
+
</InputNumber.Wrapper>
|
|
427
|
+
</>
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Below-field content
|
|
433
|
+
|
|
434
|
+
`Description` and `Error` route into the footer row, which exists only while one
|
|
435
|
+
of them is rendered. The two are never shown together: when both are present the
|
|
436
|
+
error replaces the description, since a description hints at what the field
|
|
437
|
+
wants and the error already restates it.
|
|
438
|
+
|
|
439
|
+
```tsx
|
|
440
|
+
import React, { useState } from "react";
|
|
441
|
+
import { InputNumber } from "@jobber/components";
|
|
442
|
+
|
|
443
|
+
export function InputNumberCompositionFooterExample() {
|
|
444
|
+
const [value, setValue] = useState<number | null>(50);
|
|
445
|
+
const error = (value ?? 0) > 99 ? "Enter a value between 1 and 99" : "";
|
|
446
|
+
|
|
447
|
+
return (
|
|
448
|
+
<InputNumber.Wrapper
|
|
449
|
+
invalid={Boolean(error)}
|
|
450
|
+
max={99}
|
|
451
|
+
min={1}
|
|
452
|
+
onValueChange={setValue}
|
|
453
|
+
value={value}
|
|
454
|
+
>
|
|
455
|
+
<InputNumber.Label>Quantity</InputNumber.Label>
|
|
456
|
+
<InputNumber.Description>Per visit</InputNumber.Description>
|
|
457
|
+
{error && <InputNumber.Error>{error}</InputNumber.Error>}
|
|
458
|
+
</InputNumber.Wrapper>
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
## Custom layouts
|
|
464
|
+
|
|
465
|
+
For an arrangement the standard skeleton does not produce, compose the
|
|
466
|
+
structural parts (`Group`, `Input`, `Footer`) yourself. `Wrapper` then renders
|
|
467
|
+
your tree exactly as written and adds nothing:
|
|
468
|
+
|
|
469
|
+
```tsx
|
|
470
|
+
import React, { useState } from "react";
|
|
471
|
+
import { InputNumber } from "@jobber/components";
|
|
472
|
+
|
|
473
|
+
export function InputNumberCompositionCustomLayoutExample() {
|
|
474
|
+
const [value, setValue] = useState<number | null>(3);
|
|
475
|
+
|
|
476
|
+
return (
|
|
477
|
+
<InputNumber.Wrapper inline onValueCommitted={setValue} value={value}>
|
|
365
478
|
<InputNumber.Group>
|
|
479
|
+
<InputNumber.Decrement ariaLabel="Decrease quantity" />
|
|
366
480
|
<InputNumber.Input>
|
|
367
481
|
<InputNumber.Label>Quantity</InputNumber.Label>
|
|
368
|
-
<InputNumber.Stepper>
|
|
369
|
-
<InputNumber.Increment ariaLabel="Increase Quantity">
|
|
370
|
-
+
|
|
371
|
-
</InputNumber.Increment>
|
|
372
|
-
<InputNumber.Decrement ariaLabel="Decrease Quantity">
|
|
373
|
-
−
|
|
374
|
-
</InputNumber.Decrement>
|
|
375
|
-
</InputNumber.Stepper>
|
|
376
482
|
</InputNumber.Input>
|
|
483
|
+
<InputNumber.Increment ariaLabel="Increase quantity" />
|
|
377
484
|
</InputNumber.Group>
|
|
378
485
|
</InputNumber.Wrapper>
|
|
379
486
|
);
|
|
380
487
|
}
|
|
381
488
|
```
|
|
382
489
|
|
|
490
|
+
Pick one path per `Wrapper`. Mixing structural parts with loose content parts
|
|
491
|
+
throws, rather than guessing where the loose parts belong.
|
|
492
|
+
|
|
493
|
+
The sugar does not merge consumer-provided parts into its render, so there is no
|
|
494
|
+
per-slot precedence to reason about — children passed to `<InputNumber>` are
|
|
495
|
+
ignored. Compose on `Wrapper` instead.
|
|
496
|
+
|
|
383
497
|
## Controlled usage
|
|
384
498
|
|
|
385
499
|
The field is controlled: pass `value` (a `number`, or `null` for empty) and read
|
|
@@ -86,6 +86,10 @@ and align the input with
|
|
|
86
86
|
With clearer guidance around the purpose of inputs, the user is able to better
|
|
87
87
|
focus on the task at hand.
|
|
88
88
|
|
|
89
|
+
Either affix can be given an `onClick` to make it an action, which renders the
|
|
90
|
+
affix icon as a button. An actioned affix requires both an `icon` and an
|
|
91
|
+
`ariaLabel` to name the button — affix labels are not actionable.
|
|
92
|
+
|
|
89
93
|
```tsx
|
|
90
94
|
import React, { useState } from "react";
|
|
91
95
|
import type { InputTextProps } from "@jobber/components/InputText";
|
|
@@ -128,7 +132,11 @@ export function InputTextPrefixSuffixExample(
|
|
|
128
132
|
/>
|
|
129
133
|
<InputText
|
|
130
134
|
placeholder="Search"
|
|
131
|
-
prefix={{
|
|
135
|
+
prefix={{
|
|
136
|
+
icon: "search",
|
|
137
|
+
ariaLabel: "submit search",
|
|
138
|
+
onClick: () => alert("This could submit a search"),
|
|
139
|
+
}}
|
|
132
140
|
value={search}
|
|
133
141
|
onChange={handleSearchChange}
|
|
134
142
|
suffix={{
|
|
@@ -48,7 +48,7 @@ form elements.
|
|
|
48
48
|
### Large
|
|
49
49
|
|
|
50
50
|
Use `large` spacing for higher-level "parent" containers.
|
|
51
|
-
[
|
|
51
|
+
[Dialog](/components/Dialog) uses `large` spacing in its header and around the
|
|
52
52
|
edges to give itself a bit more prominence as a standalone view, in a similar
|
|
53
53
|
manner to [Page](/components/Page).
|
|
54
54
|
|
|
@@ -43,6 +43,35 @@ More complex full-page scaffolding can be found on the [Scaffolding](../scaffold
|
|
|
43
43
|
</Stack>
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
```tsx
|
|
47
|
+
<Stack>
|
|
48
|
+
<Heading level={2}>Stack Dialog Layouts</Heading>
|
|
49
|
+
<Text>Stacks are a great way to layout content in a dialog format. They are responsive and easy to read.</Text>
|
|
50
|
+
<Dialog>
|
|
51
|
+
<Dialog.Trigger>
|
|
52
|
+
<Button label="Open Dialog" />
|
|
53
|
+
</Dialog.Trigger>
|
|
54
|
+
<Dialog.Content>
|
|
55
|
+
<Dialog.Header>
|
|
56
|
+
<Dialog.Title>Dialog Layout</Dialog.Title>
|
|
57
|
+
<Dialog.Close />
|
|
58
|
+
</Dialog.Header>
|
|
59
|
+
<Dialog.Body>
|
|
60
|
+
<Stack>
|
|
61
|
+
<Text>A dialog with a header, body text, and footer</Text>
|
|
62
|
+
<Text>And they're all stacked vertically with equal spacing</Text>
|
|
63
|
+
</Stack>
|
|
64
|
+
</Dialog.Body>
|
|
65
|
+
<Dialog.Footer>
|
|
66
|
+
<Dialog.Actions
|
|
67
|
+
primary={<Dialog.Close render={<Button label="Close the Dialog" />} />}
|
|
68
|
+
/>
|
|
69
|
+
</Dialog.Footer>
|
|
70
|
+
</Dialog.Content>
|
|
71
|
+
</Dialog>
|
|
72
|
+
</Stack>
|
|
73
|
+
```
|
|
74
|
+
|
|
46
75
|
```tsx
|
|
47
76
|
<Stack>
|
|
48
77
|
<Heading level={1}>Cluster</Heading>
|
|
@@ -26,7 +26,7 @@ Most settings can be managed with the
|
|
|
26
26
|
[FeatureSwitch](../components/FeatureSwitch) component, which allows:
|
|
27
27
|
|
|
28
28
|
* turning functionality on and off
|
|
29
|
-
* editing aspects of the feature via a [
|
|
29
|
+
* editing aspects of the feature via a [Dialog](../components/Dialog)
|
|
30
30
|
* if the page supports it, live updates to the setting
|
|
31
31
|
|
|
32
32
|
### Grouping settings
|
|
@@ -37,7 +37,7 @@ Use a [Card](../Card/Card.md) to group related settings together.
|
|
|
37
37
|
|
|
38
38
|
The [FeatureSwitch](../components/FeatureSwitch) component is a good starting
|
|
39
39
|
point for most settings. If the setting is more complex, you can trigger a
|
|
40
|
-
[
|
|
40
|
+
[Dialog](../components/Dialog) to edit the setting.
|
|
41
41
|
|
|
42
42
|
For cases where you don't need the full functionality of the `FeatureSwitch`,
|
|
43
43
|
you can either opt out of props like `onSwitch` or `onEdit`, or compose a layout
|
|
@@ -49,7 +49,7 @@ of the pieces you do need.
|
|
|
49
49
|
|
|
50
50
|
* [FeatureSwitch](../components/FeatureSwitch)
|
|
51
51
|
* [Card](../Card/Card.md)
|
|
52
|
-
* [
|
|
52
|
+
* [Dialog](../components/Dialog)
|
|
53
53
|
* [Switch](../Switch/Switch.md)
|
|
54
54
|
|
|
55
55
|
## Principles
|