@boostdev/design-system-components 1.1.0 → 1.1.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/AGENTS.md +46 -5
- package/dist/client.cjs +206 -113
- package/dist/client.css +664 -624
- package/dist/client.d.cts +9 -3
- package/dist/client.d.ts +9 -3
- package/dist/client.js +241 -149
- package/dist/index.cjs +206 -113
- package/dist/index.css +664 -624
- package/dist/index.d.cts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +241 -149
- package/dist/web-components.d.ts +1 -0
- package/dist/web-components.js +10 -0
- package/package.json +1 -1
- package/src/components/interaction/Button/Button.module.css +1 -1
- package/src/components/interaction/Button/Button.native.mdx +72 -0
- package/src/components/interaction/Command/Command.module.css +7 -7
- package/src/components/interaction/Command/Command.spec.tsx +37 -0
- package/src/components/interaction/Command/Command.tsx +37 -2
- package/src/components/interaction/Dialog/Dialog.module.css +10 -13
- package/src/components/interaction/Dialog/Dialog.spec.tsx +53 -1
- package/src/components/interaction/Dialog/Dialog.stories.tsx +17 -0
- package/src/components/interaction/Dialog/Dialog.tsx +50 -16
- package/src/components/interaction/Drawer/Drawer.module.css +11 -11
- package/src/components/interaction/Drawer/Drawer.spec.tsx +48 -1
- package/src/components/interaction/Drawer/Drawer.tsx +38 -4
- package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +6 -6
- package/src/components/interaction/Popover/Popover.module.css +74 -15
- package/src/components/interaction/Popover/Popover.spec.tsx +94 -59
- package/src/components/interaction/Popover/Popover.tsx +44 -60
- package/src/components/interaction/Toast/Toast.module.css +7 -7
- package/src/components/interaction/form/Checkbox/Checkbox.module.css +6 -6
- package/src/components/interaction/form/Checkbox/Checkbox.native.mdx +74 -0
- package/src/components/interaction/form/Combobox/Combobox.module.css +7 -8
- package/src/components/interaction/form/FileInput/FileInput.module.css +4 -4
- package/src/components/interaction/form/NumberInput/NumberInput.module.css +1 -1
- package/src/components/interaction/form/Radio/Radio.module.css +6 -6
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +5 -6
- package/src/components/interaction/form/Select/Select.module.css +3 -3
- package/src/components/interaction/form/Slider/Slider.module.css +6 -6
- package/src/components/interaction/form/Switch/Switch.module.css +8 -8
- package/src/components/interaction/form/Textarea/Textarea.module.css +1 -1
- package/src/components/layout/IconWrapper/IconWrapper.module.css +2 -2
- package/src/components/ui/Accordion/Accordion.module.css +5 -5
- package/src/components/ui/Alert/Alert.native.mdx +62 -0
- package/src/components/ui/Avatar/Avatar.native.mdx +50 -0
- package/src/components/ui/Badge/Badge.native.mdx +54 -0
- package/src/components/ui/Calendar/Calendar.module.css +7 -7
- package/src/components/ui/Carousel/Carousel.module.css +5 -5
- package/src/components/ui/Collapsible/Collapsible.module.css +4 -4
- package/src/components/ui/Link/Link.module.css +2 -2
- package/src/components/ui/Loading/Loading.module.css +7 -7
- package/src/components/ui/NotificationBanner/NotificationBanner.module.css +3 -3
- package/src/components/ui/Pagination/Pagination.module.css +6 -6
- package/src/components/ui/Progress/Progress.module.css +5 -5
- package/src/components/ui/Separator/Separator.module.css +3 -3
- package/src/components/ui/Skeleton/Skeleton.module.css +1 -1
- package/src/components/ui/Table/Table.module.css +9 -9
- package/src/components/ui/Tabs/Tabs.module.css +3 -3
- package/src/components/ui/Tooltip/Tooltip.module.css +8 -8
- package/src/components/ui/Typography/Typography.native.mdx +56 -0
- package/src/polyfill-invoker-commands.ts +68 -0
- package/src/react-augment.d.ts +19 -0
- package/src/stories/ReactNative.mdx +121 -0
- package/src/web-components/interaction/BdsButton.mdx +106 -0
- package/src/web-components/interaction/BdsPopover.mdx +120 -0
- package/src/web-components/interaction/BdsToastProvider.mdx +94 -0
- package/src/web-components/interaction/bds-popover.spec.ts +49 -1
- package/src/web-components/interaction/bds-popover.ts +12 -0
- package/src/web-components/test/helpers.ts +8 -0
- package/src/web-components/ui/BdsAlert.mdx +90 -0
- package/src/web-components/ui/BdsBadge.mdx +74 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './Avatar.native.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# Avatar (React Native)
|
|
7
|
+
|
|
8
|
+
React Native avatar component displaying user initials on a coloured background. Derives initials from the `name` prop (first letter of each word, max 2).
|
|
9
|
+
|
|
10
|
+
> **Status: alpha** — API may change before stable release.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { Avatar } from '@boostdev/components';
|
|
16
|
+
|
|
17
|
+
<Avatar name="John Doe" size="medium" />
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### All sizes
|
|
23
|
+
<Canvas of={Stories.AllSizes} />
|
|
24
|
+
|
|
25
|
+
### With initials
|
|
26
|
+
<Canvas of={Stories.WithInitials} />
|
|
27
|
+
|
|
28
|
+
### Small
|
|
29
|
+
<Canvas of={Stories.Small} />
|
|
30
|
+
|
|
31
|
+
### Large
|
|
32
|
+
<Canvas of={Stories.Large} />
|
|
33
|
+
|
|
34
|
+
### Single name
|
|
35
|
+
<Canvas of={Stories.SingleName} />
|
|
36
|
+
|
|
37
|
+
## Props
|
|
38
|
+
|
|
39
|
+
<ArgTypes of={Stories} />
|
|
40
|
+
|
|
41
|
+
## Props reference
|
|
42
|
+
|
|
43
|
+
| Prop | Type | Default | Description |
|
|
44
|
+
|------|------|---------|-------------|
|
|
45
|
+
| `name` | string | — | Full name — initials are derived from this |
|
|
46
|
+
| `size` | `"small" \| "medium" \| "large"` | `"medium"` | Circle diameter |
|
|
47
|
+
|
|
48
|
+
## Accessibility
|
|
49
|
+
|
|
50
|
+
- `accessibilityLabel` defaults to the `name` prop so screen readers announce the user's name
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './Badge.native.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# Badge (React Native)
|
|
7
|
+
|
|
8
|
+
React Native badge component for short status labels and counts. Five semantic variants matching the web `Badge` API.
|
|
9
|
+
|
|
10
|
+
> **Status: alpha** — API may change before stable release.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { Badge } from '@boostdev/components';
|
|
16
|
+
|
|
17
|
+
<Badge variant="success">Active</Badge>
|
|
18
|
+
<Badge variant="error">3</Badge>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Examples
|
|
22
|
+
|
|
23
|
+
### All variants
|
|
24
|
+
<Canvas of={Stories.AllVariants} />
|
|
25
|
+
|
|
26
|
+
### Primary
|
|
27
|
+
<Canvas of={Stories.Primary} />
|
|
28
|
+
|
|
29
|
+
### Secondary
|
|
30
|
+
<Canvas of={Stories.Secondary} />
|
|
31
|
+
|
|
32
|
+
### Success
|
|
33
|
+
<Canvas of={Stories.Success} />
|
|
34
|
+
|
|
35
|
+
### Error
|
|
36
|
+
<Canvas of={Stories.Error} />
|
|
37
|
+
|
|
38
|
+
### Warning
|
|
39
|
+
<Canvas of={Stories.Warning} />
|
|
40
|
+
|
|
41
|
+
## Props
|
|
42
|
+
|
|
43
|
+
<ArgTypes of={Stories} />
|
|
44
|
+
|
|
45
|
+
## Props reference
|
|
46
|
+
|
|
47
|
+
| Prop | Type | Default | Description |
|
|
48
|
+
|------|------|---------|-------------|
|
|
49
|
+
| `variant` | `"primary" \| "secondary" \| "success" \| "error" \| "warning"` | `"primary"` | Semantic colour |
|
|
50
|
+
| `children` | `ReactNode` | — | Badge label |
|
|
51
|
+
|
|
52
|
+
## Accessibility
|
|
53
|
+
|
|
54
|
+
- Badge is decorative — wrap in a component with `accessibilityLabel` when colour alone conveys status (e.g. `accessibilityLabel="3 notifications"`)
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
border-radius: var(--calendar_radius, var(--bdc-outline_radius));
|
|
14
14
|
padding: var(--bds-space_m);
|
|
15
15
|
box-shadow: var(--calendar_shadow, var(--bds-shadow_s));
|
|
16
|
-
|
|
16
|
+
inline-size: 20rem;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
.header {
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
display: flex;
|
|
34
34
|
align-items: center;
|
|
35
35
|
justify-content: center;
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
inline-size: 2rem;
|
|
37
|
+
block-size: 2rem;
|
|
38
38
|
border-radius: 50%;
|
|
39
39
|
cursor: pointer;
|
|
40
40
|
color: var(--bds-color_on-bg);
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
.navBtn svg {
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
inline-size: 1rem;
|
|
46
|
+
block-size: 1rem;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
.navBtn:focus-visible {
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
|
|
60
60
|
.grid {
|
|
61
61
|
border-collapse: collapse;
|
|
62
|
-
|
|
62
|
+
inline-size: 100%;
|
|
63
63
|
table-layout: fixed;
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
display: flex;
|
|
81
81
|
align-items: center;
|
|
82
82
|
justify-content: center;
|
|
83
|
-
|
|
83
|
+
inline-size: 100%;
|
|
84
84
|
aspect-ratio: 1;
|
|
85
85
|
border-radius: 50%;
|
|
86
86
|
font-size: var(--bds-font_size--body--s);
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
.track {
|
|
10
10
|
display: flex;
|
|
11
11
|
gap: var(--bds-space_m);
|
|
12
|
-
overflow-
|
|
12
|
+
overflow-inline: auto;
|
|
13
13
|
scroll-snap-type: x mandatory;
|
|
14
14
|
scrollbar-width: none;
|
|
15
15
|
flex: 1;
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
display: flex;
|
|
31
31
|
align-items: center;
|
|
32
32
|
justify-content: center;
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
inline-size: 2.5rem;
|
|
34
|
+
block-size: 2.5rem;
|
|
35
35
|
border-radius: 50%;
|
|
36
36
|
background-color: var(--bds-color_bg);
|
|
37
37
|
color: var(--bds-color_on-bg);
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
.navBtn svg {
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
inline-size: 1.25rem;
|
|
52
|
+
block-size: 1.25rem;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
.navBtn:focus-visible {
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
|
|
49
49
|
/* Chevron drawn with CSS borders */
|
|
50
50
|
.icon {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
border-
|
|
54
|
-
border-
|
|
51
|
+
inline-size: 0.5rem;
|
|
52
|
+
block-size: 0.5rem;
|
|
53
|
+
border-inline-end: 2px solid currentcolor;
|
|
54
|
+
border-block-end: 2px solid currentcolor;
|
|
55
55
|
transform: rotate(45deg);
|
|
56
56
|
flex-shrink: 0;
|
|
57
57
|
transition: transform var(--bds-animation_transition-duration) var(--bds-animation_easing);
|
|
@@ -6,23 +6,23 @@
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
.spinner {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
inline-size: 2.5em;
|
|
10
|
+
block-size: 2.5em;
|
|
11
11
|
border: 4px solid var(--bds-color_bg);
|
|
12
|
-
border-
|
|
12
|
+
border-block-start: 4px solid var(--bds-color_interactive);
|
|
13
13
|
border-radius: 50%;
|
|
14
14
|
animation: spin 1s linear infinite;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
.--size_small .spinner {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
inline-size: 1.5em;
|
|
19
|
+
block-size: 1.5em;
|
|
20
20
|
border-width: 2px;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
.--size_large .spinner {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
inline-size: 4em;
|
|
25
|
+
block-size: 4em;
|
|
26
26
|
border-width: 6px;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
border-block-end: 3px solid var(--banner_border, var(--bds-color_blue));
|
|
10
10
|
font-size: var(--bds-font_size--body);
|
|
11
11
|
line-height: var(--bds-font_line-height--body);
|
|
12
|
-
|
|
12
|
+
inline-size: 100%;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
.--variant_info {
|
|
@@ -62,8 +62,8 @@
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
.dismiss svg {
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
inline-size: 1rem;
|
|
66
|
+
block-size: 1rem;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
.dismiss:focus-visible {
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
display: inline-flex;
|
|
19
19
|
align-items: center;
|
|
20
20
|
justify-content: center;
|
|
21
|
-
min-
|
|
22
|
-
|
|
21
|
+
min-inline-size: 2.25rem;
|
|
22
|
+
block-size: 2.25rem;
|
|
23
23
|
padding-inline: var(--bds-space_xs);
|
|
24
24
|
border-radius: var(--bds-border_radius--xs);
|
|
25
25
|
background-color: var(--btn_bg, transparent);
|
|
@@ -62,16 +62,16 @@
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
.button.--nav svg {
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
inline-size: 1rem;
|
|
66
|
+
block-size: 1rem;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
.ellipsis {
|
|
70
70
|
display: inline-flex;
|
|
71
71
|
align-items: center;
|
|
72
72
|
justify-content: center;
|
|
73
|
-
min-
|
|
74
|
-
|
|
73
|
+
min-inline-size: 2.25rem;
|
|
74
|
+
block-size: 2.25rem;
|
|
75
75
|
color: var(--bds-color_on-bg--subtle);
|
|
76
76
|
font-size: var(--bds-font_size--body);
|
|
77
77
|
user-select: none;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
display: flex;
|
|
4
4
|
flex-direction: column;
|
|
5
5
|
gap: var(--bds-space_xxs);
|
|
6
|
-
|
|
6
|
+
inline-size: 100%;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.labelRow {
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
.track {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
inline-size: 100%;
|
|
23
|
+
block-size: var(--progress_height, var(--bds-space_xs));
|
|
24
24
|
background-color: var(--bds-color_bg--subtle);
|
|
25
25
|
border-radius: 999px;
|
|
26
26
|
overflow: hidden;
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
.track.--size_large { --progress_height: var(--bds-space_s); }
|
|
32
32
|
|
|
33
33
|
.fill {
|
|
34
|
-
|
|
34
|
+
block-size: 100%;
|
|
35
35
|
background-color: var(--progress_color-active, var(--bdc-color_active));
|
|
36
36
|
border-radius: 999px;
|
|
37
|
-
transition:
|
|
37
|
+
transition: inline-size var(--bds-animation_transition-duration) var(--bds-animation_easing);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
|
|
7
7
|
.separator.--horizontal {
|
|
8
8
|
display: block;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
inline-size: 100%;
|
|
10
|
+
block-size: var(--separator_thickness, 1px);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.separator.--vertical {
|
|
14
14
|
display: inline-block;
|
|
15
|
-
|
|
15
|
+
inline-size: var(--separator_thickness, 1px);
|
|
16
16
|
align-self: stretch;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@layer component {
|
|
2
2
|
.wrapper {
|
|
3
|
-
|
|
4
|
-
overflow-
|
|
3
|
+
inline-size: 100%;
|
|
4
|
+
overflow-inline: auto;
|
|
5
5
|
border: var(--table_border, none);
|
|
6
6
|
--bdc_color: var(--bds-color_bg--subtle);
|
|
7
7
|
--bdc-outline_radius: var(--bds-border_radius--s);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
.table {
|
|
15
|
-
|
|
15
|
+
inline-size: 100%;
|
|
16
16
|
border-collapse: collapse;
|
|
17
17
|
font-size: var(--bds-font_size--body);
|
|
18
18
|
font-family: var(--bds-font_family--body);
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
font-size: var(--bds-font_size--body--s);
|
|
38
38
|
color: var(--bds-color_on-bg--subtle);
|
|
39
39
|
white-space: nowrap;
|
|
40
|
-
border-
|
|
40
|
+
border-block-end: 1px solid var(--bds-color_bg--subtle);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
.th.--sortable {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
align-items: center;
|
|
51
51
|
gap: var(--bds-space_xxs);
|
|
52
52
|
padding: var(--bds-space_s) var(--bds-space_m);
|
|
53
|
-
|
|
53
|
+
inline-size: 100%;
|
|
54
54
|
cursor: pointer;
|
|
55
55
|
color: var(--bds-color_on-bg--subtle);
|
|
56
56
|
font-weight: var(--bds-font_weight--semibold);
|
|
@@ -71,8 +71,8 @@
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
.sortIcon {
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
inline-size: 1rem;
|
|
75
|
+
block-size: 1rem;
|
|
76
76
|
opacity: 0.4;
|
|
77
77
|
transition: transform var(--bds-animation_transition-duration) var(--bds-animation_easing),
|
|
78
78
|
opacity var(--bds-animation_transition-duration) var(--bds-animation_easing);
|
|
@@ -88,12 +88,12 @@
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
.tbody .tr {
|
|
91
|
-
border-
|
|
91
|
+
border-block-end: 1px solid var(--bds-color_bg--subtle);
|
|
92
92
|
transition: var(--bds-animation_transition);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
.tbody .tr:last-child {
|
|
96
|
-
border-
|
|
96
|
+
border-block-end: none;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
@media (hover: hover) and (pointer: fine) {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
.tabList {
|
|
8
8
|
display: flex;
|
|
9
|
-
border-
|
|
9
|
+
border-block-end: 1px solid var(--bds-color_bg--subtle);
|
|
10
10
|
gap: var(--bds-space_xxs);
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
font-size: var(--bds-font_size--body);
|
|
20
20
|
font-weight: var(--bds-font_weight--semibold);
|
|
21
21
|
color: var(--tab_color, var(--bds-color_on-bg));
|
|
22
|
-
border-
|
|
23
|
-
margin-
|
|
22
|
+
border-block-end: 2px solid var(--tab_border-color, transparent);
|
|
23
|
+
margin-block-end: -1px;
|
|
24
24
|
cursor: pointer;
|
|
25
25
|
transition: var(--bds-animation_transition);
|
|
26
26
|
}
|
|
@@ -32,29 +32,29 @@
|
|
|
32
32
|
|
|
33
33
|
/* Placement: top (default) */
|
|
34
34
|
.--placement_top {
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
inset-block-end: calc(100% + var(--bds-space_xs));
|
|
36
|
+
inset-inline-start: 50%;
|
|
37
37
|
transform: translateX(-50%);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/* Placement: bottom */
|
|
41
41
|
.--placement_bottom {
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
inset-block-start: calc(100% + var(--bds-space_xs));
|
|
43
|
+
inset-inline-start: 50%;
|
|
44
44
|
transform: translateX(-50%);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/* Placement: left */
|
|
48
48
|
.--placement_left {
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
inset-inline-end: calc(100% + var(--bds-space_xs));
|
|
50
|
+
inset-block-start: 50%;
|
|
51
51
|
transform: translateY(-50%);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/* Placement: right */
|
|
55
55
|
.--placement_right {
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
inset-inline-start: calc(100% + var(--bds-space_xs));
|
|
57
|
+
inset-block-start: 50%;
|
|
58
58
|
transform: translateY(-50%);
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './Typography.native.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# Typography (React Native)
|
|
7
|
+
|
|
8
|
+
React Native typography component wrapping `Text` with semantic variants. Use instead of bare `<Text>` to ensure consistent sizing, weight, and line-height from the design token scale.
|
|
9
|
+
|
|
10
|
+
> **Status: alpha** — API may change before stable release.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { Typography } from '@boostdev/components';
|
|
16
|
+
|
|
17
|
+
<Typography variant="h1">Page title</Typography>
|
|
18
|
+
<Typography variant="body">Body copy text.</Typography>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Examples
|
|
22
|
+
|
|
23
|
+
### All variants
|
|
24
|
+
<Canvas of={Stories.AllVariants} />
|
|
25
|
+
|
|
26
|
+
### Heading 1
|
|
27
|
+
<Canvas of={Stories.Heading1} />
|
|
28
|
+
|
|
29
|
+
### Heading 2
|
|
30
|
+
<Canvas of={Stories.Heading2} />
|
|
31
|
+
|
|
32
|
+
### Heading 3
|
|
33
|
+
<Canvas of={Stories.Heading3} />
|
|
34
|
+
|
|
35
|
+
### Body
|
|
36
|
+
<Canvas of={Stories.Body} />
|
|
37
|
+
|
|
38
|
+
### Body small
|
|
39
|
+
<Canvas of={Stories.BodySmall} />
|
|
40
|
+
|
|
41
|
+
## Props
|
|
42
|
+
|
|
43
|
+
<ArgTypes of={Stories} />
|
|
44
|
+
|
|
45
|
+
## Props reference
|
|
46
|
+
|
|
47
|
+
| Prop | Type | Default | Description |
|
|
48
|
+
|------|------|---------|-------------|
|
|
49
|
+
| `variant` | `"h1" \| "h2" \| "h3" \| "body" \| "body_s"` | `"body"` | Typographic scale |
|
|
50
|
+
| `children` | `ReactNode` | — | Text content |
|
|
51
|
+
| `style` | `StyleProp<TextStyle>` | — | Override text styles |
|
|
52
|
+
|
|
53
|
+
## Accessibility
|
|
54
|
+
|
|
55
|
+
- `h1`/`h2`/`h3` variants set `accessibilityRole="header"` automatically
|
|
56
|
+
- Override with the `accessibilityRole` prop if the visual hierarchy doesn't match the semantic hierarchy
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invoker Commands API polyfill (Baseline 2025).
|
|
3
|
+
*
|
|
4
|
+
* Handles `commandfor` / `command` attributes on <button> elements for browsers
|
|
5
|
+
* that don't yet support the native API. Dispatches a synthetic `command` event
|
|
6
|
+
* on the target element before performing the action — identical to native
|
|
7
|
+
* behaviour — so any existing `command` event listeners continue to work.
|
|
8
|
+
*
|
|
9
|
+
* Supports the dialog-specific commands used by this library:
|
|
10
|
+
* command="show-modal" → dialog.showModal()
|
|
11
|
+
* command="close" → dialog.close()
|
|
12
|
+
*
|
|
13
|
+
* Installation is idempotent and SSR-safe. The function is called automatically
|
|
14
|
+
* when the Dialog component is imported; consumers do not need to call it.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
let installed = false;
|
|
18
|
+
|
|
19
|
+
export function installInvokerCommandsPolyfill(): void {
|
|
20
|
+
if (installed) return;
|
|
21
|
+
if (typeof window === 'undefined') return;
|
|
22
|
+
if ('command' in HTMLButtonElement.prototype) return; // native support present
|
|
23
|
+
|
|
24
|
+
installed = true;
|
|
25
|
+
|
|
26
|
+
document.addEventListener('click', (e: MouseEvent) => {
|
|
27
|
+
const button = (e.target as Element | null)?.closest<HTMLButtonElement>('button[commandfor]');
|
|
28
|
+
if (!button) return;
|
|
29
|
+
|
|
30
|
+
const targetId = button.getAttribute('commandfor');
|
|
31
|
+
const command = button.getAttribute('command');
|
|
32
|
+
if (!targetId || !command) return;
|
|
33
|
+
|
|
34
|
+
const target = document.getElementById(targetId);
|
|
35
|
+
if (!target) return;
|
|
36
|
+
|
|
37
|
+
// Dispatch a synthetic command event that mirrors the native CommandEvent.
|
|
38
|
+
const commandEvent = new Event('command', { cancelable: true, bubbles: false });
|
|
39
|
+
Object.defineProperty(commandEvent, 'command', { value: command, configurable: true });
|
|
40
|
+
Object.defineProperty(commandEvent, 'source', { value: button, configurable: true });
|
|
41
|
+
const notCancelled = target.dispatchEvent(commandEvent);
|
|
42
|
+
|
|
43
|
+
if (!notCancelled) return;
|
|
44
|
+
|
|
45
|
+
if (target instanceof HTMLDialogElement) {
|
|
46
|
+
if (command === 'show-modal' && !target.open) {
|
|
47
|
+
target.showModal();
|
|
48
|
+
} else if (command === 'close' && target.open) {
|
|
49
|
+
target.close();
|
|
50
|
+
}
|
|
51
|
+
} else if (target.hasAttribute('popover') && 'showPopover' in target) {
|
|
52
|
+
// Popover API commands — Popover API is Baseline 2024 so showPopover exists
|
|
53
|
+
// in any browser that lacks native invoker command support.
|
|
54
|
+
const popover = target as HTMLElement & {
|
|
55
|
+
showPopover(): void;
|
|
56
|
+
hidePopover(): void;
|
|
57
|
+
togglePopover(force?: boolean): boolean;
|
|
58
|
+
};
|
|
59
|
+
if (command === 'toggle-popover') {
|
|
60
|
+
popover.togglePopover();
|
|
61
|
+
} else if (command === 'show-popover') {
|
|
62
|
+
popover.showPopover();
|
|
63
|
+
} else if (command === 'hide-popover') {
|
|
64
|
+
popover.hidePopover();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
package/src/react-augment.d.ts
CHANGED
|
@@ -10,4 +10,23 @@ declare module 'react' {
|
|
|
10
10
|
anchorName?: string;
|
|
11
11
|
positionAnchor?: string;
|
|
12
12
|
}
|
|
13
|
+
|
|
14
|
+
// Invoker Commands API (Baseline 2025) — not yet in @types/react.
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
16
|
+
interface ButtonHTMLAttributes<T> {
|
|
17
|
+
commandfor?: string;
|
|
18
|
+
command?: string;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// CommandEvent and its entry in the DOM event map — not yet in TypeScript's lib.dom.
|
|
23
|
+
declare global {
|
|
24
|
+
interface CommandEvent extends Event {
|
|
25
|
+
readonly command: string;
|
|
26
|
+
readonly source: Element;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface HTMLElementEventMap {
|
|
30
|
+
command: CommandEvent;
|
|
31
|
+
}
|
|
13
32
|
}
|