@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.
- package/components/componentLibrary/Accordion/AccordionContent/ContentFields.tsx +5 -3
- package/components/componentLibrary/Accordion/AccordionItem/StyleFields.tsx +5 -3
- package/components/componentLibrary/Accordion/AccordionItem/index.module.scss +2 -2
- package/components/componentLibrary/Accordion/AccordionItem/index.tsx +3 -3
- package/components/componentLibrary/Accordion/AccordionTitle/ContentFields.tsx +5 -3
- package/components/componentLibrary/Accordion/AccordionTitle/index.module.scss +2 -2
- package/components/componentLibrary/Accordion/stories/Accordion.stories.tsx +80 -1
- package/components/componentLibrary/Accordion/stories/AccordionDecorator.tsx +14 -14
- package/components/componentLibrary/Button/ContentFields.tsx +5 -3
- package/components/componentLibrary/Button/StyleFields.tsx +5 -3
- package/components/componentLibrary/Button/index.module.scss +22 -14
- package/components/componentLibrary/Button/index.tsx +6 -6
- package/components/componentLibrary/Button/stories/Button.AsButton.stories.tsx +30 -1
- package/components/componentLibrary/Button/stories/Button.AsLink.stories.tsx +38 -1
- package/components/componentLibrary/Button/stories/ButtonDecorator.tsx +1 -1
- package/components/componentLibrary/Card/StyleFields.tsx +5 -3
- package/components/componentLibrary/Card/stories/Card.stories.tsx +46 -1
- package/components/componentLibrary/Card/stories/CardDecorator.tsx +1 -1
- package/components/componentLibrary/Divider/ContentFields.tsx +5 -3
- package/components/componentLibrary/Divider/StyleFields.tsx +5 -3
- package/components/componentLibrary/Divider/index.module.scss +6 -6
- package/components/componentLibrary/Divider/index.tsx +7 -3
- package/components/componentLibrary/Divider/stories/Divider.stories.tsx +44 -50
- package/components/componentLibrary/Divider/stories/{DividerDecorator.module.css → DividerDecorator.module.scss} +5 -4
- package/components/componentLibrary/Divider/stories/DividerDecorator.tsx +1 -1
- package/components/componentLibrary/Divider/types.ts +3 -1
- package/components/componentLibrary/Drawer/hooks/index.tsx +13 -0
- package/components/componentLibrary/Drawer/index.module.scss +94 -0
- package/components/componentLibrary/Drawer/index.tsx +131 -0
- package/components/componentLibrary/Drawer/llm.txt +416 -0
- package/components/componentLibrary/Drawer/stories/Drawer.stories.tsx +512 -0
- package/components/componentLibrary/Drawer/stories/DrawerDecorator.module.scss +8 -0
- package/components/componentLibrary/Drawer/stories/DrawerDecorator.tsx +18 -0
- package/components/componentLibrary/Drawer/types.ts +25 -0
- package/components/componentLibrary/Flex/stories/FlexDecorator.tsx +1 -1
- package/components/componentLibrary/Flex/types.ts +3 -1
- package/components/componentLibrary/Grid/stories/Grid.stories.tsx +454 -152
- package/components/componentLibrary/Grid/stories/GridDecorator.tsx +2 -2
- package/components/componentLibrary/Heading/ContentFields.tsx +5 -3
- package/components/componentLibrary/Heading/StyleFields.tsx +11 -9
- package/components/componentLibrary/Heading/index.tsx +3 -3
- package/components/componentLibrary/Heading/llm.txt +8 -8
- package/components/componentLibrary/Heading/stories/Heading.stories.tsx +3 -3
- package/components/componentLibrary/Heading/stories/HeadingDecorator.tsx +1 -1
- package/components/componentLibrary/Heading/types.ts +4 -4
- package/components/componentLibrary/Icon/ContentFields.tsx +5 -3
- package/components/componentLibrary/Icon/stories/Icon.stories.tsx +1 -1
- package/components/componentLibrary/Icon/stories/IconDecorator.tsx +1 -1
- package/components/componentLibrary/Image/ContentFields.tsx +5 -3
- package/components/componentLibrary/Image/index.tsx +4 -4
- package/components/componentLibrary/Image/llm.txt +17 -17
- package/components/componentLibrary/Image/stories/Image.stories.tsx +61 -18
- package/components/componentLibrary/Image/stories/ImageDecorator.tsx +1 -1
- package/components/componentLibrary/Image/types.ts +2 -2
- package/components/componentLibrary/LanguageSwitcher/ContentFields.tsx +18 -0
- package/components/componentLibrary/LanguageSwitcher/LanguageOptions.module.scss +37 -0
- package/components/componentLibrary/LanguageSwitcher/LanguageOptions.tsx +65 -0
- package/components/componentLibrary/LanguageSwitcher/StyleFields.tsx +48 -0
- package/components/componentLibrary/LanguageSwitcher/_dummyData.tsx +247 -0
- package/components/componentLibrary/LanguageSwitcher/assets/Globe.tsx +16 -0
- package/components/componentLibrary/LanguageSwitcher/index.module.scss +58 -0
- package/components/componentLibrary/LanguageSwitcher/index.tsx +125 -0
- package/components/componentLibrary/LanguageSwitcher/llm.txt +380 -0
- package/components/componentLibrary/LanguageSwitcher/stories/LanguageSwitcher.stories.tsx +349 -0
- package/components/componentLibrary/LanguageSwitcher/stories/LanguageSwitcherDecorator.module.scss +5 -0
- package/components/componentLibrary/LanguageSwitcher/stories/LanguageSwitcherDecorator.tsx +8 -0
- package/components/componentLibrary/LanguageSwitcher/types.ts +48 -0
- package/components/componentLibrary/LanguageSwitcher/utils.tsx +38 -0
- package/components/componentLibrary/Link/ContentFields.tsx +5 -3
- package/components/componentLibrary/Link/StyleFields.tsx +5 -3
- package/components/componentLibrary/Link/index.module.scss +10 -0
- package/components/componentLibrary/Link/index.tsx +24 -14
- package/components/componentLibrary/Link/stories/Link.stories.tsx +35 -5
- package/components/componentLibrary/Link/stories/LinkDecorator.tsx +11 -1
- package/components/componentLibrary/Link/types.ts +22 -13
- package/components/componentLibrary/List/ContentFields.tsx +5 -3
- package/components/componentLibrary/List/ListItem/ContentFields.tsx +6 -17
- package/components/componentLibrary/List/ListItem/index.module.scss +1 -13
- package/components/componentLibrary/List/ListItem/index.tsx +3 -30
- package/components/componentLibrary/List/ListItem/types.ts +1 -16
- package/components/componentLibrary/List/StyleFields.tsx +15 -18
- package/components/componentLibrary/List/index.module.scss +3 -0
- package/components/componentLibrary/List/index.tsx +5 -2
- package/components/componentLibrary/List/llm.txt +73 -103
- package/components/componentLibrary/List/stories/List.stories.tsx +56 -80
- package/components/componentLibrary/List/stories/ListDecorator.tsx +3 -6
- package/components/componentLibrary/List/types.ts +1 -3
- package/components/componentLibrary/Logo/_dummyLogoData.ts +12 -0
- package/components/componentLibrary/Logo/assets/hubspot-logo.png +0 -0
- package/components/componentLibrary/Logo/index.module.scss +22 -0
- package/components/componentLibrary/Logo/index.tsx +73 -0
- package/components/componentLibrary/Logo/llm.txt +262 -0
- package/components/componentLibrary/Logo/stories/Logo.stories.tsx +88 -0
- package/components/componentLibrary/Logo/stories/LogoDecorator.module.scss +10 -0
- package/components/componentLibrary/Logo/stories/LogoDecorator.tsx +8 -0
- package/components/componentLibrary/Logo/types.tsx +16 -0
- package/components/componentLibrary/Menu/ContentFields.tsx +16 -0
- package/components/componentLibrary/Menu/MenuItem/Chevron/index.module.scss +6 -0
- package/components/componentLibrary/Menu/MenuItem/Chevron/index.tsx +17 -0
- package/components/componentLibrary/Menu/MenuItem/index.module.scss +7 -0
- package/components/componentLibrary/Menu/MenuItem/index.tsx +266 -0
- package/components/componentLibrary/Menu/MenuItem/types.ts +17 -0
- package/components/componentLibrary/Menu/NavigationMenu/ContentFields.tsx +20 -0
- package/components/componentLibrary/Menu/NavigationMenu/index.tsx +18 -0
- package/components/componentLibrary/Menu/NavigationMenu/islands/NavigationMenuIsland.tsx +95 -0
- package/components/componentLibrary/Menu/NavigationMenu/islands/index.module.scss +100 -0
- package/components/componentLibrary/Menu/NavigationMenu/islands/types.ts +19 -0
- package/components/componentLibrary/Menu/NavigationMenu/llm.txt +197 -0
- package/components/componentLibrary/Menu/NavigationMenu/stories/NavigationMenu.stories.tsx +286 -0
- package/components/componentLibrary/Menu/NavigationMenu/stories/NavigationMenuDecorator.module.scss +15 -0
- package/components/componentLibrary/Menu/NavigationMenu/stories/NavigationMenuDecorator.tsx +12 -0
- package/components/componentLibrary/Menu/NavigationMenu/types.ts +3 -0
- package/components/componentLibrary/Menu/VerticalMenu/ContentFields.tsx +20 -0
- package/components/componentLibrary/Menu/VerticalMenu/index.tsx +18 -0
- package/components/componentLibrary/Menu/VerticalMenu/islands/index.module.scss +53 -0
- package/components/componentLibrary/Menu/VerticalMenu/islands/verticalMenuIsland.tsx +78 -0
- package/components/componentLibrary/Menu/VerticalMenu/llm.txt +177 -0
- package/components/componentLibrary/Menu/VerticalMenu/stories/VerticalMenu.stories.tsx +242 -0
- package/components/componentLibrary/Menu/VerticalMenu/stories/VerticalMenuDecorator.module.scss +19 -0
- package/components/componentLibrary/Menu/VerticalMenu/stories/VerticalMenuDecorator.tsx +12 -0
- package/components/componentLibrary/Menu/VerticalMenu/types.ts +21 -0
- package/components/componentLibrary/Menu/_dummyMenuData.js +1346 -0
- package/components/componentLibrary/Menu/types.ts +56 -0
- package/components/componentLibrary/Menu/utils/transformMenuData.ts +11 -0
- package/components/componentLibrary/_patterns/README.md +15 -17
- package/components/componentLibrary/_patterns/checklist-and-examples.md +17 -17
- package/components/componentLibrary/_patterns/component-structure.md +21 -23
- package/components/componentLibrary/_patterns/css-patterns.md +170 -18
- package/components/componentLibrary/_patterns/field-patterns.md +97 -27
- package/components/componentLibrary/_patterns/function-declaration-patterns.md +281 -0
- package/components/componentLibrary/_patterns/llm-txt.template.md +4 -2
- package/components/componentLibrary/_patterns/prop-naming-patterns.md +208 -0
- package/components/componentLibrary/_patterns/storybook-patterns.md +25 -8
- package/components/componentLibrary/_patterns/typescript-patterns.md +6 -3
- package/package.json +4 -2
- /package/components/componentLibrary/Button/stories/{ButtonDecorator.module.css → ButtonDecorator.module.scss} +0 -0
- /package/components/componentLibrary/Card/stories/{CardDecorator.module.css → CardDecorator.module.scss} +0 -0
- /package/components/componentLibrary/Flex/stories/{FlexDecorator.module.css → FlexDecorator.module.scss} +0 -0
- /package/components/componentLibrary/Grid/stories/{GridDecorator.module.css → GridDecorator.module.scss} +0 -0
- /package/components/componentLibrary/Heading/stories/{HeadingDecorator.module.css → HeadingDecorator.module.scss} +0 -0
- /package/components/componentLibrary/Icon/stories/{IconDecorator.module.css → IconDecorator.module.scss} +0 -0
- /package/components/componentLibrary/Image/stories/{ImageDecorator.module.css → ImageDecorator.module.scss} +0 -0
- /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.
|