Skip to content

Commit

Permalink
fridge kinda done
Browse files Browse the repository at this point in the history
  • Loading branch information
spencerc99 committed Feb 18, 2024
1 parent 10d07e6 commit ae3d1b6
Show file tree
Hide file tree
Showing 3 changed files with 280 additions and 71 deletions.
90 changes: 90 additions & 0 deletions website/fridge.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
@import "./home.scss";
#fridge {
position: relative;
}

.fridgeWord {
--word-color: rgba(50, 50, 50, 1);
line-height: 1;
margin: 4px;
background-color: #efefef;
color: $color-text-light;
padding: 0.4em;
box-shadow: 3px 3px 0px 0px var(--word-color);
cursor: pointer;
position: relative;

&.custom {
position: absolute;
&::before {
content: " ";
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
animation: dynamicGlow 2s;
}
}
}

.fridgeWordHolder {
display: inline-block;

// iPhone jiggle animation
// inspo from https://www.kirupa.com/html5/creating_the_ios_icon_jiggle_wobble_effect_in_css.htm
&:nth-child(2n) .fridgeWord:hover {
animation-name: jiggle1;
animation-iteration-count: infinite;
transform-origin: 50% 10%;
animation-duration: 0.25s;
animation-delay: var(--jiggle-delay);
}

&:nth-child(2n-1) .fridgeWord:hover {
animation-name: jiggle2;
animation-iteration-count: infinite;
animation-direction: alternate;
transform-origin: 30% 5%;
animation-duration: 0.45s;
animation-delay: var(--jiggle-delay);
}
}

@keyframes jiggle1 {
0% {
transform: rotate(-1deg);
animation-timing-function: ease-in;
}

50% {
transform: rotate(1.5deg);
animation-timing-function: ease-out;
}
}

@keyframes jiggle2 {
0% {
transform: rotate(1deg);
animation-timing-function: ease-in;
}

50% {
transform: rotate(-1.5deg);
animation-timing-function: ease-out;
}
}

@keyframes dynamicGlow {
0% {
box-shadow: 0 0 8px 2px hsla(139, 22%, 85%, 0.2);
}
50% {
box-shadow: 0 0 12px 3px hsla(139, 32%, 65%, 0.6),
0 0 20px 5px hsla(139, 42%, 45%, 0.4),
0 0 30px 8px hsla(139, 52%, 35%, 0.3);
}
100% {
box-shadow: 0 0 8px 2px hsla(139, 22%, 85%, 0.2);
}
}
189 changes: 183 additions & 6 deletions website/fridge.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,74 @@
import "./home.scss";
import "./fridge.scss";
import words from "profane-words";
import { TagType } from "@playhtml/common";
import ReactDOM from "react-dom/client";
import { withPlay } from "../packages/react/src";
import React from "react";
import { PlayProvider } from "../packages/react/src";

interface Props {
interface FridgeWordType {
id?: string;
word: string;
color?: string;
}
interface Props extends FridgeWordType {
deleteMode?: boolean;
onDeleteWord?: () => void;
className?: string;
}

const FridgeWord = withPlay<Props>()(
{
tagInfo: [TagType.CanMove],
},
({ props }) => {
const { word } = props;
const { id, word, deleteMode, onDeleteWord, className } = props;
return (
<div selector-id="#fridge .fridgeWordHolder" className="fridgeWordHolder">
<div className="fridgeWord">{word}</div>
<div
id={id}
selector-id="#fridge .fridgeWordHolder"
className="fridgeWordHolder"
>
<div
className={`fridgeWord ${className}`}
style={{
"--word-color": props.color,
...(deleteMode
? {
border: "2px dotted red",
}
: {}),
}}
>
{word}
{deleteMode ? (
<button
style={{
background: "red",
borderRadius: "50%",
width: "1.5em",
marginLeft: "4px",
color: "white",
position: "absolute",
top: "-8px",
right: "-12px",
height: "1.5em",
minHeight: "unset",
lineHeight: "0",
}}
onClick={() => {
if (!deleteMode) return;

onDeleteWord?.();
}}
>
{" "}
x
</button>
) : (
""
)}
</div>
</div>
);
}
Expand Down Expand Up @@ -72,10 +123,136 @@ const Words = [
"always",
];

const WordControls = withPlay()(
{
defaultData: [] as FridgeWordType[],
id: "newWords",
},
({ data, setData }) => {
const [input, setInput] = React.useState("");
const [deleteMode, setDeleteMode] = React.useState(false);
const userColor =
window.cursors?.color || localStorage.getItem("userColor") || undefined;

function clearMessage() {
setInput("");
}

function onSubmit() {
if (!input) {
return;
}
if (
words.some((word) => {
const regex = new RegExp(`\\b${word}\\b`, "gi");
return regex.test(input);
})
) {
alert(
"we don't seem to like that word :( please keep things nice here"
);
clearMessage();
return false;
}

setData([
...data,
{ word: input, color: userColor, id: Date.now().toString() },
]);
clearMessage();
}

return (
<>
{data.map(({ word, color, id }) => (
<FridgeWord
id={id}
key={id}
word={word}
color={color}
deleteMode={deleteMode}
className="custom"
onDeleteWord={() => {
const idxToDelete = data.findIndex((w) => {
if (id) {
return id === w.id;
}

return word === w.word && color === w.color;
});
console.log(
"found idx",
idxToDelete,
id,
word,
color,
data[idxToDelete]
);
setData(data.filter((_, idx) => idx !== idxToDelete));
console.log(data);
}}
/>
))}
<div
style={{
position: "fixed",
bottom: "20%",
right: "20%",
display: "flex",
gap: ".5em",
}}
>
<input
placeholder="New word..."
value={input}
onKeyDown={(e) => {
if (e.key === "Enter") onSubmit();
}}
onChange={(e) => setInput(e.target.value.trim())}
></input>
<button
onClick={onSubmit}
disabled={!Boolean(input)}
style={{
padding: ".5em 1em",
}}
>
Add
</button>
</div>
<div
style={{
position: "fixed",
bottom: "16%",
right: "20%",
display: "flex",
gap: ".5em",
}}
>
<button
onClick={() => setDeleteMode(!deleteMode)}
style={{
background: !deleteMode ? "red" : undefined,
padding: ".5em 1em",
}}
>
{deleteMode ? "Stop" : "Delete"}
</button>
</div>
</>
);
}
);

ReactDOM.createRoot(document.getElementById("fridge") as HTMLElement).render(
<PlayProvider>
<PlayProvider
initOptions={{
room: window.location.pathname,
}}
>
{Words.map((w, i) => (
<FridgeWord key={i} word={w} />
))}
<WordControls />
</PlayProvider>
);
72 changes: 7 additions & 65 deletions website/home.scss
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,16 @@ footer {
**/

button {
background: rgb(80, 75, 69);
background: var(--color-text);
border-radius: 4px;
cursor: pointer;
color: var(--color-background-neutral);
// color: rgb(210, 210, 210);
min-height: 25px;

&:disabled {
opacity: 0.6;
}
}

.wordSubmit {
Expand Down Expand Up @@ -390,70 +396,6 @@ kbd {
}
}

/** TODO: refactor into separate files
** fridge.html
**/
#fridge {
position: relative;
}

.fridgeWord {
line-height: 1;
margin: 4px;
background-color: #efefef;
color: $color-text-light;
padding: 0.4em;
box-shadow: 3px 3px 0px 0px rgba(50, 50, 50, 1);
cursor: pointer;
}

.fridgeWordHolder {
display: inline-block;

// iPhone jiggle animation
// inspo from https://www.kirupa.com/html5/creating_the_ios_icon_jiggle_wobble_effect_in_css.htm
&:nth-child(2n) .fridgeWord:hover {
animation-name: jiggle1;
animation-iteration-count: infinite;
transform-origin: 50% 10%;
animation-duration: 0.25s;
animation-delay: var(--jiggle-delay);
}

&:nth-child(2n-1) .fridgeWord:hover {
animation-name: jiggle2;
animation-iteration-count: infinite;
animation-direction: alternate;
transform-origin: 30% 5%;
animation-duration: 0.45s;
animation-delay: var(--jiggle-delay);
}
}

@keyframes jiggle1 {
0% {
transform: rotate(-1deg);
animation-timing-function: ease-in;
}

50% {
transform: rotate(1.5deg);
animation-timing-function: ease-out;
}
}

@keyframes jiggle2 {
0% {
transform: rotate(1deg);
animation-timing-function: ease-in;
}

50% {
transform: rotate(-1.5deg);
animation-timing-function: ease-out;
}
}

.candle {
width: 80px;
cursor: pointer;
Expand Down

0 comments on commit ae3d1b6

Please sign in to comment.