Slide To Submit 2024
by kthornbloom
HTML
<div class="s2s">
<div class="s2s-submitting">
Placing Your Order
</div>
<div id="s2s-live-region" aria-live="assertive"></div>
<div class="s2s-message">
Slide To Submit
</div>
<div class="s2s-message-anim"></div>
<div class="s2s-green"></div>
<button class="s2s-thumb" aria-label="To buy this item now, drag this button or tap the right arrow key three times for keyboard users.">
<div class="s2s-icon"></div>
</button>
</div>
CSS
:root {
--thumbsize: 50px;
}
@keyframes fade {
0% {background-position-x: 0}
0% {background-position-x: -300px}
}
@keyframes spin {
0% {transform: rotate(0deg)}
100% {transform: rotate(360deg)}
}
.s2s {
background: #434750;
color: #fff;
border: 1px solid #ccc;
border-radius: var(--thumbsize);
height: var(--thumbsize);
position: relative;
width: 300px;
max-width: 100%;
}
.s2s-message {
background: #434750;
box-shadow: inset 0 0 20px #00000050;
border-radius: var(--thumbsize);
box-sizing: border-box;
position: absolute;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
padding-left: 30px;
position: absolute;
right: 0;
top: 0;
}
#s2s-live-region {
position: absolute;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
white-space: nowrap;
}
@media (prefers-reduced-motion: no-preference) {
.s2s-message-anim {
width: 100%;
height: 100%;
border-radius: var(--thumbsize);
position: absolute;
background: linear-gradient(90deg, #43475000 20%, #43475080, #43475000 70%);
animation: 1s fade infinite linear;
left: 0;
top: 0;
}
}
.s2s-green {
width: 100%;
height: 100%;
border-radius: var(--thumbsize);
position: absolute;
background: linear-gradient(90deg, #2c681c, #284d1f);
left: 0;
top: 0;
opacity: 0;
}
.s2s-thumb {
width: calc(var(--thumbsize) - 4px);
height: calc(var(--thumbsize) - 4px);
margin: 2px;
background: #3a7d19;
position: absolute;
outline: none;
border-radius: 50px;
outline: none;
top: 0;
left: 0;
border: none;
display: flex;
align-items: center;
justify-content: center;
...
JavaScript
const dragHandle = document.querySelector('.s2s-thumb');
handleDrag(dragHandle, handleDragSubmit);
keyboardDrag(dragHandle, handleDragSubmit);
function handleDragSubmit() {
console.log('submit');
const processingMessage = document.querySelector('.s2s-submitting');
processingMessage.classList.add('s2s-submitting-active')
}
function keyboardDrag(element, callback) {
var rightKeyTapCount = 0;
const parentWidth = element.parentNode.clientWidth - 50;
var liveRegion = document.getElementById('s2s-live-region');
element.addEventListener('keydown', function(event) {
if (event.key === 'ArrowRight') {
rightKeyTapCount++
liveRegion.innerHTML = '';
var plural = 's';
if (rightKeyTapCount >= 3) {
element.style.left = parentWidth + 'px';
var newText = document.createTextNode('Submitting Order. Please stay on this page.');
liveRegion.appendChild(newText);
callback();
} else {
if (rightKeyTapCount === 2) {
plural = '';
}
var newText = document.createTextNode('Tap the right arrow ' + (3 - rightKeyTapCount) + ' more time' + plural + ' to buy now.');
liveRegion.appendChild(newText);
element.style.left = (parentWidth / 3) * rightKeyTapCount + 'px';
}
}
});
}
function handleDrag(element, callback) {
let isDragging = false;
let startX = 0;
let offsetX = 0;
const parentWidth = element.parentNode.clientWidth - 50,
icon = element.querySelector('.s2s-icon'),
greenbg = element.parentNode.querySelector('.s2s-green');
// Function to update the element's position, rotation, and height
function updatePositionRotationAndHeight(x) {
offsetX = x - startX;
if (offsetX < 0) offsetX = 0; // Prevent dragging outside left edge
if (offsetX > parentWidth) offsetX = parentWidth; // Prevent dragging outside right edge
// Calculate percentage of movement within the draggable range
const percentage = offsetX /...