@hubspot/cms-component-library 0.1.0 → 0.2.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.
Files changed (143) hide show
  1. package/components/componentLibrary/Accordion/AccordionContent/ContentFields.tsx +5 -3
  2. package/components/componentLibrary/Accordion/AccordionItem/StyleFields.tsx +5 -3
  3. package/components/componentLibrary/Accordion/AccordionItem/index.module.scss +2 -2
  4. package/components/componentLibrary/Accordion/AccordionItem/index.tsx +3 -3
  5. package/components/componentLibrary/Accordion/AccordionTitle/ContentFields.tsx +5 -3
  6. package/components/componentLibrary/Accordion/AccordionTitle/index.module.scss +2 -2
  7. package/components/componentLibrary/Accordion/stories/Accordion.stories.tsx +80 -1
  8. package/components/componentLibrary/Accordion/stories/AccordionDecorator.tsx +14 -14
  9. package/components/componentLibrary/Button/ContentFields.tsx +5 -3
  10. package/components/componentLibrary/Button/StyleFields.tsx +5 -3
  11. package/components/componentLibrary/Button/index.module.scss +22 -14
  12. package/components/componentLibrary/Button/index.tsx +6 -6
  13. package/components/componentLibrary/Button/stories/Button.AsButton.stories.tsx +30 -1
  14. package/components/componentLibrary/Button/stories/Button.AsLink.stories.tsx +38 -1
  15. package/components/componentLibrary/Button/stories/ButtonDecorator.tsx +1 -1
  16. package/components/componentLibrary/Card/StyleFields.tsx +5 -3
  17. package/components/componentLibrary/Card/stories/Card.stories.tsx +46 -1
  18. package/components/componentLibrary/Card/stories/CardDecorator.tsx +1 -1
  19. package/components/componentLibrary/Divider/ContentFields.tsx +5 -3
  20. package/components/componentLibrary/Divider/StyleFields.tsx +5 -3
  21. package/components/componentLibrary/Divider/index.module.scss +6 -6
  22. package/components/componentLibrary/Divider/index.tsx +7 -3
  23. package/components/componentLibrary/Divider/stories/Divider.stories.tsx +44 -50
  24. package/components/componentLibrary/Divider/stories/{DividerDecorator.module.css → DividerDecorator.module.scss} +5 -4
  25. package/components/componentLibrary/Divider/stories/DividerDecorator.tsx +1 -1
  26. package/components/componentLibrary/Divider/types.ts +3 -1
  27. package/components/componentLibrary/Drawer/hooks/index.tsx +13 -0
  28. package/components/componentLibrary/Drawer/index.module.scss +94 -0
  29. package/components/componentLibrary/Drawer/index.tsx +131 -0
  30. package/components/componentLibrary/Drawer/llm.txt +416 -0
  31. package/components/componentLibrary/Drawer/stories/Drawer.stories.tsx +512 -0
  32. package/components/componentLibrary/Drawer/stories/DrawerDecorator.module.scss +8 -0
  33. package/components/componentLibrary/Drawer/stories/DrawerDecorator.tsx +18 -0
  34. package/components/componentLibrary/Drawer/types.ts +25 -0
  35. package/components/componentLibrary/Flex/stories/FlexDecorator.tsx +1 -1
  36. package/components/componentLibrary/Flex/types.ts +3 -1
  37. package/components/componentLibrary/Grid/stories/Grid.stories.tsx +454 -152
  38. package/components/componentLibrary/Grid/stories/GridDecorator.tsx +2 -2
  39. package/components/componentLibrary/Heading/ContentFields.tsx +5 -3
  40. package/components/componentLibrary/Heading/StyleFields.tsx +11 -9
  41. package/components/componentLibrary/Heading/index.tsx +3 -3
  42. package/components/componentLibrary/Heading/llm.txt +8 -8
  43. package/components/componentLibrary/Heading/stories/Heading.stories.tsx +3 -3
  44. package/components/componentLibrary/Heading/stories/HeadingDecorator.tsx +1 -1
  45. package/components/componentLibrary/Heading/types.ts +4 -4
  46. package/components/componentLibrary/Icon/ContentFields.tsx +5 -3
  47. package/components/componentLibrary/Icon/stories/Icon.stories.tsx +1 -1
  48. package/components/componentLibrary/Icon/stories/IconDecorator.tsx +1 -1
  49. package/components/componentLibrary/Image/ContentFields.tsx +5 -3
  50. package/components/componentLibrary/Image/index.tsx +4 -4
  51. package/components/componentLibrary/Image/llm.txt +17 -17
  52. package/components/componentLibrary/Image/stories/Image.stories.tsx +61 -18
  53. package/components/componentLibrary/Image/stories/ImageDecorator.tsx +1 -1
  54. package/components/componentLibrary/Image/types.ts +2 -2
  55. package/components/componentLibrary/LanguageSwitcher/ContentFields.tsx +18 -0
  56. package/components/componentLibrary/LanguageSwitcher/LanguageOptions.module.scss +37 -0
  57. package/components/componentLibrary/LanguageSwitcher/LanguageOptions.tsx +65 -0
  58. package/components/componentLibrary/LanguageSwitcher/StyleFields.tsx +48 -0
  59. package/components/componentLibrary/LanguageSwitcher/_dummyData.tsx +247 -0
  60. package/components/componentLibrary/LanguageSwitcher/assets/Globe.tsx +16 -0
  61. package/components/componentLibrary/LanguageSwitcher/index.module.scss +58 -0
  62. package/components/componentLibrary/LanguageSwitcher/index.tsx +125 -0
  63. package/components/componentLibrary/LanguageSwitcher/llm.txt +380 -0
  64. package/components/componentLibrary/LanguageSwitcher/stories/LanguageSwitcher.stories.tsx +349 -0
  65. package/components/componentLibrary/LanguageSwitcher/stories/LanguageSwitcherDecorator.module.scss +5 -0
  66. package/components/componentLibrary/LanguageSwitcher/stories/LanguageSwitcherDecorator.tsx +8 -0
  67. package/components/componentLibrary/LanguageSwitcher/types.ts +48 -0
  68. package/components/componentLibrary/LanguageSwitcher/utils.tsx +38 -0
  69. package/components/componentLibrary/Link/ContentFields.tsx +5 -3
  70. package/components/componentLibrary/Link/StyleFields.tsx +5 -3
  71. package/components/componentLibrary/Link/index.module.scss +10 -0
  72. package/components/componentLibrary/Link/index.tsx +24 -14
  73. package/components/componentLibrary/Link/stories/Link.stories.tsx +35 -5
  74. package/components/componentLibrary/Link/stories/LinkDecorator.tsx +11 -1
  75. package/components/componentLibrary/Link/types.ts +22 -13
  76. package/components/componentLibrary/List/ContentFields.tsx +5 -3
  77. package/components/componentLibrary/List/ListItem/ContentFields.tsx +6 -17
  78. package/components/componentLibrary/List/ListItem/index.module.scss +1 -13
  79. package/components/componentLibrary/List/ListItem/index.tsx +3 -30
  80. package/components/componentLibrary/List/ListItem/types.ts +1 -16
  81. package/components/componentLibrary/List/StyleFields.tsx +15 -18
  82. package/components/componentLibrary/List/index.module.scss +3 -0
  83. package/components/componentLibrary/List/index.tsx +5 -2
  84. package/components/componentLibrary/List/llm.txt +73 -103
  85. package/components/componentLibrary/List/stories/List.stories.tsx +56 -80
  86. package/components/componentLibrary/List/stories/ListDecorator.tsx +3 -6
  87. package/components/componentLibrary/List/types.ts +1 -3
  88. package/components/componentLibrary/Logo/_dummyLogoData.ts +12 -0
  89. package/components/componentLibrary/Logo/assets/hubspot-logo.png +0 -0
  90. package/components/componentLibrary/Logo/index.module.scss +22 -0
  91. package/components/componentLibrary/Logo/index.tsx +73 -0
  92. package/components/componentLibrary/Logo/llm.txt +262 -0
  93. package/components/componentLibrary/Logo/stories/Logo.stories.tsx +88 -0
  94. package/components/componentLibrary/Logo/stories/LogoDecorator.module.scss +10 -0
  95. package/components/componentLibrary/Logo/stories/LogoDecorator.tsx +8 -0
  96. package/components/componentLibrary/Logo/types.tsx +16 -0
  97. package/components/componentLibrary/Menu/ContentFields.tsx +16 -0
  98. package/components/componentLibrary/Menu/MenuItem/Chevron/index.module.scss +6 -0
  99. package/components/componentLibrary/Menu/MenuItem/Chevron/index.tsx +17 -0
  100. package/components/componentLibrary/Menu/MenuItem/index.module.scss +7 -0
  101. package/components/componentLibrary/Menu/MenuItem/index.tsx +266 -0
  102. package/components/componentLibrary/Menu/MenuItem/types.ts +17 -0
  103. package/components/componentLibrary/Menu/NavigationMenu/ContentFields.tsx +20 -0
  104. package/components/componentLibrary/Menu/NavigationMenu/index.tsx +18 -0
  105. package/components/componentLibrary/Menu/NavigationMenu/islands/NavigationMenuIsland.tsx +95 -0
  106. package/components/componentLibrary/Menu/NavigationMenu/islands/index.module.scss +100 -0
  107. package/components/componentLibrary/Menu/NavigationMenu/islands/types.ts +19 -0
  108. package/components/componentLibrary/Menu/NavigationMenu/llm.txt +197 -0
  109. package/components/componentLibrary/Menu/NavigationMenu/stories/NavigationMenu.stories.tsx +286 -0
  110. package/components/componentLibrary/Menu/NavigationMenu/stories/NavigationMenuDecorator.module.scss +15 -0
  111. package/components/componentLibrary/Menu/NavigationMenu/stories/NavigationMenuDecorator.tsx +12 -0
  112. package/components/componentLibrary/Menu/NavigationMenu/types.ts +3 -0
  113. package/components/componentLibrary/Menu/VerticalMenu/ContentFields.tsx +20 -0
  114. package/components/componentLibrary/Menu/VerticalMenu/index.tsx +18 -0
  115. package/components/componentLibrary/Menu/VerticalMenu/islands/index.module.scss +53 -0
  116. package/components/componentLibrary/Menu/VerticalMenu/islands/verticalMenuIsland.tsx +78 -0
  117. package/components/componentLibrary/Menu/VerticalMenu/llm.txt +177 -0
  118. package/components/componentLibrary/Menu/VerticalMenu/stories/VerticalMenu.stories.tsx +242 -0
  119. package/components/componentLibrary/Menu/VerticalMenu/stories/VerticalMenuDecorator.module.scss +19 -0
  120. package/components/componentLibrary/Menu/VerticalMenu/stories/VerticalMenuDecorator.tsx +12 -0
  121. package/components/componentLibrary/Menu/VerticalMenu/types.ts +21 -0
  122. package/components/componentLibrary/Menu/_dummyMenuData.js +1346 -0
  123. package/components/componentLibrary/Menu/types.ts +56 -0
  124. package/components/componentLibrary/Menu/utils/transformMenuData.ts +11 -0
  125. package/components/componentLibrary/_patterns/README.md +15 -17
  126. package/components/componentLibrary/_patterns/checklist-and-examples.md +17 -17
  127. package/components/componentLibrary/_patterns/component-structure.md +21 -23
  128. package/components/componentLibrary/_patterns/css-patterns.md +170 -18
  129. package/components/componentLibrary/_patterns/field-patterns.md +97 -27
  130. package/components/componentLibrary/_patterns/function-declaration-patterns.md +281 -0
  131. package/components/componentLibrary/_patterns/llm-txt.template.md +4 -2
  132. package/components/componentLibrary/_patterns/prop-naming-patterns.md +208 -0
  133. package/components/componentLibrary/_patterns/storybook-patterns.md +25 -8
  134. package/components/componentLibrary/_patterns/typescript-patterns.md +6 -3
  135. package/package.json +4 -2
  136. /package/components/componentLibrary/Button/stories/{ButtonDecorator.module.css → ButtonDecorator.module.scss} +0 -0
  137. /package/components/componentLibrary/Card/stories/{CardDecorator.module.css → CardDecorator.module.scss} +0 -0
  138. /package/components/componentLibrary/Flex/stories/{FlexDecorator.module.css → FlexDecorator.module.scss} +0 -0
  139. /package/components/componentLibrary/Grid/stories/{GridDecorator.module.css → GridDecorator.module.scss} +0 -0
  140. /package/components/componentLibrary/Heading/stories/{HeadingDecorator.module.css → HeadingDecorator.module.scss} +0 -0
  141. /package/components/componentLibrary/Icon/stories/{IconDecorator.module.css → IconDecorator.module.scss} +0 -0
  142. /package/components/componentLibrary/Image/stories/{ImageDecorator.module.css → ImageDecorator.module.scss} +0 -0
  143. /package/components/componentLibrary/Image/stories/assets/{catSmile.jpg → cat-smile.jpg} +0 -0
@@ -1,26 +1,35 @@
1
1
  import { LinkFieldDefaults } from '@hubspot/cms-components/fields';
2
2
  import { LinkFieldValue } from '../utils/linkField.js';
3
3
 
4
- type BaseLinkProps = {
4
+ export type BaseLinkProps = {
5
5
  variant?: 'primary' | 'secondary' | 'tertiary';
6
6
  className?: string;
7
7
  style?: React.CSSProperties;
8
8
  children?: React.ReactNode;
9
9
  };
10
10
 
11
- type LinkWithField = BaseLinkProps & {
12
- linkField: LinkFieldValue;
13
- href?: never;
14
- target?: never;
15
- rel?: never;
16
- };
11
+ // added this so that TS doesn't get mad about duplicate properties
12
+ // since we want to enforce required props in some of these type definitions
13
+ export type LinkHTMLProps = Omit<
14
+ React.AnchorHTMLAttributes<HTMLAnchorElement>,
15
+ 'href' | 'target' | 'rel' | 'className' | 'style' | 'children'
16
+ >;
17
17
 
18
- type LinkWithoutField = BaseLinkProps & {
19
- linkField?: never;
20
- href: string;
21
- target?: '_self' | '_blank' | '_parent' | '_top';
22
- rel?: string;
23
- };
18
+ type LinkWithField = BaseLinkProps &
19
+ LinkHTMLProps & {
20
+ linkField: LinkFieldValue;
21
+ href?: never;
22
+ target?: never;
23
+ rel?: never;
24
+ };
25
+
26
+ type LinkWithoutField = BaseLinkProps &
27
+ LinkHTMLProps & {
28
+ linkField?: never;
29
+ href: string;
30
+ target?: '_self' | '_blank' | '_parent' | '_top';
31
+ rel?: string;
32
+ };
24
33
 
25
34
  export type LinkProps = LinkWithField | LinkWithoutField;
26
35
 
@@ -1,11 +1,11 @@
1
1
  import { ChoiceField } from '@hubspot/cms-components/fields';
2
2
  import type { ContentFieldsProps } from './types.js';
3
3
 
4
- export default function ContentFields({
4
+ const ContentFields = ({
5
5
  listTypeName = 'listType',
6
6
  listTypeLabel = 'List type',
7
7
  listTypeDefault = 'unordered',
8
- }: ContentFieldsProps) {
8
+ }: ContentFieldsProps) => {
9
9
  return (
10
10
  <ChoiceField
11
11
  label={listTypeLabel}
@@ -17,4 +17,6 @@ export default function ContentFields({
17
17
  ]}
18
18
  />
19
19
  );
20
- }
20
+ };
21
+
22
+ export default ContentFields;
@@ -1,23 +1,12 @@
1
1
  import { TextField } from '@hubspot/cms-components/fields';
2
2
  import type { ContentFieldsProps } from './types.js';
3
- import Icon from '../../Icon/index.js';
4
3
 
5
- export default function ContentFields({
4
+ const ContentFields = ({
6
5
  textName = 'text',
7
6
  textLabel = 'Item text',
8
7
  textDefault = 'Add a list item here.',
9
- iconName = 'icon',
10
- iconLabel = 'Icon',
11
- iconDefault = { name: 'check', unicode: 'f00c', type: 'SOLID' },
12
- }: ContentFieldsProps) {
13
- return (
14
- <>
15
- <TextField label={textLabel} name={textName} default={textDefault} />
16
- <Icon.ContentFields
17
- iconName={iconName}
18
- iconLabel={iconLabel}
19
- iconDefault={iconDefault}
20
- />
21
- </>
22
- );
23
- }
8
+ }: ContentFieldsProps) => {
9
+ return <TextField label={textLabel} name={textName} default={textDefault} />;
10
+ };
11
+
12
+ export default ContentFields;
@@ -1,16 +1,4 @@
1
1
  .listItem {
2
- display: flex;
3
- align-items: flex-start;
4
- column-gap: 8px;
5
- color: var(--hscl-list-item-text-color);
6
- }
7
-
8
- .listItemContent {
9
- flex: 1;
10
- }
11
-
12
- .listItemDefault {
13
- display: list-item;
14
- color: var(--hscl-list-item-text-color);
2
+ color: var(--hscl-list-item-color);
15
3
  }
16
4
 
@@ -2,45 +2,18 @@ import styles from './index.module.scss';
2
2
  import ContentFields from './ContentFields.js';
3
3
  import cx from '../../utils/classname.js';
4
4
  import { ListItemProps } from './types.js';
5
- import Icon from '../../Icon/index.js';
6
5
 
7
6
  const ListItemComponent = ({
8
- children = <span>Default list item text</span>,
9
- index,
10
- itemsFieldPath,
11
- iconName = 'icon',
12
- iconSize = 16,
13
- iconFill,
14
- showIcon = true,
15
- iconPurpose = 'DECORATIVE',
16
- iconTitle,
7
+ children,
17
8
  className = '',
18
9
  style = {},
19
10
  ...rest
20
11
  }: ListItemProps) => {
21
- const itemClass = showIcon ? cx(styles.listItem) : cx(styles.listItemDefault);
22
- const combinedClasses = cx(itemClass, className);
23
-
24
- const iconFieldPath =
25
- itemsFieldPath && index !== undefined
26
- ? `${itemsFieldPath}[${index}].${iconName}`
27
- : undefined;
12
+ const combinedClasses = cx(styles.listItem, className);
28
13
 
29
14
  return (
30
15
  <li className={combinedClasses} style={style} {...rest}>
31
- {showIcon && iconFieldPath && (
32
- <div>
33
- <Icon
34
- fieldPath={iconFieldPath}
35
- height={iconSize}
36
- fill={iconFill}
37
- showIcon={showIcon}
38
- purpose={iconPurpose}
39
- title={iconTitle}
40
- />
41
- </div>
42
- )}
43
- <span className={styles.listItemContent}>{children}</span>
16
+ {children}
44
17
  </li>
45
18
  );
46
19
  };
@@ -1,19 +1,7 @@
1
- import {
2
- TextFieldDefaults,
3
- IconFieldDefaults,
4
- } from '@hubspot/cms-components/fields';
5
- import type { IconPurpose } from '../../Icon/types.js';
1
+ import { TextFieldDefaults } from '@hubspot/cms-components/fields';
6
2
 
7
3
  export type ListItemProps = {
8
4
  children?: React.ReactNode;
9
- index?: number;
10
- itemsFieldPath?: string;
11
- iconName?: string;
12
- iconSize?: number;
13
- iconFill?: string;
14
- showIcon?: boolean;
15
- iconPurpose?: IconPurpose;
16
- iconTitle?: string;
17
5
  className?: string;
18
6
  style?: React.CSSProperties;
19
7
  };
@@ -22,7 +10,4 @@ export type ContentFieldsProps = {
22
10
  textName?: string;
23
11
  textLabel?: string;
24
12
  textDefault?: typeof TextFieldDefaults;
25
- iconName?: string;
26
- iconLabel?: string;
27
- iconDefault?: typeof IconFieldDefaults;
28
13
  };
@@ -1,26 +1,23 @@
1
1
  import { ChoiceField } from '@hubspot/cms-components/fields';
2
2
  import type { StyleFieldsProps } from './types.js';
3
3
 
4
- export default function StyleFields({
4
+ const StyleFields = ({
5
5
  variantName = 'variant',
6
6
  variantLabel = 'Variant',
7
7
  variantDefault = 'primary',
8
- gapName = 'gap',
9
- gapLabel = 'Gap',
10
- gapDefault = '0px',
11
- }: StyleFieldsProps) {
8
+ }: StyleFieldsProps) => {
12
9
  return (
13
- <>
14
- <ChoiceField
15
- label={variantLabel}
16
- name={variantName}
17
- default={variantDefault}
18
- choices={[
19
- ['primary', 'Primary'],
20
- ['secondary', 'Secondary'],
21
- ['tertiary', 'Tertiary'],
22
- ]}
23
- />
24
- </>
10
+ <ChoiceField
11
+ label={variantLabel}
12
+ name={variantName}
13
+ default={variantDefault}
14
+ choices={[
15
+ ['primary', 'Primary'],
16
+ ['secondary', 'Secondary'],
17
+ ['tertiary', 'Tertiary'],
18
+ ]}
19
+ />
25
20
  );
26
- }
21
+ };
22
+
23
+ export default StyleFields;
@@ -9,3 +9,6 @@
9
9
  }
10
10
  }
11
11
 
12
+ .noMarker {
13
+ list-style: none;
14
+ }
@@ -11,18 +11,21 @@ const ListComponent = ({
11
11
  listType = 'unordered',
12
12
  variant = 'primary',
13
13
  gap = '0px',
14
+ showMarker = true,
14
15
  className = '',
15
16
  style = {},
16
17
  children,
17
18
  ...rest
18
19
  }: ListProps) => {
19
20
  const ListTag = listType === 'ordered' ? 'ol' : 'ul';
20
- const defaultClasses = cx(styles.list);
21
+ const defaultClasses = cx(styles.list, {
22
+ [styles.noMarker]: !showMarker,
23
+ });
21
24
  const combinedClasses = cx(defaultClasses, className);
22
25
 
23
26
  // !todo: placeholder values until we work out how variant system works.
24
27
  const cssVariables: CSSVariables = {
25
- '--hscl-list-item-text-color': `var(--hscl-listItem-textColor-${variant})`,
28
+ '--hscl-list-item-color': `var(--hscl-listItem-color-${variant})`,
26
29
  };
27
30
 
28
31
  return (
@@ -1,6 +1,6 @@
1
1
  # List Component
2
2
 
3
- A flexible list component that renders ordered (`<ol>`) or unordered (`<ul>`) lists with customizable spacing, variants, and optional icons for list items.
3
+ A flexible list component that renders ordered (`<ol>`) or unordered (`<ul>`) lists with customizable spacing, variants, and marker visibility.
4
4
 
5
5
  ## Import path
6
6
  ```tsx
@@ -9,7 +9,7 @@ import List, { ListItem } from '@hubspot/cms-component-library/List';
9
9
 
10
10
  ## Purpose
11
11
 
12
- The List component provides a consistent way to render lists in HubSpot CMS projects. It combines the semantic correctness of native HTML list elements with the flexibility of the Flex component for layout control. The component supports both ordered (numbered) and unordered (bulleted) lists, with an accompanying ListItem component that can display text with optional icons.
12
+ The List component provides a consistent way to render lists in HubSpot CMS projects. It combines the semantic correctness of native HTML list elements with the flexibility of the Flex component for layout control. The component supports both ordered (numbered) and unordered (bulleted) lists, with configurable marker visibility.
13
13
 
14
14
  ## Compositional Component Pattern
15
15
 
@@ -21,15 +21,15 @@ The List component follows a **parent/child compositional pattern**, consisting
21
21
  | `ListItem` | Child | `<li>` |
22
22
 
23
23
  **Why this pattern?**
24
- - **Separation of concerns**: List handles container semantics (ordered vs unordered, gap, variant), while ListItem handles individual item presentation (text, icons)
25
- - **Flexibility**: ListItem can be extended or customized independently
24
+ - **Separation of concerns**: List handles container semantics (ordered vs unordered, gap, variant, marker visibility), while ListItem handles individual item presentation
25
+ - **Flexibility**: Modules can pass any content as children to ListItem, including custom icons
26
26
  - **HubSpot CMS integration**: Each component has its own field definitions, allowing RepeatedGroup usage for dynamic lists
27
27
  - **Type safety**: Props are scoped to their respective components, preventing invalid configurations
28
28
 
29
29
  **Key relationships:**
30
30
  - ListItem should **always** be used inside a List component
31
- - List passes layout context (gap, variant styling) to children via CSS
32
- - ListItem handles its own icon resolution via `itemsFieldPath` and `index` props
31
+ - List passes layout context (gap, variant styling, marker visibility) to children via CSS
32
+ - ListItem renders children directly in the `<li>` element
33
33
 
34
34
  This pattern is distinct from the "Compound Component Pattern" (e.g., `Button.ContentFields`) which attaches field definitions—List uses *both* patterns together.
35
35
 
@@ -40,12 +40,12 @@ List/
40
40
  ├── index.tsx # Main List component with render logic
41
41
  ├── types.ts # TypeScript type definitions
42
42
  ├── ContentFields.tsx # HubSpot field definitions for list type
43
- ├── StyleFields.tsx # HubSpot field definitions for variant
43
+ ├── StyleFields.tsx # HubSpot field definitions for variant and marker
44
44
  ├── index.module.scss # CSS module for list styling
45
45
  ├── ListItem/
46
46
  │ ├── index.tsx # ListItem component
47
47
  │ ├── types.ts # ListItem TypeScript types
48
- │ ├── ContentFields.tsx # HubSpot field definitions for list items
48
+ │ ├── ContentFields.tsx # HubSpot field definitions for list item text
49
49
  │ └── index.module.scss # CSS module for list item styling
50
50
  └── stories/
51
51
  ├── List.stories.tsx # Storybook examples
@@ -65,6 +65,7 @@ List/
65
65
  listType?: 'ordered' | 'unordered'; // List type - 'ordered' renders <ol>, 'unordered' renders <ul>
66
66
  variant?: 'primary' | 'secondary' | 'tertiary'; // Visual style variant
67
67
  gap?: string; // Space between list items (any valid CSS length value, e.g., '16px', '1rem', '0')
68
+ showMarker?: boolean; // Show list markers (bullets/numbers) - default: true
68
69
  className?: string; // Additional CSS classes
69
70
  style?: CSSVariables; // Inline styles (including CSS custom properties)
70
71
  children?: React.ReactNode; // ListItem components
@@ -73,20 +74,12 @@ List/
73
74
 
74
75
  ### ListItem (Child Component)
75
76
 
76
- **Purpose:** Individual list item component that renders an `<li>` element with optional icon support (falls back to regular bullets or numbers when icons are disabled).
77
+ **Purpose:** Individual list item component that renders an `<li>` element. Children are rendered directly inside the `<li>`.
77
78
 
78
79
  **Props:**
79
80
  ```tsx
80
81
  {
81
- children?: React.ReactNode; // List item content (text, elements, etc.)
82
- index?: number; // Item index (for field path generation)
83
- itemsFieldPath?: string; // Parent field path for icon lookup
84
- iconName?: string; // Field name for icon (default: 'icon')
85
- iconSize?: number; // Icon size in pixels (default: 16)
86
- iconFill?: string; // Icon fill color
87
- showIcon?: boolean; // Toggle icon visibility (default: true)
88
- iconPurpose?: 'SEMANTIC' | 'DECORATIVE'; // Icon accessibility role (defaults to 'DECORATIVE')
89
- iconTitle?: string; // Icon title for screen readers
82
+ children?: React.ReactNode; // List item content (text, elements, icons, etc.)
90
83
  className?: string; // Additional CSS classes
91
84
  style?: React.CSSProperties; // Inline styles
92
85
  }
@@ -100,9 +93,9 @@ List/
100
93
  import List, { ListItem } from '@hubspot/cms-component-library/List';
101
94
 
102
95
  <List listType="unordered" variant="primary">
103
- <ListItem showIcon={false}>First item</ListItem>
104
- <ListItem showIcon={false}>Second item</ListItem>
105
- <ListItem showIcon={false}>Third item</ListItem>
96
+ <ListItem>First item</ListItem>
97
+ <ListItem>Second item</ListItem>
98
+ <ListItem>Third item</ListItem>
106
99
  </List>
107
100
  ```
108
101
 
@@ -112,9 +105,21 @@ import List, { ListItem } from '@hubspot/cms-component-library/List';
112
105
  import List, { ListItem } from '@hubspot/cms-component-library/List';
113
106
 
114
107
  <List listType="ordered" variant="primary">
115
- <ListItem showIcon={false}>Step one</ListItem>
116
- <ListItem showIcon={false}>Step two</ListItem>
117
- <ListItem showIcon={false}>Step three</ListItem>
108
+ <ListItem>Step one</ListItem>
109
+ <ListItem>Step two</ListItem>
110
+ <ListItem>Step three</ListItem>
111
+ </List>
112
+ ```
113
+
114
+ ### List without Markers
115
+
116
+ ```tsx
117
+ import List, { ListItem } from '@hubspot/cms-component-library/List';
118
+
119
+ <List listType="unordered" variant="primary" showMarker={false}>
120
+ <ListItem>Item without bullet</ListItem>
121
+ <ListItem>Another item without bullet</ListItem>
122
+ <ListItem>Third item without bullet</ListItem>
118
123
  </List>
119
124
  ```
120
125
 
@@ -124,37 +129,28 @@ import List, { ListItem } from '@hubspot/cms-component-library/List';
124
129
  import List, { ListItem } from '@hubspot/cms-component-library/List';
125
130
 
126
131
  <List listType="unordered" variant="primary" gap="1rem">
127
- <ListItem showIcon={false}>Spaced item one</ListItem>
128
- <ListItem showIcon={false}>Spaced item two</ListItem>
129
- <ListItem showIcon={false}>Spaced item three</ListItem>
132
+ <ListItem>Spaced item one</ListItem>
133
+ <ListItem>Spaced item two</ListItem>
134
+ <ListItem>Spaced item three</ListItem>
130
135
  </List>
131
136
  ```
132
137
 
133
- ### List Items with Icons
138
+ ### List Items with Custom Content (Icons)
139
+
140
+ When you need icons or custom content in list items, set `showMarker={false}` to hide bullets/numbers, then handle your own layout:
134
141
 
135
142
  ```tsx
136
143
  import List, { ListItem } from '@hubspot/cms-component-library/List';
144
+ import Icon from '@hubspot/cms-component-library/Icon';
137
145
 
138
- <List listType="unordered" variant="primary">
139
- <ListItem
140
- showIcon={true}
141
- iconName="icon"
142
- iconSize={20}
143
- itemsFieldPath="items"
144
- index={0}
145
- iconPurpose="DECORATIVE"
146
- >
147
- Item with icon
146
+ <List listType="unordered" variant="primary" showMarker={false} gap="0.5rem">
147
+ <ListItem style={{ display: 'flex', gap: '8px', alignItems: 'flex-start' }}>
148
+ <Icon name="check" size={16} />
149
+ <span>Item with custom icon</span>
148
150
  </ListItem>
149
- <ListItem
150
- showIcon={true}
151
- iconName="icon"
152
- iconSize={20}
153
- itemsFieldPath="items"
154
- index={1}
155
- iconPurpose="DECORATIVE"
156
- >
157
- Another item with icon
151
+ <ListItem style={{ display: 'flex', gap: '8px', alignItems: 'flex-start' }}>
152
+ <Icon name="check" size={16} />
153
+ <span>Another item with icon</span>
158
154
  </ListItem>
159
155
  </List>
160
156
  ```
@@ -171,7 +167,7 @@ import List, { ListItem } from '@hubspot/cms-component-library/List';
171
167
  className="custom-list-class"
172
168
  style={{ maxWidth: '500px' }}
173
169
  >
174
- <ListItem showIcon={false}>Custom styled item</ListItem>
170
+ <ListItem>Custom styled item</ListItem>
175
171
  </List>
176
172
  ```
177
173
 
@@ -198,18 +194,22 @@ Configurable props for list type selection:
198
194
 
199
195
  #### List.StyleFields
200
196
 
201
- Configurable props for variant selection:
197
+ Configurable props for variant and marker selection:
202
198
 
203
199
  ```tsx
204
200
  <List.StyleFields
205
201
  variantName="variant"
206
202
  variantLabel="Variant"
207
203
  variantDefault="primary"
204
+ showMarkerName="showMarker"
205
+ showMarkerLabel="Show list markers"
206
+ showMarkerDefault={true}
208
207
  />
209
208
  ```
210
209
 
211
210
  **Fields:**
212
211
  - `variant`: ChoiceField for selecting visual style (primary, secondary, tertiary)
212
+ - `showMarker`: BooleanField for toggling marker visibility
213
213
 
214
214
  **Note:** Gap must be set directly via the `gap` prop on the List component, as there is no field definition for it in StyleFields.
215
215
 
@@ -222,15 +222,11 @@ Configurable props for list item content:
222
222
  textName="text"
223
223
  textLabel="Item text"
224
224
  textDefault="Add a list item here."
225
- iconName="icon"
226
- iconLabel="Icon"
227
- iconDefault={{ name: 'check', unicode: 'f00c', type: 'SOLID' }} // FontAwesome icon set
228
225
  />
229
226
  ```
230
227
 
231
228
  **Fields:**
232
229
  - `text`: TextField for list item text content
233
- - `icon`: Icon field using Icon.ContentFields
234
230
 
235
231
  ### Module Usage Example
236
232
 
@@ -244,6 +240,7 @@ type FeatureListModuleProps = {
244
240
  style?: {
245
241
  variant?: 'primary' | 'secondary' | 'tertiary';
246
242
  gap?: GapValue;
243
+ showMarker?: boolean;
247
244
  };
248
245
  listItems?: Array<{
249
246
  text?: string;
@@ -257,22 +254,17 @@ export const Component = ({
257
254
  }: FeatureListModuleProps) => {
258
255
  const variant = style?.variant ?? 'primary';
259
256
  const gap = style?.gap ?? '0px';
257
+ const showMarker = style?.showMarker ?? true;
260
258
 
261
259
  return (
262
260
  <List
263
261
  listType={listType}
264
262
  variant={variant}
265
263
  gap={gap}
264
+ showMarker={showMarker}
266
265
  >
267
266
  {listItems.map(({ text }, index) => (
268
- <ListItem
269
- key={index}
270
- index={index}
271
- itemsFieldPath="listItems"
272
- iconFill={`var(--hscl-listItem-iconColor-${variant})`}
273
- >
274
- {text}
275
- </ListItem>
267
+ <ListItem key={index}>{text}</ListItem>
276
268
  ))}
277
269
  </List>
278
270
  );
@@ -299,7 +291,6 @@ import List, { ListItem } from '@hubspot/cms-component-library/List';
299
291
 
300
292
  const defaultItem = {
301
293
  text: 'Add a list item here.',
302
- icon: { name: 'check', unicode: 'f00c', type: 'SOLID' }, // FontAwesome icon set
303
294
  };
304
295
 
305
296
  export const fields = (
@@ -342,11 +333,6 @@ The List component uses CSS variables for theming and customization:
342
333
  - `--hscl-listItem-textColor-secondary`: Secondary variant text color
343
334
  - `--hscl-listItem-textColor-tertiary`: Tertiary variant text color
344
335
 
345
- **List Item Icon:**
346
- - `--hscl-listItem-iconColor-primary`: Primary variant icon color
347
- - `--hscl-listItem-iconColor-secondary`: Secondary variant icon color
348
- - `--hscl-listItem-iconColor-tertiary`: Tertiary variant icon color
349
-
350
336
  ### Custom Styling Example
351
337
 
352
338
  ```tsx
@@ -359,7 +345,7 @@ import List, { ListItem } from '@hubspot/cms-component-library/List';
359
345
  '--hscl-list-item-text-color': '#333333',
360
346
  }}
361
347
  >
362
- <ListItem showIcon={false}>Custom colored item</ListItem>
348
+ <ListItem>Custom colored item</ListItem>
363
349
  </List>
364
350
  ```
365
351
 
@@ -367,12 +353,12 @@ import List, { ListItem } from '@hubspot/cms-component-library/List';
367
353
 
368
354
  **List (`index.module.scss`):**
369
355
  - `.list`: Base list styles (removes default padding/margin, positions bullets inside)
356
+ - `.withMarker`: Applies `display: list-item` to children (shows bullets/numbers)
357
+ - `.noMarker`: Applies `list-style: none` (hides markers—modules handle their own internal layout)
370
358
  - Nested `.list`: Indented styling for nested lists
371
359
 
372
360
  **ListItem (`ListItem/index.module.scss`):**
373
- - `.listItem`: Flex display for items with icons
374
- - `.listItemDefault`: Standard list-item display for items without icons
375
- - `.listItemContent`: Flex content wrapper
361
+ - `.listItem`: Base list item styles with text color
376
362
 
377
363
  ## Accessibility
378
364
 
@@ -380,45 +366,36 @@ The List component follows accessibility best practices:
380
366
 
381
367
  - **Semantic HTML**: Renders appropriate elements (`<ol>` for ordered, `<ul>` for unordered)
382
368
  - **List Semantics**: Proper `<li>` elements maintain screen reader list navigation
383
- - **Icon Accessibility**:
384
- - `iconPurpose="SEMANTIC"`: Icon conveys meaning (includes accessible title)
385
- - `iconPurpose="DECORATIVE"`: Icon is visual only (aria-hidden)
386
- - `iconTitle` provides screen reader description for semantic icons
387
369
  - **Keyboard Navigation**: Native list keyboard navigation is preserved
388
370
  - **Content Structure**: Lists help screen reader users understand grouped content
389
371
 
390
372
  ## Best Practices
391
373
 
392
374
  - **Choose the right list type**: Use `ordered` for sequential steps or rankings, `unordered` for non-sequential items
393
- - **Icon field paths**: When using icons in dynamic lists, always provide `itemsFieldPath` and `index` to correctly resolve icon field paths
394
- - **showIcon prop**: Set `showIcon={false}` to use default bullet/number styling, `showIcon={true}` for custom icons
375
+ - **Marker visibility**: Use `showMarker={true}` (default) for standard lists, `showMarker={false}` when providing custom markers or icons as children
395
376
  - **Consistent variants**: Use the same variant across related lists for visual consistency
396
377
  - **Gap selection**: Use any valid CSS length value (e.g., '0', '0.5rem', '1rem', '16px') for spacing between items
397
378
  - **Dynamic rendering**: Always provide unique `key` props when mapping arrays to ListItems
398
379
  - **CSS Variables**: Override design tokens using CSS variables rather than hardcoding values
399
- - **Icon colors**: Use `iconFill` prop with variant-based CSS variables for consistent theming (e.g., `iconFill={`var(--hscl-listItem-iconColor-${variant})`}`)
380
+ - **Custom icons**: When using custom icons, set `showMarker={false}` and pass icons as part of ListItem children
381
+ - **Custom content layout**: When using `showMarker={false}`, markers are hidden but no layout is imposed. Modules are responsible for their own internal layout—use `style={{ display: 'flex', gap: '8px', alignItems: 'flex-start' }}` on ListItem or wrap content in a styled container
400
382
 
401
383
  ## Common Patterns
402
384
 
403
- ### Feature List with Icons
385
+ ### Feature List with Custom Icons
404
386
 
405
387
  ```tsx
406
388
  import List, { ListItem } from '@hubspot/cms-component-library/List';
389
+ import Icon from '@hubspot/cms-component-library/Icon';
390
+
391
+ const itemStyle = { display: 'flex', gap: '8px', alignItems: 'flex-start' };
407
392
 
408
393
  const FeatureList = ({ features, variant = 'primary' }) => (
409
- <List listType="unordered" variant={variant} gap="0.5rem">
394
+ <List listType="unordered" variant={variant} showMarker={false} gap="0.5rem">
410
395
  {features.map((feature, index) => (
411
- <ListItem
412
- key={index}
413
- showIcon={true}
414
- iconName="icon"
415
- iconSize={20}
416
- itemsFieldPath="features"
417
- index={index}
418
- iconPurpose="DECORATIVE"
419
- iconFill={`var(--hscl-listItem-iconColor-${variant})`}
420
- >
421
- {feature.text}
396
+ <ListItem key={index} style={itemStyle}>
397
+ <Icon name="check" size={20} fill={`var(--hscl-listItem-iconColor-${variant})`} />
398
+ <span>{feature.text}</span>
422
399
  </ListItem>
423
400
  ))}
424
401
  </List>
@@ -433,14 +410,7 @@ import List, { ListItem } from '@hubspot/cms-component-library/List';
433
410
  const StepList = ({ steps, variant = 'primary' }) => (
434
411
  <List listType="ordered" variant={variant} gap="1rem">
435
412
  {steps.map((step, index) => (
436
- <ListItem
437
- key={index}
438
- showIcon={false}
439
- index={index}
440
- itemsFieldPath="steps"
441
- >
442
- {step.text}
443
- </ListItem>
413
+ <ListItem key={index}>{step.text}</ListItem>
444
414
  ))}
445
415
  </List>
446
416
  );
@@ -452,13 +422,13 @@ const StepList = ({ steps, variant = 'primary' }) => (
452
422
  import List, { ListItem } from '@hubspot/cms-component-library/List';
453
423
 
454
424
  <List listType="unordered" variant="primary">
455
- <ListItem showIcon={false}>Simple item one</ListItem>
456
- <ListItem showIcon={false}>Simple item two</ListItem>
457
- <ListItem showIcon={false}>Simple item three</ListItem>
425
+ <ListItem>Simple item one</ListItem>
426
+ <ListItem>Simple item two</ListItem>
427
+ <ListItem>Simple item three</ListItem>
458
428
  </List>
459
429
  ```
460
430
 
461
431
  ## Related Components
462
432
 
463
433
  - **Flex**: Used internally for list layout control. The List component extends Flex capabilities.
464
- - **Icon**: Used internally for rendering icons in ListItem. Can be used standalone for custom implementations.
434
+ - **Icon**: Can be used as children in ListItem for custom icon lists.