@hortonstudio/main 1.9.6 → 1.9.8

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 (32) hide show
  1. package/autoInit/accessibility/README.md +94 -0
  2. package/autoInit/accessibility/accessibility.js +52 -0
  3. package/autoInit/accessibility/functions/blog-remover/README.md +61 -0
  4. package/autoInit/accessibility/functions/blog-remover/blog-remover.js +31 -0
  5. package/autoInit/accessibility/functions/click-forwarding/README.md +60 -0
  6. package/autoInit/accessibility/functions/click-forwarding/click-forwarding.js +82 -0
  7. package/autoInit/accessibility/functions/dropdown/README.md +212 -0
  8. package/autoInit/accessibility/functions/dropdown/dropdown.js +167 -0
  9. package/autoInit/accessibility/functions/list-accessibility/README.md +56 -0
  10. package/autoInit/accessibility/functions/list-accessibility/list-accessibility.js +23 -0
  11. package/autoInit/accessibility/functions/text-synchronization/README.md +62 -0
  12. package/autoInit/accessibility/functions/text-synchronization/text-synchronization.js +101 -0
  13. package/autoInit/accessibility/functions/toc/README.md +79 -0
  14. package/autoInit/accessibility/functions/toc/toc.js +191 -0
  15. package/autoInit/accessibility/functions/year-replacement/README.md +54 -0
  16. package/autoInit/accessibility/functions/year-replacement/year-replacement.js +43 -0
  17. package/autoInit/button/README.md +122 -0
  18. package/autoInit/counter/README.md +274 -0
  19. package/autoInit/{counter.js → counter/counter.js} +20 -5
  20. package/autoInit/form/README.md +338 -0
  21. package/autoInit/{form.js → form/form.js} +44 -29
  22. package/autoInit/navbar/README.md +366 -0
  23. package/autoInit/site-settings/README.md +218 -0
  24. package/autoInit/smooth-scroll/README.md +386 -0
  25. package/autoInit/transition/README.md +301 -0
  26. package/autoInit/{transition.js → transition/transition.js} +13 -2
  27. package/index.js +7 -7
  28. package/package.json +1 -1
  29. package/autoInit/accessibility.js +0 -786
  30. /package/autoInit/{button.js → button/button.js} +0 -0
  31. /package/autoInit/{site-settings.js → site-settings/site-settings.js} +0 -0
  32. /package/autoInit/{smooth-scroll.js → smooth-scroll/smooth-scroll.js} +0 -0
@@ -0,0 +1,366 @@
1
+ # **Navbar System Documentation**
2
+
3
+ ## **Webflow IX3 Notes**
4
+
5
+ When an element only has a click toggle/reverse trigger, it also works with enter/space. If it has click toggle/reverse AND hover triggers, it doesn't work with space but it does with enter.
6
+
7
+ ---
8
+
9
+ # **Navbar Setup Guide**
10
+
11
+ ## **Overview**
12
+
13
+ The navbar system uses Webflow IX3 interactions to manage visual states (`.is-active` class) while JavaScript automatically syncs ARIA attributes, keyboard navigation, and focus management.
14
+
15
+ ## **Required Structure**
16
+
17
+ ### **Navbar Setup**
18
+
19
+ Add **data-hs-nav="wrapper"** to the main wrapper of the navbar, e.g. the `<nav>` element.
20
+
21
+ **What it does:** Container for all navbar functionality. Used for arrow key navigation scope.
22
+
23
+ ---
24
+
25
+ ## **Navbar Dropdown List**
26
+
27
+ ### **Required Elements**
28
+
29
+ **Button Wrapper** *(wraps the button and dropdown list)*
30
+
31
+ * data-hs-nav="dropdown"
32
+
33
+ **Toggle Button** *(the wrapper of the actual button/link that opens/closes the dropdown list)*
34
+
35
+ * data-site-clickable="element"
36
+ * The Global / Clickable component already has this set
37
+
38
+ **Dropdown List** *(main wrapper of the list)*
39
+
40
+ * data-hs-nav="dropdown-list"
41
+
42
+ **Dropdown List Items**
43
+
44
+ * data-site-clickable="element"
45
+ * If using webflow framework, this is auto set with Global / Button and their respective Global / Clickable
46
+
47
+ **Typical element layout:**
48
+
49
+ 1. Button Wrapper (data-hs-nav="dropdown")
50
+ 1. Button Content
51
+ 1. Clickable Component (data-site-clickable="element")
52
+ 1. Toggle Button
53
+ 2. Dropdown List Component Slot
54
+ 1. Dropdown List
55
+ 1. Dropdown list items
56
+
57
+ ### **Interaction Requirements (IX3)**
58
+
59
+ **Triggers:**
60
+
61
+ 1. **Hover Trigger** on `[data-hs-nav="dropdown"]`
62
+ 1. `Mouse Enter -> Each Mouse Enter: Play`
63
+ 2. **Hover Trigger** on `[data-hs-nav="dropdown"]`
64
+ 1. `Mouse Leave -> Each Mouse Leave: Reverse`
65
+ 3. **Click Trigger** on `[data-hs-nav="dropdown"]`
66
+ 1. `Each click: Toggle play/reverse`
67
+ 4. **Add class** `.is-active` to wrapper on hover in
68
+ 5. **Remove class** `.is-active` on hover out
69
+
70
+ **Timeline requirements:**
71
+
72
+ 1. 0s: Toggle is-active class on the trigger element
73
+ 2. 0s: From: Display: none | To: Display: flex on the element you will be animating to open
74
+ 3. .06s: Rest of animation
75
+
76
+ ### **What It Does**
77
+
78
+ 1. **Keyboard navigation:** ArrowDown/ArrowUp/Space open dropdown, Escape closes
79
+ 2. **Focus management:** Auto-focuses first item on open, returns focus to toggle on close
80
+ 3. **ARIA sync:** Watches `.is-active` class, updates `aria-expanded` and `aria-hidden`
81
+ 4. **Arrow navigation:** Navigate items with ArrowDown/ArrowUp when open
82
+
83
+ ### **Notes**
84
+
85
+ 1. Using Global / Button is preferred for this system. For attribute adding, use this component props:
86
+ 1. Attribute 1 Name: set to “data-hs-nav”
87
+ 2. Attribute 1 Value: set to “dropdown”
88
+ 2. `[data-site-clickable="element"]` Is set up by default in the Global / Clickable component
89
+ 1. Toggle is the **first child** of `[data-site-clickable="element"]`
90
+ 2. Items must use same `[data-site-clickable="element"]` pattern
91
+ 3. Enter key navigates the toggle link (default behavior)
92
+
93
+ ---
94
+
95
+ ## **Mobile Menu**
96
+
97
+ ### **Required Elements**
98
+
99
+ **Menu Button** *(the wrapper of the actual button)*
100
+
101
+ * data-site-clickable="element"
102
+ * This one does not use the Global / Clickable component
103
+ * This is not required for the actual menu functionality, but for the arrow navigation throughout the Navbar
104
+
105
+ **Menu Button Element** *(the actual button)*
106
+
107
+ * data-hs-nav="menu-button"
108
+
109
+ **Menu** *(main wrapper of the menu)*
110
+
111
+ * data-hs-nav="menu"
112
+
113
+ **Menu Items**
114
+
115
+ * data-site-clickable="element"
116
+ * If using webflow framework, this is auto set with Global / Button and their respective Global / Clickable
117
+
118
+ **Breakpoint Indicator**
119
+
120
+ * This element wraps the Menu (main wrapper)
121
+ * Requires: data-hs-nav="menu-hide"
122
+
123
+ **Typical element layout:**
124
+
125
+ 1. Navbar Component (data-hs-nav=”wrapper”)
126
+ 1. Announce Bar
127
+ 1. Buttons
128
+ 2. Navbar Wrap
129
+ 1. Navbar Container
130
+ 1. Buttons
131
+ 2. Menu Button Wrapper (data-site-clickable="element")
132
+ 1. Menu Button (data-hs-nav="menu-button")
133
+ 2. Menu Hide (data-hs-nav=”menu-hide”)
134
+ 1. Menu (data-hs-nav="menu")
135
+ 1. Menu Items (elements with data-site-clickable="element")
136
+ 1. Typically Global / Button components, auto set attributes
137
+
138
+ ### **Interaction Requirements (IX3)**
139
+
140
+ #### Triggers:
141
+
142
+ 1. **Click trigger** on `[data-hs-nav="menu-button"]`
143
+ 1. `Toggle play/reverse`
144
+
145
+ #### Timeline:
146
+
147
+ 1. 0s: Toggle is-active class on the trigger element
148
+ 2. 0s: From: Display: none | To: Display: flex on the element you will be animating to open
149
+ 3. .06s: Rest of animation
150
+
151
+ ### **What It Does**
152
+
153
+ 1. **ARIA sync:** Watches `.is-active` on button, updates `aria-expanded`
154
+ 2. **Body overflow:** Adds `u-overflow-hidden` class to body when open
155
+ 1. If the site uses Lenis scrolling, this code triggers start and top so it works with lenis properly.
156
+ 3. **Focus trap:** Traps tab key within navbar when menu open
157
+ 4. **Auto-focus:** Focuses first menu item on open
158
+ 5. **Focus return:** Returns focus to button on close
159
+ 6. **Arrow navigation:** ArrowDown/ArrowUp navigate through all visible items
160
+
161
+ ### **Breakpoint Indicator (`menu-hide`)**
162
+
163
+ **CSS pattern (typically add data-responsive=”desktop/mobile” to the menu-hide element):**
164
+
165
+ /\* Mobile styles (default) \*/
166
+
167
+ \[data-responsive="desktop"\] { display: none\!important; }
168
+
169
+ \[data-responsive="mobile"\] { display: flex\!important; }
170
+
171
+ /\* Desktop styles \*/
172
+
173
+ @media (width \> 63em) {
174
+
175
+ \[data-responsive="desktop"\] { display: flex\!important; }
176
+
177
+ \[data-responsive="mobile"\] { display: none\!important; }
178
+
179
+ }
180
+
181
+ **What it does:** JavaScript checks if this element is visible to enable/disable menu button functionality at different breakpoints.
182
+
183
+ ---
184
+
185
+ ## **Mobile Menu Dropdown**
186
+
187
+ ### **Required Elements**
188
+
189
+ **Dropdown Wrapper**
190
+
191
+ * data-hs-nav="menu-dropdown"
192
+
193
+ **Dropdown Toggle Button** *(the wrapper of the actual button)*
194
+
195
+ * data-site-clickable="element"
196
+ * The Global / Clickable component already has this set
197
+
198
+ **Dropdown List** *(main wrapper of the list)*
199
+
200
+ * data-hs-nav="menu-dropdown-list"
201
+
202
+ **Dropdown List Items**
203
+
204
+ * data-site-clickable="element"
205
+ * If using webflow framework, this is auto set with Global / Button and their respective Global / Clickable
206
+
207
+ **Typical element layout:**
208
+
209
+ 1. Dropdown Wrapper (data-hs-nav="menu-dropdown")
210
+ 1. Button Wrapper (data-site-clickable="element")
211
+ 1. Toggle Button
212
+ 2. Dropdown List (data-hs-nav="menu-dropdown-list")
213
+ 1. List Items (data-site-clickable="element")
214
+ 1. Links or Buttons
215
+
216
+ ### **Interaction Requirements (IX3)**
217
+
218
+ #### Triggers:
219
+
220
+ 1. **Click trigger** on Dropdown Wrapper `[data-hs-nav="menu-dropdown"]`
221
+ 1. `Toggle play/reverse`
222
+
223
+ #### Timeline:
224
+
225
+ 1. 0s: Toggle is-active class on the trigger element
226
+ 2. 0s: From: Display: none | To: Display: flex on the element you will be animating to open
227
+ 3. .06s: Rest of animation
228
+
229
+ ### **What It Does**
230
+
231
+ 1. **ARIA sync:** Watches `.is-active` on wrapper, updates `aria-expanded` and `aria-hidden`
232
+ 2. **Focus return:** Returns focus to button when closing (if focus was inside list)
233
+ 3. **Arrow integration:** Items automatically included in menu arrow navigation when open (filtered when closed via `aria-hidden`)
234
+
235
+ ### **Notes**
236
+
237
+ 1. Using Global / Button is preferred for this system. For attribute adding, use this component props:
238
+ 1. Attribute 1 Name: set to “data-hs-nav”
239
+ 2. Attribute 1 Value: set to “menu-dropdown”
240
+ 2. Items inside closed dropdown lists are filtered from arrow navigation
241
+ 3. Uses same `[data-site-clickable="element"]` pattern as desktop
242
+ 4. Button is **first child** of clickable wrapper
243
+
244
+ ---
245
+
246
+ ## **Skip Link (Optional)**
247
+
248
+ **What it does:** When using a skip link, add these attributes so the system ignores it for arrow navigation.
249
+
250
+ ### **Required Elements**
251
+
252
+ **Skip Link Wrapper**
253
+
254
+ * data-hs-nav="skip-link"
255
+
256
+ ---
257
+
258
+ ## **Clickable Element Pattern**
259
+
260
+ **All interactive elements** (buttons, links) must follow this pattern:
261
+
262
+ **For Links:**
263
+
264
+ 1. Clickable Wrapper (data-site-clickable="element")
265
+ 1. Link Element
266
+
267
+ **For Buttons:**
268
+
269
+ 1. Clickable Wrapper (data-site-clickable="element")
270
+ 1. Button Element
271
+
272
+ **Why:** JavaScript queries `[data-site-clickable="element"]` then gets `.children[0]` to find the actual interactive element. This allows wrapping for styling while maintaining consistent selection.
273
+
274
+ This is for arrow navigation and proper accessibility labelling
275
+
276
+ ---
277
+
278
+ ## **Key Attributes Summary**
279
+
280
+ | Attribute | Purpose | Required On |
281
+ | ----- | ----- | ----- |
282
+ | `data-hs-nav="wrapper"` | Navbar container | `<nav>` |
283
+ | `data-hs-nav="dropdown"` | Desktop dropdown wrapper | Wrapper div |
284
+ | `data-hs-nav="dropdown-list"` | Desktop dropdown content | Content div |
285
+ | `data-hs-nav="menu-button"` | Mobile menu toggle | `<button>` |
286
+ | `data-hs-nav="menu"` | Mobile menu container | Menu div |
287
+ | `data-hs-nav="menu-hide"` | Breakpoint indicator | Any element |
288
+ | `data-hs-nav="menu-dropdown"` | Mobile dropdown wrapper | Wrapper div |
289
+ | `data-hs-nav="menu-dropdown-list"` | Mobile dropdown content | Content div |
290
+ | `data-site-clickable="element"` | Interactive element wrapper | Wrapper div |
291
+ | `data-hs-nav="skip-link"` | Skip link container | Wrapper div (optional) |
292
+
293
+ ---
294
+
295
+ ## **Webflow Class Requirements**
296
+
297
+ ### **`.is-active` class**
298
+
299
+ Must be added/removed by Webflow interactions on:
300
+
301
+ 1. Desktop dropdown wrapper (`[data-hs-nav="dropdown"]`)
302
+ 2. Mobile menu button (`[data-hs-nav="menu-button"]`)
303
+ 3. Mobile menu dropdown wrapper (`[data-hs-nav="menu-dropdown"]`)
304
+
305
+ JavaScript watches for this class and syncs ARIA/behavior accordingly.
306
+
307
+ ### **`.u-overflow-hidden` class**
308
+
309
+ Applied to `<body>` by JavaScript when the menu is open. Style accordingly:
310
+
311
+ .u-overflow-hidden { overflow: hidden; }
312
+
313
+ ---
314
+
315
+ ## **Keyboard Navigation**
316
+
317
+ ### **Desktop Dropdown (when focused on toggle)**
318
+
319
+ 1. **ArrowDown** → Open dropdown, focus first item
320
+ 2. **ArrowUp** → Open dropdown, focus last item
321
+ 3. **Space** → Open/close dropdown
322
+ 4. **Escape** → Close dropdown
323
+ 5. **Enter** → Navigate to toggle link href
324
+
325
+ ### **Desktop Dropdown (when inside)**
326
+
327
+ 1. **ArrowDown** → Next item
328
+ 2. **ArrowUp** → Previous item (or close if on first item)
329
+ 3. **Escape** → Close dropdown, return focus to toggle
330
+
331
+ ### **Desktop Navbar**
332
+
333
+ 1. **ArrowLeft/ArrowRight** → Navigate between navbar elements
334
+
335
+ ### **Mobile Menu**
336
+
337
+ 1. **ArrowDown/ArrowUp** → Navigate through all visible items
338
+ 2. **ArrowLeft** → Collapse dropdown (when on dropdown button)
339
+ 3. **ArrowRight** → Expand dropdown (when on dropdown button)
340
+ 4. **Home/End** → First/last item
341
+ 5. **Escape** → Close menu
342
+
343
+ ---
344
+
345
+ ## **Common Issues**
346
+
347
+ **Items not navigable with arrow keys:**
348
+
349
+ 1. Ensure items use `[data-site-clickable="element"]` wrapper
350
+ 2. Check that first child is the actual button/link
351
+
352
+ **Dropdown not syncing ARIA:**
353
+
354
+ 1. Verify Webflow interaction adds/removes `.is-active` class
355
+ 2. Check class is on correct element (wrapper for dropdowns, button for menu)
356
+
357
+ **Tab goes into hidden dropdowns:**
358
+
359
+ 1. Ensure Webflow interaction uses `display: none` or `visibility: hidden` when closed
360
+ 2. Or verify `.is-active` class is being removed properly
361
+
362
+ **Menu button doesn't work at desktop:**
363
+
364
+ 1. Check `[data-hs-nav="menu-hide"]` has correct responsive CSS
365
+ 2. Element should be `display: none` at desktop breakpoint
366
+
@@ -0,0 +1,218 @@
1
+ # **Site Settings System Documentation**
2
+
3
+ ## **Overview**
4
+
5
+ The site settings system collects dynamic values from designated elements and replaces placeholder text (`{{name}}`) throughout the entire page. This allows for centralized content management where values can be defined once and used multiple times across text and links.
6
+
7
+ ---
8
+
9
+ ## **Site Settings**
10
+
11
+ ### **Required Elements**
12
+
13
+ **Settings Wrapper** *(container for all settings lists)*
14
+
15
+ * data-site-settings-element="wrapper"
16
+
17
+ **Settings List** *(can have multiple lists inside wrapper)*
18
+
19
+ * data-site-settings-element="list"
20
+
21
+ **Setting Element** *(individual setting with a name and value)*
22
+
23
+ * data-site-settings="name"
24
+ * The attribute value is the placeholder name (e.g., "company", "email", "phone")
25
+ * The element's text content is the value to replace
26
+
27
+ **Typical element layout:**
28
+
29
+ 1. Settings Wrapper (data-site-settings-element="wrapper")
30
+ 1. Settings List (data-site-settings-element="list")
31
+ 1. Setting Element (data-site-settings="company")
32
+ 1. Text: "Compass Facilities"
33
+ 2. Setting Element (data-site-settings="email")
34
+ 1. Text: "info@compass.com"
35
+ 3. Setting Element (data-site-settings="phone")
36
+ 1. Text: "555-1234"
37
+
38
+ ### **What It Does**
39
+
40
+ 1. **Collects settings** - Finds all elements with `[data-site-settings]` and stores their text values
41
+ 2. **Ignores empty elements** - Elements without text (like images) are skipped
42
+ 3. **Replaces text placeholders** - Finds all `{{name}}` in page text and replaces with values
43
+ 4. **Replaces link placeholders** - Finds all `{{name}}` in link hrefs and replaces with values
44
+
45
+ ### **When It Runs**
46
+
47
+ * Runs once on page load
48
+ * Runs again on Barba.js page transitions (via `reinitialize()`)
49
+ * No ongoing monitoring or event listeners
50
+
51
+ ---
52
+
53
+ ## **Conditional Hide Feature**
54
+
55
+ ### **Optional Hide Attribute**
56
+
57
+ **Hide Element** *(removes content conditionally before extracting text)*
58
+
59
+ * data-site-settings-hide="class-name"
60
+ * Can specify multiple classes separated by spaces
61
+ * Element is removed if it has ANY of the specified classes
62
+
63
+ ### **Example Use Case**
64
+
65
+ For dynamic content where certain parts should be hidden based on CMS conditions:
66
+
67
+ ```html
68
+ <div data-site-settings="address">
69
+ <!-- Hidden by Webflow CMS condition -->
70
+ <span class="w-condition-invisible" data-site-settings-hide="w-condition-invisible">
71
+ <span>Suite 200</span>
72
+ <span>, </span>
73
+ </span>
74
+
75
+ <!-- Always visible -->
76
+ <span>Rockwall</span>
77
+ <span>, </span>
78
+ <span>Texas</span>
79
+ <span> 75087</span>
80
+ </div>
81
+ ```
82
+
83
+ **Result:** If the span has class `w-condition-invisible`, it's removed before extracting text. Final value: "Rockwall, Texas 75087"
84
+
85
+ ### **How It Works**
86
+
87
+ 1. Clones element to avoid modifying original DOM
88
+ 2. Finds all descendants with `[data-site-settings-hide]`
89
+ 3. Checks if element has any matching classes
90
+ 4. Removes matching elements from clone
91
+ 5. Extracts text from cleaned clone
92
+
93
+ ---
94
+
95
+ ## **Usage Examples**
96
+
97
+ ### **Define Settings**
98
+
99
+ ```html
100
+ <div data-site-settings-element="wrapper" style="display: none;">
101
+ <div data-site-settings-element="list">
102
+ <div data-site-settings="company">Compass Facilities</div>
103
+ <div data-site-settings="email">info@compass.com</div>
104
+ <div data-site-settings="phone">555-1234</div>
105
+ <div data-site-settings="address">123 Main St, Dallas, TX 75001</div>
106
+ </div>
107
+ </div>
108
+ ```
109
+
110
+ **Note:** The wrapper is typically hidden with `display: none` since it's only for data storage.
111
+
112
+ ### **Use Settings in Text**
113
+
114
+ ```html
115
+ <h1>Welcome to {{company}}</h1>
116
+ <p>Contact us at {{email}} or call {{phone}}</p>
117
+ <p>Visit us at {{address}}</p>
118
+ ```
119
+
120
+ **Result:**
121
+ ```html
122
+ <h1>Welcome to Compass Facilities</h1>
123
+ <p>Contact us at info@compass.com or call 555-1234</p>
124
+ <p>Visit us at 123 Main St, Dallas, TX 75001</p>
125
+ ```
126
+
127
+ ### **Use Settings in Links**
128
+
129
+ ```html
130
+ <a href="mailto:{{email}}">Email Us</a>
131
+ <a href="tel:{{phone}}">Call Us</a>
132
+ <a href="https://maps.google.com/?q={{address}}">Get Directions</a>
133
+ ```
134
+
135
+ **Result:**
136
+ ```html
137
+ <a href="mailto:info@compass.com">Email Us</a>
138
+ <a href="tel:555-1234">Call Us</a>
139
+ <a href="https://maps.google.com/?q=123 Main St, Dallas, TX 75001">Get Directions</a>
140
+ ```
141
+
142
+ ---
143
+
144
+ ## **Multiple Lists**
145
+
146
+ You can have multiple lists inside the wrapper for organization:
147
+
148
+ ```html
149
+ <div data-site-settings-element="wrapper">
150
+ <!-- Contact info -->
151
+ <div data-site-settings-element="list">
152
+ <div data-site-settings="email">info@compass.com</div>
153
+ <div data-site-settings="phone">555-1234</div>
154
+ </div>
155
+
156
+ <!-- Company info -->
157
+ <div data-site-settings-element="list">
158
+ <div data-site-settings="company">Compass Facilities</div>
159
+ <div data-site-settings="established">2020</div>
160
+ </div>
161
+ </div>
162
+ ```
163
+
164
+ All settings are collected regardless of which list they're in.
165
+
166
+ ---
167
+
168
+ ## **Key Attributes Summary**
169
+
170
+ | Attribute | Purpose | Required On |
171
+ | ----- | ----- | ----- |
172
+ | `data-site-settings-element="wrapper"` | Settings container | Wrapper div |
173
+ | `data-site-settings-element="list"` | Settings list | List div (at least one) |
174
+ | `data-site-settings="name"` | Setting with name | Individual setting elements |
175
+ | `data-site-settings-hide="class"` | Conditional hide | Optional (inside setting elements) |
176
+
177
+ ---
178
+
179
+ ## **Placeholder Syntax**
180
+
181
+ **Format:** `{{name}}`
182
+
183
+ * Double curly braces
184
+ * Name must match the `data-site-settings` attribute value exactly
185
+ * Case-sensitive
186
+ * Works in text content and link hrefs
187
+
188
+ ---
189
+
190
+ ## **Notes**
191
+
192
+ 1. **Empty elements ignored** - Elements without text (images, empty divs) are skipped
193
+ 2. **No visual component** - Settings wrapper should be hidden with CSS
194
+ 3. **Page-wide replacement** - Placeholders are replaced throughout entire page
195
+ 4. **Multiple replacements** - Same placeholder can be used unlimited times
196
+ 5. **Barba.js compatible** - Automatically reinitializes on page transitions
197
+
198
+ ---
199
+
200
+ ## **Common Issues**
201
+
202
+ **Placeholder not replacing:**
203
+
204
+ 1. Verify `data-site-settings` attribute matches placeholder name exactly
205
+ 2. Check that setting element has text content
206
+ 3. Ensure double curly braces: `{{name}}` not `{name}` or `{{ name }}`
207
+
208
+ **Wrong value appearing:**
209
+
210
+ 1. Check for duplicate setting names (last one wins)
211
+ 2. Verify conditional hide elements are working correctly
212
+ 3. Inspect the settings wrapper to confirm expected text
213
+
214
+ **Links not working:**
215
+
216
+ 1. Ensure placeholder syntax is correct in href attribute
217
+ 2. Check that value is URL-safe (encode special characters if needed)
218
+ 3. For tel: links, ensure phone number has no spaces or dashes in setting value