@hubspot/cms-component-library 0.3.8 → 0.3.10

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 (48) hide show
  1. package/components/componentLibrary/Accordion/AccordionTitle/AccordionTitleBase.tsx +45 -0
  2. package/components/componentLibrary/Accordion/AccordionTitle/index.tsx +17 -30
  3. package/components/componentLibrary/Accordion/AccordionTitle/islands/AccordionTitleIsland.tsx +29 -0
  4. package/components/componentLibrary/Button/StyleFields.tsx +8 -8
  5. package/components/componentLibrary/Button/index.module.scss +24 -27
  6. package/components/componentLibrary/Button/index.tsx +4 -4
  7. package/components/componentLibrary/Button/llm.txt +51 -64
  8. package/components/componentLibrary/Button/stories/Button.AsButton.stories.tsx +2 -2
  9. package/components/componentLibrary/Button/stories/Button.AsLink.stories.tsx +2 -2
  10. package/components/componentLibrary/Button/stories/ButtonDecorator.module.scss +19 -23
  11. package/components/componentLibrary/Button/types.ts +2 -2
  12. package/components/componentLibrary/Card/StyleFields.tsx +9 -14
  13. package/components/componentLibrary/Card/index.module.scss +7 -7
  14. package/components/componentLibrary/Card/index.tsx +8 -13
  15. package/components/componentLibrary/Card/llm.txt +22 -43
  16. package/components/componentLibrary/Card/stories/Card.stories.tsx +28 -20
  17. package/components/componentLibrary/Card/stories/CardDecorator.module.scss +28 -5
  18. package/components/componentLibrary/Card/types.ts +8 -5
  19. package/components/componentLibrary/Form/StyleFields.tsx +19 -0
  20. package/components/componentLibrary/Form/index.tsx +7 -1
  21. package/components/componentLibrary/Form/islands/FormIsland.tsx +3 -1
  22. package/components/componentLibrary/Form/islands/LegacyFormIsland.tsx +2 -1
  23. package/components/componentLibrary/Form/islands/legacyForm.module.css +251 -0
  24. package/components/componentLibrary/Form/islands/v4Form.module.css +95 -0
  25. package/components/componentLibrary/Form/llm.txt +184 -0
  26. package/components/componentLibrary/Form/types.ts +6 -0
  27. package/components/componentLibrary/Link/ContentFields.tsx +2 -2
  28. package/components/componentLibrary/Link/StyleFields.tsx +10 -17
  29. package/components/componentLibrary/Link/index.module.scss +9 -9
  30. package/components/componentLibrary/Link/index.tsx +3 -8
  31. package/components/componentLibrary/Link/llm.txt +29 -85
  32. package/components/componentLibrary/Link/stories/Link.stories.tsx +4 -11
  33. package/components/componentLibrary/Link/stories/LinkDecorator.module.scss +15 -0
  34. package/components/componentLibrary/Link/stories/LinkDecorator.tsx +2 -11
  35. package/components/componentLibrary/Link/types.ts +11 -8
  36. package/components/componentLibrary/Video/ContentFields.tsx +112 -0
  37. package/components/componentLibrary/Video/StyleFields.tsx +19 -0
  38. package/components/componentLibrary/Video/index.tsx +47 -0
  39. package/components/componentLibrary/Video/islands/HSVideoIsland.tsx +53 -0
  40. package/components/componentLibrary/Video/serverUtils.ts +41 -0
  41. package/components/componentLibrary/Video/types.ts +74 -0
  42. package/components/componentLibrary/_patterns/README.md +11 -7
  43. package/components/componentLibrary/_patterns/checklist-and-examples.md +8 -0
  44. package/components/componentLibrary/_patterns/component-structure.md +5 -1
  45. package/components/componentLibrary/_patterns/field-patterns.md +46 -0
  46. package/components/componentLibrary/_patterns/island-patterns.md +136 -0
  47. package/components/componentLibrary/utils/index.ts +1 -0
  48. package/package.json +4 -3
@@ -0,0 +1,45 @@
1
+ import Text from '../../Text/index.js';
2
+ import styles from './index.module.scss';
3
+ import cx from '../../utils/classname.js';
4
+ import { ChevronIcon, PlusIcon, MinusIcon, CaretIcon } from './icons.js';
5
+ import type { AccordionTitleProps } from './types.js';
6
+
7
+ const AccordionTitleBase = ({
8
+ icon = 'chevron',
9
+ fieldPath,
10
+ className = '',
11
+ style = {},
12
+ children,
13
+ }: AccordionTitleProps) => {
14
+ const combinedClasses = cx(styles.accordionTitle, className);
15
+
16
+ const renderIcon = () => {
17
+ if (icon === 'chevron') return <ChevronIcon />;
18
+
19
+ if (icon === 'plus') {
20
+ return (
21
+ <>
22
+ <PlusIcon />
23
+ <MinusIcon />
24
+ </>
25
+ );
26
+ }
27
+
28
+ if (icon === 'caret') return <CaretIcon />;
29
+
30
+ return null;
31
+ };
32
+
33
+ return (
34
+ <summary className={combinedClasses} style={style}>
35
+ {fieldPath ? (
36
+ <Text fieldPath={fieldPath} className={styles.accordionTitleText} />
37
+ ) : (
38
+ <span className={styles.accordionTitleText}>{children}</span>
39
+ )}
40
+ {renderIcon()}
41
+ </summary>
42
+ );
43
+ };
44
+
45
+ export default AccordionTitleBase;
@@ -1,10 +1,10 @@
1
- import Text from '../../Text/index.js';
2
- import styles from './index.module.scss';
1
+ import { useEditorVariableChecks, Island } from '@hubspot/cms-components';
2
+ // @ts-expect-error -- ?island not typed
3
+ import AccordionTitleIslandModule from './islands/AccordionTitleIsland.js?island';
3
4
  import ContentFields from './ContentFields.js';
4
5
  import StyleFields from './StyleFields.js';
5
- import cx from '../../utils/classname.js';
6
6
  import { AccordionTitleProps } from './types.js';
7
- import { ChevronIcon, PlusIcon, MinusIcon, CaretIcon } from './icons.js';
7
+ import AccordionTitleBase from './AccordionTitleBase.js';
8
8
 
9
9
  const AccordionTitleComponent = ({
10
10
  icon = 'chevron',
@@ -13,34 +13,21 @@ const AccordionTitleComponent = ({
13
13
  style = {},
14
14
  children,
15
15
  }: AccordionTitleProps) => {
16
- const combinedClasses = cx(styles.accordionTitle, className);
17
-
18
- const renderIcon = () => {
19
- if (icon === 'chevron') return <ChevronIcon />;
20
-
21
- if (icon === 'plus') {
22
- return (
23
- <>
24
- <PlusIcon />
25
- <MinusIcon />
26
- </>
27
- );
28
- }
29
-
30
- if (icon === 'caret') return <CaretIcon />;
31
-
32
- return null;
33
- };
16
+ const editorChecks = useEditorVariableChecks();
17
+ const isInEditor = editorChecks.is_in_editor && !!fieldPath;
34
18
 
35
19
  return (
36
- <summary className={combinedClasses} style={style}>
37
- {fieldPath ? (
38
- <Text fieldPath={fieldPath} className={styles.accordionTitleText} />
39
- ) : (
40
- <span className={styles.accordionTitleText}>{children}</span>
41
- )}
42
- {renderIcon()}
43
- </summary>
20
+ <>
21
+ <AccordionTitleBase
22
+ icon={icon}
23
+ fieldPath={fieldPath}
24
+ className={className}
25
+ style={style}
26
+ >
27
+ {children}
28
+ </AccordionTitleBase>
29
+ {isInEditor && <Island module={AccordionTitleIslandModule} />}
30
+ </>
44
31
  );
45
32
  };
46
33
 
@@ -0,0 +1,29 @@
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ const AccordionTitleIsland = () => {
4
+ const markerRef = useRef<HTMLSpanElement>(null);
5
+
6
+ useEffect(() => {
7
+ const marker = markerRef.current;
8
+ if (!marker) return;
9
+
10
+ const details = marker.closest('details');
11
+ const summary = details?.querySelector('summary');
12
+ if (!summary) return;
13
+
14
+ const handleClick = (e: MouseEvent) => {
15
+ const target = e.target as HTMLElement;
16
+ const isIconClick = target.closest('svg');
17
+ if (!isIconClick) {
18
+ e.preventDefault();
19
+ }
20
+ };
21
+
22
+ summary.addEventListener('click', handleClick);
23
+ return () => summary.removeEventListener('click', handleClick);
24
+ }, []);
25
+
26
+ return <span ref={markerRef} style={{ display: 'none' }} />;
27
+ };
28
+
29
+ export default AccordionTitleIsland;
@@ -1,10 +1,14 @@
1
- import { ChoiceField, Visibility } from '@hubspot/cms-components/fields';
1
+ import {
2
+ ChoiceField,
3
+ VariantSelectionField,
4
+ Visibility,
5
+ } from '@hubspot/cms-components/fields';
2
6
  import { StyleFieldsProps } from './types.js';
3
7
 
4
8
  const StyleFields = ({
5
9
  buttonVariantLabel = 'Button variant',
6
10
  buttonVariantName = 'buttonVariant',
7
- buttonVariantDefault = 'primary',
11
+ buttonVariantDefault = { variant_name: 'primaryButton' },
8
12
  buttonIconPositionLabel = 'Icon position',
9
13
  buttonIconPositionName = 'buttonIconPosition',
10
14
  buttonIconPositionDefault = 'right',
@@ -18,14 +22,10 @@ const StyleFields = ({
18
22
 
19
23
  return (
20
24
  <>
21
- <ChoiceField
25
+ <VariantSelectionField
22
26
  label={buttonVariantLabel}
23
27
  name={buttonVariantName}
24
- choices={[
25
- ['primary', 'Primary'],
26
- ['secondary', 'Secondary'],
27
- ['tertiary', 'Tertiary'],
28
- ]}
28
+ variantDefinitionName="button"
29
29
  default={buttonVariantDefault}
30
30
  />
31
31
  <ChoiceField
@@ -1,48 +1,45 @@
1
- // CSS variables that can be mapped to theme settings
1
+ // CSS variables provided via theme settings variant system (scoped via data-buttons-variant)
2
2
  .button {
3
3
  display: inline-flex;
4
4
  flex-direction: row;
5
5
  align-items: center;
6
6
  justify-content: center;
7
- text-decoration: none;
8
- gap: var(--hscl-button-gap, 8px);
9
- background-color: var(--hscl-button-backgroundColor);
10
- color: var(--hscl-button-color);
11
- padding: var(--hscl-button-paddingBlock) var(--hscl-button-paddingInline);
12
- border-radius: var(--hscl-button-borderRadius);
13
- border: var(--hscl-button-borderWidth) solid var(--hscl-button-borderColor);
14
- font-size: var(--hscl-button-fontSize);
15
- font-weight: var(--hscl-button-fontWeight);
7
+ gap: 8px;
8
+ background-color: var(--hs-button-backgroundColor);
9
+ color: var(--hs-button-color);
10
+ padding: 12px 24px;
11
+ border-radius: var(--hs-button-borderRadius);
12
+ border: var(--hs-button-border);
13
+ font-size: var(--hs-button-fontSize);
14
+ font-family: var(--hs-button-fontFamily);
15
+ font-style: var(--hs-button-fontStyle);
16
+ font-weight: var(--hs-button-fontWeight);
17
+ text-decoration: var(--hs-button-textDecoration);
16
18
  cursor: pointer;
17
19
  transition: all 0.2s ease;
18
- text-decoration: none;
19
20
 
20
21
  @media (prefers-reduced-motion: reduce) {
21
22
  transition: none;
22
23
  }
23
24
 
24
25
  &:hover {
25
- background-color: var(--hscl-button-backgroundColor-hover, var(--hscl-button-backgroundColor));
26
- color: var(--hscl-button-color-hover, var(--hscl-button-color));
27
- border-width: var(--hscl-button-borderWidth-hover, var(--hscl-button-borderWidth));
28
- border-color: var(--hscl-button-borderColor-hover, var(--hscl-button-borderColor));
29
- text-decoration: none;
26
+ background-color: var(--hs-button-backgroundColor-hover, var(--hs-button-backgroundColor));
27
+ color: var(--hs-button-color-hover, var(--hs-button-color));
28
+ border: var(--hs-button-border-hover, var(--hs-button-border));
30
29
  }
31
30
 
32
31
  &:focus-visible {
33
- background-color: var(--hscl-button-backgroundColor-focus, var(--hscl-button-backgroundColor));
34
- color: var(--hscl-button-color-focus, var(--hscl-button-color));
35
- border-width: var(--hscl-button-borderWidth-focus, var(--hscl-button-borderWidth));
36
- border-color: var(--hscl-button-borderColor-focus, var(--hscl-button-borderColor));
37
- outline: var(--hscl-button-outlineWidth-focus, 2px) solid var(--hscl-button-outlineColor-focus, currentColor);
38
- outline-offset: var(--hscl-button-outlineOffset-focus, 2px);
32
+ background-color: var(--hs-button-backgroundColor-focus, var(--hs-button-backgroundColor));
33
+ color: var(--hs-button-color-focus, var(--hs-button-color));
34
+ border: var(--hs-button-border-focus, var(--hs-button-border));
35
+ outline: 2px solid;
36
+ outline-offset: 2px;
39
37
  }
40
38
 
41
39
  &:active {
42
- background-color: var(--hscl-button-backgroundColor-active, var(--hscl-button-backgroundColor));
43
- color: var(--hscl-button-color-active, var(--hscl-button-color));
44
- border-width: var(--hscl-button-borderWidth-active, var(--hscl-button-borderWidth));
45
- border-color: var(--hscl-button-borderColor-active, var(--hscl-button-borderColor));
40
+ background-color: var(--hs-button-backgroundColor-active, var(--hs-button-backgroundColor));
41
+ color: var(--hs-button-color-active, var(--hs-button-color));
42
+ border: var(--hs-button-border-active, var(--hs-button-border));
46
43
  }
47
44
 
48
45
  &:disabled {
@@ -54,6 +51,6 @@
54
51
  display: inline-flex;
55
52
  align-items: center;
56
53
  justify-content: center;
57
- fill: var(--hscl-button-icon-fill);
54
+ fill: currentColor;
58
55
  }
59
56
  }
@@ -13,16 +13,16 @@ import {
13
13
 
14
14
  const ButtonComponent = ({
15
15
  buttonType = 'link',
16
- variant = 'primary',
16
+ variant = 'primaryButton',
17
17
  className = '',
18
18
  style = {},
19
19
  ...rest
20
20
  }: ButtonProps) => {
21
- const variantClass = styles[`hscl-button-${variant}`]; // !todo: not used atm but keeping for when we need to add variant system.
22
- const defaultClasses = cx(styles.button, variantClass);
21
+ const defaultClasses = cx(styles.button, className);
23
22
  const sharedProps = {
24
- className: cx(defaultClasses, className),
23
+ className: defaultClasses,
25
24
  style: style,
25
+ 'data-button-variant': variant,
26
26
  };
27
27
 
28
28
  const RenderWithIcon = ({
@@ -37,7 +37,7 @@ Button/
37
37
  **Base Props (shared by both types):**
38
38
  ```tsx
39
39
  {
40
- variant?: 'primary' | 'secondary' | 'tertiary'; // Visual style variant
40
+ variant?: 'primaryButton' | 'secondaryButton' | 'tertiaryButton' | 'accentButton'; // Visual style variant (connected to theme settings)
41
41
  className?: string; // Additional CSS classes
42
42
  style?: React.CSSProperties; // Inline styles
43
43
  children?: React.ReactNode; // Button text/content
@@ -108,7 +108,7 @@ import { Island } from '@hubspot/cms-components'
108
108
  ```tsx
109
109
  <Button
110
110
  buttonType="link"
111
- variant="primary"
111
+ variant="primaryButton"
112
112
  href="https://www.hubspot.com"
113
113
  target="_self"
114
114
  >
@@ -121,7 +121,7 @@ import { Island } from '@hubspot/cms-components'
121
121
  ```tsx
122
122
  <Button
123
123
  buttonType="link"
124
- variant="primary"
124
+ variant="primaryButton"
125
125
  href="https://www.hubspot.com"
126
126
  target="_blank"
127
127
  rel="noopener noreferrer"
@@ -135,7 +135,7 @@ import { Island } from '@hubspot/cms-components'
135
135
  ```tsx
136
136
  <Button
137
137
  buttonType="button"
138
- variant="primary"
138
+ variant="primaryButton"
139
139
  onClick={handleClick}
140
140
  showIcon={true}
141
141
  iconFieldPath="icon"
@@ -152,7 +152,7 @@ import { Island } from '@hubspot/cms-components'
152
152
  ```tsx
153
153
  <Button
154
154
  buttonType="link"
155
- variant="secondary"
155
+ variant="secondaryButton"
156
156
  href="/back"
157
157
  showIcon={true}
158
158
  iconFieldPath="icon"
@@ -170,7 +170,7 @@ import { Island } from '@hubspot/cms-components'
170
170
  ```tsx
171
171
  <Button
172
172
  buttonType="button"
173
- variant="primary"
173
+ variant="primaryButton"
174
174
  disabled={true}
175
175
  onClick={handleClick}
176
176
  >
@@ -183,7 +183,7 @@ import { Island } from '@hubspot/cms-components'
183
183
  ```tsx
184
184
  <Button
185
185
  buttonType="link"
186
- variant="primary"
186
+ variant="primaryButton"
187
187
  href="/custom"
188
188
  className="custom-button-class"
189
189
  style={{ maxWidth: '300px' }}
@@ -240,7 +240,7 @@ Configurable props for variant and icon position:
240
240
  <Button.StyleFields
241
241
  buttonVariantLabel="Button variant"
242
242
  buttonVariantName="buttonVariant"
243
- buttonVariantDefault="primary"
243
+ buttonVariantDefault={{ variant_name: 'primaryButton' }}
244
244
  buttonIconPositionLabel="Icon position"
245
245
  buttonIconPositionName="buttonIconPosition"
246
246
  buttonIconPositionDefault="right"
@@ -248,7 +248,7 @@ Configurable props for variant and icon position:
248
248
  ```
249
249
 
250
250
  **Fields:**
251
- - `buttonVariant`: ChoiceField for selecting visual style (primary, secondary, tertiary)
251
+ - `buttonVariant`: VariantSelectionField connected to theme settings (primaryButton, secondaryButton, tertiaryButton, accentButton)
252
252
  - `buttonIconPosition`: ChoiceField for selecting icon placement (left, right). This field has a hardcoded visibility rule — it is only shown when the icon toggle is enabled (`iconComponentShowIcon === true`), which corresponds to the `BooleanField` id hardcoded in `Icon.ContentFields`.
253
253
 
254
254
  ### Module Usage Example
@@ -276,57 +276,44 @@ export default function CTAModule({ fieldValues }) {
276
276
 
277
277
  ## Styling
278
278
 
279
- ### CSS Variables
280
-
281
- The Button component uses CSS variables for theming and customization:
282
-
283
- **Base Styles:**
284
- - `--hscl-button-gap`: Space between text and icon (default: 8px)
285
- - `--hscl-button-backgroundColor`: Background color
286
- - `--hscl-button-color`: Text color
287
- - `--hscl-button-paddingBlock`: Vertical padding
288
- - `--hscl-button-paddingInline`: Horizontal padding
289
- - `--hscl-button-borderRadius`: Border radius
290
- - `--hscl-button-borderWidth`: Border width
291
- - `--hscl-button-borderColor`: Border color
292
- - `--hscl-button-fontSize`: Font size
293
- - `--hscl-button-fontWeight`: Font weight
294
-
295
- **Hover States:**
296
- - `--hscl-button-backgroundColor-hover`: Hover background color
297
- - `--hscl-button-color-hover`: Hover text color
298
- - `--hscl-button-borderWidth-hover`: Hover border width
299
- - `--hscl-button-borderColor-hover`: Hover border color
300
-
301
- **Focus States:**
302
- - `--hscl-button-backgroundColor-focus`: Focus background color
303
- - `--hscl-button-color-focus`: Focus text color
304
- - `--hscl-button-borderWidth-focus`: Focus border width
305
- - `--hscl-button-borderColor-focus`: Focus border color
306
- - `--hscl-button-outlineWidth-focus`: Focus outline width
307
- - `--hscl-button-outlineColor-focus`: Focus outline color
308
- - `--hscl-button-outlineOffset-focus`: Focus outline offset
309
-
310
- **Icon:**
311
- - `--hscl-button-icon-fill`: Icon fill color
312
-
313
- ### Custom Styling Example
279
+ ### Theme CSS Variables
314
280
 
315
- ```tsx
316
- <Button
317
- buttonType="button"
318
- variant="primary"
319
- style={{
320
- '--hscl-button-backgroundColor': '#FF7A59',
321
- '--hscl-button-color': '#FFFFFF',
322
- '--hscl-button-paddingBlock': '12px',
323
- '--hscl-button-paddingInline': '24px',
324
- '--hscl-button-borderRadius': '8px',
325
- }}
326
- >
327
- Custom Colors
328
- </Button>
329
- ```
281
+ The Button component is themed via `--hs-button-*` CSS variables, which are provided by the theme settings variant system (scoped via the variant prop and `data-buttons-variant` attribute).
282
+
283
+ **Base Styles (from theme):**
284
+ - `--hs-button-backgroundColor`: Background color
285
+ - `--hs-button-color`: Text color
286
+ - `--hs-button-borderRadius`: Border radius
287
+ - `--hs-button-border`: Border shorthand
288
+ - `--hs-button-fontSize`: Font size
289
+ - `--hs-button-fontFamily`: Font family
290
+ - `--hs-button-fontStyle`: Font style
291
+ - `--hs-button-fontWeight`: Font weight
292
+ - `--hs-button-textDecoration`: Text decoration
293
+
294
+ **Hover States (from theme):**
295
+ - `--hs-button-backgroundColor-hover`: Hover background (falls back to base)
296
+ - `--hs-button-color-hover`: Hover text color (falls back to base)
297
+ - `--hs-button-border-hover`: Hover border (falls back to base)
298
+
299
+ **Focus States (from theme):**
300
+ - `--hs-button-backgroundColor-focus`: Focus background (falls back to base)
301
+ - `--hs-button-color-focus`: Focus text color (falls back to base)
302
+ - `--hs-button-border-focus`: Focus border (falls back to base)
303
+
304
+ **Active States (from theme):**
305
+ - `--hs-button-backgroundColor-active`: Active background (falls back to base)
306
+ - `--hs-button-color-active`: Active text color (falls back to base)
307
+ - `--hs-button-border-active`: Active border (falls back to base)
308
+
309
+ ### Hardcoded Layout Values
310
+
311
+ The following properties use fixed values and are not configurable via CSS variables:
312
+
313
+ - **Gap:** 8px (space between text and icon)
314
+ - **Padding:** 12px vertical, 24px horizontal
315
+ - **Focus outline:** 2px solid currentColor, offset 2px
316
+ - **Icon fill:** currentColor
330
317
 
331
318
  ## Accessibility
332
319
 
@@ -359,7 +346,7 @@ The Button component follows accessibility best practices:
359
346
  - **Icon purpose**: Use `SEMANTIC` when the icon adds meaning, `DECORATIVE` when it's purely visual
360
347
  - **Disabled state**: Only use with `buttonType="button"`, not applicable to links
361
348
  - **CSS Variables**: Override design tokens using CSS variables rather than hardcoding values
362
- - **Variant system**: Currently variants are passed as props but full theming implementation is pending
349
+ - **Variant system**: Variants are connected to theme settings via `VariantSelectionField` and `data-variant-name` attribute. CSS variables are scoped automatically by the ContentUILib variant system.
363
350
 
364
351
  ## Common Patterns
365
352
 
@@ -368,7 +355,7 @@ The Button component follows accessibility best practices:
368
355
  ```tsx
369
356
  <Button
370
357
  buttonType="link"
371
- variant="primary"
358
+ variant="primaryButton"
372
359
  href="/signup"
373
360
  showIcon={true}
374
361
  iconFieldPath="icon"
@@ -383,7 +370,7 @@ The Button component follows accessibility best practices:
383
370
  ```tsx
384
371
  <Button
385
372
  buttonType="button"
386
- variant="primary"
373
+ variant="primaryButton"
387
374
  onClick={handleSubmit}
388
375
  disabled={isSubmitting}
389
376
  >
@@ -396,7 +383,7 @@ The Button component follows accessibility best practices:
396
383
  ```tsx
397
384
  <Button
398
385
  buttonType="link"
399
- variant="secondary"
386
+ variant="secondaryButton"
400
387
  href="/dashboard"
401
388
  showIcon={true}
402
389
  iconFieldPath="icon"
@@ -411,7 +398,7 @@ The Button component follows accessibility best practices:
411
398
  ```tsx
412
399
  <Button
413
400
  buttonType="link"
414
- variant="tertiary"
401
+ variant="tertiaryButton"
415
402
  href="https://docs.hubspot.com"
416
403
  target="_blank"
417
404
  rel="noopener noreferrer"
@@ -26,7 +26,7 @@ type Story = StoryObj<typeof meta>;
26
26
 
27
27
  export const Default: Story = {
28
28
  args: {
29
- variant: 'primary',
29
+ variant: 'primaryButton',
30
30
  children: 'Click me',
31
31
  onClick: () => alert('Button clicked!'),
32
32
  },
@@ -34,7 +34,7 @@ export const Default: Story = {
34
34
 
35
35
  export const WithIcon: Story = {
36
36
  args: {
37
- variant: 'primary',
37
+ variant: 'primaryButton',
38
38
  children: 'Click me',
39
39
  onClick: () => alert('Button clicked!'),
40
40
  showIcon: true,
@@ -26,7 +26,7 @@ type Story = StoryObj<typeof meta>;
26
26
 
27
27
  export const Default: Story = {
28
28
  args: {
29
- variant: 'primary',
29
+ variant: 'primaryButton',
30
30
  children: 'Click me',
31
31
  href: 'https://www.hubspot.com',
32
32
  },
@@ -34,7 +34,7 @@ export const Default: Story = {
34
34
 
35
35
  export const WithIcon: Story = {
36
36
  args: {
37
- variant: 'primary',
37
+ variant: 'primaryButton',
38
38
  children: 'Click me',
39
39
  href: 'https://www.hubspot.com',
40
40
  showIcon: true,
@@ -1,25 +1,21 @@
1
1
  .buttonContainer {
2
- padding: '20px';
3
- --hscl-button-gap: 8px;
4
- --hscl-button-backgroundColor: #0066cc;
5
- --hscl-button-color: #ffffff;
6
- --hscl-button-paddingBlock: 10px;
7
- --hscl-button-paddingInline: 20px;
8
- --hscl-button-borderRadius: 4px;
9
- --hscl-button-borderWidth: 1px;
10
- --hscl-button-borderColor: transparent;
11
- --hscl-button-fontSize: 14px;
12
- --hscl-button-fontWeight: 500;
13
- --hscl-button-backgroundColor-hover: #0052a3;
14
- --hscl-button-color-hover: #ffffff;
15
- --hscl-button-borderWidth-hover: 1px;
16
- --hscl-button-borderColor-hover: transparent;
17
- --hscl-button-backgroundColor-focus: #0066cc;
18
- --hscl-button-color-focus: #ffffff;
19
- --hscl-button-borderWidth-focus: 1px;
20
- --hscl-button-borderColor-focus: transparent;
21
- --hscl-button-outlineWidth-focus: 2px;
22
- --hscl-button-outlineColor-focus: #0066cc;
23
- --hscl-button-outlineOffset-focus: 2px;
24
- --hscl-button-icon-fill: currentColor;
2
+ padding: 20px;
3
+ --hs-button-backgroundColor: #0066cc;
4
+ --hs-button-color: #ffffff;
5
+ --hs-button-borderRadius: 4px;
6
+ --hs-button-border: 1px solid transparent;
7
+ --hs-button-fontSize: 14px;
8
+ --hs-button-fontFamily: inherit;
9
+ --hs-button-fontStyle: normal;
10
+ --hs-button-fontWeight: 500;
11
+ --hs-button-textDecoration: none;
12
+ --hs-button-backgroundColor-hover: #0052a3;
13
+ --hs-button-color-hover: #ffffff;
14
+ --hs-button-border-hover: 1px solid transparent;
15
+ --hs-button-backgroundColor-focus: #0066cc;
16
+ --hs-button-color-focus: #ffffff;
17
+ --hs-button-border-focus: 1px solid transparent;
18
+ --hs-button-backgroundColor-active: #004080;
19
+ --hs-button-color-active: #ffffff;
20
+ --hs-button-border-active: 1px solid transparent;
25
21
  }
@@ -8,7 +8,7 @@ export type IconPositionHorizontal = 'left' | 'right';
8
8
 
9
9
  // Base props shared by all variants
10
10
  export type BaseButtonProps = {
11
- variant?: 'primary' | 'secondary' | 'tertiary'; // !todo: not used atm but keeping for when we need to add variant system.
11
+ variant?: 'primaryButton' | 'secondaryButton' | 'tertiaryButton' | 'accentButton';
12
12
  className?: string;
13
13
  style?: React.CSSProperties;
14
14
  children?: React.ReactNode;
@@ -57,7 +57,7 @@ export type ContentFieldsProps = Omit<
57
57
  export type StyleFieldsProps = {
58
58
  buttonVariantLabel?: string;
59
59
  buttonVariantName?: string;
60
- buttonVariantDefault?: string;
60
+ buttonVariantDefault?: { variant_name: string };
61
61
  buttonIconPositionLabel?: string;
62
62
  buttonIconPositionName?: string;
63
63
  buttonIconPositionDefault?: IconPositionHorizontal;
@@ -1,22 +1,17 @@
1
- import { ChoiceField } from '@hubspot/cms-components/fields';
1
+ import { VariantSelectionField } from '@hubspot/cms-components/fields';
2
2
  import { StyleFieldsProps } from './types.js';
3
3
 
4
4
  const StyleFields = ({
5
- variantLabel = 'Card Variant',
6
- variantName = 'variant',
7
- variantDefault = 'elevated',
5
+ cardVariantLabel = 'Card variant',
6
+ cardVariantName = 'cardVariant',
7
+ cardVariantDefault = { variantName: 'cardStyle1' },
8
8
  }: StyleFieldsProps) => {
9
9
  return (
10
- <ChoiceField
11
- label={variantLabel}
12
- name={variantName}
13
- required={true}
14
- choices={[
15
- ['elevated', 'Elevated (with shadow)'],
16
- ['outlined', 'Outlined (with border)'],
17
- ['filled', 'Filled (solid background)'],
18
- ]}
19
- default={variantDefault}
10
+ <VariantSelectionField
11
+ label={cardVariantLabel}
12
+ name={cardVariantName}
13
+ variantDefinitionName="card"
14
+ default={cardVariantDefault}
20
15
  />
21
16
  );
22
17
  };
@@ -2,13 +2,13 @@
2
2
  display: flex;
3
3
  flex-direction: column;
4
4
  box-sizing: border-box;
5
- padding: var(--hscl-card-padding, 24px);
6
- border-radius: var(--hscl-card-borderRadius, 8px);
7
- background-color: var(--hscl-card-backgroundColor, #ffffff);
8
- box-shadow: var(--hscl-card-boxShadow, none);
9
- border: var(--hscl-card-border, none);
5
+ padding: 24px;
6
+ border-radius: var(--hs-card-borderRadius, 8px);
7
+ background-color: var(--hs-card-backgroundColor, #ffffff);
8
+ color: var(--hs-card-color, inherit);
9
+ border: var(--hs-card-border, none);
10
10
 
11
- &:hover {
12
- box-shadow: var(--hscl-card-boxShadow-hover, var(--hscl-card-boxShadow, none));
11
+ h1,h2,h3,h4,h5,h6,p,span {
12
+ color: inherit;
13
13
  }
14
14
  }