Added first draft of channel page

This commit is contained in:
2022-09-29 15:05:46 +02:00
parent db1bee79ac
commit 2433d0c225
29 changed files with 1851 additions and 9 deletions

View File

@@ -0,0 +1,37 @@
import { ArrowLeftIcon } from "@heroicons/react/24/outline";
import Button from "../components/Button";
import NavBar from "../components/NavBar";
import SideNavChannel from "../components/SideNavChannel";
import { Outlet } from "react-router-dom";
import streamData from "../placeholder/GetStreams";
import { NavLink } from "react-router-dom";
function BrowseLayout() {
return (
<div className="font-inter flex flex-col h-screen text-gray-100">
<NavBar />
<main className="flex-1 flex flex-row overflow-hidden">
<div className="bg-neutral-800 w-60 flex flex-col">
<div className="flex flex-row justify-between p-2 items-center">
<p className="uppercase font-semibold text-sm">Followed channels</p>
<Button variant="subtle" className="p-2">
<ArrowLeftIcon className="w-4 h-4" />
</Button>
</div>
<ul className="flex-1 overflow-scrollbar">
{streamData.data.map((stream) => (
<li key={stream.id}>
<NavLink to={`/${stream.user_login}`}>
<SideNavChannel stream={stream} />
</NavLink>
</li>
))}
</ul>
</div>
<Outlet />
</main>
</div>
);
}
export default BrowseLayout;

View File

@@ -0,0 +1,34 @@
import { FC } from "react";
import clsx from "clsx";
type ButtonVariants = "filled" | "subtle";
interface ButtonProps extends React.ComponentPropsWithoutRef<"button"> {
variant?: ButtonVariants;
}
const getStyling = (variant?: ButtonVariants) => {
switch (variant) {
case "filled":
return "bg-neutral-700";
case "subtle":
return "hover:bg-neutral-500";
default:
return "bg-neutral-700";
}
};
const Button: FC<ButtonProps> = ({
className,
variant,
...rest
}: ButtonProps) => {
return (
<button
className={clsx("rounded-md", getStyling(variant), className)}
{...rest}
/>
);
};
export default Button;

View File

@@ -0,0 +1,9 @@
import { FC } from "react";
const ChatBadge: FC = () => {
return (
<div className="w-5 h-5 rounded-sm bg-pink-300 inline-block align-middle" />
);
};
export default ChatBadge;

View File

@@ -0,0 +1,23 @@
import { FC } from "react";
import ChatBadge from "./ChatBadge";
const ChatMessage: FC = () => {
return (
<p className="mx-2 p-2 hover:bg-neutral-700 text-sm rounded-md">
<div className="space-x-1 inline">
<ChatBadge />
<ChatBadge />
<span className="align-middle">Username</span>
</div>
<span className="align-middle">: </span>
<span className="break-all align-middle">
<img
src="https://cdn.7tv.app/emote/60afbe0599923bbe7fe9bae1/2x"
className="inline w-7 h-7"
/>
</span>
</p>
);
};
export default ChatMessage;

View File

@@ -0,0 +1,17 @@
import clsx from "clsx";
interface InputProps extends React.ComponentPropsWithoutRef<"input"> {}
const Input = ({ className, ...rest }: InputProps) => {
return (
<input
className={clsx(
"bg-zinc-700 rounded-md box-border focus:outline outline-violet-400 text-sm",
className
)}
{...rest}
/>
);
};
export default Input;

View File

@@ -0,0 +1,36 @@
import { TvIcon } from "@heroicons/react/24/outline";
import { FC } from "react";
import Input from "./Input";
const NavBar: FC = () => {
return (
<nav className="bg-zinc-800 w-screen font-semibold">
<div className="flex flex-row justify-between items-center mx-2">
<div className="basis-1/4">
<ul className="flex flex-row space-x-3 items-center">
<li>
<TvIcon className="w-6 h-6" />
</li>
<li>Following</li>
<li>Browse</li>
</ul>
</div>
<div className="basis-2/4">
<div className="flex flex-row space-x-3 items-center justify-center">
<Input className=" w-72 my-2 p-2" placeholder="Search" />
</div>
</div>
<div className="basis-1/4">
<ul className="justify-end flex flex-row space-x-3 items-center">
<li>Hello</li>
<li>
<div className="w-8 h-8 rounded-full bg-yellow-300" />
</li>
</ul>
</div>
</div>
</nav>
);
};
export default NavBar;

View File

@@ -0,0 +1,33 @@
import { FC } from "react";
import { numFormatter } from "../lib/format";
import { Stream } from "../types";
interface SideNavChannelProps {
stream: Stream;
}
const SideNavChannel: FC<SideNavChannelProps> = ({
stream,
}: SideNavChannelProps) => {
const imgSrc = stream.thumbnail_url
.replace("{width}", "150")
.replace("{height}", "150");
return (
<div className="flex flex-row px-3 py-2 text-sm leading-4 space-x-2 hover:bg-neutral-700/40 cursor-pointer">
<img className="rounded-full w-8 h-8" src={imgSrc} />
<div className="flex flex-col flex-1">
<div className="flex flex-row justify-between">
<div className="font-bold">{stream.user_name}</div>
<div className="space-x-1 flex flex-row items-center">
<div className="w-2 h-2 bg-red-600 rounded-full inline-block" />
<span>{numFormatter.format(stream.viewer_count)}</span>
</div>
</div>
<div className="text-gray-300">{stream.game_name}</div>
</div>
</div>
);
};
export default SideNavChannel;