@hubspot/cms-component-library 0.3.0 → 0.3.2

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.
Files changed (33) hide show
  1. package/components/componentLibrary/Button/index.tsx +1 -1
  2. package/components/componentLibrary/Divider/StyleFields.tsx +72 -14
  3. package/components/componentLibrary/Divider/index.tsx +31 -16
  4. package/components/componentLibrary/Divider/llm.txt +97 -103
  5. package/components/componentLibrary/Divider/stories/Divider.stories.tsx +30 -19
  6. package/components/componentLibrary/Divider/types.ts +31 -20
  7. package/components/componentLibrary/Flex/index.module.scss +4 -6
  8. package/components/componentLibrary/Flex/llm.txt +5 -7
  9. package/components/componentLibrary/Flex/types.ts +0 -4
  10. package/components/componentLibrary/Icon/StyleFields.tsx +69 -0
  11. package/components/componentLibrary/Icon/index.module.scss +2 -2
  12. package/components/componentLibrary/Icon/index.tsx +6 -2
  13. package/components/componentLibrary/Icon/llm.txt +7 -6
  14. package/components/componentLibrary/Icon/stories/Icon.stories.tsx +11 -11
  15. package/components/componentLibrary/Icon/stories/IconDecorator.module.scss +1 -2
  16. package/components/componentLibrary/Icon/types.ts +26 -1
  17. package/components/componentLibrary/Text/ContentFields.tsx +66 -0
  18. package/components/componentLibrary/Text/index.module.scss +3 -0
  19. package/components/componentLibrary/Text/index.tsx +27 -0
  20. package/components/componentLibrary/Text/llm.txt +170 -0
  21. package/components/componentLibrary/Text/types.ts +16 -0
  22. package/components/componentLibrary/_patterns/css-patterns.md +7 -18
  23. package/package.json +4 -4
  24. package/components/componentLibrary/Divider/ContentFields.tsx +0 -63
  25. package/components/componentLibrary/Heading/ContentFields.tsx +0 -37
  26. package/components/componentLibrary/Heading/StyleFields.tsx +0 -40
  27. package/components/componentLibrary/Heading/index.module.scss +0 -11
  28. package/components/componentLibrary/Heading/index.tsx +0 -52
  29. package/components/componentLibrary/Heading/llm.txt +0 -175
  30. package/components/componentLibrary/Heading/stories/Heading.stories.tsx +0 -88
  31. package/components/componentLibrary/Heading/stories/HeadingDecorator.module.scss +0 -47
  32. package/components/componentLibrary/Heading/stories/HeadingDecorator.tsx +0 -8
  33. package/components/componentLibrary/Heading/types.ts +0 -35
@@ -0,0 +1,170 @@
1
+ # Text Component
2
+
3
+ A component for rendering HubSpot CMS rich text field content.
4
+
5
+ ## Import path
6
+ ```tsx
7
+ import Text from '@hubspot/cms-component-library/Text';
8
+ ```
9
+
10
+ ## Purpose
11
+
12
+ The Text component wraps HubSpot's native `RichText` component to provide a consistent interface for rendering editable rich text content in HubSpot CMS modules. It handles the connection between a CMS field and the rendered output, while exposing a single CSS variable for text color theming. Use this component whenever a module needs a rich text area managed through the HubSpot page editor.
13
+
14
+ ## Component Structure
15
+
16
+ ```
17
+ Text/
18
+ ├── index.tsx # Main component wrapping HubSpot RichText
19
+ ├── types.ts # TypeScript type definitions
20
+ ├── ContentFields.tsx # HubSpot field definitions for rich text content
21
+ └── index.module.scss # CSS module with design tokens
22
+ ```
23
+
24
+ ## Components
25
+
26
+ ### Text (Main Component)
27
+
28
+ **Purpose:** Renders a HubSpot CMS rich text field at the given `fieldPath`, applying CSS module class and CSS variable theming for text color.
29
+
30
+ **Props:**
31
+ ```tsx
32
+ {
33
+ fieldPath?: string; // Path to the RichText field in HubSpot CMS (e.g., 'text', 'bodyContent')
34
+ className?: string; // Additional CSS classes (default: '')
35
+ style?: CSSVariables; // Inline styles, supports CSS custom properties (default: {})
36
+ }
37
+ ```
38
+
39
+ ## Usage Examples
40
+
41
+ ### Basic Text
42
+
43
+ ```tsx
44
+ import Text from '@hubspot/cms-component-library/Text';
45
+
46
+ <Text fieldPath="text" />
47
+ ```
48
+
49
+ ## HubSpot CMS Integration
50
+
51
+ ### Field Definitions
52
+
53
+ The Text component provides `ContentFields` for defining a `RichTextField` inside a HubSpot CMS module.
54
+
55
+ #### ContentFields
56
+
57
+ Configurable props for customizing the text field label, name, default value, and editor features:
58
+
59
+ ```tsx
60
+ <Text.ContentFields
61
+ textLabel="Body text"
62
+ textName="bodyText"
63
+ textDefault="<p>Enter your content here.</p>"
64
+ textFeatureSet="bodyContent"
65
+ />
66
+ ```
67
+
68
+ **Props:**
69
+ - `textLabel` (default: `'Text'`): Label shown in the HubSpot editor
70
+ - `textName` (default: `'text'`): Field name used as the `fieldPath` reference in the component
71
+ - `textDefault` (default: `'<p>Text goes here.</p>'`): Default HTML content for the field
72
+ - `textFeatureSet` (`'bodyContent' | 'heading'`, default: `'bodyContent'`): Controls the editor toolbar
73
+ - Use `'bodyContent'` for full-featured editing (includes image, emoji, table, embed, video, and more)
74
+ - Use `'heading'` for a reduced feature set suited to titles and captions (no rich media)
75
+
76
+ **Fields:**
77
+ - `text` (name set by `textName`): RichTextField for the rich text content
78
+
79
+ #### Style Fields
80
+
81
+ **Note:** There are no style fields included with this component. Do not try to import them.
82
+
83
+ ### Module Usage Example
84
+
85
+ ```tsx
86
+ import Text from '@hubspot/cms-component-library/Text';
87
+
88
+ export default function ArticleModule() {
89
+ return (
90
+ <Text fieldPath="bodyText" />
91
+ );
92
+ }
93
+ ```
94
+
95
+ ### Module Fields Example
96
+
97
+ ```tsx
98
+ import { ModuleFields } from '@hubspot/cms-components/fields';
99
+ import Text from '@hubspot/cms-component-library/Text';
100
+
101
+ export const fields = (
102
+ <ModuleFields>
103
+ <Text.ContentFields
104
+ textLabel="Body text"
105
+ textName="bodyText"
106
+ textDefault="<p>Enter your content here.</p>"
107
+ textFeatureSet="bodyContent"
108
+ />
109
+ </ModuleFields>
110
+ );
111
+ ```
112
+
113
+ ### Multiple Text Fields in One Module
114
+
115
+ ```tsx
116
+ import { ModuleFields } from '@hubspot/cms-components/fields';
117
+ import Text from '@hubspot/cms-component-library/Text';
118
+
119
+ export const fields = (
120
+ <ModuleFields>
121
+ <Text.ContentFields
122
+ textLabel="Heading text"
123
+ textName="headingText"
124
+ textDefault="<p>Enter your heading.</p>"
125
+ textFeatureSet="heading"
126
+ />
127
+ <Text.ContentFields
128
+ textLabel="Body text"
129
+ textName="bodyText"
130
+ textDefault="<p>Enter your body content.</p>"
131
+ textFeatureSet="bodyContent"
132
+ />
133
+ </ModuleFields>
134
+ );
135
+
136
+ export default function ArticleModule() {
137
+ return (
138
+ <div>
139
+ <Text fieldPath="headingText" />
140
+ <Text fieldPath="bodyText" />
141
+ </div>
142
+ );
143
+ }
144
+ ```
145
+
146
+ ## Styling
147
+
148
+ ### CSS Variables
149
+
150
+ **Base Styles:**
151
+ - `--hscl-text-color`: Text color applied to the rendered rich text content (default: `currentColor`)
152
+
153
+ ## Accessibility
154
+
155
+ - **Semantic HTML**: Content is rendered directly from the HubSpot CMS editor output, which produces standard HTML elements (`<p>`, `<h1>`–`<h6>`, `<ul>`, `<ol>`, etc.)
156
+ - **Structured content**: Encourage editors to use proper heading hierarchy and list elements within the rich text editor for screen reader compatibility
157
+ - **Link accessibility**: Links created in the rich text editor will render as native `<a>` elements
158
+
159
+ ## Best Practices
160
+
161
+ - **Match `fieldPath` to `textName`**: The `fieldPath` prop on the component must match the `textName` prop on `ContentFields` — they reference the same CMS field
162
+ - **Choose the right feature set**: Use `'heading'` for simpler text areas (titles, captions) to keep the editor toolbar uncluttered; use `'bodyContent'` for full article or section content
163
+ - **Style fields**: There are no style fields for this component. Do not try to import them
164
+ - **CSS Variables for theming**: Override `--hscl-text-color` via the `style` prop rather than using CSS selectors that target the component's internals
165
+ - **Multiple fields per module**: You can render multiple `Text` components in one module by giving each a unique `textName` / `fieldPath` pair
166
+
167
+ ## Related Components
168
+
169
+ - **Button**: Use for call-to-action elements within or adjacent to text content
170
+ - **Link**: Use for standalone clickable text or wrapped content that requires a link without rich text editing
@@ -0,0 +1,16 @@
1
+ import type { CSSVariables } from '../utils/types.js';
2
+
3
+ export type TextProps = {
4
+ fieldPath?: string;
5
+ className?: string;
6
+ style?: CSSVariables;
7
+ };
8
+
9
+ export type TextFeatureSet = 'bodyContent' | 'heading';
10
+
11
+ export type ContentFieldsProps = {
12
+ textLabel?: string;
13
+ textName?: string;
14
+ textDefault?: string;
15
+ textFeatureSet?: TextFeatureSet;
16
+ };
@@ -7,7 +7,7 @@ This document outlines CSS variable naming conventions, styling patterns, and CS
7
7
  **Pattern:** `--hscl-componentName-[elementName]-cssProperty-[state]`
8
8
 
9
9
  - **Prefix:** Always start with `--hscl-` (HubSpot Component Library)
10
- - **Component name:** Lowercase component name in camelCase, with name taken from the index.tsx file (e.g., `button`, `heading`, `icon`, `divider`, `image`, `accordion`)
10
+ - **Component name:** Lowercase component name in camelCase, with name taken from the index.tsx file (e.g., `button`, `icon`, `divider`, `image`, `accordion`, `card`)
11
11
  - **Element name (optional):** For sub-elements within a component, specify the element name in camelCase (e.g., `icon`, `body`, `title`, `header`, `overlay`, `submenu`)
12
12
  - Omit for properties that apply to the main component element itself
13
13
  - Include for properties that apply to specific sub-elements
@@ -19,8 +19,6 @@ This document outlines CSS variable naming conventions, styling patterns, and CS
19
19
  --hscl-button-backgroundColor
20
20
  --hscl-button-backgroundColor-hover
21
21
  --hscl-button-backgroundColor-focus
22
- --hscl-heading-fontSize
23
- --hscl-heading-textAlign
24
22
  --hscl-divider-borderColor
25
23
  --hscl-icon-fill
26
24
  --hscl-card-padding
@@ -47,12 +45,12 @@ This document outlines CSS variable naming conventions, styling patterns, and CS
47
45
 
48
46
  **Nested/Dynamic Variables:**
49
47
  ```typescript
50
- // Example from Heading component - uses template variables
51
- '--hscl-heading-font': `var(--hscl-heading-${displayAsValue}-font)`
52
- '--hscl-heading-fontSize': `var(--hscl-heading-${displayAsValue}-fontSize)`
48
+ // Components can use template variables to dynamically reference nested variables
49
+ '--hscl-component-font': `var(--hscl-component-${variantValue}-font)`
50
+ '--hscl-component-fontSize': `var(--hscl-component-${variantValue}-fontSize)`
53
51
  ```
54
52
 
55
- **Note:** When using dynamic variants (like h1, h2, display1), use numbers without underscores (e.g., `display1` not `display_1`).
53
+ **Note:** When using dynamic variants, use numbers without underscores (e.g., `variant1` not `variant_1`).
56
54
 
57
55
  ## CSS Variables Application
58
56
 
@@ -105,15 +103,6 @@ const elementStyle: CSSVariables = {
105
103
  ```typescript
106
104
  import type { CSSVariables } from '../utils/types.js';
107
105
 
108
- // Heading - dynamic variable references
109
- const cssVariables: CSSVariables = {
110
- '--hscl-heading-font': `var(--hscl-heading-${displayAsValue}-font)`,
111
- '--hscl-heading-fontSize': `var(--hscl-heading-${displayAsValue}-fontSize)`,
112
- ...(alignment && {
113
- '--hscl-heading-textAlign': alignment.toLowerCase(),
114
- }),
115
- };
116
-
117
106
  // Divider - direct values with units
118
107
  const cssVariables: CSSVariables = {
119
108
  '--hscl-divider-alignment': getAlignmentCSSVar(alignment),
@@ -235,8 +224,8 @@ Variables can reference other variables for dynamic behavior:
235
224
 
236
225
  ```typescript
237
226
  const cssVariables = {
238
- '--hscl-heading-font': `var(--hscl-heading-${displayAsValue}-font)`,
239
- '--hscl-heading-fontSize': `var(--hscl-heading-${displayAsValue}-fontSize)`,
227
+ '--hscl-component-font': `var(--hscl-component-${variantValue}-font)`,
228
+ '--hscl-component-fontSize': `var(--hscl-component-${variantValue}-fontSize)`,
240
229
  };
241
230
  ```
242
231
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cms-component-library",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "HubSpot CMS React component library for building CMS modules",
5
5
  "license": "Apache-2.0",
6
6
  "exports": {
@@ -21,9 +21,8 @@
21
21
  },
22
22
  "type": "module",
23
23
  "dependencies": {
24
- "@hubspot/cms-components": "^1.2.13",
25
- "sass-embedded": "^1.90.0",
26
- "tsx": "^4.20.5"
24
+ "@hubspot/cms-components": "1.2.17",
25
+ "sass-embedded": "^1.97.3"
27
26
  },
28
27
  "peerDependencies": {
29
28
  "react": "^18.3.1"
@@ -31,6 +30,7 @@
31
30
  "devDependencies": {
32
31
  "@types/node": "^20.0.0",
33
32
  "@vitejs/plugin-react": "4.6.0",
33
+ "@hubspot/cms-dev-server": "^1.0.0",
34
34
  "typescript": "^5.0.0"
35
35
  },
36
36
  "author": "content-assets",
@@ -1,63 +0,0 @@
1
- import { ChoiceField, NumberField } from '@hubspot/cms-components/fields';
2
- import { ContentFieldsProps } from './types.js';
3
-
4
- const ContentFields = ({
5
- orientationLabel = 'Orientation',
6
- orientationName = 'orientation',
7
- orientationDefault = 'horizontal',
8
- alignmentLabel = 'Alignment',
9
- alignmentName = 'alignment',
10
- alignmentDefault = 'stretch',
11
- lengthLabel = 'Length',
12
- lengthName = 'length',
13
- lengthDefault = 100,
14
- thicknessLabel = 'Thickness',
15
- thicknessName = 'thickness',
16
- thicknessDefault = 1,
17
- }: ContentFieldsProps) => {
18
- return (
19
- <>
20
- <ChoiceField
21
- label={orientationLabel}
22
- name={orientationName}
23
- required={true}
24
- choices={[
25
- ['horizontal', 'Horizontal'],
26
- ['vertical', 'Vertical'],
27
- ]}
28
- default={orientationDefault}
29
- />
30
- <ChoiceField
31
- label={alignmentLabel}
32
- name={alignmentName}
33
- required={true}
34
- choices={[
35
- ['stretch', 'Stretch'],
36
- ['start', 'Start'],
37
- ['center', 'Center'],
38
- ['end', 'End'],
39
- ]}
40
- default={alignmentDefault}
41
- />
42
- <NumberField
43
- label={lengthLabel}
44
- name={lengthName}
45
- required={true}
46
- suffix="%"
47
- min={1}
48
- max={100}
49
- default={lengthDefault}
50
- />
51
- <NumberField
52
- label={thicknessLabel}
53
- name={thicknessName}
54
- required={true}
55
- suffix="px"
56
- min={1}
57
- default={thicknessDefault}
58
- />
59
- </>
60
- );
61
- };
62
-
63
- export default ContentFields;
@@ -1,37 +0,0 @@
1
- import { ChoiceField, TextField } from '@hubspot/cms-components/fields';
2
- import type { ContentFieldsProps } from './types.js';
3
-
4
- const ContentFields = ({
5
- headingTextLabel = 'Heading text',
6
- headingTextName = 'headingText',
7
- headingTextDefault = 'Heading Text',
8
- headingLevelLabel = 'Heading level',
9
- headingLevelName = 'headingLevel',
10
- headingLevelDefault = 'h1',
11
- }: ContentFieldsProps) => {
12
- return (
13
- <>
14
- <TextField
15
- label={headingTextLabel}
16
- name={headingTextName}
17
- default={headingTextDefault}
18
- />
19
- <ChoiceField
20
- label={headingLevelLabel}
21
- name={headingLevelName}
22
- choices={[
23
- ['h1', 'h1'],
24
- ['h2', 'h2'],
25
- ['h3', 'h3'],
26
- ['h4', 'h4'],
27
- ['h5', 'h5'],
28
- ['h6', 'h6'],
29
- ]}
30
- required={true}
31
- default={headingLevelDefault}
32
- />
33
- </>
34
- );
35
- };
36
-
37
- export default ContentFields;
@@ -1,40 +0,0 @@
1
- import { AlignmentField, ChoiceField } from '@hubspot/cms-components/fields';
2
- import type { StyleFieldsProps } from './types.js';
3
-
4
- const StyleFields = ({
5
- textAlignLabel = 'Heading alignment',
6
- textAlignName = 'headingTextAlign',
7
- textAlignDefault = 'LEFT',
8
- displayAsLabel = 'Display as',
9
- displayAsName = 'headingDisplayAs',
10
- displayAsDefault = 'h1',
11
- }: StyleFieldsProps) => {
12
- return (
13
- <>
14
- <AlignmentField
15
- label={textAlignLabel}
16
- name={textAlignName}
17
- alignmentDirection="HORIZONTAL"
18
- default={{ horizontal_align: textAlignDefault }}
19
- />
20
- <ChoiceField
21
- label={displayAsLabel}
22
- name={displayAsName}
23
- choices={[
24
- ['h1', 'h1'],
25
- ['h2', 'h2'],
26
- ['h3', 'h3'],
27
- ['h4', 'h4'],
28
- ['h5', 'h5'],
29
- ['h6', 'h6'],
30
- ['display_1', 'Display 1'],
31
- ['display_2', 'Display 2'],
32
- ]}
33
- required={true}
34
- default={displayAsDefault}
35
- />
36
- </>
37
- );
38
- };
39
-
40
- export default StyleFields;
@@ -1,11 +0,0 @@
1
- .heading {
2
- font-family: var(--hscl-heading-font);
3
- font-size: var(--hscl-heading-fontSize);
4
- font-style: var(--hscl-heading-fontStyle);
5
- font-weight: var(--hscl-heading-fontWeight);
6
- line-height: var(--hscl-heading-lineHeight);
7
- margin-block: var(--hscl-heading-margin);
8
- color: var(--hscl-heading-color);
9
- text-align: var(--hscl-heading-textAlign);
10
- }
11
-
@@ -1,52 +0,0 @@
1
- import styles from './index.module.scss';
2
- import ContentFields from './ContentFields.js';
3
- import StyleFields from './StyleFields.js';
4
- import cx from '../utils/classname.js';
5
- import type { CSSVariables } from '../utils/types.js';
6
- import { HeadingProps } from './types.js';
7
-
8
- const HeadingComponent = ({
9
- headingLevel,
10
- displayAs,
11
- textAlign,
12
- className = '',
13
- style = {},
14
- children = 'A clear and bold heading',
15
- ...rest
16
- }: HeadingProps) => {
17
- const HeadingLevel = headingLevel;
18
- const displayAsValue = displayAs || headingLevel;
19
-
20
- const cssVariables: CSSVariables = {
21
- '--hscl-heading-font': `var(--hscl-heading-${displayAsValue}-font)`,
22
- '--hscl-heading-fontSize': `var(--hscl-heading-${displayAsValue}-fontSize)`,
23
- '--hscl-heading-fontStyle': `var(--hscl-heading-${displayAsValue}-fontStyle)`,
24
- '--hscl-heading-fontWeight': `var(--hscl-heading-${displayAsValue}-fontWeight)`,
25
- ...(textAlign && {
26
- '--hscl-heading-textAlign': textAlign.toLowerCase(),
27
- }),
28
- };
29
-
30
- const defaultClasses = cx(styles.heading, className);
31
-
32
- return (
33
- <HeadingLevel
34
- className={defaultClasses}
35
- style={{ ...cssVariables, ...style }}
36
- {...rest}
37
- >
38
- {children}
39
- </HeadingLevel>
40
- );
41
- };
42
-
43
- type HeadingComponentType = typeof HeadingComponent & {
44
- ContentFields: typeof ContentFields;
45
- StyleFields: typeof StyleFields;
46
- };
47
-
48
- const Heading = HeadingComponent as HeadingComponentType;
49
- Heading.ContentFields = ContentFields;
50
- Heading.StyleFields = StyleFields;
51
-
52
- export default Heading;
@@ -1,175 +0,0 @@
1
- # Heading Component
2
-
3
- A semantic heading component that renders HTML heading elements (h1-h6) with flexible visual styling and alignment controls, allowing the semantic level to differ from the visual appearance.
4
-
5
- ## Import path
6
- ```tsx
7
- import Heading from '@hubspot/cms-component-library/Heading';
8
- ```
9
-
10
- ## Purpose
11
-
12
- The Heading component provides proper semantic structure while maintaining visual design flexibility. It solves the common challenge where semantic HTML hierarchy (h1-h6) needs to differ from visual styling - for example, an h3 element styled to look like an h1. This separation of semantic meaning from visual presentation ensures both accessibility and design consistency.
13
-
14
- ## Component Structure
15
-
16
- ```
17
- Heading/
18
- ├── index.tsx # Main component with render logic
19
- ├── types.ts # TypeScript type definitions
20
- ├── ContentFields.tsx # HubSpot field definitions for content
21
- ├── StyleFields.tsx # HubSpot field definitions for styling
22
- ├── index.module.scss # CSS module with design tokens
23
- └── stories/
24
- ├── Heading.stories.tsx # Component usage examples
25
- ├── HeadingDecorator.tsx # Storybook decorator
26
- └── HeadingDecorator.module.css # Decorator styles
27
- ```
28
-
29
- ## Props
30
-
31
- ```tsx
32
- {
33
- headingLevel: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; // Semantic HTML level (required)
34
- displayAs?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'display_1' | 'display_2'; // Visual style (defaults to headingLevel)
35
- textAlign?: 'LEFT' | 'CENTER' | 'RIGHT'; // Text alignment
36
- className?: string; // Additional CSS classes
37
- style?: React.CSSProperties; // Inline styles (including CSS variables)
38
- children?: React.ReactNode; // Heading text content
39
- }
40
- ```
41
-
42
- ## Usage Examples
43
-
44
- ### Basic Heading
45
-
46
- ```tsx
47
- import Heading from '@hubspot/cms-component-library/Heading';
48
-
49
- <Heading headingLevel="h1">
50
- Welcome to Our Site
51
- </Heading>
52
- ```
53
-
54
- ### Semantic vs Visual Styling
55
-
56
- When you need a lower-level heading to look like a higher-level one:
57
-
58
- ```tsx
59
- <Heading
60
- headingLevel="h3" // Semantic: third-level heading
61
- displayAs="h1" // Visual: styled like an h1
62
- >
63
- Section Title
64
- </Heading>
65
- ```
66
-
67
- ### With Text Alignment
68
-
69
- ```tsx
70
- <Heading
71
- headingLevel="h2"
72
- textAlign="CENTER"
73
- >
74
- Centered Heading
75
- </Heading>
76
- ```
77
-
78
-
79
- ## HubSpot CMS Integration
80
-
81
- ### Field Definitions
82
-
83
- #### ContentFields.tsx
84
-
85
- ```tsx
86
- <Heading.ContentFields
87
- headingTextLabel="Heading text"
88
- headingTextName="headingText"
89
- headingTextDefault="Heading Text"
90
- headingLevelLabel="Heading Level"
91
- headingLevelName="headingLevel"
92
- headingLevelDefault="h1"
93
- />
94
- ```
95
-
96
- **Fields:**
97
- - `headingText`: TextField for heading content
98
- - `headingLevel`: ChoiceField for semantic level (h1-h6)
99
-
100
- #### StyleFields.tsx
101
-
102
- ```tsx
103
- <Heading.StyleFields
104
- textAlignLabel="Heading text align"
105
- textAlignName="headingTextAlign"
106
- textAlignDefault="LEFT"
107
- displayAsLabel="Display as"
108
- displayAsName="headingDisplayAs"
109
- displayAsDefault="h1"
110
- />
111
- ```
112
-
113
- **Fields:**
114
- - `headingTextAlign`: AlignmentField for text alignment
115
- - `headingDisplayAs`: ChoiceField for visual style (h1-h6, display_1, display_2)
116
-
117
- ### Module Usage Example
118
-
119
- ```tsx
120
- import Heading from '@hubspot/cms-component-library/Heading';
121
-
122
- export default function HeroModule({ fieldValues }) {
123
- return (
124
- <Heading
125
- headingLevel={fieldValues.headingLevel}
126
- displayAs={fieldValues.headingDisplayAs}
127
- textAlign={fieldValues.headingTextAlign?.horizontal_align}
128
- >
129
- {fieldValues.headingText}
130
- </Heading>
131
- );
132
- }
133
- ```
134
-
135
- ## Styling
136
-
137
- ### CSS Variables
138
-
139
- The Heading component uses CSS variables for theming and customization:
140
-
141
- **Base Styles:**
142
- - `--hscl-heading-font`: Font family
143
- - `--hscl-heading-fontSize`: Font size (set by displayAs level)
144
- - `--hscl-heading-fontStyle`: Font style (set by displayAs level)
145
- - `--hscl-heading-fontWeight`: Font weight (set by displayAs level)
146
- - `--hscl-heading-lineHeight`: Line height
147
- - `--hscl-heading-margin`: Vertical margin (margin-block)
148
- - `--hscl-heading-color`: Text color
149
- - `--hscl-heading-textAlign`: Text alignment
150
-
151
- **Level-specific Variables:**
152
- Each heading level has its own design tokens:
153
- - `--hscl-heading-h1-font`, `--hscl-heading-h1-fontSize`, etc.
154
- - `--hscl-heading-h2-font`, `--hscl-heading-h2-fontSize`, etc.
155
- - Through `--hscl-heading-h6-font`, `--hscl-heading-h6-fontSize`, etc.
156
- - `--hscl-heading-display_1-font`, `--hscl-heading-display_1-fontSize`, etc.
157
- - `--hscl-heading-display_2-font`, `--hscl-heading-display_2-fontSize`, etc.
158
-
159
- ## Accessibility
160
-
161
- The Heading component follows accessibility best practices:
162
-
163
- - **Semantic HTML**: Always renders the appropriate heading element (h1-h6) based on `headingLevel` for proper document structure
164
- - **Visual Hierarchy Independence**: The `displayAs` prop allows visual styling to differ from semantic structure, ensuring flexibility without breaking accessibility
165
- - **Proper Nesting**: Ensure headings follow logical order in your document (h1 → h2 → h3, etc.) regardless of visual styling
166
- - **Screen Readers**: Screen readers announce the semantic level (`headingLevel`), not the visual style
167
- - **Keyboard Navigation**: Native heading element support for keyboard navigation and focus management
168
-
169
- ## Best Practices
170
-
171
- - **Follow semantic order**: Use headings in logical order (h1 for main title, h2 for sections, h3 for subsections, etc.)
172
- - **One h1 per page**: Each page should have exactly one h1 element representing the main topic
173
- - **Use displayAs for visual flexibility**: When you need a different visual style than the semantic level requires, use the `displayAs` prop
174
- - **Don't skip levels**: Don't jump from h2 to h4; maintain proper hierarchy
175
-