Reason
We needed to explain technical terms to a general audience without interrupting their reading flow.
While popovers work for short definitions, some terms required more depth, so I created Clavis to bridge that gap.
Tap Clavis
Clavis explaining Obfuscation.
Idea
Clavis is a bottom-aligned pill-like component. It stays at the bottom of the screen and displays a preview of the selected word and expands into a full view when tapped.
Why?
I wanted an experience that feels natural and fluid, without disrupting the user's reading flow. It should be easy to minimize or expand, allowing users to click a word and see its meaning without the friction of opening and closing a modal.
Clavis
Latin
cla·vis (noun)
A key or glossary serving as an aid to interpretation.
Inspiration
Inspired by the Dynamic Island, Clavis provides supplementary information through subtle, non-intrusive previews that maintain the user's focus.
Tools
Built with React, Clavis prioritises performance for a broad audience.
Rather than using Motion (Framer Motion formerly), I utilized the Web Animations API and CSS lightweight transitions without the overhead of a heavy library.
Animation
The component animates width, height, opacity, bottom, and scale.
To create a smooth animation, I used a custom linear easing function for most transitions and an ease-in-out curve for the opacity.
animation-timing-function: linear(0, 0.01, 0.02, 0.1 6%, 0.53 18%, 0.71, 0.84 31%, 0.89, 0.93, 0.96, 0.98, 1 49%, 1.01 55% 64%, 1);Custom linear Ease:
Ease In Out:
Feedback
For tactile feedback, I implemented vibration. While this is a single line of code on Android:
navigator.vibrate(50);iOS/Safari presented a challenge as they do not support the standard Vibration API.
Vibration API not supported
I discovered that while programmatically clicking a hidden checkbox - with a switch attribute - fails to trigger haptics, triggering a click on its associated label successfully bypasses the restriction, enabling haptic feedback for iOS users.
let el = document.createElement("div");
el.innerHTML = `<input type="checkbox" id="unique_id" switch />
<label for="unique_id"></label>`;
el.setAttribute(
"style",
`opacity:0 !important;
display:none !important;
visibility:hidden !important;`
);
document.querySelector("body")?.appendChild(el);
el.querySelector("label")?.click();
setTimeout(function () {
el.remove();
}, 1000);
By routing the interaction through the label rather than the checkbox itself, it becomes possible to provide haptic feedback on iOS.
Accessibility
The Clavis component follows WAI-ARIA patterns to ensure it is usable by everyone, including those using screen readers or those with vestibular (motion) sensitivities.
Reduce Motion
Clavis respects the prefers-reduced-motion media query by forcing animation timings to zero across both CSS and the Web Animations API.
I centralize my animation logic by using variables for easing functions and durations to maintain consistency.
#clavis {
--2ms: 0.2s;
--4ms: 0.4s;
--45ms: 0.45s;
}
This approach allows for quick, global adjustments to animation timings without refactoring individual components.
@media (prefers-reduced-motion: reduce) {
#clavis {
--2ms: 0s;
--4ms: 0s;
--45ms: 0s;
}
}
Since Clavis utilizes the Web Animations API, I implemented a check to detect if the user has prefers-reduced-motion enabled in their system settings.
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;As a final step, I programmatically set the animation duration to 0ms whenever reduced motion is active to ensure an accessible experience.
duration: prefersReducedMotion ? 0 : 450,This effectively disables motion while preserving the underlying logic, ensuring a comfortable experience for all users.
Production
While the original article pivoted to external links for in-depth definitions, Clavis found a new home in form design. It now serves as a dynamic guide, expanding to explain specific requirements and steps as users fill out complex forms.