@hubspot/cms-component-library 0.3.2 → 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/Icon/index.module.scss +11 -0
- package/components/componentLibrary/Icon/index.tsx +28 -4
- package/components/componentLibrary/Icon/llm.txt +50 -10
- package/components/componentLibrary/Icon/types.ts +4 -0
- package/package.json +1 -1
|
@@ -57,3 +57,22 @@ export const MinusIcon = () => {
|
|
|
57
57
|
</svg>
|
|
58
58
|
);
|
|
59
59
|
};
|
|
60
|
+
|
|
61
|
+
export const CaretIcon = () => {
|
|
62
|
+
return (
|
|
63
|
+
<svg
|
|
64
|
+
className={cx(
|
|
65
|
+
styles.accordionIcon,
|
|
66
|
+
styles.accordionIconCaret,
|
|
67
|
+
'accordionIconCaret'
|
|
68
|
+
)}
|
|
69
|
+
viewBox="0 0 24 24"
|
|
70
|
+
fill="currentColor"
|
|
71
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
72
|
+
aria-hidden="true"
|
|
73
|
+
role="img"
|
|
74
|
+
>
|
|
75
|
+
<path d="M11.2445 16.5296C11.717 16.9121 12.4107 16.8859 12.8495 16.4471L17.6495 11.6471C17.9945 11.3021 18.0957 10.7884 17.9082 10.3384C17.7207 9.88836 17.2857 9.59961 16.802 9.59961H7.20195C6.7182 9.59961 6.27945 9.89211 6.09195 10.3421C5.90445 10.7921 6.00945 11.3059 6.35445 11.6471L11.1545 16.4471L11.2445 16.5296Z" />
|
|
76
|
+
</svg>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
@@ -2,7 +2,7 @@ import styles from './index.module.scss';
|
|
|
2
2
|
import ContentFields from './ContentFields.js';
|
|
3
3
|
import cx from '../../utils/classname.js';
|
|
4
4
|
import { AccordionTitleProps } from './types.js';
|
|
5
|
-
import { ChevronIcon, PlusIcon, MinusIcon } from './icons.js';
|
|
5
|
+
import { ChevronIcon, PlusIcon, MinusIcon, CaretIcon } from './icons.js';
|
|
6
6
|
|
|
7
7
|
const AccordionTitleComponent = ({
|
|
8
8
|
icon = 'chevron',
|
|
@@ -24,6 +24,8 @@ const AccordionTitleComponent = ({
|
|
|
24
24
|
);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
if (icon === 'caret') return <CaretIcon />;
|
|
28
|
+
|
|
27
29
|
return null;
|
|
28
30
|
};
|
|
29
31
|
|
|
@@ -104,10 +104,10 @@ Accordion/
|
|
|
104
104
|
**Props:**
|
|
105
105
|
```tsx
|
|
106
106
|
{
|
|
107
|
-
icon?: 'chevron' | 'plus';
|
|
108
|
-
className?: string;
|
|
109
|
-
style?: React.CSSProperties;
|
|
110
|
-
children?: React.ReactNode;
|
|
107
|
+
icon?: 'chevron' | 'plus' | 'caret'; // Icon type (default: 'chevron')
|
|
108
|
+
className?: string; // Additional CSS classes
|
|
109
|
+
style?: React.CSSProperties; // Inline styles
|
|
110
|
+
children?: React.ReactNode; // Title text content
|
|
111
111
|
}
|
|
112
112
|
```
|
|
113
113
|
|
|
@@ -243,7 +243,7 @@ Configurable props for title text and icon:
|
|
|
243
243
|
|
|
244
244
|
**Fields:**
|
|
245
245
|
- `title`: TextField for accordion title text
|
|
246
|
-
- `icon`: ChoiceField for selecting icon type (chevron, plus)
|
|
246
|
+
- `icon`: ChoiceField for selecting icon type (caret, chevron, plus)
|
|
247
247
|
|
|
248
248
|
#### AccordionContent.ContentFields
|
|
249
249
|
|
|
@@ -397,6 +397,7 @@ The Accordion component uses CSS variables for theming and customization. Variab
|
|
|
397
397
|
- `.accordionIconChevron`: Chevron-specific sizing (rotates 180° when open)
|
|
398
398
|
- `.accordionIconPlus`: Plus icon (hidden when open)
|
|
399
399
|
- `.accordionIconMinus`: Minus icon (shown when open)
|
|
400
|
+
- `.accordionIconCaret`: Caret icon (rotates 180° when open)
|
|
400
401
|
|
|
401
402
|
**AccordionContent (`AccordionContent/index.module.scss`):**
|
|
402
403
|
- `.accordionContent`: Content area with padding and typography
|
|
@@ -420,7 +421,7 @@ The Accordion component follows accessibility best practices:
|
|
|
420
421
|
|
|
421
422
|
## Best Practices
|
|
422
423
|
|
|
423
|
-
- **Choose appropriate icons**: Use `chevron` for subtle indication, `plus` for clearer expand/collapse semantics (common in FAQs)
|
|
424
|
+
- **Choose appropriate icons**: Use `caret` for a compact filled triangle indicator, `chevron` for subtle indication, `plus` for clearer expand/collapse semantics (common in FAQs)
|
|
424
425
|
- **Consistent variants**: Apply the same variant to all items within an accordion for visual consistency
|
|
425
426
|
- **Gap selection**: Use any valid CSS length value (e.g., '8px', '16px', '24px', '48px') for spacing between items
|
|
426
427
|
- **Dynamic rendering**: Always provide unique `key` props when mapping arrays to AccordionItems
|
|
@@ -106,6 +106,27 @@ export const IconOptions: Story = {
|
|
|
106
106
|
</AccordionItem>
|
|
107
107
|
</Accordion>
|
|
108
108
|
</SBContainer>
|
|
109
|
+
|
|
110
|
+
<SBContainer addBackground>
|
|
111
|
+
<h4>Caret Icon</h4>
|
|
112
|
+
<Accordion gap="16px">
|
|
113
|
+
<AccordionItem>
|
|
114
|
+
<AccordionTitle icon="caret">Caret Icon</AccordionTitle>
|
|
115
|
+
<AccordionContent>
|
|
116
|
+
<p>
|
|
117
|
+
The caret icon provides a simple visual cue for the expanded
|
|
118
|
+
state.
|
|
119
|
+
</p>
|
|
120
|
+
</AccordionContent>
|
|
121
|
+
</AccordionItem>
|
|
122
|
+
<AccordionItem>
|
|
123
|
+
<AccordionTitle icon="caret">Another caret item</AccordionTitle>
|
|
124
|
+
<AccordionContent>
|
|
125
|
+
<p>This is just some caret cake.</p>
|
|
126
|
+
</AccordionContent>
|
|
127
|
+
</AccordionItem>
|
|
128
|
+
</Accordion>
|
|
129
|
+
</SBContainer>
|
|
109
130
|
</SBContainer>
|
|
110
131
|
),
|
|
111
132
|
};
|
|
@@ -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
|
+
}
|
|
@@ -15,18 +15,22 @@ const IconComponent = ({
|
|
|
15
15
|
purpose = 'DECORATIVE',
|
|
16
16
|
title = '',
|
|
17
17
|
fill,
|
|
18
|
+
showIconBackground = false,
|
|
19
|
+
iconBackgroundColor,
|
|
20
|
+
iconBackgroundPadding,
|
|
21
|
+
iconBackgroundShape,
|
|
18
22
|
}: IconProps) => {
|
|
19
23
|
if (!showIcon) return null;
|
|
20
24
|
|
|
21
|
-
const defaultClasses = styles.icon;
|
|
22
|
-
const combinedClasses = cx(defaultClasses, className);
|
|
23
|
-
|
|
24
25
|
const cssVariables: CSSVariables = {
|
|
25
26
|
'--hscl-icon-size': `${size}px`,
|
|
26
27
|
...(fill && { '--hscl-icon-fill': fill }),
|
|
27
28
|
};
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
const defaultClasses = styles.icon;
|
|
31
|
+
const combinedClasses = cx(defaultClasses, className);
|
|
32
|
+
|
|
33
|
+
const icon = (
|
|
30
34
|
<CMSIcon
|
|
31
35
|
fieldPath={fieldPath}
|
|
32
36
|
height={size}
|
|
@@ -36,6 +40,26 @@ const IconComponent = ({
|
|
|
36
40
|
title={title}
|
|
37
41
|
/>
|
|
38
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
|
+
);
|
|
39
63
|
};
|
|
40
64
|
|
|
41
65
|
type IconComponentType = typeof IconComponent & {
|
|
@@ -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
|
|
@@ -17,6 +17,10 @@ export type IconProps = {
|
|
|
17
17
|
showIcon?: boolean;
|
|
18
18
|
purpose?: IconPurpose;
|
|
19
19
|
title?: string;
|
|
20
|
+
showIconBackground?: boolean;
|
|
21
|
+
iconBackgroundColor?: string;
|
|
22
|
+
iconBackgroundPadding?: number;
|
|
23
|
+
iconBackgroundShape?: string;
|
|
20
24
|
};
|
|
21
25
|
|
|
22
26
|
type IconToggleProps = {
|