feat: finish commands

This commit is contained in:
Stevan Freeborn
2026-01-23 18:22:13 -06:00
parent 68fe011b35
commit 7196cdb3ab
3 changed files with 202 additions and 63 deletions
+2 -2
View File
@@ -16,7 +16,7 @@
<header>
<h1>Stevan's Stream Commands</h1>
<p>
These are the commands available to use during a stream to interact in
These are commands you can use during a stream to interact in
chat.
</p>
</header>
@@ -24,7 +24,7 @@
<ul id="commandsList"></ul>
</main>
<footer>
<p>Hope you enjoy the streams!</p>
<p>Hope you enjoy the stream!</p>
</footer>
<script type="module" src="index.js" />
</body>
+156 -43
View File
@@ -1,12 +1,121 @@
const COMMANDS = [
{
name: "Topic",
description: "Find out what is happening on the stream.",
aliases: ["!whatbrodoing"],
},
{
name: "Lurk",
description:
"Let chat know you are here, but lurking. We support our fellow lurkers.",
aliases: ["!lurk"],
},
{
name: "Schedule",
description: "Get my stream schedule.",
aliases: ["!schedule"],
},
{
name: "Lofi Generator",
description: "Get the link to the website that I use for my stream music.",
aliases: ["!lofi", "!music"],
},
{
name: "ZoomIt",
description: "Get the link to the tool I use to draw on my screen.",
aliases: ["!zoomit"],
},
{
name: "Neovim",
description: "Get the link to my Neovim configs.",
aliases: ["!nvim", "!neovim"],
},
{
name: "My Font",
description: "Get the link to the NerdFont I use.",
aliases: ["!font", "!nerdfont"],
},
{
name: "PowerShell",
description: "Get the link to my PowerShell profile.",
aliases: ["!pwsh", "!powershell"],
},
{
name: "Oh My Posh",
description: "Get the link to my Oh My Posh configs.",
aliases: ["!omp", "!ohmyposh"],
},
{
name: "Member",
description: "Get a link to become a member of the YouTube channel.",
aliases: ["!member"],
},
{
name: "Links",
description: "Get a link to all my links.",
aliases: ["!links"],
},
{
name: "Blog",
description: "Get the link to my blog.",
aliases: ["!blog"],
},
{
name: "Bluesky",
description: "Get the link to my Bluesky profile.",
aliases: ["!bsky", "!bluesky"],
},
{
name: "Bottom",
description: "Get the link to the terminal monitor I use.",
aliases: ["!btm", "!bottom"],
},
{
name: "Discord",
description: "Want to chat off stream? Get the invite link to my discord.",
aliases: ["!discord"],
},
{
name: "GitHub",
description: "Get the link to my github",
aliases: ["!gh"],
description: "Get the link to my GitHub profile.",
aliases: ["!gh", "!github"],
},
{
name: "Tangled",
description: "Get the link to my Tangled profile.",
aliases: ["!tangled"],
},
{
name: "LinkedIn",
description: "Get the link to my LinkedIn profile.",
aliases: ["!li", "!linkedin"],
},
{
name: "Telegram",
description: "Get the invite link to my Telegram channel.",
aliases: ["!tg", "!telegram"],
},
{
name: "Twitch",
description: "Get the link to my Twitch channel.",
aliases: ["!ttv", "!twitch"],
},
{
name: "YouTube",
description: "Get the link to my YouTube channel.",
aliases: ["!yt", "!youtube"],
},
{
name: "Commands",
description:
"Get the link to the list of commands available in chat during a stream.",
aliases: ["!help", "!commands"],
},
];
document.addEventListener("DOMContentLoaded", () => {
document.addEventListener("DOMContentLoaded", handleContentLoaded);
function handleContentLoaded() {
const commandsList = document.getElementById("commandsList");
if (commandsList === null) {
@@ -14,17 +123,25 @@ document.addEventListener("DOMContentLoaded", () => {
}
for (const command of COMMANDS) {
const listItemElement = document.createElement("li");
listItemElement.innerHTML = /*html*/ `
commandsList.appendChild(CommandListItem(command));
}
commandsList.addEventListener("click", handleCopyButtonClick);
}
function CommandListItem(command) {
const listItemElement = document.createElement("li");
listItemElement.innerHTML = /*html*/ `
<div class="command-card">
<div class="left">
<div class="name">${command.name}</div>
</div>
<div class="right">
<div class="aliases">
${command.aliases
.map(
(a) => /*html*/ `
<div class="command-alias">
<code>${a}</code>
${command.aliases
.map((a) => /*html*/ `
<div class="command-alias">
<code>${a}
<button
type="button"
class="copy-button"
@@ -32,48 +149,44 @@ document.addEventListener("DOMContentLoaded", () => {
data-alias="${a}"
>
<i class="fa-solid fa-copy"></i>
<i class="fa-solid fa-check hidden"></i>
<i class="fa-solid fa-check"></i>
</button>
</div>
`,
)
.join("")}
</code>
</div>
`,
)
.join("")}
</div>
</div>
<div class="right">
<p>${command.description}</p>
</div>
</div>
`;
`;
commandsList.appendChild(listItemElement);
return listItemElement;
}
async function handleCopyButtonClick(e) {
const button = e.target.closest(".copy-button");
if (!button || !button.dataset.alias || button.classList.contains("copied")) {
return;
}
commandsList.addEventListener("click", async (e) => {
const copyButton = e.target.closest(".copy-button");
if (copyButton === null) {
return;
}
try {
await navigator.clipboard.writeText(button.dataset.alias);
const alias = copyButton.dataset.alias;
await navigator.clipboard.writeText(alias);
const copyButtonIcons = Array.from(copyButton.children);
for (const icon of copyButtonIcons) {
icon.classList.toggle("hidden");
}
const originalColor = copyButton.style.color;
copyButton.style.color = '#b39cd0';
button.classList.add("copied");
setTimeout(() => {
for (const icon of copyButtonIcons) {
icon.classList.toggle("hidden");
}
button.classList.remove("copied");
}, 1000);
} catch (err) {
const permissionStatus = await navigator.permissions.query({
name: "clipboard-write",
});
copyButton.style.color = originalColor;
}, 500);
});
});
alert(
`Failed to copy command to clipboard. This is most often caused my a permission issue. Current clipboard write permission state is ${permissionStatus.state}`,
);
}
}
+44 -18
View File
@@ -27,7 +27,6 @@
button {
background: none;
border: none;
outline: none;
cursor: pointer;
color: inherit;
font-family: inherit;
@@ -52,17 +51,12 @@ table {
border-collapse: collapse;
}
/* Utils */
.hidden {
display: none;
}
/* Site Styles */
:root {
--bg-color: #181818;
--text-color: #E4E4E4;
--accent-color: #b39cd0;
font-family: 'CaskaydiaCove NFM', monospace;
font-size: 16px;
@@ -94,26 +88,40 @@ main {
flex: 1;
}
#commandsList {
display: flex;
flex-direction: column;
gap: 1rem;
margin: auto;
max-width: 50rem;
}
.command-card {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;
border: 1px solid #b39cd0;
border: 1px solid var(--accent-color);
border-radius: 1rem;
background-color: #353232;
background-color: #323232;
}
.command-card .left {
display: flex;
align-items: center;
flex: 1;
gap: 1rem;
}
.command-card .left .aliases {
.command-card .right {
display: flex;
flex-direction: column;
gap: 1rem;
flex: 6;
}
.command-card .right .aliases {
display: flex;
gap: 0.5rem;
}
.command-alias {
@@ -122,25 +130,43 @@ main {
}
.command-alias code {
display: flex;
gap: 0.25rem;
color: var(--accent-color);
background-color: var(--bg-color);
padding: 0.25rem;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
}
.command-alias button {
.copy-button {
display: flex;
align-items: center;
justify-content: center;
}
.command-card .right {
display: flex;
justify-content: flex-end;
flex: 1;
.copy-button .fa-copy {
display: block;
}
.copy-button .fa-check {
display: none;
}
.copy-button.copied {
color: #89D185;
pointer-events: none;
}
.copy-button.copied .fa-copy {
display: none;
}
.copy-button.copied .fa-check {
display: block;
}
footer {
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 1rem;
}