@hortonstudio/main 1.9.4 → 1.9.7

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 (41) hide show
  1. package/autoInit/accessibility/README.md +126 -0
  2. package/autoInit/accessibility/accessibility.js +56 -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/convert-to-span/README.md +59 -0
  8. package/autoInit/accessibility/functions/convert-to-span/convert-to-span.js +70 -0
  9. package/autoInit/accessibility/functions/custom-values-replacement/README.md +71 -0
  10. package/autoInit/accessibility/functions/custom-values-replacement/custom-values-replacement.js +102 -0
  11. package/autoInit/accessibility/functions/dropdown/README.md +212 -0
  12. package/autoInit/accessibility/functions/dropdown/dropdown.js +167 -0
  13. package/autoInit/accessibility/functions/list-accessibility/README.md +56 -0
  14. package/autoInit/accessibility/functions/list-accessibility/list-accessibility.js +23 -0
  15. package/autoInit/accessibility/functions/prevent-default/README.md +58 -0
  16. package/autoInit/accessibility/functions/prevent-default/prevent-default.js +58 -0
  17. package/autoInit/accessibility/functions/remove-list-accessibility/README.md +57 -0
  18. package/autoInit/accessibility/functions/remove-list-accessibility/remove-list-accessibility.js +68 -0
  19. package/autoInit/accessibility/functions/text-synchronization/README.md +62 -0
  20. package/autoInit/accessibility/functions/text-synchronization/text-synchronization.js +101 -0
  21. package/autoInit/accessibility/functions/toc/README.md +79 -0
  22. package/autoInit/accessibility/functions/toc/toc.js +191 -0
  23. package/autoInit/accessibility/functions/year-replacement/README.md +54 -0
  24. package/autoInit/accessibility/functions/year-replacement/year-replacement.js +43 -0
  25. package/autoInit/button/README.md +122 -0
  26. package/autoInit/counter/README.md +274 -0
  27. package/autoInit/{counter.js → counter/counter.js} +20 -5
  28. package/autoInit/form/README.md +338 -0
  29. package/autoInit/{form.js → form/form.js} +44 -29
  30. package/autoInit/navbar/README.md +366 -0
  31. package/autoInit/{navbar.js → navbar/navbar.js} +128 -118
  32. package/autoInit/site-settings/README.md +218 -0
  33. package/autoInit/smooth-scroll/README.md +386 -0
  34. package/autoInit/transition/README.md +301 -0
  35. package/autoInit/{transition.js → transition/transition.js} +13 -2
  36. package/index.js +8 -8
  37. package/package.json +1 -1
  38. package/autoInit/accessibility.js +0 -786
  39. /package/autoInit/{button.js → button/button.js} +0 -0
  40. /package/autoInit/{site-settings.js → site-settings/site-settings.js} +0 -0
  41. /package/autoInit/{smooth-scroll.js → smooth-scroll/smooth-scroll.js} +0 -0
@@ -0,0 +1,386 @@
1
+ # **Smooth Scroll System Documentation**
2
+
3
+ ## **Overview**
4
+
5
+ The smooth scroll system provides GSAP-powered smooth scrolling for anchor links, replacing Webflow's default behavior with a more customizable solution. It supports scroll offsets, reduced motion preferences, and automatically triggers scroll-based animations on page load.
6
+
7
+ **Note:** This module auto-initializes on every page load.
8
+
9
+ ---
10
+
11
+ ## **Smooth Scroll**
12
+
13
+ ### **Required Dependencies**
14
+
15
+ **GSAP Core**
16
+ * Must be loaded before this script
17
+
18
+ **GSAP ScrollToPlugin**
19
+ * Required for smooth scrolling functionality
20
+
21
+ **Typical setup:**
22
+ ```html
23
+ <script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
24
+ <script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollToPlugin.min.js"></script>
25
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@hortonstudio/main@latest"></script>
26
+ ```
27
+
28
+ ### **What It Does**
29
+
30
+ 1. **Disables native smooth scroll** - Removes Webflow's jQuery-based anchor link handler
31
+ 2. **Disables CSS smooth scrolling** - Sets `scroll-behavior: auto` on html and body
32
+ 3. **GSAP smooth scrolling** - Uses GSAP ScrollToPlugin for animated scrolling
33
+ 4. **Respects reduced motion** - Instant scroll if user has `prefers-reduced-motion` enabled
34
+ 5. **Custom offset support** - Reads `--misc--scroll-offset` CSS variable for scroll offset
35
+ 6. **Focus management** - Sets focus on target element after scroll
36
+ 7. **URL hash updates** - Updates browser URL with hash when scrolling to anchor
37
+ 8. **Mock scroll trigger** - Triggers scroll-based animations on page load with quick scroll
38
+ 9. **Keyboard support** - Handles Enter/Space key activation on anchor links
39
+
40
+ ### **When It Runs**
41
+
42
+ * Auto-initializes on page load
43
+ * Runs on every page in a multi-page site
44
+ * Listed in `autoInitModules` in index.js
45
+
46
+ ---
47
+
48
+ ## **Scroll Offset**
49
+
50
+ ### **CSS Variable**
51
+
52
+ Define a scroll offset using a CSS custom property:
53
+
54
+ ```css
55
+ :root {
56
+ --misc--scroll-offset: 100px;
57
+ }
58
+ ```
59
+
60
+ **What it does:** When scrolling to an anchor, the page scrolls to the target element minus this offset. Useful for fixed headers.
61
+
62
+ **Default:** `0` (no offset)
63
+
64
+ **Units:** Pixels only (parsed as integer)
65
+
66
+ ### **Example with Fixed Header**
67
+
68
+ ```css
69
+ :root {
70
+ --misc--scroll-offset: 80px; /* Height of fixed navbar */
71
+ }
72
+ ```
73
+
74
+ **Result:** When clicking an anchor link, the page scrolls so the target element is 80px from the top of the viewport.
75
+
76
+ ---
77
+
78
+ ## **Anchor Links**
79
+
80
+ ### **Supported Anchor Links**
81
+
82
+ Any link with `href` starting with `#`:
83
+
84
+ ```html
85
+ <a href="#section-1">Go to Section 1</a>
86
+ <a href="#about">About Us</a>
87
+ <a href="#contact">Contact</a>
88
+ ```
89
+
90
+ **Requirements:**
91
+ - Must have `href` attribute starting with `#`
92
+ - Target element must have matching `id` attribute
93
+ - Cannot be just `#` (empty hash)
94
+
95
+ ### **Target Elements**
96
+
97
+ ```html
98
+ <section id="section-1">
99
+ <h2>Section 1</h2>
100
+ </section>
101
+
102
+ <div id="about">
103
+ <h2>About Us</h2>
104
+ </div>
105
+ ```
106
+
107
+ **Requirements:**
108
+ - Must have `id` attribute matching the anchor's `href` (without `#`)
109
+
110
+ ---
111
+
112
+ ## **Animation Settings**
113
+
114
+ ### **GSAP Configuration**
115
+
116
+ The scroll animation uses these GSAP settings:
117
+
118
+ **Duration:** `1` second
119
+ **Easing:** `power2.out` (fast start, slow end)
120
+ **Plugin:** ScrollToPlugin with `offsetY` support
121
+
122
+ ### **Example of smooth scroll behavior:**
123
+
124
+ ```javascript
125
+ gsap.to(window, {
126
+ duration: 1,
127
+ scrollTo: {
128
+ y: target,
129
+ offsetY: offset,
130
+ },
131
+ ease: "power2.out"
132
+ });
133
+ ```
134
+
135
+ **Result:** Smooth 1-second scroll with deceleration easing.
136
+
137
+ ---
138
+
139
+ ## **Reduced Motion Support**
140
+
141
+ ### **What It Does**
142
+
143
+ If user has `prefers-reduced-motion: reduce` enabled:
144
+ - Skips GSAP animation entirely
145
+ - Uses instant scroll with `window.scrollTo()`
146
+ - Still respects scroll offset
147
+ - Still sets focus on target element
148
+
149
+ ### **Detection**
150
+
151
+ ```javascript
152
+ window.matchMedia("(prefers-reduced-motion: reduce)").matches
153
+ ```
154
+
155
+ **Result:** Users with motion sensitivity get instant, non-animated scrolling while maintaining all functionality.
156
+
157
+ ---
158
+
159
+ ## **Focus Management**
160
+
161
+ ### **Automatic Focus**
162
+
163
+ After scrolling to target element:
164
+ 1. Sets `tabindex="-1"` on target (makes it focusable without adding to tab order)
165
+ 2. Calls `focus({ preventScroll: true })` on target
166
+ 3. Announces target to screen readers
167
+
168
+ **Why:** Improves accessibility by moving keyboard focus to the section you scrolled to, similar to native anchor link behavior.
169
+
170
+ ---
171
+
172
+ ## **Mock Scroll (Animation Trigger)**
173
+
174
+ ### **What It Does**
175
+
176
+ On page load, performs a quick scroll:
177
+ 1. Scrolls to `1px`
178
+ 2. Immediately scrolls back to `0px`
179
+
180
+ **Why:** Triggers scroll-based animations (IntersectionObserver, scroll triggers) that only fire when the page scrolls.
181
+
182
+ **Condition:** Only runs if page is scrollable (`document.body.scrollHeight > window.innerHeight`)
183
+
184
+ **Result:** Scroll-based animations initialize properly on page load without user interaction.
185
+
186
+ ---
187
+
188
+ ## **URL Hash Updates**
189
+
190
+ When clicking an anchor link:
191
+ 1. Prevents default browser behavior
192
+ 2. Updates URL hash using `history.replaceState()`
193
+ 3. Scrolls to target
194
+
195
+ **Example:**
196
+ - Click `<a href="#about">`
197
+ - URL changes from `example.com` to `example.com#about`
198
+ - Page smoothly scrolls to `#about` element
199
+
200
+ **Note:** Uses `replaceState` (not `pushState`), so it doesn't create a new browser history entry.
201
+
202
+ ---
203
+
204
+ ## **Keyboard Support**
205
+
206
+ ### **Supported Keys**
207
+
208
+ When an anchor link is focused:
209
+ - **Enter** � Triggers smooth scroll to target
210
+ - **Space** � Triggers smooth scroll to target
211
+
212
+ **Implementation:** Keyboard events are handled the same as clicks, providing consistent behavior.
213
+
214
+ ---
215
+
216
+ ## **Usage Examples**
217
+
218
+ ### **Basic Anchor Link**
219
+
220
+ ```html
221
+ <nav>
222
+ <a href="#section-1">Section 1</a>
223
+ <a href="#section-2">Section 2</a>
224
+ </nav>
225
+
226
+ <section id="section-1">
227
+ <h2>Section 1</h2>
228
+ <p>Content here...</p>
229
+ </section>
230
+
231
+ <section id="section-2">
232
+ <h2>Section 2</h2>
233
+ <p>More content...</p>
234
+ </section>
235
+ ```
236
+
237
+ **Result:** Clicking links smoothly scrolls to corresponding sections with 1-second animation.
238
+
239
+ ### **With Scroll Offset**
240
+
241
+ ```css
242
+ :root {
243
+ --misc--scroll-offset: 100px;
244
+ }
245
+ ```
246
+
247
+ ```html
248
+ <header style="position: fixed; height: 100px;">
249
+ <nav>
250
+ <a href="#content">Skip to content</a>
251
+ </nav>
252
+ </header>
253
+
254
+ <main id="content" style="margin-top: 100px;">
255
+ <h1>Main Content</h1>
256
+ </main>
257
+ ```
258
+
259
+ **Result:** Clicking "Skip to content" scrolls so the main content appears 100px from top (below the fixed header).
260
+
261
+ ### **Table of Contents**
262
+
263
+ ```html
264
+ <nav class="toc">
265
+ <a href="#introduction">Introduction</a>
266
+ <a href="#features">Features</a>
267
+ <a href="#installation">Installation</a>
268
+ <a href="#usage">Usage</a>
269
+ </nav>
270
+
271
+ <article>
272
+ <section id="introduction">
273
+ <h2>Introduction</h2>
274
+ </section>
275
+
276
+ <section id="features">
277
+ <h2>Features</h2>
278
+ </section>
279
+
280
+ <section id="installation">
281
+ <h2>Installation</h2>
282
+ </section>
283
+
284
+ <section id="usage">
285
+ <h2>Usage</h2>
286
+ </section>
287
+ </article>
288
+ ```
289
+
290
+ **Result:** Fully functional table of contents with smooth scrolling and focus management.
291
+
292
+ ---
293
+
294
+ ## **Webflow Integration**
295
+
296
+ ### **Disables Webflow's Default Behavior**
297
+
298
+ This script automatically disables:
299
+ 1. **jQuery scroll handler** - Removes `click.wf-scroll` event listener
300
+ 2. **CSS smooth scrolling** - Sets `scroll-behavior: auto`
301
+
302
+ **When:** On Webflow ready (`afterWebflowReady()` callback)
303
+
304
+ **Why:** Prevents conflicts between Webflow's scroll and GSAP scroll.
305
+
306
+ ---
307
+
308
+ ## **Key Attributes Summary**
309
+
310
+ This module doesn't require any data attributes - it works automatically with standard HTML anchor links.
311
+
312
+ | Element | Requirement |
313
+ | ----- | ----- |
314
+ | Anchor link | `href="#target-id"` |
315
+ | Target element | `id="target-id"` |
316
+
317
+ ---
318
+
319
+ ## **API**
320
+
321
+ This module has no public API methods. It runs automatically and handles all anchor links on the page.
322
+
323
+ ---
324
+
325
+ ## **Notes**
326
+
327
+ 1. **GSAP required** - Must load GSAP and ScrollToPlugin before this script
328
+ 2. **Auto-initializes** - Runs on every page load
329
+ 3. **Disables Webflow scroll** - Replaces Webflow's default anchor link behavior
330
+ 4. **Accessibility first** - Respects reduced motion, manages focus
331
+ 5. **No configuration** - Works out of the box with standard HTML
332
+ 6. **CSS variable for offset** - Use `--misc--scroll-offset` for custom offset
333
+ 7. **Mock scroll triggers animations** - Ensures scroll-based animations initialize
334
+ 8. **Clean destroy** - Removes listeners and re-enables CSS smooth scrolling on cleanup
335
+
336
+ ---
337
+
338
+ ## **Common Issues**
339
+
340
+ **Smooth scroll not working:**
341
+
342
+ 1. Verify GSAP and ScrollToPlugin are loaded before main script
343
+ 2. Check browser console for GSAP errors
344
+ 3. Ensure anchor `href` starts with `#` and matches target `id`
345
+ 4. Verify target element exists in DOM
346
+
347
+ **Scroll offset not working:**
348
+
349
+ 1. Check CSS variable is defined: `--misc--scroll-offset: 100px`
350
+ 2. Verify it's on `:root` or `html` element (computed style)
351
+ 3. Ensure value is in pixels (no other units supported)
352
+ 4. Check computed styles in browser DevTools
353
+
354
+ **Focus not working after scroll:**
355
+
356
+ 1. This is expected behavior for accessibility
357
+ 2. Target element gets `tabindex="-1"` and focus
358
+ 3. Use CSS to style `:focus` state if needed
359
+ 4. Don't prevent this - it's important for screen reader users
360
+
361
+ **Scroll animations not triggering on load:**
362
+
363
+ 1. Mock scroll only runs if page is scrollable
364
+ 2. Check that `document.body.scrollHeight > window.innerHeight`
365
+ 3. If page isn't tall enough, animations may not trigger
366
+ 4. Add more content or adjust animation triggers
367
+
368
+ **Reduced motion not instant:**
369
+
370
+ 1. Check browser/OS motion settings
371
+ 2. Test with DevTools: Rendering � Emulate CSS media `prefers-reduced-motion: reduce`
372
+ 3. Verify scroll is instant (no animation)
373
+
374
+ **URL hash not updating:**
375
+
376
+ 1. Check `history.replaceState` is supported (all modern browsers)
377
+ 2. Verify no errors in console
378
+ 3. Ensure target element has `id` attribute
379
+ 4. Check that link click isn't being prevented elsewhere
380
+
381
+ **Conflicts with other scroll libraries:**
382
+
383
+ 1. This module disables Webflow's scroll on init
384
+ 2. If using Lenis or other smooth scroll libraries, may conflict
385
+ 3. Choose one smooth scroll solution per site
386
+ 4. Remove this module if using another smooth scroll library
@@ -0,0 +1,301 @@
1
+ # **Page Transition System Documentation**
2
+
3
+ ## **Overview**
4
+
5
+ The page transition system provides smooth animated transitions between pages in your Webflow site. It automatically triggers entrance animations on page load and exit animations when clicking internal links, creating a seamless single-page-application feel.
6
+
7
+ **Note:** This module auto-initializes by default unless the `no-transition` attribute is added to the script tag.
8
+
9
+ ---
10
+
11
+ ## **Page Transitions**
12
+
13
+ ### **Required Elements**
14
+
15
+ **Transition Trigger** *(invisible element that triggers Webflow IX animation)*
16
+
17
+ * data-hs-transition="trigger"
18
+ * Webflow IX interaction attached (entrance and exit animations)
19
+
20
+ **Transition Element** *(visual overlay that covers the page during transition)*
21
+
22
+ * data-hs-transition="element"
23
+ * Should cover entire viewport
24
+ * Contains visual transition effect (fade, slide, etc.)
25
+
26
+ **Exit Time** *(optional attribute on transition element)*
27
+
28
+ * data-hs-exit-time="0.5"
29
+ * Time in seconds to wait before navigating to new page
30
+ * Should match your Webflow exit animation duration
31
+
32
+ **Entrance Delay** *(optional attribute on transition element)*
33
+
34
+ * data-hs-delay="0.3"
35
+ * Delay in seconds before triggering entrance animation on FIRST page load only
36
+ * Subsequent page loads trigger instantly (no delay)
37
+ * Default: 0 (instant trigger)
38
+
39
+ **Typical element layout:**
40
+
41
+ 1. Transition Wrapper
42
+ 1. Transition Trigger (data-hs-transition="trigger")
43
+ 1. Hidden element (0px × 0px, invisible)
44
+ 2. Transition Element (data-hs-transition="element")
45
+ 1. Full-screen overlay with animation
46
+ 2. Attribute: data-hs-exit-time="0.5"
47
+ 3. Attribute: data-hs-delay="0.3"
48
+
49
+ ### **What It Does**
50
+
51
+ 1. **Page load animation** - Clicks trigger on load to play entrance animation
52
+ 2. **Link interception** - Captures clicks on internal links
53
+ 3. **Exit animation** - Clicks trigger before navigation
54
+ 4. **Timed navigation** - Waits for exit animation to complete, then navigates
55
+ 5. **Back button handling** - Reloads page when using browser back button
56
+ 6. **Resize handling** - Hides transition element on window resize to prevent visual bugs
57
+ 7. **Session awareness** - Tracks first page load via sessionStorage
58
+
59
+ ### **When It Runs**
60
+
61
+ * Auto-initializes on page load (unless `no-transition` attribute is present)
62
+ * Waits for Webflow to be ready (`afterWebflowReady()`)
63
+ * Adds 50ms delay after Webflow ready to ensure IX is fully loaded
64
+ * Runs on every page in a multi-page site
65
+
66
+ ---
67
+
68
+ ## **Disabling Transitions**
69
+
70
+ ### **no-transition Attribute**
71
+
72
+ Add `no-transition` attribute to the script tag to disable page transitions:
73
+
74
+ ```html
75
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@hortonstudio/main@latest" no-transition></script>
76
+ ```
77
+
78
+ **When to use:**
79
+ - During development/testing
80
+ - On sites where transitions cause issues
81
+ - For specific pages where you don't want transitions
82
+
83
+ **Result:** The transition module will not load, and pages will navigate normally without animations.
84
+
85
+ ---
86
+
87
+ ## **Interaction Requirements (IX3)**
88
+
89
+ **CRITICAL:** Webflow interactions MUST be set up on the trigger element.
90
+
91
+ **Triggers:**
92
+
93
+ 1. **Click trigger** on `[data-hs-transition="trigger"]`
94
+ 1. First click: Play entrance animation
95
+ 2. Second click: Play exit animation (or reverse)
96
+
97
+ **Timeline (Entrance):**
98
+
99
+ 1. 0s: Transition element visible (covering page)
100
+ 2. 0s-0.5s: Fade out or slide out animation
101
+ 3. 0.5s: Transition element hidden
102
+
103
+ **Timeline (Exit):**
104
+
105
+ 1. 0s: Transition element hidden
106
+ 2. 0s-0.5s: Fade in or slide in animation
107
+ 3. 0.5s: Transition element visible (covering page)
108
+
109
+ **Important:** The `data-hs-exit-time` should match the exit animation duration.
110
+
111
+ ---
112
+
113
+ ## **Link Behavior**
114
+
115
+ ### **Links that trigger transitions:**
116
+
117
+ - Internal links (same hostname)
118
+ - Links without `target="_blank"`
119
+ - Links without `#` hash in href
120
+ - Links with valid `href` attribute
121
+
122
+ ### **Links that DON'T trigger transitions:**
123
+
124
+ - External links (different domain)
125
+ - Links with `target="_blank"`
126
+ - Anchor links (`href="#section"`)
127
+ - Links without `href` attribute
128
+ - `mailto:` and `tel:` links
129
+
130
+ ---
131
+
132
+ ## **Fallback Script (Recommended)**
133
+
134
+ Add this script to your site's `<head>` BEFORE the main script to prevent transition elements from blocking the page if the codebase fails to load:
135
+
136
+ ```html
137
+ <script>
138
+ // Prevent transition if codebase hasn't loaded
139
+ new MutationObserver((m,o)=>{if(document.documentElement.classList.contains('w-mod-ix3')){if(!document.documentElement.classList.contains('hs-main'))document.querySelectorAll('[data-hs-transition="element"]').forEach(el=>el.remove());o.disconnect()}}).observe(document.documentElement,{attributes:true,attributeFilter:['class']})
140
+ </script>
141
+ ```
142
+
143
+ **What it does:**
144
+ 1. Waits for Webflow IX to load (`w-mod-ix3` class)
145
+ 2. Checks if main codebase loaded (`hs-main` class)
146
+ 3. If main codebase didn't load, removes all transition elements
147
+ 4. Prevents transition overlay from blocking page content
148
+
149
+ **Why it's needed:** If the CDN fails or the script errors, the transition element could cover the entire page permanently, making the site unusable.
150
+
151
+ ---
152
+
153
+ ## **Usage Example**
154
+
155
+ ### **Basic Setup**
156
+
157
+ ```html
158
+ <!-- Fallback script in <head> -->
159
+ <script>
160
+ new MutationObserver((m,o)=>{if(document.documentElement.classList.contains('w-mod-ix3')){if(!document.documentElement.classList.contains('hs-main'))document.querySelectorAll('[data-hs-transition="element"]').forEach(el=>el.remove());o.disconnect()}}).observe(document.documentElement,{attributes:true,attributeFilter:['class']})
161
+ </script>
162
+
163
+ <!-- Main script -->
164
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@hortonstudio/main@latest"></script>
165
+
166
+ <!-- Transition wrapper in <body> -->
167
+ <div class="page-transition">
168
+ <!-- Invisible trigger -->
169
+ <div data-hs-transition="trigger" style="width: 0; height: 0; opacity: 0;"></div>
170
+
171
+ <!-- Visual overlay with 0.5s exit time -->
172
+ <div data-hs-transition="element" data-hs-exit-time="0.5" style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: black; z-index: 9999;">
173
+ <!-- Optional loading animation or logo -->
174
+ </div>
175
+ </div>
176
+ ```
177
+
178
+ ### **With Custom Exit Time**
179
+
180
+ ```html
181
+ <div data-hs-transition="element" data-hs-exit-time="1.2">
182
+ <!-- Longer transition: 1.2 seconds -->
183
+ </div>
184
+ ```
185
+
186
+ **Result:** JavaScript waits 1200ms after clicking the trigger before navigating to the new page.
187
+
188
+ ### **With Entrance Delay**
189
+
190
+ ```html
191
+ <div data-hs-transition="element" data-hs-exit-time="0.5" data-hs-delay="0.3">
192
+ <!-- First page load: waits 300ms before entrance animation -->
193
+ <!-- Subsequent loads: instant entrance animation -->
194
+ </div>
195
+ ```
196
+
197
+ **Result:**
198
+ - First visit to site: Waits 300ms, then triggers entrance animation
199
+ - Navigating to other pages: Triggers entrance animation immediately
200
+
201
+ ---
202
+
203
+ ## **Session Storage**
204
+
205
+ The system uses `sessionStorage` to track the first page load:
206
+
207
+ **Key:** `transition-loaded`
208
+ **Value:** `'true'`
209
+
210
+ **Purpose:** Differentiates between initial site visit and subsequent page navigations. Used to determine whether to apply the entrance delay (`data-hs-delay`):
211
+ - **First load:** Delay is applied before entrance animation
212
+ - **Subsequent loads:** No delay, entrance animation triggers immediately
213
+
214
+ ---
215
+
216
+ ## **Resize Handling**
217
+
218
+ When the browser window is resized:
219
+ - The transition element is hidden (`display: none`)
220
+ - Prevents visual bugs with fixed positioning during resize
221
+ - Transition will work again on next navigation
222
+
223
+ ---
224
+
225
+ ## **Back Button Behavior**
226
+
227
+ When using the browser back button:
228
+ - Page is fully reloaded (not cached)
229
+ - Ensures transition animations play correctly
230
+ - Uses `window.onpageshow` event with `persisted` check
231
+
232
+ ---
233
+
234
+ ## **Key Attributes Summary**
235
+
236
+ | Attribute | Purpose | Required On |
237
+ | ----- | ----- | ----- |
238
+ | `data-hs-transition="trigger"` | Animation trigger | Hidden trigger element |
239
+ | `data-hs-transition="element"` | Visual transition overlay | Transition element |
240
+ | `data-hs-exit-time="0.5"` | Exit duration in seconds | Transition element (optional) |
241
+ | `data-hs-delay="0.3"` | First load entrance delay in seconds | Transition element (optional) |
242
+ | `no-transition` | Disable transitions | Script tag (optional) |
243
+
244
+ ---
245
+
246
+ ## **Notes**
247
+
248
+ 1. **Auto-initializes** - Runs by default unless `no-transition` attribute is present
249
+ 2. **Webflow IX required** - Must have click interaction on trigger element
250
+ 3. **Exit time critical** - Should match your Webflow animation duration
251
+ 4. **Fallback script recommended** - Prevents site from being blocked if script fails
252
+ 5. **Session tracking** - Uses sessionStorage to track first load
253
+ 6. **Back button reloads** - Forces full page reload on back navigation
254
+ 7. **Resize hides transition** - Prevents visual bugs during window resize
255
+
256
+ ---
257
+
258
+ ## **Common Issues**
259
+
260
+ **Transition element blocks entire page:**
261
+
262
+ 1. Ensure main script is loading correctly (check for `hs-main` class on `<html>`)
263
+ 2. Add the fallback script to `<head>` to auto-remove transition on failure
264
+ 3. Check browser console for script errors
265
+
266
+ **Page navigates without exit animation:**
267
+
268
+ 1. Verify `data-hs-exit-time` attribute is set on transition element
269
+ 2. Check that Webflow IX click interaction is on trigger element
270
+ 3. Ensure exit animation is playing when trigger is clicked second time
271
+
272
+ **Exit animation is cut short:**
273
+
274
+ 1. Increase `data-hs-exit-time` to match animation duration
275
+ 2. Test animation by manually clicking trigger element
276
+ 3. Verify Webflow IX timeline duration matches exit time
277
+
278
+ **Entrance animation not playing:**
279
+
280
+ 1. Check that Webflow IX is loaded (`w-mod-ix3` class on `<html>`)
281
+ 2. Verify 50ms delay is sufficient (can be timing issue)
282
+ 3. Ensure trigger element exists before script runs
283
+
284
+ **Links not triggering transitions:**
285
+
286
+ 1. Check link is internal (same hostname)
287
+ 2. Verify link doesn't have `target="_blank"`
288
+ 3. Ensure href doesn't contain `#` hash
289
+ 4. Check that click event listener is attached (inspect in debugger)
290
+
291
+ **Transition shows on window resize:**
292
+
293
+ 1. This is expected - resize handler hides it with `display: none`
294
+ 2. Will work again on next navigation
295
+ 3. Check that resize handler is attached correctly
296
+
297
+ **Back button doesn't work:**
298
+
299
+ 1. Page should reload when using back button
300
+ 2. Check that `onpageshow` handler is attached
301
+ 3. Verify `event.persisted` is true when using back button
@@ -33,6 +33,10 @@ export async function init() {
33
33
  const exitTimeAttr = transitionElement.getAttribute('data-hs-exit-time');
34
34
  const exitTime = exitTimeAttr ? parseFloat(exitTimeAttr) * 1000 : 0;
35
35
 
36
+ // Get delay time for first load from data attribute (in seconds)
37
+ const delayAttr = transitionElement.getAttribute('data-hs-delay');
38
+ const delayTime = delayAttr ? parseFloat(delayAttr) * 1000 : 0;
39
+
36
40
  // Page Load - Trigger entrance animation
37
41
  // Check if this is the first page load of the session
38
42
  const isFirstLoad = !sessionStorage.getItem('transition-loaded');
@@ -43,9 +47,16 @@ export async function init() {
43
47
  });
44
48
  };
45
49
 
46
- triggerAnimation();
47
- if (isFirstLoad) {
50
+ // If first load and delay is set, wait before triggering
51
+ if (isFirstLoad && delayTime > 0) {
52
+ setTimeout(triggerAnimation, delayTime);
48
53
  sessionStorage.setItem('transition-loaded', 'true');
54
+ } else {
55
+ // Subsequent loads or no delay: trigger immediately
56
+ triggerAnimation();
57
+ if (isFirstLoad) {
58
+ sessionStorage.setItem('transition-loaded', 'true');
59
+ }
49
60
  }
50
61
 
51
62
  // On Link Click