@keenmate/pure-admin-core 2.3.6 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +23 -29
  2. package/dist/css/main.css +68 -148
  3. package/package.json +1 -5
  4. package/snippets/AUDIT.md +94 -0
  5. package/snippets/alerts.html +264 -89
  6. package/snippets/badges.html +193 -61
  7. package/snippets/buttons.html +178 -0
  8. package/snippets/callouts.html +210 -129
  9. package/snippets/cards.html +383 -200
  10. package/snippets/checkbox-lists.html +199 -65
  11. package/snippets/code.html +55 -11
  12. package/snippets/command-palette.html +401 -111
  13. package/snippets/comparison.html +144 -93
  14. package/snippets/customization.html +311 -104
  15. package/snippets/data-display.html +584 -0
  16. package/snippets/detail-panel.html +470 -138
  17. package/snippets/filter-card.html +246 -0
  18. package/snippets/forms.html +408 -308
  19. package/snippets/grid.html +253 -141
  20. package/snippets/layout.html +379 -480
  21. package/snippets/lists.html +144 -47
  22. package/snippets/loaders.html +64 -39
  23. package/snippets/manifest.json +330 -280
  24. package/snippets/modal-dialogs.html +137 -64
  25. package/snippets/modals.html +221 -151
  26. package/snippets/notifications.html +285 -0
  27. package/snippets/popconfirm.html +213 -19
  28. package/snippets/profile.html +290 -330
  29. package/snippets/statistics.html +247 -0
  30. package/snippets/tables.html +359 -150
  31. package/snippets/tabs.html +129 -45
  32. package/snippets/timeline.html +123 -56
  33. package/snippets/toasts.html +179 -31
  34. package/snippets/tooltips.html +199 -81
  35. package/snippets/typography.html +183 -58
  36. package/snippets/utilities.html +511 -415
  37. package/snippets/virtual-scroll.html +201 -75
  38. package/snippets/web-daterangepicker.html +369 -189
  39. package/snippets/web-multiselect.html +360 -124
  40. package/src/scss/core-components/_alerts.scss +51 -12
  41. package/src/scss/core-components/_pagers.scss +1 -1
  42. package/src/scss/core-components/_popconfirm.scss +35 -13
  43. package/src/scss/core-components/_profile.scss +18 -8
  44. package/src/scss/core-components/_statistics.scss +12 -12
  45. package/src/scss/core-components/_tables.scss +2 -134
  46. package/src/scss/variables/_components.scss +17 -2
  47. package/scripts/download-themes.js +0 -351
@@ -3,17 +3,27 @@
3
3
  Pure Admin Visual Framework
4
4
  ================================ -->
5
5
 
6
- <!-- Note: Toast containers should be at body level in your layout -->
7
- <!-- Include these containers once in your main layout -->
8
- <div id="toast-container-top-right" class="pa-toast-container pa-toast-container--top-right"></div>
9
- <div id="toast-container-top-center" class="pa-toast-container pa-toast-container--top-center"></div>
10
- <div id="toast-container-top-left" class="pa-toast-container pa-toast-container--top-left"></div>
11
- <div id="toast-container-bottom-right" class="pa-toast-container pa-toast-container--bottom-right"></div>
6
+ <!--
7
+ Toast containers live at body level so toasts float above the layout.
8
+ Include one container per position you plan to use (usually all six,
9
+ once, in the app shell).
10
+
11
+ IMPORTANT: positions use CSS logical property names (start/end), NOT
12
+ left/right, so the UI mirrors correctly in RTL. --top-end is the
13
+ most common "toast in the upper-right" slot in LTR.
14
+ -->
15
+ <div id="toast-container-top-end" class="pa-toast-container pa-toast-container--top-end"></div>
16
+ <div id="toast-container-top-center" class="pa-toast-container pa-toast-container--top-center"></div>
17
+ <div id="toast-container-top-start" class="pa-toast-container pa-toast-container--top-start"></div>
18
+ <div id="toast-container-bottom-end" class="pa-toast-container pa-toast-container--bottom-end"></div>
12
19
  <div id="toast-container-bottom-center" class="pa-toast-container pa-toast-container--bottom-center"></div>
13
- <div id="toast-container-bottom-left" class="pa-toast-container pa-toast-container--bottom-left"></div>
20
+ <div id="toast-container-bottom-start" class="pa-toast-container pa-toast-container--bottom-start"></div>
14
21
 
15
22
 
16
- <!-- TOAST STRUCTURE -->
23
+ <!-- ================================
24
+ TOAST STRUCTURE — BORDERED VARIANTS
25
+ Card-background with a coloured border and tinted icon chip.
26
+ ================================ -->
17
27
 
18
28
  <!-- Primary Toast -->
19
29
  <div class="pa-toast pa-toast--primary pa-toast--show">
@@ -66,9 +76,60 @@
66
76
  </div>
67
77
 
68
78
 
69
- <!-- TOAST WITH PROGRESS BAR -->
79
+ <!-- ================================
80
+ FILLED VARIANTS
81
+ Full-colour background; icon chip is a white-at-20%-alpha pill;
82
+ __actions separator goes to a 25% white line.
83
+ ================================ -->
84
+
85
+ <!-- Filled Primary -->
86
+ <div class="pa-toast pa-toast--filled-primary pa-toast--show">
87
+ <div class="pa-toast__icon">ℹ️</div>
88
+ <div class="pa-toast__content">
89
+ <div class="pa-toast__title">Heads up</div>
90
+ <div class="pa-toast__message">This is a filled primary toast.</div>
91
+ </div>
92
+ <button class="pa-toast__close" aria-label="Close">✕</button>
93
+ </div>
94
+
95
+ <!-- Filled Success -->
96
+ <div class="pa-toast pa-toast--filled-success pa-toast--show">
97
+ <div class="pa-toast__icon">✓</div>
98
+ <div class="pa-toast__content">
99
+ <div class="pa-toast__title">Saved</div>
100
+ <div class="pa-toast__message">Changes stored successfully.</div>
101
+ </div>
102
+ <button class="pa-toast__close" aria-label="Close">✕</button>
103
+ </div>
104
+
105
+ <!-- Pattern: pa-toast--filled-{primary|success|danger|warning|info} and pa-toast--filled-color-{1..9} -->
106
+
107
+
108
+ <!-- ================================
109
+ TOAST WITH ACTION BUTTONS
110
+ __actions sits under a separator — good fit for "Undo" on an
111
+ optimistic delete, "Retry" on a failed request, etc.
112
+ ================================ -->
113
+
114
+ <div class="pa-toast pa-toast--info pa-toast--show">
115
+ <div class="pa-toast__icon">🗑️</div>
116
+ <div class="pa-toast__content">
117
+ <div class="pa-toast__title">Entry removed</div>
118
+ <div class="pa-toast__message">The record was deleted from the list.</div>
119
+ <div class="pa-toast__actions">
120
+ <button class="pa-btn pa-btn--xs pa-btn--secondary">Undo</button>
121
+ </div>
122
+ </div>
123
+ <button class="pa-toast__close" aria-label="Close">✕</button>
124
+ </div>
125
+
126
+
127
+ <!-- ================================
128
+ TOAST WITH AUTO-DISMISS PROGRESS BAR
129
+ __progress is absolutely positioned along the bottom; JS animates
130
+ its width from 100% → 0% over the toast's lifetime.
131
+ ================================ -->
70
132
 
71
- <!-- Toast with Auto-dismiss Progress -->
72
133
  <div class="pa-toast pa-toast--primary pa-toast--show">
73
134
  <div class="pa-toast__icon">ℹ</div>
74
135
  <div class="pa-toast__content">
@@ -80,11 +141,37 @@
80
141
  </div>
81
142
 
82
143
 
83
- <!-- JAVASCRIPT API -->
144
+ <!-- ================================
145
+ THEME COLOR SLOT VARIANTS
146
+ ================================ -->
147
+
148
+ <!-- Bordered theme-color-1 toast -->
149
+ <div class="pa-toast pa-toast--color-1 pa-toast--show">
150
+ <div class="pa-toast__icon">●</div>
151
+ <div class="pa-toast__content">
152
+ <div class="pa-toast__title">Color 1</div>
153
+ <div class="pa-toast__message">Border and icon pulled from <code>--pa-color-1</code>.</div>
154
+ </div>
155
+ <button class="pa-toast__close" aria-label="Close">✕</button>
156
+ </div>
157
+
158
+ <!-- Pattern: pa-toast--color-{1..9} (bordered) and pa-toast--filled-color-{1..9} (filled) -->
159
+
160
+
161
+ <!-- ================================
162
+ JAVASCRIPT API
163
+ The real implementation lives in demo/js/toast-service.js
164
+ (exposed as window.PureAdmin.toast). Below is a minimal
165
+ reference for embedding toasts without that service.
166
+ ================================ -->
167
+
84
168
  <script>
85
169
  // Create a toast notification
86
170
  function createToast(position, variant, title, message, duration = 5000, showProgress = false, persistent = false) {
171
+ // position is one of: top-end, top-start, top-center, bottom-end, bottom-start, bottom-center
87
172
  const container = document.getElementById(`toast-container-${position}`);
173
+ if (!container) return;
174
+
88
175
  const toastId = `toast-${Date.now()}-${Math.random()}`;
89
176
 
90
177
  const toast = document.createElement('div');
@@ -111,44 +198,105 @@ function createToast(position, variant, title, message, duration = 5000, showPro
111
198
 
112
199
  container.appendChild(toast);
113
200
 
114
- // Show toast
115
- setTimeout(() => {
116
- toast.classList.add('pa-toast--show');
117
- }, 10);
201
+ // Flip to show state on the next frame so the transition runs
202
+ setTimeout(() => toast.classList.add('pa-toast--show'), 10);
118
203
 
119
- // Progress bar animation
204
+ // Progress bar animation — width transitions from 100% → 0% over the toast lifetime
120
205
  if (showProgress && !persistent) {
121
206
  const progress = toast.querySelector('.pa-toast__progress');
122
207
  if (progress) {
123
208
  progress.style.transition = `width ${duration}ms linear`;
124
- setTimeout(() => {
125
- progress.style.width = '0%';
126
- }, 50);
209
+ setTimeout(() => { progress.style.width = '0%'; }, 50);
127
210
  }
128
211
  }
129
212
 
130
- // Auto-dismiss (only if not persistent)
131
213
  if (!persistent) {
132
- setTimeout(() => {
133
- dismissToast(toastId);
134
- }, duration);
214
+ setTimeout(() => dismissToast(toastId), duration);
135
215
  }
136
216
  }
137
217
 
138
- // Dismiss a toast
139
218
  function dismissToast(toastId) {
140
219
  const toast = document.getElementById(toastId);
141
220
  if (!toast) return;
142
-
143
221
  toast.classList.remove('pa-toast--show');
144
222
  toast.classList.add('pa-toast--hide');
145
-
146
- setTimeout(() => {
147
- toast.remove();
148
- }, 300);
223
+ setTimeout(() => toast.remove(), 300);
149
224
  }
150
225
 
151
226
  // Usage examples:
152
- // createToast('top-right', 'success', 'Success', 'Operation completed!');
153
- // createToast('top-right', 'warning', 'Warning', 'Please review', 0, false, true); // Persistent
227
+ // createToast('top-end', 'success', 'Saved', 'Operation completed.');
228
+ // createToast('top-end', 'warning', 'Heads up', 'Please review.', 0, false, true); // persistent
154
229
  </script>
230
+
231
+
232
+ <!-- ================================
233
+ COMPONENT REFERENCE
234
+ ================================ -->
235
+
236
+ <!--
237
+ CONTAINERS:
238
+ - .pa-toast-container — fixed, pointer-events: none so toasts through
239
+ - .pa-toast-container--top-end — upper inline-end (right in LTR, left in RTL)
240
+ - .pa-toast-container--top-start — upper inline-start (left in LTR, right in RTL)
241
+ - .pa-toast-container--top-center — upper centre (translateX)
242
+ - .pa-toast-container--bottom-end — lower inline-end
243
+ - .pa-toast-container--bottom-start — lower inline-start
244
+ - .pa-toast-container--bottom-center — lower centre
245
+
246
+ (No --*-right / --*-left classes exist. Logical props mirror in RTL.)
247
+
248
+ TOAST ITEM:
249
+ - .pa-toast — base toast (card-bg + border + shadow); starts hidden
250
+ - .pa-toast--show — animation end state: opacity 1, transform: 0 (apply via JS)
251
+ - .pa-toast--hide — animation exit state: opacity 0, transform: off-axis
252
+
253
+ BORDERED VARIANTS (coloured border + tinted icon chip):
254
+ - .pa-toast--primary / --success / --danger / --warning / --info
255
+ - .pa-toast--color-{1..9} — theme colour slots
256
+
257
+ FILLED VARIANTS (full-colour background):
258
+ - .pa-toast--filled-primary / -success / -danger / -warning / -info
259
+ - .pa-toast--filled-color-{1..9}
260
+
261
+ SUB-ELEMENTS:
262
+ - .pa-toast__icon — leading chip (48×48 default, flex-centered)
263
+ - .pa-toast__content — flex: 1 column; hosts __title + __message (+ __actions)
264
+ - .pa-toast__title — bold, text-color-1
265
+ - .pa-toast__message — text-color-2, line-height-base
266
+ - .pa-toast__actions — optional button row under a 1px separator (Undo/Retry/etc.)
267
+ - .pa-toast__close — 32×32 trailing close button (inherits color)
268
+ - .pa-toast__progress — absolute bar along the bottom edge; JS animates width → 0
269
+
270
+ RESPONSIVE:
271
+ - Below $mobile-breakpoint the container goes full-width (inset-inline: $spacing-md)
272
+ and centre positions drop their translateX — so toasts are readable on phones.
273
+
274
+ PATTERNS:
275
+
276
+ Bordered toast:
277
+ <div class="pa-toast pa-toast--success pa-toast--show">
278
+ <div class="pa-toast__icon">✓</div>
279
+ <div class="pa-toast__content">
280
+ <div class="pa-toast__title">Saved</div>
281
+ <div class="pa-toast__message">Entry stored.</div>
282
+ </div>
283
+ <button class="pa-toast__close" aria-label="Close">✕</button>
284
+ </div>
285
+
286
+ Toast with Undo action:
287
+ <div class="pa-toast pa-toast--info pa-toast--show">
288
+ <div class="pa-toast__content">
289
+ <div class="pa-toast__title">Entry removed</div>
290
+ <div class="pa-toast__actions">
291
+ <button class="pa-btn pa-btn--xs pa-btn--secondary">Undo</button>
292
+ </div>
293
+ </div>
294
+ <button class="pa-toast__close" aria-label="Close">✕</button>
295
+ </div>
296
+
297
+ Toast with progress bar:
298
+ <div class="pa-toast pa-toast--primary pa-toast--show">
299
+
300
+ <div class="pa-toast__progress w-100" style="transition: width 5000ms linear;"></div>
301
+ </div>
302
+ -->
@@ -89,18 +89,25 @@
89
89
  <span class="pa-tooltip pa-tooltip--color-9" data-tooltip="Color 9">Color 9</span>
90
90
 
91
91
 
92
- <!-- CURSOR MODIFIERS -->
92
+ <!-- CURSOR / UNDERLINE MODIFIERS -->
93
93
 
94
- <!-- Default tooltip (inherits parent cursor - good for clickable elements like buttons, tabs) -->
94
+ <!-- Default tooltip (inherits parent cursor good for clickable elements like buttons, tabs) -->
95
95
  <button class="pa-btn pa-btn--primary pa-tooltip" data-tooltip="Click to view">
96
96
  Clickable Item
97
97
  </button>
98
98
 
99
- <!-- Help cursor tooltip (question mark cursor - good for informational hints) -->
99
+ <!-- Help cursor tooltip (question-mark cursor good for informational hints) -->
100
100
  <span class="pa-tooltip pa-tooltip--help" data-tooltip="This provides helpful information">
101
101
  What's this?
102
102
  </span>
103
103
 
104
+ <!-- Keyword tooltip (dotted underline + help cursor — good for inline term explanations) -->
105
+ <p>
106
+ The system uses
107
+ <span class="pa-tooltip pa-tooltip--keyword" data-tooltip="JSON Web Tokens: a signed claim used for stateless auth">JWT</span>
108
+ for session authentication.
109
+ </p>
110
+
104
111
 
105
112
  <!-- COLORED TOOLTIPS WITH POSITIONS -->
106
113
 
@@ -172,6 +179,42 @@
172
179
  </span>
173
180
 
174
181
 
182
+ <!-- ================================
183
+ JS-PORTAL TOOLTIP (.pa-tooltip-floating)
184
+ A separate class for tooltips rendered into the body by JS (the
185
+ tooltips-popovers.js script does this automatically). Use when the
186
+ trigger sits inside an overflow: hidden container — a CSS tooltip
187
+ would be clipped; the portal-rendered one escapes the parent.
188
+
189
+ Consumers don't author this markup directly — it's emitted by
190
+ the tooltip JS at runtime. But for framework wrappers (Svelte/Vue/
191
+ React) that render their own portal tooltip, match this shape:
192
+ ================================ -->
193
+
194
+ <div class="pa-tooltip-floating" role="tooltip">
195
+ Tooltip text here
196
+ </div>
197
+
198
+ <!-- Floating tooltip with colour / multiline variants -->
199
+ <div class="pa-tooltip-floating pa-tooltip--primary" role="tooltip">Primary</div>
200
+ <div class="pa-tooltip-floating pa-tooltip--success" role="tooltip">Success</div>
201
+ <div class="pa-tooltip-floating pa-tooltip--warning" role="tooltip">Warning</div>
202
+ <div class="pa-tooltip-floating pa-tooltip--danger" role="tooltip">Danger</div>
203
+ <div class="pa-tooltip-floating pa-tooltip--color-3" role="tooltip">Theme color 3</div>
204
+
205
+ <div class="pa-tooltip-floating pa-tooltip--multiline" role="tooltip">
206
+ Long multi-line content that wraps inside the tooltip box.
207
+ </div>
208
+
209
+ <!--
210
+ If you attach the portal tooltip to an element that ALSO has a
211
+ pa-tooltip CSS class, add pa-tooltip--floating to the element to
212
+ suppress the CSS pseudo tooltip — otherwise you get two tooltips
213
+ stacked over the trigger.
214
+ -->
215
+ <span class="pa-tooltip pa-tooltip--floating" data-tooltip="handled by JS">Trigger</span>
216
+
217
+
175
218
  <!-- POPOVERS - Basic -->
176
219
 
177
220
  <!-- Popovers are click-triggered rich content overlays
@@ -394,86 +437,161 @@ document.addEventListener('content-loaded', function() {
394
437
  </script>
395
438
 
396
439
 
397
- <!-- AVAILABLE CLASSES REFERENCE -->
398
- <!--
399
- TOOLTIPS:
400
- - pa-tooltip (base class, top position by default)
401
-
402
- POSITIONS (RTL-aware):
403
- - pa-tooltip--end (inline-end: right in LTR, left in RTL)
404
- - pa-tooltip--bottom
405
- - pa-tooltip--start (inline-start: left in LTR, right in RTL)
406
-
407
- VARIANTS:
408
- - pa-tooltip--primary (primary colored background)
409
- - pa-tooltip--success (success colored background)
410
- - pa-tooltip--warning (warning colored background)
411
- - pa-tooltip--danger (danger colored background)
412
- - pa-tooltip--color-1 through pa-tooltip--color-9 (theme-defined colors)
413
-
414
- MULTILINE:
415
- - pa-tooltip--multiline (allows text wrapping)
416
-
417
- POPOVERS:
418
- - pa-popover (base container)
419
-
420
- POSITIONING (use data-placement attribute, RTL-aware):
421
- - data-placement="top" (default)
422
- - data-placement="end" (inline-end: right in LTR, left in RTL)
423
- - data-placement="bottom"
424
- - data-placement="start" (inline-start: left in LTR, right in RTL)
425
-
426
- SIZES:
427
- - pa-popover--sm (small)
428
- - pa-popover--lg (large)
429
-
430
- ALIGNMENT:
431
- - pa-popover--center (centered body text)
432
- - pa-popover--end (end-aligned body text)
433
-
434
- COMPONENTS:
435
- - pa-popover__trigger (button/trigger element)
436
- - pa-popover__content (popover container)
437
- - pa-popover__header (header section)
438
- - pa-popover__body (content section)
439
- - pa-popover__close (close button)
440
-
441
- FLOATING UI FEATURES:
442
- - Automatic collision detection
443
- - Auto-flipping when near viewport edges
444
- - Smart shift to stay visible
445
- - No manual positioning needed
446
- - autoUpdate for automatic repositioning on scroll/resize
447
- -->
440
+ <!-- ================================
441
+ COMPONENT REFERENCE
442
+ ================================ -->
448
443
 
449
- <!-- IMPLEMENTATION NOTES -->
450
444
  <!--
451
- REQUIREMENTS:
452
- - @floating-ui/core and @floating-ui/dom must be loaded
453
- - tooltips-popovers.js handles all initialization
454
- - SCSS styles in core-components/_tooltips.scss
455
-
456
- FLOATING UI BENEFITS:
457
- - Tooltips never go off-screen
458
- - Auto-flip to opposite side if no space
459
- - Shift horizontally/vertically to stay visible
460
- - Works with scrolling and resizing
461
- - Position is calculated dynamically
462
-
463
- TOOLTIP BEHAVIOR:
464
- - Show on mouseenter and focus
465
- - Hide on mouseleave and blur
445
+ CSS TOOLTIP (.pa-tooltip):
446
+ Pure CSS pseudo-element tooltip no JS needed for the basic effect.
447
+ Text comes from the `data-tooltip` attribute on the trigger.
448
+
449
+ Position (logical, RTL-aware):
450
+ - .pa-tooltip default (top)
451
+ - .pa-tooltip--bottom below the trigger
452
+ - .pa-tooltip--end inline-end (right in LTR, left in RTL)
453
+ - .pa-tooltip--start inline-start (left in LTR, right in RTL)
454
+
455
+ Colour variants (colour the bubble + arrow):
456
+ - .pa-tooltip--primary / --success / --warning / --danger
457
+ (--warning uses dark text automatically because yellow-on-white is
458
+ low-contrast; the others keep --pa-tooltip-text.)
459
+ - .pa-tooltip--color-{1..9} theme colour slots
460
+
461
+ Modifiers:
462
+ - .pa-tooltip--multiline allow text wrapping (fixed width); default
463
+ is single-line with ellipsis overflow.
464
+ - .pa-tooltip--help cursor: help (? cursor) — informational hints
465
+ - .pa-tooltip--keyword dotted underline + help cursor — for
466
+ term-explanation inline in prose.
467
+ - .pa-tooltip--floating suppress the CSS pseudo tooltip — used when
468
+ a JS portal tooltip (.pa-tooltip-floating)
469
+ is showing over the same trigger, to prevent
470
+ double tooltips.
471
+
472
+ Auto-flip (applied at runtime by tooltips-popovers.js when the
473
+ tooltip would overflow the viewport — not typically authored):
474
+ - .pa-tooltip--auto-flip-top shifted to show above after being
475
+ authored below
476
+ - .pa-tooltip--auto-flip-bottom inverse
477
+ - .pa-tooltip--auto-flip-start inverse of --end
478
+ - .pa-tooltip--auto-flip-end inverse of --start
479
+ (These are CSS classes the JS toggles dynamically. Safe to author
480
+ your tooltip with whatever side you prefer and let the JS handle
481
+ collisions.)
482
+
483
+
484
+ JS PORTAL TOOLTIP (.pa-tooltip-floating):
485
+ Separate class for a tooltip element appended to the body by JS. Used
486
+ when the trigger lives inside an `overflow: hidden` ancestor that
487
+ would clip the pseudo-element tooltip. Emitted automatically by
488
+ tooltips-popovers.js; framework wrappers should match this structure:
489
+
490
+ <div class="pa-tooltip-floating" role="tooltip">Tooltip text</div>
491
+
492
+ Variants (compose with the base class):
493
+ - .pa-tooltip--multiline
494
+ - .pa-tooltip--primary / --success / --warning / --danger
495
+ - .pa-tooltip--color-{1..9}
496
+
497
+ (When using .pa-tooltip-floating against a trigger that also has
498
+ pa-tooltip, add .pa-tooltip--floating to the trigger to hide the
499
+ CSS pseudo — otherwise both tooltips render.)
500
+
501
+
502
+ POPOVER (.pa-popover):
503
+ Click-triggered rich-content container. JS-positioned via Floating UI;
504
+ shown/hidden by toggling `data-show` on `__content`.
505
+
506
+ Structure:
507
+ .pa-popover[data-placement="top|bottom|start|end"]
508
+ button.pa-popover__trigger circular trigger button
509
+ .pa-popover__content[data-show] hidden without data-show
510
+ .pa-popover__header
511
+ <h4>Title</h4> header expects <h4> (styled)
512
+ button.pa-popover__close × close button
513
+ .pa-popover__body
514
+ <p>, <ul>/<ol>, <a>, <code> all auto-styled (see below)
515
+
516
+ Positioning:
517
+ - data-placement="top" (default)
518
+ - data-placement="bottom"
519
+ - data-placement="end" inline-end (RTL-aware)
520
+ - data-placement="start" inline-start (RTL-aware)
521
+ (Popovers use an attribute, not a class modifier, because positioning
522
+ is entirely JS-driven — there's no CSS fallback.)
523
+
524
+ Sizes:
525
+ - .pa-popover--sm
526
+ - (default)
527
+ - .pa-popover--lg
528
+
529
+ Body alignment:
530
+ - (default) text-align: start
531
+ - .pa-popover--center text-align: center on body
532
+ - .pa-popover--end text-align: end on body (RTL-aware)
533
+
534
+ Auto-styled inside .pa-popover__body:
535
+ - <p> spaced paragraphs; last-child bottom margin collapsed
536
+ - <a> accent colour, underlined, darker on hover
537
+ - <ul>, <ol> spacing-sm vertical margin, padding-inline-start
538
+ - <code> monospace, tinted background, small padding
539
+
540
+
541
+ FLOATING UI CONTRACT:
542
+ Both .pa-tooltip-floating rendering and .pa-popover positioning are
543
+ driven by @floating-ui/core + @floating-ui/dom. Features the demo
544
+ bundle wires up via tooltips-popovers.js:
545
+ - computePosition() with offset + flip + shift middleware
546
+ - autoUpdate() so tooltips / popovers reposition on scroll + resize
466
547
  - Single shared tooltip element (performance)
467
- - Positioned using computePosition() with flip, shift, offset middleware
468
-
469
- POPOVER BEHAVIOR:
470
- - Show on trigger click
471
- - Hide on close button click or outside click
472
- - Use data-placement attribute for positioning (not CSS classes)
473
- - Positioned using computePosition() with flip, shift, offset middleware
474
- - autoUpdate ensures automatic repositioning on scroll/resize
475
- - Uses data-show attribute for visibility control
476
- - Absolute positioning relative to trigger
477
548
  - Only one popover open at a time
478
- - Proper cleanup of autoUpdate on hide
549
+ - Outside-click and Escape close popovers; close-button does the same
550
+
551
+ JAVASCRIPT API:
552
+ tooltips-popovers.js exposes:
553
+ window.PureAdminTooltips.init() (re-scan DOM)
554
+ window.PureAdminTooltips.initTooltips()
555
+ window.PureAdminTooltips.initPopovers()
556
+ window.PureAdminTooltips.showTooltip(el)
557
+ window.PureAdminTooltips.hideTooltip()
558
+
559
+ Call init() after dynamically-inserted content to register new
560
+ triggers. Demo example:
561
+ document.addEventListener('content-loaded', () => {
562
+ window.PureAdminTooltips.init();
563
+ });
564
+
565
+
566
+ STRUCTURE PATTERNS:
567
+
568
+ Simple tooltip:
569
+ <span class="pa-tooltip" data-tooltip="Hello">Hover me</span>
570
+
571
+ Tooltip on an icon button (bottom, coloured):
572
+ <button class="pa-btn pa-btn--xs pa-btn--icon-only pa-btn--danger pa-tooltip pa-tooltip--bottom" data-tooltip="Delete user">
573
+ 🗑️
574
+ </button>
575
+
576
+ Keyword tooltip inline in prose (dotted underline):
577
+ <p>
578
+ Ask for a
579
+ <span class="pa-tooltip pa-tooltip--keyword" data-tooltip="Web Worker">WW</span>
580
+ when you need background threads.
581
+ </p>
582
+
583
+ Rich popover:
584
+ <div class="pa-popover" data-placement="bottom">
585
+ <button class="pa-popover__trigger">?</button>
586
+ <div class="pa-popover__content">
587
+ <div class="pa-popover__header">
588
+ <h4>Help</h4>
589
+ <button class="pa-popover__close">×</button>
590
+ </div>
591
+ <div class="pa-popover__body">
592
+ <p>Rich popover with a <a href="#">link</a> and a list:</p>
593
+ <ul><li>Item A</li><li>Item B</li></ul>
594
+ </div>
595
+ </div>
596
+ </div>
479
597
  -->