added card component and workspace display
This commit is contained in:
20
src/lib/components/ui/card/card-action.svelte
Normal file
20
src/lib/components/ui/card/card-action.svelte
Normal file
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="card-action"
|
||||
class={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
15
src/lib/components/ui/card/card-content.svelte
Normal file
15
src/lib/components/ui/card/card-content.svelte
Normal file
@@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div bind:this={ref} data-slot="card-content" class={cn("px-6", className)} {...restProps}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
20
src/lib/components/ui/card/card-description.svelte
Normal file
20
src/lib/components/ui/card/card-description.svelte
Normal file
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLParagraphElement>> = $props();
|
||||
</script>
|
||||
|
||||
<p
|
||||
bind:this={ref}
|
||||
data-slot="card-description"
|
||||
class={cn("text-muted-foreground text-sm", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</p>
|
||||
20
src/lib/components/ui/card/card-footer.svelte
Normal file
20
src/lib/components/ui/card/card-footer.svelte
Normal file
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="card-footer"
|
||||
class={cn("[.border-t]:pt-6 flex items-center px-6", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
23
src/lib/components/ui/card/card-header.svelte
Normal file
23
src/lib/components/ui/card/card-header.svelte
Normal file
@@ -0,0 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="card-header"
|
||||
class={cn(
|
||||
"@container/card-header has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6 grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6",
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
20
src/lib/components/ui/card/card-title.svelte
Normal file
20
src/lib/components/ui/card/card-title.svelte
Normal file
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="card-title"
|
||||
class={cn("font-semibold leading-none", className)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
23
src/lib/components/ui/card/card.svelte
Normal file
23
src/lib/components/ui/card/card.svelte
Normal file
@@ -0,0 +1,23 @@
|
||||
<script lang="ts">
|
||||
import type { HTMLAttributes } from "svelte/elements";
|
||||
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
children,
|
||||
...restProps
|
||||
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
bind:this={ref}
|
||||
data-slot="card"
|
||||
class={cn(
|
||||
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
25
src/lib/components/ui/card/index.ts
Normal file
25
src/lib/components/ui/card/index.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import Root from "./card.svelte";
|
||||
import Content from "./card-content.svelte";
|
||||
import Description from "./card-description.svelte";
|
||||
import Footer from "./card-footer.svelte";
|
||||
import Header from "./card-header.svelte";
|
||||
import Title from "./card-title.svelte";
|
||||
import Action from "./card-action.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
Content,
|
||||
Description,
|
||||
Footer,
|
||||
Header,
|
||||
Title,
|
||||
Action,
|
||||
//
|
||||
Root as Card,
|
||||
Content as CardContent,
|
||||
Description as CardDescription,
|
||||
Footer as CardFooter,
|
||||
Header as CardHeader,
|
||||
Title as CardTitle,
|
||||
Action as CardAction,
|
||||
};
|
||||
@@ -1,5 +1,33 @@
|
||||
import type { Workspace } from "$lib/types/workspace";
|
||||
|
||||
let ws: Workspace[] = [
|
||||
{
|
||||
Id: "1",
|
||||
Name: "Test 1",
|
||||
Description: "This is a test description"
|
||||
},
|
||||
{
|
||||
Id: "2",
|
||||
Name: "Test 2",
|
||||
Description: "This is a longer test description"
|
||||
},
|
||||
{
|
||||
Id: "3",
|
||||
Name: "Test 3",
|
||||
Description: "This is a slightly longer test description"
|
||||
},
|
||||
{
|
||||
Id: "4",
|
||||
Name: "Test 4",
|
||||
Description: "This is an even slightly longer test description"
|
||||
},
|
||||
{
|
||||
Id: "5",
|
||||
Name: "Test 5",
|
||||
Description: "This is a veryyyyyyyyyyyyyyyyyyyyyyyyyyy longggggggggggggggggggggggggggg test descriptionnnnnnnnnnnnnnnnnnnnnnnnnnnnnn"
|
||||
},
|
||||
]
|
||||
|
||||
export async function get_workspaces(): Promise<Workspace[]> {
|
||||
return []
|
||||
return ws
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
export type Workspace = {
|
||||
Id: string,
|
||||
Name: string,
|
||||
}
|
||||
Id: string;
|
||||
Name: string;
|
||||
Description: string;
|
||||
};
|
||||
|
||||
@@ -3,24 +3,65 @@
|
||||
import { Button } from "$lib/components/ui/button/index.js";
|
||||
import FolderCodeIcon from "@lucide/svelte/icons/folder-code";
|
||||
import { get_workspaces } from "$lib/services/workspaces";
|
||||
import type { Workspace } from "$lib/types/workspace";
|
||||
import * as Card from "$lib/components/ui/card/index";
|
||||
|
||||
get_workspaces;
|
||||
let showPrompt = false;
|
||||
let workspaces: Workspace[] = [];
|
||||
|
||||
get_workspaces().then((ws) => {
|
||||
if (ws.length == 0) {
|
||||
showPrompt = true;
|
||||
} else {
|
||||
workspaces = ws;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<Empty.Root class="flex min-h-[calc(100vh-4rem)] items-center justify-center">
|
||||
<Empty.Header>
|
||||
<Empty.Media variant="icon">
|
||||
<FolderCodeIcon />
|
||||
</Empty.Media>
|
||||
<Empty.Title>No Workspaces Yet</Empty.Title>
|
||||
<Empty.Description>
|
||||
You haven't created any Workspaces yet. Get started by creating your first
|
||||
project.
|
||||
</Empty.Description>
|
||||
</Empty.Header>
|
||||
<Empty.Content>
|
||||
<div class="flex gap-2">
|
||||
<Button>Create Workspace</Button>
|
||||
{#if showPrompt}
|
||||
<Empty.Root class="flex min-h-[calc(100vh-4rem)] items-center justify-center">
|
||||
<Empty.Header>
|
||||
<Empty.Media variant="icon">
|
||||
<FolderCodeIcon />
|
||||
</Empty.Media>
|
||||
<Empty.Title>No Workspaces Yet</Empty.Title>
|
||||
<Empty.Description>
|
||||
You haven't created any Workspaces yet. Get started by creating your
|
||||
first project.
|
||||
</Empty.Description>
|
||||
</Empty.Header>
|
||||
<Empty.Content>
|
||||
<div class="flex gap-2">
|
||||
<Button>Create Workspace</Button>
|
||||
</div>
|
||||
</Empty.Content>
|
||||
</Empty.Root>
|
||||
{:else}
|
||||
<div class="min-h-[calc(100vh-4rem)] p-6">
|
||||
<div
|
||||
class="grid gap-6
|
||||
grid-cols-1
|
||||
sm:grid-cols-2
|
||||
md:grid-cols-3
|
||||
xl:grid-cols-4
|
||||
2xl:grid-cols-5"
|
||||
>
|
||||
{#each workspaces as workspace (workspace.Id)}
|
||||
<Card.Root
|
||||
class="min-h-40 w-full max-w-xs mx-auto flex flex-col justify-between cursor-pointer hover:shadow-md transition-shadow"
|
||||
>
|
||||
<Card.Header>
|
||||
<Card.Title class="truncate">{workspace.Name}</Card.Title>
|
||||
<Card.Description class="text-xs text-muted-foreground">
|
||||
{workspace.Description}
|
||||
</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Footer class="flex items-center justify-center gap-2">
|
||||
<Button size="sm" class="justify-center">Open</Button>
|
||||
<Button size="sm" class="justify-center">Edit</Button>
|
||||
</Card.Footer>
|
||||
</Card.Root>
|
||||
{/each}
|
||||
</div>
|
||||
</Empty.Content>
|
||||
</Empty.Root>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user