rails_onboarding 0.8.9 → 0.8.11

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5de350daba589470bba3cfa3afe9daa037307873d47a888f81899b2e542172fa
4
- data.tar.gz: 6871219f6639948ec9e66747c2e89be3b58d2260d6ef8bc2750a84900db14b1d
3
+ metadata.gz: 8e42f9771d8f9d357ebbf763900651576721b726c548e6f837853d6590ff2da5
4
+ data.tar.gz: 5892846e24f4c86ab43217016e5713c8a80958e72aa861cdeed555d659e83179
5
5
  SHA512:
6
- metadata.gz: 2b6e4ccc57e00c7d41e4b21604be312330888ac2cc96e6b8ef0bc39206c529416ddc35f5d4bdc998632a6488fca0ce2a1c53e900c50115a17b08c17c2f9193f3
7
- data.tar.gz: a4714eaed7cca529878cc9cc99ed06e0e48fa117a1cfa7f327eed5e9de97abf98cf5c35cc4ef7b51e2c8449cca5e78bf64953f9d2a8b2114487b60a9a0dc27d5
6
+ metadata.gz: ed6b1a9c9a64766bca536370562c962e04dfafb0478283834e335e7a80e0e1e11e5bd7619e468597af0c2fe24d1fa84a2c2bfd2eaf52b57a546a209053bca307
7
+ data.tar.gz: 7dd60ecfec9f08115c6b25a40ed91c7c54790ca79e539085929891cb900895767bc4e17e2b64cfa50117132464dd655c709ae7bdc83fd05f1319142ca826acc7
@@ -28,6 +28,12 @@ export default class extends Controller {
28
28
  scrollBehavior: { type: String, default: "smooth" }, // smooth, auto, none
29
29
  scrollOffset: { type: Number, default: 80 }, // px offset from top when scrolling
30
30
  persistProgress: { type: Boolean, default: true },
31
+ // Whether the highlighted element stays clickable. It is lifted above the
32
+ // overlay so that a tour can say "click here to continue", and that is the
33
+ // default. An informational tour wants the opposite: a link inside the
34
+ // spotlight is a trap, because following it navigates away and the tour is
35
+ // either lost or restarted from step one. Overridable per step.
36
+ allowInteraction: { type: Boolean, default: true },
31
37
  tourId: String
32
38
  }
33
39
 
@@ -43,10 +49,33 @@ export default class extends Controller {
43
49
 
44
50
  // Auto-start if configured and not completed
45
51
  if (this.autoStartValue && !this.isTourCompleted()) {
46
- setTimeout(() => this.start(), 1000)
52
+ this.autoStartTimer = setTimeout(() => this.autoStart(), 1000)
47
53
  }
48
54
  }
49
55
 
56
+ /**
57
+ * Begin an auto-started tour, if the page it was configured on is still the
58
+ * one on screen.
59
+ *
60
+ * Turbo renders a cached snapshot as a preview while the fresh response is
61
+ * still in flight, and every controller on the page connects to that preview
62
+ * as well as to the render that replaces it a few milliseconds later.
63
+ * Starting on the preview builds the whole tour, tears it down again when the
64
+ * preview is discarded, and rebuilds it - which a member sees as the popup
65
+ * appearing, vanishing and appearing again. The real render starts it
66
+ * properly, so the preview should simply stand aside.
67
+ *
68
+ * The element check covers the same ground from the other side: a controller
69
+ * whose element has left the document must not build an overlay and a popup,
70
+ * because it no longer has the handlers that would take them down again.
71
+ */
72
+ autoStart() {
73
+ if (!this.element.isConnected) return
74
+ if (document.documentElement.hasAttribute('data-turbo-preview')) return
75
+
76
+ this.start()
77
+ }
78
+
50
79
  /**
51
80
  * Parse and validate tour steps from configuration
52
81
  */
@@ -80,6 +109,7 @@ export default class extends Controller {
80
109
  beforeHide: step.beforeHide,
81
110
  onComplete: step.onComplete,
82
111
  width: step.width || 400, // Popup width in px
112
+ allowInteraction: step.allowInteraction ?? this.allowInteractionValue,
83
113
  ...step
84
114
  }))
85
115
  }
@@ -259,13 +289,25 @@ export default class extends Controller {
259
289
  }
260
290
  }
261
291
 
292
+ /**
293
+ * Elements the controller injects into document.body. Turbo caches the whole body
294
+ * when you navigate away, so without this a Back lands you on a snapshot with a
295
+ * frozen overlay and popup baked in - which then sit underneath the live tour the
296
+ * launcher starts, as duplicated and inert DOM. The attribute is ignored by hosts
297
+ * that do not use Turbo.
298
+ */
299
+ excludeFromSnapshot(element) {
300
+ element.setAttribute('data-turbo-cache', 'false')
301
+ return element
302
+ }
303
+
262
304
  /**
263
305
  * Create modal overlay
264
306
  */
265
307
  createOverlay() {
266
308
  if (this.overlay) return
267
309
 
268
- this.overlay = document.createElement('div')
310
+ this.overlay = this.excludeFromSnapshot(document.createElement('div'))
269
311
  this.overlay.className = 'tour-overlay'
270
312
  this.overlay.style.cssText = `
271
313
  position: fixed;
@@ -322,7 +364,7 @@ export default class extends Controller {
322
364
 
323
365
  if (style === 'none') return
324
366
 
325
- this.spotlight = document.createElement('div')
367
+ this.spotlight = this.excludeFromSnapshot(document.createElement('div'))
326
368
  this.spotlight.className = `tour-spotlight tour-spotlight-${style}`
327
369
 
328
370
  const baseStyles = `
@@ -381,8 +423,16 @@ export default class extends Controller {
381
423
  this.highlightedElement = element
382
424
  this.previousElementPosition = element.style.position
383
425
  this.previousElementZIndex = element.style.zIndex
426
+ this.previousElementPointerEvents = element.style.pointerEvents
384
427
  element.style.position = 'relative'
385
428
  element.style.zIndex = '10000'
429
+
430
+ // With interaction off, clicks fall through the highlighted element to the
431
+ // overlay beneath, which swallows them like the rest of the page. The element
432
+ // is still lifted above the overlay so it stays fully lit.
433
+ if (step.allowInteraction === false) {
434
+ element.style.pointerEvents = 'none'
435
+ }
386
436
  }
387
437
 
388
438
  /**
@@ -426,6 +476,7 @@ export default class extends Controller {
426
476
  if (this.highlightedElement) {
427
477
  this.highlightedElement.style.position = this.previousElementPosition || ''
428
478
  this.highlightedElement.style.zIndex = this.previousElementZIndex || ''
479
+ this.highlightedElement.style.pointerEvents = this.previousElementPointerEvents || ''
429
480
  this.highlightedElement = null
430
481
  }
431
482
  }
@@ -436,7 +487,7 @@ export default class extends Controller {
436
487
  createPopup(step, targetElement) {
437
488
  this.removePopup()
438
489
 
439
- this.popup = document.createElement('div')
490
+ this.popup = this.excludeFromSnapshot(document.createElement('div'))
440
491
  this.popup.className = 'tour-popup'
441
492
 
442
493
  // Build popup HTML
@@ -843,6 +894,8 @@ export default class extends Controller {
843
894
  disconnect() {
844
895
  this.stop()
845
896
 
897
+ if (this.autoStartTimer) clearTimeout(this.autoStartTimer)
898
+
846
899
  if (this.keyboardHandler) {
847
900
  document.removeEventListener('keydown', this.keyboardHandler)
848
901
  }
@@ -71,6 +71,13 @@
71
71
  --onboarding-border: #e5e7eb;
72
72
  --onboarding-border-focus: var(--onboarding-primary);
73
73
 
74
+ /* The edge of a tour spotlight's cutout. Transparent here because a light page
75
+ needs none: the scrim darkens the surround and the cutout keeps the page's
76
+ own white, which is a step anyone can see. The dark block at the foot of
77
+ this file turns them on, where that step does not exist. */
78
+ --onboarding-tour-spotlight-ring: transparent;
79
+ --onboarding-tour-spotlight-glow: transparent;
80
+
74
81
  /* Spacing */
75
82
  --onboarding-space-xs: 0.25rem;
76
83
  --onboarding-space-sm: 0.5rem;
@@ -1143,6 +1150,15 @@
1143
1150
  --onboarding-text-muted: #d1d5db;
1144
1151
  --onboarding-text-light: #9ca3af;
1145
1152
  --onboarding-border: #374151;
1153
+
1154
+ /* Draw the spotlight's edge instead of relying on one. A black scrim over a
1155
+ page that is already near-black moves the surround by a few points of
1156
+ luminance, so the cutout has no visible boundary and the highlight reads
1157
+ as nothing in particular - the tour points at the page and the page looks
1158
+ the same. The brand colour is the foreground role here, hence
1159
+ --onboarding-primary rather than the fill. */
1160
+ --onboarding-tour-spotlight-ring: var(--onboarding-primary);
1161
+ --onboarding-tour-spotlight-glow: color-mix(in srgb, var(--onboarding-primary) 35%, transparent);
1146
1162
  }
1147
1163
 
1148
1164
  .step-debug {
@@ -28,9 +28,21 @@
28
28
  together composited to ~0.92 and buried the surrounding page.
29
29
  The alpha comes from --onboarding-tour-scrim, which the controller sets on :root from
30
30
  its overlayOpacity value. It is deliberately not animated: an animation on this
31
- property overrides the inline style, which is what made overlayOpacity a dead knob. */
31
+ property overrides the inline style, which is what made overlayOpacity a dead knob.
32
+
33
+ The ring and glow are listed first because a box-shadow list paints in reverse: the
34
+ first shadow lands on top, so both sit over the scrim rather than under it. Both
35
+ default to transparent, which is a light page's answer - there the scrim alone
36
+ separates the cutout, since the surround visibly darkens while the cutout keeps the
37
+ page's own white. A dark page has no such headroom - a black scrim over a near-black
38
+ background lands on a slightly nearer black, a difference nobody can see - so the
39
+ cutout has to be given an edge rather than a luminance step to be seen by.
40
+ application.css turns these on in its dark block. */
32
41
  .tour-spotlight-spotlight {
33
- box-shadow: 0 0 0 9999px rgba(0, 0, 0, var(--onboarding-tour-scrim, 0.7));
42
+ box-shadow:
43
+ 0 0 0 3px var(--onboarding-tour-spotlight-ring, transparent),
44
+ 0 0 24px 8px var(--onboarding-tour-spotlight-glow, transparent),
45
+ 0 0 0 9999px rgba(0, 0, 0, var(--onboarding-tour-scrim, 0.7));
34
46
  }
35
47
 
36
48
  /* Border highlight style */
@@ -1,3 +1,3 @@
1
1
  module RailsOnboarding
2
- VERSION = "0.8.9"
2
+ VERSION = "0.8.11"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_onboarding
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.9
4
+ version: 0.8.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Lewis
@@ -282,7 +282,7 @@ licenses:
282
282
  metadata:
283
283
  allowed_push_host: https://rubygems.org
284
284
  homepage_uri: https://github.com/bunnahabhain/rails_onboarding
285
- source_code_uri: https://github.com/bunnahabhain/rails_onboarding/tree/v0.8.9
285
+ source_code_uri: https://github.com/bunnahabhain/rails_onboarding/tree/v0.8.11
286
286
  changelog_uri: https://github.com/bunnahabhain/rails_onboarding/blob/master/docs/CHANGELOG.md
287
287
  rdoc_options: []
288
288
  require_paths: