Add a custom site cursor component
This commit is contained in:
81
app/cursor.css
Normal file
81
app/cursor.css
Normal file
@@ -0,0 +1,81 @@
|
||||
/* Immediate aiming dot, soft ring follow, and an arrow on actionable targets. */
|
||||
.site-cursor {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 100;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity 120ms;
|
||||
}
|
||||
.site-cursor[data-visible="true"] {
|
||||
opacity: 1;
|
||||
}
|
||||
.site-cursor-ring,
|
||||
.site-cursor-dot {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
will-change: transform;
|
||||
}
|
||||
.site-cursor-orbit {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
margin: -18px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border: 1px solid #dbead0a6;
|
||||
border-radius: 50%;
|
||||
color: #162310;
|
||||
transition:
|
||||
transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1),
|
||||
background-color 220ms,
|
||||
border-color 220ms;
|
||||
}
|
||||
.site-cursor-orbit svg {
|
||||
opacity: 0;
|
||||
transform: translate(-3px, 3px) scale(0.75);
|
||||
transition:
|
||||
opacity 160ms,
|
||||
transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
|
||||
}
|
||||
.site-cursor-dot span {
|
||||
display: block;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
margin: -2px;
|
||||
border-radius: 50%;
|
||||
background: #f0f6eb;
|
||||
box-shadow: 0 0 1px #081006;
|
||||
transition:
|
||||
opacity 140ms,
|
||||
transform 160ms;
|
||||
}
|
||||
.site-cursor[data-mode="link"] .site-cursor-orbit {
|
||||
transform: scale(1.45);
|
||||
border-color: #b4e78a;
|
||||
background: #b4e78af2;
|
||||
}
|
||||
.site-cursor[data-mode="link"] .site-cursor-orbit svg {
|
||||
opacity: 1;
|
||||
transform: translate(0, 0) scale(0.8);
|
||||
}
|
||||
.site-cursor[data-mode="link"] .site-cursor-dot span {
|
||||
opacity: 0;
|
||||
}
|
||||
.site-cursor[data-pressed="true"] .site-cursor-orbit {
|
||||
transform: scale(0.85);
|
||||
}
|
||||
.site-cursor[data-mode="link"][data-pressed="true"] .site-cursor-orbit {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
|
||||
html.has-site-cursor,
|
||||
html.has-site-cursor * {
|
||||
cursor: none !important;
|
||||
}
|
||||
}
|
||||
@media (hover: none), (pointer: coarse), (prefers-reduced-motion: reduce) {
|
||||
.site-cursor {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import "./workshop.css";
|
||||
import "./leaderboard.css";
|
||||
import "./home-map.css";
|
||||
import "./rounded-theme.css";
|
||||
import "./cursor.css";
|
||||
import { SiteCursor } from "@/components/SiteCursor";
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
default: "MineGeo — Get lost in a familiar world",
|
||||
@@ -22,7 +24,10 @@ export default function RootLayout({
|
||||
}) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>{children}</body>
|
||||
<body>
|
||||
{children}
|
||||
<SiteCursor />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -202,36 +202,6 @@ body {
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
/* Native vector cursors track directly, with normal text/drag cursors retained. */
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
body {
|
||||
cursor:
|
||||
url("/cursors/orbit.svg") 14 14,
|
||||
auto;
|
||||
}
|
||||
a,
|
||||
button,
|
||||
select,
|
||||
summary,
|
||||
label[for],
|
||||
input[type="checkbox"],
|
||||
input[type="radio"],
|
||||
input[type="file"],
|
||||
[role="button"] {
|
||||
cursor:
|
||||
url("/cursors/orbit-link.svg") 18 18,
|
||||
pointer;
|
||||
}
|
||||
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
|
||||
textarea,
|
||||
[contenteditable="true"] {
|
||||
cursor: text;
|
||||
}
|
||||
button:disabled,
|
||||
[aria-disabled="true"] {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
@media (max-width: 1000px) {
|
||||
.hero {
|
||||
grid-template-columns: 1.15fr 1fr;
|
||||
|
||||
Reference in New Issue
Block a user