The Free Component Library · Volume 01
Useful Interface Details, Ready to Borrow.
Six dependency-free components with live states, practical notes, and source you can paste into an ordinary HTML file.
Liquid Glass Button
A refractive glass pill with a live WebGL chromatic-metal orb, a rotating gradient stroke, and an SVG lens that bends whatever sits behind it. One file, zero dependencies.
Copy the Source
<script src="cm-liquid-button.js" defer></script>
<button data-lgb>Get started</button>
<button data-lgb data-lgb-preset="northern">Text me</button>
<!-- shader under the glass (original recipe) -->
<button data-lgb data-lgb-crisp="false">Warped orb</button>
<!-- full control from JS -->
<script>
CMLiquidButton.upgrade(document.querySelector('#cta'), {
gradient: ['#5c6168', '#f2f5f8', '#ffffff', '#545963'],
orbSettings: { speed: 0.5, rgbSplit: 0.03 },
glass: { refraction: 32, dispersion: 0.35 }
});
// SPA teardown: stops the loop, restores the button
CMLiquidButton.destroy(document.querySelector('#cta'));
</script>
<!-- set label color per surface -->
<style>
.my-dark-hero .lgb { --lgb-text: #fff; }
</style>
Loading the source…
Tactile Glass Card
A content surface with pointer-responsive tilt and glare whose depth makes interaction legible rather than merely decorative.
Copy the Source
<div class="cm-glass-card-wrap">
<a class="cm-glass-card" href="/notes/depth">
<span class="cm-glass-card__glare" aria-hidden="true"></span>
<span class="cm-glass-card__meta">Interface Note · 01</span>
<strong class="cm-glass-card__title">
Depth should clarify what can move.
</strong>
<span class="cm-glass-card__arrow">Read the note →</span>
</a>
</div>
Loading the source…
Loading the source…
Glass Toggle
A switch with real weight: a sunken glass track, a springy thumb that squashes under press, and a checked state that changes color honestly.
Copy the Source
<!-- the visible text IS the accessible name -->
<div class="cm-glass-toggle-row">
<button class="cm-glass-toggle" type="button"
role="switch" aria-checked="true"
aria-labelledby="sync-label"></button>
<span id="sync-label">Ambient sync</span>
</div>
Loading the source…
Loading the source…
Glass Input
A sunken glass field with a calm focus ring and an invalid state driven entirely by aria-invalid — accessibility and styling from the same attribute.
That email address does not look valid.
Copy the Source
<div class="cm-glass-field">
<label class="cm-glass-field__label" for="ws">
Workspace name
</label>
<input class="cm-glass-input" id="ws"
type="text" placeholder="northern-clearing">
</div>
<!-- invalid: set aria-invalid + describedby -->
<div class="cm-glass-field">
<label class="cm-glass-field__label" for="email">
Email address
</label>
<input class="cm-glass-input" id="email" type="email"
aria-invalid="true" aria-describedby="email-error">
<p class="cm-glass-field__error" id="email-error">
That email address does not look valid.
</p>
</div>
Loading the source…
Glass Dialog
A frosted modal built on the native <dialog> element — focus trap, Escape, inert background, and backdrop come from the platform, not from a library.
Copy the Source
<button type="button" data-dialog-open="confirm-dialog">
Open the dialog
</button>
<dialog class="cm-glass-dialog" id="confirm-dialog"
aria-labelledby="confirm-title">
<div class="cm-glass-dialog__body">
<h2 class="cm-glass-dialog__title" id="confirm-title">
Clear this draft?
</h2>
<p class="cm-glass-dialog__copy">
The draft goes away permanently.
</p>
<!-- method="dialog" buttons close natively -->
<form method="dialog" class="cm-glass-dialog__actions">
<button class="cm-glass-dialog__button"
value="cancel">Keep it</button>
<button class="cm-glass-dialog__button
cm-glass-dialog__button--primary"
value="confirm">Clear draft</button>
</form>
</div>
</dialog>
Loading the source…
Loading the source…
That’s Volume 01
More When They’re Worth Sharing.
I’ll add components when I have something genuinely reusable—not to make the grid look fuller.
Back to Casey’s site