@hortonstudio/main 1.9.8 → 1.9.10
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/autoInit/accessibility/README.md +9 -1
- package/autoInit/accessibility/accessibility.js +2 -1
- package/autoInit/accessibility/functions/pagination/README.md +428 -0
- package/{utils/slider.js → autoInit/accessibility/functions/pagination/pagination.js} +173 -242
- package/index.js +1 -3
- package/package.json +1 -1
- package/utils/before-after/README.md +520 -0
- package/utils/{before-after.js → before-after/before-after.js} +208 -75
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## **Overview**
|
|
4
4
|
|
|
5
|
-
The accessibility system provides
|
|
5
|
+
The accessibility system provides 8 modular functions to enhance website accessibility and functionality. Each function operates independently and can be customized through data attributes.
|
|
6
6
|
|
|
7
7
|
**Note:** This module auto-initializes and loads all functions on page load.
|
|
8
8
|
|
|
@@ -61,6 +61,13 @@ Universal dropdown system for FAQ, summary/read-more, and general toggle compone
|
|
|
61
61
|
|
|
62
62
|
---
|
|
63
63
|
|
|
64
|
+
### **8. Pagination**
|
|
65
|
+
Complete pagination system for paginated lists with controls, counters, dot navigation, and infinite looping. Supports responsive layouts and accessibility features.
|
|
66
|
+
|
|
67
|
+
**Use case:** Multi-item paginated lists (product grids, blog lists, search results) and carousels (with `show-1` config).
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
64
71
|
## **Documentation**
|
|
65
72
|
|
|
66
73
|
Each function has detailed documentation in its respective folder:
|
|
@@ -72,6 +79,7 @@ Each function has detailed documentation in its respective folder:
|
|
|
72
79
|
- `functions/text-synchronization/README.md`
|
|
73
80
|
- `functions/toc/README.md`
|
|
74
81
|
- `functions/dropdown/README.md`
|
|
82
|
+
- `functions/pagination/README.md`
|
|
75
83
|
|
|
76
84
|
---
|
|
77
85
|
|
|
@@ -12,7 +12,8 @@ export async function init() {
|
|
|
12
12
|
"click-forwarding": () => import("./functions/click-forwarding/click-forwarding.js"),
|
|
13
13
|
"text-synchronization": () => import("./functions/text-synchronization/text-synchronization.js"),
|
|
14
14
|
"toc": () => import("./functions/toc/toc.js"),
|
|
15
|
-
"dropdown": () => import("./functions/dropdown/dropdown.js")
|
|
15
|
+
"dropdown": () => import("./functions/dropdown/dropdown.js"),
|
|
16
|
+
"pagination": () => import("./functions/pagination/pagination.js")
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
const loadFunction = async (functionName) => {
|
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# **Pagination System Documentation**
|
|
2
|
+
|
|
3
|
+
## **Overview**
|
|
4
|
+
|
|
5
|
+
Complete pagination system for paginated lists with controls, counters, dot navigation, and infinite looping. Features responsive layouts, ARIA live announcements, and full keyboard accessibility.
|
|
6
|
+
|
|
7
|
+
**Note:** This function auto-initializes on page load as part of the accessibility system.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## **Features**
|
|
12
|
+
|
|
13
|
+
- **Infinite Loop Pagination**: Seamless page transitions with cloned pages
|
|
14
|
+
- **Responsive Layouts**: Different items per page for desktop/mobile
|
|
15
|
+
- **Page Controls**: Next/Previous buttons with infinite looping
|
|
16
|
+
- **Page Counter**: Live-updating "X / Y" page indicator
|
|
17
|
+
- **Dot Navigation**: Visual page indicators with click/keyboard support
|
|
18
|
+
- **Auto-height Management**: Smooth height transitions between pages
|
|
19
|
+
- **Focus Management**: Uses `inert` attribute for inactive pages
|
|
20
|
+
- **ARIA Live Announcements**: Screen reader announcements for page changes
|
|
21
|
+
- **Mobile Auto-scroll**: Scrolls controls into view on mobile after navigation
|
|
22
|
+
- **Infinite Mode**: Disable all pagination for continuous scrolling
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## **Required Structure**
|
|
27
|
+
|
|
28
|
+
### **Wrapper** *(required)*
|
|
29
|
+
|
|
30
|
+
**Attribute:** `data-hs-pagination="wrapper"`
|
|
31
|
+
|
|
32
|
+
**What it does:** Main container for entire pagination instance.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### **List** *(required)*
|
|
37
|
+
|
|
38
|
+
**Attribute:** `data-hs-pagination="list"`
|
|
39
|
+
|
|
40
|
+
**What it does:** Container for all items to be paginated. System will split these into pages.
|
|
41
|
+
|
|
42
|
+
**Important:** Must be a direct child of a wrapper element (typically a div).
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### **Next Button** *(required)*
|
|
47
|
+
|
|
48
|
+
**Attribute:** `data-hs-pagination="next"`
|
|
49
|
+
|
|
50
|
+
**What it does:** Navigate to next page. Loops to first page after last page.
|
|
51
|
+
|
|
52
|
+
**Accessibility:** Automatically receives `aria-label="Go to next page"`
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### **Previous Button** *(required)*
|
|
57
|
+
|
|
58
|
+
**Attribute:** `data-hs-pagination="previous"`
|
|
59
|
+
|
|
60
|
+
**What it does:** Navigate to previous page. Loops to last page from first page.
|
|
61
|
+
|
|
62
|
+
**Accessibility:** Automatically receives `aria-label="Go to previous page"`
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
### **Controls Container** *(required for configuration)*
|
|
67
|
+
|
|
68
|
+
**Attribute:** `data-hs-pagination="controls"`
|
|
69
|
+
|
|
70
|
+
**What it does:** Container for pagination controls AND configuration via `data-hs-config`.
|
|
71
|
+
|
|
72
|
+
**Configuration Syntax:**
|
|
73
|
+
```
|
|
74
|
+
data-hs-config="[option], [option], ..."
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Configuration Options:**
|
|
78
|
+
|
|
79
|
+
**Show Items (Desktop):**
|
|
80
|
+
```html
|
|
81
|
+
data-hs-config="show-6"
|
|
82
|
+
```
|
|
83
|
+
Shows 6 items per page on desktop (default: 6)
|
|
84
|
+
|
|
85
|
+
**Show Items (Mobile):**
|
|
86
|
+
```html
|
|
87
|
+
data-hs-config="show-3-mobile"
|
|
88
|
+
```
|
|
89
|
+
Shows 3 items per page on mobile (default: desktop value)
|
|
90
|
+
|
|
91
|
+
**Infinite Mode:**
|
|
92
|
+
```html
|
|
93
|
+
data-hs-config="infinite"
|
|
94
|
+
```
|
|
95
|
+
Disables pagination completely (hides controls and dots, shows all items)
|
|
96
|
+
|
|
97
|
+
**Combined Example:**
|
|
98
|
+
```html
|
|
99
|
+
<div data-hs-pagination="controls" data-hs-config="show-4, show-2-mobile">
|
|
100
|
+
<!-- Buttons, counter, etc. -->
|
|
101
|
+
</div>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### **Counter** *(optional)*
|
|
107
|
+
|
|
108
|
+
**Attribute:** `data-hs-pagination="counter"`
|
|
109
|
+
|
|
110
|
+
**What it does:** Displays current page and total pages (e.g., "2 / 5").
|
|
111
|
+
|
|
112
|
+
**Accessibility:** Automatically receives:
|
|
113
|
+
- `aria-live="polite"` - Announces changes
|
|
114
|
+
- `aria-label="Current page"`
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### **Dots Container** *(optional)*
|
|
119
|
+
|
|
120
|
+
**Attribute:** `data-hs-pagination="dots"`
|
|
121
|
+
|
|
122
|
+
**What it does:** Container for pagination dots. Requires template dot as first child.
|
|
123
|
+
|
|
124
|
+
**Template Requirements:**
|
|
125
|
+
- At least one child element (used as template)
|
|
126
|
+
- Use `.is-active` class to designate active template
|
|
127
|
+
- If only one template, same used for active/inactive states
|
|
128
|
+
|
|
129
|
+
**Accessibility:** System automatically adds:
|
|
130
|
+
- Individual dots via separate pagination dots system
|
|
131
|
+
- `role="button"`, `tabindex="0"`, `aria-label` on each dot
|
|
132
|
+
- `aria-current="page"` on active dot
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## **Usage Example**
|
|
137
|
+
|
|
138
|
+
### **Basic Pagination**
|
|
139
|
+
|
|
140
|
+
```html
|
|
141
|
+
<div data-hs-pagination="wrapper">
|
|
142
|
+
<!-- Wrapper for list -->
|
|
143
|
+
<div>
|
|
144
|
+
<div data-hs-pagination="list">
|
|
145
|
+
<div>Item 1</div>
|
|
146
|
+
<div>Item 2</div>
|
|
147
|
+
<div>Item 3</div>
|
|
148
|
+
<div>Item 4</div>
|
|
149
|
+
<div>Item 5</div>
|
|
150
|
+
<div>Item 6</div>
|
|
151
|
+
<div>Item 7</div>
|
|
152
|
+
<div>Item 8</div>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
<!-- Controls -->
|
|
157
|
+
<div data-hs-pagination="controls" data-hs-config="show-4, show-2-mobile">
|
|
158
|
+
<button data-hs-pagination="previous">Previous</button>
|
|
159
|
+
<div data-hs-pagination="counter">1 / 2</div>
|
|
160
|
+
<button data-hs-pagination="next">Next</button>
|
|
161
|
+
</div>
|
|
162
|
+
|
|
163
|
+
<!-- Dots -->
|
|
164
|
+
<div data-hs-pagination="dots">
|
|
165
|
+
<div class="dot is-active"></div> <!-- Active template -->
|
|
166
|
+
<div class="dot"></div> <!-- Inactive template -->
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
### **Infinite Mode (No Pagination)**
|
|
174
|
+
|
|
175
|
+
```html
|
|
176
|
+
<div data-hs-pagination="wrapper">
|
|
177
|
+
<div>
|
|
178
|
+
<div data-hs-pagination="list">
|
|
179
|
+
<!-- All items displayed, no pagination -->
|
|
180
|
+
<div>Item 1</div>
|
|
181
|
+
<div>Item 2</div>
|
|
182
|
+
<div>Item 3</div>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<div data-hs-pagination="controls" data-hs-config="infinite">
|
|
187
|
+
<!-- Controls hidden automatically -->
|
|
188
|
+
<button data-hs-pagination="previous">Previous</button>
|
|
189
|
+
<button data-hs-pagination="next">Next</button>
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## **Responsive Breakpoints**
|
|
197
|
+
|
|
198
|
+
Uses CSS custom property `--data-hs-break` to detect layout:
|
|
199
|
+
|
|
200
|
+
```css
|
|
201
|
+
.pagination-list {
|
|
202
|
+
--data-hs-break: "desktop";
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@media (max-width: 768px) {
|
|
206
|
+
.pagination-list {
|
|
207
|
+
--data-hs-break: "mobile";
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**When breakpoint changes:**
|
|
213
|
+
- Re-calculates items per page
|
|
214
|
+
- Re-generates pagination
|
|
215
|
+
- Maintains current page when possible
|
|
216
|
+
- Updates dots accordingly
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## **Key Attributes Summary**
|
|
221
|
+
|
|
222
|
+
| Attribute | Purpose | Required | Element Type |
|
|
223
|
+
| ----- | ----- | ----- | ----- |
|
|
224
|
+
| `data-hs-pagination="wrapper"` | Main container | **Required** | Wrapper div |
|
|
225
|
+
| `data-hs-pagination="list"` | Items to paginate | **Required** | List container |
|
|
226
|
+
| `data-hs-pagination="next"` | Next button | **Required** | `<button>` |
|
|
227
|
+
| `data-hs-pagination="previous"` | Previous button | **Required** | `<button>` |
|
|
228
|
+
| `data-hs-pagination="controls"` | Controls + config | Required for config | Wrapper div |
|
|
229
|
+
| `data-hs-pagination="counter"` | Page counter | Optional | Any element |
|
|
230
|
+
| `data-hs-pagination="dots"` | Dots container | Optional | Wrapper div |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## **Accessibility Features**
|
|
235
|
+
|
|
236
|
+
### **ARIA Live Regions**
|
|
237
|
+
- Dynamically created live region for announcements
|
|
238
|
+
- Announces page changes: "Page 2 of 5"
|
|
239
|
+
- Uses `aria-live="assertive"` and `aria-atomic="true"`
|
|
240
|
+
- Visually hidden with sr-only styling
|
|
241
|
+
|
|
242
|
+
### **Button Accessibility**
|
|
243
|
+
- Next/Previous buttons: `aria-label` with clear descriptions
|
|
244
|
+
- Counter: `aria-live="polite"` for automatic announcements
|
|
245
|
+
|
|
246
|
+
### **Focus Management**
|
|
247
|
+
- Active page: No `inert` attribute (focusable)
|
|
248
|
+
- Inactive pages: `inert` attribute prevents tab navigation
|
|
249
|
+
- Focus stays on controls during navigation
|
|
250
|
+
|
|
251
|
+
### **Dot Navigation**
|
|
252
|
+
- Handled by separate pagination dots system
|
|
253
|
+
- Full keyboard support (Enter/Space)
|
|
254
|
+
- ARIA attributes for current page
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## **How It Works**
|
|
259
|
+
|
|
260
|
+
### **Initialization:**
|
|
261
|
+
1. Finds all `[data-hs-pagination="wrapper"]` containers
|
|
262
|
+
2. Reads configuration from `data-hs-config`
|
|
263
|
+
3. Calculates total pages based on items and config
|
|
264
|
+
4. Splits items into page lists
|
|
265
|
+
5. Clones pages for infinite loop (adds before/after)
|
|
266
|
+
6. Positions wrapper at page 1 (middle clone)
|
|
267
|
+
7. Initializes dots via pagination dots system
|
|
268
|
+
|
|
269
|
+
### **Navigation:**
|
|
270
|
+
1. User clicks next/previous or dot
|
|
271
|
+
2. Updates current page index
|
|
272
|
+
3. Animates wrapper with CSS transform
|
|
273
|
+
4. On loop boundary, instantly resets to real page
|
|
274
|
+
5. Updates counter, announces change, manages focus
|
|
275
|
+
6. Auto-scrolls on mobile to keep controls visible
|
|
276
|
+
|
|
277
|
+
### **Responsive:**
|
|
278
|
+
1. ResizeObserver monitors wrapper size
|
|
279
|
+
2. Detects breakpoint via CSS custom property
|
|
280
|
+
3. Re-initializes pagination if breakpoint changes
|
|
281
|
+
4. Maintains current page position when possible
|
|
282
|
+
|
|
283
|
+
### **Infinite Mode:**
|
|
284
|
+
1. Hides all pagination controls and dots
|
|
285
|
+
2. Shows all items without splitting
|
|
286
|
+
3. No page transitions or animations
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## **Pagination Behavior**
|
|
291
|
+
|
|
292
|
+
### **Single Page:**
|
|
293
|
+
- Controls and dots hidden automatically
|
|
294
|
+
- All items visible
|
|
295
|
+
- No navigation needed
|
|
296
|
+
|
|
297
|
+
### **Multiple Pages:**
|
|
298
|
+
- Infinite loop (last → first, first → last)
|
|
299
|
+
- Clones pages at boundaries for seamless transitions
|
|
300
|
+
- Instant position reset after loop animation
|
|
301
|
+
- Smooth CSS transitions between pages
|
|
302
|
+
|
|
303
|
+
### **Mobile Scroll:**
|
|
304
|
+
After page change on mobile:
|
|
305
|
+
- Auto-scrolls to keep controls visible
|
|
306
|
+
- 5rem clearance from bottom of viewport
|
|
307
|
+
- Smooth scroll behavior
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## **Dot Navigation Integration**
|
|
312
|
+
|
|
313
|
+
The pagination system integrates with the separate pagination dots system:
|
|
314
|
+
|
|
315
|
+
**How Integration Works:**
|
|
316
|
+
1. Pagination sets attributes on dots container:
|
|
317
|
+
- `data-hs-pagination=""` (empty, triggers dots system)
|
|
318
|
+
- `data-hs-pagination-total` (total pages)
|
|
319
|
+
- `data-hs-pagination-current` (current page)
|
|
320
|
+
2. Dots system handles rendering and click events
|
|
321
|
+
3. Pagination listens for `hs-pagination-change` custom event
|
|
322
|
+
4. Updates are bidirectional via `hsPaginationUpdate()` API
|
|
323
|
+
|
|
324
|
+
**See:** `/autoInit/accessibility/functions/pagination/README.md` for full dots documentation
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## **Configuration Examples**
|
|
329
|
+
|
|
330
|
+
### **Desktop: 6 items, Mobile: 3 items**
|
|
331
|
+
```html
|
|
332
|
+
<div data-hs-config="show-6, show-3-mobile">
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### **Desktop: 4 items, Mobile: 2 items**
|
|
336
|
+
```html
|
|
337
|
+
<div data-hs-config="show-4, show-2-mobile">
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### **Same on all devices (8 items)**
|
|
341
|
+
```html
|
|
342
|
+
<div data-hs-config="show-8">
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### **Disable pagination (infinite mode)**
|
|
346
|
+
```html
|
|
347
|
+
<div data-hs-config="infinite">
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## **Edge Cases**
|
|
353
|
+
|
|
354
|
+
### **No Items:**
|
|
355
|
+
- Early exit, no initialization
|
|
356
|
+
- Console warning displayed
|
|
357
|
+
|
|
358
|
+
### **Single Page:**
|
|
359
|
+
- Controls hidden with `display: none` and `aria-hidden="true"`
|
|
360
|
+
- Dots hidden similarly
|
|
361
|
+
- All items displayed on single page
|
|
362
|
+
|
|
363
|
+
### **Infinite Mode:**
|
|
364
|
+
- Controls completely hidden
|
|
365
|
+
- Dots completely hidden
|
|
366
|
+
- List displayed as-is
|
|
367
|
+
- No pagination logic runs
|
|
368
|
+
|
|
369
|
+
### **Layout Changes:**
|
|
370
|
+
- ResizeObserver detects breakpoint changes
|
|
371
|
+
- Re-initializes pagination with new item count
|
|
372
|
+
- Tries to maintain current page position
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## **Performance**
|
|
377
|
+
|
|
378
|
+
- Uses CSS custom properties for breakpoint detection
|
|
379
|
+
- ResizeObserver for efficient layout monitoring
|
|
380
|
+
- `inert` attribute prevents unnecessary focus handling
|
|
381
|
+
- Cleanup on destroy for Barba.js compatibility
|
|
382
|
+
- Efficient DOM cloning and manipulation
|
|
383
|
+
- CSS transitions (not JavaScript animations) for page changes
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## **Common Issues**
|
|
388
|
+
|
|
389
|
+
**Pagination not working:**
|
|
390
|
+
1. Ensure wrapper, list, next, and previous elements exist
|
|
391
|
+
2. Check `data-hs-config` has valid configuration
|
|
392
|
+
3. Verify list has children elements
|
|
393
|
+
4. Check console for warnings
|
|
394
|
+
|
|
395
|
+
**Items not splitting into pages:**
|
|
396
|
+
1. Ensure `data-hs-config` specifies `show-X`
|
|
397
|
+
2. Check that total items > items per page
|
|
398
|
+
3. Verify CSS custom property `--data-hs-break` is set
|
|
399
|
+
|
|
400
|
+
**Dots not appearing:**
|
|
401
|
+
1. Ensure dots container has template children
|
|
402
|
+
2. Check that there are multiple pages (>1)
|
|
403
|
+
3. Verify pagination accessibility system is loaded
|
|
404
|
+
4. Check that `data-hs-pagination="dots"` attribute is correct
|
|
405
|
+
|
|
406
|
+
**Layout not responsive:**
|
|
407
|
+
1. Add `--data-hs-break` CSS custom property to list
|
|
408
|
+
2. Ensure media query updates the property
|
|
409
|
+
3. Check ResizeObserver is not being blocked
|
|
410
|
+
|
|
411
|
+
**Controls always hidden:**
|
|
412
|
+
1. Check `data-hs-config` doesn't include "infinite"
|
|
413
|
+
2. Ensure total items > items per page
|
|
414
|
+
3. Verify controls container exists
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## **Notes**
|
|
419
|
+
|
|
420
|
+
- Each wrapper is an independent instance
|
|
421
|
+
- Pages are cloned for infinite looping
|
|
422
|
+
- Dots handled by separate pagination dots system
|
|
423
|
+
- Works with any element type for items
|
|
424
|
+
- Requires GSAP-less approach (uses CSS transitions)
|
|
425
|
+
- Barba.js compatible with proper cleanup
|
|
426
|
+
- Auto-initializes as part of accessibility system
|
|
427
|
+
- Supports any number of items
|
|
428
|
+
- Mobile-first responsive behavior
|