Skip to content

Commit

Permalink
positive example + kubric slab
Browse files Browse the repository at this point in the history
  • Loading branch information
KutnerUri committed Jun 28, 2023
1 parent d4968b8 commit 5d387d4
Show file tree
Hide file tree
Showing 11 changed files with 317 additions and 51 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@ What did you feel? Would you incorporate sounds in your app?
- [x] play audio on :hover
- [x] play something else on click
- [x] replace sounds with something from the Space Odyssey 2001
- [ ] style to look like the slab.
- [x] style to look like the slab.
- [ ] style page to look like its surrounding.
Binary file added public/sounds/correct.mp3
Binary file not shown.
Binary file added public/sounds/journey-through-solar-system.mp3
Binary file not shown.
151 changes: 111 additions & 40 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ import { shake, shakeHover } from "./effects/shake";
import { Sound } from "./experiments/sound";
import { turnOff, turnOn } from "./state-mutators";
import { shadowTheme } from "./theme/shadows";
import { Brick } from "./components/brick";
import { times } from "./effects/times";

const SOUNDS = {
eerieChoir: "./sounds/eerie-choir.mp3",
eerieChoirLight: "./sounds/eerie-choir-long.mp3",
dead: "./sounds/noise.mp3",
exploration: "./sounds/journey-through-solar-system.mp3",
success: "./sounds/correct.mp3",
};

// the browser may block sounds if played before the user has a chance to interact.
Expand All @@ -25,67 +29,134 @@ function ClickFirst() {
return (
<div className={styles.clickWall}>
<div className={styles.card}>
<Brick />
<StitchesButton onClick={turnOn(setClicked)}>
Click here to start
</StitchesButton>
<p style={{ textAlign: "center" }}>
(Some browsers require user interaction before making sounds)
<br />
<b>🔉 please turn on your audio 🔊</b>
<br />
(Some browsers require user interaction before making sounds)
</p>
</div>
</div>
);
}

function App() {
return (
<div className={cn(modernTheme(), shadowTheme())}>
<BuyPremium />
<DelAccount />

<div className={styles.explanation}>
<h1>Sound showcase</h1>
<p>This demos how sounds could be used in a web application.</p>
<p>
Of course, this is a dramatic exaggeration, showing a button we don't
want the user to click, but using sounds.
</p>
</div>
</div>
);
}

function BuyPremium() {
const [hoveringContainer, setHoveringContainer] = useState(false);
const [hoveringButton, setHoveringButton] = useState(false);
const [dead, setDead] = useState(false);

return (
<div
className={styles.card}
// manually track hover - we don't have css for sound
onMouseEnter={turnOn(setHoveringContainer)}
onMouseLeave={turnOff(setHoveringContainer)}
>
<h3>Delete Account</h3>
{dead && (
<span onClick={turnOff(setDead)} className={styles.skull}>
☠️
</span>
)}
{!dead && (
<StitchesButton
intent="danger"
onClick={turnOn(setDead)}
className={shakeHover()}
// manually track hover - we don't have css for sound
onMouseEnter={turnOn(setHoveringButton)}
onMouseLeave={turnOff(setHoveringButton)}
>
delete forever
</StitchesButton>
)}
<p>All your data will be deleted</p>

{/* sounds effects: */}
<Sound
src={SOUNDS.eerieChoirLight}
play={!dead && hoveringContainer}
loop
/>
<Sound
src={SOUNDS.eerieChoir}
play={!dead && hoveringButton}
fadeIn={times.sloth}
loop
/>
<Sound src={SOUNDS.dead} play={dead} loop fadeIn={times.relaxed} />
</div>
);
}

function DelAccount() {
// const [hoveringContainer, setHoveringContainer] = useState(false);
const [hoveringButton, setHoveringButton] = useState(false);
const [purchased, setPurchased] = useState(false);

// stop hover effects when in the "dead"
useEffect(() => {
if (dead) setHoveringContainer(false);
if (dead) setHoveringButton(false);
}, [dead]);
if (purchased) setHoveringButton(false);
}, [purchased]);

return (
<div className={cn(modernTheme(), shadowTheme())}>
<div
className={styles.card}
// manually track hover - we don't have css for sound
onMouseEnter={turnOn(setHoveringContainer)}
onMouseLeave={turnOff(setHoveringContainer)}
>
<h3>Delete Account</h3>
{dead && (
<span onClick={turnOff(setDead)} className={styles.skull}>
☠️
</span>
)}
{!dead && (
<StitchesButton
intent="danger"
onClick={turnOn(setDead)}
className={shakeHover()}
// manually track hover - we don't have css for sound
onMouseEnter={turnOn(setHoveringButton)}
onMouseLeave={turnOff(setHoveringButton)}
>
delete forever
</StitchesButton>
)}
<div className={styles.card}>
<h3>Premium subscription</h3>
{purchased && (
<span onClick={turnOff(setPurchased)} className={styles.skull}>
</span>
)}
{!purchased && (
<StitchesButton
intent="success"
onClick={turnOn(setPurchased)}
className={shakeHover()}
// manually track hover - we don't have css for sound
onMouseEnter={turnOn(setHoveringButton)}
onMouseLeave={turnOff(setHoveringButton)}
>
Buy now!
</StitchesButton>
)}
{!purchased && (
<p style={{ textAlign: "center" }}>
Get AccountPlus for
<br />
just <code>3.99$</code>/mo
</p>
)}
{purchased && <p style={{ textAlign: "center" }}>purchased!</p>}

{/* sounds effects: */}
<Sound src={SOUNDS.eerieChoirLight} play={hoveringContainer} loop />
<Sound
src={SOUNDS.eerieChoir}
play={hoveringButton}
loop
fadeIn={3000}
/>
<Sound src={SOUNDS.dead} play={dead} loop fadeIn={500} />
</div>
{/* sounds effects: */}
<Sound
src={SOUNDS.exploration}
play={hoveringButton}
fadeIn={times.relaxed}
loop
/>
<Sound src={SOUNDS.success} play={purchased} autoReset />
</div>
);
}
Expand Down
6 changes: 6 additions & 0 deletions src/app.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
border-radius: 8px;
}

.explanation {
margin: 2em auto;
padding: 0 2em;
max-width: 768px;
}

h3, p {
margin: 0;
}
Expand Down
68 changes: 68 additions & 0 deletions src/components/brick/brick.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { css } from "@stitches/react";
import classNames from "classnames";

const cube = css({
position: "relative",
transformStyle: "preserve-3d",
});

const rotate45 = css({
transition: "all 300ms",
transform: "rotateX(-9deg) rotateY(-80deg) rotate(0deg)",
});

// might be half the surface size
const translate = "32px";

// a face is a 2D "side" of a 3D object
const cubeFace = css({
position: "absolute",
width: "100%",
height: "100%",

variants: {
side: {
front: {
background:
"linear-gradient(to bottom left, hsl(0, 0%, 23%), hsl(0, 0%, 9%))",
},
right: {
transform: "rotateY(90deg) translateZ(var(--brick-z)) translateX(50%)", // TODO 121.5 = size - 10%/2
width: "9%",
background: "linear-gradient(150deg, hsl(0, 0%, 23%), hsl(0, 0%, 9%))",
},
top: {
transform:
"rotateX(90deg) translateZ(var(--brick-z)) translateX(0px) translateY(-50%)",
width: "100%",
height: "9%",
background: "linear-gradient(336deg, hsl(0deg 0% 38%), hsl(0 0% 23%));",
},
},
},
});

export function Brick({ size = 128 }) {
return (
<div
className={classNames(cube(), rotate45())}
style={{ width: size, height: size }}
>
<div className={classNames(cubeFace({ side: "front" }))} />
<div
className={classNames(cubeFace({ side: "right" }))}
style={{
// @ts-ignore
"--brick-z": `${size * 0.95}px`,
}}
/>
<div
className={classNames(cubeFace({ side: "top" }))}
style={{
// @ts-ignore
"--brick-z": `${size * 0.045}px`,
}}
/>
</div>
);
}
1 change: 1 addition & 0 deletions src/components/brick/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Brick } from "./brick";
4 changes: 2 additions & 2 deletions src/effects/shake.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ const shakeTransform = keyframes({
});

export const shake = css({
animation: `${shakeTransform} ${times.long} infinite cubic-bezier(.36,.07,.19,.97) both`,
animation: `${shakeTransform} ${times.long}ms infinite cubic-bezier(.36,.07,.19,.97) both`,
transform: "translate3d(0, 0, 0)",
"backface-visibility": "hidden",
perspective: "1000px",
});

export const shakeHover = css({
"&:hover": {
animation: `${shakeTransform} ${times.long} infinite cubic-bezier(.36,.07,.19,.97) both`,
animation: `${shakeTransform} ${times.long}ms infinite cubic-bezier(.36,.07,.19,.97) both`,
transform: "translate3d(0, 0, 0)",
"backface-visibility": "hidden",
perspective: "1000px",
Expand Down
14 changes: 7 additions & 7 deletions src/effects/times.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export const times = {
blink: "80ms",
quick: "130ms",
snappy: "210ms",
normal: "330ms",
relaxed: "485ms",
long: "785ms",
sloth: "1271ms",
blink: 80,
quick: 130,
snappy: 210,
normal: 330,
relaxed: 485,
long: 785,
sloth: 1271,
};
Loading

0 comments on commit 5d387d4

Please sign in to comment.