Added first draft of channel page
This commit is contained in:
parent
db1bee79ac
commit
2433d0c225
.gitignore
client
.gitignore.prettierrcindex.htmlpackage.jsonpnpm-lock.yamlpostcss.config.cjs
public
src
tailwind.config.cjstsconfig.jsontsconfig.node.jsonvite.config.tsdist
1
.gitignore
vendored
1
.gitignore
vendored
@ -21,3 +21,4 @@
|
||||
go.work
|
||||
|
||||
tmp/
|
||||
dist/
|
||||
|
24
client/.gitignore
vendored
Normal file
24
client/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
4
client/.prettierrc
Normal file
4
client/.prettierrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false
|
||||
}
|
13
client/index.html
Normal file
13
client/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
30
client/package.json
Normal file
30
client/package.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "client",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build --outDir ../dist",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@heroicons/react": "^2.0.11",
|
||||
"clsx": "^1.2.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.4.1",
|
||||
"tailwind-scrollbar": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.17",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@vitejs/plugin-react": "^2.1.0",
|
||||
"autoprefixer": "^10.4.12",
|
||||
"postcss": "^8.4.16",
|
||||
"prettier": "^2.7.1",
|
||||
"tailwindcss": "^3.1.8",
|
||||
"typescript": "^4.6.4",
|
||||
"vite": "^3.1.0"
|
||||
}
|
||||
}
|
1297
client/pnpm-lock.yaml
generated
Normal file
1297
client/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
6
client/postcss.config.cjs
Normal file
6
client/postcss.config.cjs
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
1
client/public/vite.svg
Normal file
1
client/public/vite.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After (image error) Size: 1.5 KiB |
16
client/src/App.tsx
Normal file
16
client/src/App.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { Routes, Route } from "react-router-dom";
|
||||
import BrowseLayout from "./components/BrowseLayout";
|
||||
import ChannelPage from "./pages/ChannelPage";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Routes>
|
||||
<Route element={<BrowseLayout />}>
|
||||
<Route path="/:channel" element={<ChannelPage />} />
|
||||
<Route path="/" element={<h1>Hi</h1>} />
|
||||
</Route>
|
||||
</Routes>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
37
client/src/components/BrowseLayout.tsx
Normal file
37
client/src/components/BrowseLayout.tsx
Normal 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;
|
34
client/src/components/Button.tsx
Normal file
34
client/src/components/Button.tsx
Normal 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;
|
9
client/src/components/ChatBadge.tsx
Normal file
9
client/src/components/ChatBadge.tsx
Normal 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;
|
23
client/src/components/ChatMessage.tsx
Normal file
23
client/src/components/ChatMessage.tsx
Normal 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;
|
17
client/src/components/Input.tsx
Normal file
17
client/src/components/Input.tsx
Normal 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;
|
36
client/src/components/NavBar.tsx
Normal file
36
client/src/components/NavBar.tsx
Normal 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;
|
33
client/src/components/SideNavChannel.tsx
Normal file
33
client/src/components/SideNavChannel.tsx
Normal 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;
|
1
client/src/lib/format.ts
Normal file
1
client/src/lib/format.ts
Normal file
@ -0,0 +1 @@
|
||||
export const numFormatter = Intl.NumberFormat("en", { notation: "compact" });
|
13
client/src/main.tsx
Normal file
13
client/src/main.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import App from "./App";
|
||||
import "./styles/global.css";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
67
client/src/pages/ChannelPage.tsx
Normal file
67
client/src/pages/ChannelPage.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
import {
|
||||
ArrowRightIcon,
|
||||
HeartIcon,
|
||||
UserIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
import Button from "../components/Button";
|
||||
import ChatMessage from "../components/ChatMessage";
|
||||
import Input from "../components/Input";
|
||||
import { numFormatter } from "../lib/format";
|
||||
import streams from "../placeholder/GetStreams";
|
||||
|
||||
function ChannelPage() {
|
||||
const stream = streams.data[1];
|
||||
|
||||
return (
|
||||
<div className="flex-1 flex flex-row">
|
||||
<div className="bg-neutral-900 flex-1">
|
||||
<div className="w-full h-auto aspect-video bg-red-200 " />
|
||||
<div className="flex flex-row p-4 space-x-3">
|
||||
<div className="w-20 h-20 bg-yellow-300 rounded-full" />
|
||||
<div className="flex-1">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="font-bold">{stream.user_name}</div>
|
||||
<div>
|
||||
<Button className="h-8 w-10">
|
||||
<HeartIcon className="text-gray-100 h-5 w-5 mx-auto" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="space-y-1">
|
||||
<div className="font-bold">{stream.title}</div>
|
||||
<div className="text-violet-400">{stream.game_name}</div>
|
||||
</div>
|
||||
<div className="flex flex-row items-center text-sm space-x-3">
|
||||
<span>
|
||||
<UserIcon className="h-5 w-5 inline-block" />
|
||||
<span>{numFormatter.format(stream.viewer_count)}</span>
|
||||
</span>
|
||||
<span>{stream.started_at}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-zinc-900 w-80 border-l border-l-zinc-700 flex flex-col">
|
||||
<div className="flex flex-row justify-between items-center border-b border-b-zinc-700 p-2">
|
||||
<Button variant="subtle" className="p-2">
|
||||
<ArrowRightIcon className="w-4 h-4" />
|
||||
</Button>
|
||||
<p className="uppercase font-semibold text-sm">Stream Chat</p>
|
||||
<div className="w-5" />
|
||||
</div>
|
||||
<div className="flex-1 overflow-scrollbar">
|
||||
{new Array(60).fill(0).map(() => (
|
||||
<ChatMessage />
|
||||
))}
|
||||
</div>
|
||||
<div className="m-2">
|
||||
<Input className="w-full p-2" placeholder="Send a message" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ChannelPage;
|
46
client/src/placeholder/GetStreams.ts
Normal file
46
client/src/placeholder/GetStreams.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { FollowedStreams } from "../types";
|
||||
|
||||
const streams: FollowedStreams = {
|
||||
data: [
|
||||
{
|
||||
id: "41375541868",
|
||||
user_id: "459331509",
|
||||
user_login: "auronplay",
|
||||
user_name: "auronplay",
|
||||
game_id: "494131",
|
||||
game_name: "Little Nightmares",
|
||||
type: "live",
|
||||
title: "hablamos y le damos a Little Nightmares 1",
|
||||
viewer_count: 78365,
|
||||
started_at: "2021-03-10T15:04:21Z",
|
||||
language: "es",
|
||||
thumbnail_url:
|
||||
"https://static-cdn.jtvnw.net/previews-ttv/live_user_auronplay-{width}x{height}.jpg",
|
||||
tag_ids: [],
|
||||
is_mature: false,
|
||||
},
|
||||
{
|
||||
id: "41375541869",
|
||||
user_id: "459331510",
|
||||
user_login: "xqcow",
|
||||
user_name: "xqcow",
|
||||
game_id: "494131",
|
||||
game_name: "Just Chatting",
|
||||
type: "live",
|
||||
title: "slam",
|
||||
viewer_count: 56230,
|
||||
started_at: "2022-09-29T14:04:21Z",
|
||||
language: "en",
|
||||
thumbnail_url:
|
||||
"https://static-cdn.jtvnw.net/previews-ttv/live_user_xqcow-{width}x{height}.jpg",
|
||||
tag_ids: [],
|
||||
is_mature: false,
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
cursor:
|
||||
"eyJiIjp7IkN1cnNvciI6ImV5SnpJam8zT0RNMk5TNDBORFF4TlRjMU1UY3hOU3dpWkNJNlptRnNjMlVzSW5RaU9uUnlkV1Y5In0sImEiOnsiQ3Vyc29yIjoiZXlKeklqb3hOVGs0TkM0MU56RXhNekExTVRZNU1ESXNJbVFpT21aaGJITmxMQ0owSWpwMGNuVmxmUT09In19",
|
||||
},
|
||||
};
|
||||
|
||||
export default streams;
|
28
client/src/placeholder/GetUserFollows.ts
Normal file
28
client/src/placeholder/GetUserFollows.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { UserFollows } from "../types";
|
||||
|
||||
export const following: UserFollows = {
|
||||
total: 4,
|
||||
data: [
|
||||
{
|
||||
from_id: "171003792",
|
||||
from_login: "niku",
|
||||
from_name: "niku",
|
||||
to_id: "23161357",
|
||||
to_name: "LIRIK",
|
||||
to_login: "lirik",
|
||||
followed_at: "2017-08-22T22:55:24Z",
|
||||
},
|
||||
{
|
||||
from_id: "171003792",
|
||||
from_login: "niku",
|
||||
from_name: "niku",
|
||||
to_id: "23161358",
|
||||
to_name: "Cowser",
|
||||
to_login: "cowser",
|
||||
followed_at: "2017-08-22T22:55:24Z",
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
cursor: "eyJiIjpudWxsLCJhIjoiMTUwMzQ0MTc3NjQyNDQyMjAwMCJ9",
|
||||
},
|
||||
};
|
9
client/src/styles/global.css
Normal file
9
client/src/styles/global.css
Normal file
@ -0,0 +1,9 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Inter&display=swap");
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
.overflow-scrollbar {
|
||||
@apply scrollbar-thin scrollbar-thumb-neutral-600 scrollbar-thumb-rounded-full overflow-y-auto;
|
||||
}
|
41
client/src/types.ts
Normal file
41
client/src/types.ts
Normal file
@ -0,0 +1,41 @@
|
||||
export interface Pagination {
|
||||
cursor: string;
|
||||
}
|
||||
|
||||
export interface UserFollow {
|
||||
followed_at: string;
|
||||
from_id: string;
|
||||
from_login: string;
|
||||
from_name: string;
|
||||
to_id: string;
|
||||
to_login: string;
|
||||
to_name: string;
|
||||
}
|
||||
|
||||
export interface UserFollows {
|
||||
total: number;
|
||||
data: UserFollow[];
|
||||
pagination: Pagination;
|
||||
}
|
||||
|
||||
export interface Stream {
|
||||
game_id: string;
|
||||
game_name: string;
|
||||
id: string;
|
||||
language: string;
|
||||
started_at: string;
|
||||
tag_ids: string[];
|
||||
thumbnail_url: string;
|
||||
title: string;
|
||||
type: string;
|
||||
user_id: string;
|
||||
user_login: string;
|
||||
user_name: string;
|
||||
viewer_count: number;
|
||||
is_mature: boolean;
|
||||
}
|
||||
|
||||
export interface FollowedStreams {
|
||||
data: Stream[];
|
||||
pagination: Pagination;
|
||||
}
|
1
client/src/vite-env.d.ts
vendored
Normal file
1
client/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
15
client/tailwind.config.cjs
Normal file
15
client/tailwind.config.cjs
Normal file
@ -0,0 +1,15 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ["./index.html", "./src/**/*.tsx"],
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
inter: ["Inter"],
|
||||
},
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
scrollbar: ["rounded"],
|
||||
},
|
||||
plugins: [require("tailwind-scrollbar")],
|
||||
};
|
21
client/tsconfig.json
Normal file
21
client/tsconfig.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
9
client/tsconfig.node.json
Normal file
9
client/tsconfig.node.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
7
client/vite.config.ts
Normal file
7
client/vite.config.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()]
|
||||
})
|
21
dist/index.html
vendored
21
dist/index.html
vendored
@ -1,12 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello there!</h1>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
<script type="module" crossorigin src="/assets/index.08ff9814.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index.3fce1f81.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
x
Reference in New Issue
Block a user