JSFiddle - React, Tailwind, and code Playground
by Chris Ball
HTML
<link href="https://fonts.cdnfonts.com/css/lexend-deca" rel="stylesheet" />
<style>@import url('https://fonts.cdnfonts.com/css/lexend-deca');</style>
<div id="cursor"></div>
<div>
<span>See more</span>
<span>See EVEN more</span>
</div>
<button class="small">Buy Tickets</button>
<button>Buy Tickets</button>
<button class="large">Buy Tickets</button>
<div class="var var-one">Variant One</div>
<div class="var var-two">Variant Two</div>
<canvas></canvas>
CSS
:root {
--her-purple: #4E3366;
--her-pink: #FFCCD0;
}
html, body {
font-family: 'Lexend Deca', sans-serif;
height: 100%;
}
#cursor {
background: var(--her-pink);
border-radius: 500px;
/* padding: 0.5em; */
left:0;
line-height: 1;
pointer-events: none!important;
position: fixed;
top:0;
transition: transform 80ms, opacity 600ms;
z-index: 20000;
& .contents {
white-space: nowrap;
}
&.transition-contents .contents {
transition-property: height width;
transition-duration: 200ms;
transition-delay: 150ms;
}
}
@property --button_blur-start-color{
syntax: "<color>";
inherits: true;
initial-value: transparent;
}
button {
--button_blur-start: 0.5em;
--button_blur-end: 3.5em;
--button_hover-bg-color: hsl(from var(--her-pink) h s calc(l + 6));
/* --button_hover-bg-color: transparent; */
--x-pos: 0;
--y-pos: 0;
background-color: transparent;
background-image: radial-gradient(
circle at var(--x-pos) var(--y-pos),
var(--button_blur-start-color) var(--button_blur-start),
transparent var(--button_blur-end)
);
border: none;
border-radius: 100vmax;
color: var(--her-purple);
font-family: inherit;
font-size: inherit;
font-feature-settings: "ss01" 1;
font-variation-settings: "wght" 550;
overflow: hidden;
padding: 0.5em 0.75em;
transition: background-color 600ms, --button_blur-start-color 300ms;
/* Size variants */
&.large { font-size: 21px }
&.small { font-size: 13px }
&:hover {
--button_blur-start-color: var(--her-pink);
background-color: var(--button_hover-bg-color);
}
}
.var {
background: #faece5;
margin: 0 0 1rem;
padding: 1rem;
}
TypeScript
/****************************************
* Button Shit
****************************************/
let buttons = document.querySelectorAll('button')
let output = document.querySelector('#output')
;[...buttons].forEach((button) => {
button.addEventListener('mousemove', ({ offsetX, offsetY }) => {
requestAnimationFrame(() => {
button.setAttribute('style', `--x-pos:${offsetX}px; --y-pos:${offsetY}px;`)
})
})
})
/****************************************
* Cursor Shit
****************************************/
type Variation ={
selector: string
content: string
width?: string
}
type Variations = Array<Variation>
type Config = {
selector?: String
hiddenOn?: Array<String>
delay?: Number
fontFamily?: String
fontSize?: String
variations?: Variations
}
class Cursory {
// Configurable
selector = '#cursor'
hiddenOn = []
delay = 1
fontSize = '1em'
variations = []
#el = null
#elContents
#cursorX = 0
#cursorY = 0
#x = 0
#y = 0
#isHidden = false
constructor(config: Config) {
Object.assign(this, config)
this.#el = document.querySelector(this.selector)
this.#elContents = document.createElement("div")
this.#elContents.classList.add('contents')
this.#el.appendChild(this.#elContents)
this.addListeners()
this.measureVariantContent()
requestAnimationFrame(this.updateLoop)
}
addListeners = () => {
document.body.addEventListener('mousemove', (e) => this.onMouseMove(e))
document.documentElement.addEventListener('mouseleave', () => this.hide())
document.documentElement.addEventListener('mouseenter', () => this.show())
}
onMouseMove = (e: MouseEvent) => {
this.#cursorX = e.clientX
this.#cursorY = e.clientY
const target = e.target as HTMLElement
const variation = this.variations.find(v => target.closest(v.selector))
variation
? this.injectContent(variation)
: this.removeContent()
const shouldHide = this.hiddenOn.find(h =>...