Browse Source

feat: add flickerlist to homepage

pull/2/head
Muthu Kumar 5 months ago
parent
commit
feb6a4c485
Failed to extract signature
  1. 1
      src/components/Container.tsx
  2. 13
      src/components/Dashed.tsx
  3. 145
      src/components/FlickerList.tsx
  4. 1
      src/index.css
  5. 29
      src/pages/main/Home.tsx
  6. 11
      src/util/index.ts

1
src/components/Container.tsx

@ -157,7 +157,6 @@ const Container: React.FC<{
return ( return (
<div <div
className={css` className={css`
background: var(--bg-colour);
padding-block-start: 15rem; padding-block-start: 15rem;
padding-block-end: 8rem; padding-block-end: 8rem;
padding-inline: calc(100vw / 8); padding-inline: calc(100vw / 8);

13
src/components/Dashed.tsx

@ -1,13 +0,0 @@
import React from "react";
import { css } from "@emotion/css";
const Dashed: React.FC<{ children: React.ReactNode }> = ({ children }) => (
<span
className={css`
border-bottom: 1px dashed var(--text-colour);
`}>
{children}
</span>
);
export default Dashed;

145
src/components/FlickerList.tsx

@ -0,0 +1,145 @@
import React from "react";
import { css, cx } from "@emotion/css";
import { intersperse, sleep } from "../util";
const tripleBlink = async (el: HTMLElement) => {
const delay = 150;
await sleep(1000);
el.style.opacity = "0.5";
await sleep(delay);
el.style.opacity = "1";
await sleep(delay);
el.style.opacity = "0.5";
await sleep(delay);
el.style.opacity = "1";
await sleep(delay);
el.style.opacity = "0.5";
await sleep(delay * 2);
el.style.opacity = "1";
};
const Flicker: React.FC<{
children: React.ReactNode;
index: number;
description: string;
}> = ({ children, index, description }) => {
return (
<span
className={css`
position: relative;
& button:focus ~ .tooltip,
& button:hover ~ .tooltip {
opacity: 1;
}
& button:focus,
& button:hover {
opacity: 1 !important;
}
`}>
<button
className={css`
border-bottom: 1px dashed var(--text-colour);
opacity: 0;
background-color: transparent;
border: none;
color: inherit;
position: relative;
`}
ref={async el => {
if (!el) return;
await sleep(150);
await sleep(250 * index);
el.style.opacity = "1";
await sleep(1000 + Math.random() * 1000);
tripleBlink(el);
while (true) {
await sleep(5000 + Math.random() * 10000);
el.style.opacity = String(0.5 + Math.random() * 0.5);
await sleep(2000);
tripleBlink(el);
}
}}>
{children}
</button>
<span
className={cx(
"tooltip",
css`
/* tooltip */
position: absolute;
top: 150%;
left: 50%;
transform: translateX(-50%);
background: var(--card-tags);
color: var(--text-colour);
border-radius: 0.5rem;
padding: 0.5rem 0.8rem;
font-size: 0.8rem;
min-width: 20rem;
width: fit-content;
max-width: 80vw;
opacity: 0;
transition: opacity 0.2s;
user-select: none;
text-align: left;
@media screen and (max-width: 65rem) {
position: fixed;
top: unset;
left: 1rem;
transform: translateY(2rem);
}
`,
)}>
{description}
</span>
</span>
);
};
const FlickerList: React.FC<{
list: { text: string; description: string }[];
}> = ({ list }) => {
return (
<ul
className={css`
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin: 0;
padding: 0;
list-style: none;
&:has(> li > span > button:focus) li > span > button:not(:focus),
&:has(> li > span > button:hover) li > span > button:not(:hover)
/* */ {
opacity: 0.5 !important;
}
`}>
{[
...intersperse(
list.map((item, index) => (
<li
key={item.text}
className={css`
display: inline-block;
`}>
<Flicker index={index} description={item.description}>
{item.text}
</Flicker>
</li>
)),
<li>·</li>,
),
]}
</ul>
);
};
export default FlickerList;

1
src/index.css

@ -27,6 +27,7 @@ body {
margin: 0; margin: 0;
color: var(--text-colour); color: var(--text-colour);
overflow-x: hidden; overflow-x: hidden;
background-color: var(--bg-colour);
} }
code { code {

29
src/pages/main/Home.tsx

@ -1,6 +1,6 @@
import React from "react"; import React from "react";
import Container from "../../components/Container"; import Container from "../../components/Container";
import Dashed from "../../components/Dashed"; import FlickerList from "../../components/FlickerList";
import { ReactComponent as Arrow } from "../../assets/arrow-thin.svg"; import { ReactComponent as Arrow } from "../../assets/arrow-thin.svg";
import { css, cx } from "@emotion/css"; import { css, cx } from "@emotion/css";
import { setupCursorTracking } from "../../util"; import { setupCursorTracking } from "../../util";
@ -15,7 +15,30 @@ const section = css`
const Home: React.FC = () => { const Home: React.FC = () => {
return ( return (
<Container> <Container>
<section>
<h1>MKRhere</h1> <h1>MKRhere</h1>
<p>
<FlickerList
list={[
{
text: "Designer",
description:
"Graphic design is my passion 🤓 I have plenty of experience with Figma and Adobe Suite tools (especially Photoshop and InDesign)",
},
{
text: "Developer",
description:
"🧑🏻‍💻 I started developing websites in 2015, and in 2017 I joined The Devs Network, catapulting my growth as a full-time developer",
},
{
text: "Architect",
description:
"I have a formal degree in architecture! I'm an architect in both construction and software 😉",
},
]}
/>
</p>
</section>
<section <section
className={cx( className={cx(
section, section,
@ -24,9 +47,7 @@ const Home: React.FC = () => {
`, `,
)}> )}>
<p> <p>
Welcome to the web home of <Dashed>designer</Dashed>,{" "} Welcome to the web home of <b>Anu Rahul Nandhan.</b>
<Dashed>developer</Dashed>, and <Dashed>architect</Dashed>{" "}
<b>Anu Rahul Nandhan.</b>
</p> </p>
<p> <p>
I'm also commonly known as <b>Muthu Kumar</b>. I'm also commonly known as <b>Muthu Kumar</b>.

11
src/util/index.ts

@ -1,6 +1,17 @@
import React from "react"; import React from "react";
import useLocation from "wouter/use-location"; import useLocation from "wouter/use-location";
export const sleep = (t: number) => new Promise(r => setTimeout(r, t));
export function* intersperse<T, U>(xs: T[], delim: U): Generator<T | U> {
let first = true;
for (const x of xs) {
if (!first) yield delim;
first = false;
yield x;
}
}
export const getTimeout = () => { export const getTimeout = () => {
const clearables = new Set<number>(); const clearables = new Set<number>();

Loading…
Cancel
Save