Skip to content

Commit

Permalink
fix argyleink#20: radio role to hint at arrow keys for screen reader …
Browse files Browse the repository at this point in the history
…users

also added demo
  • Loading branch information
hchiam committed Jun 26, 2024
1 parent bbeb454 commit 81e0226
Show file tree
Hide file tree
Showing 18 changed files with 317 additions and 9 deletions.
15 changes: 15 additions & 0 deletions demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Demo

```sh
yarn dev
```

or

```sh
npm run dev
```

then

http://localhost:5173/
7 changes: 7 additions & 0 deletions demo/arrowkey-support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {rovingIndex} from '../index'
console.log('rovingIndex',rovingIndex);

rovingIndex({
element: document.querySelector('.threeD-button-set'),
target: 'button',
})
177 changes: 177 additions & 0 deletions demo/game-menu.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
body {
perspective: 40vw;
}

.threeD-button-set {
--y:;
--x:;
--distance: 1px;
--theme: hsl(180 100% 50%);
--theme-bg: hsl(180 100% 50% / 25%);
--theme-bg-hover: hsl(180 100% 50% / 40%);
--theme-text: white;
--theme-shadow: hsl(180 100% 10% / 25%);

--_max-rotateY: 10deg;
--_max-rotateX: 15deg;
--_btn-bg: var(--theme-bg);
--_btn-bg-hover: var(--theme-bg-hover);
--_btn-text: var(--theme-text);
--_btn-text-shadow: var(--theme-shadow);
--_bounce-ease: cubic-bezier(.5, 1.75, .75, 1.25);

/* remove <ul> margins */
margin: 0;

/* vertical rag-right layout */
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 2.5vh;

/* create 3D space context */
transform-style: preserve-3d;

/* clamped menu rotation to not be too extreme */
transform:
rotateY(
clamp(
calc(var(--_max-rotateY) * -1),
var(--y),
var(--_max-rotateY)
)
)
rotateX(
clamp(
calc(var(--_max-rotateX) * -1),
var(--x),
var(--_max-rotateX)
)
)
;

/* removes Safari focus ring on <ul> after button interaction */
&:focus {
outline: none;
}

@media (--motionOK) {
will-change: transform;
transition: transform .1s ease;
animation: rotate-y 5s ease-in-out infinite;
}

@media (--dark) {
--theme: hsl(255 53% 50%);
--theme-bg: hsl(255 53% 71% / 25%);
--theme-bg-hover: hsl(255 53% 50% / 40%);
--theme-shadow: hsl(255 53% 10% / 25%);
}

@media (--HDcolor) {
@supports (color: color(display-p3 0 0 0)) {
--theme: color(display-p3 .4 0 .9);
}
}
}

.threeD-button-set > li {
/* change display type from list-item */
display: inline-flex;

/* create context for button pseudos */
position: relative;

/* create 3D space context */
transform-style: preserve-3d;
}

.threeD-button-set button {
/* strip out default button styles */
appearance: none;
outline: none;
border: none;
-webkit-tap-highlight-color: transparent;

/* bring in brand styles via props */
background-color: var(--_btn-bg);
color: var(--_btn-text);
text-shadow: 0 1px 1px var(--_btn-text-shadow);

font-size: min(5vmin, 3rem);
font-family: Audiowide;
padding-block: .75ch;
padding-inline: 2ch;
border-radius: 5px 20px;

/* prepare for 3D perspective transforms */
transform: translateZ(var(--distance));
transform-style: preserve-3d;

&:is(:hover, :focus-visible):not(:active) {
/* subtle distance plus bg color change on hover/focus */
--distance: 15px;
background-color: var(--_btn-bg-hover);

/* if motion is OK, setup transitions and increase distance */
@media (--motionOK) {
--distance: 3vmax;

transition-timing-function: var(--_bounce-ease);
transition-duration: .4s;

&::after { transition-duration: .5s }
&::before { transition-duration: .3s }
}
}

&::after,
&::before {
/* create empty element */
content: '';
opacity: .8;

/* cover the parent (button) */
position: absolute;
inset: 0;

/* style the element for border accents */
border: 1px solid var(--theme);
border-radius: 5px 20px;

/* move in Z space with a multiplier */
transform: translateZ(calc(var(--distance) / 3));

/* if motion is OK, transition the Z space move */
@media (--motionOK) {
transition: transform .1s ease-out;
}
}

/* exceptions for one of the pseudo elements */
/* this will be pushed back and have a thicker border */
&::before {
border-width: 3px;
transform: translateZ(calc(var(--distance) / 3 * -1));

/* in dark mode, it glows! */
@media (--dark) {
box-shadow:
0 0 25px var(--theme),
inset 0 0 25px var(--theme);
}
}

@media (--motionOK) {
will-change: transform;
transition:
transform .2s ease,
background-color .5s ease;
}
}

@keyframes rotate-y {
50% {
transform: rotateY(15deg) rotateX(-6deg);
}
}
19 changes: 19 additions & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>demo</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<ul class="threeD-button-set">
<li><button>New Game</button></li>
<li><button>Continue</button></li>
<li><button>Online</button></li>
<li><button>Settings</button></li>
<li><button>Quit</button></li>
</ul>
<script type="module" src="index.js"></script>
</body>
</html>
2 changes: 2 additions & 0 deletions demo/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import './arrowkey-support.js'
import './mouse-parallax.js'
24 changes: 24 additions & 0 deletions demo/mouse-parallax.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const menu = document.querySelector('.threeD-button-set')
const menuRect = menu.getBoundingClientRect()

const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)

if (motionOK) {
window.addEventListener('mousemove', ({target, clientX, clientY}) => {
const {dx,dy} = getAngles(clientX, clientY)

menu.style.setProperty('--x', `${dy / 20}deg`)
menu.style.setProperty('--y', `${dx / 20}deg`)
})
}

const getAngles = (clientX, clientY) => {
const { x, y, width, height } = menuRect

const dx = clientX - (x + 0.5 * width)
const dy = clientY - (y + 0.5 * height)

return {dx,dy}
}
9 changes: 9 additions & 0 deletions demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"scripts": {
"start": "vite",
"dev": "vite"
},
"devDependencies": {
"vite": "2.x || >2.0.0-alpha"
}
}
49 changes: 49 additions & 0 deletions demo/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
@import url('https://fonts.googleapis.com/css2?family=Audiowide&display=swap');
@import "game-menu.css";

@custom-media --motionOK (prefers-reduced-motion: no-preference);
@custom-media --dark (prefers-color-scheme: dark);
@custom-media --HDcolor (dynamic-range: high);

* {
box-sizing: border-box;
margin: 0;
}

html {
block-size: 100%;
background: conic-gradient(at -10% 50%, deeppink, cyan);

@media (--dark) {
background: conic-gradient(at -10% 50%, #212529, 50%, #495057, #212529);
}
}

body {
min-block-size: 100%;
font-family: system-ui, sans-serif;

display: grid;
place-content: center;
}

.github-corner {
fill: indigo;
color: white;

&:hover .octo-arm {
animation: octocat-wave 560ms ease-in-out
}
}

@keyframes octocat-wave{
0%,100% {
transform: rotate(0)
}
20%,60% {
transform: rotate(-25deg)
}
40%,80% {
transform: rotate(10deg)
}
}
2 changes: 1 addition & 1 deletion dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 81e0226

Please sign in to comment.