@hubspot/ui-extensions 0.0.0 → 0.0.1-beta.0
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/README.md +1715 -0
- package/dist/coreComponents.d.ts +167 -0
- package/dist/coreComponents.js +35 -0
- package/dist/crm/components.d.ts +27 -0
- package/dist/crm/components.js +7 -0
- package/dist/crm/index.d.ts +2 -0
- package/dist/crm/index.js +2 -0
- package/dist/hubspot.d.ts +7 -0
- package/dist/hubspot.js +17 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/types.d.ts +433 -0
- package/dist/types.js +17 -0
- package/dist/utils/createExtensionComponent.d.ts +3 -0
- package/dist/utils/createExtensionComponent.js +4 -0
- package/package.json +39 -4
- package/components.ts +0 -92
- package/hubspot.ts +0 -20
- package/index.ts +0 -24
- package/types.ts +0 -213
package/README.md
ADDED
|
@@ -0,0 +1,1715 @@
|
|
|
1
|
+
# UI Extensions
|
|
2
|
+
|
|
3
|
+
React components and utilities for extending HubSpot's UI.
|
|
4
|
+
|
|
5
|
+
## TOC
|
|
6
|
+
|
|
7
|
+
- [Alert](#alert)
|
|
8
|
+
- [Button](#button)
|
|
9
|
+
- [ButtonRow](#buttonrow)
|
|
10
|
+
- [Card](#card)
|
|
11
|
+
- [DescriptionList](#descriptionlist)
|
|
12
|
+
- [DescriptionListItem](#descriptionlistitem)
|
|
13
|
+
- [Divider](#divider)
|
|
14
|
+
- [Form](#form)
|
|
15
|
+
- [EmptyState](#emptystate)
|
|
16
|
+
- [ErrorState](#errorstate)
|
|
17
|
+
- [Heading](#heading)
|
|
18
|
+
- [Image](#image)
|
|
19
|
+
- [Input](#input)
|
|
20
|
+
- [Link](#link)
|
|
21
|
+
- [LoadingSpinner](#loadingspinner)
|
|
22
|
+
- [ProgressBar](#progressbar)
|
|
23
|
+
- [Select](#select)
|
|
24
|
+
- [Stack](#stack)
|
|
25
|
+
- [Statistics](#statistics)
|
|
26
|
+
- [StatisticsItem](#statisticsitem)
|
|
27
|
+
- [StatisticsTrend](#statisticstrend)
|
|
28
|
+
- [Table](#table)
|
|
29
|
+
- [TableBody](#tablebody)
|
|
30
|
+
- [TableCell](#tablecell)
|
|
31
|
+
- [TableFooter](#tablefooter)
|
|
32
|
+
- [TableHead](#tablehead)
|
|
33
|
+
- [TableHeader](#tableheader)
|
|
34
|
+
- [TableRow](#tablerow)
|
|
35
|
+
- [Tag](#tag)
|
|
36
|
+
- [Text](#text)
|
|
37
|
+
- [Textarea](#textarea)
|
|
38
|
+
- [Tile](#tile)
|
|
39
|
+
- [ToggleGroup](#togglegroup)
|
|
40
|
+
|
|
41
|
+
## Components
|
|
42
|
+
|
|
43
|
+
### Alert
|
|
44
|
+
|
|
45
|
+
##### Import
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
import { Alert } from '@hubspot/ui-extensions';
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
##### Props
|
|
52
|
+
|
|
53
|
+
The Alert component accepts the following props:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
export interface AlertProps {
|
|
57
|
+
title: string;
|
|
58
|
+
body?: string;
|
|
59
|
+
children?: ReactNode;
|
|
60
|
+
variant?: 'info' | 'warning' | 'success' | 'error' | 'danger';
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
| Prop | Type | Default | Description |
|
|
65
|
+
| --- | --- | --- | --- |
|
|
66
|
+
| `title` | `string` | `N/A` | The title text for the alert message. |
|
|
67
|
+
| `body` | `string(optional)` | `N/A` | The main content of the alert message. If not provided, the children prop is used. |
|
|
68
|
+
| `children` | `ReactNode(optional)` | `N/A` | The main content of the alert message when the body prop is not provided. |
|
|
69
|
+
| `variant` | `'info' \| 'warning' \| 'success' \|'error' \| 'danger'` `(optional)` | `'info'` | Sets the color variation of the alert |
|
|
70
|
+
|
|
71
|
+
##### Usage
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
const Extension = () => {
|
|
75
|
+
return (
|
|
76
|
+
<>
|
|
77
|
+
<Alert title="Important Info" variant="info">
|
|
78
|
+
This is an informative message.
|
|
79
|
+
</Alert>
|
|
80
|
+
<Alert
|
|
81
|
+
title="Success"
|
|
82
|
+
body="Operation completed successfully."
|
|
83
|
+
variant="success"
|
|
84
|
+
/>
|
|
85
|
+
<Alert title="Warning" body="Proceed with caution." variant="warning" />
|
|
86
|
+
<Alert
|
|
87
|
+
title="Error"
|
|
88
|
+
body="Something went wrong. Please try again."
|
|
89
|
+
variant="error"
|
|
90
|
+
/>
|
|
91
|
+
<Alert
|
|
92
|
+
title="Danger"
|
|
93
|
+
body="This action cannot be undone. Be careful."
|
|
94
|
+
variant="danger"
|
|
95
|
+
/>
|
|
96
|
+
</>
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Button
|
|
102
|
+
|
|
103
|
+
##### Import
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
import { Button } from '@hubspot/ui-extensions';
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
##### Props
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
interface ButtonProps {
|
|
113
|
+
children: string;
|
|
114
|
+
onClick?: () => void;
|
|
115
|
+
href?: string;
|
|
116
|
+
disabled?: boolean;
|
|
117
|
+
variant?: 'primary' | 'secondary' | 'destructive';
|
|
118
|
+
type?: 'button' | 'reset' | 'submit';
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
| Prop | Type | Default | Description |
|
|
123
|
+
| --- | --- | --- | --- |
|
|
124
|
+
| `children` | `string` | `N/A` | The displayable text for the Button |
|
|
125
|
+
| `onClick` | `() => void` `(optional)` | `N/A` | A function that will be invoked when the button is clicked. It receives no arguments and it's return value is ignored |
|
|
126
|
+
| `href` | `string(optional)` | `N/A` | A URL that will be opened when the button is clicked. If the value is a URL external to HubSpot it will be opened in a new tab. |
|
|
127
|
+
| `disabled` | `boolean(optional)` | `N/A` | Determines if the button should be disabled or not. |
|
|
128
|
+
| `variant` | `'primary' \| 'secondary' \| 'destructive'` `(optional)` | `'secondary'` | Sets the color variation of the button |
|
|
129
|
+
| `type` | `'button' \| 'reset' \| 'submit'` `(optional)` | `'button'` | Sets the HTML attribute "role" of the button |
|
|
130
|
+
|
|
131
|
+
##### Usage
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
const Extension = () => {
|
|
135
|
+
return (
|
|
136
|
+
<Button
|
|
137
|
+
onClick={() => {
|
|
138
|
+
console.log('Someone clicked on the button!');
|
|
139
|
+
}}
|
|
140
|
+
href="https://hubspot.com"
|
|
141
|
+
variant="destructive"
|
|
142
|
+
type="button"
|
|
143
|
+
>
|
|
144
|
+
Click me!
|
|
145
|
+
</Button>
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### ButtonRow
|
|
151
|
+
|
|
152
|
+
##### Import
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
import { ButtonRow } from '@hubspot/ui-extensions';
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
##### Props
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
interface ButtonRowProps {
|
|
162
|
+
children: ReactNode;
|
|
163
|
+
disableDropdown?: boolean;
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
| Prop | Type | Default | Description |
|
|
168
|
+
| --- | --- | --- | --- |
|
|
169
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. |
|
|
170
|
+
| `disableDropdown` | `boolean(optional)` | `false` | Disables the dropdown list of buttons that appears the the children expand beyond the horizontal space |
|
|
171
|
+
|
|
172
|
+
##### Usage
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
const Extension = () => {
|
|
176
|
+
return (
|
|
177
|
+
<ButtonRow disableDropdown={false}>
|
|
178
|
+
<Button
|
|
179
|
+
onClick={() => {
|
|
180
|
+
console.log('Regular button clicked');
|
|
181
|
+
}}
|
|
182
|
+
>
|
|
183
|
+
Regular Button
|
|
184
|
+
</Button>
|
|
185
|
+
<Button
|
|
186
|
+
onClick={() => {
|
|
187
|
+
console.log('Reset button clicked');
|
|
188
|
+
}}
|
|
189
|
+
variant="destructive"
|
|
190
|
+
type="reset"
|
|
191
|
+
>
|
|
192
|
+
Reset
|
|
193
|
+
</Button>
|
|
194
|
+
<Button
|
|
195
|
+
onClick={() => {
|
|
196
|
+
console.log('Submit button clicked');
|
|
197
|
+
}}
|
|
198
|
+
variant="primary"
|
|
199
|
+
type="submit"
|
|
200
|
+
>
|
|
201
|
+
Submit
|
|
202
|
+
</Button>
|
|
203
|
+
</ButtonRow>
|
|
204
|
+
);
|
|
205
|
+
};
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Card
|
|
209
|
+
|
|
210
|
+
##### Import
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
import { Card } from '@hubspot/ui-extensions';
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
##### Props
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
interface CardProps {
|
|
220
|
+
children: ReactNode;
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
| Prop | Type | Default | Description |
|
|
225
|
+
| --- | --- | --- | --- |
|
|
226
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. |
|
|
227
|
+
|
|
228
|
+
##### Usage
|
|
229
|
+
|
|
230
|
+
```javascript
|
|
231
|
+
const Extension = () => {
|
|
232
|
+
return (
|
|
233
|
+
<Card>
|
|
234
|
+
<Button
|
|
235
|
+
onClick={() => {
|
|
236
|
+
console.log('Regular button clicked');
|
|
237
|
+
}}
|
|
238
|
+
>
|
|
239
|
+
Regular Button
|
|
240
|
+
</Button>
|
|
241
|
+
</Card>
|
|
242
|
+
);
|
|
243
|
+
};
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### DescriptionList
|
|
247
|
+
|
|
248
|
+
##### Import
|
|
249
|
+
|
|
250
|
+
```javascript
|
|
251
|
+
import { DescriptionList } from '@hubspot/ui-extensions';
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
##### Props
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
interface DescriptionListProps {
|
|
258
|
+
children: ReactNode;
|
|
259
|
+
direction?: 'row' | 'column';
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
| Prop | Type | Default | Description |
|
|
264
|
+
| --- | --- | --- | --- |
|
|
265
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. The children should be [DescriptionListItem](#descriptionlistitem) |
|
|
266
|
+
| `direction` | `'row' \| 'column'` `(optional)` | `'column'` | The direction the label/value pairs are placed in the description list container. |
|
|
267
|
+
|
|
268
|
+
##### Usage
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
const Extension = () => {
|
|
272
|
+
return (
|
|
273
|
+
<DescriptionList direction="row">
|
|
274
|
+
<DescriptionListItem label={'First Name'}>
|
|
275
|
+
<Text>Alan</Text>
|
|
276
|
+
</DescriptionListItem>
|
|
277
|
+
<DescriptionListItem label={'Last Name'}>
|
|
278
|
+
<Text>Turing</Text>
|
|
279
|
+
</DescriptionListItem>
|
|
280
|
+
</DescriptionList>
|
|
281
|
+
);
|
|
282
|
+
};
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### DescriptionListItem
|
|
286
|
+
|
|
287
|
+
##### Import
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
import { DescriptionListItem } from '@hubspot/ui-extensions';
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
##### Props
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
interface DescriptionListItemProps {
|
|
297
|
+
children: ReactNode;
|
|
298
|
+
label: string;
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
| Prop | Type | Default | Description |
|
|
303
|
+
| --- | --- | --- | --- |
|
|
304
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. |
|
|
305
|
+
| `label` | `string` | `N/A` | Text to be displayed as the label |
|
|
306
|
+
|
|
307
|
+
##### Usage
|
|
308
|
+
|
|
309
|
+
```javascript
|
|
310
|
+
const Extension = () => {
|
|
311
|
+
return (
|
|
312
|
+
<DescriptionList direction="row">
|
|
313
|
+
<DescriptionListItem label={'First Name'}>
|
|
314
|
+
<Text>Alan</Text>
|
|
315
|
+
</DescriptionListItem>
|
|
316
|
+
<DescriptionListItem label={'Last Name'}>
|
|
317
|
+
<Text>Turing</Text>
|
|
318
|
+
</DescriptionListItem>
|
|
319
|
+
</DescriptionList>
|
|
320
|
+
);
|
|
321
|
+
};
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Divider
|
|
325
|
+
|
|
326
|
+
##### Import
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
import { Divider } from '@hubspot/ui-extensions';
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
##### Props
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
interface DividerProps {
|
|
336
|
+
distance?:
|
|
337
|
+
| 'flush'
|
|
338
|
+
| 'extra-small'
|
|
339
|
+
| 'small'
|
|
340
|
+
| 'medium'
|
|
341
|
+
| 'large'
|
|
342
|
+
| 'extra-large';
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
| Prop | Type | Default | Description |
|
|
347
|
+
| --- | --- | --- | --- |
|
|
348
|
+
| `distance` | `'flush'\| 'extra-small' \| 'small' \| 'medium' \| 'large'\| 'extra-large'` `(optional)` | `'small'` | The size of the padding above and below the divider. |
|
|
349
|
+
|
|
350
|
+
##### Usage
|
|
351
|
+
|
|
352
|
+
```javascript
|
|
353
|
+
const Extension = () => {
|
|
354
|
+
return <Divider distance="extra-large" />;
|
|
355
|
+
};
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Form
|
|
359
|
+
|
|
360
|
+
##### Import
|
|
361
|
+
|
|
362
|
+
```javascript
|
|
363
|
+
import { Form } from '@hubspot/ui-extensions';
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
##### Props
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
interface FormProps {
|
|
370
|
+
children: ReactNode;
|
|
371
|
+
onSubmit?: (event: RemoteEvent<FormInputValues>) => void;
|
|
372
|
+
preventDefault?: boolean;
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
| Prop | Type | Default | Description |
|
|
377
|
+
| --- | --- | --- | --- |
|
|
378
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. |
|
|
379
|
+
| `onSubmit` | `function(optional)` | `N/A` | A function that will be called when the form is submitted. It will receive a `RemoteEvent` as argument and it's return value will be ignored. |
|
|
380
|
+
| `preventDefault` | `boolean(optional)` | `false` | If set to `true` `event.preventDefault()` will be invoked before your `onSubmit` function is called, preventing the default html form behavior. |
|
|
381
|
+
|
|
382
|
+
##### Usage
|
|
383
|
+
|
|
384
|
+
```javascript
|
|
385
|
+
const Extension = () => {
|
|
386
|
+
return (
|
|
387
|
+
<Form onSubmit={() => { console.log('Form submitted!')}} preventDefault={true}>
|
|
388
|
+
<Input {...} />
|
|
389
|
+
<Select {...} />
|
|
390
|
+
<Button
|
|
391
|
+
onClick={() => {
|
|
392
|
+
console.log('Submit button clicked');
|
|
393
|
+
}}
|
|
394
|
+
variant="primary"
|
|
395
|
+
type="submit"
|
|
396
|
+
>
|
|
397
|
+
Submit
|
|
398
|
+
</Button>
|
|
399
|
+
</Form>
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### EmptyState
|
|
405
|
+
|
|
406
|
+
##### Import
|
|
407
|
+
|
|
408
|
+
```javascript
|
|
409
|
+
import { EmptyState } from '@hubspot/ui-extensions';
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
##### Props
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
interface EmptyStateProps {
|
|
416
|
+
children: ReactNode;
|
|
417
|
+
flush?: boolean;
|
|
418
|
+
imageWidth?: number;
|
|
419
|
+
layout?: 'horizontal' | 'vertical';
|
|
420
|
+
reverseOrder?: boolean;
|
|
421
|
+
title?: string;
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
| Prop | Type | Default | Description |
|
|
426
|
+
| --- | --- | --- | --- |
|
|
427
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. |
|
|
428
|
+
| `flush` | `boolean(optional)` | `false` | Removes the default vertical margins for the component. |
|
|
429
|
+
| `imageWidth` | `number(optional)` | `250` | The max-width for the image container. |
|
|
430
|
+
| `layout` | `'horizontal' \| 'vertical'` `(optional)` | `'horizontal'` | Sets the layout direction for the content. |
|
|
431
|
+
| `reverseOrder` | `boolean(optional)` | `false` | Swaps the visual order of the text (primary) and image (secondary) content. This ensures the primary content is still presented first to assistive technology. |
|
|
432
|
+
| `title` | `string(optional)` | `Intl('All is not lost.')` | The text for the title header rendered above the `children`. |
|
|
433
|
+
|
|
434
|
+
##### Usage
|
|
435
|
+
|
|
436
|
+
```javascript
|
|
437
|
+
const Extension = ({ data }) => {
|
|
438
|
+
if (!data || !data.length) {
|
|
439
|
+
return (
|
|
440
|
+
<EmptyState title="Nothing here yet" layout="vertical" reverseOrder={true}>
|
|
441
|
+
<Text>Go out there and get some leads!</Text>
|
|
442
|
+
</EmptyState>
|
|
443
|
+
)
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return (
|
|
447
|
+
<Stack>
|
|
448
|
+
{data.map(...)}
|
|
449
|
+
</Stack>
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### ErrorState
|
|
455
|
+
|
|
456
|
+
##### Import
|
|
457
|
+
|
|
458
|
+
```javascript
|
|
459
|
+
import { ErrorState } from '@hubspot/ui-extensions';
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
##### Props
|
|
463
|
+
|
|
464
|
+
```typescript
|
|
465
|
+
interface ErrorStateProps {
|
|
466
|
+
children: ReactNode;
|
|
467
|
+
title?: string;
|
|
468
|
+
type?: 'error' | 'support' | 'lock';
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
| Prop | Type | Default | Description |
|
|
473
|
+
| --- | --- | --- | --- |
|
|
474
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. |
|
|
475
|
+
| `title` | `string(optional)` | `Intl('All is not lost.')` | The text for the title header rendered above the `children`. |
|
|
476
|
+
| `type` | `'error' \| 'support' \| 'lock'` `(optional)` | `'error'` | Sets the type of error image that will be shown. |
|
|
477
|
+
|
|
478
|
+
##### Usage
|
|
479
|
+
|
|
480
|
+
```javascript
|
|
481
|
+
const Extension = ({ data, error, fetchData }) => {
|
|
482
|
+
if (error) {
|
|
483
|
+
return (
|
|
484
|
+
<ErrorState title="Trouble fetching properties." layout="vertical" reverseOrder={true}>
|
|
485
|
+
<Stack>
|
|
486
|
+
<Text>
|
|
487
|
+
Please try again in a few moments.
|
|
488
|
+
</Text>
|
|
489
|
+
<Button onClick={fetchData}>
|
|
490
|
+
Try again
|
|
491
|
+
</Button>
|
|
492
|
+
</Stack>
|
|
493
|
+
</ErrorState>
|
|
494
|
+
)
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return (
|
|
498
|
+
<Stack>
|
|
499
|
+
{data.map(...)}
|
|
500
|
+
</Stack>
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### Heading
|
|
506
|
+
|
|
507
|
+
##### Import
|
|
508
|
+
|
|
509
|
+
```javascript
|
|
510
|
+
import { Heading } from '@hubspot/ui-extensions';
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
##### Props
|
|
514
|
+
|
|
515
|
+
```typescript
|
|
516
|
+
interface HeadingProps {
|
|
517
|
+
children: ReactNode;
|
|
518
|
+
inline?: boolean;
|
|
519
|
+
}
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
| Prop | Type | Default | Description |
|
|
523
|
+
| --- | --- | --- | --- |
|
|
524
|
+
| `children` | `string` | `N/A` | Text to be displayed as heading text. |
|
|
525
|
+
| `inline` | `boolean(optional)` | `false` | Determines if the text will break line or share the space. |
|
|
526
|
+
|
|
527
|
+
##### Usage
|
|
528
|
+
|
|
529
|
+
```javascript
|
|
530
|
+
const Extension = () => {
|
|
531
|
+
return <Heading>Plain text, nothing special here</Heading>;
|
|
532
|
+
};
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### Image
|
|
536
|
+
|
|
537
|
+
##### Import
|
|
538
|
+
|
|
539
|
+
```javascript
|
|
540
|
+
import { Image } from '@hubspot/ui-extensions';
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
##### Props
|
|
544
|
+
|
|
545
|
+
```typescript
|
|
546
|
+
interface ImageProps {
|
|
547
|
+
alt?: string;
|
|
548
|
+
href?: string;
|
|
549
|
+
onClick?: () => void;
|
|
550
|
+
src: string;
|
|
551
|
+
width?: number;
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
| Prop | Type | Description |
|
|
556
|
+
| --- | --- | --- |
|
|
557
|
+
| `alt` | `string(optional)` | The alt text for the image, similar to the `alt` attribute for the html [img tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attributes) |
|
|
558
|
+
| `href` | `string(optional)` | If provided, it will be used as a href that will be opened in a new tag when the image is clicked |
|
|
559
|
+
| `onClick` | `function(optional)` | A function that will be called when the image is clicked on. This function will receive no arguments any returned values will be ignored. |
|
|
560
|
+
| `src` | `string` | The url to the image to display, similar to [img tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attributes) |
|
|
561
|
+
| `width` | `number(optional)` | The pixel width of the image |
|
|
562
|
+
|
|
563
|
+
##### Usage
|
|
564
|
+
|
|
565
|
+
```javascript
|
|
566
|
+
const Extension = () => {
|
|
567
|
+
return (
|
|
568
|
+
<Image
|
|
569
|
+
alt="A picture of an adorable black lab puppy, click on me to see in a new tab"
|
|
570
|
+
src="https://picsum.photos/id/237/200/300"
|
|
571
|
+
href="https://picsum.photos/id/237"
|
|
572
|
+
onClick={() => {
|
|
573
|
+
console.log('Someone clicked on the image!');
|
|
574
|
+
}}
|
|
575
|
+
width={200}
|
|
576
|
+
/>
|
|
577
|
+
);
|
|
578
|
+
};
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### Input
|
|
582
|
+
|
|
583
|
+
##### Import
|
|
584
|
+
|
|
585
|
+
```javascript
|
|
586
|
+
import { Input } from '@hubspot/ui-extensions';
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
##### Props
|
|
590
|
+
|
|
591
|
+
```typescript
|
|
592
|
+
interface InputProps {
|
|
593
|
+
label: string;
|
|
594
|
+
name: string;
|
|
595
|
+
value?: string;
|
|
596
|
+
required?: boolean;
|
|
597
|
+
readOnly?: boolean;
|
|
598
|
+
description?: string;
|
|
599
|
+
tooltip?: string;
|
|
600
|
+
placeholder?: string;
|
|
601
|
+
error?: boolean;
|
|
602
|
+
validationMessage?: string;
|
|
603
|
+
onChange?: (value: string) => void;
|
|
604
|
+
onInput?: (value: string) => void;
|
|
605
|
+
onBlur?: (value: string) => void;
|
|
606
|
+
onFocus?: (value: string) => void;
|
|
607
|
+
}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
| Prop | Type | Default | Description |
|
|
611
|
+
| --- | --- | --- | --- |
|
|
612
|
+
| `label` | `string` | `N/A` | The label text to display for the form input element |
|
|
613
|
+
| `name` | `string` | `N/A` | The unique identifier for the input element, this could be thought of as the HTML5 [Input element's name attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#name) |
|
|
614
|
+
| `value` | `string(optional)` | `''` | The value of the input |
|
|
615
|
+
| `required` | `boolean(optional)` | `false` | Determines if the required indicator should be displayed |
|
|
616
|
+
| `readOnly` | `boolean(optional)` | `false` | Determines if the field is editable or not. |
|
|
617
|
+
| `description` | `string(optional)` | `N/A` | Instructional message to display to the user to help understand the purpose of the input. |
|
|
618
|
+
| `tooltip` | `string(optional)` | `N/A` | Text that will appear in a tooltip next to the input label. |
|
|
619
|
+
| `placeholder` | `string(optional)` | `N/A` | Text that appears in the input when it has no value set. |
|
|
620
|
+
| `error` | `boolean(optional)` | `false` | If set to true, `validationMessage` is displayed as an error message, if it was provided. The input will also render it's error state to let the user know there is an error. If false, `validationMessage` is displayed as a success message. |
|
|
621
|
+
| `validationMessage` | `string(optional)` | `''` | The text to show if the input has an error. |
|
|
622
|
+
| `onChange` | `(value: string) => void(optional)` | `N/A` | A callback function that is invoked when the value is committed. Currently these times are `onBlur` of the input and when the user submits the form. |
|
|
623
|
+
| `onInput` | `(value: string) => void(optional)` | `N/A` | A function that is called and passed the value every time the field is edited by the user. It is recommended that you do not use this value to update state, that is what `onChange` should be used for. Instead this should be used for validation. |
|
|
624
|
+
| `onBlur` | `(value: string) => void(optional)` | `N/A` | A function that is called and passed the value every time the field loses focus. |
|
|
625
|
+
| `onFocus` | `(value: string) => void(optional)` | `N/A` | A function that is called and passed the value every time the field gets focused. |
|
|
626
|
+
|
|
627
|
+
##### Usage
|
|
628
|
+
|
|
629
|
+
```javascript
|
|
630
|
+
import { useState } from 'react';
|
|
631
|
+
|
|
632
|
+
const Extension = () => {
|
|
633
|
+
const [name, setName] = useState('');
|
|
634
|
+
const [validationMessage, setValidationMessage] = useState('');
|
|
635
|
+
const [isValid, setIsValid] = useState(true);
|
|
636
|
+
|
|
637
|
+
return (
|
|
638
|
+
<Form>
|
|
639
|
+
<Input
|
|
640
|
+
label="First Name"
|
|
641
|
+
name="first-name"
|
|
642
|
+
tooltip="Please enter your first name"
|
|
643
|
+
description="Please enter your first name"
|
|
644
|
+
placeholder="First name"
|
|
645
|
+
required={true}
|
|
646
|
+
error={!isValid}
|
|
647
|
+
validationMessage={validationMessage}
|
|
648
|
+
onChange={value => {
|
|
649
|
+
setName(value);
|
|
650
|
+
}}
|
|
651
|
+
onInput={value => {
|
|
652
|
+
if (value !== 'Bill') {
|
|
653
|
+
setValidationMessage('This form only works for people named Bill');
|
|
654
|
+
setIsValid(false);
|
|
655
|
+
} else if (value === '') {
|
|
656
|
+
setValidationMessage('First name is required');
|
|
657
|
+
setIsValid(false);
|
|
658
|
+
} else {
|
|
659
|
+
setValidationMessage('Valid first name!');
|
|
660
|
+
setIsValid(true);
|
|
661
|
+
}
|
|
662
|
+
}}
|
|
663
|
+
/>
|
|
664
|
+
</Form>
|
|
665
|
+
);
|
|
666
|
+
};
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
### Link
|
|
670
|
+
|
|
671
|
+
##### Import
|
|
672
|
+
|
|
673
|
+
```javascript
|
|
674
|
+
import { Link } from '@hubspot/ui-extensions';
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
##### Props
|
|
678
|
+
|
|
679
|
+
```typescript
|
|
680
|
+
export interface LinkProps {
|
|
681
|
+
href: string;
|
|
682
|
+
variant?: 'primary' | 'destructive' | 'light' | 'dark';
|
|
683
|
+
children: ReactNode;
|
|
684
|
+
}
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
| Prop | Type | Default | Description |
|
|
688
|
+
| --- | --- | --- | --- |
|
|
689
|
+
| `href` | `string` | `N/A` | A URL that will be opened when the link is clicked. If the value is a URL external to HubSpot it will be opened in a new tab. |
|
|
690
|
+
| `variant` | `'primary' \| 'light' \| 'dark' \| 'destructive'` `(optional)` | `'primary'` | Sets the color variation of the link |
|
|
691
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. |
|
|
692
|
+
|
|
693
|
+
##### Usage
|
|
694
|
+
|
|
695
|
+
```javascript
|
|
696
|
+
const Extension = () => {
|
|
697
|
+
return <Link href="https://app.hubspot.com/">HubSpot</Link>;
|
|
698
|
+
};
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### LoadingSpinner
|
|
702
|
+
|
|
703
|
+
##### Import
|
|
704
|
+
|
|
705
|
+
```javascript
|
|
706
|
+
import { LoadingSpinner } from '@hubspot/ui-extensions';
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
##### Props
|
|
710
|
+
|
|
711
|
+
```typescript
|
|
712
|
+
export interface LoadingSpinnerProps {
|
|
713
|
+
label: string;
|
|
714
|
+
showLabel?: boolean;
|
|
715
|
+
size?: 'xs' | 'sm' | 'md';
|
|
716
|
+
layout?: 'inline' | 'centered';
|
|
717
|
+
}
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
| Prop | Type | Default | Description |
|
|
721
|
+
| --- | --- | --- | --- |
|
|
722
|
+
| `label` | `string` | `N/A` | The companion text for the loading spinner. |
|
|
723
|
+
| `showLabel` | `boolean(optional)` | `false` | if `true`, the label will be visible alongside the loading spinner. |
|
|
724
|
+
| `size` | `'xs'\| 'sm' \| 'md'` `(optional)` | `'sm'` | The size of the loading spinner icon. |
|
|
725
|
+
| `layout` | `'inline'\| 'centered'` `(optional)` | `N/A` | Use the `centered` option for layout as a convenience for the common pattern of filling the space of its parent. |
|
|
726
|
+
|
|
727
|
+
##### Usage
|
|
728
|
+
|
|
729
|
+
```javascript
|
|
730
|
+
const Extension = () => {
|
|
731
|
+
return <LoadingSpinner label="Loading..." />;
|
|
732
|
+
};
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
### ProgressBar
|
|
736
|
+
|
|
737
|
+
##### Import
|
|
738
|
+
|
|
739
|
+
```javascript
|
|
740
|
+
import { ProgressBar } from '@hubspot/ui-extensions';
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
##### Props
|
|
744
|
+
|
|
745
|
+
```typescript
|
|
746
|
+
export interface ProgressBarProps {
|
|
747
|
+
title?: string;
|
|
748
|
+
showPercentage?: boolean;
|
|
749
|
+
value?: number;
|
|
750
|
+
valueMax?: number;
|
|
751
|
+
valueDescription?: string;
|
|
752
|
+
variant?: 'success' | 'danger' | 'warning';
|
|
753
|
+
}
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
| Prop | Type | Default | Description |
|
|
757
|
+
| --- | --- | --- | --- |
|
|
758
|
+
| `title` | `string(optional)` | `N/A` | Text to be displayed in the progressbar title. |
|
|
759
|
+
| `showPercentage` | `boolean(optional)` | `false` | Toggles the display of the completion percentage. |
|
|
760
|
+
| `value` | `number(optional)` | `0` | The value of the progress indicator. |
|
|
761
|
+
| `valueMax` | `number(optional)` | `100` | The maximum value of the progress. |
|
|
762
|
+
| `valueDescription` | `string(optional)` | `N/A` | Text that explains the current state of the `value` prop. Renders to the right of `title`. **Example: "10,000 of 7,500"** |
|
|
763
|
+
| `variant` | `'success' \| 'danger' \| 'warning'` | `'success'` | The type of progressbar to display. Defaults to success. |
|
|
764
|
+
|
|
765
|
+
##### Usage
|
|
766
|
+
|
|
767
|
+
```javascript
|
|
768
|
+
const Extension = () => {
|
|
769
|
+
return (
|
|
770
|
+
<ProgressBar
|
|
771
|
+
variant="warning"
|
|
772
|
+
value={50}
|
|
773
|
+
valueMax={200}
|
|
774
|
+
showPercentage={true}
|
|
775
|
+
/>
|
|
776
|
+
);
|
|
777
|
+
};
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
### Select
|
|
781
|
+
|
|
782
|
+
##### Import
|
|
783
|
+
|
|
784
|
+
```javascript
|
|
785
|
+
import { Select } from '@hubspot/ui-extensions';
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
##### Props
|
|
789
|
+
|
|
790
|
+
```typescript
|
|
791
|
+
interface SelectProps {
|
|
792
|
+
label: string;
|
|
793
|
+
name: string;
|
|
794
|
+
value?: string | number | boolean;
|
|
795
|
+
required?: boolean;
|
|
796
|
+
readOnly?: boolean;
|
|
797
|
+
description?: string;
|
|
798
|
+
tooltip?: string;
|
|
799
|
+
placeholder?: string;
|
|
800
|
+
error?: boolean;
|
|
801
|
+
errorMessage?: string;
|
|
802
|
+
onChange: (value: string) => void;
|
|
803
|
+
options: {
|
|
804
|
+
label: string;
|
|
805
|
+
value: string | number | boolean;
|
|
806
|
+
}[];
|
|
807
|
+
}
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
| Prop | Type | Default | Description |
|
|
811
|
+
| --- | --- | --- | --- |
|
|
812
|
+
| `label` | `string` | `N/A` | The label text to display for the select element |
|
|
813
|
+
| `name` | `string` | `N/A` | The unique identifier for the select element. |
|
|
814
|
+
| `value` | `string \| number \| boolean` | `''` | The value of the select input. |
|
|
815
|
+
| `required` | `boolean` | `false` | Determines if the required indicator should be displayed |
|
|
816
|
+
| `readOnly` | `boolean` | `false` | Determines if the field is editable or not. |
|
|
817
|
+
| `description` | `string` | `N/A` | Instructional message to display to the user to help understand the purpose of the input. |
|
|
818
|
+
| `tooltip` | `string` | `N/A` | Text that will appear in a tooltip next to the input label. |
|
|
819
|
+
| `placeholder` | `string` | `N/A` | Text that appears in the input when it has no value set. |
|
|
820
|
+
| `error` | `boolean(optional)` | `false` | If set to true, `validationMessage` is displayed as an error message, if it was provided. The input will also render it's error state to let the user know there is an error. If false, `validationMessage` is displayed as a success message. |
|
|
821
|
+
| `validationMessage` | `string(optional)` | `''` | The text to show if the input has an error. |
|
|
822
|
+
| `onChange` | `(value: string) => void` | `N/A` | Function that is called with the new value when it is updated. |
|
|
823
|
+
| `options` | `Array<{label: string; value: string \| number \| boolean}>` | `N/A` | Array of options to be displayed in the select. `label` will be used as the display text in the dropdown list and `value` should be a **unique** identifier. `value` is the data that will be submitted with the form. |
|
|
824
|
+
|
|
825
|
+
##### Usage
|
|
826
|
+
|
|
827
|
+
```javascript
|
|
828
|
+
const Extension = () => {
|
|
829
|
+
const [name, setName] = useState(null);
|
|
830
|
+
const [validationMessage, setValidationMessage] = useState('');
|
|
831
|
+
const [isValid, setIsValid] = useState(true);
|
|
832
|
+
|
|
833
|
+
const options = [
|
|
834
|
+
{ label: 'Bill', value: 42 },
|
|
835
|
+
{ label: 'Ted', value: 43 },
|
|
836
|
+
];
|
|
837
|
+
|
|
838
|
+
return (
|
|
839
|
+
<Form>
|
|
840
|
+
<Select
|
|
841
|
+
label="Best Bill & Ted Character?"
|
|
842
|
+
name="best-char"
|
|
843
|
+
tooltip="Please choose"
|
|
844
|
+
description="Please choose"
|
|
845
|
+
placeholder="Bill or Ted?"
|
|
846
|
+
required={true}
|
|
847
|
+
error={!isValid}
|
|
848
|
+
validationMessage={validationMessage}
|
|
849
|
+
onChange={value => {
|
|
850
|
+
setName(value);
|
|
851
|
+
if (!value) {
|
|
852
|
+
setValidationMessage('This is required');
|
|
853
|
+
setIsValid(false);
|
|
854
|
+
} else {
|
|
855
|
+
setValidationMessage('Excellent!');
|
|
856
|
+
setIsValid(true);
|
|
857
|
+
}
|
|
858
|
+
}}
|
|
859
|
+
options={options}
|
|
860
|
+
/>
|
|
861
|
+
</Form>
|
|
862
|
+
);
|
|
863
|
+
};
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
### Stack
|
|
867
|
+
|
|
868
|
+
##### Import
|
|
869
|
+
|
|
870
|
+
```javascript
|
|
871
|
+
import { Stack } from '@hubspot/ui-extensions';
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
##### Props
|
|
875
|
+
|
|
876
|
+
```typescript
|
|
877
|
+
interface StackProps {
|
|
878
|
+
distance?: 'flush' | 'small' | 'extra-small' | 'medium' | 'large';
|
|
879
|
+
direction?: 'row' | 'column';
|
|
880
|
+
children?: ReactNode;
|
|
881
|
+
}
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
| Prop | Type | Default | Description |
|
|
885
|
+
| --- | --- | --- | --- |
|
|
886
|
+
| `distance` | `'flush' \| 'extra-small' \| 'small' \| 'medium' \| 'large'` | `'small'` | Amount of space between each child component passed as children |
|
|
887
|
+
| `direction` | `'row' \| 'column'` | `'column'` | Stacks elements in the vertical or horizontal direction. |
|
|
888
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. |
|
|
889
|
+
|
|
890
|
+
##### Usage
|
|
891
|
+
|
|
892
|
+
```javascript
|
|
893
|
+
const Extension = () => {
|
|
894
|
+
return (
|
|
895
|
+
<Stack>
|
|
896
|
+
<Image {...} />
|
|
897
|
+
<Text {...} />
|
|
898
|
+
</Stack>
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
### Statistics
|
|
904
|
+
|
|
905
|
+
##### Import
|
|
906
|
+
|
|
907
|
+
```javascript
|
|
908
|
+
import { Statistics } from '@hubspot/ui-extensions';
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
##### Props
|
|
912
|
+
|
|
913
|
+
```typescript
|
|
914
|
+
interface StatisticsProps {
|
|
915
|
+
children: ReactNode;
|
|
916
|
+
}
|
|
917
|
+
```
|
|
918
|
+
|
|
919
|
+
| Prop | Type | Default | Description |
|
|
920
|
+
| --- | --- | --- | --- |
|
|
921
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. These children should be [StatisticsItem](#statisticsitem) or [StatisticsTrend](#statisticstrend) |
|
|
922
|
+
|
|
923
|
+
##### Usage
|
|
924
|
+
|
|
925
|
+
```javascript
|
|
926
|
+
const Extension = () => {
|
|
927
|
+
return (
|
|
928
|
+
<Statistics>
|
|
929
|
+
<StatisticsItem {...} />
|
|
930
|
+
<StatisticsTrend {...} />
|
|
931
|
+
</Statistics>
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
#### StatisticsItem
|
|
937
|
+
|
|
938
|
+
##### Import
|
|
939
|
+
|
|
940
|
+
```javascript
|
|
941
|
+
import { StatisticsItem } from '@hubspot/ui-extensions';
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
##### Props
|
|
945
|
+
|
|
946
|
+
```typescript
|
|
947
|
+
interface StatisticsItemProps {
|
|
948
|
+
id?: string;
|
|
949
|
+
label: string;
|
|
950
|
+
number: string;
|
|
951
|
+
children: ReactNode;
|
|
952
|
+
}
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
| Prop | Type | Default | Description |
|
|
956
|
+
| --- | --- | --- | --- |
|
|
957
|
+
| `id` | `string(optional)` | `N/A` | The unique identifier |
|
|
958
|
+
| `label` | `string` | `N/A` | The text to be used as a label |
|
|
959
|
+
| `number` | `string` | `N/A` | Fully formatted string to be displayed as the item's primary number |
|
|
960
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. These children should be [Text](#text) or [StatisticsTrend](#statisticstrend) |
|
|
961
|
+
|
|
962
|
+
##### Usage
|
|
963
|
+
|
|
964
|
+
```javascript
|
|
965
|
+
const Extension = () => {
|
|
966
|
+
return (
|
|
967
|
+
<Statistics>
|
|
968
|
+
<StatisticsItem label="Sales" number={'30000'}>
|
|
969
|
+
<Text>Big Numbers</Text>
|
|
970
|
+
</StatisticsItem>
|
|
971
|
+
</Statistics>
|
|
972
|
+
);
|
|
973
|
+
};
|
|
974
|
+
```
|
|
975
|
+
|
|
976
|
+
#### StatisticsTrend
|
|
977
|
+
|
|
978
|
+
##### Import
|
|
979
|
+
|
|
980
|
+
```javascript
|
|
981
|
+
import { StatisticsTrend } from '@hubspot/ui-extensions';
|
|
982
|
+
```
|
|
983
|
+
|
|
984
|
+
##### Props
|
|
985
|
+
|
|
986
|
+
```typescript
|
|
987
|
+
interface StatisticsTrendProps {
|
|
988
|
+
value: string;
|
|
989
|
+
direction: 'increase' | 'decrease';
|
|
990
|
+
}
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
| Prop | Type | Default | Description |
|
|
994
|
+
| --- | --- | --- | --- |
|
|
995
|
+
| `value` | `string` | `N/A` | Formatted string to be displayed as trend value |
|
|
996
|
+
| `direction` | `'increase' \| 'decrease'` | `N/A` | Direction in which the trend arrow should be displayed |
|
|
997
|
+
|
|
998
|
+
##### Usage
|
|
999
|
+
|
|
1000
|
+
```javascript
|
|
1001
|
+
const Extension = () => {
|
|
1002
|
+
return (
|
|
1003
|
+
<Statistics>
|
|
1004
|
+
<StatisticsItem label="Item A Sales" number="10000">
|
|
1005
|
+
<StatisticsTrend direction="decrease" value="200%" />
|
|
1006
|
+
</StatisticsItem>
|
|
1007
|
+
<StatisticsItem label="Item B Sales" number="100000">
|
|
1008
|
+
<StatisticsTrend direction="increase" value="100%" />
|
|
1009
|
+
</StatisticsItem>
|
|
1010
|
+
</Statistics>
|
|
1011
|
+
);
|
|
1012
|
+
};
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
### Table
|
|
1016
|
+
|
|
1017
|
+
##### Import
|
|
1018
|
+
|
|
1019
|
+
```javascript
|
|
1020
|
+
import { Table } from '@hubspot/ui-extensions';
|
|
1021
|
+
```
|
|
1022
|
+
|
|
1023
|
+
##### Props
|
|
1024
|
+
|
|
1025
|
+
```typescript
|
|
1026
|
+
interface TableProps {
|
|
1027
|
+
children: ReactNode;
|
|
1028
|
+
flush?: boolean;
|
|
1029
|
+
bordered?: boolean;
|
|
1030
|
+
paginated?: boolean;
|
|
1031
|
+
// if paginated=true
|
|
1032
|
+
pageCount: number;
|
|
1033
|
+
onPageChange: (pageNumber: number) => void;
|
|
1034
|
+
showButtonLabels?: boolean;
|
|
1035
|
+
showFirstLastButtons?: boolean;
|
|
1036
|
+
maxVisiblePageButtons?: number;
|
|
1037
|
+
page?: number;
|
|
1038
|
+
}
|
|
1039
|
+
```
|
|
1040
|
+
|
|
1041
|
+
| Prop | Type | Default | Description |
|
|
1042
|
+
| --- | --- | --- | --- |
|
|
1043
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. These children should be [TableHead](#tablehead), [TableFooter](#tablefooter), or [TableBody](#tablebody) |
|
|
1044
|
+
| `flush` | `boolean(optional)` | `false` | If true the table will not have bottom margin. |
|
|
1045
|
+
| `bordered` | `boolean(optional)` | `true` | If false the table will not haver borders around its content. |
|
|
1046
|
+
| `paginated` | `boolean(optional)` | `false` | If true, the table will display the paginator component and consumer will have to provide extra pagination props. |
|
|
1047
|
+
|
|
1048
|
+
**Props for paginated=true**
|
|
1049
|
+
|
|
1050
|
+
| Prop | Type | Default | Description |
|
|
1051
|
+
| --- | --- | --- | --- |
|
|
1052
|
+
| `pageCount` | `number` | `N/A` | The total number of pages available |
|
|
1053
|
+
| `onPageChange` | `onPageChange: (pageNumber: number) => void` | `N/A` | A function that will be invoked when the pagination button is clicked. It receives the new page number as argument. |
|
|
1054
|
+
| `showButtonLabels` | `boolean(optional)` | `true` | if `false`, it hides the text labels for the First/Prev/Next/Last buttons. The button labels will still be accessible for screen readers. |
|
|
1055
|
+
| `showFirstLastButtons` | `boolean(optional)` | `false` | if `true`, it displays the First page and Last page buttons. |
|
|
1056
|
+
| `maxVisiblePageButtons` | `number(optional)` | `5` | Changes how many page buttons are shown. |
|
|
1057
|
+
| `page` | `number(optional)` | `N/A` | Denotes the current page. |
|
|
1058
|
+
|
|
1059
|
+
##### Usage
|
|
1060
|
+
|
|
1061
|
+
```javascript
|
|
1062
|
+
const Extension = () => {
|
|
1063
|
+
return (
|
|
1064
|
+
<Table bordered={true}>
|
|
1065
|
+
<TableHead>
|
|
1066
|
+
<TableRow>
|
|
1067
|
+
<TableHeader>Name</TableHeader>
|
|
1068
|
+
<TableHeader>Phone</TableHeader>
|
|
1069
|
+
</TableRow>
|
|
1070
|
+
</TableHead>
|
|
1071
|
+
<TableBody>
|
|
1072
|
+
<TableRow>
|
|
1073
|
+
<TableCell>Roger Federer</TableCell>
|
|
1074
|
+
<TableCell>555-555-7866</TableCell>
|
|
1075
|
+
</TableRow>
|
|
1076
|
+
</TableBody>
|
|
1077
|
+
</Table>
|
|
1078
|
+
);
|
|
1079
|
+
};
|
|
1080
|
+
|
|
1081
|
+
// Paginated example
|
|
1082
|
+
|
|
1083
|
+
function generateData(count = 15) {
|
|
1084
|
+
const result = [];
|
|
1085
|
+
|
|
1086
|
+
for (let index = 0; index < count; index++) {
|
|
1087
|
+
result.push({
|
|
1088
|
+
name: `Jane Doe ${index}`,
|
|
1089
|
+
email: `janedoemail${index}@hubspot.com`,
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
return result;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
function PaginatedTable() {
|
|
1097
|
+
const ITEMS_PER_PAGE = 10;
|
|
1098
|
+
const data = generateData(30);
|
|
1099
|
+
|
|
1100
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
1101
|
+
const pageCount = data.length / ITEMS_PER_PAGE;
|
|
1102
|
+
|
|
1103
|
+
const dataToDisplay = data.slice(
|
|
1104
|
+
(currentPage - 1) * ITEMS_PER_PAGE,
|
|
1105
|
+
currentPage * ITEMS_PER_PAGE
|
|
1106
|
+
);
|
|
1107
|
+
|
|
1108
|
+
return (
|
|
1109
|
+
<Table
|
|
1110
|
+
paginated={true}
|
|
1111
|
+
pageCount={pageCount}
|
|
1112
|
+
page={currentPage}
|
|
1113
|
+
onPageChange={(nextPageNumber: number) => {
|
|
1114
|
+
setCurrentPage(nextPageNumber);
|
|
1115
|
+
}}
|
|
1116
|
+
>
|
|
1117
|
+
<TableHead>
|
|
1118
|
+
<TableRow>
|
|
1119
|
+
<TableHeader>Name</TableHeader>
|
|
1120
|
+
<TableHeader>Email</TableHeader>
|
|
1121
|
+
</TableRow>
|
|
1122
|
+
</TableHead>
|
|
1123
|
+
<TableBody>
|
|
1124
|
+
{dataToDisplay.map(({ name, email }) => {
|
|
1125
|
+
console.log(name, email);
|
|
1126
|
+
return (
|
|
1127
|
+
<TableRow key={email}>
|
|
1128
|
+
<TableCell>{name}</TableCell>
|
|
1129
|
+
<TableCell>{email}</TableCell>
|
|
1130
|
+
</TableRow>
|
|
1131
|
+
);
|
|
1132
|
+
})}
|
|
1133
|
+
</TableBody>
|
|
1134
|
+
</Table>
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1137
|
+
```
|
|
1138
|
+
|
|
1139
|
+
### TableBody
|
|
1140
|
+
|
|
1141
|
+
##### Import
|
|
1142
|
+
|
|
1143
|
+
```javascript
|
|
1144
|
+
import { TableBody } from '@hubspot/ui-extensions';
|
|
1145
|
+
```
|
|
1146
|
+
|
|
1147
|
+
##### Props
|
|
1148
|
+
|
|
1149
|
+
```typescript
|
|
1150
|
+
interface TableBodyProps {
|
|
1151
|
+
children: ReactNode;
|
|
1152
|
+
}
|
|
1153
|
+
```
|
|
1154
|
+
|
|
1155
|
+
| Prop | Type | Default | Description |
|
|
1156
|
+
| --- | --- | --- | --- |
|
|
1157
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. These children should be [TableRow](#tablerow). |
|
|
1158
|
+
|
|
1159
|
+
##### Usage
|
|
1160
|
+
|
|
1161
|
+
```javascript
|
|
1162
|
+
const Extension = () => {
|
|
1163
|
+
return (
|
|
1164
|
+
<Table bordered={true}>
|
|
1165
|
+
<TableHead>
|
|
1166
|
+
<TableRow>
|
|
1167
|
+
<TableHeader>Name</TableHeader>
|
|
1168
|
+
<TableHeader>Phone</TableHeader>
|
|
1169
|
+
</TableRow>
|
|
1170
|
+
</TableHead>
|
|
1171
|
+
<TableBody>
|
|
1172
|
+
<TableRow>
|
|
1173
|
+
<TableCell>Roger Federer</TableCell>
|
|
1174
|
+
<TableCell>555-555-7866</TableCell>
|
|
1175
|
+
</TableRow>
|
|
1176
|
+
</TableBody>
|
|
1177
|
+
</Table>
|
|
1178
|
+
);
|
|
1179
|
+
};
|
|
1180
|
+
```
|
|
1181
|
+
|
|
1182
|
+
### TableCell
|
|
1183
|
+
|
|
1184
|
+
##### Import
|
|
1185
|
+
|
|
1186
|
+
```javascript
|
|
1187
|
+
import { TableCell } from '@hubspot/ui-extensions';
|
|
1188
|
+
```
|
|
1189
|
+
|
|
1190
|
+
##### Props
|
|
1191
|
+
|
|
1192
|
+
```typescript
|
|
1193
|
+
interface TableCellProps {
|
|
1194
|
+
children: ReactNode;
|
|
1195
|
+
}
|
|
1196
|
+
```
|
|
1197
|
+
|
|
1198
|
+
| Prop | Type | Default | Description |
|
|
1199
|
+
| --- | --- | --- | --- |
|
|
1200
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. |
|
|
1201
|
+
|
|
1202
|
+
##### Usage
|
|
1203
|
+
|
|
1204
|
+
```javascript
|
|
1205
|
+
const Extension = () => {
|
|
1206
|
+
return (
|
|
1207
|
+
<Table bordered={true}>
|
|
1208
|
+
<TableHead>
|
|
1209
|
+
<TableRow>
|
|
1210
|
+
<TableHeader>Name</TableHeader>
|
|
1211
|
+
<TableHeader>Phone</TableHeader>
|
|
1212
|
+
</TableRow>
|
|
1213
|
+
</TableHead>
|
|
1214
|
+
<TableBody>
|
|
1215
|
+
<TableRow>
|
|
1216
|
+
<TableCell>Roger Federer</TableCell>
|
|
1217
|
+
<TableCell>555-555-7866</TableCell>
|
|
1218
|
+
</TableRow>
|
|
1219
|
+
</TableBody>
|
|
1220
|
+
</Table>
|
|
1221
|
+
);
|
|
1222
|
+
};
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
### TableFooter
|
|
1226
|
+
|
|
1227
|
+
##### Import
|
|
1228
|
+
|
|
1229
|
+
```javascript
|
|
1230
|
+
import { TableFooter } from '@hubspot/ui-extensions';
|
|
1231
|
+
```
|
|
1232
|
+
|
|
1233
|
+
##### Props
|
|
1234
|
+
|
|
1235
|
+
```typescript
|
|
1236
|
+
interface TableFooterProps {
|
|
1237
|
+
children: ReactNode;
|
|
1238
|
+
}
|
|
1239
|
+
```
|
|
1240
|
+
|
|
1241
|
+
| Prop | Type | Default | Description |
|
|
1242
|
+
| --- | --- | --- | --- |
|
|
1243
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. These children should be [TableRow](#tablerow). |
|
|
1244
|
+
|
|
1245
|
+
##### Usage
|
|
1246
|
+
|
|
1247
|
+
```javascript
|
|
1248
|
+
const Extension = () => {
|
|
1249
|
+
return (
|
|
1250
|
+
<Table>
|
|
1251
|
+
<TableHead>
|
|
1252
|
+
<TableRow>
|
|
1253
|
+
<TableHeader>Series</TableHeader>
|
|
1254
|
+
<TableHeader>Years on air</TableHeader>
|
|
1255
|
+
<TableHeader>Emmys</TableHeader>
|
|
1256
|
+
</TableRow>
|
|
1257
|
+
</TableHead>
|
|
1258
|
+
<TableFooter>
|
|
1259
|
+
<TableRow>
|
|
1260
|
+
<TableHeader>Totals</TableHeader>
|
|
1261
|
+
<TableHeader>43</TableHeader>
|
|
1262
|
+
<TableHeader>50</TableHeader>
|
|
1263
|
+
</TableRow>
|
|
1264
|
+
</TableFooter>
|
|
1265
|
+
<TableBody>
|
|
1266
|
+
<TableRow>
|
|
1267
|
+
<TableCell>The Simpsons</TableCell>
|
|
1268
|
+
<TableCell>28</TableCell>
|
|
1269
|
+
<TableCell>31</TableCell>
|
|
1270
|
+
</TableRow>
|
|
1271
|
+
<TableRow>
|
|
1272
|
+
<TableCell>M*A*S*H</TableCell>
|
|
1273
|
+
<TableCell>11</TableCell>
|
|
1274
|
+
<TableCell>14</TableCell>
|
|
1275
|
+
</TableRow>
|
|
1276
|
+
<TableRow>
|
|
1277
|
+
<TableCell>Arrested Development</TableCell>
|
|
1278
|
+
<TableCell>4</TableCell>
|
|
1279
|
+
<TableCell>5</TableCell>
|
|
1280
|
+
</TableRow>
|
|
1281
|
+
</TableBody>
|
|
1282
|
+
</Table>
|
|
1283
|
+
);
|
|
1284
|
+
};
|
|
1285
|
+
```
|
|
1286
|
+
|
|
1287
|
+
### TableHead
|
|
1288
|
+
|
|
1289
|
+
##### Import
|
|
1290
|
+
|
|
1291
|
+
```javascript
|
|
1292
|
+
import { TableHead } from '@hubspot/ui-extensions';
|
|
1293
|
+
```
|
|
1294
|
+
|
|
1295
|
+
##### Props
|
|
1296
|
+
|
|
1297
|
+
```typescript
|
|
1298
|
+
interface TableHeadProps {
|
|
1299
|
+
children: ReactNode;
|
|
1300
|
+
}
|
|
1301
|
+
```
|
|
1302
|
+
|
|
1303
|
+
| Prop | Type | Default | Description |
|
|
1304
|
+
| --- | --- | --- | --- |
|
|
1305
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. These children should be [TableHeader](#tableheader). |
|
|
1306
|
+
|
|
1307
|
+
##### Usage
|
|
1308
|
+
|
|
1309
|
+
```javascript
|
|
1310
|
+
const Extension = () => {
|
|
1311
|
+
return (
|
|
1312
|
+
<Table bordered={true}>
|
|
1313
|
+
<TableHead>
|
|
1314
|
+
<TableRow>
|
|
1315
|
+
<TableHeader>Name</TableHeader>
|
|
1316
|
+
<TableHeader>Phone</TableHeader>
|
|
1317
|
+
</TableRow>
|
|
1318
|
+
</TableHead>
|
|
1319
|
+
<TableBody>
|
|
1320
|
+
<TableRow>
|
|
1321
|
+
<TableCell>Roger Federer</TableCell>
|
|
1322
|
+
<TableCell>555-555-7866</TableCell>
|
|
1323
|
+
</TableRow>
|
|
1324
|
+
</TableBody>
|
|
1325
|
+
</Table>
|
|
1326
|
+
);
|
|
1327
|
+
};
|
|
1328
|
+
```
|
|
1329
|
+
|
|
1330
|
+
### TableHeader
|
|
1331
|
+
|
|
1332
|
+
##### Import
|
|
1333
|
+
|
|
1334
|
+
```javascript
|
|
1335
|
+
import { TableHeader } from '@hubspot/ui-extensions';
|
|
1336
|
+
```
|
|
1337
|
+
|
|
1338
|
+
##### Props
|
|
1339
|
+
|
|
1340
|
+
```typescript
|
|
1341
|
+
interface TableHeaderProps {
|
|
1342
|
+
children: ReactNode;
|
|
1343
|
+
}
|
|
1344
|
+
```
|
|
1345
|
+
|
|
1346
|
+
| Prop | Type | Default | Description |
|
|
1347
|
+
| --- | --- | --- | --- |
|
|
1348
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. |
|
|
1349
|
+
|
|
1350
|
+
##### Usage
|
|
1351
|
+
|
|
1352
|
+
```javascript
|
|
1353
|
+
const Extension = () => {
|
|
1354
|
+
return (
|
|
1355
|
+
<Table bordered={true}>
|
|
1356
|
+
<TableHead>
|
|
1357
|
+
<TableRow>
|
|
1358
|
+
<TableHeader>Name</TableHeader>
|
|
1359
|
+
<TableHeader>Phone</TableHeader>
|
|
1360
|
+
</TableRow>
|
|
1361
|
+
</TableHead>
|
|
1362
|
+
<TableBody>
|
|
1363
|
+
<TableRow>
|
|
1364
|
+
<TableCell>Roger Federer</TableCell>
|
|
1365
|
+
<TableCell>555-555-7866</TableCell>
|
|
1366
|
+
</TableRow>
|
|
1367
|
+
</TableBody>
|
|
1368
|
+
</Table>
|
|
1369
|
+
);
|
|
1370
|
+
};
|
|
1371
|
+
```
|
|
1372
|
+
|
|
1373
|
+
### TableRow
|
|
1374
|
+
|
|
1375
|
+
##### Import
|
|
1376
|
+
|
|
1377
|
+
```javascript
|
|
1378
|
+
import { TableRow } from '@hubspot/ui-extensions';
|
|
1379
|
+
```
|
|
1380
|
+
|
|
1381
|
+
##### Props
|
|
1382
|
+
|
|
1383
|
+
```typescript
|
|
1384
|
+
interface TableRowProps {
|
|
1385
|
+
children: ReactNode;
|
|
1386
|
+
}
|
|
1387
|
+
```
|
|
1388
|
+
|
|
1389
|
+
| Prop | Type | Default | Description |
|
|
1390
|
+
| --- | --- | --- | --- |
|
|
1391
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. |
|
|
1392
|
+
|
|
1393
|
+
##### Usage
|
|
1394
|
+
|
|
1395
|
+
```javascript
|
|
1396
|
+
const Extension = () => {
|
|
1397
|
+
return (
|
|
1398
|
+
<Table bordered={true}>
|
|
1399
|
+
<TableHead>
|
|
1400
|
+
<TableRow>
|
|
1401
|
+
<TableHeader>Name</TableHeader>
|
|
1402
|
+
<TableHeader>Phone</TableHeader>
|
|
1403
|
+
</TableRow>
|
|
1404
|
+
</TableHead>
|
|
1405
|
+
<TableBody>
|
|
1406
|
+
<TableRow>
|
|
1407
|
+
<TableCell>Roger Federer</TableCell>
|
|
1408
|
+
<TableCell>555-555-7866</TableCell>
|
|
1409
|
+
</TableRow>
|
|
1410
|
+
</TableBody>
|
|
1411
|
+
</Table>
|
|
1412
|
+
);
|
|
1413
|
+
};
|
|
1414
|
+
```
|
|
1415
|
+
|
|
1416
|
+
### Tag
|
|
1417
|
+
|
|
1418
|
+
##### Import
|
|
1419
|
+
|
|
1420
|
+
```javascript
|
|
1421
|
+
import { Tag } from '@hubspot/ui-extensions';
|
|
1422
|
+
```
|
|
1423
|
+
|
|
1424
|
+
##### Props
|
|
1425
|
+
|
|
1426
|
+
```typescript
|
|
1427
|
+
interface TagProps {
|
|
1428
|
+
children: ReactNode;
|
|
1429
|
+
onClick?: () => void;
|
|
1430
|
+
variant?: 'default' | 'warning' | 'success' | 'error';
|
|
1431
|
+
}
|
|
1432
|
+
```
|
|
1433
|
+
|
|
1434
|
+
| Prop | Type | Default | Description |
|
|
1435
|
+
| --- | --- | --- | --- |
|
|
1436
|
+
| `children` | `string` | `N/A` | Text to be displayed in the tag. |
|
|
1437
|
+
| `onClick` | `() => void` `(optional)` | `N/A` | A function that will be invoked when the `Tag` is clicked. It receives no arguments and it's return value is ignored. |
|
|
1438
|
+
| `variant` | `'default' \| 'warning' \| 'success' \| 'error'` `(optional)` | `'default'` | The color variation of the tag to display |
|
|
1439
|
+
|
|
1440
|
+
##### Usage
|
|
1441
|
+
|
|
1442
|
+
```javascript
|
|
1443
|
+
const Extension = () => {
|
|
1444
|
+
return (
|
|
1445
|
+
<Tag
|
|
1446
|
+
variant="success"
|
|
1447
|
+
onClick={() => {
|
|
1448
|
+
console.log('Tag clicked!');
|
|
1449
|
+
}}
|
|
1450
|
+
>
|
|
1451
|
+
Success
|
|
1452
|
+
</Tag>
|
|
1453
|
+
);
|
|
1454
|
+
};
|
|
1455
|
+
```
|
|
1456
|
+
|
|
1457
|
+
### Text
|
|
1458
|
+
|
|
1459
|
+
##### Import
|
|
1460
|
+
|
|
1461
|
+
```javascript
|
|
1462
|
+
import { Text } from '@hubspot/ui-extensions';
|
|
1463
|
+
```
|
|
1464
|
+
|
|
1465
|
+
##### Props
|
|
1466
|
+
|
|
1467
|
+
```typescript
|
|
1468
|
+
interface TextProps {
|
|
1469
|
+
format?: 'plaintext' | 'markdown';
|
|
1470
|
+
variant?: 'bodytext' | 'microcopy';
|
|
1471
|
+
children: ReactNode;
|
|
1472
|
+
tagName?: 'p' | 'span' | 'small';
|
|
1473
|
+
}
|
|
1474
|
+
```
|
|
1475
|
+
|
|
1476
|
+
| Prop | Type | Default | Description |
|
|
1477
|
+
| --- | --- | --- | --- |
|
|
1478
|
+
| `format` | `'plaintext' \| 'markdown'` `(optional)` | `'plaintext'` | Type of formatting for the display text. |
|
|
1479
|
+
| `children` | `string` | `N/A` | Text to be displayed as body text. |
|
|
1480
|
+
| `variant` | `'bodytext' \| 'microcopy'` | `'bodytext'` | Type of text to display |
|
|
1481
|
+
| `tagName` | `'p' \| 'small' \| 'span'` | `'bodytext'` | Type of text element(tag) to display. |
|
|
1482
|
+
|
|
1483
|
+
#### Markdown
|
|
1484
|
+
|
|
1485
|
+
Markdown syntax supported in the component:
|
|
1486
|
+
|
|
1487
|
+
- bold text: `**like this**` or `__like this__`
|
|
1488
|
+
- italicized text: `*like this*` or `_like this_`
|
|
1489
|
+
- inline code: `` `like this` ``
|
|
1490
|
+
- links: `[visible anchor text](https://www.hubspot.com/)`
|
|
1491
|
+
|
|
1492
|
+
##### Usage
|
|
1493
|
+
|
|
1494
|
+
```javascript
|
|
1495
|
+
const Extension = () => {
|
|
1496
|
+
return (
|
|
1497
|
+
<>
|
|
1498
|
+
<Text format="markdown">**Bold**</Text>
|
|
1499
|
+
<Text format="markdown">*Italics*</Text>
|
|
1500
|
+
<Text>**Not Bold because format isn't markdown**</Text>
|
|
1501
|
+
<Text variant="microcopy">This is going to be small</Text>
|
|
1502
|
+
</>
|
|
1503
|
+
);
|
|
1504
|
+
};
|
|
1505
|
+
```
|
|
1506
|
+
|
|
1507
|
+
### Textarea
|
|
1508
|
+
|
|
1509
|
+
##### Import
|
|
1510
|
+
|
|
1511
|
+
```javascript
|
|
1512
|
+
import { Textarea } from '@hubspot/ui-extensions';
|
|
1513
|
+
```
|
|
1514
|
+
|
|
1515
|
+
##### Props
|
|
1516
|
+
|
|
1517
|
+
```typescript
|
|
1518
|
+
interface TextareaProps {
|
|
1519
|
+
label: string;
|
|
1520
|
+
name: string;
|
|
1521
|
+
value?: string;
|
|
1522
|
+
required?: boolean;
|
|
1523
|
+
readOnly?: boolean;
|
|
1524
|
+
description?: string;
|
|
1525
|
+
tooltip?: string;
|
|
1526
|
+
placeholder?: string;
|
|
1527
|
+
error?: boolean;
|
|
1528
|
+
validationMessage?: string;
|
|
1529
|
+
onChange?: (value: string) => void;
|
|
1530
|
+
onInput?: (value: string) => void;
|
|
1531
|
+
onBlur?: (value: string) => void;
|
|
1532
|
+
onFocus?: (value: string) => void;
|
|
1533
|
+
cols?: number;
|
|
1534
|
+
maxLength?: number;
|
|
1535
|
+
rows?: number;
|
|
1536
|
+
resize?: 'vertical' | 'horizontal' | 'both' | 'none';
|
|
1537
|
+
}
|
|
1538
|
+
```
|
|
1539
|
+
|
|
1540
|
+
| Prop | Type | Default | Description |
|
|
1541
|
+
| --- | --- | --- | --- |
|
|
1542
|
+
| `label` | `string` | `N/A` | The label text to display for the textarea element |
|
|
1543
|
+
| `name` | `string` | `N/A` | The unique identifier for the textarea element, this could be thought of as the HTML5 [Textarea element's name attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#name) |
|
|
1544
|
+
| `value` | `string(optional)` | `''` | The value of the textarea |
|
|
1545
|
+
| `required` | `boolean(optional)` | `false` | Determines if the required indicator should be displayed |
|
|
1546
|
+
| `readOnly` | `boolean(optional)` | `false` | Determines if the field is editable or not. |
|
|
1547
|
+
| `description` | `string(optional)` | `N/A` | Instructional message to display to the user to help understand the purpose of the textarea. |
|
|
1548
|
+
| `tooltip` | `string(optional)` | `N/A` | Text that will appear in a tooltip next to the textarea label. |
|
|
1549
|
+
| `placeholder` | `string(optional)` | `N/A` | Text that appears in the textarea when it has no value set. |
|
|
1550
|
+
| `error` | `boolean(optional)` | `false` | If set to true, `validationMessage` is displayed as an error message, if it was provided. The textarea will also render it's error state to let the user know there is an error. If false, `validationMessage` is displayed as a success message. |
|
|
1551
|
+
| `validationMessage` | `string(optional)` | `''` | The text to show if the textarea has an error. |
|
|
1552
|
+
| `onChange` | `(value: string) => void(optional)` | `N/A` | A callback function that is invoked when the value is committed. Currently these times are `onBlur` of the textarea and when the user submits the form. |
|
|
1553
|
+
| `onInput` | `(value: string) => void(optional)` | `N/A` | A function that is called and passed the value every time the field is edited by the user. It is recommended that you do not use this value to update state, that is what `onChange` should be used for. Instead this should be used for validation. |
|
|
1554
|
+
| `onBlur` | `(value: string) => void(optional)` | `N/A` | A function that is called and passed the value every time the field loses focus. |
|
|
1555
|
+
| `onFocus` | `(value: string) => void(optional)` | `N/A` | A function that is called and passed the value every time the field gets focused. |
|
|
1556
|
+
| `cols` | `number(optional)` | `N/A` | The visible width of the text control, in average character widths. |
|
|
1557
|
+
| `rows` | `number(optional)` | `N/A` | The number of visible text lines for the control. |
|
|
1558
|
+
| `maxLength` | `number(optional)` | `N/A` | The maximum number of characters (UTF-16 code units) that the user can enter. If this value isn't specified, the user can enter an unlimited number of characters. |
|
|
1559
|
+
| `resize` | `'vertical' \| 'horizontal' \| 'both' \| 'none'` `(optional)` | `'vertical'` | Sets whether an element is resizable, and if so, in which directions. |
|
|
1560
|
+
|
|
1561
|
+
##### Usage
|
|
1562
|
+
|
|
1563
|
+
```javascript
|
|
1564
|
+
import { useState } from 'react';
|
|
1565
|
+
|
|
1566
|
+
const Extension = () => {
|
|
1567
|
+
const [desciptiption, setDescription] = useState('');
|
|
1568
|
+
const [validationMessage, setValidationMessage] = useState('');
|
|
1569
|
+
const [isValid, setIsValid] = useState(true);
|
|
1570
|
+
|
|
1571
|
+
return (
|
|
1572
|
+
<Form>
|
|
1573
|
+
<Textarea
|
|
1574
|
+
label="Description"
|
|
1575
|
+
name="description"
|
|
1576
|
+
tooltip="Provide as much detail as possible"
|
|
1577
|
+
description="Please include a link"
|
|
1578
|
+
placeholder="My desription"
|
|
1579
|
+
required={true}
|
|
1580
|
+
error={!isValid}
|
|
1581
|
+
validationMessage={validationMessage}
|
|
1582
|
+
onChange={value => {
|
|
1583
|
+
setDescription(value);
|
|
1584
|
+
}}
|
|
1585
|
+
onInput={value => {
|
|
1586
|
+
if (!value.includes('http')) {
|
|
1587
|
+
setValidationMessage('A link must be included.');
|
|
1588
|
+
setIsValid(false);
|
|
1589
|
+
} else {
|
|
1590
|
+
setValidationMessage('Valid description!');
|
|
1591
|
+
setIsValid(true);
|
|
1592
|
+
}
|
|
1593
|
+
}}
|
|
1594
|
+
/>
|
|
1595
|
+
</Form>
|
|
1596
|
+
);
|
|
1597
|
+
};
|
|
1598
|
+
```
|
|
1599
|
+
|
|
1600
|
+
### Tile
|
|
1601
|
+
|
|
1602
|
+
##### Import
|
|
1603
|
+
|
|
1604
|
+
```javascript
|
|
1605
|
+
import { Tile } from '@hubspot/ui-extensions';
|
|
1606
|
+
```
|
|
1607
|
+
|
|
1608
|
+
##### Props
|
|
1609
|
+
|
|
1610
|
+
```typescript
|
|
1611
|
+
interface TileProps {
|
|
1612
|
+
children: ReactNode;
|
|
1613
|
+
flush?: boolean;
|
|
1614
|
+
}
|
|
1615
|
+
```
|
|
1616
|
+
|
|
1617
|
+
| Prop | Type | Default | Description |
|
|
1618
|
+
| --- | --- | --- | --- |
|
|
1619
|
+
| `children` | `ReactNode` | `N/A` | Sets the content that will render inside the component. This prop is passed implicitly by providing sub-components. |
|
|
1620
|
+
| `flush` | `boolean(optional)` | `false` | If true the content of the Tile will have no left or right padding. |
|
|
1621
|
+
|
|
1622
|
+
##### Usage
|
|
1623
|
+
|
|
1624
|
+
```javascript
|
|
1625
|
+
const Extension = () => {
|
|
1626
|
+
return (
|
|
1627
|
+
<>
|
|
1628
|
+
<Tile flush={true}>
|
|
1629
|
+
<Text>No left padding</Text>
|
|
1630
|
+
</Tile>
|
|
1631
|
+
<Tile>
|
|
1632
|
+
<Text>Small amount of left padding</Text>
|
|
1633
|
+
</Tile>
|
|
1634
|
+
</>
|
|
1635
|
+
);
|
|
1636
|
+
};
|
|
1637
|
+
```
|
|
1638
|
+
|
|
1639
|
+
### ToggleGroup
|
|
1640
|
+
|
|
1641
|
+
##### Import
|
|
1642
|
+
|
|
1643
|
+
```javascript
|
|
1644
|
+
import { ToggleGroup } from '@hubspot/ui-extensions';
|
|
1645
|
+
```
|
|
1646
|
+
|
|
1647
|
+
##### Props
|
|
1648
|
+
|
|
1649
|
+
```typescript
|
|
1650
|
+
type ToggleGroupProps = {
|
|
1651
|
+
toggleType: 'checkboxList' | 'radioButtonList';
|
|
1652
|
+
name: string;
|
|
1653
|
+
label: string;
|
|
1654
|
+
value?: string | string[];
|
|
1655
|
+
onChange?: (value: string) => void | (value: string[]) => void;
|
|
1656
|
+
validationMessage?: string;
|
|
1657
|
+
required?: boolean;
|
|
1658
|
+
tooltip?: string;
|
|
1659
|
+
error?: boolean;
|
|
1660
|
+
options: {
|
|
1661
|
+
label: string;
|
|
1662
|
+
value: string;
|
|
1663
|
+
initialIsChecked?: boolean;
|
|
1664
|
+
readonly?: boolean;
|
|
1665
|
+
description?: string;
|
|
1666
|
+
}[];
|
|
1667
|
+
inline?: boolean;
|
|
1668
|
+
variant?: 'default' | 'small';
|
|
1669
|
+
};
|
|
1670
|
+
|
|
1671
|
+
```
|
|
1672
|
+
|
|
1673
|
+
| Prop | Type | Default | Description |
|
|
1674
|
+
| --- | --- | --- | --- | --- |
|
|
1675
|
+
| `toggleType` | `'radioButtonList' \| 'checkboxList'` | `N/A` | The type of toggles that will be shown. `'checkboxList'` is a multi-select and `'radioButtonList'` is a single select | ; |
|
|
1676
|
+
| `name` | `string` | `N/A` | The unique identifier for the toggle group element. |
|
|
1677
|
+
| `label` | `string` | `N/A` | The label text to display for the toggle group element. |
|
|
1678
|
+
| `options` | `Array<{ label: string; value: string; initialIsChecked?: boolean; readonly?: boolean; description?: string }>` | `N/A` | |
|
|
1679
|
+
| `value` | `string \| string[]` `(optional)` | `N/A` | The value of the toggle group. If `toggleType` is `'radioButtonList'`, this should be a `string`. If `toggleType` is `'checkboxList'` this should be an array of `string`s. |
|
|
1680
|
+
| `onChange` | `(value: string) => void \| (value: string[]) => void` `(optional)` | `N/A` | A function that is called with the new value or values when it is updated. If `toggleType` is `'radioButtonList'`, the function will be called with the `value` that is a `string`. If `toggleType` is `'checkboxList'` the function will be called with the `value` that is an array of `string`s. |
|
|
1681
|
+
| `required` | `boolean(optional)` | `false` | Determines if the required indicator should be displayed |
|
|
1682
|
+
| `tooltip` | `string` | `N/A` | Text that will appear in a tooltip next to the toggle group label. |
|
|
1683
|
+
| `error` | `boolean(optional)` | `false` | If set to true, `validationMessage` is displayed as an error message, if it was provided. The input will also render it's error state to let the user know there is an error. If false, `validationMessage` is displayed as a success message. |
|
|
1684
|
+
| `validationMessage` | `string(optional)` | `''` | The text to show if the input has an error. |
|
|
1685
|
+
| `inline` | `boolean(optional)` | `false` | Determines of the options are stacked vertically or share a line horizontally. |
|
|
1686
|
+
| `variant` | `'default' \| 'small'` `(optional)` | `default` | The size variation of the individual options. |
|
|
1687
|
+
|
|
1688
|
+
##### Usage
|
|
1689
|
+
|
|
1690
|
+
```javascript
|
|
1691
|
+
const options = [1, 2, 3, 4].map(n => ({
|
|
1692
|
+
label: `Option ${n}`,
|
|
1693
|
+
value: `${n}`,
|
|
1694
|
+
initialIsChecked: n === 2,
|
|
1695
|
+
readonly: false,
|
|
1696
|
+
description: `This is option ${n}`,
|
|
1697
|
+
}));
|
|
1698
|
+
|
|
1699
|
+
const Extension = () => {
|
|
1700
|
+
return (
|
|
1701
|
+
<ToggleGroup
|
|
1702
|
+
name="toggle-checkboxes"
|
|
1703
|
+
label="Toggle these things"
|
|
1704
|
+
error={false}
|
|
1705
|
+
options={options}
|
|
1706
|
+
tooltip="Here's a secret tip."
|
|
1707
|
+
validationMessage="Make sure you do the thing correctly."
|
|
1708
|
+
required={false}
|
|
1709
|
+
inline={false}
|
|
1710
|
+
toggleType="checkboxList"
|
|
1711
|
+
variant="default"
|
|
1712
|
+
/>
|
|
1713
|
+
);
|
|
1714
|
+
};
|
|
1715
|
+
```
|