@bspk/ui 1.3.18 → 1.3.20

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.
Files changed (107) hide show
  1. package/dist/components/Accordion/AccordionExample.js +1 -1
  2. package/dist/components/Accordion/AccordionExample.js.map +1 -1
  3. package/dist/components/BannerAlert/BannerAlert.js +1 -1
  4. package/dist/components/BannerAlert/BannerAlert.js.map +1 -1
  5. package/dist/components/BannerAlert/banner-alert.css +3 -3
  6. package/dist/components/BannerAlert/banner-alert.css.js +3 -3
  7. package/dist/components/CheckboxOption/CheckboxOption.d.ts +15 -3
  8. package/dist/components/CheckboxOption/CheckboxOption.js +2 -3
  9. package/dist/components/CheckboxOption/CheckboxOption.js.map +1 -1
  10. package/dist/components/Dialog/Dialog.d.ts +17 -7
  11. package/dist/components/Dialog/Dialog.js +19 -11
  12. package/dist/components/Dialog/Dialog.js.map +1 -1
  13. package/dist/components/Dialog/DialogExample.d.ts +2 -2
  14. package/dist/components/Dialog/DialogExample.js +32 -3
  15. package/dist/components/Dialog/DialogExample.js.map +1 -1
  16. package/dist/components/Dialog/dialog.css +74 -4
  17. package/dist/components/Dialog/dialog.css.js +74 -4
  18. package/dist/components/Flex/Flex.d.ts +2 -0
  19. package/dist/components/Flex/Flex.js +1 -0
  20. package/dist/components/Flex/Flex.js.map +1 -1
  21. package/dist/components/ListItem/list-item.css +4 -0
  22. package/dist/components/ListItem/list-item.css.js +4 -0
  23. package/dist/components/Modal/Modal.js +1 -2
  24. package/dist/components/Modal/Modal.js.map +1 -1
  25. package/dist/components/Modal/modal.css +4 -0
  26. package/dist/components/Modal/modal.css.js +4 -0
  27. package/dist/components/PageHeader/PageHeader.d.ts +1 -1
  28. package/dist/components/PageHeader/PageHeader.js +1 -1
  29. package/dist/components/PageHeader/PageHeaderBlockConfigs.d.ts +1 -0
  30. package/dist/components/PageHeader/PageHeaderBlockConfigs.js +32 -0
  31. package/dist/components/PageHeader/PageHeaderBlockConfigs.js.map +1 -0
  32. package/dist/components/PageHeader/PageHeaderExample.d.ts +3 -2
  33. package/dist/components/PageHeader/PageHeaderExample.js +4 -42
  34. package/dist/components/PageHeader/PageHeaderExample.js.map +1 -1
  35. package/dist/components/PageHeader/page-header.css +1 -1
  36. package/dist/components/PageHeader/page-header.css.js +1 -1
  37. package/dist/components/Portal/Portal.d.ts +1 -1
  38. package/dist/components/RadioOption/RadioOption.d.ts +7 -3
  39. package/dist/components/RadioOption/RadioOption.js +2 -3
  40. package/dist/components/RadioOption/RadioOption.js.map +1 -1
  41. package/dist/components/Scrim/Scrim.d.ts +3 -1
  42. package/dist/components/Scrim/Scrim.js +2 -2
  43. package/dist/components/Scrim/Scrim.js.map +1 -1
  44. package/dist/components/Scrim/scrim.css +3 -0
  45. package/dist/components/Scrim/scrim.css.js +3 -0
  46. package/dist/components/Switch/Switch.d.ts +1 -1
  47. package/dist/components/SwitchOption/SwitchOption.d.ts +16 -3
  48. package/dist/components/SwitchOption/SwitchOption.js +3 -4
  49. package/dist/components/SwitchOption/SwitchOption.js.map +1 -1
  50. package/dist/components/Tag/Tag.d.ts +2 -1
  51. package/dist/components/Tag/Tag.js +2 -2
  52. package/dist/components/Tag/Tag.js.map +1 -1
  53. package/dist/styles/base.css +0 -42
  54. package/dist/styles/base.css.js +0 -42
  55. package/dist/types/meta.d.ts +6 -0
  56. package/dist/types/meta.js.map +1 -1
  57. package/dist/utils/blocks.d.ts +32 -0
  58. package/dist/utils/blocks.js +21 -0
  59. package/dist/utils/blocks.js.map +1 -0
  60. package/dist/utils/demo.d.ts +33 -9
  61. package/dist/utils/demo.js +98 -0
  62. package/dist/utils/demo.js.map +1 -1
  63. package/meta.ts +39 -1
  64. package/package.json +1 -3
  65. package/src/components/Accordion/AccordionExample.tsx +1 -1
  66. package/src/components/BannerAlert/BannerAlert.tsx +2 -2
  67. package/src/components/BannerAlert/banner-alert.scss +1 -1
  68. package/src/components/CheckboxOption/CheckboxOption.tsx +26 -14
  69. package/src/components/Dialog/Dialog.tsx +20 -10
  70. package/src/components/Dialog/DialogExample.tsx +104 -6
  71. package/src/components/Dialog/dialog.scss +91 -4
  72. package/src/components/Flex/Flex.tsx +3 -0
  73. package/src/components/ListItem/list-item.scss +4 -0
  74. package/src/components/Modal/Modal.tsx +1 -4
  75. package/src/components/Modal/modal.scss +5 -0
  76. package/src/components/PageHeader/PageHeader.rtl.test.tsx +8 -5
  77. package/src/components/PageHeader/PageHeader.tsx +1 -1
  78. package/src/components/PageHeader/PageHeaderBlockConfigs.tsx +152 -0
  79. package/src/components/PageHeader/PageHeaderExample.tsx +6 -44
  80. package/src/components/PageHeader/page-header.scss +1 -1
  81. package/src/components/Portal/Portal.tsx +1 -1
  82. package/src/components/RadioOption/RadioOption.tsx +16 -8
  83. package/src/components/Scrim/Scrim.tsx +4 -1
  84. package/src/components/Scrim/scrim.scss +4 -0
  85. package/src/components/Switch/Switch.tsx +1 -1
  86. package/src/components/SwitchOption/SwitchOption.tsx +28 -9
  87. package/src/components/Tag/Tag.tsx +9 -2
  88. package/src/styles/base.scss +0 -52
  89. package/src/types/meta.ts +7 -0
  90. package/src/utils/blocks.ts +26 -0
  91. package/src/utils/demo.ts +141 -18
  92. package/dist/components/Drawer/Drawer.d.ts +0 -73
  93. package/dist/components/Drawer/Drawer.js +0 -46
  94. package/dist/components/Drawer/Drawer.js.map +0 -1
  95. package/dist/components/Drawer/DrawerExample.d.ts +0 -5
  96. package/dist/components/Drawer/DrawerExample.js +0 -53
  97. package/dist/components/Drawer/DrawerExample.js.map +0 -1
  98. package/dist/components/Drawer/drawer.css +0 -62
  99. package/dist/components/Drawer/drawer.css.js +0 -67
  100. package/dist/components/Drawer/index.d.ts +0 -1
  101. package/dist/components/Drawer/index.js +0 -2
  102. package/dist/components/Drawer/index.js.map +0 -1
  103. package/src/components/Drawer/Drawer.rtl.test.tsx +0 -27
  104. package/src/components/Drawer/Drawer.tsx +0 -127
  105. package/src/components/Drawer/DrawerExample.tsx +0 -117
  106. package/src/components/Drawer/drawer.scss +0 -74
  107. package/src/components/Drawer/index.tsx +0 -1
@@ -5,20 +5,24 @@
5
5
  display: flex;
6
6
  pointer-events: none; // makes scrim clickable
7
7
 
8
+ --height: 100vh;
9
+ --width: 100vw;
10
+
8
11
  [data-dialog-box] {
9
12
  pointer-events: all; // allow pointer events on the dialog box
10
13
  text-align: start;
11
- position: relative;
14
+ position: absolute;
12
15
  box-shadow: var(--drop-shadow-float);
13
16
  background: var(--surface-neutral-t1-base);
14
17
  color: var(--foreground-neutral-on-surface);
15
- max-height: calc(100vh - var(--spacing-sizing-24));
18
+ max-height: calc(var(--height) - var(--spacing-sizing-24));
16
19
  z-index: 2;
17
20
  width: calc(100% - var(--spacing-sizing-08));
18
21
  animation-name: var(--box-animation-name);
19
22
  animation-duration: 0.5s;
20
23
  animation-iteration-count: 1;
21
24
  animation-fill-mode: forwards;
25
+ animation-delay: 0;
22
26
 
23
27
  > :first-of-type {
24
28
  margin-top: 0;
@@ -89,7 +93,7 @@
89
93
  [data-dialog-box] {
90
94
  max-height: unset;
91
95
  width: 280px;
92
- height: 100vh;
96
+ height: var(--height);
93
97
  border-bottom-right-radius: var(--radius-lg);
94
98
  border-top-right-radius: var(--radius-lg);
95
99
  }
@@ -103,7 +107,7 @@
103
107
  [data-dialog-box] {
104
108
  max-height: unset;
105
109
  width: 280px;
106
- height: 100vh;
110
+ height: var(--height);
107
111
  border-bottom-left-radius: var(--radius-lg);
108
112
  border-top-left-radius: var(--radius-lg);
109
113
  }
@@ -112,6 +116,89 @@
112
116
  [data-width-full='true'] {
113
117
  width: 100%;
114
118
  }
119
+
120
+ &[data-contained] {
121
+ position: absolute;
122
+
123
+ --height: 100%;
124
+ --width: 100%;
125
+ }
126
+
127
+ @keyframes fade-in {
128
+ 0% {
129
+ opacity: 0;
130
+ transform: translate(var(--spacing-sizing-01), var(--spacing-sizing-01));
131
+ }
132
+
133
+ 100% {
134
+ opacity: 1;
135
+ transform: translate(0, 0);
136
+ }
137
+ }
138
+
139
+ @keyframes placement-left {
140
+ 0% {
141
+ opacity: 0;
142
+ }
143
+
144
+ 1% {
145
+ transform: translateX(calc(-1 * var(--width, 100vw)));
146
+ opacity: 1;
147
+ }
148
+
149
+ 100% {
150
+ opacity: 1;
151
+ transform: translateX(0);
152
+ }
153
+ }
154
+
155
+ @keyframes placement-right {
156
+ 0% {
157
+ opacity: 0;
158
+ }
159
+
160
+ 1% {
161
+ opacity: 1;
162
+ transform: translateX(var(--width, 100vw));
163
+ }
164
+
165
+ 100% {
166
+ opacity: 1;
167
+ transform: translateX(0);
168
+ }
169
+ }
170
+
171
+ @keyframes placement-top {
172
+ 0% {
173
+ opacity: 0;
174
+ }
175
+
176
+ 1% {
177
+ opacity: 1;
178
+ transform: translateY(calc(-1 * var(--height, 100vh)));
179
+ }
180
+
181
+ 100% {
182
+ opacity: 1;
183
+ transform: translateY(0);
184
+ }
185
+ }
186
+
187
+ @keyframes placement-bottom {
188
+ 0% {
189
+ opacity: 0;
190
+ }
191
+
192
+ 1% {
193
+ opacity: 1;
194
+ transform: translateY(var(--height, 100vh));
195
+ }
196
+
197
+ 100% {
198
+ opacity: 1;
199
+ transform: translateY(0);
200
+ }
201
+ }
115
202
  }
116
203
 
117
204
  /** Copyright 2025 Anywhere Real Estate - CC BY 4.0 */
@@ -36,6 +36,8 @@ export type FlexProps<As extends ElementType = ElementType> = {
36
36
  direction?: 'column-reverse' | 'column' | 'row-reverse' | 'row';
37
37
  /** The padding to apply to the Flex. */
38
38
  padding?: SizingPixels | SizingPixels[];
39
+ /** If true the Flex will take up the full width of its container. */
40
+ full?: boolean;
39
41
  };
40
42
 
41
43
  /**
@@ -83,6 +85,7 @@ export function Flex<As extends ElementType = ElementType>({
83
85
  justifyContent: justify || 'flex-start',
84
86
  flexWrap: wrap ? 'wrap' : 'nowrap',
85
87
  padding: paddingValue,
88
+ width: props.full ? '100%' : undefined,
86
89
  ...style,
87
90
  }}
88
91
  >
@@ -67,6 +67,10 @@
67
67
  [data-trailing] {
68
68
  width: fit-content;
69
69
  flex: 0 0 auto;
70
+
71
+ &:empty {
72
+ display: none;
73
+ }
70
74
  }
71
75
 
72
76
  [data-item-label] {
@@ -3,7 +3,6 @@ import { SvgClose } from '@bspk/icons/Close';
3
3
  import { ReactNode, useMemo, useRef } from 'react';
4
4
  import { Button, ButtonProps } from '-/components/Button';
5
5
  import { DialogProps, Dialog } from '-/components/Dialog';
6
- import { Txt } from '-/components/Txt';
7
6
  import { useDebounceCallback } from '-/hooks/useDebounceCallback';
8
7
  import { useEventListener } from '-/hooks/useEventListener';
9
8
  import { useUIContext } from '-/hooks/useUIContext';
@@ -183,9 +182,7 @@ export function Modal({
183
182
  >
184
183
  <div data-bspk="modal" ref={(node) => innerRef?.(node)} style={{ visibility: 'hidden' }}>
185
184
  <div data-modal-header>
186
- <Txt as="div" data-dialog-title variant="heading-h4">
187
- {header}
188
- </Txt>
185
+ <div data-modal-title>{header}</div>
189
186
  <Button
190
187
  icon={<SvgClose />}
191
188
  iconOnly
@@ -15,6 +15,11 @@
15
15
  justify-content: space-between;
16
16
  align-items: center;
17
17
  gap: var(--spacing-sizing-04);
18
+
19
+ [data-modal-title] {
20
+ font: var(--heading-h4);
21
+ flex: 1;
22
+ }
18
23
  }
19
24
 
20
25
  [data-modal-main] {
@@ -1,15 +1,18 @@
1
1
  import { PageHeader } from './PageHeader';
2
- import { presets } from './PageHeaderExample';
2
+ import { PageHeaderExample } from './PageHeaderExample';
3
3
  import { hasNoBasicA11yIssues } from '-/rtl/hasNoBasicA11yIssues';
4
4
  import { render } from '-/rtl/util';
5
5
 
6
+ const props = {
7
+ ...PageHeaderExample.defaultState,
8
+ title: 'Page Title',
9
+ };
10
+
6
11
  describe('PageHeader (RTL)', () => {
7
- presets.forEach((preset) => {
8
- it(`has no basic a11y issues - ${preset.label}`, hasNoBasicA11yIssues(<PageHeader {...preset.propState} />));
9
- });
12
+ it(`has no basic a11y issues`, hasNoBasicA11yIssues(<PageHeader {...props} />));
10
13
 
11
14
  it('renders', () => {
12
- const { getByText } = render(<PageHeader {...presets[0].propState} />);
15
+ const { getByText } = render(<PageHeader {...props} />);
13
16
 
14
17
  expect(getByText('Page Title')).toBeInTheDocument();
15
18
  });
@@ -53,7 +53,7 @@ export type PageHeaderProps = {
53
53
  * />;
54
54
  *
55
55
  * @name PageHeader
56
- * @phase Dev
56
+ * @phase UXReview
57
57
  */
58
58
  export function PageHeader({ actions, breadcrumb, avatar, subHeader, title }: PageHeaderProps) {
59
59
  return (
@@ -0,0 +1,152 @@
1
+ import { PageHeader } from './PageHeader';
2
+ import { Avatar } from '-/components/Avatar';
3
+ import { Breadcrumb } from '-/components/Breadcrumb';
4
+ import { Flex } from '-/components/Flex';
5
+ import { Txt } from '-/components/Txt';
6
+ import { BlockExample, Slot } from '-/utils/blocks';
7
+
8
+ export const blockConfigs = (
9
+ <>
10
+ <BlockExample name="Slots">
11
+ <BlockExample.Component>
12
+ <PageHeader
13
+ actions={<Slot height={32} label="Page actions slot" width={372} />}
14
+ subHeader={
15
+ <>
16
+ <Slot height="var(--spacing-sizing-06)" label="Slot component" width={200} />
17
+ <Slot height="var(--spacing-sizing-06)" label="Slot component 2" width={200} />
18
+ </>
19
+ }
20
+ title="Dashboard"
21
+ />
22
+ </BlockExample.Component>
23
+ <BlockExample.Pattern>
24
+ <Flex
25
+ direction="column"
26
+ padding={['20', '20', '0']}
27
+ style={{
28
+ background: 'var(--background-base)',
29
+ width: '100%',
30
+ }}
31
+ >
32
+ <Flex align="center" data-header gap="20" justify="space-between" style={{ width: '100%' }}>
33
+ <Txt variant="heading-h3">Dashboard</Txt>
34
+ <div
35
+ data-page-actions-slot
36
+ style={{
37
+ height: 'var(--spacing-sizing-08)',
38
+ width: 'auto',
39
+ }}
40
+ >
41
+ <Slot height="100%" label="Page actions slot" width={372} />
42
+ </div>
43
+ </Flex>
44
+ <Flex
45
+ align="end"
46
+ data-subheader
47
+ justify="space-between"
48
+ style={{ height: 'var(--spacing-sizing-11)', width: '100%' }}
49
+ >
50
+ <Slot height="var(--spacing-sizing-06)" label="Slot component" width={200} />
51
+ <Slot height="var(--spacing-sizing-06)" label="Slot component 2" width={200} />
52
+ </Flex>
53
+ </Flex>
54
+ </BlockExample.Pattern>
55
+ </BlockExample>
56
+ <BlockExample name="No Subheader">
57
+ <BlockExample.Component>
58
+ <PageHeader actions={<Slot height={32} label="Page actions slot" width={372} />} title="Dashboard" />
59
+ </BlockExample.Component>
60
+ <BlockExample.Pattern>
61
+ <Flex
62
+ align="center"
63
+ data-header
64
+ gap="20"
65
+ justify="space-between"
66
+ style={{
67
+ background: 'var(--background-base)',
68
+ padding: 'var(--spacing-sizing-05)',
69
+ width: '100%',
70
+ }}
71
+ >
72
+ <Txt variant="heading-h3">Dashboard</Txt>
73
+ <div data-page-actions-slot style={{ height: 'var(--spacing-sizing-08)', width: 'auto' }}>
74
+ <Slot height="100%" label="Page actions slot" width={372} />
75
+ </div>
76
+ </Flex>
77
+ </BlockExample.Pattern>
78
+ </BlockExample>
79
+ <BlockExample name="With Breadcrumbs">
80
+ <BlockExample.Component>
81
+ <PageHeader
82
+ actions={<Slot height={32} label="Page actions slot" width={372} />}
83
+ breadcrumb={{
84
+ items: [
85
+ { label: 'Home', href: '#' },
86
+ { label: 'Analytics', href: '#' },
87
+ { label: 'Dashboard', href: '#' },
88
+ ],
89
+ }}
90
+ title="Dashboard"
91
+ />
92
+ </BlockExample.Component>
93
+ <BlockExample.Pattern>
94
+ <Flex direction="column" style={{ background: 'var(--background-base)', width: '100%' }}>
95
+ <div style={{ padding: 'var(--spacing-sizing-05) var(--spacing-sizing-05) 0' }}>
96
+ <Breadcrumb
97
+ items={[
98
+ { label: 'Home', href: '#' },
99
+ { label: 'Analytics', href: '#' },
100
+ { label: 'Dashboard', href: '#' },
101
+ ]}
102
+ />
103
+ </div>
104
+ <Flex
105
+ align="center"
106
+ data-header
107
+ gap="20"
108
+ justify="space-between"
109
+ padding="20"
110
+ style={{ width: '100%' }}
111
+ >
112
+ <Txt variant="heading-h3">Dashboard</Txt>
113
+ <div data-page-actions-slot style={{ height: 'var(--spacing-sizing-08)', width: 'auto' }}>
114
+ <Slot height="100%" label="Page actions slot" width={372} />
115
+ </div>
116
+ </Flex>
117
+ </Flex>
118
+ ;
119
+ </BlockExample.Pattern>
120
+ </BlockExample>
121
+ <BlockExample name="Profile">
122
+ <BlockExample.Component>
123
+ <PageHeader
124
+ actions={<Slot height={32} label="Page actions slot" width={372} />}
125
+ avatar={{
126
+ name: 'Brian Blake',
127
+ size: 'xx-large',
128
+ }}
129
+ title="Dashboard"
130
+ />
131
+ </BlockExample.Component>
132
+ <BlockExample.Pattern>
133
+ <Flex
134
+ align="center"
135
+ data-header
136
+ gap="20"
137
+ justify="space-between"
138
+ padding="20"
139
+ style={{ background: 'var(--background-base)', width: '100%' }}
140
+ >
141
+ <Flex align="center" gap="16">
142
+ <Avatar name="Brian Blake" size="xx-large" />
143
+ <Txt variant="heading-h3">Dashboard</Txt>
144
+ </Flex>
145
+ <div data-page-actions-slot style={{ height: 'var(--spacing-sizing-08)', width: 'auto' }}>
146
+ <Slot height="100%" label="Page actions slot" width={372} />
147
+ </div>
148
+ </Flex>
149
+ </BlockExample.Pattern>
150
+ </BlockExample>
151
+ </>
152
+ );
@@ -1,48 +1,7 @@
1
+ import { blockConfigs } from './PageHeaderBlockConfigs';
1
2
  import { PageHeaderProps } from '.';
2
3
  import { ExamplePlaceholder } from '-/components/ExamplePlaceholder';
3
- import { ComponentExample, Preset } from '-/utils/demo';
4
-
5
- export const presets: Preset<PageHeaderProps>[] = [
6
- {
7
- label: 'Title Only',
8
- propState: {
9
- title: 'Page Title',
10
- },
11
- designPattern: true,
12
- },
13
- {
14
- label: 'With Actions',
15
- propState: {
16
- title: 'Page Title',
17
- actions: <ExamplePlaceholder height={32} label="Page actions slot" width={372} />,
18
- },
19
- designPattern: true,
20
- },
21
- {
22
- label: 'With Breadcrumb',
23
- propState: {
24
- title: 'Page Title',
25
- breadcrumb: {
26
- items: [
27
- { label: 'Home', href: '#/home' },
28
- { label: 'Section', href: '#/section' },
29
- { label: 'Page Title', href: '#/page' },
30
- ],
31
- },
32
- actions: <ExamplePlaceholder height={32} label="Page actions slot" width={372} />,
33
- },
34
- designPattern: true,
35
- },
36
- {
37
- label: 'Profile',
38
- propState: {
39
- title: 'Charlie Brown',
40
- avatar: { image: '/avatar-01.png', name: 'CB' },
41
- actions: <ExamplePlaceholder height={32} label="Page actions slot" width={372} />,
42
- },
43
- designPattern: true,
44
- },
45
- ];
4
+ import { ComponentExample } from '-/utils/demo';
46
5
 
47
6
  export const PageHeaderExample: ComponentExample<PageHeaderProps> = {
48
7
  defaultState: {
@@ -50,9 +9,12 @@ export const PageHeaderExample: ComponentExample<PageHeaderProps> = {
50
9
  actions: <ExamplePlaceholder height={32} label="Page actions slot" width={372} />,
51
10
  },
52
11
  disableProps: [],
53
- presets,
54
12
  render: ({ props, Component }) => <Component {...props} />,
55
13
  variants: false,
56
14
  fullPage: true,
57
15
  hideDemo: true,
16
+ hideUsage: true,
17
+ presets: [],
58
18
  };
19
+
20
+ export { blockConfigs };
@@ -17,7 +17,7 @@
17
17
  [data-title] {
18
18
  display: flex;
19
19
  align-items: center;
20
- gap: var(--spacing-sizing-03);
20
+ gap: var(--spacing-sizing-04);
21
21
 
22
22
  h1 {
23
23
  margin: 0;
@@ -8,7 +8,7 @@ export type PortalProps = {
8
8
  * @required
9
9
  */
10
10
  children: ReactNode;
11
- /** The container to render the portal in. */
11
+ /** The container to render the portal content in. */
12
12
  container?: HTMLElement;
13
13
  };
14
14
 
@@ -1,7 +1,12 @@
1
+ import { ListItem } from '-/components/ListItem';
1
2
  import { RadioProps, Radio } from '-/components/Radio';
2
- import { ToggleOption, ToggleOptionControlProps } from '-/components/ToggleOption';
3
3
 
4
- export type RadioOptionProps = ToggleOptionControlProps<RadioProps>;
4
+ export type RadioOptionProps = RadioProps & {
5
+ /** The label of the option. Also used as the aria-label of the control. */
6
+ label: string;
7
+ /** The description of the option. */
8
+ description?: string;
9
+ };
5
10
 
6
11
  /**
7
12
  * A control that allows users to choose one or more items from a list or turn an feature on or off.
@@ -12,14 +17,17 @@ export type RadioOptionProps = ToggleOptionControlProps<RadioProps>;
12
17
  * @phase Utility
13
18
  */
14
19
  export function RadioOption({ label: labelProp, description, disabled, ...radioProps }: RadioOptionProps) {
15
- const label = labelProp || description;
16
20
  const ariaLabel = description ? `${labelProp} - ${description}` : labelProp;
17
21
  return (
18
- label && (
19
- <ToggleOption data-bspk="radio-option" description={description} disabled={disabled} label={label}>
20
- <Radio {...radioProps} aria-label={ariaLabel} disabled={disabled} />
21
- </ToggleOption>
22
- )
22
+ <ListItem
23
+ aria-disabled={disabled || undefined}
24
+ as="label"
25
+ label={labelProp}
26
+ leading={<Radio {...radioProps} aria-label={ariaLabel} disabled={disabled} />}
27
+ owner="radio-option"
28
+ subText={description}
29
+ width="hug"
30
+ />
23
31
  );
24
32
  }
25
33
 
@@ -16,6 +16,8 @@ export type ScrimProps = CommonProps<'owner'> & {
16
16
  * @required;
17
17
  */
18
18
  onClick: () => void;
19
+ /** If the scrim should be contained within a parent element, or fixed to the viewport. */
20
+ contained?: boolean;
19
21
  };
20
22
 
21
23
  /**
@@ -25,13 +27,14 @@ export type ScrimProps = CommonProps<'owner'> & {
25
27
  * @name Scrim
26
28
  * @phase Utility
27
29
  */
28
- export function Scrim({ visible = true, owner, ...props }: ScrimProps) {
30
+ export function Scrim({ visible = true, owner, contained, ...props }: ScrimProps) {
29
31
  return (
30
32
  <div
31
33
  {...props}
32
34
  aria-hidden="true"
33
35
  data-bspk="scrim"
34
36
  data-bspk-owner={owner || undefined}
37
+ data-contained={contained || undefined}
35
38
  data-hidden={!visible || undefined}
36
39
  />
37
40
  );
@@ -14,6 +14,10 @@
14
14
  animation-iteration-count: 1;
15
15
  animation-fill-mode: forwards;
16
16
 
17
+ &[data-contained] {
18
+ position: absolute;
19
+ }
20
+
17
21
  @keyframes fade-in {
18
22
  0% {
19
23
  opacity: 0;
@@ -2,7 +2,7 @@ import './switch.scss';
2
2
  import { ChangeEvent } from 'react';
3
3
  import { CommonProps } from '-/types/common';
4
4
 
5
- export type SwitchProps = CommonProps<'aria-label' | 'disabled' | 'name'> & {
5
+ export type SwitchProps = CommonProps<'aria-label' | 'disabled' | 'id' | 'name'> & {
6
6
  /**
7
7
  * Marks the control as checked.
8
8
  *
@@ -1,7 +1,22 @@
1
+ import { ListItem } from '-/components/ListItem';
1
2
  import { SwitchProps, Switch } from '-/components/Switch';
2
- import { ToggleOption, ToggleOptionControlProps } from '-/components/ToggleOption';
3
+ import { CommonProps } from '-/types/common';
3
4
 
4
- export type SwitchOptionProps = ToggleOptionControlProps<SwitchProps>;
5
+ export type SwitchOptionProps = CommonProps<'style'> &
6
+ SwitchProps & {
7
+ /**
8
+ * The label of the option. Also used as the aria-label of the control.
9
+ *
10
+ * @required
11
+ */
12
+ label: string;
13
+ /**
14
+ * The description of the option.
15
+ *
16
+ * @type multiline
17
+ */
18
+ description?: string;
19
+ };
5
20
 
6
21
  /**
7
22
  * A control that allows users to choose one or more items from a list or turn an feature on or off.
@@ -11,16 +26,20 @@ export type SwitchOptionProps = ToggleOptionControlProps<SwitchProps>;
11
26
  * @name SwitchOption
12
27
  * @phase Stable
13
28
  */
14
- export function SwitchOption({ label: labelProp, description, ...checkboxProps }: SwitchOptionProps) {
15
- const label = labelProp || description;
29
+ export function SwitchOption({ label: labelProp, description, disabled, style, ...switchProps }: SwitchOptionProps) {
16
30
  const ariaLabel = description ? `${labelProp} - ${description}` : labelProp;
17
31
 
18
32
  return (
19
- label && (
20
- <ToggleOption data-bspk-owner="switch-option" description={description} label={label}>
21
- <Switch {...checkboxProps} aria-label={ariaLabel} />
22
- </ToggleOption>
23
- )
33
+ <ListItem
34
+ aria-disabled={disabled || undefined}
35
+ as="label"
36
+ label={labelProp}
37
+ leading={<Switch {...switchProps} aria-label={ariaLabel} disabled={disabled} />}
38
+ owner="switch-option"
39
+ style={style}
40
+ subText={description}
41
+ width="hug"
42
+ />
24
43
  );
25
44
  }
26
45
 
@@ -1,5 +1,6 @@
1
1
  import './tag.scss';
2
2
  import { Truncated } from '-/components/Truncated';
3
+ import { ElementProps } from '-/types/common';
3
4
  import { ColorVariant } from '-/utils/colorVariants';
4
5
 
5
6
  export type TagProps = {
@@ -40,9 +41,15 @@ export type TagProps = {
40
41
  * @name Tag
41
42
  * @phase Stable
42
43
  */
43
- export function Tag({ label, color = 'white', size = 'small', variant = 'flat' }: TagProps) {
44
+ export function Tag({
45
+ label,
46
+ color = 'grey',
47
+ size = 'small',
48
+ variant = 'flat',
49
+ ...props
50
+ }: ElementProps<TagProps, 'span'>) {
44
51
  return (
45
- <span data-bspk="tag" data-color={color} data-size={size} data-variant={variant}>
52
+ <span {...props} data-bspk="tag" data-color={color} data-size={size} data-variant={variant}>
46
53
  {label && <Truncated>{label}</Truncated>}
47
54
  {variant === 'corner-wrap' && <div data-triangle />}
48
55
  </span>