@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
@@ -0,0 +1,380 @@
1
+ # LanguageSwitcher Component
2
+
3
+ A multilingual navigation component that displays the current page language and provides a slide-out drawer interface for selecting available language variants. Integrates with HubSpot's multi-language content system to enable seamless language switching across translated pages.
4
+
5
+ ## Import path
6
+ ```tsx
7
+ import LanguageSwitcher from '@hubspot/cms-component-library/LanguageSwitcher';
8
+ ```
9
+
10
+ ## Purpose
11
+
12
+ The LanguageSwitcher component provides an accessible interface for users to view and switch between available language variants of the current page. It displays a button showing the current language with a globe icon, and opens a slide-out drawer panel listing all available translations. The component automatically fetches language variants from HubSpot's CMS using the `useLanguageVariants` hook and handles navigation to the localized URLs. Use this component in global navigation areas like headers or footers to provide consistent language selection across multilingual sites.
13
+
14
+ ## Component Structure
15
+
16
+ ```
17
+ LanguageSwitcher/
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
+ ├── LanguageOptions.tsx # Language option list component
23
+ ├── LanguageOptions.module.scss # CSS module for language options
24
+ ├── utils.tsx # Utility functions for language display
25
+ ├── _dummyData.tsx # Dummy translation data for development
26
+ ├── index.module.scss # CSS module with design tokens
27
+ ├── assets/
28
+ │ └── Globe.tsx # Globe SVG icon component
29
+ └── stories/
30
+ ├── LanguageSwitcher.stories.tsx # Component usage examples
31
+ ├── LanguageSwitcherDecorator.tsx # Storybook decorator
32
+ └── LanguageSwitcherDecorator.module.css # Decorator styles
33
+ ```
34
+
35
+ ## Components
36
+
37
+ ### LanguageSwitcher (Main Component)
38
+
39
+ **Purpose:** Renders a button displaying the current page language that opens a drawer panel with all available language options.
40
+
41
+ **Props:**
42
+ ```tsx
43
+ {
44
+ className?: string; // Additional CSS classes
45
+ style?: React.CSSProperties; // Inline styles
46
+ textColor?: ColorFieldValue; // Text color for button and menu items
47
+ textColorHover?: ColorFieldValue; // Text color for menu items on hover
48
+ menuBackgroundColor?: ColorFieldValue; // Background color for the drawer
49
+ menuBackgroundColorHover?: ColorFieldValue; // Background color for menu items on hover
50
+ languageSwitcherSelectText?: string; // Header text in drawer (default: 'Select a language')
51
+ useDummyData?: boolean; // Use dummy data for testing (development only)
52
+ }
53
+ ```
54
+
55
+ ## Usage Examples
56
+
57
+ ### Island Usage
58
+
59
+ The LanguageSwitcher component requires JavaScript for interactive state management and must be used within an Island component.
60
+
61
+ #### Island Component
62
+
63
+ ```tsx
64
+ // islands/LanguageSwitcherIsland.tsx
65
+ import LanguageSwitcher from '@hubspot/cms-component-library/LanguageSwitcher';
66
+
67
+ export default function LanguageSwitcherIsland({
68
+ textColor,
69
+ textColorHover,
70
+ menuBackgroundColor,
71
+ menuBackgroundColorHover,
72
+ languageSwitcherSelectText,
73
+ }) {
74
+ return (
75
+ <LanguageSwitcher
76
+ textColor={textColor}
77
+ textColorHover={textColorHover}
78
+ menuBackgroundColor={menuBackgroundColor}
79
+ menuBackgroundColorHover={menuBackgroundColorHover}
80
+ languageSwitcherSelectText={languageSwitcherSelectText}
81
+ />
82
+ );
83
+ }
84
+ ```
85
+
86
+ #### Module File
87
+
88
+ ```tsx
89
+ import { Island } from '@hubspot/cms-components';
90
+ import LanguageSwitcherIsland from './islands/LanguageSwitcherIsland?island';
91
+
92
+ export const Component = ({ fieldValues }) => {
93
+ return (
94
+ <Island
95
+ module={LanguageSwitcherIsland}
96
+ textColor={fieldValues.textColor}
97
+ textColorHover={fieldValues.textColorHover}
98
+ menuBackgroundColor={fieldValues.menuBackgroundColor}
99
+ menuBackgroundColorHover={fieldValues.menuBackgroundColorHover}
100
+ languageSwitcherSelectText={fieldValues.languageSwitcherSelectText}
101
+ />
102
+ );
103
+ };
104
+ ```
105
+
106
+ ### Basic Language Switcher
107
+
108
+ ```tsx
109
+ import LanguageSwitcher from '@hubspot/cms-component-library/LanguageSwitcher';
110
+
111
+ export default function LanguageSwitcherIsland() {
112
+ return <LanguageSwitcher />;
113
+ }
114
+ ```
115
+
116
+ ### With Custom Header Text
117
+
118
+ ```tsx
119
+ <LanguageSwitcher languageSwitcherSelectText="Choose your language" />
120
+ ```
121
+
122
+ ### With Custom Colors
123
+
124
+ If passing in colors directly (without using a ColorField), like the below example, ensure rgba is an object key. This is because the component expects the rgba key for the color props.
125
+
126
+ ```tsx
127
+ <LanguageSwitcher
128
+ textColor={{ rgba: 'rgba(51, 71, 91, 1)' }}
129
+ textColorHover={{ rgba: 'rgba(0, 102, 204, 1)' }}
130
+ menuBackgroundColor={{ rgba: 'rgba(255, 255, 255, 1)' }}
131
+ menuBackgroundColorHover={{ rgba: 'rgba(245, 245, 245, 1)' }}
132
+ />
133
+ ```
134
+
135
+ ### In Header Navigation
136
+
137
+ ```tsx
138
+ <header style={{ display: 'flex', justifyContent: 'space-between', padding: '16px' }}>
139
+ <div>
140
+ <h1>My Website</h1>
141
+ </div>
142
+ <nav style={{ display: 'flex', gap: '24px', alignItems: 'center' }}>
143
+ <a href="/about">About</a>
144
+ <a href="/contact">Contact</a>
145
+ <LanguageSwitcher />
146
+ </nav>
147
+ </header>
148
+ ```
149
+
150
+ ## HubSpot CMS Integration
151
+
152
+ ### Field Definitions
153
+
154
+ The LanguageSwitcher component provides field definitions for easy integration with HubSpot CMS modules.
155
+
156
+ #### ContentFields
157
+
158
+ Configurable props for customizing the drawer header text:
159
+
160
+ ```tsx
161
+ <LanguageSwitcher.ContentFields
162
+ languageSwitcherSelectTextLabel="Language selector text"
163
+ languageSwitcherSelectTextName="languageSwitcherSelectText"
164
+ languageSwitcherSelectTextDefault="Select a language"
165
+ />
166
+ ```
167
+
168
+ **Fields:**
169
+ - `languageSwitcherSelectText`: TextField for drawer header text
170
+
171
+ #### StyleFields
172
+
173
+ Configurable props for color customization:
174
+
175
+ ```tsx
176
+ <LanguageSwitcher.StyleFields
177
+ textColorLabel="Text color"
178
+ textColorName="textColor"
179
+ textColorDefault={{ color: '#000000', opacity: 100 }}
180
+ textColorHoverLabel="Text color (hover)"
181
+ textColorHoverName="textColorHover"
182
+ textColorHoverDefault={{ color: '#000000', opacity: 100 }}
183
+ menuBackgroundColorLabel="Menu background color"
184
+ menuBackgroundColorName="menuBackgroundColor"
185
+ menuBackgroundColorDefault={{ color: '#FFFFFF', opacity: 100 }}
186
+ menuBackgroundColorHoverLabel="Menu background color (hover)"
187
+ menuBackgroundColorHoverName="menuBackgroundColorHover"
188
+ menuBackgroundColorHoverDefault={{ color: '#eaeaea', opacity: 100 }}
189
+ />
190
+ ```
191
+
192
+ **Fields:**
193
+ - `textColor`: ColorField for button and menu item text
194
+ - `textColorHover`: ColorField for menu item text on hover
195
+ - `menuBackgroundColor`: ColorField for drawer background
196
+ - `menuBackgroundColorHover`: ColorField for menu item background on hover
197
+
198
+ ### Module Usage Example
199
+
200
+ If passing in colors using a ColorField, like the below example, pass in the entire field value. HubSpot will transform the field value from a default of { color: hex, opacity: number } to { rbga, rgb, opacity, color, hex, css }. The LanguageSwitcher component will pull the rgba value from this final output.
201
+
202
+ ```tsx
203
+ import { Island } from '@hubspot/cms-components';
204
+ import LanguageSwitcherIsland from './islands/LanguageSwitcherIsland?island';
205
+
206
+ export default function HeaderModule({ fieldValues }) {
207
+ return (
208
+ <header>
209
+ <nav>
210
+ {/* Other navigation items */}
211
+ <Island
212
+ module={LanguageSwitcherIsland}
213
+ textColor={fieldValues.textColor}
214
+ textColorHover={fieldValues.textColorHover}
215
+ menuBackgroundColor={fieldValues.menuBackgroundColor}
216
+ menuBackgroundColorHover={fieldValues.menuBackgroundColorHover}
217
+ languageSwitcherSelectText={fieldValues.languageSwitcherSelectText}
218
+ />
219
+ </nav>
220
+ </header>
221
+ );
222
+ }
223
+ ```
224
+
225
+ ## Styling
226
+
227
+ ### CSS Variables
228
+
229
+ The LanguageSwitcher component uses CSS variables for theming and customization:
230
+
231
+ **Base Styles:**
232
+ - `--hscl-languageSwitcher-textColor`: Text color for button, drawer header, and close button (default: currentColor)
233
+ - `--hscl-languageSwitcher-backgroundColor`: Background color for drawer header (default: #ffffff)
234
+
235
+ **Button Styles:**
236
+ - Button has 8px 12px padding with 8px gap between icon and text
237
+ - Globe icon size: 20px height
238
+ - Font size: 18px
239
+
240
+ **Drawer Styles:**
241
+ - Drawer width: 400px (responsive: 100% width on screens ≤400px)
242
+ - Header padding: 24px
243
+ - Header font size: 24px with font weight 600
244
+ - Options container padding: 24px
245
+
246
+ ### Custom Styling Example
247
+
248
+ ```tsx
249
+ <LanguageSwitcher
250
+ style={{
251
+ '--hscl-languageSwitcher-textColor': 'rgba(51, 71, 91, 1)',
252
+ '--hscl-languageSwitcher-backgroundColor': 'rgba(255, 255, 255, 1)',
253
+ } as React.CSSProperties}
254
+ />
255
+ ```
256
+
257
+ ## Accessibility
258
+
259
+ The LanguageSwitcher component follows accessibility best practices:
260
+
261
+ - **Semantic HTML**: Uses proper button elements and drawer component with role="dialog"
262
+ - **Keyboard Navigation**:
263
+ - Button activates with Space or Enter keys
264
+ - ESC key closes the drawer
265
+ - Tab navigation works through language options
266
+ - **ARIA Attributes**:
267
+ - `aria-expanded` on button indicates drawer state
268
+ - `aria-label="Language selector"` on drawer provides context
269
+ - `aria-label="Close language selector"` on close button
270
+ - **Screen Reader Support**:
271
+ - Current language is announced on button
272
+ - Language options are properly labeled with native names
273
+ - Drawer state changes are announced
274
+ - **Visual Indicators**:
275
+ - Globe icon provides visual language indication
276
+ - Current language displayed prominently on button
277
+ - Clear visual feedback for hover states
278
+ - **Focus Management**: Drawer overlay prevents focus from leaving the language selector when open
279
+ - **Color Contrast**: Customizable colors allow meeting WCAG AA standards
280
+
281
+ ## Best Practices
282
+
283
+ - **Use Islands for interactivity**: The LanguageSwitcher component is interactive and requires JavaScript, so it must be used within an Island component in modules
284
+ - **Position prominently**: Place in global navigation (header or footer) where users expect language controls
285
+ - **Use native language names**: The component automatically displays language names in their native script (e.g., "Español" for Spanish, "Français" for French)
286
+ - **Customize header text**: Set `languageSwitcherSelectText` to match your site's primary language for consistency
287
+ - **Color coordination**: Match `textColor` and `menuBackgroundColor` to your site's theme
288
+ - **Color setting**: If using ColorFields, pass in the entire field value, as HubSpot transforms the user's color choice into an object with an rgba key. Otherwise, ensure the color object has an rgba key and value. The component expects an object with an rgba key.
289
+ - **Responsive design**: The drawer automatically adjusts to full width on mobile devices (≤400px)
290
+ - **Test with real translations**: While `useDummyData` prop exists for development, always test with actual HubSpot language variants in production
291
+ - **Provide clear visual feedback**: Use hover colors that provide sufficient contrast for user interaction
292
+ - **Consider placement**: Position near other utility navigation items (search, account, etc.)
293
+ - **Dark mode support**: Provide appropriate color values for dark backgrounds when needed
294
+
295
+ ## Common Patterns
296
+
297
+ ### Header Navigation Integration
298
+
299
+ ```tsx
300
+ import { Island } from '@hubspot/cms-components';
301
+ import LanguageSwitcherIsland from './islands/LanguageSwitcherIsland?island';
302
+
303
+ export default function SiteHeader({ fieldValues }) {
304
+ return (
305
+ <header style={{
306
+ display: 'flex',
307
+ justifyContent: 'space-between',
308
+ padding: '16px 24px',
309
+ alignItems: 'center'
310
+ }}>
311
+ <div>
312
+ <h1>Website Name</h1>
313
+ </div>
314
+ <nav style={{ display: 'flex', gap: '24px', alignItems: 'center' }}>
315
+ <a href="/about">About</a>
316
+ <a href="/services">Services</a>
317
+ <a href="/contact">Contact</a>
318
+ <Island
319
+ module={LanguageSwitcherIsland}
320
+ textColor={fieldValues.textColor}
321
+ menuBackgroundColor={fieldValues.menuBackgroundColor}
322
+ languageSwitcherSelectText={fieldValues.languageSwitcherSelectText}
323
+ />
324
+ </nav>
325
+ </header>
326
+ );
327
+ }
328
+ ```
329
+
330
+ ### Footer Placement
331
+
332
+ ```tsx
333
+ export default function SiteFooter({ fieldValues }) {
334
+ return (
335
+ <footer style={{ padding: '48px 24px', textAlign: 'center' }}>
336
+ <div style={{ marginBottom: '24px' }}>
337
+ <Island
338
+ module={LanguageSwitcherIsland}
339
+ textColor={fieldValues.footerTextColor}
340
+ menuBackgroundColor={fieldValues.menuBackgroundColor}
341
+ languageSwitcherSelectText={fieldValues.languageSwitcherSelectText}
342
+ />
343
+ </div>
344
+ <p>© 2024 Company Name. All rights reserved.</p>
345
+ </footer>
346
+ );
347
+ }
348
+ ```
349
+
350
+ ### Mobile-First Navigation
351
+
352
+ ```tsx
353
+ export default function MobileNav({ fieldValues }) {
354
+ return (
355
+ <nav style={{
356
+ display: 'flex',
357
+ flexDirection: 'column',
358
+ gap: '16px',
359
+ padding: '16px'
360
+ }}>
361
+ <a href="/">Home</a>
362
+ <a href="/about">About</a>
363
+ <a href="/contact">Contact</a>
364
+ <div style={{ borderTop: '1px solid #eee', paddingTop: '16px' }}>
365
+ <Island
366
+ module={LanguageSwitcherIsland}
367
+ textColor={fieldValues.textColor}
368
+ menuBackgroundColor={fieldValues.menuBackgroundColor}
369
+ />
370
+ </div>
371
+ </nav>
372
+ );
373
+ }
374
+ ```
375
+
376
+ ## Related Components
377
+
378
+ - **Drawer**: Used internally for the language selection panel. The LanguageSwitcher uses Drawer with direction="right" and handles open/close state.
379
+ - **Button**: Used for the trigger button and close button within the drawer.
380
+ - **Divider**: Used to separate the drawer header from language options.