@kaizen/components 0.0.0-canary-button-codemod-canary-20250212054517 → 0.0.0-canary-stacking-context-fix-20250225001220
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/bin/codemod.sh +0 -2
- package/codemods/README.md +0 -45
- package/codemods/utils/createProp.spec.ts +19 -75
- package/codemods/utils/createProp.ts +1 -8
- package/codemods/utils/getKaioTagName.ts +5 -13
- package/codemods/utils/index.ts +0 -1
- package/dist/cjs/Filter/FilterBar/subcomponents/FilterBarButton/FilterBarButton.cjs +1 -0
- package/dist/cjs/Filter/FilterMultiSelect/subcomponents/Trigger/FilterTriggerButton/FilterTriggerButton.cjs +1 -0
- package/dist/cjs/Filter/FilterMultiSelect/subcomponents/Trigger/RemovableFilterTrigger/RemovableFilterTrigger.cjs +1 -0
- package/dist/cjs/index.cjs +2 -0
- package/dist/esm/Filter/FilterBar/subcomponents/FilterBarButton/FilterBarButton.mjs +1 -0
- package/dist/esm/Filter/FilterMultiSelect/subcomponents/Trigger/FilterTriggerButton/FilterTriggerButton.mjs +1 -0
- package/dist/esm/Filter/FilterMultiSelect/subcomponents/Trigger/RemovableFilterTrigger/RemovableFilterTrigger.mjs +1 -0
- package/dist/esm/index.mjs +1 -0
- package/dist/styles.css +8647 -8640
- package/dist/types/Filter/FilterBar/subcomponents/FilterBarButton/FilterBarButton.d.ts +1 -1
- package/dist/types/Filter/FilterButton/index.d.ts +1 -0
- package/dist/types/Filter/FilterMultiSelect/types.d.ts +2 -1
- package/dist/types/RichTextEditor/utils/commands/fixtures/helpers.d.ts +0 -1
- package/dist/types/RichTextEditor/utils/commands/fixtures/index.d.ts +2 -0
- package/dist/types/RichTextEditor/utils/commands/fixtures/mockRangeForBoundingRect.d.ts +1 -0
- package/dist/types/__rc__/Icon/constants.d.ts +1 -1
- package/package.json +6 -1
- package/src/Filter/FilterButton/index.ts +1 -0
- package/src/Filter/FilterMultiSelect/types.ts +3 -1
- package/src/RichTextEditor/utils/commands/addMark.spec.ts +1 -5
- package/src/RichTextEditor/utils/commands/fixtures/helpers.ts +0 -31
- package/src/RichTextEditor/utils/commands/fixtures/index.ts +2 -0
- package/src/RichTextEditor/utils/commands/fixtures/mockRangeForBoundingRect.ts +32 -0
- package/src/TitleBlockZen/TitleBlockZen.module.scss +1 -6
- package/src/__rc__/Button/_docs/Button--usage-guidelines.mdx +170 -1
- package/src/__rc__/Button/_docs/Button.docs.stories.tsx +264 -9
- package/src/__rc__/Button/_docs/assets/button_anatomy.png +0 -0
- package/src/__rc__/Button/_docs/assets/button_icon_only_spec.png +0 -0
- package/src/__rc__/Button/_docs/assets/button_icon_spec.png +0 -0
- package/src/__rc__/Button/_docs/assets/button_spec.png +0 -0
- package/src/__rc__/Icon/constants.ts +1 -0
- package/src/__rc__/Tabs/subcomponents/Tab/Tab.module.css +5 -2
- package/src/__rc__/Tabs/subcomponents/TabList/TabList.module.css +11 -4
- package/codemods/upgradeV1Buttons/index.ts +0 -19
- package/codemods/upgradeV1Buttons/transformV1ButtonAttributes.spec.ts +0 -202
- package/codemods/upgradeV1Buttons/transformV1ButtonAttributes.ts +0 -132
- package/codemods/upgradeV1Buttons/upgradeV1Buttons.spec.ts +0 -658
- package/codemods/upgradeV1Buttons/upgradeV1Buttons.ts +0 -93
- package/codemods/utils/createJsxElementWithChildren.spec.ts +0 -119
- package/codemods/utils/createJsxElementWithChildren.ts +0 -55
- package/src/__rc__/Button/_docs/Button--migration-guide.mdx +0 -58
|
@@ -9,7 +9,7 @@ export declare const FilterBarButton: React.ForwardRefExoticComponent<{
|
|
|
9
9
|
label: string;
|
|
10
10
|
selectedValue?: string | JSX.Element;
|
|
11
11
|
isOpen?: boolean;
|
|
12
|
-
} & Omit<import("../../../FilterButton
|
|
12
|
+
} & Omit<import("../../../FilterButton").FilterButtonBaseProps, "children"> & {
|
|
13
13
|
filterId: string;
|
|
14
14
|
isRemovable: boolean | undefined;
|
|
15
15
|
} & React.RefAttributes<FilterTriggerRef>>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Key, type Node } from '@react-types/shared';
|
|
1
|
+
import { type Key, type Node, type Selection as ReactAriaSelection } from '@react-types/shared';
|
|
2
2
|
export type ItemType = {
|
|
3
3
|
label: string;
|
|
4
4
|
value: Key;
|
|
@@ -6,3 +6,4 @@ export type ItemType = {
|
|
|
6
6
|
isDisabled?: boolean;
|
|
7
7
|
};
|
|
8
8
|
export type MultiSelectItem = Node<ItemType>;
|
|
9
|
+
export type Selection = ReactAriaSelection;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type EditorState, type Transaction } from 'prosemirror-state';
|
|
2
2
|
import { type ProseMirrorModel } from '../../prosemirror';
|
|
3
|
-
export declare const mockRangeForBoundingRect: () => void;
|
|
4
3
|
export declare const simulateRangeSelection: (anchorPositionStart?: number, anchorPositionEnd?: number) => (state: EditorState, dispatch?: (tx: Transaction) => void) => boolean;
|
|
5
4
|
export declare const getStartNode: (state: EditorState) => ReturnType<ProseMirrorModel.Node["childAfter"]>;
|
|
6
5
|
export declare const simulateSelectionOfCurrentElement: (selectEntireElement?: boolean) => (state: EditorState, dispatch: (tx: Transaction) => void) => boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const mockRangeForBoundingRect: () => void;
|
|
@@ -2,4 +2,4 @@ export declare const handledRtlIcons: {
|
|
|
2
2
|
checklist: "checklist_rtl";
|
|
3
3
|
format_list_numbered: "format_list_numbered_rtl";
|
|
4
4
|
};
|
|
5
|
-
export declare const iconDefaultSet: ("add" | "add_a_photo" | "add_comment" | "add_link" | "arrow_back" | "arrow_downward" | "arrow_drop_down" | "arrow_drop_up" | "arrow_forward" | "arrow_upward" | "assignment" | "assignment_add" | "assignment_ind" | "assignment_returned" | "assignment_turned_in" | "backup" | "bar_chart" | "bookmark" | "brush" | "build" | "cached" | "cancel" | "chat_apps_script" | "chat_error" | "chat_paste_go" | "check" | "check_circle" | "chevron_left" | "chevron_right" | "close" | "close_fullscreen" | "cloud_download" | "comment_bank" | "content_copy" | "dashboard" | "date_range" | "delete" | "domain" | "draft" | "drag_indicator" | "edit" | "error" | "event" | "favorite" | "find_in_page" | "flag" | "flash_on" | "format_bold" | "format_indent_decrease" | "format_indent_increase" | "format_italic" | "format_list_bulleted" | "format_list_numbered" | "format_underlined" | "forum" | "forward" | "front_hand" | "grade" | "group" | "groups" | "help" | "history" | "home" | "horizontal_rule" | "info" | "key" | "keyboard_arrow_down" | "keyboard_arrow_up" | "keyboard_tab" | "keyboard_tab_rtl" | "label" | "lan" | "lightbulb" | "link_off" | "list" | "local_fire_department" | "lock" | "logout" | "mail" | "manage_accounts" | "menu" | "mms" | "more_horiz" | "more_vert" | "north_east" | "note_alt" | "notifications_active" | "open_in_full" | "open_in_new" | "pause" | "percent" | "person" | "person_add" | "person_cancel" | "person_check" | "play_circle" | "playlist_add_check" | "potted_plant" | "power" | "power_settings_new" | "print" | "privacy_tip" | "psychology_alt" | "radio_button_checked" | "radio_button_unchecked" | "rate_review" | "redo" | "reduce_capacity" | "refresh" | "remove" | "reviews" | "schedule" | "school" | "search" | "send" | "sensors" | "sentiment_dissatisfied" | "sentiment_neutral" | "sentiment_satisfied" | "sentiment_very_satisfied" | "settings" | "sms" | "south_east" | "star" | "support" | "thumb_down" | "thumb_up" | "today" | "translate" | "tune" | "undo" | "user_attributes" | "visibility" | "visibility_off" | "warning" | "zoom_in" | "zoom_out" | "auto_awesome")[];
|
|
5
|
+
export declare const iconDefaultSet: ("add" | "add_a_photo" | "add_comment" | "add_link" | "arrow_back" | "arrow_downward" | "arrow_drop_down" | "arrow_drop_up" | "arrow_forward" | "arrow_upward" | "assignment" | "assignment_add" | "assignment_ind" | "assignment_returned" | "assignment_turned_in" | "backup" | "bar_chart" | "bookmark" | "brush" | "build" | "cached" | "cancel" | "chat_apps_script" | "chat_error" | "chat_paste_go" | "check" | "check_circle" | "chevron_left" | "chevron_right" | "close" | "close_fullscreen" | "cloud_download" | "comment_bank" | "content_copy" | "dashboard" | "date_range" | "delete" | "domain" | "draft" | "drag_indicator" | "edit" | "error" | "event" | "favorite" | "find_in_page" | "flag" | "flash_on" | "format_bold" | "format_indent_decrease" | "format_indent_increase" | "format_italic" | "format_list_bulleted" | "format_list_numbered" | "format_underlined" | "forum" | "forward" | "front_hand" | "grade" | "group" | "groups" | "help" | "history" | "home" | "horizontal_rule" | "info" | "key" | "keyboard_arrow_down" | "keyboard_arrow_up" | "keyboard_tab" | "keyboard_tab_rtl" | "label" | "lan" | "lightbulb" | "link_off" | "list" | "local_fire_department" | "lock" | "logout" | "mail" | "manage_accounts" | "menu" | "mms" | "more_horiz" | "more_vert" | "north_east" | "note_alt" | "notifications_active" | "open_in_full" | "open_in_new" | "pause" | "percent" | "person" | "person_add" | "person_cancel" | "person_check" | "play_circle" | "playlist_add_check" | "potted_plant" | "power" | "power_settings_new" | "print" | "privacy_tip" | "psychology_alt" | "radio_button_checked" | "radio_button_unchecked" | "rate_review" | "redo" | "reduce_capacity" | "refresh" | "remove" | "reviews" | "schedule" | "school" | "search" | "send" | "sensors" | "sentiment_dissatisfied" | "sentiment_neutral" | "sentiment_satisfied" | "sentiment_very_satisfied" | "settings" | "share" | "sms" | "south_east" | "star" | "support" | "thumb_down" | "thumb_up" | "today" | "translate" | "tune" | "undo" | "user_attributes" | "visibility" | "visibility_off" | "warning" | "zoom_in" | "zoom_out" | "auto_awesome")[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaizen/components",
|
|
3
|
-
"version": "0.0.0-canary-
|
|
3
|
+
"version": "0.0.0-canary-stacking-context-fix-20250225001220",
|
|
4
4
|
"description": "Kaizen component library",
|
|
5
5
|
"author": "Geoffrey Chong <geoff.chong@cultureamp.com>",
|
|
6
6
|
"homepage": "https://cultureamp.design",
|
|
@@ -81,6 +81,11 @@
|
|
|
81
81
|
"require": "./dist/cjs/reactAriaComponentsV3.cjs",
|
|
82
82
|
"types": "./dist/types/__react-aria-components__/index.d.ts"
|
|
83
83
|
},
|
|
84
|
+
"./v3/utilities": {
|
|
85
|
+
"import": "./dist/esm/utilitiesV3.mjs",
|
|
86
|
+
"require": "./dist/cjs/utilitiesV3.cjs",
|
|
87
|
+
"types": "./dist/types/__utilities__/v3.d.ts"
|
|
88
|
+
},
|
|
84
89
|
"./dist/styles.css": {
|
|
85
90
|
"import": "./dist/styles.css",
|
|
86
91
|
"require": "./dist/styles.css",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Key, type Node } from '@react-types/shared'
|
|
1
|
+
import { type Key, type Node, type Selection as ReactAriaSelection } from '@react-types/shared'
|
|
2
2
|
|
|
3
3
|
export type ItemType = {
|
|
4
4
|
label: string
|
|
@@ -8,3 +8,5 @@ export type ItemType = {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export type MultiSelectItem = Node<ItemType>
|
|
11
|
+
|
|
12
|
+
export type Selection = ReactAriaSelection
|
|
@@ -2,11 +2,7 @@ import { findByText, waitFor } from '@testing-library/dom'
|
|
|
2
2
|
import { vi } from 'vitest'
|
|
3
3
|
import { createRichTextEditor } from '../core'
|
|
4
4
|
import { addMark } from './addMark'
|
|
5
|
-
import {
|
|
6
|
-
mockRangeForBoundingRect,
|
|
7
|
-
simulateSelectionByText,
|
|
8
|
-
simulateTextInsert,
|
|
9
|
-
} from './fixtures/helpers'
|
|
5
|
+
import { mockRangeForBoundingRect, simulateSelectionByText, simulateTextInsert } from './fixtures/'
|
|
10
6
|
import { testEditorState, testSchema } from './fixtures/test-state'
|
|
11
7
|
describe('addMark()', () => {
|
|
12
8
|
const onChange = vi.fn()
|
|
@@ -5,38 +5,7 @@ import {
|
|
|
5
5
|
type Transaction,
|
|
6
6
|
} from 'prosemirror-state'
|
|
7
7
|
import { findChildrenByType } from 'prosemirror-utils'
|
|
8
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
9
|
-
import { vi } from 'vitest'
|
|
10
8
|
import { type ProseMirrorModel } from '../../prosemirror'
|
|
11
|
-
/*
|
|
12
|
-
** This is used handle the JSDom type error issue you may encounter in testing
|
|
13
|
-
** See https://github.com/jsdom/jsdom/issues/3002
|
|
14
|
-
*/
|
|
15
|
-
export const mockRangeForBoundingRect = (): void => {
|
|
16
|
-
vi.spyOn(document, 'createRange').mockImplementation(() => {
|
|
17
|
-
const range = new Range()
|
|
18
|
-
|
|
19
|
-
range.getBoundingClientRect = () => ({
|
|
20
|
-
x: 0,
|
|
21
|
-
y: 0,
|
|
22
|
-
bottom: 0,
|
|
23
|
-
height: 0,
|
|
24
|
-
left: 0,
|
|
25
|
-
right: 0,
|
|
26
|
-
top: 0,
|
|
27
|
-
width: 0,
|
|
28
|
-
toJSON: () => undefined,
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
range.getClientRects = () => ({
|
|
32
|
-
item: () => null,
|
|
33
|
-
length: 0,
|
|
34
|
-
[Symbol.iterator]: vi.fn(),
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
return range
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
9
|
|
|
41
10
|
/*
|
|
42
11
|
** Prosemirror cannot intuit a real `Selection` of content injected into the base test.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
import { vi } from 'vitest'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
** This is used handle the JSDom type error issue you may encounter in testing
|
|
6
|
+
** See https://github.com/jsdom/jsdom/issues/3002
|
|
7
|
+
*/
|
|
8
|
+
export const mockRangeForBoundingRect = (): void => {
|
|
9
|
+
vi.spyOn(document, 'createRange').mockImplementation(() => {
|
|
10
|
+
const range = new Range()
|
|
11
|
+
|
|
12
|
+
range.getBoundingClientRect = () => ({
|
|
13
|
+
x: 0,
|
|
14
|
+
y: 0,
|
|
15
|
+
bottom: 0,
|
|
16
|
+
height: 0,
|
|
17
|
+
left: 0,
|
|
18
|
+
right: 0,
|
|
19
|
+
top: 0,
|
|
20
|
+
width: 0,
|
|
21
|
+
toJSON: () => undefined,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
range.getClientRects = () => ({
|
|
25
|
+
item: () => null,
|
|
26
|
+
length: 0,
|
|
27
|
+
[Symbol.iterator]: vi.fn(),
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
return range
|
|
31
|
+
})
|
|
32
|
+
}
|
|
@@ -114,7 +114,6 @@ $tab-container-height-medium-and-small-collapsed: 0;
|
|
|
114
114
|
display: flex;
|
|
115
115
|
align-items: center;
|
|
116
116
|
min-width: 0; // this is an important trick to prevent flexbox items from overflowing
|
|
117
|
-
z-index: $ca-z-index-dropdown; // this ensures the page switcher dropdown sits over nav tabs
|
|
118
117
|
transform: translateY(-0.0833em);
|
|
119
118
|
|
|
120
119
|
.hasSubtitle & {
|
|
@@ -434,7 +433,7 @@ $tab-container-height-medium-and-small-collapsed: 0;
|
|
|
434
433
|
width: $tab-container-height-small;
|
|
435
434
|
height: $tab-container-height-small;
|
|
436
435
|
background: linear-gradient(0deg, $color-purple-600, rgba($color-purple-600-rgb, 0));
|
|
437
|
-
z-index:
|
|
436
|
+
z-index: 1;
|
|
438
437
|
}
|
|
439
438
|
|
|
440
439
|
.adminVariant & {
|
|
@@ -503,7 +502,6 @@ $tab-container-height-medium-and-small-collapsed: 0;
|
|
|
503
502
|
cursor: pointer;
|
|
504
503
|
display: flex;
|
|
505
504
|
position: absolute;
|
|
506
|
-
z-index: $ca-z-index-sticky;
|
|
507
505
|
align-items: center;
|
|
508
506
|
top: 50%;
|
|
509
507
|
transform: translateY(-50%);
|
|
@@ -573,9 +571,6 @@ $tab-container-height-medium-and-small-collapsed: 0;
|
|
|
573
571
|
// We are using visually hidden here instead of display:none so that a screen reader
|
|
574
572
|
// navigating via 'read mode' (which doesn't trigger hover/focus) will still hear this link name
|
|
575
573
|
@include visually-hidden;
|
|
576
|
-
|
|
577
|
-
z-index: $ca-z-index-sticky - 1;
|
|
578
|
-
|
|
579
574
|
@include ca-position($start: -2 * $ca-grid);
|
|
580
575
|
|
|
581
576
|
position: absolute;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { Canvas, Meta, Controls } from '@storybook/blocks'
|
|
2
|
-
import { ResourceLinks, KAIOInstallation } from '~storybook/components'
|
|
2
|
+
import { ResourceLinks, KAIOInstallation, DosAndDonts, DoOrDont } from '~storybook/components'
|
|
3
3
|
import * as Button from './Button.docs.stories'
|
|
4
|
+
import ButtonIconOnlySpec from './assets/button_icon_only_spec.png'
|
|
5
|
+
import ButtonIconSpec from './assets/button_icon_spec.png'
|
|
6
|
+
import ButtonSpec from './assets/button_spec.png'
|
|
7
|
+
import ButtonAnatomy from './assets/button_anatomy.png'
|
|
4
8
|
|
|
5
9
|
<Meta title="Components/Button/Button (v3)/Usage Guidelines" />
|
|
6
10
|
|
|
@@ -27,3 +31,168 @@ Buttons allow users to perform an action. They have multiple styles for various
|
|
|
27
31
|
include={['children', 'variant', 'size', 'isDisabled', 'icon', 'iconPosition']}
|
|
28
32
|
className="mb-64"
|
|
29
33
|
/>
|
|
34
|
+
|
|
35
|
+
## Anatomy
|
|
36
|
+
|
|
37
|
+
<img
|
|
38
|
+
src={ButtonAnatomy}
|
|
39
|
+
alt="Indicates the anatomy of an Button component with text"
|
|
40
|
+
className="my-auto"
|
|
41
|
+
/>
|
|
42
|
+
|
|
43
|
+
### When to use
|
|
44
|
+
|
|
45
|
+
Use buttons to communicate actions users can take. Each page should have only one primary button, and any remaining calls to action should use lower emphasis buttons.
|
|
46
|
+
|
|
47
|
+
### When not to use
|
|
48
|
+
|
|
49
|
+
Do not use buttons as navigational elements. Instead, use links when the desired action is to take the user to a new page.
|
|
50
|
+
|
|
51
|
+
## Specs
|
|
52
|
+
|
|
53
|
+
<img
|
|
54
|
+
src={ButtonSpec}
|
|
55
|
+
alt="Indicates the spacing specifications of a Button component with text"
|
|
56
|
+
className="my-auto"
|
|
57
|
+
/>
|
|
58
|
+
|
|
59
|
+
<img
|
|
60
|
+
src={ButtonIconSpec}
|
|
61
|
+
alt="Indicates the spacing specifications of a Button component with text and an icon"
|
|
62
|
+
className="my-auto"
|
|
63
|
+
/>
|
|
64
|
+
|
|
65
|
+
<img
|
|
66
|
+
src={ButtonIconOnlySpec}
|
|
67
|
+
alt="Indicates the spacing specifications of an icon-only Button"
|
|
68
|
+
className="my-auto"
|
|
69
|
+
/>
|
|
70
|
+
|
|
71
|
+
### Dos and don'ts
|
|
72
|
+
|
|
73
|
+
#### Use primary buttons to highlight a single, important action
|
|
74
|
+
|
|
75
|
+
Reserve the primary button for actions that are essential to an experience. Usually, use only one primary button on a page or section. These buttons give extra prominence and help establish a clear hierarchy.
|
|
76
|
+
|
|
77
|
+
<DosAndDonts>
|
|
78
|
+
<DoOrDont story={Button.DoExamplePrimaryAndSecondary} />
|
|
79
|
+
<DoOrDont story={Button.DontExamplePrimaryAndSecondary} isDont />
|
|
80
|
+
</DosAndDonts>
|
|
81
|
+
|
|
82
|
+
#### Use secondary buttons for medium emphasis actions
|
|
83
|
+
|
|
84
|
+
Use secondary buttons when the action requires less prominence, or if there are multiple actions with the same importance on a page or section.
|
|
85
|
+
|
|
86
|
+
#### Use tertiary buttons to communicate action hierarchy
|
|
87
|
+
|
|
88
|
+
Use tertiary buttons for less important actions within a group or section to help establish a clear hierarchy. Don't use tertiary buttons in isolation.
|
|
89
|
+
|
|
90
|
+
#### Use large buttons for high emphasis
|
|
91
|
+
|
|
92
|
+
Use large buttons sparingly within pages or sections where you need a high emphasis and prominent button to provide balance with other large elements. This might be on a landing page or a CTA in proximity to large headings.
|
|
93
|
+
|
|
94
|
+
<DosAndDonts>
|
|
95
|
+
<DoOrDont story={Button.DoExampleCta} />
|
|
96
|
+
</DosAndDonts>
|
|
97
|
+
|
|
98
|
+
#### Use medium buttons most of the time
|
|
99
|
+
|
|
100
|
+
Medium buttons are appropriate in most common contexts such as pairing with input fields.
|
|
101
|
+
|
|
102
|
+
<DosAndDonts>
|
|
103
|
+
<DoOrDont story={Button.DoExampleDefaultToMediumSize} />
|
|
104
|
+
<DoOrDont story={Button.DontExampleDefaultToMediumSize} isDont />
|
|
105
|
+
</DosAndDonts>
|
|
106
|
+
|
|
107
|
+
#### Use small buttons in information rich contexts
|
|
108
|
+
|
|
109
|
+
Use small buttons when space is limited, such as inside or adjacent to lists, tables, or data visualizations.
|
|
110
|
+
|
|
111
|
+
Ensure clarity by prioritizing the most important actions. Think about how many buttons you use and where you put them. Don't overload your interface with too many buttons, as clustering buttons can confuse people.
|
|
112
|
+
|
|
113
|
+
#### Use icons in Primary and Secondary buttons sparingly and consistently
|
|
114
|
+
|
|
115
|
+
Overusing icons can create visual clutter and overwhelm users. Use them sparingly to highlight common and recognizable actions.
|
|
116
|
+
|
|
117
|
+
<DosAndDonts>
|
|
118
|
+
<DoOrDont story={Button.DoExampleUseIconsSparingly} />
|
|
119
|
+
<DoOrDont story={Button.DontExampleUseIconsSparingly} isDont />
|
|
120
|
+
</DosAndDonts>
|
|
121
|
+
|
|
122
|
+
#### Always use icons in Tertiary buttons
|
|
123
|
+
|
|
124
|
+
Without icons, tertiary buttons can look like plain text. Tertiary buttons must always use icons to support a button affordance and meet accessibility standards.
|
|
125
|
+
|
|
126
|
+
<DosAndDonts>
|
|
127
|
+
<DoOrDont story={Button.DoExampleTertiaryButtonWithIcons} />
|
|
128
|
+
<DoOrDont story={Button.DontExampleTertiaryButtonWithIcons} isDont />
|
|
129
|
+
</DosAndDonts>
|
|
130
|
+
|
|
131
|
+
#### Use tooltips when the label is hidden
|
|
132
|
+
|
|
133
|
+
When a button label is hidden and only an icon is used, show a tooltip on hover that displays the label text.
|
|
134
|
+
|
|
135
|
+
<DosAndDonts>
|
|
136
|
+
<DoOrDont story={Button.DoExampleUseTooltips} />
|
|
137
|
+
<DoOrDont story={Button.DontExampleUseTooltips} isDont />
|
|
138
|
+
</DosAndDonts>
|
|
139
|
+
|
|
140
|
+
#### Use a menu button when all actions are equally important
|
|
141
|
+
|
|
142
|
+
Group related actions in a menu. The action options should be closely related and make sense as a group. You can use any type or size of button based on the context.
|
|
143
|
+
|
|
144
|
+
<DosAndDonts>
|
|
145
|
+
<DoOrDont story={Button.DoExampleMenuButton} />
|
|
146
|
+
</DosAndDonts>
|
|
147
|
+
|
|
148
|
+
#### Use a button and an overflow button when there is a most common or distinct action
|
|
149
|
+
|
|
150
|
+
Highlight the most important, common, or a distinct action by using a button with text. Group related, less important actions in an overflow button. The action options should be closely related and make sense as a group. You can use any type or size of button based on the context. This pattern replaces Split Buttons.
|
|
151
|
+
|
|
152
|
+
<DosAndDonts>
|
|
153
|
+
<DoOrDont story={Button.DoExampleKebabMenuButton} />
|
|
154
|
+
</DosAndDonts>
|
|
155
|
+
|
|
156
|
+
#### Write clear, action-oriented button labels
|
|
157
|
+
|
|
158
|
+
Write button labels as concise verbs that clearly state the action and its outcome. Always align the button label with the language used elsewhere in the Platform to maintain consistency and clarity.
|
|
159
|
+
Make sure that all your buttons begin with a strong verb (something that elicits an action from the user). Verbs indicate to a user what they’re about to see or do next.
|
|
160
|
+
|
|
161
|
+
<DosAndDonts>
|
|
162
|
+
<DoOrDont story={Button.DoExampleClearAndConciseLabels} />
|
|
163
|
+
<DoOrDont story={Button.DontExampleClearAndConciseLabels} isDont />
|
|
164
|
+
</DosAndDonts>
|
|
165
|
+
|
|
166
|
+
A verb and noun combination gives users more context and can help guide them when the action they’re about to perform isn’t commonplace.
|
|
167
|
+
|
|
168
|
+
<DosAndDonts>
|
|
169
|
+
<DoOrDont story={Button.DoExampleDeclareContext} />
|
|
170
|
+
<DoOrDont story={Button.DontExampleDeclareContext} isDont />
|
|
171
|
+
</DosAndDonts>
|
|
172
|
+
|
|
173
|
+
#### Write in sentence case with minimal punctuation
|
|
174
|
+
|
|
175
|
+
All buttons should be in sentence case i.e. the first letter of the first word is capitalized and everything else is in lower case unless it’s a proper noun or feature name. Always err on the side of minimal punctuation, so leave out full stops and commas where possible.
|
|
176
|
+
|
|
177
|
+
<DosAndDonts>
|
|
178
|
+
<DoOrDont story={Button.DoExampleMinimalPunctuation} />
|
|
179
|
+
<DoOrDont story={Button.DontExampleMinimalPunctuation} isDont />
|
|
180
|
+
</DosAndDonts>
|
|
181
|
+
|
|
182
|
+
#### Use second person
|
|
183
|
+
|
|
184
|
+
Any buttons that include a personal pronoun should be written in the second person. Keep in mind that you shouldn’t use personal pronouns unless you’re asking the user to filter something. For example, “View your reports” vs “View all reports.”
|
|
185
|
+
|
|
186
|
+
<DosAndDonts>
|
|
187
|
+
<DoOrDont story={Button.DoExampleSecondPerson} />
|
|
188
|
+
<DoOrDont story={Button.DontExampleSecondPerson} isDont />
|
|
189
|
+
</DosAndDonts>
|
|
190
|
+
|
|
191
|
+
#### Button labels should make sense in isolation
|
|
192
|
+
|
|
193
|
+
If buttons on a page have the same label repeated multiple times, they should have distinct, accessible names that add context for users. This ensures better accessibility for screen reader users, who rely on descriptive labels to distinguish between actions.
|
|
194
|
+
|
|
195
|
+
<DosAndDonts>
|
|
196
|
+
<DoOrDont story={Button.DoExampleFunctionalLabels} />
|
|
197
|
+
<DoOrDont story={Button.DontExampleFunctionalLabels} isDont />
|
|
198
|
+
</DosAndDonts>
|