<div id="root" class="app"></div>
:focus-visible {
outline: 4px dashed orange;
}
.app {
display: flex;
box-sizing: border-box;
margin: 2rem auto;
padding: 2rem;
width: calc(100% - 4rem);
min-width: 200px;
background-color: #fff;
border-radius: 0.5rem;
font-size: 1.5rem;
}
.custom-button {
display: inline-flex;
justify-content: center;
background-color: #f1f2f3;
min-width: 140px;
box-shadow: inset -3px -3px 6px 0 rgba(#000, 0.15),
1px 1px 2px 0 rgba(#000, 0.15), 2px 2px 4px 0 rgba(#000, 0.15);
padding: 0.35rem 0.5rem;
border-radius: 10px;
cursor: pointer;
&:active,
&-pressed {
box-shadow: inset 3px 3px 6px 0 rgba(#000, 0.15),
-1px -1px 2px 0 rgba(#000, 0.15), -2px -2px 4px 0 rgba(#000, 0.15);
}
}
.button-demo-message {
padding: 2rem;
font-size: 1.2rem;
border: 1px solid #dadada;
margin: 2rem 0 0;
&:empty {
display: none;
}
}
View Compiled
import React from "https://esm.sh/react@18.2.0";
import ReactDOM from "https://esm.sh/react-dom@18.2.0";
//////////////////////
const KEY = {
Enter: 'Enter',
Spacebar: ' ',
}
function useButton({ onClick, className }) {
const [isPressed, setIsPressed] = React.useState(false);
const onKeyDown = (e) => {
if (e.key === KEY.Enter || e.key === KEY.Spacebar) {
onClick(e);
setIsPressed(true);
}
};
const onKeyUp = (e) => {
if (e.key === KEY.Enter || e.key === KEY.Spacebar) {
setIsPressed(false);
}
};
return {
isPressed,
a11yProps: {
tabIndex: 0,
role: "button"
},
eventProps: {
onClick,
onKeyDown,
onKeyUp
}
};
}
function App() {
const [clickedMessage, setClicked] = React.useState("");
const onClick = (_) => {
setClicked("button clicked!");
setTimeout(() => setClicked(""), 350);
};
const { isPressed, a11yProps, eventProps, restProps } = useButton({
onClick
});
let className = "custom-button";
if (isPressed) {
className += " custom-button-pressed";
}
return (
<div className="button-demo">
<span className={className} {a11yProps} {eventProps}>
Click Me
</span>
<div className="button-demo-message" aria-live="polite">
{clickedMessage}
</div>
</div>
);
}
// Render
ReactDOM.render(<App />, document.getElementById("root"));
View Compiled
This Pen doesn't use any external JavaScript resources.