Skip to content

Commit

Permalink
WORKSHOP
Browse files Browse the repository at this point in the history
  • Loading branch information
spencerc99 committed Aug 18, 2024
1 parent 07eca32 commit 9aff2ef
Show file tree
Hide file tree
Showing 5 changed files with 510 additions and 20 deletions.
129 changes: 129 additions & 0 deletions packages/react/examples/LiveChat.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
.live-chat {
width: 300px;
height: 400px;
border: 2px solid #000;
background-color: #fff;
display: flex;
flex-direction: column;
font-family: "Comic Sans MS", cursive, sans-serif;
margin-right: 10px;
transition: height 0.3s ease;

&.minimized {
height: 40px;
}

.chat-header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #007700;
color: #fff;
padding: 5px;
cursor: pointer;

h2 {
margin: 0;
font-size: 1em;
}

button {
background: none;
border: none;
color: #fff;
cursor: pointer;
}
}

.chat-window {
flex: 1;
padding: 10px;
overflow-y: auto;
border-bottom: 2px solid #000;
background-color: #f0f0f0;

.chat-message {
margin-bottom: 10px;
padding: 5px;
border-radius: 5px;
background-color: #e0e0e0;

strong {
color: #007700;
}
}
}

.chat-input {
display: flex;
padding: 10px;
background-color: #d0d0d0;

input {
flex: 1;
padding: 5px;
border: 1px solid #000;
border-radius: 3px;
margin-right: 5px;
}

button {
padding: 5px 10px;
border: 1px solid #000;
border-radius: 3px;
background-color: #007700;
color: #fff;
cursor: pointer;

&:hover {
background-color: #005500;
}
}
}
}

.live-chat-controller {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
display: flex;
flex-direction: column;

.chat-creation {
display: flex;
background-color: #007700;
color: #fff;
padding: 10px;
display: flex;

input {
flex: 1;
padding: 5px;
border: 1px solid #000;
border-radius: 3px;
margin-right: 5px;
}

button {
padding: 5px 10px;
border: 1px solid #000;
border-radius: 3px;
background-color: #fff;
color: #007700;
cursor: pointer;

&:hover {
background-color: #005500;
color: #fff;
}
}
}

.chat-list {
display: flex;
flex-wrap: nowrap;
align-items: flex-end;
overflow-x: auto;
}
}
121 changes: 121 additions & 0 deletions packages/react/examples/LiveChat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React, { useState } from "react";
import { withSharedState } from "@playhtml/react";
import { PlayProvider } from "@playhtml/react";
import "./LiveChat.scss";

interface ChatMessage {
id: string;
name: string;
text: string;
color?: string;
}

interface LiveChatProps {
name: string;
}

const LiveChat = withSharedState(
{
defaultData: { messages: [] as ChatMessage[] },
},
({ data, setData }, { name }) => {
const [newMessage, setNewMessage] = useState("");
const [isMinimized, setIsMinimized] = useState(true);
const userId = localStorage.getItem("userId") || "unknown";
const userName = Boolean(localStorage.getItem("username"))
? JSON.parse(localStorage.getItem("username")) || "Anonymous"
: "Anonymous";

const handleSend = () => {
if (newMessage.trim()) {
const message = {
id: userId,
name: userName,
text: newMessage,
// this comes from cursor party, if not defined it just defaults to black
// @ts-ignore
color: window.cursors.color,
};
setData({ messages: [...data.messages, message] });
setNewMessage("");
}
};

// TODO: add read in local store, handle notifications
return (
<div className={`live-chat ${isMinimized ? "minimized" : ""}`}>
<div
className="chat-header"
onClick={() => setIsMinimized(!isMinimized)}
>
<h2>{name}</h2>
<button>{isMinimized ? "⬆︎" : "–"}</button>
</div>
{!isMinimized && (
<>
<div className="chat-window">
{data.messages.map((msg, index) => (
<div key={index} className="chat-message">
<strong
style={{
color: msg.color || "black",
}}
>
{msg.name}
</strong>
: {msg.text}
</div>
))}
</div>
<div className="chat-input">
<input
type="text"
value={newMessage}
onChange={(e) => setNewMessage(e.target.value)}
placeholder="Type your message..."
/>
<button onClick={handleSend}>Send</button>
</div>
</>
)}
</div>
);
}
);

export const LiveChatController = withSharedState(
{
defaultData: { chatNames: [] as string[] },
},
({ data, setData }) => {
const [newChatName, setNewChatName] = useState("");

const handleCreateChat = () => {
if (newChatName.trim() && !data.chatNames.includes(newChatName)) {
setData({ chatNames: [...data.chatNames, newChatName] });
setNewChatName("");
}
};

return (
<div className="live-chat-controller" id="live-chats">
<div className="chat-list">
{data.chatNames.map((name, index) => (
<LiveChat key={index} name={name} />
))}
</div>
<div className="chat-creation">
<div>
<input
type="text"
value={newChatName}
onChange={(e) => setNewChatName(e.target.value)}
placeholder="Enter chat name..."
/>
<button onClick={handleCreateChat}>Create Chat</button>
</div>
</div>
</div>
);
}
);
8 changes: 6 additions & 2 deletions packages/react/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,9 @@ export function withSharedState<T extends object, V = any, P = any>(
// };
// }

// @deprecated use withSharedState instead
/**
* @deprecated use withSharedState instead
*/
export const withPlay =
<P extends object = {}>() =>
<T extends object, V = any>(
Expand All @@ -304,7 +306,9 @@ export const withPlay =
) => React.ReactElement
) =>
withPlayBase<P, T, V>(playConfig, component);
// @deprecated use withSharedState instead
/**
* @deprecated use withSharedState instead
*/
export function withPlayBase<P, T extends object, V = any>(
playConfig: WithPlayProps<T, V> | ((props: P) => WithPlayProps<T, V>),
component: (
Expand Down
66 changes: 65 additions & 1 deletion website/events/gray-area/gray-area.scss
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,13 @@ h3 {
}

section {
margin: 8em 0;
margin: 15em 0;
&:nth-child(2) {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}

.retro-timer {
Expand Down Expand Up @@ -169,3 +172,64 @@ section {
background: yellow;
color: #808080;
}

#guestbook {
background: #d1e7ff;
border: 2px solid #0078d7;
border-radius: 10px;
padding: 20px;
width: 100%;
max-width: 600px;
margin: 20px auto;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
font-family: "Comic Sans MS", cursive, sans-serif;
}

.guestbook-actions {
display: flex;
flex-direction: column;
margin-bottom: 1em;
gap: 0.3em;
}

.guestbook-actions span {
}

.guestbook-actions textarea {
height: 100px;
margin-bottom: 10px;
padding: 10px;
border: 2px solid #0078d7;
border-radius: 5px;
font-family: "Comic Sans MS", cursive, sans-serif;
}

.guestbook-actions button {
background: #0078d7;
color: white;
border: none;
padding: 10px 20px;
font-size: 1em;
align-self: flex-end;
cursor: pointer;
border-radius: 5px;
transition: background 0.3s;
}

.guestbook-actions button:hover {
background: #005bb5;
}

.guestbook-entry {
background: white;
border: 1px solid #0078d7;
gap: 0.1em;
border-radius: 5px;
padding: 10px;
margin-bottom: 10px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}

.guestbook-entry b {
color: #0078d7;
}
Loading

0 comments on commit 9aff2ef

Please sign in to comment.