Something went wrong. Try again.
https://clembs.com
Something went wrong. Try again.
3.6 kB · 148 lines
Astro
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149---import type { HTMLAttributes } from 'astro/types';import { getTheme } from 'src/layouts/theme';
type Props = HTMLAttributes<'input'> & { 'thumb-size'?: string;};
const { baseHue } = getTheme(Astro);
const INITIAL_VALUE = 266;
const { 'thumb-size': thumbSize, ...restProps } = Astro.props;---
<script> const inputs = document.querySelectorAll<HTMLInputElement>('[name="global-base-hue"]');
inputs.forEach((i) => { i.value = i.dataset.initialValue as string;
i.addEventListener('input', (ev) => { const value = (ev.currentTarget as HTMLInputElement)?.value; document.documentElement.style.setProperty('--base-hue', value); // tell the body the hue has updated, to update all other base hue inputs document.documentElement.dispatchEvent( new CustomEvent('onbasehueupdate', { detail: { value } }), ); }); });
document.documentElement.addEventListener('onbasehueupdate', (ev) => { // barebones checking if ev.detail.value exists and is a numeric string if ( !('detail' in ev) || !ev.detail || typeof ev.detail !== 'object' || !('value' in ev.detail) || typeof ev.detail.value !== 'string' || isNaN(parseInt(ev.detail.value)) ) return;
const value = ev.detail.value; // sync all base hue inputs inputs.forEach((i) => { i.value = value; // to reset the slider back to the original value i.setAttribute('value', value); }); });</script>
<input type="range" name="global-base-hue" min="0" max="360" value={baseHue ?? INITIAL_VALUE} data-initial-value={baseHue ?? INITIAL_VALUE} style={`--thumb-size: ${thumbSize ?? '1.75rem'}`} {...restProps}/>
<style lang="scss"> [name='global-base-hue'] { --border-size: calc(var(--thumb-size) * 0.1875);
-webkit-appearance: none; appearance: none;
background: transparent; width: 100%; height: var(--thumb-size); border-radius: 99px;
cursor: grab;
&:hover { &::-webkit-slider-thumb { transform: scale(1.1); } &::-moz-range-thumb { transform: scale(1.1); } }
&:active { cursor: grabbing;
&::-webkit-slider-thumb { transform: scale(0.95); } &::-moz-range-thumb { transform: scale(0.95); } }
@mixin thumb { background-color: var(--color-500); border: var(--border-size) solid white; box-shadow: 0 0 0 3px var(--color-600); border-radius: 99px;
-webkit-appearance: none; appearance: none; transition: transform 150ms; }
@mixin track { height: var(--thumb-size); border-radius: 99px;
background: linear-gradient( 90deg, oklch(0.5 0.3 0) 0%, oklch(0.6 0.3 36) 10%, oklch(0.7 0.3 72) 20%, oklch(0.7 0.3 108) 30%, oklch(0.6 0.3 144) 40%, oklch(0.5 0.3 180) 50%, oklch(0.5 0.3 216) 60%, oklch(0.5 0.3 252) 70%, oklch(0.5 0.3 288) 80%, oklch(0.5 0.3 324) 90%, oklch(0.5 0.3 360) 100% ); }
&::-webkit-slider-thumb { @include thumb; height: var(--thumb-size); width: var(--thumb-size); } &::-moz-range-thumb { @include thumb; height: calc(var(--thumb-size) - var(--border-size) * 2); width: calc(var(--thumb-size) - var(--border-size) * 2); }
&::-moz-range-track { @include track; } &::-webkit-slider-runnable-track { @include track; } }</style>