@jobber/components-native 0.101.5 → 0.101.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/ActionItem/ActionItem.md +65 -0
- package/dist/docs/ActionItemGroup/ActionItemGroup.md +33 -0
- package/dist/docs/ActionLabel/ActionLabel.md +43 -0
- package/dist/docs/ActivityIndicator/ActivityIndicator.md +116 -0
- package/dist/docs/Animation/Animation.md +71 -0
- package/dist/docs/AtlantisThemeContext/AtlantisThemeContext.md +256 -0
- package/dist/docs/AutoLink/AutoLink.md +47 -0
- package/dist/docs/Banner/Banner.md +390 -0
- package/dist/docs/Borders/Borders.md +45 -0
- package/dist/docs/BottomSheet/BottomSheet.md +67 -0
- package/dist/docs/Button/Button.md +918 -0
- package/dist/docs/ButtonGroup/ButtonGroup.md +89 -0
- package/dist/docs/Card/Card.md +270 -0
- package/dist/docs/Checkbox/Checkbox.md +69 -0
- package/dist/docs/Chip/Chip.md +371 -0
- package/dist/docs/Colors/Colors.md +217 -0
- package/dist/docs/Content/Content.md +67 -0
- package/dist/docs/ContentOverlay/ContentOverlay.md +64 -0
- package/dist/docs/Disclosure/Disclosure.md +161 -0
- package/dist/docs/Divider/Divider.md +84 -0
- package/dist/docs/Elevations/Elevations.md +76 -0
- package/dist/docs/EmptyState/EmptyState.md +72 -0
- package/dist/docs/Flex/Flex.md +37 -0
- package/dist/docs/Form/Form.md +126 -0
- package/dist/docs/FormField/FormField.md +57 -0
- package/dist/docs/FormatFile/FormatFile.md +56 -0
- package/dist/docs/Glimmer/Glimmer.md +143 -0
- package/dist/docs/Heading/Heading.md +132 -0
- package/dist/docs/Icon/Icon.md +585 -0
- package/dist/docs/IconButton/IconButton.md +25 -0
- package/dist/docs/InputCurrency/InputCurrency.md +61 -0
- package/dist/docs/InputDate/InputDate.md +133 -0
- package/dist/docs/InputEmail/InputEmail.md +69 -0
- package/dist/docs/InputFieldWrapper/InputFieldWrapper.md +70 -0
- package/dist/docs/InputNumber/InputNumber.md +72 -0
- package/dist/docs/InputPassword/InputPassword.md +61 -0
- package/dist/docs/InputPressable/InputPressable.md +64 -0
- package/dist/docs/InputSearch/InputSearch.md +49 -0
- package/dist/docs/InputText/InputText.md +324 -0
- package/dist/docs/InputTime/InputTime.md +54 -0
- package/dist/docs/Opacity/Opacity.md +12 -0
- package/dist/docs/ProgressBar/ProgressBar.md +39 -0
- package/dist/docs/Radii/Radii.md +23 -0
- package/dist/docs/ResponsiveBreakpoint/ResponsiveBreakpoint.md +74 -0
- package/dist/docs/Select/Select.md +213 -0
- package/dist/docs/Spacing/Spacing.md +103 -0
- package/dist/docs/StatusLabel/StatusLabel.md +119 -0
- package/dist/docs/Switch/Switch.md +54 -0
- package/dist/docs/Text/Text.md +368 -0
- package/dist/docs/TextList/TextList.md +29 -0
- package/dist/docs/ThumbnailList/ThumbnailList.md +16 -0
- package/dist/docs/Toast/Toast.md +71 -0
- package/dist/docs/Typography/Typography.md +170 -0
- package/dist/docs/choosing-components/choosing-components.md +76 -0
- package/dist/docs/customizing-components/customizing-components.md +167 -0
- package/dist/docs/disabled-states/disabled-states.md +86 -0
- package/dist/docs/empty-states/empty-states.md +126 -0
- package/dist/docs/errors/errors.md +114 -0
- package/dist/docs/index.md +64 -0
- package/dist/docs/interaction/interaction.md +109 -0
- package/dist/docs/page-layouts/page-layouts.md +323 -0
- package/dist/docs/scaffolding/scaffolding.md +109 -0
- package/dist/docs/settings/settings.md +58 -0
- package/dist/docs/usage-guidelines/usage-guidelines.md +177 -0
- package/dist/package.json +8 -4
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +8 -4
|
@@ -0,0 +1,918 @@
|
|
|
1
|
+
# Button
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
Buttons are a core user interface component. They allow service providers (SPs)
|
|
6
|
+
to initiate, complete, or reverse actions such as submitting forms, triggering
|
|
7
|
+
workflows, or navigating between screens. At Jobber, Buttons empower SPs to
|
|
8
|
+
complete work quickly and confidently, whether they're logging in, saving a job,
|
|
9
|
+
or taking action from a modal.
|
|
10
|
+
|
|
11
|
+
The right button to use depends on:
|
|
12
|
+
|
|
13
|
+
* The type of action the SP is attempting to complete
|
|
14
|
+
* The hierarchy of the interface the button lives in
|
|
15
|
+
|
|
16
|
+
## Anatomy
|
|
17
|
+
|
|
18
|
+
A Button typically includes:
|
|
19
|
+
|
|
20
|
+
* Label (required): Clear, concise verb describing the action
|
|
21
|
+
* Icon (optional): Reinforces meaning or improves scanability
|
|
22
|
+
|
|
23
|
+
## Behaviour
|
|
24
|
+
|
|
25
|
+
Buttons should be easy to find and easy to use. They should appear near the
|
|
26
|
+
thing they affect, or in a place that makes sense for the next step.
|
|
27
|
+
|
|
28
|
+
* In modals: Buttons usually sit at the bottom right. The main action comes
|
|
29
|
+
last, and cancel is placed before it. In some cases tertiary buttons can be
|
|
30
|
+
placed on the far left.
|
|
31
|
+
|
|
32
|
+
* On pages: Buttons should line up with related content, like form fields or
|
|
33
|
+
cards. Avoid placing actions too far away from the thing they’re acting on.
|
|
34
|
+
|
|
35
|
+
* When tapped or clicked: buttons should respond right away. Changing state to
|
|
36
|
+
show that something is happening. If an action takes time, use a loading state
|
|
37
|
+
so SPs know it’s in progress and don’t tap again by mistake.
|
|
38
|
+
|
|
39
|
+
Buttons don’t dismiss things unless they’re meant to. If tapping a button closes
|
|
40
|
+
a modal or banner, that should feel intentional rather than surprising. An
|
|
41
|
+
example of this would be in confirmation modals. Secondary buttons that act as a
|
|
42
|
+
way for the SP to reverse the action they've states they want to take, such as
|
|
43
|
+
"Go Back", would dismiss the modal as this is the expected action.
|
|
44
|
+
|
|
45
|
+
#### Sizes
|
|
46
|
+
|
|
47
|
+
Buttons come in three sizes. `Base` is the default and should be used for almost
|
|
48
|
+
every use case.
|
|
49
|
+
|
|
50
|
+
Only use `large` for extremely spacious interfaces such as a login form, and
|
|
51
|
+
`small` when the interface has extremely tight size constraints.
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import React from "react";
|
|
55
|
+
import { Button } from "@jobber/components/Button";
|
|
56
|
+
import { Content } from "@jobber/components/Content";
|
|
57
|
+
|
|
58
|
+
export function ButtonSizesExample() {
|
|
59
|
+
return (
|
|
60
|
+
<Content>
|
|
61
|
+
<Content>
|
|
62
|
+
<Button label="Small" size="small" />
|
|
63
|
+
</Content>
|
|
64
|
+
<Content>
|
|
65
|
+
<Button label="Base" />
|
|
66
|
+
</Content>
|
|
67
|
+
<Content>
|
|
68
|
+
<Button label="Large" size="large" />
|
|
69
|
+
</Content>
|
|
70
|
+
</Content>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### Disabled Buttons
|
|
76
|
+
|
|
77
|
+
As a best practice, do not design with disabled button states. This has negative
|
|
78
|
+
impacts on accessibility as well as an increase in complexity for users to
|
|
79
|
+
understand why the interface is disabled and how to resolve it.
|
|
80
|
+
|
|
81
|
+
Before progressing,
|
|
82
|
+
[review Jobber's guidance on disabled states](../disabled-states/disabled-states.md) to
|
|
83
|
+
ensure you can't design a flow without it.
|
|
84
|
+
|
|
85
|
+
If, after reviewing the documentation, you still believe you can't design a flow
|
|
86
|
+
without disabling a button, this is how you do it:
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import React from "react";
|
|
90
|
+
import { Button } from "@jobber/components/Button";
|
|
91
|
+
|
|
92
|
+
export function ButtonDisabledExample() {
|
|
93
|
+
return <Button label="Do the Thing" disabled />;
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### Use of icons
|
|
98
|
+
|
|
99
|
+
You can use icons inside the buttons. They can stand-alone or appear alongside
|
|
100
|
+
the button label.
|
|
101
|
+
|
|
102
|
+
**Note:** If an icon is used in a stand-alone method, an `ariaLabel` must be
|
|
103
|
+
present to describe the button.
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
import React from "react";
|
|
107
|
+
import { Button } from "@jobber/components/Button";
|
|
108
|
+
import { Content } from "@jobber/components/Content";
|
|
109
|
+
|
|
110
|
+
export function ButtonIconsExample() {
|
|
111
|
+
return (
|
|
112
|
+
<Content>
|
|
113
|
+
<Content>
|
|
114
|
+
<Button type="secondary" icon="user" ariaLabel="I'm a person" />
|
|
115
|
+
</Content>
|
|
116
|
+
<Content>
|
|
117
|
+
<Button label="More" type="secondary" icon="more" />
|
|
118
|
+
</Content>
|
|
119
|
+
<Content>
|
|
120
|
+
<Button
|
|
121
|
+
label="Actions"
|
|
122
|
+
type="secondary"
|
|
123
|
+
icon="arrowDown"
|
|
124
|
+
iconOnRight={true}
|
|
125
|
+
/>
|
|
126
|
+
</Content>
|
|
127
|
+
</Content>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Loading states
|
|
133
|
+
|
|
134
|
+
Use a loading state on a button when clicking it triggers a background action
|
|
135
|
+
that takes more than a moment to complete. This helps SPs understand that
|
|
136
|
+
something is happening, prevents them from clicking again, and avoids duplicated
|
|
137
|
+
actions.
|
|
138
|
+
|
|
139
|
+
Only show the loading state **after** the button is clicked, not pre-emptively
|
|
140
|
+
or passively.
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import React from "react";
|
|
144
|
+
import { Button } from "@jobber/components/Button";
|
|
145
|
+
import { Content } from "@jobber/components/Content";
|
|
146
|
+
|
|
147
|
+
export function ButtonLoadingExample() {
|
|
148
|
+
return (
|
|
149
|
+
<Content>
|
|
150
|
+
<Content>
|
|
151
|
+
<Button
|
|
152
|
+
label="Deleting..."
|
|
153
|
+
type="primary"
|
|
154
|
+
variation="destructive"
|
|
155
|
+
loading={true}
|
|
156
|
+
/>
|
|
157
|
+
</Content>
|
|
158
|
+
<Content>
|
|
159
|
+
<Button
|
|
160
|
+
label="Loading..."
|
|
161
|
+
type="tertiary"
|
|
162
|
+
variation="learning"
|
|
163
|
+
loading={true}
|
|
164
|
+
/>
|
|
165
|
+
</Content>
|
|
166
|
+
<Content>
|
|
167
|
+
<Button label="Canceling..." variation="subtle" loading={true} />
|
|
168
|
+
</Content>
|
|
169
|
+
</Content>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Variants
|
|
175
|
+
|
|
176
|
+
### Work
|
|
177
|
+
|
|
178
|
+
Work buttons help SPs move through their workflows with clarity and confidence.
|
|
179
|
+
They can start or finish a task, go back, cancel, or confirm—depending on where
|
|
180
|
+
the SP is and what they need to do next.
|
|
181
|
+
|
|
182
|
+
All work buttons should feel purposeful, with labels that clearly communicate
|
|
183
|
+
outcomes.
|
|
184
|
+
|
|
185
|
+
Work buttons come in three visual variants:\
|
|
186
|
+
**primary**, **secondary**, and **tertiary**.
|
|
187
|
+
|
|
188
|
+
#### Primary
|
|
189
|
+
|
|
190
|
+
The most important action in a view. Examples include the Save Job button, Log
|
|
191
|
+
In, or the main action in a dialog. There should be one Primary action per view,
|
|
192
|
+
at most.
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
import React from "react";
|
|
196
|
+
import { Button } from "@jobber/components/Button";
|
|
197
|
+
import { Content } from "@jobber/components/Content";
|
|
198
|
+
|
|
199
|
+
export function ButtonWorkExample() {
|
|
200
|
+
return (
|
|
201
|
+
<Content>
|
|
202
|
+
<Content>
|
|
203
|
+
<Button label="Do the Thing" />
|
|
204
|
+
</Content>
|
|
205
|
+
<Content>
|
|
206
|
+
<Button label="Do the Thing" type="secondary" />
|
|
207
|
+
</Content>
|
|
208
|
+
<Content>
|
|
209
|
+
<Button label="Do the Thing" type="tertiary" />
|
|
210
|
+
</Content>
|
|
211
|
+
</Content>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
| ✅ Do | ❌ Don’t |
|
|
217
|
+
| ----------------------------------- | ------------------------------------ |
|
|
218
|
+
| Use for high-value, forward actions | Use to answer a question |
|
|
219
|
+
| Use a clear, verb-first label | Use conversational labels like “Yes” |
|
|
220
|
+
| Keep the label short and specific | Use ellipses (e.g. “Save and...”) |
|
|
221
|
+
| Use one primary per view | Stack multiple primary buttons |
|
|
222
|
+
|
|
223
|
+
**Please note:** At Jobber, we want to avoid use of elipsis in buttons. Going
|
|
224
|
+
forward, buttons with grouped actions should be handled by Splitbutton.
|
|
225
|
+
|
|
226
|
+
#### Secondary
|
|
227
|
+
|
|
228
|
+
Use a secondary button when there are one or more alternate actions available
|
|
229
|
+
that are less important than the primary one. Secondary buttons support the main
|
|
230
|
+
task—they don’t compete with it.
|
|
231
|
+
|
|
232
|
+
They’re used for actions like going back, or previewing before sending.
|
|
233
|
+
|
|
234
|
+
| ✅ Do | ❌ Don’t |
|
|
235
|
+
| ------------------------------------ | ----------------------------------- |
|
|
236
|
+
| Use for optional or supporting steps | Use as a second primary |
|
|
237
|
+
| Pair with a primary button | Stack multiple secondaries together |
|
|
238
|
+
| Keep labels short and outcome-based | Use vague text like “Maybe Later” |
|
|
239
|
+
|
|
240
|
+
#### Tertiary
|
|
241
|
+
|
|
242
|
+
Use a tertiary button for low-emphasis actions that happen within a view—like
|
|
243
|
+
editing a section, showing more details, or navigating between tabs or steps.
|
|
244
|
+
|
|
245
|
+
These buttons are unobtrusive and helpful, but shouldn’t pull attention away
|
|
246
|
+
from the task at hand.
|
|
247
|
+
|
|
248
|
+
| ✅ Do | ❌ Don’t |
|
|
249
|
+
| -------------------------------- | ------------------------------------- |
|
|
250
|
+
| Use for in-context interactions | Use for key tasks or submissions |
|
|
251
|
+
| Pair with a primary or secondary | Use as a workaround for layout issues |
|
|
252
|
+
| Reserve for non-critical actions | Make them the only path forward |
|
|
253
|
+
|
|
254
|
+
### Learning
|
|
255
|
+
|
|
256
|
+
Use learning buttons to help SPs understand Jobber—whether that’s exploring a
|
|
257
|
+
feature, discovering a workflow, or seeing how Jobber can support their
|
|
258
|
+
business.
|
|
259
|
+
|
|
260
|
+
These buttons are for education. They often appear in onboarding, product tours,
|
|
261
|
+
or marketing surfaces.
|
|
262
|
+
|
|
263
|
+
Learning buttons follow the same hierarchy as work buttons:\
|
|
264
|
+
**primary**, **secondary**, and **tertiary**, depending on emphasis.
|
|
265
|
+
|
|
266
|
+
#### Primary, Secondary, Tertiary
|
|
267
|
+
|
|
268
|
+
The usage pattern for Learning Actions should follow the same logic as Work
|
|
269
|
+
Actions for all three levels.
|
|
270
|
+
|
|
271
|
+
```tsx
|
|
272
|
+
import React from "react";
|
|
273
|
+
import { Button } from "@jobber/components/Button";
|
|
274
|
+
import { Content } from "@jobber/components/Content";
|
|
275
|
+
|
|
276
|
+
export function ButtonLearningExample() {
|
|
277
|
+
return (
|
|
278
|
+
<Content>
|
|
279
|
+
<Content>
|
|
280
|
+
<Button
|
|
281
|
+
label="Learn More"
|
|
282
|
+
variation="learning"
|
|
283
|
+
url="//getjobber.com"
|
|
284
|
+
external={true}
|
|
285
|
+
/>
|
|
286
|
+
</Content>
|
|
287
|
+
<Content>
|
|
288
|
+
<Button
|
|
289
|
+
label="Learn More"
|
|
290
|
+
variation="learning"
|
|
291
|
+
type="secondary"
|
|
292
|
+
url="//getjobber.com"
|
|
293
|
+
external={true}
|
|
294
|
+
/>
|
|
295
|
+
</Content>
|
|
296
|
+
<Content>
|
|
297
|
+
<Button
|
|
298
|
+
label="Learn More"
|
|
299
|
+
variation="learning"
|
|
300
|
+
type="tertiary"
|
|
301
|
+
url="//getjobber.com"
|
|
302
|
+
external={true}
|
|
303
|
+
/>
|
|
304
|
+
</Content>
|
|
305
|
+
</Content>
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
| ✅ Do | ❌ Don’t |
|
|
311
|
+
| ----------------------------------- | ------------------------------------ |
|
|
312
|
+
| Use in onboarding or educational UI | Use in job, quote, or invoice flows |
|
|
313
|
+
| Use when the goal is understanding | Use when the goal is completing work |
|
|
314
|
+
| Pair with clear, relevant messaging | Drop into views without context |
|
|
315
|
+
|
|
316
|
+
**Please note:** "Learn More" is the most common CTA for learning buttons. It
|
|
317
|
+
should be the default text. It's important to ensure that the accompanying
|
|
318
|
+
content is clear enough so that it's obvious to SPs what they'll be learning
|
|
319
|
+
about when they interact with learning button with a "Learn More" CTA.
|
|
320
|
+
|
|
321
|
+
### Destructive
|
|
322
|
+
|
|
323
|
+
Destructive buttons are used to remove something from Jobber. They should be
|
|
324
|
+
clear, deliberate, and hard to activate by mistake.
|
|
325
|
+
|
|
326
|
+
Destructive actions come in **primary**, **secondary**, and **tertiary** styles
|
|
327
|
+
depending on impact and context.
|
|
328
|
+
|
|
329
|
+
#### Primary
|
|
330
|
+
|
|
331
|
+
A Primary destructive action will permanently destroy an object carrying
|
|
332
|
+
significant data, such as a job, quote, or client. This destructive action
|
|
333
|
+
should be contained in a [ConfirmationModal](/components/ConfirmationModal)
|
|
334
|
+
triggered by clicking a secondary or tertiary destructive button.
|
|
335
|
+
|
|
336
|
+
#### Secondary or Tertiary
|
|
337
|
+
|
|
338
|
+
Use a secondary or tertiary destructive button when:
|
|
339
|
+
|
|
340
|
+
* The deletion is low-stakes or easily reversible
|
|
341
|
+
* The button is a trigger for a **confirmation modal** that holds the primary
|
|
342
|
+
destructive action
|
|
343
|
+
|
|
344
|
+
In both cases, make sure it’s doesn’t compete with core workflow actions.
|
|
345
|
+
|
|
346
|
+
```tsx
|
|
347
|
+
import React from "react";
|
|
348
|
+
import { Button } from "@jobber/components/Button";
|
|
349
|
+
import { Content } from "@jobber/components/Content";
|
|
350
|
+
|
|
351
|
+
export function ButtonDestructiveExample() {
|
|
352
|
+
return (
|
|
353
|
+
<Content>
|
|
354
|
+
<Content>
|
|
355
|
+
<Button label="Delete" variation="destructive" />
|
|
356
|
+
</Content>
|
|
357
|
+
<Content>
|
|
358
|
+
<Button label="Delete" variation="destructive" type="secondary" />
|
|
359
|
+
</Content>
|
|
360
|
+
<Content>
|
|
361
|
+
<Button label="Delete" variation="destructive" type="tertiary" />
|
|
362
|
+
</Content>
|
|
363
|
+
</Content>
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Subtle
|
|
369
|
+
|
|
370
|
+
Use a "subtle" button when you want the visual appearance to be more *subtle.*
|
|
371
|
+
This variation of button uses subdued color, allowing it to sit comfortably
|
|
372
|
+
alongside more prominent content.
|
|
373
|
+
|
|
374
|
+
Subtle buttons are visually de-emphasized and designed for low-priority or
|
|
375
|
+
non-blocking actions. They use minimal styling so they sit quietly next to more
|
|
376
|
+
prominent content—ideal for secondary navigation, opt-outs, or dismissing
|
|
377
|
+
lightweight UI.
|
|
378
|
+
|
|
379
|
+
Think of icon actions in a navigation bar, buttons to dismiss a modal, or opting
|
|
380
|
+
out of completing an action they have triggered.
|
|
381
|
+
|
|
382
|
+
*Note: This is still known as "Cancel" on mobile. See
|
|
383
|
+
[Mobile/Cancel example](/storybook/mobile/?path=/story/components-actions-button--cancel).*
|
|
384
|
+
|
|
385
|
+
#### Primary, Secondary, and Tertiary
|
|
386
|
+
|
|
387
|
+
A key distinction between subtle buttons and the other variations is that the
|
|
388
|
+
primary/secondary/tertiary scale is styled differently, but the conceptual
|
|
389
|
+
hierarchy is the same. Notably, the tertiary subtle button has a transparent
|
|
390
|
+
background, allowing it to be *extra* subtle when placed overtop
|
|
391
|
+
`surface--background` elements such as a Modal header.
|
|
392
|
+
|
|
393
|
+
```tsx
|
|
394
|
+
import React from "react";
|
|
395
|
+
import { Button } from "@jobber/components/Button";
|
|
396
|
+
import { Content } from "@jobber/components/Content";
|
|
397
|
+
|
|
398
|
+
export function ButtonSubtleExample() {
|
|
399
|
+
return (
|
|
400
|
+
<Content>
|
|
401
|
+
<Content>
|
|
402
|
+
<Content>
|
|
403
|
+
<Button label="Cancel" type="primary" variation="subtle" />
|
|
404
|
+
</Content>
|
|
405
|
+
<Content>
|
|
406
|
+
<Button label="Dismiss" type="secondary" variation="subtle" />
|
|
407
|
+
</Content>
|
|
408
|
+
<Content>
|
|
409
|
+
<Button label="Maybe Later" type="tertiary" variation="subtle" />
|
|
410
|
+
</Content>
|
|
411
|
+
</Content>
|
|
412
|
+
<div
|
|
413
|
+
style={{
|
|
414
|
+
backgroundColor: "var(--color-surface--background)",
|
|
415
|
+
padding: "var(--space-base)",
|
|
416
|
+
}}
|
|
417
|
+
>
|
|
418
|
+
<Button
|
|
419
|
+
variation="subtle"
|
|
420
|
+
type="tertiary"
|
|
421
|
+
icon="search"
|
|
422
|
+
aria-label="search"
|
|
423
|
+
/>
|
|
424
|
+
<Button
|
|
425
|
+
variation="subtle"
|
|
426
|
+
type="tertiary"
|
|
427
|
+
icon="cog"
|
|
428
|
+
aria-label="settings"
|
|
429
|
+
/>
|
|
430
|
+
<Button
|
|
431
|
+
variation="subtle"
|
|
432
|
+
type="tertiary"
|
|
433
|
+
icon="help"
|
|
434
|
+
aria-label="help"
|
|
435
|
+
/>
|
|
436
|
+
<Button
|
|
437
|
+
variation="subtle"
|
|
438
|
+
type="tertiary"
|
|
439
|
+
icon="more"
|
|
440
|
+
aria-label="more"
|
|
441
|
+
/>
|
|
442
|
+
</div>
|
|
443
|
+
</Content>
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
## Content guidelines
|
|
449
|
+
|
|
450
|
+
Effective button labels are clear, concise, and action-driven. They help SPs
|
|
451
|
+
feel confident about what will happen next. These guidelines are focused on text
|
|
452
|
+
inside buttons, not hover labels or tooltip content.
|
|
453
|
+
|
|
454
|
+
#### Mental model: What will happen when I click this
|
|
455
|
+
|
|
456
|
+
Use **verb-first phrasing** to emphasize action and reduce hesitation.
|
|
457
|
+
|
|
458
|
+
Button text should reflect the outcome of the action. Not necessarily the
|
|
459
|
+
system's implementation.
|
|
460
|
+
|
|
461
|
+
Remember that SPs are often working quickly; on mobile, between visits, or in
|
|
462
|
+
the field. That means buttons should support fast, confident decision-making.
|
|
463
|
+
|
|
464
|
+
| ✅ Do | ❌ Don’t |
|
|
465
|
+
| ------------ | ---------------- |
|
|
466
|
+
| Send Invoice | Continue to Send |
|
|
467
|
+
| Save Job | Click Here |
|
|
468
|
+
| Mark as Done | Done |
|
|
469
|
+
|
|
470
|
+
#### Reflect the outcome
|
|
471
|
+
|
|
472
|
+
It's a good idea to focus on the outcome of the action with buttons, rather than
|
|
473
|
+
exposing technical complexity (unless it's particularly meaningful to SPs).
|
|
474
|
+
|
|
475
|
+
| ✅ Do | ❌ Don’t |
|
|
476
|
+
| --------------- | ------------------------ |
|
|
477
|
+
| Download Report | Export to CSV |
|
|
478
|
+
| Send Quote | Generate PDF |
|
|
479
|
+
| Schedule Visit | Create Visit in Schedule |
|
|
480
|
+
|
|
481
|
+
SPs think in terms of **visits, quotes, jobs, and invoices**. Not CSV files or
|
|
482
|
+
data exports. At Jobber, we prefer terminology grounded in the workflow of
|
|
483
|
+
running a service business.
|
|
484
|
+
|
|
485
|
+
#### Keep it concise
|
|
486
|
+
|
|
487
|
+
* Aim for **2–3 words**
|
|
488
|
+
* Don’t abbreviate unless the meaning is universally known
|
|
489
|
+
* Avoid truncation, ellipses, or filler words like “Please” or “Now”
|
|
490
|
+
|
|
491
|
+
| ✅ Do | ❌ Don’t |
|
|
492
|
+
| ---------- | ------------------ |
|
|
493
|
+
| Add Client | Add a New Client |
|
|
494
|
+
| Delete | Delete Permanently |
|
|
495
|
+
| Sign Up | Sign Up Now |
|
|
496
|
+
|
|
497
|
+
Try to default to being concise. It helps reduce visual noise, especially on
|
|
498
|
+
mobile. Key for SPs using Jobber on the go.
|
|
499
|
+
|
|
500
|
+
#### Use title case
|
|
501
|
+
|
|
502
|
+
Capitalize all major words in button labels. Don't capitalize:
|
|
503
|
+
|
|
504
|
+
* Articles: *a, an, the*
|
|
505
|
+
* Coordinating conjunctions: *and, but, or*
|
|
506
|
+
* Short prepositions: *to, by, at*
|
|
507
|
+
|
|
508
|
+
| ✅ Do | ❌ Don’t |
|
|
509
|
+
| ------------ | ------------ |
|
|
510
|
+
| Go to Visits | Go To Visits |
|
|
511
|
+
| Save Job | SAVE JOB |
|
|
512
|
+
|
|
513
|
+
Title case supports scannability and will help us maintain visual consistency
|
|
514
|
+
across SP workflows.
|
|
515
|
+
|
|
516
|
+
#### Avoid ampersands
|
|
517
|
+
|
|
518
|
+
Avoid using ampersands in buttons. They’re often introduced to save space, but
|
|
519
|
+
they create inconsistency and visual clutter. Put simply, they draw attention to
|
|
520
|
+
the most irrelevant part of the sentence.
|
|
521
|
+
|
|
522
|
+
Use “and” unless there’s a strong reason not to—and even then, consider
|
|
523
|
+
simplifying the label instead.
|
|
524
|
+
|
|
525
|
+
| ✅ Do | ❌ Don’t |
|
|
526
|
+
| -------------------- | ------------------ |
|
|
527
|
+
| Review and Send | Review & Send |
|
|
528
|
+
| Approve and Schedule | Approve & Schedule |
|
|
529
|
+
|
|
530
|
+
#### Be specific
|
|
531
|
+
|
|
532
|
+
Generic CTAs like “Submit” or “Continue” generally don’t give SPs confidence.
|
|
533
|
+
That said, they are fine if there's another visual indicator of what comes next
|
|
534
|
+
E.g. a stepper.
|
|
535
|
+
|
|
536
|
+
When there's no other indication of what is coming next, try to be explicit
|
|
537
|
+
about what the button does or what's to come.
|
|
538
|
+
|
|
539
|
+
| ✅ Do | ❌ Don’t |
|
|
540
|
+
| ---------------- | -------- |
|
|
541
|
+
| Book Appointment | Submit |
|
|
542
|
+
| Send Quote | Continue |
|
|
543
|
+
|
|
544
|
+
#### Buttons in confirmation modals
|
|
545
|
+
|
|
546
|
+
In confirmation modals, button labels should reinforce the decision the SP is
|
|
547
|
+
making—not just echo the UI element that triggered it.
|
|
548
|
+
|
|
549
|
+
**Primary action buttons should restate the consequence of the action.** This
|
|
550
|
+
helps avoid second-guessing and reduces accidental taps.
|
|
551
|
+
|
|
552
|
+
| ✅ Do | ❌ Don’t |
|
|
553
|
+
| ---------------- | ----------- |
|
|
554
|
+
| Delete Visit | Yes, Delete |
|
|
555
|
+
| Delete Timesheet | Confirm |
|
|
556
|
+
| Send Invoice | Submit |
|
|
557
|
+
| Remove Line Item | OK |
|
|
558
|
+
|
|
559
|
+
**Secondary buttons** should be clear but low-friction. Stick with **Go Back**,
|
|
560
|
+
unless you need to clarify the context.
|
|
561
|
+
|
|
562
|
+
We want to avoid questions as titles in confirmation modals, as this can add to
|
|
563
|
+
visual clutter and increase the cognitive load. As a result, the button should
|
|
564
|
+
reflect that. No answering a question, just confirming the action.
|
|
565
|
+
|
|
566
|
+
## Do's and Don'ts
|
|
567
|
+
|
|
568
|
+
In summary, here are some general rules to follow when working with the button
|
|
569
|
+
component:
|
|
570
|
+
|
|
571
|
+
#### Do:
|
|
572
|
+
|
|
573
|
+
* ✅ Use clear, verb-first labels that describe the outcome
|
|
574
|
+
* ✅ Keep button text short (1–3 words max)
|
|
575
|
+
* ✅ Use title case for button labels
|
|
576
|
+
* ✅ Show a loading state for async actions
|
|
577
|
+
* ✅ Use one primary button per view
|
|
578
|
+
* ✅ Use hierarchy (primary, secondary, tertiary) to guide attention
|
|
579
|
+
* ✅ Use destructive styling only for real deletions
|
|
580
|
+
* ✅ Place buttons near the content or object they act on
|
|
581
|
+
* ✅ Pair “Learn More” learning buttons with clear supporting content
|
|
582
|
+
* ✅ Ensure icon-only buttons have accessible labels
|
|
583
|
+
|
|
584
|
+
#### Don't:
|
|
585
|
+
|
|
586
|
+
* ❌ Use vague or conversational labels like “Yes” or “Okay”
|
|
587
|
+
* ❌ Stack multiple primary buttons together
|
|
588
|
+
* ❌ Style non-destructive actions (like “Archive”) as destructive
|
|
589
|
+
* ❌ Position buttons too far away from the related content
|
|
590
|
+
* ❌ Rely on the button label alone to explain what it does
|
|
591
|
+
* ❌ Assume icons are self-explanatory without text or `aria-label`
|
|
592
|
+
|
|
593
|
+
## Accessibility notes
|
|
594
|
+
|
|
595
|
+
* Avoid using disabled buttons when possible—they increase complexity and make
|
|
596
|
+
it harder for SPs to understand what to do next
|
|
597
|
+
|
|
598
|
+
* If a button uses only an icon, include an `aria-label` so screen readers can
|
|
599
|
+
describe the action
|
|
600
|
+
|
|
601
|
+
* Show clear feedback when a button is tapped or clicked. Use a loading state
|
|
602
|
+
where applicable to prevent repeated taps
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
## Configuration
|
|
606
|
+
|
|
607
|
+
### Client-side routing (web only)
|
|
608
|
+
|
|
609
|
+
A Button can be used for client-side routing as well. When using a Button to
|
|
610
|
+
handle the client-side routing, use the `to` prop. Notice when you click below
|
|
611
|
+
that the URL will change to the appropriate route. See
|
|
612
|
+
[Web/Client Side Routing example](/storybook/web/?path=/story/components-actions-button--client-side-routing).
|
|
613
|
+
|
|
614
|
+
### Form submit (web only)
|
|
615
|
+
|
|
616
|
+
Passing the `submit` prop will allow a Button to submit a
|
|
617
|
+
[Form](../Form/Form.md). Since submitting a form is a specific action, only a
|
|
618
|
+
form is a specific action, only `variation="work"` and `type="primary"` are
|
|
619
|
+
allowed. See
|
|
620
|
+
[Web/Form Submit example](/storybook/web/?path=/story/components-actions-button--form-submit)
|
|
621
|
+
|
|
622
|
+
Since this type of `Button` will only be used to submit a form, it does not make
|
|
623
|
+
sense to allow the `external`, `onClick`, `to`, or `url` props.
|
|
624
|
+
|
|
625
|
+
## Component customization
|
|
626
|
+
|
|
627
|
+
### Composable usage (web only)
|
|
628
|
+
|
|
629
|
+
The Button component is built with the `Button.Label`, `Button.Icon` components.
|
|
630
|
+
This composition is the recommended way to customize the Button component
|
|
631
|
+
instead of the prop driven usages.
|
|
632
|
+
|
|
633
|
+
`Button.Label` is used to display the label of the button.
|
|
634
|
+
|
|
635
|
+
`Button.Icon` is used to display an icon on the button.
|
|
636
|
+
|
|
637
|
+
Buttons with icons and labels can be converted using the following example:
|
|
638
|
+
|
|
639
|
+
```tsx
|
|
640
|
+
<Button icon="add" label="Add" />
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
becomes
|
|
644
|
+
|
|
645
|
+
```tsx
|
|
646
|
+
<Button>
|
|
647
|
+
<Button.Icon name="add" />
|
|
648
|
+
<Button.Label>Add</Button.Label>
|
|
649
|
+
</Button>
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
To convert a button with an icon on the right, use the following example:
|
|
653
|
+
|
|
654
|
+
```tsx
|
|
655
|
+
<Button icon="add" label="Add" iconOnRight />
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
becomes
|
|
659
|
+
|
|
660
|
+
```tsx
|
|
661
|
+
<Button>
|
|
662
|
+
<Button.Label>Add</Button.Label>
|
|
663
|
+
<Button.Icon name="add" />
|
|
664
|
+
</Button>
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
### Styling another component with Button styles
|
|
668
|
+
|
|
669
|
+
Using the `useButtonStyles` hook, the styles for a button can be applied to
|
|
670
|
+
another component. This is useful for styling Client-side routing links to look
|
|
671
|
+
like a Button.
|
|
672
|
+
|
|
673
|
+
`useButtonStyles` is a hook that provides three sets of styles:
|
|
674
|
+
|
|
675
|
+
* `wrapper`: The styles for the button wrapper. This handles the background
|
|
676
|
+
color, border radius, and padding.
|
|
677
|
+
* `children`: The styles for the button children. This handles the icon and
|
|
678
|
+
label spacing.
|
|
679
|
+
* `combined`: The combined styles of `wrapper` and `children`. This is useful if
|
|
680
|
+
you don't want to customize the styles
|
|
681
|
+
|
|
682
|
+
The following example shows how to do this with React Router:
|
|
683
|
+
|
|
684
|
+
```tsx
|
|
685
|
+
import { Link } from "react-router-dom";
|
|
686
|
+
|
|
687
|
+
function LinkButton() {
|
|
688
|
+
const buttonStyles = useButtonStyles({
|
|
689
|
+
type: "tertiary",
|
|
690
|
+
variation: "subtle",
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
return (
|
|
694
|
+
<Link
|
|
695
|
+
to="/"
|
|
696
|
+
className={classnames(buttonStyles.wrapper, buttonStyles.children)}
|
|
697
|
+
// or
|
|
698
|
+
className={buttonStyles.combined}
|
|
699
|
+
>
|
|
700
|
+
<Button.Label>Navigate Home</Button.Label>
|
|
701
|
+
<Button.Icon name="home" />
|
|
702
|
+
</Link>
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### UNSAFE\_ props (advanced usage)
|
|
708
|
+
|
|
709
|
+
General information for using `UNSAFE_` props can be found
|
|
710
|
+
[here](../customizing-components/customizing-components.md).
|
|
711
|
+
|
|
712
|
+
**Note**: Use of `UNSAFE_` props is **at your own risk** and should be
|
|
713
|
+
considered a **last resort**. Future Button updates may lead to unintended
|
|
714
|
+
breakages.
|
|
715
|
+
|
|
716
|
+
**Use of !important** You will see that `!important` is used for `path.fill` of
|
|
717
|
+
Icon's UNSAFE props. This is needed since Button's children element `fill` is
|
|
718
|
+
set to `inherit !important`. *However*, in React `!important` is unreliable with
|
|
719
|
+
`style` attribute when used with non css variable colors.
|
|
720
|
+
|
|
721
|
+
#### UNSAFE\_className and UNSAFE\_style (web)
|
|
722
|
+
|
|
723
|
+
The Button component has multiple elements that can be targeted with classes or
|
|
724
|
+
styles:
|
|
725
|
+
|
|
726
|
+
* `container`: The root button element
|
|
727
|
+
* `buttonLabel`: The text label element of the Button
|
|
728
|
+
* `buttonIcon`: The icon element of the Button
|
|
729
|
+
|
|
730
|
+
**Note** that `buttonLabel` and `buttonIcon` are to be used in a non-composed
|
|
731
|
+
Button. If you're using the composed Button with children, you should use the
|
|
732
|
+
UNSAFE props on the sub-components.
|
|
733
|
+
|
|
734
|
+
### UNSAFE\_className
|
|
735
|
+
|
|
736
|
+
Use `UNSAFE_className` to apply custom classes to the Button. This can be useful
|
|
737
|
+
for applying styles via CSS Modules.
|
|
738
|
+
|
|
739
|
+
##### Non composed UNSAFE\_className usage
|
|
740
|
+
|
|
741
|
+
```tsx
|
|
742
|
+
<Button
|
|
743
|
+
label="Custom styling with className"
|
|
744
|
+
icon="add"
|
|
745
|
+
UNSAFE_className={{
|
|
746
|
+
container: styles.customButton,
|
|
747
|
+
buttonLabel: { textStyle: styles.customLabel },
|
|
748
|
+
buttonIcon: { svg: styles.customIcon, path: styles.customIconPath },
|
|
749
|
+
}}
|
|
750
|
+
/>
|
|
751
|
+
|
|
752
|
+
// css
|
|
753
|
+
.customButton {
|
|
754
|
+
border-radius: 24px;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
.customLabel {
|
|
758
|
+
color: var(--color-blue);
|
|
759
|
+
text-transform: uppercase;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
.customIcon {
|
|
763
|
+
background-color: var(--color-red);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
.customIconPath {
|
|
767
|
+
fill: var(--color-green) !important;
|
|
768
|
+
}
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
##### Composed UNSAFE\_className usage
|
|
772
|
+
|
|
773
|
+
```tsx
|
|
774
|
+
<Button>
|
|
775
|
+
<Button.Icon
|
|
776
|
+
name="sparkles"
|
|
777
|
+
UNSAFE_className={{ svg: styles.customIcon, path: styles.customIconPath }}
|
|
778
|
+
/>
|
|
779
|
+
<Button.Label
|
|
780
|
+
UNSAFE_className={{
|
|
781
|
+
textStyle: styles.customLabel,
|
|
782
|
+
}}
|
|
783
|
+
>
|
|
784
|
+
label 1
|
|
785
|
+
</Button.Label>
|
|
786
|
+
</Button>
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
### UNSAFE\_style
|
|
790
|
+
|
|
791
|
+
The `UNSAFE_style` prop provides granular control over the Button's appearance
|
|
792
|
+
through inline styles. The structure mirrors `UNSAFE_className` to allow for
|
|
793
|
+
consistent styling patterns.
|
|
794
|
+
|
|
795
|
+
##### Non composed UNSAFE\_style usage
|
|
796
|
+
|
|
797
|
+
```tsx
|
|
798
|
+
<Button
|
|
799
|
+
label="Custom styling with style"
|
|
800
|
+
icon="sparkles"
|
|
801
|
+
UNSAFE_style={{
|
|
802
|
+
container: {
|
|
803
|
+
borderRadius: "24px",
|
|
804
|
+
},
|
|
805
|
+
buttonLabel: {
|
|
806
|
+
textStyle: {
|
|
807
|
+
color: "var(--color-blue)",
|
|
808
|
+
textTransform: "uppercase",
|
|
809
|
+
},
|
|
810
|
+
},
|
|
811
|
+
buttonIcon: {
|
|
812
|
+
svg: {
|
|
813
|
+
backgroundColor: "var(--color-red)",
|
|
814
|
+
},
|
|
815
|
+
path: {
|
|
816
|
+
fill: "var(--color-green) !important",
|
|
817
|
+
},
|
|
818
|
+
},
|
|
819
|
+
}}
|
|
820
|
+
/>
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
##### Composed UNSAFE\_style usage
|
|
824
|
+
|
|
825
|
+
```tsx
|
|
826
|
+
<Button UNSAFE_style={{ borderRadius: "24px" }}>
|
|
827
|
+
<Button.Icon
|
|
828
|
+
name="sparkles"
|
|
829
|
+
UNSAFE_style={{
|
|
830
|
+
svg: { backgroundColor: "var(--color-red)" },
|
|
831
|
+
path: { fill: "var(--color-green) !important" },
|
|
832
|
+
}}
|
|
833
|
+
/>
|
|
834
|
+
<Button.Label
|
|
835
|
+
UNSAFE_style={{
|
|
836
|
+
textStyle: {
|
|
837
|
+
color: "var(--color-red)",
|
|
838
|
+
textDecoration: "underline",
|
|
839
|
+
},
|
|
840
|
+
}}
|
|
841
|
+
>
|
|
842
|
+
label 1
|
|
843
|
+
</Button.Label>
|
|
844
|
+
</Button>
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
#### UNSAFE\_style (mobile)
|
|
848
|
+
|
|
849
|
+
The mobile Button component has four elements that can be targeted with styles.
|
|
850
|
+
These are the container, content container, icon container, and action label
|
|
851
|
+
container.
|
|
852
|
+
|
|
853
|
+
React Native does not support className. Instead, you can use `UNSAFE_style` to
|
|
854
|
+
apply styles either inline or through a StyleSheet.
|
|
855
|
+
|
|
856
|
+
##### Inline styles
|
|
857
|
+
|
|
858
|
+
```tsx
|
|
859
|
+
UNSAFE_style: {
|
|
860
|
+
container: { backgroundColor: tokens["color-purple--light"] },
|
|
861
|
+
contentContainer: {
|
|
862
|
+
backgroundColor: tokens["color-purple--lighter"],
|
|
863
|
+
borderRadius: tokens["radius-large"],
|
|
864
|
+
},
|
|
865
|
+
iconContainer: { backgroundColor: tokens["color-purple"] },
|
|
866
|
+
actionLabelContainer: { paddingLeft: tokens["space-larger"] },
|
|
867
|
+
},
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
##### StyleSheet
|
|
871
|
+
|
|
872
|
+
```tsx
|
|
873
|
+
// Button.tsx
|
|
874
|
+
UNSAFE_style={{
|
|
875
|
+
container: styles.customContainer,
|
|
876
|
+
contentContainer: styles.customContentContainer,
|
|
877
|
+
iconContainer: styles.customIconContainer,
|
|
878
|
+
actionLabelContainer: styles.customActionLabelContainer,
|
|
879
|
+
}}
|
|
880
|
+
|
|
881
|
+
// Button.style.ts
|
|
882
|
+
export const styles = StyleSheet.create({
|
|
883
|
+
customContainer: {
|
|
884
|
+
backgroundColor: tokens["color-purple--light"],
|
|
885
|
+
},
|
|
886
|
+
customContentContainer: {
|
|
887
|
+
borderRadius: tokens["radius-large"],
|
|
888
|
+
},
|
|
889
|
+
customIconContainer: {
|
|
890
|
+
backgroundColor: tokens["color-purple--lighter"],
|
|
891
|
+
},
|
|
892
|
+
customActionLabelContainer: {
|
|
893
|
+
paddingLeft: tokens["space-larger"],
|
|
894
|
+
},
|
|
895
|
+
});
|
|
896
|
+
```
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
## Props
|
|
900
|
+
|
|
901
|
+
### Mobile
|
|
902
|
+
|
|
903
|
+
| Prop | Type | Required | Default | Description |
|
|
904
|
+
|------|------|----------|---------|-------------|
|
|
905
|
+
| `accessibilityHint` | `string` | No | — | Accessibility hint to help users understand what will happen when they press the button |
|
|
906
|
+
| `accessibilityLabel` | `string` | No | — | Accessibility label for the component. This is required for components that have an `icon` but not a `label`. If the... |
|
|
907
|
+
| `disabled` | `boolean` | No | `false` | Makes the button un-clickable |
|
|
908
|
+
| `fullHeight` | `boolean` | No | `false` | Will make the button scale to take up all the available height |
|
|
909
|
+
| `fullWidth` | `boolean` | No | `true` | Will make the button scale to take up all of the available width |
|
|
910
|
+
| `icon` | `IconNames` | No | — | Adds an leading icon beside the label. |
|
|
911
|
+
| `label` | `string` | No | — | Text to be displayed on the button |
|
|
912
|
+
| `loading` | `boolean` | No | `false` | Changes the button interface to imply loading and prevents the press callback |
|
|
913
|
+
| `onPress` | `() => void` | No | — | Press handler |
|
|
914
|
+
| `size` | `ButtonSize` | No | `base` | Defines the size of the button |
|
|
915
|
+
| `testID` | `string` | No | — | Used to locate this view in end-to-end tests. |
|
|
916
|
+
| `type` | `ButtonType` | No | `primary` | Sets the visual hierarchy |
|
|
917
|
+
| `UNSAFE_style` | `ButtonUnsafeStyle` | No | — | **Use at your own risk:** Custom style for specific elements. This should only be used as a **last resort**. Using th... |
|
|
918
|
+
| `variation` | `ButtonVariation` | No | `work` | Themes the button to the type of action it performs |
|