@hortonstudio/main 1.9.10 → 1.9.20

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 (124) hide show
  1. package/.prettierrc +8 -0
  2. package/README.md +146 -0
  3. package/eslint.config.js +32 -0
  4. package/index.ts +275 -0
  5. package/package.json +19 -2
  6. package/public/bootstrap.js +16 -0
  7. package/src/animations/animations.ts +93 -0
  8. package/src/animations/functions/counter/counter.ts +137 -0
  9. package/src/config.json +570 -0
  10. package/src/config.ts +105 -0
  11. package/src/modules/default/README.md +167 -0
  12. package/src/modules/default/default.ts +71 -0
  13. package/{autoInit → src/modules/default/functions}/accessibility/README.md +44 -12
  14. package/src/modules/default/functions/accessibility/accessibility.ts +54 -0
  15. package/src/modules/default/functions/accordion/README.md +451 -0
  16. package/src/modules/default/functions/accordion/accordion.ts +189 -0
  17. package/src/modules/default/functions/comparison/comparison.ts +424 -0
  18. package/src/modules/default/functions/marquee/marquee.ts +206 -0
  19. package/src/modules/default/functions/navbar/README.md +393 -0
  20. package/src/modules/default/functions/navbar/functions/arrow-navigation/arrow-navigation.ts +183 -0
  21. package/src/modules/default/functions/navbar/functions/dropdown/dropdown.ts +313 -0
  22. package/src/modules/default/functions/navbar/functions/menu/menu.ts +315 -0
  23. package/src/modules/default/functions/navbar/navbar.ts +51 -0
  24. package/{autoInit → src/modules/default/functions}/smooth-scroll/README.md +45 -14
  25. package/{autoInit/smooth-scroll/smooth-scroll.js → src/modules/default/functions/smooth-scroll/smooth-scroll.ts} +33 -38
  26. package/{autoInit → src/modules/default/functions}/transition/README.md +59 -32
  27. package/src/modules/default/functions/transition/transition.ts +290 -0
  28. package/src/modules/normalize/README.md +172 -0
  29. package/src/modules/normalize/functions/clickable/README.md +84 -0
  30. package/src/modules/normalize/functions/clickable/clickable.ts +43 -0
  31. package/src/modules/normalize/functions/clickable/functions/normalize/README.md +213 -0
  32. package/src/modules/normalize/functions/clickable/functions/normalize/normalize.ts +68 -0
  33. package/src/modules/normalize/functions/dupe/README.md +405 -0
  34. package/src/modules/normalize/functions/dupe/dupe.ts +197 -0
  35. package/src/modules/normalize/functions/sync/sync.ts +378 -0
  36. package/src/modules/normalize/normalize.ts +58 -0
  37. package/src/modules/structure/README.md +190 -0
  38. package/src/modules/structure/functions/form/README.md +94 -0
  39. package/src/modules/structure/functions/form/form.ts +54 -0
  40. package/src/modules/structure/functions/form/functions/honeypot/README.md +77 -0
  41. package/src/modules/structure/functions/form/functions/honeypot/honeypot.ts +37 -0
  42. package/src/modules/structure/functions/form/functions/range/README.md +410 -0
  43. package/src/modules/structure/functions/form/functions/range/range.ts +92 -0
  44. package/src/modules/structure/functions/form/functions/select/README.md +393 -0
  45. package/src/modules/structure/functions/form/functions/select/functions/custom-select/custom-select.ts +637 -0
  46. package/src/modules/structure/functions/form/functions/select/functions/states/states.ts +118 -0
  47. package/src/modules/structure/functions/form/functions/select/select.ts +48 -0
  48. package/src/modules/structure/functions/form/functions/test/test.ts +132 -0
  49. package/src/modules/structure/functions/pagination/README.md +527 -0
  50. package/src/modules/structure/functions/pagination/pagination.ts +493 -0
  51. package/src/modules/structure/functions/site-settings/README.md +395 -0
  52. package/src/modules/structure/functions/site-settings/site-settings.ts +158 -0
  53. package/{autoInit/accessibility → src/modules/structure}/functions/toc/README.md +18 -15
  54. package/{autoInit/accessibility/functions/toc/toc.js → src/modules/structure/functions/toc/functions/heading-links/heading-links.ts} +43 -63
  55. package/src/modules/structure/functions/toc/functions/progress-bar/progress-bar.ts +101 -0
  56. package/src/modules/structure/functions/toc/toc.ts +35 -0
  57. package/{autoInit/accessibility → src/modules/structure}/functions/year-replacement/README.md +7 -6
  58. package/src/modules/structure/functions/year-replacement/year-replacement.ts +59 -0
  59. package/src/modules/structure/structure.ts +59 -0
  60. package/src/utils/attributeSelector.ts +78 -0
  61. package/src/utils/cssVariables.ts +24 -0
  62. package/src/utils/gsap.ts +198 -0
  63. package/src/utils/heightAnimator.ts +130 -0
  64. package/src/utils/modalManager.ts +150 -0
  65. package/src/utils.ts +54 -0
  66. package/tsconfig.json +24 -0
  67. package/vite.config.js +45 -0
  68. package/.claude/settings.local.json +0 -70
  69. package/archive/hero.js +0 -794
  70. package/archive/modal.js +0 -80
  71. package/archive/text.js +0 -628
  72. package/autoInit/accessibility/accessibility.js +0 -53
  73. package/autoInit/accessibility/functions/blog-remover/README.md +0 -61
  74. package/autoInit/accessibility/functions/blog-remover/blog-remover.js +0 -31
  75. package/autoInit/accessibility/functions/click-forwarding/README.md +0 -60
  76. package/autoInit/accessibility/functions/click-forwarding/click-forwarding.js +0 -82
  77. package/autoInit/accessibility/functions/dropdown/README.md +0 -212
  78. package/autoInit/accessibility/functions/dropdown/dropdown.js +0 -167
  79. package/autoInit/accessibility/functions/list-accessibility/README.md +0 -56
  80. package/autoInit/accessibility/functions/list-accessibility/list-accessibility.js +0 -23
  81. package/autoInit/accessibility/functions/pagination/README.md +0 -428
  82. package/autoInit/accessibility/functions/pagination/pagination.js +0 -359
  83. package/autoInit/accessibility/functions/text-synchronization/README.md +0 -62
  84. package/autoInit/accessibility/functions/text-synchronization/text-synchronization.js +0 -101
  85. package/autoInit/accessibility/functions/year-replacement/year-replacement.js +0 -43
  86. package/autoInit/button/README.md +0 -122
  87. package/autoInit/button/button.js +0 -51
  88. package/autoInit/counter/README.md +0 -274
  89. package/autoInit/counter/counter.js +0 -185
  90. package/autoInit/form/README.md +0 -338
  91. package/autoInit/form/form.js +0 -374
  92. package/autoInit/navbar/README.md +0 -366
  93. package/autoInit/navbar/navbar.js +0 -786
  94. package/autoInit/site-settings/README.md +0 -218
  95. package/autoInit/site-settings/site-settings.js +0 -134
  96. package/autoInit/transition/transition.js +0 -116
  97. package/index.js +0 -305
  98. package/utils/before-after/README.md +0 -520
  99. package/utils/before-after/before-after.js +0 -653
  100. package/utils/css-animations/buttons/main/bgbasic/btn-main-bgbasic.html +0 -10
  101. package/utils/css-animations/buttons/main/bgfill/btn-main-bgfill.html +0 -29
  102. package/utils/css-animations/buttons/navbar/bgbasic/navbar-main-bgbasic.html +0 -17
  103. package/utils/css-animations/buttons/navbar/bgbasic/navbar-menu-bgbasic.html +0 -16
  104. package/utils/css-animations/buttons/navbar/bgfill/navbar-main-bgfill.html +0 -46
  105. package/utils/css-animations/buttons/navbar/bgfill/navbar-menu-bgfill.html +0 -39
  106. package/utils/css-animations/buttons/navbar/color/navbar-announce-color.html +0 -5
  107. package/utils/css-animations/buttons/navbar/color/navbar-main-color.html +0 -7
  108. package/utils/css-animations/buttons/navbar/color/navbar-menu-color.html +0 -7
  109. package/utils/css-animations/buttons/navbar/double-slide/navbar-announce-double-slide.html +0 -40
  110. package/utils/css-animations/buttons/navbar/double-slide/navbar-main-double-slide.html +0 -77
  111. package/utils/css-animations/buttons/navbar/scale/navbar-announce-scale.html +0 -6
  112. package/utils/css-animations/buttons/navbar/scale/navbar-main-scale.html +0 -9
  113. package/utils/css-animations/buttons/navbar/scale/navbar-menu-scale.html +0 -8
  114. package/utils/css-animations/buttons/navbar/underline/navbar-announce-underline.html +0 -32
  115. package/utils/css-animations/buttons/navbar/underline/navbar-main-underline.html +0 -56
  116. package/utils/css-animations/buttons/text/color/text-footer-color.html +0 -5
  117. package/utils/css-animations/buttons/text/color/text-main-color.html +0 -5
  118. package/utils/css-animations/buttons/text/double-slide/text-main-double-slide.html +0 -56
  119. package/utils/css-animations/buttons/text/scale/text-footer-scale.html +0 -6
  120. package/utils/css-animations/buttons/text/scale/text-main-scale.html +0 -6
  121. package/utils/css-animations/buttons/text/underline/text-footer-underline.html +0 -45
  122. package/utils/css-animations/buttons/text/underline/text-main-underline.html +0 -58
  123. package/utils/css-animations/cards/card-clickable.html +0 -11
  124. package/utils/css-animations/defaults.html +0 -69
@@ -0,0 +1,393 @@
1
+ # **Custom Select Component**
2
+
3
+ ## **Overview**
4
+
5
+ Fully accessible, styled select dropdowns that sync with native `<select>` elements for form submission. Features typeahead search, keyboard navigation, autofill support, and all modern accessibility requirements.
6
+
7
+ ---
8
+
9
+ ### **Required Elements**
10
+
11
+ **Select Wrapper** _(main container)_
12
+
13
+ - data-hs-form-select="wrapper"
14
+
15
+ **Native Select** _(hidden select element for form submission)_
16
+
17
+ - Standard `<select>` element with `<option>` children
18
+ - Should have `name` attribute for form submission
19
+ - Will be hidden but remains functional
20
+
21
+ **Toggle Button** _(visual button to open/close dropdown)_
22
+
23
+ - data-hs-form-select="button"
24
+ - Should contain a `<span>` element for displaying selected text
25
+ - Webflow IX must add/remove `.is-active` class on this button for open/close animation
26
+ - Script automatically adds/removes `.is-filled` class based on whether a value is selected
27
+
28
+ **Custom List** _(dropdown container)_
29
+
30
+ - data-hs-form-select="list"
31
+ - First child is used as template for generating options
32
+ - Webflow IX must show/hide this when button is clicked
33
+
34
+ **Template Element** _(first child of select-list)_
35
+
36
+ - Should contain a `<span>` element for option text
37
+ - Will be cloned for each `<option>` in the native select
38
+ - Original template is removed after cloning
39
+
40
+ **Label** _(optional but recommended)_
41
+
42
+ - Standard `<label>` element
43
+ - Can be inside wrapper or reference select by `for` attribute
44
+
45
+ **Typical element layout:**
46
+
47
+ 1. Select Wrapper (data-hs-form-select="wrapper")
48
+ 1. Label (optional)
49
+ 1. Text: "Choose an option"
50
+ 2. Native Select (`<select>`)
51
+ 1. Option 1 (`<option value="value1">`)
52
+ 1. Text: "Option 1"
53
+ 2. Option 2 (`<option value="value2">`)
54
+ 1. Text: "Option 2"
55
+ 3. Toggle Button (data-hs-form-select="button")
56
+ 1. Button Text (`<span>`)
57
+ 1. Text: "Choose an option"
58
+ 4. Custom List (data-hs-form-select="list")
59
+ 1. Template Element
60
+ 1. Text Span (`<span>`)
61
+ 1. Text: "Placeholder"
62
+
63
+ ### **What It Does**
64
+
65
+ 1. **Unwraps Webflow slots** - Removes any `<div>` wrappers inside `<select>` elements
66
+ 2. **Clones template** - Uses first child of select-list as template
67
+ 3. **Generates options** - Creates custom option elements from native `<option>` elements
68
+ 4. **Syncs state** - Keeps custom UI and native select in sync
69
+ 5. **ARIA management** - Automatically updates accessibility attributes
70
+ 6. **Keyboard navigation** - Full arrow key, Home/End, Tab, Enter, Space, Escape support
71
+ 7. **Typeahead search** - Type to quickly navigate to options (native select behavior)
72
+ 8. **Focus management** - Handles focus return, tabbing out, and keyboard navigation
73
+ 9. **Value state tracking** - Adds/removes `.is-filled` class on button based on whether an actual value is selected
74
+ 10. **Disabled state sync** - Automatically disables button when native select is disabled
75
+ 11. **Form reset support** - Updates custom UI when form is reset via `<button type="reset">`
76
+ 12. **Autofill support** - Syncs with browser autofill and password managers
77
+
78
+ ### **When It Runs**
79
+
80
+ - Runs once on page load (or DOMContentLoaded)
81
+ - Available for manual re-initialization via `window.initCustomSelects()`
82
+ - Runs again on Barba.js page transitions (via `reinitialize()`)
83
+
84
+ ### **Interaction Requirements (IX3)**
85
+
86
+ **CRITICAL:** Webflow interactions MUST add/remove `.is-active` class on the toggle button.
87
+
88
+ **Triggers:**
89
+
90
+ 1. **Click trigger** on button element (data-hs-form-select="button")
91
+ 1. `Each click: Toggle play/reverse`
92
+
93
+ **Timeline:**
94
+
95
+ 1. 0s: Toggle `.is-active` class on the button element
96
+ 2. .06s: Rest of animation (fade in, slide, etc.)
97
+
98
+ **Class Behavior:**
99
+
100
+ - `.is-active` - Controlled by Webflow IX for dropdown open/close animation state
101
+ - `.is-filled` - Automatically controlled by script to indicate if a value is selected (use for placeholder-like styling)
102
+
103
+ ---
104
+
105
+ ## **Accessibility**
106
+
107
+ ### **Automatic ARIA Setup**
108
+
109
+ For each select, the system automatically:
110
+
111
+ 1. **Button (combobox)**
112
+ - `role="combobox"`
113
+ - `aria-haspopup="listbox"`
114
+ - `aria-expanded="true|false"` (synced with `.is-active` class)
115
+ - `aria-controls="[listbox-id]"`
116
+ - `aria-labelledby="[label-id]"` (if label exists)
117
+ - `aria-activedescendant="[option-id]"` (when navigating with arrows)
118
+
119
+ 2. **Select List**
120
+ - `role="listbox"`
121
+ - `tabindex="-1"` (not directly tabbable)
122
+
123
+ 3. **Options**
124
+ - `role="option"`
125
+ - `aria-selected="true|false"`
126
+ - `tabindex="0"` when dropdown open, `tabindex="-1"` when closed
127
+ - Unique `id` for aria-activedescendant
128
+
129
+ 4. **Label**
130
+ - Connected to native select with `for` attribute
131
+ - Linked to button with `aria-labelledby`
132
+
133
+ ### **Focus Management**
134
+
135
+ 1. **Opening dropdown** - All options become tabbable
136
+ 2. **Closing dropdown** - Focus returns to button if inside list
137
+ 3. **Tabbing out** - Automatically closes dropdown
138
+ 4. **Arrow navigation** - Focuses options with visual `.focused` class
139
+
140
+ ---
141
+
142
+ ## **Usage Examples**
143
+
144
+ ### **Basic Select**
145
+
146
+ ```html
147
+ <div data-hs-form-select="wrapper">
148
+ <label for="fruit-select">Choose a fruit</label>
149
+
150
+ <select name="fruit" id="fruit-select">
151
+ <option value="">Choose an option</option>
152
+ <option value="apple">Apple</option>
153
+ <option value="banana">Banana</option>
154
+ <option value="orange">Orange</option>
155
+ </select>
156
+
157
+ <button data-hs-form-select="button">
158
+ <span>Choose an option</span>
159
+ </button>
160
+
161
+ <div data-hs-form-select="list">
162
+ <div>
163
+ <span>Template</span>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ ```
168
+
169
+ **Result:** Creates 4 custom options (including empty "Choose an option"). Native select stays synced for form submission.
170
+
171
+ ### **Pre-selected Option**
172
+
173
+ ```html
174
+ <select name="size">
175
+ <option value="small">Small</option>
176
+ <option value="medium" selected>Medium</option>
177
+ <option value="large">Large</option>
178
+ </select>
179
+ ```
180
+
181
+ **Result:** Button text automatically shows "Medium" on page load. Corresponding custom option has `aria-selected="true"`.
182
+
183
+ ### **Options with Special Characters**
184
+
185
+ ```html
186
+ <option value='product"deluxe"'>Deluxe Edition</option>
187
+ <option value="user's choice">Custom Option</option>
188
+ ```
189
+
190
+ **Result:** Works correctly - uses safe value comparison instead of selector injection.
191
+
192
+ ---
193
+
194
+ ## **Keyboard Navigation**
195
+
196
+ ### **When Button is Focused**
197
+
198
+ 1. **Space** or **Enter** � Open/close dropdown
199
+ 2. **ArrowDown** � Open dropdown (or focus first option if already open)
200
+ 3. **ArrowUp** � Focus last option (if dropdown is open)
201
+ 4. **Home** � Open dropdown and focus first option
202
+ 5. **End** � Open dropdown and focus last option
203
+ 6. **Escape** � Close dropdown (if open)
204
+ 7. **Alphanumeric keys** � Typeahead search (see below)
205
+
206
+ ### **When Option is Focused**
207
+
208
+ 1. **ArrowDown** � Focus next option
209
+ 2. **ArrowUp** � Focus previous option (or close and focus button if on first option)
210
+ 3. **Home** � Jump to first option
211
+ 4. **End** � Jump to last option
212
+ 5. **Enter** or **Space** � Select option and close dropdown
213
+ 6. **Escape** � Close dropdown and return focus to button
214
+ 7. **Tab** � Navigate through options, tab out of last option closes dropdown
215
+ 8. **Alphanumeric keys** � Typeahead search (see below)
216
+
217
+ ### **Typeahead Search**
218
+
219
+ The select supports native-like typeahead functionality:
220
+
221
+ 1. **Single character** � Jumps to first option starting with that letter
222
+ 2. **Repeated character** � Cycles through options starting with that letter
223
+ - Example: Press "B" → "Banana", press "B" again → "Blueberry", press "B" again → "Banana"
224
+ 3. **Multi-character** � Builds search string to find matches
225
+ - Example: Type "te" → "Texas", type "tenn" → "Tennessee"
226
+ 4. **Auto-reset** � Search string clears after 500ms of no typing
227
+ 5. **Works from button or list** � Typeahead works whether focused on button (opens dropdown) or within list
228
+ 6. **Auto-scroll** � Focused option automatically scrolls into view in scrollable lists
229
+ 7. **No backspace** � Matches native select behavior (wait for timeout to reset if you mistype)
230
+
231
+ ---
232
+
233
+ ## **State Synchronization**
234
+
235
+ ### **Native Select � Custom UI**
236
+
237
+ When native select value changes (programmatically or via Webflow):
238
+
239
+ 1. Finds matching custom option by value
240
+ 2. Updates button text
241
+ 3. Updates `aria-selected` on all options
242
+
243
+ ### **Custom UI � Native Select**
244
+
245
+ When user selects custom option:
246
+
247
+ 1. Updates native select's `value`
248
+ 2. Dispatches `change` event on native select
249
+ 3. Updates button text
250
+ 4. Updates `aria-selected`
251
+ 5. Closes dropdown
252
+
253
+ **Both stay in sync at all times.**
254
+
255
+ ---
256
+
257
+ ## **Key Attributes Summary**
258
+
259
+ | Attribute | Purpose | Required On |
260
+ | ------------------------------- | -------------------------- | ----------------------- |
261
+ | `data-hs-form-select="wrapper"` | Select wrapper | Wrapper div |
262
+ | `data-hs-form-select="button"` | Toggle button for dropdown | Button element |
263
+ | `data-hs-form-select="list"` | Custom options container | List div |
264
+ | `data-hs-form="form-handler"` | Honeypot spam field | Hidden input (optional) |
265
+
266
+ ---
267
+
268
+ ## **API**
269
+
270
+ ### **Manual Re-initialization**
271
+
272
+ ```javascript
273
+ window.initCustomSelects();
274
+ ```
275
+
276
+ Re-scans page for new selects and initializes them. Useful for dynamically added content.
277
+
278
+ ---
279
+
280
+ ## **Notes**
281
+
282
+ 1. **Native select required** - Must have actual `<select>` element for form submission
283
+ 2. **Button must have span** - `<span>` child is required for text updates
284
+ 3. **Button attribute required** - Button must have `data-hs-form-select="button"` attribute
285
+ 4. **Template is removed** - First child of list is cloned then deleted
286
+ 5. **Webflow IX required** - Must toggle `.is-active` class on button for open/close animation
287
+ 6. **Auto class management** - Script automatically adds/removes `.is-filled` class based on value state
288
+ 7. **Barba.js compatible** - Automatically cleans up on destroy/reinitialize (including timeouts)
289
+ 8. **Silent failures** - Missing required elements cause function to return early (no errors)
290
+ 9. **Empty values supported** - Options with `value=""` work correctly (removes `.is-filled` class)
291
+ 10. **Special characters safe** - Handles quotes and special characters in option values
292
+ 11. **Typeahead search** - Matches native select behavior with 500ms timeout
293
+
294
+ ---
295
+
296
+ ## **v2.0.0 Improvements**
297
+
298
+ ### **JSON Config System**
299
+
300
+ - Added config.js with all attribute definitions
301
+ - Future-proof: Easy to add aliases or change attribute patterns
302
+ - Self-documenting: All supported attributes in one place
303
+ - Config-based selectors: `data-hs-form-select` attribute namespace
304
+
305
+ ### **Typeahead Search**
306
+
307
+ - Native select-like typeahead functionality
308
+ - Single letter cycling (press "B" repeatedly to cycle through "Banana", "Blueberry", etc.)
309
+ - Multi-character search (type "tenn" to find "Tennessee")
310
+ - 500ms auto-reset timeout
311
+ - Works from both button and list focus states
312
+ - Auto-scrolls focused option into view
313
+
314
+ ### **Value State Tracking**
315
+
316
+ - Automatic `.is-filled` class management on button
317
+ - Adds `.is-filled` when option with value is selected
318
+ - Removes `.is-filled` when empty/default option selected
319
+ - Enables placeholder-like CSS styling based on value state
320
+
321
+ ### **Enhanced Keyboard Navigation**
322
+
323
+ - **Home/End keys** - Jump to first/last option (matches native select)
324
+ - Works from both button and list focus states
325
+ - Auto-opens dropdown if closed
326
+
327
+ ### **Disabled State Synchronization**
328
+
329
+ - Automatically syncs button disabled state with native select
330
+ - Observes `disabled` attribute changes on native select
331
+ - Sets `aria-disabled` for accessibility
332
+ - Prevents interaction when disabled
333
+
334
+ ### **Form Integration**
335
+
336
+ - **Form reset support** - Listens for form `reset` event, syncs custom UI to default values
337
+ - **Autofill support** - Listens for `input` events to catch browser autofill and password managers
338
+ - **Autocomplete attribute** - Use standard `autocomplete` attribute on native select for proper autofill
339
+
340
+ ### **Barba.js / SPA Compatibility**
341
+
342
+ The form system is fully compatible with Barba.js and other SPA frameworks:
343
+
344
+ - Proper cleanup on destroy (removes all event listeners, observers, and timeouts)
345
+ - Fresh initialization on reinitialize
346
+ - Syncs custom select state with native select on new pages
347
+ - Works like fresh page load on new DOM
348
+
349
+ ---
350
+
351
+ ## **Common Issues**
352
+
353
+ **Dropdown not opening:**
354
+
355
+ 1. Verify Webflow IX adds `.is-active` class to button (not wrapper or list)
356
+ 2. Check that button has `data-hs-form-select="button"` attribute
357
+ 3. Ensure list exists with `data-hs-form-select="list"`
358
+
359
+ **Button text not updating:**
360
+
361
+ 1. Verify button has a `<span>` child element
362
+ 2. Check that template element has a `<span>` child
363
+ 3. Ensure option values match between native and custom
364
+
365
+ **Options not clickable:**
366
+
367
+ 1. Check that template element exists as first child of select-list
368
+ 2. Verify template has `<span>` for text
369
+ 3. Ensure options are being generated (inspect DOM)
370
+
371
+ **Can't tab to options:**
372
+
373
+ 1. Verify dropdown is open (`.is-active` class on button)
374
+ 2. Check Webflow IX animation shows the select-list
375
+ 3. Ensure `display: none` is removed when open
376
+
377
+ **Form not submitting selected value:**
378
+
379
+ 1. Native `<select>` must have `name` attribute
380
+ 2. Check that native select's value is updating (inspect DOM or use console)
381
+ 3. Verify native select is inside `<form>` element
382
+
383
+ **Dropdown doesn't close when tabbing out:**
384
+
385
+ 1. Ensure wrapper element properly contains button and list
386
+ 2. Check that `data-hs-form-select="wrapper"` is on wrapper
387
+ 3. Verify Webflow IX removes `.is-active` when clicking button again
388
+
389
+ **Spam prevention not working:**
390
+
391
+ 1. Verify honeypot field has `data-hs-form="form-handler"`
392
+ 2. Ensure field is hidden with CSS (not removed from DOM)
393
+ 3. Check that field is inside the `<form>` element