@workday/canvas-kit-preview-react 9.0.0-alpha.336-next.6 → 9.0.0-alpha.344-next.3
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/commonjs/form-field/lib/FormField.d.ts +2 -2
- package/dist/commonjs/form-field/lib/FormFieldHint.d.ts +1 -1
- package/dist/commonjs/form-field/lib/FormFieldInput.d.ts +1 -1
- package/dist/commonjs/form-field/lib/hooks/useFormFieldHint.d.ts +1 -1
- package/dist/commonjs/form-field/lib/hooks/useFormFieldInput.d.ts +1 -1
- package/dist/commonjs/form-field/lib/hooks/useFormFieldLabel.d.ts +1 -1
- package/dist/commonjs/form-field/lib/hooks/useFormFieldModel.d.ts +2 -12
- package/dist/commonjs/form-field/lib/hooks/useFormFieldModel.d.ts.map +1 -1
- package/dist/commonjs/form-field/lib/hooks/useFormFieldModel.js +1 -3
- package/dist/commonjs/menu/lib/Menu.d.ts +12 -5
- package/dist/commonjs/menu/lib/Menu.d.ts.map +1 -1
- package/dist/commonjs/menu/lib/Menu.js +14 -5
- package/dist/commonjs/menu/lib/MenuItem.d.ts +15 -5
- package/dist/commonjs/menu/lib/MenuItem.d.ts.map +1 -1
- package/dist/commonjs/menu/lib/MenuItem.js +18 -6
- package/dist/commonjs/pill/lib/Pill.d.ts +103 -5
- package/dist/commonjs/pill/lib/Pill.d.ts.map +1 -1
- package/dist/commonjs/pill/lib/Pill.js +101 -2
- package/dist/commonjs/segmented-control/index.d.ts +2 -0
- package/dist/commonjs/segmented-control/index.d.ts.map +1 -1
- package/dist/commonjs/segmented-control/index.js +4 -0
- package/dist/commonjs/segmented-control/lib/SegmentedControl.d.ts +74 -38
- package/dist/commonjs/segmented-control/lib/SegmentedControl.d.ts.map +1 -1
- package/dist/commonjs/segmented-control/lib/SegmentedControl.js +36 -0
- package/dist/commonjs/segmented-control/lib/SegmentedControlItem.d.ts +1 -1
- package/dist/commonjs/segmented-control/lib/SegmentedControlList.d.ts +64 -1
- package/dist/commonjs/segmented-control/lib/SegmentedControlList.d.ts.map +1 -1
- package/dist/commonjs/segmented-control/lib/SegmentedControlList.js +3 -3
- package/dist/commonjs/segmented-control/lib/hooks/useSegmentedControlItem.d.ts +2 -2
- package/dist/commonjs/segmented-control/lib/hooks/useSegmentedControlModel.d.ts +39 -39
- package/dist/commonjs/segmented-control/lib/hooks/useSegmentedControlModel.js +2 -1
- package/dist/commonjs/select/lib/Select.js +2 -0
- package/dist/commonjs/side-panel/lib/SidePanel.d.ts +13 -26
- package/dist/commonjs/side-panel/lib/SidePanel.d.ts.map +1 -1
- package/dist/commonjs/side-panel/lib/SidePanel.js +73 -96
- package/dist/commonjs/side-panel/lib/SidePanelToggleButton.d.ts +17 -0
- package/dist/commonjs/side-panel/lib/SidePanelToggleButton.d.ts.map +1 -0
- package/dist/commonjs/side-panel/lib/SidePanelToggleButton.js +88 -0
- package/dist/commonjs/side-panel/lib/hooks.d.ts +20 -0
- package/dist/commonjs/side-panel/lib/hooks.d.ts.map +1 -1
- package/dist/commonjs/side-panel/lib/hooks.js +20 -1
- package/dist/commonjs/status-indicator/index.d.ts +2 -0
- package/dist/commonjs/status-indicator/index.d.ts.map +1 -1
- package/dist/commonjs/status-indicator/index.js +4 -0
- package/dist/commonjs/status-indicator/lib/StatusIndicator.d.ts +28 -2
- package/dist/commonjs/status-indicator/lib/StatusIndicator.d.ts.map +1 -1
- package/dist/commonjs/status-indicator/lib/StatusIndicator.js +27 -1
- package/dist/commonjs/status-indicator/lib/StatusIndicatorIcon.d.ts +13 -0
- package/dist/commonjs/status-indicator/lib/StatusIndicatorIcon.d.ts.map +1 -1
- package/dist/commonjs/status-indicator/lib/StatusIndicatorIcon.js +3 -3
- package/dist/commonjs/text-area/lib/TextArea.d.ts +1 -1
- package/dist/commonjs/text-area/lib/TextArea.d.ts.map +1 -1
- package/dist/commonjs/text-area/lib/TextArea.js +1 -2
- package/dist/commonjs/text-input/lib/TextInput.d.ts +2 -2
- package/dist/commonjs/text-input/lib/TextInput.d.ts.map +1 -1
- package/dist/commonjs/text-input/lib/TextInput.js +1 -2
- package/dist/commonjs/text-input/lib/TextInputField.js +1 -1
- package/dist/commonjs/text-input/lib/hooks/useTextInputField.d.ts +1 -1
- package/dist/commonjs/text-input/lib/hooks/useTextInputModel.d.ts +1 -0
- package/dist/commonjs/text-input/lib/hooks/useTextInputModel.d.ts.map +1 -1
- package/dist/commonjs/text-input/lib/hooks/useTextInputModel.js +1 -0
- package/dist/es6/form-field/lib/FormField.d.ts +2 -2
- package/dist/es6/form-field/lib/FormFieldHint.d.ts +1 -1
- package/dist/es6/form-field/lib/FormFieldInput.d.ts +1 -1
- package/dist/es6/form-field/lib/hooks/useFormFieldHint.d.ts +1 -1
- package/dist/es6/form-field/lib/hooks/useFormFieldInput.d.ts +1 -1
- package/dist/es6/form-field/lib/hooks/useFormFieldLabel.d.ts +1 -1
- package/dist/es6/form-field/lib/hooks/useFormFieldModel.d.ts +2 -12
- package/dist/es6/form-field/lib/hooks/useFormFieldModel.d.ts.map +1 -1
- package/dist/es6/form-field/lib/hooks/useFormFieldModel.js +1 -3
- package/dist/es6/menu/lib/Menu.d.ts +12 -5
- package/dist/es6/menu/lib/Menu.d.ts.map +1 -1
- package/dist/es6/menu/lib/Menu.js +14 -5
- package/dist/es6/menu/lib/MenuItem.d.ts +15 -5
- package/dist/es6/menu/lib/MenuItem.d.ts.map +1 -1
- package/dist/es6/menu/lib/MenuItem.js +18 -6
- package/dist/es6/pill/lib/Pill.d.ts +103 -5
- package/dist/es6/pill/lib/Pill.d.ts.map +1 -1
- package/dist/es6/pill/lib/Pill.js +101 -2
- package/dist/es6/segmented-control/index.d.ts +2 -0
- package/dist/es6/segmented-control/index.d.ts.map +1 -1
- package/dist/es6/segmented-control/index.js +2 -0
- package/dist/es6/segmented-control/lib/SegmentedControl.d.ts +74 -38
- package/dist/es6/segmented-control/lib/SegmentedControl.d.ts.map +1 -1
- package/dist/es6/segmented-control/lib/SegmentedControl.js +36 -0
- package/dist/es6/segmented-control/lib/SegmentedControlItem.d.ts +1 -1
- package/dist/es6/segmented-control/lib/SegmentedControlList.d.ts +64 -1
- package/dist/es6/segmented-control/lib/SegmentedControlList.d.ts.map +1 -1
- package/dist/es6/segmented-control/lib/SegmentedControlList.js +1 -1
- package/dist/es6/segmented-control/lib/hooks/useSegmentedControlItem.d.ts +2 -2
- package/dist/es6/segmented-control/lib/hooks/useSegmentedControlModel.d.ts +39 -39
- package/dist/es6/segmented-control/lib/hooks/useSegmentedControlModel.js +2 -1
- package/dist/es6/select/lib/Select.js +2 -0
- package/dist/es6/side-panel/lib/SidePanel.d.ts +13 -26
- package/dist/es6/side-panel/lib/SidePanel.d.ts.map +1 -1
- package/dist/es6/side-panel/lib/SidePanel.js +75 -97
- package/dist/es6/side-panel/lib/SidePanelToggleButton.d.ts +17 -0
- package/dist/es6/side-panel/lib/SidePanelToggleButton.d.ts.map +1 -0
- package/dist/es6/side-panel/lib/SidePanelToggleButton.js +66 -0
- package/dist/es6/side-panel/lib/hooks.d.ts +20 -0
- package/dist/es6/side-panel/lib/hooks.d.ts.map +1 -1
- package/dist/es6/side-panel/lib/hooks.js +19 -0
- package/dist/es6/status-indicator/index.d.ts +2 -0
- package/dist/es6/status-indicator/index.d.ts.map +1 -1
- package/dist/es6/status-indicator/index.js +2 -0
- package/dist/es6/status-indicator/lib/StatusIndicator.d.ts +28 -2
- package/dist/es6/status-indicator/lib/StatusIndicator.d.ts.map +1 -1
- package/dist/es6/status-indicator/lib/StatusIndicator.js +27 -1
- package/dist/es6/status-indicator/lib/StatusIndicatorIcon.d.ts +13 -0
- package/dist/es6/status-indicator/lib/StatusIndicatorIcon.d.ts.map +1 -1
- package/dist/es6/status-indicator/lib/StatusIndicatorIcon.js +1 -1
- package/dist/es6/text-area/lib/TextArea.d.ts +1 -1
- package/dist/es6/text-area/lib/TextArea.d.ts.map +1 -1
- package/dist/es6/text-area/lib/TextArea.js +2 -3
- package/dist/es6/text-input/lib/TextInput.d.ts +2 -2
- package/dist/es6/text-input/lib/TextInput.d.ts.map +1 -1
- package/dist/es6/text-input/lib/TextInput.js +2 -3
- package/dist/es6/text-input/lib/TextInputField.js +3 -3
- package/dist/es6/text-input/lib/hooks/useTextInputField.d.ts +1 -1
- package/dist/es6/text-input/lib/hooks/useTextInputModel.d.ts +1 -0
- package/dist/es6/text-input/lib/hooks/useTextInputModel.d.ts.map +1 -1
- package/dist/es6/text-input/lib/hooks/useTextInputModel.js +1 -0
- package/form-field/lib/hooks/useFormFieldModel.tsx +1 -3
- package/menu/lib/Menu.tsx +12 -5
- package/menu/lib/MenuItem.tsx +15 -5
- package/package.json +4 -4
- package/pill/lib/Pill.tsx +101 -2
- package/segmented-control/index.ts +2 -0
- package/segmented-control/lib/SegmentedControl.tsx +36 -0
- package/segmented-control/lib/SegmentedControlList.tsx +1 -1
- package/side-panel/lib/SidePanel.tsx +119 -169
- package/side-panel/lib/SidePanelToggleButton.tsx +78 -0
- package/side-panel/lib/hooks.ts +20 -0
- package/status-indicator/index.ts +2 -0
- package/status-indicator/lib/StatusIndicator.tsx +27 -1
- package/status-indicator/lib/StatusIndicatorIcon.tsx +1 -1
- package/text-area/lib/TextArea.tsx +6 -3
- package/text-input/lib/TextInput.tsx +6 -3
- package/text-input/lib/TextInputField.tsx +3 -3
- package/text-input/lib/hooks/useTextInputModel.ts +1 -0
- package/dist/commonjs/text-area/lib/hooks/index.d.ts +0 -2
- package/dist/commonjs/text-area/lib/hooks/index.d.ts.map +0 -1
- package/dist/commonjs/text-area/lib/hooks/index.js +0 -13
- package/dist/commonjs/text-area/lib/hooks/useTextAreaModel.d.ts +0 -28
- package/dist/commonjs/text-area/lib/hooks/useTextAreaModel.d.ts.map +0 -1
- package/dist/commonjs/text-area/lib/hooks/useTextAreaModel.js +0 -5
- package/dist/es6/text-area/lib/hooks/index.d.ts +0 -2
- package/dist/es6/text-area/lib/hooks/index.d.ts.map +0 -1
- package/dist/es6/text-area/lib/hooks/index.js +0 -1
- package/dist/es6/text-area/lib/hooks/useTextAreaModel.d.ts +0 -28
- package/dist/es6/text-area/lib/hooks/useTextAreaModel.d.ts.map +0 -1
- package/dist/es6/text-area/lib/hooks/useTextAreaModel.js +0 -2
- package/text-area/lib/hooks/index.ts +0 -1
- package/text-area/lib/hooks/useTextAreaModel.ts +0 -3
package/pill/lib/Pill.tsx
CHANGED
|
@@ -160,14 +160,113 @@ const StyledNonInteractivePill = styled(StyledBasePill)<StyledType>({
|
|
|
160
160
|
position: 'relative',
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
+
/**
|
|
164
|
+
* By default, a `Pill` renders an interactive element that accepts subcomponents. By "interactive"
|
|
165
|
+
* we mean that the Pill container is a focusable element (a `<button>`). All leading elements
|
|
166
|
+
* (icons or avatars) are intended to be descriptive, helping support the label. They should not
|
|
167
|
+
* receive focus.
|
|
168
|
+
*
|
|
169
|
+
* `Pill` is the container component. It also provides a React context model for its subcomponents.
|
|
170
|
+
* Based on the `variant` prop this component will render different styled `Pill`s.
|
|
171
|
+
*
|
|
172
|
+
* Example of read only:
|
|
173
|
+
*
|
|
174
|
+
* ```tsx
|
|
175
|
+
* <Pill variant="readOnly">This is a read only</Pill>
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* Example of interactive:
|
|
179
|
+
*
|
|
180
|
+
* ```tsx
|
|
181
|
+
* <Pill onClick={() => console.log('clicked')}>
|
|
182
|
+
* <Pill.Avatar /> Regina Skeltor
|
|
183
|
+
* </Pill>
|
|
184
|
+
* ```
|
|
185
|
+
*
|
|
186
|
+
* Example of removable:
|
|
187
|
+
*
|
|
188
|
+
* ```tsx
|
|
189
|
+
* <Pill variant="removable">
|
|
190
|
+
* <Pill.Avatar /> Regina Skeltor
|
|
191
|
+
* <Pill.IconButton onClick={() => console.log('clicked')} />
|
|
192
|
+
* </Pill>
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* If you set the `Pill` `variant` to `removable`, it will render a `<span>` element. You can then
|
|
196
|
+
* provide a `Pill.IconButton` that acts as the focus target. This creates a smaller, more
|
|
197
|
+
* intentional click target that prevents users from accidentally deleting an item.
|
|
198
|
+
*
|
|
199
|
+
* ```tsx
|
|
200
|
+
* <Pill variant="removable">
|
|
201
|
+
* Shoes
|
|
202
|
+
* <Pill.IconButton onClick={() => console.log('handle remove')} />
|
|
203
|
+
* </Pill>
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
163
206
|
export const Pill = createContainer('button')({
|
|
207
|
+
displayName: 'Pill',
|
|
164
208
|
modelHook: usePillModel,
|
|
165
209
|
subComponents: {
|
|
166
|
-
|
|
210
|
+
/**
|
|
211
|
+
* This component renders an avatar. It supports all props of the `Avatar` component.
|
|
212
|
+
*
|
|
213
|
+
* ```tsx
|
|
214
|
+
* <Pill variant="removable">
|
|
215
|
+
* <Pill.Avatar url={avatarUrl} />
|
|
216
|
+
* Regina Skeltor
|
|
217
|
+
* <Pill.IconButton onClick={() => console.log('handle remove')} />
|
|
218
|
+
* </Pill>
|
|
219
|
+
* ```
|
|
220
|
+
*/
|
|
167
221
|
Avatar: PillAvatar,
|
|
222
|
+
/**
|
|
223
|
+
* This component renders its `children` as the count.
|
|
224
|
+
*
|
|
225
|
+
* ```tsx
|
|
226
|
+
* <Pill onClick={() => console.warn('clicked')}>
|
|
227
|
+
* Shoes
|
|
228
|
+
* <Pill.Count>30</Pill.Count>
|
|
229
|
+
* </Pill>
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
168
232
|
Count: PillCount,
|
|
169
|
-
|
|
233
|
+
/**
|
|
234
|
+
* This component renders an `icon`. It not be used with the `default` styling – not `readOnly`
|
|
235
|
+
* or `removable` variants. By default it renders a `plusIcon` but it can be overridden by
|
|
236
|
+
* providing an icon to the `icon` prop.
|
|
237
|
+
*
|
|
238
|
+
* ```tsx
|
|
239
|
+
* <Pill onClick={() => console.warn('clicked')}>
|
|
240
|
+
* <Pill.Icon />
|
|
241
|
+
* <Pill.Label>Regina Skeltor</Pill.Label>
|
|
242
|
+
* </Pill>
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
Icon: PillIcon,
|
|
246
|
+
/**
|
|
247
|
+
* This component renders a custom icon button. It is only intended to be used with the
|
|
248
|
+
* `removable` variant. By default, it renders a `xSmallIcon` but can be overridden by providing
|
|
249
|
+
* an icon to the `icon` prop.
|
|
250
|
+
*
|
|
251
|
+
* ```tsx
|
|
252
|
+
* <Pill variant="removable">
|
|
253
|
+
* Pink Shirts
|
|
254
|
+
* <Pill.IconButton onClick={() => console.warn('clicked')} />
|
|
255
|
+
* </Pill>
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
170
258
|
IconButton: PillIconButton,
|
|
259
|
+
/**
|
|
260
|
+
* This component renders a `<span>` that automatically handles overflow by rendering a tooltip.
|
|
261
|
+
* There's no need to use this component directly since the overflow is handled for you automatically.
|
|
262
|
+
*
|
|
263
|
+
* ```tsx
|
|
264
|
+
* <Pill variant="readOnly">
|
|
265
|
+
* <Pill.Label>Read-only</Pill.Label>
|
|
266
|
+
* </Pill>
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
Label: PillLabel,
|
|
171
270
|
},
|
|
172
271
|
})<PillProps>(({variant = 'default', maxWidth, ...elemProps}, Element, model) => {
|
|
173
272
|
return (
|
|
@@ -9,11 +9,47 @@ export interface SegmentedControlProps {
|
|
|
9
9
|
children: React.ReactNode;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* `SegmentedControl` is a container component that is responsible for creating a
|
|
14
|
+
* {@link SegmentedControlModel} and sharing it with its subcomponents using React context. It does
|
|
15
|
+
* not represent a real element.
|
|
16
|
+
*
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <SegmentedControl items={[]}>{Child components}</SegmentedControl>
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Alternatively, you may pass in a model using the [hoisted model
|
|
22
|
+
* pattern](/getting-started/for-developers/resources/compound-components/#configuring-a-model).
|
|
23
|
+
*
|
|
24
|
+
* ```tsx
|
|
25
|
+
* const model = useSegmentedControlModel({
|
|
26
|
+
* items: [],
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* <SegmentedControl model={model}>{Child components}</SegmentedControl>;
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
12
32
|
export const SegmentedControl = createContainer()({
|
|
13
33
|
displayName: 'SegmentedControl',
|
|
14
34
|
modelHook: useSegmentedControlModel,
|
|
15
35
|
subComponents: {
|
|
36
|
+
/**
|
|
37
|
+
* `SegmentedControl.List` renders {@link Grid} under the hood. It is a container for
|
|
38
|
+
* {@link SegmentedControlItem SegmentedControl.Item} subcomponents.
|
|
39
|
+
*
|
|
40
|
+
* ```tsx
|
|
41
|
+
* <SegmentedControl.List>{SegmentedControl.Items}</SegmentedControl.List>
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
16
44
|
List: SegmentedControlList,
|
|
45
|
+
/**
|
|
46
|
+
* `SegmentedControl.Item` is a `button` element built on `BaseButton`. `SegmentedControl.Item`
|
|
47
|
+
* has a `data-id` prop to handle `onSelect` properly.
|
|
48
|
+
*
|
|
49
|
+
* ```tsx
|
|
50
|
+
* <SegmentedControl.Item data-id="table">Table</SegmentedControl.Item>
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
17
53
|
Item: SegmentedControlItem,
|
|
18
54
|
},
|
|
19
55
|
})<SegmentedControlProps>(({children}) => {
|
|
@@ -15,7 +15,7 @@ export interface SegmentedControlListProps<T = any>
|
|
|
15
15
|
children: ((item: T) => React.ReactNode) | React.ReactNode;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const useSegmentedControlList = createElemPropsHook(useSegmentedControlModel)(
|
|
18
|
+
export const useSegmentedControlList = createElemPropsHook(useSegmentedControlModel)(
|
|
19
19
|
({state: {orientation, disabled, items}}) => {
|
|
20
20
|
const directionName = orientation === 'vertical' ? 'Row' : 'Column';
|
|
21
21
|
return {
|
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
/** @jsxRuntime classic */
|
|
2
2
|
/** @jsx jsx */
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
|
|
4
|
+
import {createComponent, styled} from '@workday/canvas-kit-react/common';
|
|
5
|
+
import {jsx, keyframes, CSSObject} from '@emotion/react';
|
|
6
|
+
import {colors, depth} from '@workday/canvas-kit-react/tokens';
|
|
7
|
+
import {SidePanelContext} from './hooks';
|
|
8
|
+
import {SidePanelToggleButton} from './SidePanelToggleButton';
|
|
10
9
|
|
|
11
10
|
export type SidePanelVariant = 'standard' | 'alternate';
|
|
12
11
|
export type SidePanelTransitionStates = 'collapsed' | 'collapsing' | 'expanded' | 'expanding';
|
|
13
12
|
|
|
14
|
-
export interface SidePanelProps
|
|
15
|
-
/**
|
|
16
|
-
* The element the side panel will render as (e.g. 'div').
|
|
17
|
-
*
|
|
18
|
-
* @default 'section'
|
|
19
|
-
*/
|
|
20
|
-
as?: React.ElementType;
|
|
13
|
+
export interface SidePanelProps {
|
|
21
14
|
/**
|
|
22
15
|
* The width of the component (in `px` if it's a `number`) when it is collapsed.
|
|
23
16
|
*
|
|
@@ -67,6 +60,9 @@ export interface SidePanelProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
67
60
|
* @param boolean
|
|
68
61
|
*/
|
|
69
62
|
touched: boolean;
|
|
63
|
+
children?: React.ReactNode;
|
|
64
|
+
onAnimationStart?: React.AnimationEventHandler<HTMLElement>;
|
|
65
|
+
onAnimationEnd?: React.AnimationEventHandler<HTMLElement>;
|
|
70
66
|
}
|
|
71
67
|
|
|
72
68
|
const createKeyframes = (from: number | string, to: number | string) => {
|
|
@@ -98,172 +94,126 @@ const containerVariantStyle: Record<SidePanelVariant, CSSObject> = {
|
|
|
98
94
|
},
|
|
99
95
|
};
|
|
100
96
|
|
|
101
|
-
const Panel = styled('section')
|
|
97
|
+
const Panel = styled('section')({
|
|
102
98
|
overflow: 'hidden',
|
|
103
99
|
position: 'relative',
|
|
104
100
|
boxSizing: 'border-box',
|
|
105
101
|
height: '100%',
|
|
106
102
|
});
|
|
107
103
|
|
|
108
|
-
export const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
}, [expanded, onExpandedChange]);
|
|
137
|
-
|
|
138
|
-
React.useEffect(() => {
|
|
139
|
-
if (typeof onStateTransition !== 'undefined') {
|
|
140
|
-
onStateTransition(state);
|
|
141
|
-
}
|
|
142
|
-
}, [state, onStateTransition]);
|
|
143
|
-
|
|
144
|
-
const motion = {
|
|
145
|
-
collapse: createKeyframes(expandedWidth, collapsedWidth),
|
|
146
|
-
expand: createKeyframes(collapsedWidth, expandedWidth),
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const handleAnimationEnd = (event: React.AnimationEvent<HTMLDivElement>) => {
|
|
150
|
-
if (event.currentTarget === event.target) {
|
|
151
|
-
if (event.animationName === motion.collapse.name) {
|
|
152
|
-
setState('collapsed');
|
|
104
|
+
export const SidePanel = createComponent('section')({
|
|
105
|
+
displayName: 'SidePanel',
|
|
106
|
+
Component(
|
|
107
|
+
{
|
|
108
|
+
children,
|
|
109
|
+
collapsedWidth = 64,
|
|
110
|
+
expanded = true,
|
|
111
|
+
expandedWidth = 320,
|
|
112
|
+
onAnimationEnd,
|
|
113
|
+
onAnimationStart,
|
|
114
|
+
onExpandedChange,
|
|
115
|
+
onStateTransition,
|
|
116
|
+
origin = 'left',
|
|
117
|
+
variant = 'standard',
|
|
118
|
+
touched,
|
|
119
|
+
...elemProps
|
|
120
|
+
}: SidePanelProps,
|
|
121
|
+
ref,
|
|
122
|
+
Element
|
|
123
|
+
) {
|
|
124
|
+
const [state, setState] = React.useState<SidePanelTransitionStates>(
|
|
125
|
+
expanded ? 'expanded' : 'collapsed'
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
React.useEffect(() => {
|
|
129
|
+
if (typeof onExpandedChange !== 'undefined') {
|
|
130
|
+
onExpandedChange(expanded);
|
|
153
131
|
}
|
|
132
|
+
}, [expanded, onExpandedChange]);
|
|
154
133
|
|
|
155
|
-
|
|
156
|
-
|
|
134
|
+
React.useEffect(() => {
|
|
135
|
+
if (typeof onStateTransition !== 'undefined') {
|
|
136
|
+
onStateTransition(state);
|
|
157
137
|
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
138
|
+
}, [state, onStateTransition]);
|
|
139
|
+
|
|
140
|
+
const motion = {
|
|
141
|
+
collapse: createKeyframes(expandedWidth, collapsedWidth),
|
|
142
|
+
expand: createKeyframes(collapsedWidth, expandedWidth),
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const handleAnimationEnd = (event: React.AnimationEvent<HTMLDivElement>) => {
|
|
146
|
+
if (event.currentTarget === event.target) {
|
|
147
|
+
if (event.animationName === motion.collapse.name) {
|
|
148
|
+
setState('collapsed');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (event.animationName === motion.expand.name) {
|
|
152
|
+
setState('expanded');
|
|
153
|
+
}
|
|
172
154
|
}
|
|
173
|
-
}
|
|
174
155
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
156
|
+
if (typeof onAnimationEnd !== 'undefined') {
|
|
157
|
+
onAnimationEnd(event);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const handleAnimationStart = (event: React.AnimationEvent<HTMLDivElement>) => {
|
|
162
|
+
if (event.currentTarget === event.target) {
|
|
163
|
+
if (
|
|
164
|
+
event.animationName === motion.collapse.name ||
|
|
165
|
+
event.animationName === motion.expand.name
|
|
166
|
+
) {
|
|
167
|
+
setState(expanded ? 'expanding' : 'collapsing');
|
|
168
|
+
}
|
|
169
|
+
}
|
|
179
170
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
:
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
171
|
+
if (typeof onAnimationStart !== 'undefined') {
|
|
172
|
+
onAnimationStart(event);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<Panel
|
|
178
|
+
ref={ref}
|
|
179
|
+
as={Element}
|
|
180
|
+
css={[
|
|
181
|
+
{
|
|
182
|
+
width: expanded ? expandedWidth : collapsedWidth,
|
|
183
|
+
maxWidth: expanded ? expandedWidth : collapsedWidth,
|
|
184
|
+
// mounted.current will be false on the first render, thus you won't get an unwanted animation here
|
|
185
|
+
// Will animate again if you force a re-render (like in Storybook)
|
|
186
|
+
animation: touched
|
|
187
|
+
? `${expanded ? motion.expand : motion.collapse} 200ms ease-out`
|
|
188
|
+
: undefined,
|
|
189
|
+
},
|
|
190
|
+
containerVariantStyle[variant],
|
|
191
|
+
]}
|
|
192
|
+
onAnimationEnd={handleAnimationEnd}
|
|
193
|
+
onAnimationStart={handleAnimationStart}
|
|
194
|
+
{...elemProps}
|
|
204
195
|
>
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
icon = transformationImportIcon,
|
|
230
|
-
tooltipTextExpand: expandLabel = 'Expand',
|
|
231
|
-
tooltipTextCollapse: collapseLabel = 'Collapse',
|
|
232
|
-
...rest
|
|
233
|
-
}: ToggleButtonProps & React.ButtonHTMLAttributes<HTMLButtonElement>) => {
|
|
234
|
-
const context = React.useContext(SidePanelContext);
|
|
235
|
-
|
|
236
|
-
const useRTLOrigin = () => {
|
|
237
|
-
const isRTL = useIsRTL();
|
|
238
|
-
// if the direction is set to RTl, flip the origin
|
|
239
|
-
if (isRTL) {
|
|
240
|
-
return context.origin === 'left' ? 'right' : 'left';
|
|
241
|
-
}
|
|
242
|
-
// Otherwise, default to returning the origin
|
|
243
|
-
return context.origin;
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
const rtlOrigin = useRTLOrigin();
|
|
247
|
-
|
|
248
|
-
// Note: Depending on the collapsed width, the button could "jump" to it's final position.
|
|
249
|
-
const buttonStyle = css({
|
|
250
|
-
position: 'absolute',
|
|
251
|
-
top: space.m,
|
|
252
|
-
width: space.l,
|
|
253
|
-
right: context.state === 'collapsed' ? 0 : rtlOrigin === 'left' ? space.s : undefined,
|
|
254
|
-
left: context.state === 'collapsed' ? 0 : rtlOrigin === 'right' ? space.s : undefined,
|
|
255
|
-
margin: context.state === 'collapsed' ? 'auto' : 0, // to override the -8px margin for TertiaryButton.Plain
|
|
256
|
-
transform:
|
|
257
|
-
context.state === 'collapsed' || context.state === 'collapsing'
|
|
258
|
-
? `scaleX(${rtlOrigin === 'left' ? '1' : '-1'})`
|
|
259
|
-
: `scaleX(${rtlOrigin === 'left' ? '-1' : '1'})`,
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
return (
|
|
263
|
-
<Tooltip title={context.state === 'collapsed' ? expandLabel : collapseLabel} type="muted">
|
|
264
|
-
<TertiaryButton type="button" css={buttonStyle} icon={icon} variant={variant} {...rest} />
|
|
265
|
-
</Tooltip>
|
|
266
|
-
);
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
SidePanel.ToggleButton = ToggleButton;
|
|
196
|
+
<SidePanelContext.Provider
|
|
197
|
+
value={{
|
|
198
|
+
state,
|
|
199
|
+
origin,
|
|
200
|
+
}}
|
|
201
|
+
>
|
|
202
|
+
{children}
|
|
203
|
+
</SidePanelContext.Provider>
|
|
204
|
+
</Panel>
|
|
205
|
+
);
|
|
206
|
+
},
|
|
207
|
+
subComponents: {
|
|
208
|
+
/**
|
|
209
|
+
* `SidePanel.ToggleButton` is a control that is meant to toggle between `expanded = true` and
|
|
210
|
+
* `expanded = false` states. It must be used within the `SidePanel` component as a child. Use
|
|
211
|
+
* in conjunction with `useSidePanel`'s `controlProps`, otherwise it does not come with explicit
|
|
212
|
+
* `onClick` handlers.
|
|
213
|
+
*
|
|
214
|
+
* For accessibility purposes, it must be the first focusable element. We recommend that you
|
|
215
|
+
* keep it as the first child of `SidePanel`
|
|
216
|
+
*/
|
|
217
|
+
ToggleButton: SidePanelToggleButton,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/** @jsxRuntime classic */
|
|
2
|
+
/** @jsx jsx */
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import {createComponent, ExtractProps, useIsRTL} from '@workday/canvas-kit-react/common';
|
|
5
|
+
import {css, jsx} from '@emotion/react';
|
|
6
|
+
import {TertiaryButton} from '@workday/canvas-kit-react/button';
|
|
7
|
+
import {space} from '@workday/canvas-kit-react/tokens';
|
|
8
|
+
import {transformationImportIcon} from '@workday/canvas-system-icons-web';
|
|
9
|
+
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
|
|
10
|
+
import {SidePanelContext} from './hooks';
|
|
11
|
+
|
|
12
|
+
export interface SidePanelToggleButtonProps extends ExtractProps<typeof TertiaryButton, never> {
|
|
13
|
+
/**
|
|
14
|
+
* The tooltip text to expand the side panel
|
|
15
|
+
*/
|
|
16
|
+
tooltipTextExpand?: string;
|
|
17
|
+
/**
|
|
18
|
+
* The tooltip text to collapse the side panel
|
|
19
|
+
*/
|
|
20
|
+
tooltipTextCollapse?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A toggle button styled specifically for the side panel container.
|
|
25
|
+
*/
|
|
26
|
+
export const SidePanelToggleButton = createComponent('button')({
|
|
27
|
+
displayName: 'SidePanel.ToggleButton',
|
|
28
|
+
Component({
|
|
29
|
+
variant = undefined,
|
|
30
|
+
icon = transformationImportIcon,
|
|
31
|
+
tooltipTextExpand = 'Expand',
|
|
32
|
+
tooltipTextCollapse = 'Collapse',
|
|
33
|
+
...elemProps
|
|
34
|
+
}: SidePanelToggleButtonProps) {
|
|
35
|
+
const context = React.useContext(SidePanelContext);
|
|
36
|
+
|
|
37
|
+
const useRTLOrigin = () => {
|
|
38
|
+
const isRTL = useIsRTL();
|
|
39
|
+
// if the direction is set to RTl, flip the origin
|
|
40
|
+
if (isRTL) {
|
|
41
|
+
return context.origin === 'left' ? 'right' : 'left';
|
|
42
|
+
}
|
|
43
|
+
// Otherwise, default to returning the origin
|
|
44
|
+
return context.origin;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const rtlOrigin = useRTLOrigin();
|
|
48
|
+
|
|
49
|
+
// Note: Depending on the collapsed width, the button could "jump" to it's final position.
|
|
50
|
+
const buttonStyle = css({
|
|
51
|
+
position: 'absolute',
|
|
52
|
+
top: space.m,
|
|
53
|
+
width: space.l,
|
|
54
|
+
right: context.state === 'collapsed' ? 0 : rtlOrigin === 'left' ? space.s : undefined,
|
|
55
|
+
left: context.state === 'collapsed' ? 0 : rtlOrigin === 'right' ? space.s : undefined,
|
|
56
|
+
margin: context.state === 'collapsed' ? 'auto' : 0, // to override the -8px margin for TertiaryButton.Plain
|
|
57
|
+
transform:
|
|
58
|
+
context.state === 'collapsed' || context.state === 'collapsing'
|
|
59
|
+
? `scaleX(${rtlOrigin === 'left' ? '1' : '-1'})`
|
|
60
|
+
: `scaleX(${rtlOrigin === 'left' ? '-1' : '1'})`,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<Tooltip
|
|
65
|
+
title={context.state === 'collapsed' ? tooltipTextExpand : tooltipTextCollapse}
|
|
66
|
+
type="muted"
|
|
67
|
+
>
|
|
68
|
+
<TertiaryButton
|
|
69
|
+
type="button"
|
|
70
|
+
css={buttonStyle}
|
|
71
|
+
icon={icon}
|
|
72
|
+
variant={variant}
|
|
73
|
+
{...elemProps}
|
|
74
|
+
/>
|
|
75
|
+
</Tooltip>
|
|
76
|
+
);
|
|
77
|
+
},
|
|
78
|
+
});
|
package/side-panel/lib/hooks.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
+
export const SidePanelContext = React.createContext({
|
|
4
|
+
state: 'expanded',
|
|
5
|
+
origin: 'left',
|
|
6
|
+
});
|
|
7
|
+
|
|
3
8
|
import {useUniqueId} from '@workday/canvas-kit-react/common';
|
|
4
9
|
/**
|
|
5
10
|
* The optional config options for the `useSidePanel` hook
|
|
@@ -77,6 +82,21 @@ export interface ControlProps {
|
|
|
77
82
|
onClick: () => void;
|
|
78
83
|
}
|
|
79
84
|
|
|
85
|
+
/**
|
|
86
|
+
*
|
|
87
|
+
* This hook manages the state and `aria-` attributes for the SidePanel. It takes an optional
|
|
88
|
+
* configuration object:
|
|
89
|
+
*
|
|
90
|
+
* ```tsx
|
|
91
|
+
* import {useSidePanel} from '@workday/canvas-kit-preview-react/side-panel';
|
|
92
|
+
*
|
|
93
|
+
* const {expanded, setExpanded, panelProps, labelProps, controlProps} = useSidePanel({
|
|
94
|
+
* initialExpanded: false,
|
|
95
|
+
* panelId: 'custom-panel-id',
|
|
96
|
+
* labelId: 'custom-label-id',
|
|
97
|
+
* });
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
80
100
|
export const useSidePanel = (config?: UseSidePanelProps) => {
|
|
81
101
|
const [touched, setTouched] = React.useState(false);
|
|
82
102
|
const configParams = config
|
|
@@ -22,13 +22,39 @@ export const useStatusIndicator = createElemPropsHook(useStatusIndicatorModel)((
|
|
|
22
22
|
};
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* `StatusIndicator` is a container component which renders an {@link Flex} under the hood to
|
|
27
|
+
* apply spacing evenly between its children. It has a default maximum width of `200px`.
|
|
28
|
+
*
|
|
29
|
+
* ```tsx
|
|
30
|
+
* <StatusIndicator emphasis="low" variant="blue">
|
|
31
|
+
* {Child components}
|
|
32
|
+
* </StatusIndicator>
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
25
35
|
export const StatusIndicator = createContainer('div')({
|
|
26
36
|
displayName: 'StatusIndicator',
|
|
27
37
|
modelHook: useStatusIndicatorModel,
|
|
28
38
|
elemPropsHook: useStatusIndicator,
|
|
29
39
|
subComponents: {
|
|
30
|
-
|
|
40
|
+
/**
|
|
41
|
+
* `StatusIndicator.Label` renders {@link Text} under the hood. It will apply an ellipsis if its
|
|
42
|
+
* contents exceed the component's maximum width.
|
|
43
|
+
*
|
|
44
|
+
* ```tsx
|
|
45
|
+
* <StatusIndicator.Label>{The text to be rendered}</StatusIndicator.Label>
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
31
48
|
Label: StatusIndicatorLabel,
|
|
49
|
+
/**
|
|
50
|
+
* `StatusIndicator.Icon` renders {@link SystemIcon} under the hood. It's used as a decorative
|
|
51
|
+
* element to visually support the {@link StatusIndicatorLabel StatusIndicator.Label} text.
|
|
52
|
+
*
|
|
53
|
+
* ```tsx
|
|
54
|
+
* <StatusIndicator.Icon icon={uploadCloudIcon} />
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
Icon: StatusIndicatorIcon,
|
|
32
58
|
},
|
|
33
59
|
})<StatusIndicatorProps>(({children, ...elemProps}, Element, model) => {
|
|
34
60
|
return (
|
|
@@ -72,7 +72,7 @@ export const statusIndicatorColors = {
|
|
|
72
72
|
},
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
-
const useStatusIndicatorIcon = createElemPropsHook(useStatusIndicatorModel)(({state}) => {
|
|
75
|
+
export const useStatusIndicatorIcon = createElemPropsHook(useStatusIndicatorModel)(({state}) => {
|
|
76
76
|
const colors = statusIndicatorColors[state.variant][state.emphasis];
|
|
77
77
|
return {
|
|
78
78
|
color: colors.text,
|