feat: add repos page
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,6 +8,8 @@ node_modules
|
|||||||
/.svelte-kit
|
/.svelte-kit
|
||||||
/build
|
/build
|
||||||
|
|
||||||
|
api/target
|
||||||
|
|
||||||
# OS
|
# OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|||||||
2518
api/Cargo.lock
generated
Normal file
2518
api/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
8
api/Cargo.toml
Normal file
8
api/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "api"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-web = "4.12.1"
|
||||||
|
reqwest = "0.13.1"
|
||||||
11
api/src/main.rs
Normal file
11
api/src/main.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
use actix_web::{App, HttpServer};
|
||||||
|
|
||||||
|
struct AppState {}
|
||||||
|
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() -> std::io::Result<()> {
|
||||||
|
HttpServer::new(|| App::new())
|
||||||
|
.bind(("127.0.0.1", 8080))?
|
||||||
|
.run()
|
||||||
|
.await
|
||||||
|
}
|
||||||
11
bun.lock
11
bun.lock
@@ -7,6 +7,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lucide/svelte": "^0.562.0",
|
"@lucide/svelte": "^0.562.0",
|
||||||
"@neondatabase/serverless": "^1.0.2",
|
"@neondatabase/serverless": "^1.0.2",
|
||||||
|
"@tanstack/svelte-query": "^6.0.15",
|
||||||
|
"@tanstack/svelte-query-devtools": "^6.0.3",
|
||||||
"better-auth": "^1.4.12",
|
"better-auth": "^1.4.12",
|
||||||
"bits-ui": "^2.15.4",
|
"bits-ui": "^2.15.4",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
@@ -28,7 +30,6 @@
|
|||||||
"tailwindcss": "^4.1.17",
|
"tailwindcss": "^4.1.17",
|
||||||
"tsx": "^4.21.0",
|
"tsx": "^4.21.0",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"vite": "^7.3.1",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -273,6 +274,14 @@
|
|||||||
|
|
||||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.18", "", { "dependencies": { "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA=="],
|
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.18", "", { "dependencies": { "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA=="],
|
||||||
|
|
||||||
|
"@tanstack/query-core": ["@tanstack/query-core@5.90.17", "", {}, "sha512-hDww+RyyYhjhUfoYQ4es6pbgxY7LNiPWxt4l1nJqhByjndxJ7HIjDxTBtfvMr5HwjYavMrd+ids5g4Rfev3lVQ=="],
|
||||||
|
|
||||||
|
"@tanstack/query-devtools": ["@tanstack/query-devtools@5.92.0", "", {}, "sha512-N8D27KH1vEpVacvZgJL27xC6yPFUy0Zkezn5gnB3L3gRCxlDeSuiya7fKge8Y91uMTnC8aSxBQhcK6ocY7alpQ=="],
|
||||||
|
|
||||||
|
"@tanstack/svelte-query": ["@tanstack/svelte-query@6.0.15", "", { "dependencies": { "@tanstack/query-core": "5.90.17" }, "peerDependencies": { "svelte": "^5.25.0" } }, "sha512-l9j5SWiixjtMM9OFDRqF+P2rfrMs62+xigGMPIOgBFYZoVQTmO5CtF12oTgtoSzgRmc/Ur9iI9a6elYu8Wmu3w=="],
|
||||||
|
|
||||||
|
"@tanstack/svelte-query-devtools": ["@tanstack/svelte-query-devtools@6.0.3", "", { "dependencies": { "@tanstack/query-devtools": "5.92.0", "esm-env": "^1.2.1" }, "peerDependencies": { "@tanstack/svelte-query": "^6.0.12", "svelte": "^5.25.0" } }, "sha512-AHc/vPiUWeMFXKvtrlZot7wIlsIm4z5vd0wDeQUKwE5XTfZODu0no1A4UCLzVnY2WpbBpakIEUMH+PmSMwYXKg=="],
|
||||||
|
|
||||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||||
|
|
||||||
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
||||||
|
|||||||
27
flake.lock
generated
Normal file
27
flake.lock
generated
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1768127708,
|
||||||
|
"narHash": "sha256-1Sm77VfZh3mU0F5OqKABNLWxOuDeHIlcFjsXeeiPazs=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "ffbc9f8cbaacfb331b6017d5a5abb21a492c9a38",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
35
flake.nix
Normal file
35
flake.nix
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
description = "ghost v2";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
{ nixpkgs, ... }@inputs:
|
||||||
|
let
|
||||||
|
systems = [ "x86_64-linux" ];
|
||||||
|
forAllSystems =
|
||||||
|
f:
|
||||||
|
nixpkgs.lib.genAttrs systems (
|
||||||
|
system:
|
||||||
|
f {
|
||||||
|
inherit system;
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells = forAllSystems (
|
||||||
|
{ pkgs, system }:
|
||||||
|
{
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
openssl
|
||||||
|
pkgconf
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -33,6 +33,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lucide/svelte": "^0.562.0",
|
"@lucide/svelte": "^0.562.0",
|
||||||
"@neondatabase/serverless": "^1.0.2",
|
"@neondatabase/serverless": "^1.0.2",
|
||||||
|
"@tanstack/svelte-query": "^6.0.15",
|
||||||
|
"@tanstack/svelte-query-devtools": "^6.0.3",
|
||||||
"better-auth": "^1.4.12",
|
"better-auth": "^1.4.12",
|
||||||
"bits-ui": "^2.15.4",
|
"bits-ui": "^2.15.4",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Avatar, Button, DropdownMenu } from 'bits-ui';
|
import { Avatar, Button, DropdownMenu, Separator } from 'bits-ui';
|
||||||
import { authClient } from './auth-client';
|
import { authClient } from './auth-client';
|
||||||
import Image from './Image.svelte';
|
import Image from './Image.svelte';
|
||||||
import { User } from '@lucide/svelte';
|
import { CircleUser, FolderGit2, User } from '@lucide/svelte';
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
type MockUser = {
|
||||||
|
image: string;
|
||||||
|
};
|
||||||
|
|
||||||
const session = authClient.useSession();
|
const session = authClient.useSession();
|
||||||
const user = $derived($session.data?.user);
|
const user = $derived($session.data?.user);
|
||||||
@@ -16,27 +20,38 @@
|
|||||||
|
|
||||||
<div class="h-14 w-full bg-[#292e42]">
|
<div class="h-14 w-full bg-[#292e42]">
|
||||||
<div class="mx-auto flex h-full max-w-[78rem] items-center justify-between">
|
<div class="mx-auto flex h-full max-w-[78rem] items-center justify-between">
|
||||||
|
<Button.Root onclick={() => goto('/')}>
|
||||||
<h1 class="header-title font-light">Godot Host</h1>
|
<h1 class="header-title font-light">Godot Host</h1>
|
||||||
<div>
|
</Button.Root>
|
||||||
{#if !user}
|
{#if !user && !$session.isPending}
|
||||||
<Button.Root class="rounded-md p-2 transition-colors hover:bg-gray-800" onclick={signIn}>
|
<Button.Root class="rounded-md p-2 transition-colors hover:bg-gray-800" onclick={signIn}>
|
||||||
Sign In
|
Sign In
|
||||||
</Button.Root>
|
</Button.Root>
|
||||||
{:else}
|
{:else if user}
|
||||||
<DropdownMenu.Root open={true}>
|
<DropdownMenu.Root>
|
||||||
<DropdownMenu.Trigger>
|
<DropdownMenu.Trigger>
|
||||||
<Image class="shadow-4xl h-10 w-10 rounded-full" src={user.image} />
|
<Image class="shadow-4xl h-10 w-10 rounded-full" src={user.image} />
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DropdownMenu.Portal>
|
<DropdownMenu.Portal>
|
||||||
<DropdownMenu.Content class="w-42 rounded-md bg-black shadow-xl shadow-gray-800/5">
|
<DropdownMenu.Content
|
||||||
<DropdownMenu.Item class="mt-1 flex h-10 items-center rounded-md px-2 py-1.5">
|
class="w-42 rounded-xl bg-black px-1 py-1.5 shadow-xl shadow-gray-800/5"
|
||||||
<User />
|
>
|
||||||
|
<DropdownMenu.Item class="dropdown-item cursor-pointer" onclick={() => goto('/add')}>
|
||||||
|
<FolderGit2 class="mr-2" />
|
||||||
|
<span>Add Project</span>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
class="dropdown-item cursor-pointer"
|
||||||
|
onclick={() => authClient.signOut()}
|
||||||
|
>
|
||||||
|
<User class="mr-2" />
|
||||||
<span>Sign Out</span>
|
<span>Sign Out</span>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
</DropdownMenu.Content>
|
</DropdownMenu.Content>
|
||||||
</DropdownMenu.Portal>
|
</DropdownMenu.Portal>
|
||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
|
{:else}
|
||||||
|
<div class="h-10 w-10 animate-pulse rounded-full bg-gray-700"></div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
147
src/lib/Repos.svelte
Normal file
147
src/lib/Repos.svelte
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Button } from 'bits-ui';
|
||||||
|
import { GitBranch, Star, Clock, Import, Search, RefreshCw } from '@lucide/svelte';
|
||||||
|
import type { Repository } from './types/repo';
|
||||||
|
import { createQuery } from '@tanstack/svelte-query';
|
||||||
|
import { authClient } from './auth-client';
|
||||||
|
|
||||||
|
const session = authClient.useSession();
|
||||||
|
|
||||||
|
const query = createQuery(() => ({
|
||||||
|
queryKey: ['github-repositories'],
|
||||||
|
queryFn: async () => {
|
||||||
|
const response = await fetch('https://api.github.com/user/repos?affiliation=owner', {
|
||||||
|
headers: {}
|
||||||
|
});
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
$inspect(query.data);
|
||||||
|
|
||||||
|
const mockRepositories: Repository[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: 'Mock',
|
||||||
|
fullName: 'Mock',
|
||||||
|
description: 'Mock Data',
|
||||||
|
language: 'GDScript',
|
||||||
|
stars: 42,
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
|
isPrivate: false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
let searchQuery = $state('');
|
||||||
|
let adding = $state<number | null>(null);
|
||||||
|
|
||||||
|
const filteredRepositories = $derived(
|
||||||
|
mockRepositories.filter(
|
||||||
|
(repo) =>
|
||||||
|
repo.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||||
|
repo.description?.toLowerCase().includes(searchQuery.toLowerCase())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleImport = async (repoId: number) => {
|
||||||
|
adding = repoId;
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||||
|
adding = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const languageColors: Record<string, string> = {
|
||||||
|
GDScript: 'bg-blue-500',
|
||||||
|
'C#': 'bg-green-500',
|
||||||
|
Rust: 'bg-orange-500',
|
||||||
|
C: 'bg-gray-500',
|
||||||
|
'C++': 'bg-pink-500'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="rounded-xl bg-gray-900 p-6 shadow-xl ring-1 ring-gray-800">
|
||||||
|
<div class="mb-6 flex items-center justify-between">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<GitBranch class="h-6 w-6 text-gray-400" />
|
||||||
|
<h2 class="text-xl font-semibold text-white">Import Git Repository</h2>
|
||||||
|
</div>
|
||||||
|
<Button.Root
|
||||||
|
class="flex items-center gap-2 rounded-lg px-3 py-2 text-sm text-gray-400 transition-colors hover:bg-gray-800 hover:text-white"
|
||||||
|
>
|
||||||
|
<RefreshCw class="h-4 w-4" />
|
||||||
|
<span>Refresh</span>
|
||||||
|
</Button.Root>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="relative mb-6">
|
||||||
|
<Search class="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-gray-500" />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
bind:value={searchQuery}
|
||||||
|
placeholder="Search repositories..."
|
||||||
|
class="w-full rounded-lg border border-gray-700 bg-gray-800 py-2.5 pr-4 pl-10 text-white placeholder-gray-500 transition-colors outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-3">
|
||||||
|
{#each filteredRepositories as repo (repo.id)}
|
||||||
|
<div
|
||||||
|
class="group flex items-center justify-between rounded-lg border border-gray-800 bg-gray-800/50 p-4 transition-colors hover:border-gray-700 hover:bg-gray-800"
|
||||||
|
>
|
||||||
|
<div class="min-w-0 flex-1">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h3 class="truncate font-medium text-white">{repo.name}</h3>
|
||||||
|
{#if repo.isPrivate}
|
||||||
|
<span class="rounded-full border border-gray-600 px-2 py-0.5 text-xs text-gray-400">
|
||||||
|
Private
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{#if repo.description}
|
||||||
|
<p class="mt-1 truncate text-sm text-gray-400">{repo.description}</p>
|
||||||
|
{:else}
|
||||||
|
<p class="mt-1 text-sm text-gray-500 italic">No description</p>
|
||||||
|
{/if}
|
||||||
|
<div class="mt-2 flex items-center gap-4 text-xs text-gray-500">
|
||||||
|
{#if repo.language}
|
||||||
|
<span class="flex items-center gap-1.5">
|
||||||
|
<span
|
||||||
|
class="h-2.5 w-2.5 rounded-full {languageColors[repo.language] ?? 'bg-gray-500'}"
|
||||||
|
></span>
|
||||||
|
{repo.language}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
<span class="flex items-center gap-1">
|
||||||
|
<Star class="h-3.5 w-3.5" />
|
||||||
|
{repo.stars}
|
||||||
|
</span>
|
||||||
|
<span class="flex items-center gap-1">
|
||||||
|
<Clock class="h-3.5 w-3.5" />
|
||||||
|
{repo.updatedAt}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button.Root
|
||||||
|
class="ml-4 flex items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-500 disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
disabled={adding !== null}
|
||||||
|
onclick={() => handleImport(repo.id)}
|
||||||
|
>
|
||||||
|
{#if adding === repo.id}
|
||||||
|
<RefreshCw class="h-4 w-4 animate-spin" />
|
||||||
|
<span>Adding...</span>
|
||||||
|
{:else}
|
||||||
|
<Import class="h-4 w-4" />
|
||||||
|
<span>Add</span>
|
||||||
|
{/if}
|
||||||
|
</Button.Root>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="py-8 text-center text-gray-500">
|
||||||
|
<p>No repositories found matching "{searchQuery}"</p>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-6 text-center text-sm text-gray-500">
|
||||||
|
You must have a dist/ folder with index.html + index.wasm
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
10
src/lib/types/repo.ts
Normal file
10
src/lib/types/repo.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export type Repository = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
fullName: string;
|
||||||
|
description: string | null;
|
||||||
|
language: string | null;
|
||||||
|
stars: number;
|
||||||
|
updatedAt: string;
|
||||||
|
isPrivate: boolean;
|
||||||
|
};
|
||||||
@@ -1,9 +1,16 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Header from '$lib/Header.svelte';
|
import Header from '$lib/Header.svelte';
|
||||||
|
import { QueryClient, QueryClientProvider } from '@tanstack/svelte-query';
|
||||||
import './layout.css';
|
import './layout.css';
|
||||||
|
import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools';
|
||||||
|
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
|
const queryClient = new QueryClient();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Header />
|
<Header />
|
||||||
{@render children()}
|
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
{@render children()}
|
||||||
|
<SvelteQueryDevtools />
|
||||||
|
</QueryClientProvider>
|
||||||
|
|||||||
7
src/routes/add/+page.svelte
Normal file
7
src/routes/add/+page.svelte
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Repos from '$lib/Repos.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<main class="mx-auto mt-8 max-w-3xl px-4">
|
||||||
|
<Repos />
|
||||||
|
</main>
|
||||||
@@ -52,6 +52,15 @@ h1 {
|
|||||||
font-family: 'Times New Roman';
|
font-family: 'Times New Roman';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
@apply h-10;
|
||||||
|
@apply rounded-lg;
|
||||||
|
@apply px-2 py-1;
|
||||||
|
@apply hover:bg-gray-800;
|
||||||
|
}
|
||||||
|
|
||||||
button:default {
|
button:default {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
|
|||||||
Reference in New Issue
Block a user