compare-images-slider 1.0.2 → 1.1.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.
@@ -0,0 +1,20 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-node@v4
14
+ with:
15
+ node-version: 20
16
+ cache: npm
17
+ - run: npm ci --no-audit --no-fund
18
+ - run: npm run lint
19
+ - run: npm test
20
+ - run: npm run build
@@ -0,0 +1,39 @@
1
+ name: Publish to npm
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write # required for npm trusted publishing (OIDC)
11
+
12
+ jobs:
13
+ publish:
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ # Checkout the repository
18
+ - name: Checkout code
19
+ uses: actions/checkout@v6
20
+
21
+ # Set up Node.js
22
+ - name: Set up Node.js
23
+ uses: actions/setup-node@v6
24
+ with:
25
+ node-version: 24
26
+ cache: "npm"
27
+ registry-url: "https://registry.npmjs.org"
28
+
29
+ # Trusted publishing requires npm >= 11.5.1
30
+ - name: Update npm
31
+ run: npm install -g npm@latest
32
+
33
+ # Install dependencies
34
+ - name: Install dependencies
35
+ run: npm ci
36
+
37
+ # Publish to npm (auth via OIDC, provenance generated automatically)
38
+ - name: Publish
39
+ run: npm publish
package/README.md CHANGED
@@ -11,15 +11,16 @@ A simple slider for comparing two images visually.
11
11
  - No dependencies
12
12
  - Mobile friendly
13
13
  - Vertical slider
14
- - Inertia physics
14
+ - Inertia physics with capped, natural-feeling flicks
15
15
  - Bounce back
16
+ - Keyboard accessible ([W3C APG Window Splitter](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/))
17
+ - Custom element, no shadow DOM
16
18
  - Customizable via CSS
17
19
 
18
20
  ## Demo
19
21
 
20
22
  [Check out the demo](https://stamat.github.io/compare-images-slider/)
21
23
 
22
-
23
24
  ## Installation
24
25
 
25
26
  ```bash
@@ -30,16 +31,19 @@ or use the CDN:
30
31
 
31
32
  ```html
32
33
  <script src="https://unpkg.com/compare-images-slider/dist/compare-images-slider.min.js"></script>
33
- <link rel="stylesheet" href="https://unpkg.com/compare-images-slider/dist/compare-images-slider.min.css">
34
+ <link
35
+ rel="stylesheet"
36
+ href="https://unpkg.com/compare-images-slider/dist/compare-images-slider.min.css"
37
+ />
34
38
  ```
35
39
 
36
40
  ## Usage
37
41
 
38
42
  ```html
39
43
  <div class="js-compare-images-slider compare-images-slider">
40
- <img src="img.jpg" alt="">
44
+ <img src="img.jpg" alt="" />
41
45
  <div class="frame">
42
- <img src="img-alt.jpg" alt="">
46
+ <img src="img-alt.jpg" alt="" />
43
47
  </div>
44
48
  <span class="handle"></span>
45
49
  </div>
@@ -48,25 +52,50 @@ or use the CDN:
48
52
  **⚠️ Note:** Don't be lazy and please set the intrinsic dimensions of the images. This eliminates layout shifts and will ensure the slider works as expected.
49
53
 
50
54
  ```javascript
51
- import CompareImagesSlider from 'compare-images-slider';
55
+ import CompareImagesSlider from "compare-images-slider";
52
56
 
53
- const slider = document.querySelector('.js-compare-images-slider');
57
+ const slider = document.querySelector(".js-compare-images-slider");
54
58
  const compareImagesSlider = new CompareImagesSlider(slider);
55
59
  ```
56
60
 
57
61
  If you are loading the script asynchronously, you can listen for the `CompareImagesSliderLoaded` event to initialize the slider:
58
62
 
59
63
  ```javascript
60
- document.addEventListener('CompareImagesSliderLoaded', function() {
61
- const slider = document.querySelector('.js-compare-images-slider');
64
+ document.addEventListener("CompareImagesSliderLoaded", function () {
65
+ const slider = document.querySelector(".js-compare-images-slider");
62
66
  const compareImagesSlider = new CompareImagesSlider(slider);
63
67
  });
64
68
  ```
65
69
 
66
70
  ```scss
67
- @import 'node_modules/compare-images-slider/src/styles/index.scss';
71
+ @import "node_modules/compare-images-slider/src/styles/index.scss";
68
72
  ```
69
73
 
74
+ ## Custom element
75
+
76
+ The same markup wrapped in a `<compare-images-slider>` tag upgrades itself — no
77
+ JavaScript call needed. It uses light DOM (no shadow root), so the images, frame
78
+ and handle stay fully stylable. Options are read from attributes (bare, `data-*`
79
+ or kebab-case):
80
+
81
+ ```html
82
+ <compare-images-slider inertia initial-position="35">
83
+ <img src="img.jpg" alt="" />
84
+ <div class="frame">
85
+ <img src="img-alt.jpg" alt="" />
86
+ </div>
87
+ <span class="handle"></span>
88
+ </compare-images-slider>
89
+ ```
90
+
91
+ ## Accessibility
92
+
93
+ The handle is a focusable `role="separator"` implementing the
94
+ [W3C APG Window Splitter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/)
95
+ with `aria-valuenow`/`min`/`max`, `aria-orientation` and `aria-controls`. Once
96
+ focused: arrow keys move by `step`, Page Up/Down by `pageStep`, Home/End jump to
97
+ the extremes, and double-click snaps to the nearest extreme.
98
+
70
99
  ## Options
71
100
 
72
101
  ```javascript
@@ -74,37 +103,43 @@ document.addEventListener('CompareImagesSliderLoaded', function() {
74
103
  const options = {
75
104
  inertia: false, // inertia physics, you can flick the handle
76
105
  friction: 0.9, // the friction of the inertia
77
- bounce: false, // will bounce back when intertia is enabled and the boundary is reached
106
+ bounce: false, // will bounce back when inertia is enabled and the boundary is reached
78
107
  bounceFactor: 0.1, // the force of the bounce
108
+ maxFlickVelocity: 0.5, // cap on flick velocity (% per ms), tames hard flicks
79
109
  vertical: false, // vertical slider
80
- onlyHandle: true // only the handle is draggable
81
- }
110
+ onlyHandle: true, // only the handle is draggable
111
+ initialPosition: 50, // starting position (0-100)
112
+ step: 5, // arrow-key step (percent)
113
+ pageStep: 25, // Page Up/Down step (percent)
114
+ };
82
115
 
83
116
  new CompareImagesSlider(slider, options);
84
117
  ```
85
118
 
86
- Available attribute options:
119
+ Available attribute options (bare, `data-*` or kebab-case):
87
120
 
88
- - `vertical` - vertical slider or `data-vertical`
121
+ - `vertical` - vertical slider
122
+ - `inertia`, `bounce`, `only-handle` - booleans
123
+ - `friction`, `bounce-factor`, `max-flick-velocity`, `initial-position`, `step`, `page-step` - numbers
89
124
 
90
125
  ```html
91
126
  <div class="js-compare-images-slider compare-images-slider" vertical>
92
- <img src="img.jpg" alt="">
127
+ <img src="img.jpg" alt="" />
93
128
  <div class="frame">
94
- <img src="img-alt.jpg" alt="">
129
+ <img src="img-alt.jpg" alt="" />
95
130
  </div>
96
131
  <span class="handle"></span>
97
132
  </div>
98
133
  ```
99
134
 
100
- ## TODO:
135
+ ## Development
101
136
 
102
- - [x] Add options
103
- - [x] Scroll block on drag
104
- - [x] Vertical option
105
- - [ ] Add factory class, migrate the general factory class to the book of spells prior to that? Better turn this into custom element!
106
- - [x] Refactor onDrag and move it to the book of spells
107
- - [ ] Add initialized state, don't initialize twice
137
+ ```bash
138
+ npm install
139
+ npm test # unit tests (node:test)
140
+ npm run lint
141
+ npm run build
142
+ ```
108
143
 
109
144
  ---
110
145
 
@@ -0,0 +1,2 @@
1
+ /* compare-images-slider v1.0.2 | https://stamat.github.io/compare-images-slider/ | MIT License */
2
+ @charset "UTF-8";:root{--content-max: 46rem;--radius: .5rem;--font-body: "DM Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--font-mono: "SFMono-Regular", "JetBrains Mono", Menlo, Consolas, monospace}:root,:root[data-theme=light]{--bg: #fff;--bg-alt: #f5f6f8;--bg-code: #f5f6f8;--fg: #1c2024;--fg-muted: #5b6570;--border: #e3e6ea;--accent: #7048e8;--accent-fg: #fff;--link: #6741d9;--shadow: 0 4px 20px rgb(20 24 30 / 8%)}:root[data-theme=dark]{--bg: #16181d;--bg-alt: #1d2026;--bg-code: #1d2026;--fg: #e4e7eb;--fg-muted: #98a1ad;--border: #2b2f36;--accent: #9775fa;--accent-fg: #16181d;--link: #b197fc;--shadow: 0 4px 20px rgb(0 0 0 / 40%)}*{box-sizing:border-box}body{margin:0;font-family:var(--font-body);background:var(--bg);color:var(--fg);line-height:1.65;-webkit-font-smoothing:antialiased}a{color:var(--link)}a:hover{text-decoration:none}:root{--topbar-h: 3.25rem}html{scroll-padding-top:calc(var(--topbar-h) + 1rem)}.topbar{position:sticky;top:0;z-index:40;height:var(--topbar-h);display:flex;align-items:center;gap:.75rem;padding:0 1rem;background:var(--bg);border-top:1px solid var(--border);border-bottom:1px solid var(--border)}.topbar a{text-decoration:none}.brand{font-weight:700;font-size:1.1rem;color:var(--fg);display:flex;align-items:center;gap:.4rem}.brand:hover{text-decoration:none}.brand-mark{font-size:1.3rem}.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border:0;background:transparent;color:var(--fg-muted);cursor:pointer;border-radius:var(--radius);font-size:1.1rem}.icon-btn:hover{background:var(--bg-alt);color:var(--fg);text-decoration:none}.topbar-actions{display:flex;align-items:center;gap:.75rem;margin-left:auto}.topbar-links{display:flex;align-items:center;gap:1rem}.topbar-links:empty{display:none}.topbar-links a{color:var(--fg-muted);font-size:.9rem;font-weight:500}.topbar-links a:hover{color:var(--fg)}@media(max-width:40rem){.topbar-links{display:none}}.theme-sun{display:none}.theme-moon{display:inline}:root[data-theme=dark] .theme-sun{display:inline}:root[data-theme=dark] .theme-moon{display:none}.content{flex:1 1 auto;min-width:0;padding:2rem clamp(1rem,5vw,3rem) 4rem;display:flex;flex-direction:column;align-items:center}.page-footer{width:100%;max-width:var(--content-max);margin-top:3rem;padding-top:1.5rem;border-top:1px solid var(--border);color:var(--fg-muted);font-size:.85rem}.prose{width:100%;max-width:var(--content-max)}.prose a{text-decoration:underline}.prose a:hover{text-decoration:none}.prose h1,.prose h2,.prose h3,.prose h4{position:relative;line-height:1.25;scroll-margin-top:calc(var(--topbar-h, 0rem) + 1rem)}.prose h1{font-size:2rem;margin:0 0 1rem}.prose h2{font-size:1.5rem;margin:2.5rem 0 1rem;padding-bottom:.3rem;border-bottom:1px solid var(--border)}.prose h3{font-size:1.2rem;margin:2rem 0 .75rem}.heading-anchor{padding-left:.3em;color:var(--fg-muted);opacity:0;text-decoration:none!important}.heading-anchor:before{content:"#"}.prose :is(h1,h2,h3,h4):hover .heading-anchor,.heading-anchor:focus{opacity:1}.heading-anchor:hover{color:var(--link)}.prose p,.prose ul,.prose ol{margin:0 0 1rem}.prose li{margin:.25rem 0}.prose :is(img,video,embed,object){max-width:100%;height:auto;border-radius:var(--radius)}.prose svg{max-width:100%}.prose iframe{width:100%;aspect-ratio:16/9;height:auto;border:0;border-radius:var(--radius)}.prose hr{border:0;border-top:1px solid var(--border);margin:2rem 0}.prose :is(figure,.code-wrap){margin:1.75rem 0}.prose p:has(>:is(img,video,iframe,embed,object):only-child){margin:1.75rem 0}.prose figure{padding:0}.prose figure>:is(img,video,iframe,embed,object){display:block;margin-inline:auto}.prose figcaption{margin-top:.6rem;color:var(--fg-muted);font-size:.85rem;line-height:1.5;text-align:center}.prose :not(pre)>code{background:var(--bg-code);padding:.12em .4em;border-radius:.3rem;font-family:var(--font-mono);font-size:.875em;border:1px solid var(--border)}.prose table{width:100%;border-collapse:collapse;margin:0 0 1.25rem;font-size:.9rem;display:block;overflow-x:auto}.prose th,.prose td{border:1px solid var(--border);padding:.5rem .75rem;text-align:left}.prose thead th{background:var(--bg-alt)}.prose tbody tr:nth-child(2n){background:color-mix(in srgb,var(--fg) 4%,transparent)}.prose blockquote{margin:0 0 1rem;padding:.5rem 1rem;border-left:3px solid var(--border);color:var(--fg-muted)}.code-wrap{position:relative}.prose pre{margin:1.75rem 0;background:var(--bg-code);border:1px solid var(--border);border-radius:var(--radius);padding:1rem 3.7rem 1rem 1.1rem;overflow-x:auto;font-size:.85rem;line-height:1.6}.prose .code-wrap>pre{margin:0}.prose pre code{font-family:var(--font-mono);background:none;border:0;padding:0}.copy-btn{position:absolute;top:.7rem;right:.7rem;display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:1px solid var(--border);border-radius:.35rem;background:var(--bg);color:var(--fg-muted);cursor:pointer;transition:color .12s,border-color .12s,background .12s}.copy-btn:hover{background:var(--bg-alt);color:var(--fg)}.copy-btn .icon-check{display:none}.copy-btn.copied{color:#2f9e44;border-color:#2f9e44}.copy-btn.copied .icon-copy{display:none}.copy-btn.copied .icon-check{display:inline}.copy-btn.copied:after{content:attr(data-tip);position:absolute;top:50%;right:calc(100% + .4rem);transform:translateY(-50%);padding:.15rem .45rem;border-radius:.3rem;background:var(--fg);color:var(--bg);font-size:.7rem;font-family:var(--font-body);white-space:nowrap;pointer-events:none}.admonition,.marked-github-alert{--adm: var(--accent);margin:0 0 1.25rem;border:1px solid var(--adm);border-left:1px solid var(--adm)!important;border-radius:var(--radius);padding:0!important}.admonition p,.marked-github-alert p{padding:0 1rem}.admonition p:last-child,.marked-github-alert p:last-child{margin-bottom:.75rem}.admonition-title,.marked-github-alert-title{background:color-mix(in srgb,var(--adm) 7%,var(--bg));border-top-left-radius:var(--radius);border-top-right-radius:var(--radius);border-bottom:1px solid var(--adm);padding:.5rem 1rem!important;margin-bottom:.75rem!important;font-weight:700;font-size:.9rem;color:var(--adm);display:flex;align-items:center;gap:.4rem}.admonition-title:before{content:attr(data-icon)}.marked-github-alert-title svg{width:1rem;height:1rem;fill:currentColor}.admonition.info,.marked-github-alert-info,.marked-github-alert-important{--adm: #1c7ed6}.admonition.tip,.marked-github-alert-tip{--adm: #2f9e44}.admonition.warning,.marked-github-alert-warning{--adm: #f08c00}.admonition.caution,.marked-github-alert-caution{--adm: #e03131}.admonition.note,.marked-github-alert-note{--adm: #7048e8}.hljs-comment,.hljs-quote{color:var(--fg-muted);font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-section,.hljs-name{color:#cc5de8}.hljs-string,.hljs-attr,.hljs-template-tag,.hljs-addition{color:#2b8a3e}.hljs-number,.hljs-symbol,.hljs-bullet{color:#f76707}.hljs-title,.hljs-title.function_,.hljs-selector-id,.hljs-selector-class{color:#1c7ed6}.hljs-type,.hljs-class .hljs-title,.hljs-built_in{color:#a67500}.hljs-attribute,.hljs-variable,.hljs-tag{color:#e8590c}.hljs-meta,.hljs-deletion{color:var(--fg-muted)}:root[data-theme=dark] .hljs-keyword,:root[data-theme=dark] .hljs-selector-tag,:root[data-theme=dark] .hljs-literal,:root[data-theme=dark] .hljs-section,:root[data-theme=dark] .hljs-name{color:#e599f7}:root[data-theme=dark] .hljs-string,:root[data-theme=dark] .hljs-attr,:root[data-theme=dark] .hljs-template-tag,:root[data-theme=dark] .hljs-addition{color:#69db7c}:root[data-theme=dark] .hljs-number,:root[data-theme=dark] .hljs-symbol,:root[data-theme=dark] .hljs-bullet{color:#ffa94d}:root[data-theme=dark] .hljs-title,:root[data-theme=dark] .hljs-title.function_,:root[data-theme=dark] .hljs-selector-id,:root[data-theme=dark] .hljs-selector-class{color:#74c0fc}:root[data-theme=dark] .hljs-type,:root[data-theme=dark] .hljs-built_in{color:#ffd43b}:root[data-theme=dark] .hljs-attribute,:root[data-theme=dark] .hljs-variable,:root[data-theme=dark] .hljs-tag{color:#ffa94d}:root{--compare-images-slider-initial-position: 50%;--compare-images-slider-handle-bg: #fff;--compare-images-slider-handle-fg: #000;--compare-images-slider-handle-size: 42px;--compare-images-slider-handle-font-size: 28px}.compare-images-slider,compare-images-slider{display:block;position:relative;user-select:none;-webkit-user-select:none;-moz-user-select:none}.compare-images-slider img,compare-images-slider img{pointer-events:none}.compare-images-slider>img,compare-images-slider>img{max-width:100%;height:auto;display:block}.compare-images-slider .frame,compare-images-slider .frame{position:absolute;top:0;left:0;height:100%;width:var(--compare-images-slider-initial-position);overflow:hidden;z-index:2}.compare-images-slider .frame>img,compare-images-slider .frame>img{height:auto;display:block;max-width:none}.compare-images-slider .handle,compare-images-slider .handle{position:absolute;left:var(--compare-images-slider-initial-position);top:0;bottom:0;width:2px;margin-left:-1px;height:100%;cursor:ew-resize;z-index:3;touch-action:none}.compare-images-slider .handle:after,compare-images-slider .handle:after{position:absolute;top:50%;left:50%;width:var(--compare-images-slider-handle-size);height:var(--compare-images-slider-handle-size);transform:translate3d(-50%,-50%,0);content:"\2194";font-size:var(--compare-images-slider-handle-font-size);background:var(--compare-images-slider-handle-bg);color:var(--compare-images-slider-handle-fg);display:flex;align-items:center;justify-content:center;text-align:center;border-radius:21px}.compare-images-slider .handle:focus-visible,compare-images-slider .handle:focus-visible{outline:none}.compare-images-slider .handle:focus-visible:after,compare-images-slider .handle:focus-visible:after{outline:3px solid Highlight;outline:3px solid -webkit-focus-ring-color;outline-offset:2px}.compare-images-slider[data-vertical] .frame,.compare-images-slider[vertical] .frame,compare-images-slider[data-vertical] .frame,compare-images-slider[vertical] .frame{width:100%;height:var(--compare-images-slider-initial-position)}.compare-images-slider[data-vertical] .handle,.compare-images-slider[vertical] .handle,compare-images-slider[data-vertical] .handle,compare-images-slider[vertical] .handle{left:0;top:var(--compare-images-slider-initial-position);width:100%;height:2px;margin-top:-1px;margin-left:0;cursor:ns-resize}.compare-images-slider[data-vertical] .handle:after,.compare-images-slider[vertical] .handle:after,compare-images-slider[data-vertical] .handle:after,compare-images-slider[vertical] .handle:after{content:"\2195"}.compare-images-slider img,compare-images-slider img{border-radius:var(--radius)}.compare-images-slider,compare-images-slider{--compare-images-slider-handle-bg: var(--bg);--compare-images-slider-handle-fg: var(--fg)}.compare-images-slider .handle:after,compare-images-slider .handle:after{display:none}.compare-images-slider .handle-knob,compare-images-slider .handle-knob{position:absolute;top:50%;left:50%;width:var(--compare-images-slider-handle-size);height:var(--compare-images-slider-handle-size);transform:translate3d(-50%,-50%,0);background:var(--compare-images-slider-handle-bg);color:var(--compare-images-slider-handle-fg);display:flex;align-items:center;justify-content:center;border-radius:21px}.compare-images-slider .handle-knob svg,compare-images-slider .handle-knob svg{width:24px;height:24px;fill:currentColor}.compare-images-slider[data-vertical] .handle-knob,.compare-images-slider[vertical] .handle-knob,compare-images-slider[data-vertical] .handle-knob,compare-images-slider[vertical] .handle-knob{transform:translate3d(-50%,-50%,0) rotate(90deg)}
@@ -2,24 +2,32 @@
2
2
  @charset "UTF-8";
3
3
  :root {
4
4
  --compare-images-slider-initial-position: 50%;
5
+ --compare-images-slider-handle-bg: #fff;
6
+ --compare-images-slider-handle-fg: #000;
7
+ --compare-images-slider-handle-size: 42px;
8
+ --compare-images-slider-handle-font-size: 28px;
5
9
  }
6
10
 
7
- .compare-images-slider {
11
+ .compare-images-slider,
12
+ compare-images-slider {
8
13
  display: block;
9
14
  position: relative;
10
15
  user-select: none;
11
16
  -webkit-user-select: none;
12
17
  -moz-user-select: none;
13
18
  }
14
- .compare-images-slider img {
19
+ .compare-images-slider img,
20
+ compare-images-slider img {
15
21
  pointer-events: none;
16
22
  }
17
- .compare-images-slider > img {
23
+ .compare-images-slider > img,
24
+ compare-images-slider > img {
18
25
  max-width: 100%;
19
26
  height: auto;
20
27
  display: block;
21
28
  }
22
- .compare-images-slider .frame {
29
+ .compare-images-slider .frame,
30
+ compare-images-slider .frame {
23
31
  position: absolute;
24
32
  top: 0;
25
33
  left: 0;
@@ -28,11 +36,16 @@
28
36
  overflow: hidden;
29
37
  z-index: 2;
30
38
  }
31
- .compare-images-slider .frame > img {
39
+ .compare-images-slider .frame > img,
40
+ compare-images-slider .frame > img {
32
41
  height: auto;
33
42
  display: block;
43
+ /* The script sets this image's width to the slider's full width; a page-level
44
+ `img { max-width: 100% }` would clamp it to the frame and break the reveal. */
45
+ max-width: none;
34
46
  }
35
- .compare-images-slider .handle {
47
+ .compare-images-slider .handle,
48
+ compare-images-slider .handle {
36
49
  position: absolute;
37
50
  left: var(--compare-images-slider-initial-position);
38
51
  top: 0;
@@ -42,26 +55,45 @@
42
55
  height: 100%;
43
56
  cursor: ew-resize;
44
57
  z-index: 3;
58
+ touch-action: none;
45
59
  }
46
- .compare-images-slider .handle:after {
60
+ .compare-images-slider .handle:after,
61
+ compare-images-slider .handle:after {
47
62
  position: absolute;
48
63
  top: 50%;
49
64
  left: 50%;
50
- width: 42px;
51
- height: 42px;
65
+ width: var(--compare-images-slider-handle-size);
66
+ height: var(--compare-images-slider-handle-size);
52
67
  transform: translate3d(-50%, -50%, 0);
53
68
  content: "↔";
54
- line-height: 38px;
55
- font-size: 28px;
56
- background: #fff;
69
+ font-size: var(--compare-images-slider-handle-font-size);
70
+ background: var(--compare-images-slider-handle-bg);
71
+ color: var(--compare-images-slider-handle-fg);
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: center;
57
75
  text-align: center;
58
76
  border-radius: 21px;
59
77
  }
60
- .compare-images-slider[data-vertical] .frame, .compare-images-slider[vertical] .frame {
78
+ .compare-images-slider .handle:focus-visible,
79
+ compare-images-slider .handle:focus-visible {
80
+ outline: none;
81
+ }
82
+ .compare-images-slider .handle:focus-visible:after,
83
+ compare-images-slider .handle:focus-visible:after {
84
+ outline: 3px solid Highlight;
85
+ outline: 3px solid -webkit-focus-ring-color;
86
+ outline-offset: 2px;
87
+ }
88
+ .compare-images-slider[data-vertical] .frame, .compare-images-slider[vertical] .frame,
89
+ compare-images-slider[data-vertical] .frame,
90
+ compare-images-slider[vertical] .frame {
61
91
  width: 100%;
62
92
  height: var(--compare-images-slider-initial-position);
63
93
  }
64
- .compare-images-slider[data-vertical] .handle, .compare-images-slider[vertical] .handle {
94
+ .compare-images-slider[data-vertical] .handle, .compare-images-slider[vertical] .handle,
95
+ compare-images-slider[data-vertical] .handle,
96
+ compare-images-slider[vertical] .handle {
65
97
  left: 0;
66
98
  top: var(--compare-images-slider-initial-position);
67
99
  width: 100%;
@@ -70,7 +102,9 @@
70
102
  margin-left: 0;
71
103
  cursor: ns-resize;
72
104
  }
73
- .compare-images-slider[data-vertical] .handle:after, .compare-images-slider[vertical] .handle:after {
105
+ .compare-images-slider[data-vertical] .handle:after, .compare-images-slider[vertical] .handle:after,
106
+ compare-images-slider[data-vertical] .handle:after,
107
+ compare-images-slider[vertical] .handle:after {
74
108
  content: "↕";
75
109
  }
76
110
  /*# sourceMappingURL=compare-images-slider.css.map */
@@ -1 +1 @@
1
- {"version":3,"sourceRoot":"","sources":["file:///Users/stamat/Sites/localhost/compare-images-slider/src/styles/index.scss"],"names":[],"mappings":";;AAAA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAKA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE","sourcesContent":[":root {\n --compare-images-slider-initial-position: 50%;\n}\n\n.compare-images-slider {\n display: block;\n position: relative;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n\n img {\n pointer-events: none;\n }\n\n & > img {\n max-width: 100%;\n height: auto;\n display: block;\n }\n\n .frame {\n position: absolute;\n top:0;\n left: 0;\n height: 100%;\n width: var(--compare-images-slider-initial-position);\n overflow: hidden;\n z-index: 2;\n\n & > img {\n height: auto;\n display: block;\n }\n }\n\n .handle {\n position:absolute;\n left: var(--compare-images-slider-initial-position);\n top:0;\n bottom:0;\n width: 2px;\n margin-left: -1px;\n height: 100%;\n cursor: ew-resize;\n z-index: 3;\n }\n\n .handle:after {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 42px;\n height: 42px;\n transform: translate3d(-50%, -50%, 0);\n\n content:'↔';\n line-height: 38px;\n font-size: 28px;\n background: #fff;\n text-align: center;\n border-radius: 21px;\n }\n\n &[data-vertical],\n &[vertical] {\n .frame {\n width: 100%;\n height: var(--compare-images-slider-initial-position);\n }\n\n .handle {\n left: 0;\n top: var(--compare-images-slider-initial-position);\n width: 100%;\n height: 2px;\n margin-top: -1px;\n margin-left: 0;\n cursor: ns-resize;\n }\n\n .handle:after {\n content:'↕';\n }\n }\n}\n"]}
1
+ {"version":3,"sourceRoot":"","sources":["file:///Users/stamat/Sites/localhost/compare-images-slider/src/styles/index.scss"],"names":[],"mappings":";;AAAA;EACE;EACA;EACA;EACA;EACA;;;AAGF;AAAA;EAEE;EACA;EACA;EACA;EACA;;AAEA;AAAA;EACE;;AAGF;AAAA;EACE;EACA;EACA;;AAGF;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;EACE;EACA;AACA;AAAA;EAEA;;AAIJ;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;AAAA;EACE;;AAGF;AAAA;EACE;EACA;EACA;;AAKA;AAAA;AAAA;EACE;EACA;;AAGF;AAAA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;AAAA;AAAA;EACE","sourcesContent":[":root {\n --compare-images-slider-initial-position: 50%;\n --compare-images-slider-handle-bg: #fff;\n --compare-images-slider-handle-fg: #000;\n --compare-images-slider-handle-size: 42px;\n --compare-images-slider-handle-font-size: 28px;\n}\n\n.compare-images-slider,\ncompare-images-slider {\n display: block;\n position: relative;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n\n img {\n pointer-events: none;\n }\n\n & > img {\n max-width: 100%;\n height: auto;\n display: block;\n }\n\n .frame {\n position: absolute;\n top:0;\n left: 0;\n height: 100%;\n width: var(--compare-images-slider-initial-position);\n overflow: hidden;\n z-index: 2;\n\n & > img {\n height: auto;\n display: block;\n /* The script sets this image's width to the slider's full width; a page-level\n `img { max-width: 100% }` would clamp it to the frame and break the reveal. */\n max-width: none;\n }\n }\n\n .handle {\n position:absolute;\n left: var(--compare-images-slider-initial-position);\n top:0;\n bottom:0;\n width: 2px;\n margin-left: -1px;\n height: 100%;\n cursor: ew-resize;\n z-index: 3;\n touch-action: none;\n }\n\n .handle:after {\n position: absolute;\n top: 50%;\n left: 50%;\n width: var(--compare-images-slider-handle-size);\n height: var(--compare-images-slider-handle-size);\n transform: translate3d(-50%, -50%, 0);\n\n content:'↔';\n font-size: var(--compare-images-slider-handle-font-size);\n background: var(--compare-images-slider-handle-bg);\n color: var(--compare-images-slider-handle-fg);\n display: flex;\n align-items: center;\n justify-content: center;\n text-align: center;\n border-radius: 21px;\n }\n\n .handle:focus-visible {\n outline: none;\n }\n\n .handle:focus-visible:after {\n outline: 3px solid Highlight;\n outline: 3px solid -webkit-focus-ring-color;\n outline-offset: 2px;\n }\n\n &[data-vertical],\n &[vertical] {\n .frame {\n width: 100%;\n height: var(--compare-images-slider-initial-position);\n }\n\n .handle {\n left: 0;\n top: var(--compare-images-slider-initial-position);\n width: 100%;\n height: 2px;\n margin-top: -1px;\n margin-left: 0;\n cursor: ns-resize;\n }\n\n .handle:after {\n content:'↕';\n }\n }\n}\n"]}