@hubspot/cms-component-library 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/componentLibrary/Accordion/AccordionItem/index.module.scss +4 -0
- package/components/componentLibrary/Accordion/AccordionTitle/ContentFields.tsx +1 -0
- package/components/componentLibrary/Accordion/AccordionTitle/icons.tsx +19 -0
- package/components/componentLibrary/Accordion/AccordionTitle/index.module.scss +4 -0
- package/components/componentLibrary/Accordion/AccordionTitle/index.tsx +3 -1
- package/components/componentLibrary/Accordion/AccordionTitle/types.ts +1 -1
- package/components/componentLibrary/Accordion/llm.txt +7 -6
- package/components/componentLibrary/Accordion/stories/Accordion.stories.tsx +21 -0
- package/components/componentLibrary/Divider/StyleFields.tsx +72 -14
- package/components/componentLibrary/Divider/index.tsx +31 -16
- package/components/componentLibrary/Divider/llm.txt +97 -103
- package/components/componentLibrary/Divider/stories/Divider.stories.tsx +30 -19
- package/components/componentLibrary/Divider/types.ts +31 -20
- package/components/componentLibrary/Icon/StyleFields.tsx +69 -0
- package/components/componentLibrary/Icon/index.module.scss +11 -0
- package/components/componentLibrary/Icon/index.tsx +31 -4
- package/components/componentLibrary/Icon/llm.txt +50 -10
- package/components/componentLibrary/Icon/types.ts +29 -0
- package/components/componentLibrary/Text/ContentFields.tsx +66 -0
- package/components/componentLibrary/Text/index.module.scss +3 -0
- package/components/componentLibrary/Text/index.tsx +27 -0
- package/components/componentLibrary/Text/llm.txt +170 -0
- package/components/componentLibrary/Text/types.ts +16 -0
- package/package.json +4 -4
- package/components/componentLibrary/Divider/ContentFields.tsx +0 -63
|
@@ -13,7 +13,7 @@ const meta: Meta<DividerProps> = {
|
|
|
13
13
|
layout: 'centered',
|
|
14
14
|
docs: {
|
|
15
15
|
description: {
|
|
16
|
-
component: `The Divider component provides a visual separator between content sections. It supports both horizontal and vertical orientations with customizable styling options including
|
|
16
|
+
component: `The Divider component provides a visual separator between content sections. It supports both horizontal and vertical orientations with customizable styling options including line type, thickness, length, alignment, color, and spacing.`,
|
|
17
17
|
},
|
|
18
18
|
},
|
|
19
19
|
},
|
|
@@ -26,7 +26,6 @@ type Story = StoryObj<typeof meta>;
|
|
|
26
26
|
export const Default: Story = {
|
|
27
27
|
args: {
|
|
28
28
|
orientation: 'horizontal',
|
|
29
|
-
alignment: 'stretch',
|
|
30
29
|
borderStyle: 'solid',
|
|
31
30
|
length: 100,
|
|
32
31
|
thickness: 1,
|
|
@@ -196,25 +195,37 @@ export const Alignment: Story = {
|
|
|
196
195
|
<SBContainer addBackground flex>
|
|
197
196
|
<h4>Stretch (Default)</h4>
|
|
198
197
|
<p>Divider stretches to fill available space</p>
|
|
199
|
-
<Divider length={100} thickness={1}
|
|
198
|
+
<Divider length={100} thickness={1} />
|
|
200
199
|
</SBContainer>
|
|
201
200
|
|
|
202
201
|
<SBContainer addBackground flex>
|
|
203
|
-
<h4>
|
|
204
|
-
<p>Divider aligns to the
|
|
205
|
-
<Divider
|
|
202
|
+
<h4>Left</h4>
|
|
203
|
+
<p>Divider aligns to the left</p>
|
|
204
|
+
<Divider
|
|
205
|
+
length={50}
|
|
206
|
+
thickness={1}
|
|
207
|
+
alignment={{ horizontal_align: 'LEFT' }}
|
|
208
|
+
/>
|
|
206
209
|
</SBContainer>
|
|
207
210
|
|
|
208
211
|
<SBContainer addBackground flex>
|
|
209
212
|
<h4>Center</h4>
|
|
210
213
|
<p>Divider aligns to the center</p>
|
|
211
|
-
<Divider
|
|
214
|
+
<Divider
|
|
215
|
+
length={50}
|
|
216
|
+
thickness={1}
|
|
217
|
+
alignment={{ horizontal_align: 'CENTER' }}
|
|
218
|
+
/>
|
|
212
219
|
</SBContainer>
|
|
213
220
|
|
|
214
221
|
<SBContainer addBackground flex>
|
|
215
|
-
<h4>
|
|
216
|
-
<p>Divider aligns to the
|
|
217
|
-
<Divider
|
|
222
|
+
<h4>Right</h4>
|
|
223
|
+
<p>Divider aligns to the right</p>
|
|
224
|
+
<Divider
|
|
225
|
+
length={50}
|
|
226
|
+
thickness={1}
|
|
227
|
+
alignment={{ horizontal_align: 'RIGHT' }}
|
|
228
|
+
/>
|
|
218
229
|
</SBContainer>
|
|
219
230
|
</SBContainer>
|
|
220
231
|
),
|
|
@@ -323,8 +334,8 @@ export const VerticalAlignment: Story = {
|
|
|
323
334
|
render: () => (
|
|
324
335
|
<SBContainer flex direction="column" gap="large">
|
|
325
336
|
<SBContainer addBackground>
|
|
326
|
-
<h4>
|
|
327
|
-
<p>Divider aligns to the
|
|
337
|
+
<h4>Top</h4>
|
|
338
|
+
<p>Divider aligns to the top</p>
|
|
328
339
|
<div
|
|
329
340
|
style={{
|
|
330
341
|
display: 'flex',
|
|
@@ -337,7 +348,7 @@ export const VerticalAlignment: Story = {
|
|
|
337
348
|
orientation="vertical"
|
|
338
349
|
length={50}
|
|
339
350
|
thickness={1}
|
|
340
|
-
alignment=
|
|
351
|
+
alignment={{ vertical_align: 'TOP' }}
|
|
341
352
|
spacing="16px"
|
|
342
353
|
/>
|
|
343
354
|
<span>Right</span>
|
|
@@ -345,8 +356,8 @@ export const VerticalAlignment: Story = {
|
|
|
345
356
|
</SBContainer>
|
|
346
357
|
|
|
347
358
|
<SBContainer addBackground>
|
|
348
|
-
<h4>
|
|
349
|
-
<p>Divider aligns to the
|
|
359
|
+
<h4>Middle</h4>
|
|
360
|
+
<p>Divider aligns to the middle</p>
|
|
350
361
|
<div
|
|
351
362
|
style={{
|
|
352
363
|
display: 'flex',
|
|
@@ -359,7 +370,7 @@ export const VerticalAlignment: Story = {
|
|
|
359
370
|
orientation="vertical"
|
|
360
371
|
length={50}
|
|
361
372
|
thickness={1}
|
|
362
|
-
alignment=
|
|
373
|
+
alignment={{ vertical_align: 'MIDDLE' }}
|
|
363
374
|
spacing="16px"
|
|
364
375
|
/>
|
|
365
376
|
<span>Right</span>
|
|
@@ -367,8 +378,8 @@ export const VerticalAlignment: Story = {
|
|
|
367
378
|
</SBContainer>
|
|
368
379
|
|
|
369
380
|
<SBContainer addBackground>
|
|
370
|
-
<h4>
|
|
371
|
-
<p>Divider aligns to the
|
|
381
|
+
<h4>Bottom</h4>
|
|
382
|
+
<p>Divider aligns to the bottom</p>
|
|
372
383
|
<div
|
|
373
384
|
style={{
|
|
374
385
|
display: 'flex',
|
|
@@ -381,7 +392,7 @@ export const VerticalAlignment: Story = {
|
|
|
381
392
|
orientation="vertical"
|
|
382
393
|
length={50}
|
|
383
394
|
thickness={1}
|
|
384
|
-
alignment=
|
|
395
|
+
alignment={{ vertical_align: 'BOTTOM' }}
|
|
385
396
|
spacing="16px"
|
|
386
397
|
/>
|
|
387
398
|
<span>Right</span>
|
|
@@ -1,45 +1,56 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AlignmentFieldDefaults,
|
|
3
|
+
ColorFieldDefaults,
|
|
4
|
+
} from '@hubspot/cms-components/fields';
|
|
1
5
|
import type { CSSVariables } from '../utils/types.js';
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
type AlignmentValue = typeof AlignmentFieldDefaults;
|
|
8
|
+
type ColorValue = typeof ColorFieldDefaults;
|
|
4
9
|
|
|
5
|
-
export type
|
|
10
|
+
export type DividerOrientation = 'horizontal' | 'vertical';
|
|
6
11
|
|
|
7
12
|
export type DividerBorderStyle = 'solid' | 'dotted' | 'dashed' | 'double';
|
|
8
13
|
|
|
14
|
+
export type DividerAlignmentDirection = 'HORIZONTAL' | 'VERTICAL';
|
|
15
|
+
|
|
9
16
|
type PixelValue = `${number}px`;
|
|
10
17
|
|
|
11
18
|
export type DividerProps = {
|
|
12
19
|
orientation?: DividerOrientation;
|
|
13
|
-
alignment?:
|
|
20
|
+
alignment?: AlignmentValue;
|
|
14
21
|
spacing?: PixelValue;
|
|
15
22
|
borderStyle?: DividerBorderStyle;
|
|
16
23
|
length?: number;
|
|
17
24
|
thickness?: number;
|
|
25
|
+
color?: ColorValue;
|
|
18
26
|
variant?: 'primary' | 'secondary' | 'tertiary';
|
|
19
27
|
className?: string;
|
|
20
28
|
style?: CSSVariables;
|
|
21
29
|
};
|
|
22
30
|
|
|
23
|
-
export type
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
alignmentDefault?: string;
|
|
30
|
-
lengthLabel?: string;
|
|
31
|
-
lengthName?: string;
|
|
32
|
-
lengthDefault?: number;
|
|
33
|
-
thicknessLabel?: string;
|
|
34
|
-
thicknessName?: string;
|
|
35
|
-
thicknessDefault?: number;
|
|
36
|
-
};
|
|
31
|
+
export type StyleFieldName =
|
|
32
|
+
| 'borderStyle'
|
|
33
|
+
| 'color'
|
|
34
|
+
| 'thickness'
|
|
35
|
+
| 'length'
|
|
36
|
+
| 'alignment';
|
|
37
37
|
|
|
38
38
|
export type StyleFieldsProps = {
|
|
39
|
-
|
|
40
|
-
spacingName?: string;
|
|
41
|
-
spacingDefault?: string;
|
|
39
|
+
hideFields?: StyleFieldName[];
|
|
42
40
|
borderStyleLabel?: string;
|
|
43
41
|
borderStyleName?: string;
|
|
44
42
|
borderStyleDefault?: string;
|
|
43
|
+
thicknessLabel?: string;
|
|
44
|
+
thicknessName?: string;
|
|
45
|
+
thicknessDefault?: number;
|
|
46
|
+
lengthLabel?: string;
|
|
47
|
+
lengthName?: string;
|
|
48
|
+
lengthDefault?: number;
|
|
49
|
+
alignmentLabel?: string;
|
|
50
|
+
alignmentName?: string;
|
|
51
|
+
alignmentDefault?: AlignmentValue;
|
|
52
|
+
alignmentDirection?: DividerAlignmentDirection;
|
|
53
|
+
colorLabel?: string;
|
|
54
|
+
colorName?: string;
|
|
55
|
+
colorDefault?: ColorValue;
|
|
45
56
|
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ColorField, ChoiceField } from '@hubspot/cms-components/fields';
|
|
2
|
+
import type { StyleFieldsProps } from './types.js';
|
|
3
|
+
|
|
4
|
+
const StyleFields = ({
|
|
5
|
+
hideFields = [],
|
|
6
|
+
iconColorLabel = 'Icon color',
|
|
7
|
+
iconColorName = 'iconColor',
|
|
8
|
+
iconColorDefault = { color: '#A8A8A8', opacity: 100 },
|
|
9
|
+
iconBackgroundColorLabel = 'Background color',
|
|
10
|
+
iconBackgroundColorName = 'iconBackgroundColor',
|
|
11
|
+
iconBackgroundColorDefault = { color: '#2C2C2C', opacity: 100 },
|
|
12
|
+
iconShapeLabel = 'Icon shape',
|
|
13
|
+
iconShapeName = 'iconShape',
|
|
14
|
+
iconShapeDefault = '0px',
|
|
15
|
+
iconSizeLabel = 'Icon size',
|
|
16
|
+
iconSizeName = 'iconSize',
|
|
17
|
+
iconSizeDefault = '16',
|
|
18
|
+
}: StyleFieldsProps) => {
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
{!hideFields.includes('iconColor') && (
|
|
22
|
+
<ColorField
|
|
23
|
+
label={iconColorLabel}
|
|
24
|
+
name={iconColorName}
|
|
25
|
+
default={iconColorDefault}
|
|
26
|
+
showOpacity={false}
|
|
27
|
+
/>
|
|
28
|
+
)}
|
|
29
|
+
{!hideFields.includes('iconBackgroundColor') && (
|
|
30
|
+
<ColorField
|
|
31
|
+
label={iconBackgroundColorLabel}
|
|
32
|
+
name={iconBackgroundColorName}
|
|
33
|
+
default={iconBackgroundColorDefault}
|
|
34
|
+
showOpacity={false}
|
|
35
|
+
/>
|
|
36
|
+
)}
|
|
37
|
+
{!hideFields.includes('iconShape') && (
|
|
38
|
+
<ChoiceField
|
|
39
|
+
label={iconShapeLabel}
|
|
40
|
+
name={iconShapeName}
|
|
41
|
+
display="buttons"
|
|
42
|
+
preset="icon_shape"
|
|
43
|
+
choices={[
|
|
44
|
+
['0px', 'Square'],
|
|
45
|
+
['8px', 'Rounded'],
|
|
46
|
+
['100%', 'Circle'],
|
|
47
|
+
]}
|
|
48
|
+
default={iconShapeDefault}
|
|
49
|
+
required={true}
|
|
50
|
+
/>
|
|
51
|
+
)}
|
|
52
|
+
{!hideFields.includes('iconSize') && (
|
|
53
|
+
<ChoiceField
|
|
54
|
+
label={iconSizeLabel}
|
|
55
|
+
name={iconSizeName}
|
|
56
|
+
choices={[
|
|
57
|
+
['16', 'Small (16x16 px)'],
|
|
58
|
+
['24', 'Medium (24x24 px)'],
|
|
59
|
+
['32', 'Large (32x32 px)'],
|
|
60
|
+
]}
|
|
61
|
+
default={iconSizeDefault}
|
|
62
|
+
required={true}
|
|
63
|
+
/>
|
|
64
|
+
)}
|
|
65
|
+
</>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export default StyleFields;
|
|
@@ -7,3 +7,14 @@
|
|
|
7
7
|
width: var(--hscl-icon-size);
|
|
8
8
|
height: var(--hscl-icon-size);
|
|
9
9
|
}
|
|
10
|
+
|
|
11
|
+
.iconBackground {
|
|
12
|
+
display: inline-flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
justify-content: center;
|
|
15
|
+
justify-self: flex-start;
|
|
16
|
+
align-self: flex-start;
|
|
17
|
+
background-color: var(--hscl-iconBackground-backgroundColor, transparent);
|
|
18
|
+
padding: var(--hscl-iconBackground-padding, 12px);
|
|
19
|
+
border-radius: var(--hscl-iconBackground-shape, 0px);
|
|
20
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import styles from './index.module.scss';
|
|
2
2
|
import { Icon as CMSIcon } from '@hubspot/cms-components';
|
|
3
3
|
import ContentFields from './ContentFields.js';
|
|
4
|
+
import StyleFields from './StyleFields.js';
|
|
4
5
|
import cx from '../utils/classname.js';
|
|
5
6
|
import type { CSSVariables } from '../utils/types.js';
|
|
6
7
|
import { IconProps } from './types.js';
|
|
@@ -14,18 +15,22 @@ const IconComponent = ({
|
|
|
14
15
|
purpose = 'DECORATIVE',
|
|
15
16
|
title = '',
|
|
16
17
|
fill,
|
|
18
|
+
showIconBackground = false,
|
|
19
|
+
iconBackgroundColor,
|
|
20
|
+
iconBackgroundPadding,
|
|
21
|
+
iconBackgroundShape,
|
|
17
22
|
}: IconProps) => {
|
|
18
23
|
if (!showIcon) return null;
|
|
19
24
|
|
|
20
|
-
const defaultClasses = styles.icon;
|
|
21
|
-
const combinedClasses = cx(defaultClasses, className);
|
|
22
|
-
|
|
23
25
|
const cssVariables: CSSVariables = {
|
|
24
26
|
'--hscl-icon-size': `${size}px`,
|
|
25
27
|
...(fill && { '--hscl-icon-fill': fill }),
|
|
26
28
|
};
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
const defaultClasses = styles.icon;
|
|
31
|
+
const combinedClasses = cx(defaultClasses, className);
|
|
32
|
+
|
|
33
|
+
const icon = (
|
|
29
34
|
<CMSIcon
|
|
30
35
|
fieldPath={fieldPath}
|
|
31
36
|
height={size}
|
|
@@ -35,13 +40,35 @@ const IconComponent = ({
|
|
|
35
40
|
title={title}
|
|
36
41
|
/>
|
|
37
42
|
);
|
|
43
|
+
|
|
44
|
+
if (!showIconBackground) return icon;
|
|
45
|
+
|
|
46
|
+
const backgroundCssVariables: CSSVariables = {
|
|
47
|
+
...(iconBackgroundColor && {
|
|
48
|
+
'--hscl-iconBackground-backgroundColor': iconBackgroundColor,
|
|
49
|
+
}),
|
|
50
|
+
...(iconBackgroundPadding && {
|
|
51
|
+
'--hscl-iconBackground-padding': `${iconBackgroundPadding}px`,
|
|
52
|
+
}),
|
|
53
|
+
...(iconBackgroundShape && {
|
|
54
|
+
'--hscl-iconBackground-shape': iconBackgroundShape,
|
|
55
|
+
}),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<div className={styles.iconBackground} style={backgroundCssVariables}>
|
|
60
|
+
{icon}
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
38
63
|
};
|
|
39
64
|
|
|
40
65
|
type IconComponentType = typeof IconComponent & {
|
|
41
66
|
ContentFields: typeof ContentFields;
|
|
67
|
+
StyleFields: typeof StyleFields;
|
|
42
68
|
};
|
|
43
69
|
|
|
44
70
|
const Icon = IconComponent as IconComponentType;
|
|
45
71
|
Icon.ContentFields = ContentFields;
|
|
72
|
+
Icon.StyleFields = StyleFields;
|
|
46
73
|
|
|
47
74
|
export default Icon;
|
|
@@ -9,7 +9,7 @@ import Icon from '@hubspot/cms-component-library/Icon';
|
|
|
9
9
|
|
|
10
10
|
## Purpose
|
|
11
11
|
|
|
12
|
-
The Icon component wraps the native HubSpot CMS Icon component to provide a consistent interface for rendering icons with customizable styling and accessibility options. It simplifies icon usage in HubSpot CMS projects by handling common configuration patterns like sizing, color theming through CSS variables, and proper accessibility attributes (SEMANTIC vs DECORATIVE purpose).
|
|
12
|
+
The Icon component wraps the native HubSpot CMS Icon component to provide a consistent interface for rendering icons with customizable styling and accessibility options. It simplifies icon usage in HubSpot CMS projects by handling common configuration patterns like sizing, color theming through CSS variables, optional background containers, and proper accessibility attributes (SEMANTIC vs DECORATIVE purpose).
|
|
13
13
|
|
|
14
14
|
## Component Structure
|
|
15
15
|
|
|
@@ -18,6 +18,7 @@ Icon/
|
|
|
18
18
|
├── index.tsx # Main component with render logic
|
|
19
19
|
├── types.ts # TypeScript type definitions
|
|
20
20
|
├── ContentFields.tsx # HubSpot field definitions for icon content
|
|
21
|
+
├── StyleFields.tsx # HubSpot field definitions for icon styles
|
|
21
22
|
├── index.module.scss # CSS module with design tokens
|
|
22
23
|
└── stories/
|
|
23
24
|
├── Icon.stories.tsx # Component usage examples
|
|
@@ -29,7 +30,7 @@ Icon/
|
|
|
29
30
|
|
|
30
31
|
### Icon (Main Component)
|
|
31
32
|
|
|
32
|
-
**Purpose:** Renders an icon with configurable size, color, and accessibility properties.
|
|
33
|
+
**Purpose:** Renders an icon with configurable size, color, background, and accessibility properties.
|
|
33
34
|
|
|
34
35
|
**Props:**
|
|
35
36
|
```tsx
|
|
@@ -42,6 +43,10 @@ Icon/
|
|
|
42
43
|
showIcon?: boolean; // Toggle icon visibility (default: true)
|
|
43
44
|
purpose?: 'SEMANTIC' | 'DECORATIVE'; // Icon accessibility role (default: 'DECORATIVE')
|
|
44
45
|
title?: string; // Icon title for screen readers (use with SEMANTIC)
|
|
46
|
+
showIconBackground?: boolean; // Renders a centered background div behind the icon (default: false)
|
|
47
|
+
iconBackgroundColor?: string; // Background div color (used when showIconBackground is true)
|
|
48
|
+
iconBackgroundPadding?: number; // Padding around the icon inside the background div in px (default: 12)
|
|
49
|
+
iconBackgroundShape?: string; // Border-radius of the background div, e.g. '0px', '8px', '100%' (default: 0px)
|
|
45
50
|
}
|
|
46
51
|
```
|
|
47
52
|
|
|
@@ -89,6 +94,19 @@ import Icon from '@hubspot/cms-component-library/Icon';
|
|
|
89
94
|
/>
|
|
90
95
|
```
|
|
91
96
|
|
|
97
|
+
### Icon with Background
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
<Icon
|
|
101
|
+
fieldPath="icon"
|
|
102
|
+
size={24}
|
|
103
|
+
showIconBackground={true}
|
|
104
|
+
iconBackgroundColor="#2C2C2C"
|
|
105
|
+
iconBackgroundPadding={16}
|
|
106
|
+
iconBackgroundShape="100%"
|
|
107
|
+
/>
|
|
108
|
+
```
|
|
109
|
+
|
|
92
110
|
## HubSpot CMS Integration
|
|
93
111
|
|
|
94
112
|
### Field Definitions
|
|
@@ -115,9 +133,21 @@ Configurable props for icon selection and visibility:
|
|
|
115
133
|
- `icon`: IconField for selecting the icon
|
|
116
134
|
- `showIcon`: BooleanField toggle for icon visibility (optional, enabled with `addIconToggle={true}`)
|
|
117
135
|
|
|
118
|
-
####
|
|
136
|
+
#### StyleFields
|
|
119
137
|
|
|
120
|
-
|
|
138
|
+
Configurable props for icon appearance:
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
<Icon.StyleFields />
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Fields:**
|
|
145
|
+
- `iconColor`: ColorField for the icon fill color
|
|
146
|
+
- `iconBackgroundColor`: ColorField for the background div color
|
|
147
|
+
- `iconShape`: ChoiceField for the background border-radius (`'0px'` Square, `'8px'` Rounded, `'100%'` Circle)
|
|
148
|
+
- `iconSize`: ChoiceField for icon size (16px Small, 24px Medium, 32px Large)
|
|
149
|
+
|
|
150
|
+
All fields support `label`, `name`, and `default` customization props, and can be hidden via `hideFields`.
|
|
121
151
|
|
|
122
152
|
### Module Usage Example
|
|
123
153
|
|
|
@@ -128,8 +158,12 @@ export default function IconModule({ fieldValues }) {
|
|
|
128
158
|
return (
|
|
129
159
|
<Icon
|
|
130
160
|
fieldPath="icon"
|
|
131
|
-
size={fieldValues.iconSize || 24}
|
|
161
|
+
size={Number(fieldValues.style?.iconSize) || 24}
|
|
132
162
|
showIcon={fieldValues.showIcon}
|
|
163
|
+
fill={fieldValues.style?.iconColor?.color}
|
|
164
|
+
showIconBackground={fieldValues.style?.showIconBackground}
|
|
165
|
+
iconBackgroundColor={fieldValues.style?.iconBackgroundColor?.color}
|
|
166
|
+
iconBackgroundShape={fieldValues.style?.iconShape}
|
|
133
167
|
purpose="DECORATIVE"
|
|
134
168
|
/>
|
|
135
169
|
);
|
|
@@ -139,14 +173,15 @@ export default function IconModule({ fieldValues }) {
|
|
|
139
173
|
### Module Fields Example
|
|
140
174
|
|
|
141
175
|
```tsx
|
|
142
|
-
import { ModuleFields } from '@hubspot/cms-components/fields';
|
|
176
|
+
import { ModuleFields, FieldGroup } from '@hubspot/cms-components/fields';
|
|
143
177
|
import Icon from '@hubspot/cms-component-library/Icon';
|
|
144
178
|
|
|
145
179
|
export const fields = (
|
|
146
180
|
<ModuleFields>
|
|
147
|
-
<Icon.ContentFields
|
|
148
|
-
|
|
149
|
-
|
|
181
|
+
<Icon.ContentFields addIconToggle={true} />
|
|
182
|
+
<FieldGroup name="style" label="Style" tab="STYLE">
|
|
183
|
+
<Icon.StyleFields />
|
|
184
|
+
</FieldGroup>
|
|
150
185
|
</ModuleFields>
|
|
151
186
|
);
|
|
152
187
|
```
|
|
@@ -161,6 +196,11 @@ The Icon component uses CSS variables for theming and customization:
|
|
|
161
196
|
- `--hscl-icon-fill`: Icon fill color (default: currentColor)
|
|
162
197
|
- `--hscl-icon-size`: Icon width and height (set automatically from the `size` prop)
|
|
163
198
|
|
|
199
|
+
**Background Styles (applied when `showIconBackground` is true):**
|
|
200
|
+
- `--hscl-iconBackground-backgroundColor`: Background div color
|
|
201
|
+
- `--hscl-iconBackground-padding`: Padding around the icon inside the background div (default: 12px)
|
|
202
|
+
- `--hscl-iconBackground-shape`: Border-radius of the background div (default: 0px)
|
|
203
|
+
|
|
164
204
|
|
|
165
205
|
## Accessibility
|
|
166
206
|
|
|
@@ -179,4 +219,4 @@ The Icon component follows accessibility best practices:
|
|
|
179
219
|
- **Use CSS variables for theming**: Override `--hscl-icon-fill` for consistent color theming across your application
|
|
180
220
|
- **Size appropriately**: Common sizes are 12px (small), 16px (default inline), 24px (medium), 32px (large), 48px (extra large)
|
|
181
221
|
- **Field path**: The `fieldPath` prop should match the field name defined in ContentFields
|
|
182
|
-
- **
|
|
222
|
+
- **Background shape**: The `iconShape` StyleField value maps directly to `iconBackgroundShape` on the component — pass it through as-is
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
IconFieldDefaults,
|
|
3
3
|
BooleanFieldDefaults,
|
|
4
|
+
ColorFieldDefaults,
|
|
4
5
|
} from '@hubspot/cms-components/fields';
|
|
5
6
|
|
|
7
|
+
type ColorFieldValue = typeof ColorFieldDefaults;
|
|
8
|
+
|
|
6
9
|
export type IconPurpose = 'SEMANTIC' | 'DECORATIVE';
|
|
7
10
|
|
|
8
11
|
export type IconProps = {
|
|
@@ -14,6 +17,10 @@ export type IconProps = {
|
|
|
14
17
|
showIcon?: boolean;
|
|
15
18
|
purpose?: IconPurpose;
|
|
16
19
|
title?: string;
|
|
20
|
+
showIconBackground?: boolean;
|
|
21
|
+
iconBackgroundColor?: string;
|
|
22
|
+
iconBackgroundPadding?: number;
|
|
23
|
+
iconBackgroundShape?: string;
|
|
17
24
|
};
|
|
18
25
|
|
|
19
26
|
type IconToggleProps = {
|
|
@@ -36,3 +43,25 @@ export type IconContentFieldsWithToggleProps =
|
|
|
36
43
|
export type ContentFieldsProps =
|
|
37
44
|
| IconContentFieldsWithToggleProps
|
|
38
45
|
| IconContentFieldsWithoutToggleProps;
|
|
46
|
+
|
|
47
|
+
export type StyleFieldName =
|
|
48
|
+
| 'iconColor'
|
|
49
|
+
| 'iconBackgroundColor'
|
|
50
|
+
| 'iconShape'
|
|
51
|
+
| 'iconSize';
|
|
52
|
+
|
|
53
|
+
export type StyleFieldsProps = {
|
|
54
|
+
hideFields?: StyleFieldName[];
|
|
55
|
+
iconColorLabel?: string;
|
|
56
|
+
iconColorName?: string;
|
|
57
|
+
iconColorDefault?: ColorFieldValue;
|
|
58
|
+
iconBackgroundColorLabel?: string;
|
|
59
|
+
iconBackgroundColorName?: string;
|
|
60
|
+
iconBackgroundColorDefault?: ColorFieldValue;
|
|
61
|
+
iconShapeLabel?: string;
|
|
62
|
+
iconShapeName?: string;
|
|
63
|
+
iconShapeDefault?: string;
|
|
64
|
+
iconSizeLabel?: string;
|
|
65
|
+
iconSizeName?: string;
|
|
66
|
+
iconSizeDefault?: string;
|
|
67
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RichTextField,
|
|
3
|
+
RichTextFieldType,
|
|
4
|
+
} from '@hubspot/cms-components/fields';
|
|
5
|
+
import type { ContentFieldsProps } from './types.js';
|
|
6
|
+
|
|
7
|
+
// To do: These are placeholders - we can refine and add more after some UX feedback and further discussion
|
|
8
|
+
|
|
9
|
+
const headingEnabledFeatures: RichTextFieldType['enabledFeatures'] = [
|
|
10
|
+
'block',
|
|
11
|
+
'alignment',
|
|
12
|
+
'indents',
|
|
13
|
+
'lists',
|
|
14
|
+
'standard_emphasis',
|
|
15
|
+
'advanced_emphasis',
|
|
16
|
+
'link',
|
|
17
|
+
'personalize',
|
|
18
|
+
'nonbreaking_space',
|
|
19
|
+
'source_code',
|
|
20
|
+
'visual_blocks',
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const bodyContentEnabledFeatures: RichTextFieldType['enabledFeatures'] = [
|
|
24
|
+
'block',
|
|
25
|
+
'alignment',
|
|
26
|
+
'indents',
|
|
27
|
+
'lists',
|
|
28
|
+
'standard_emphasis',
|
|
29
|
+
'advanced_emphasis',
|
|
30
|
+
'link',
|
|
31
|
+
'image',
|
|
32
|
+
'emoji',
|
|
33
|
+
'table',
|
|
34
|
+
'personalize',
|
|
35
|
+
'cta',
|
|
36
|
+
'embed',
|
|
37
|
+
'video',
|
|
38
|
+
'charmap',
|
|
39
|
+
'anchor',
|
|
40
|
+
'nonbreaking_space',
|
|
41
|
+
'source_code',
|
|
42
|
+
'visual_blocks',
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const featureSetMap = {
|
|
46
|
+
bodyContent: bodyContentEnabledFeatures,
|
|
47
|
+
heading: headingEnabledFeatures,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const ContentFields = ({
|
|
51
|
+
textLabel = 'Text',
|
|
52
|
+
textName = 'text',
|
|
53
|
+
textDefault = '<p>Text goes here.</p>',
|
|
54
|
+
textFeatureSet = 'bodyContent',
|
|
55
|
+
}: ContentFieldsProps) => {
|
|
56
|
+
return (
|
|
57
|
+
<RichTextField
|
|
58
|
+
label={textLabel}
|
|
59
|
+
name={textName}
|
|
60
|
+
default={textDefault}
|
|
61
|
+
enabledFeatures={featureSetMap[textFeatureSet]}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default ContentFields;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { RichText } from '@hubspot/cms-components';
|
|
2
|
+
import styles from './index.module.scss';
|
|
3
|
+
import ContentFields from './ContentFields.js';
|
|
4
|
+
import cx from '../utils/classname.js';
|
|
5
|
+
import { TextProps } from './types.js';
|
|
6
|
+
|
|
7
|
+
const TextComponent = ({
|
|
8
|
+
fieldPath,
|
|
9
|
+
className = '',
|
|
10
|
+
style = {},
|
|
11
|
+
}: TextProps) => {
|
|
12
|
+
const defaultClasses = styles.text;
|
|
13
|
+
const combinedClasses = cx(defaultClasses, className);
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<RichText fieldPath={fieldPath} className={combinedClasses} style={style} />
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type TextComponentType = typeof TextComponent & {
|
|
21
|
+
ContentFields: typeof ContentFields;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const Text = TextComponent as TextComponentType;
|
|
25
|
+
Text.ContentFields = ContentFields;
|
|
26
|
+
|
|
27
|
+
export default Text;
|