Skip to content

Commit d84bcea

Browse files
committed
Merge branch 'kiizuha' (patches from Muhammad Rizki)
This series of patches was planned only to update profile page feature, since there is a change in the API structure, I also fixed the API response type to prevent breaking change. To prevent more breaking change on production site in the future, sir Ammar has made a staging API for development stage, since there is a staging API version, I added an environment variable `PUBLIC_BASE_URL` for each environment (development or production). You should set `PUBLIC_BASE_URL` environment in your own server, there is an example file for development and production environment in this patch, please see `.env.development.example` and `.env.production.example` in root directory. I also added API documentation in Postman workspace that I created myself, you can find it in this link: https://gnuweeb.postman.co/workspace/GNU%252FWeeb~2805fbdd-376b-42de-8fe1-2a4cfa22ed3c/overview?ctx=updates * kiizuha: docs: update README.md chore(login): use $derived() instead of function based feat(seo): add SEO for site metadata chore(meta): rename favicon.png to favicon.ico refactor!:feat: update API response structure, update profile page feat(typing/enum): add Gender and IsActive enum feat(icons): Add social icons feat(http): Use PUBLIC_BASE_URL for each environment feat(ui): Add popover and dialog UI component chore(navigations): Replace index /settings url chore(responsive): adjust styling fix(breadcrumb): Move settingsNav to settings items navigations fix(profile): fix edit avatar button position chore(settings/layout): use prose: for heading styling chore(change-pwd): adjust change password heading styling refactor: optimize icon imports to reduce bundle size fix(typing): add user_info type prop Link: https://lore.gnuweeb.org/gwml/[email protected] Signed-off-by: Ammar Faizi <[email protected]>
2 parents b6844e2 + 2d08530 commit d84bcea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1024
-219
lines changed

.env.development.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# remove .example filename suffix
2+
PUBLIC_BASE_URL="https://mail-staging.gnuweeb.org/api.php"

.env.production.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# remove .example filename suffix
2+
PUBLIC_BASE_URL="https://mail-staging.gnuweeb.org/api.php"

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Thumbs.db
2727
# Env
2828
.env
2929
.env.*
30-
!.env.example
30+
!.env.*.example
3131
!.env.test
3232

3333
# Vite

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- [How to Build](#how-to-build)
1212
- [Code Standards](#code-standards)
1313
- [How to Develop or Contribute](#how-to-develop)
14+
- [API examples](#api-examples)
1415

1516
<h2 id="requirements">
1617
Requirements
@@ -109,3 +110,9 @@ if you want to create styles or CSS that affects globally you can write it in [.
109110
<h3>Aliases</h3>
110111

111112
You may add some import aliases, you can edit it in [svelte.config.js](./svelte.config.js), we used `$` as import alias, you must follow our standards to remain consistency.
113+
114+
<h2 id="api-examples">
115+
API Examples
116+
</h2>
117+
118+
You can view all API examples in our Postman workspace [here](https://gnuweeb.postman.co/workspace/GNU%252FWeeb~2805fbdd-376b-42de-8fe1-2a4cfa22ed3c/overview?ctx=updates).

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"@sveltejs/kit": "^2.0.0",
1919
"@sveltejs/vite-plugin-svelte": "^4.0.0",
2020
"autoprefixer": "^10.4.20",
21-
"bits-ui": "^1.3.2",
21+
"bits-ui": "^1.3.5",
2222
"clsx": "^2.1.1",
2323
"eslint": "^9.7.0",
2424
"eslint-config-prettier": "^9.1.0",

src/app.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="utf-8" />
5-
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
5+
<link rel="icon" href="%sveltekit.assets%/favicon.ico" />
66
<meta name="viewport" content="width=device-width, initial-scale=1" />
77
%sveltekit.head%
88
</head>

src/lib/components/customs/app-sidebar.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import Separator from "$components/ui/separator/separator.svelte";
44
import * as Sidebar from "$lib/components/ui/sidebar";
55
import { useAuth } from "$lib/hooks/auth.svelte";
6-
import { LogOut, Mails, SquareArrowOutUpRight } from "lucide-svelte";
6+
import LogOut from "lucide-svelte/icons/log-out";
7+
import Mails from "lucide-svelte/icons/mails";
8+
import SquareArrowOutUpRight from "lucide-svelte/icons/square-arrow-out-up-right";
79
import type { ComponentProps } from "svelte";
810
import { goto } from "$app/navigation";
911
import Button from "$components/ui/button/button.svelte";

src/lib/components/customs/header.svelte

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,28 @@
44
import { page } from "$app/state";
55
import { navigations } from "$constants";
66
import Separator from "$components/ui/separator/separator.svelte";
7+
import * as typing from "$typings";
78
8-
const getRouteName = () => {
9-
const pathname = page.url.pathname;
10-
const found = navigations.find((path) => path.url === pathname);
9+
const getParentRoute = (
10+
path: string,
11+
items: typing.Navigations[],
12+
routePath: typing.Navigations[] = []
13+
): typing.Navigations[] => {
14+
for (const item of items) {
15+
if (path === item.url) {
16+
return [...routePath, item];
17+
}
1118
12-
return found?.name ?? "";
19+
if (item.items) {
20+
const foundPath = getParentRoute(path, item.items, [...routePath, item]);
21+
if (foundPath.length) return foundPath;
22+
}
23+
}
24+
return [];
25+
};
26+
27+
const getRouteName = () => {
28+
return getParentRoute(page.url.pathname, navigations);
1329
};
1430
</script>
1531

@@ -23,9 +39,18 @@
2339
<Breadcrumb.Link href="/">G/W Mail</Breadcrumb.Link>
2440
</Breadcrumb.Item>
2541
<Breadcrumb.Separator />
26-
<Breadcrumb.Item class="select-none">
27-
<Breadcrumb.Page>{getRouteName()}</Breadcrumb.Page>
28-
</Breadcrumb.Item>
42+
{#each getRouteName() as route, index (route.url)}
43+
{#if index === getRouteName().length - 1}
44+
<Breadcrumb.Item class="select-none">
45+
<Breadcrumb.Page>{route.name}</Breadcrumb.Page>
46+
</Breadcrumb.Item>
47+
{:else}
48+
<Breadcrumb.Item class="hidden md:block">
49+
<Breadcrumb.Link href={route.url}>{route.name}</Breadcrumb.Link>
50+
</Breadcrumb.Item>
51+
<Breadcrumb.Separator />
52+
{/if}
53+
{/each}
2954
</Breadcrumb.List>
3055
</Breadcrumb.Root>
3156
</div>

src/lib/components/customs/seo.svelte

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script lang="ts">
2+
interface Props {
3+
title: string;
4+
description: string;
5+
image?: string;
6+
}
7+
8+
let { title, description, image }: Props = $props();
9+
10+
const META_IMG = image ?? "/favicon.ico";
11+
</script>
12+
13+
<svelte:head>
14+
<title>{title}</title>
15+
<meta name="description" content={description} />
16+
<meta property="og:type" content="website" />
17+
<meta property="og:title" content={title} />
18+
<meta property="og:description" content={description} />
19+
<meta property="og:image" content={META_IMG} />
20+
<meta property="og:image:alt" content={META_IMG} />
21+
<meta name="twitter:card" content="summary_large_image" />
22+
<meta name="twitter:title" content={title} />
23+
<meta name="twitter:description" content={description} />
24+
<meta name="twitter:image" content={META_IMG} />
25+
<meta name="twitter:image:alt" content={META_IMG} />
26+
<meta name="robots" content="index, follow" />
27+
</svelte:head>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<script lang="ts">
2+
import type { HTMLAttributes } from "svelte/elements";
3+
4+
let { href, class: className }: HTMLAttributes<SVGElement> & { href?: string } = $props();
5+
</script>
6+
7+
{#if href}
8+
<a {href} aria-label="Social Icon" target="_blank" rel="noopener noreferrer">
9+
<svg
10+
xmlns="http://www.w3.org/2000/svg"
11+
width="24"
12+
height="24"
13+
viewBox="0 0 24 24"
14+
class={className}
15+
>
16+
<path
17+
fill="currentColor"
18+
d="M20.317 4.37a19.8 19.8 0 0 0-4.885-1.515a.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.3 18.3 0 0 0-5.487 0a13 13 0 0 0-.617-1.25a.08.08 0 0 0-.079-.037A19.7 19.7 0 0 0 3.677 4.37a.1.1 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.08.08 0 0 0 .031.057a19.9 19.9 0 0 0 5.993 3.03a.08.08 0 0 0 .084-.028a14 14 0 0 0 1.226-1.994a.076.076 0 0 0-.041-.106a13 13 0 0 1-1.872-.892a.077.077 0 0 1-.008-.128a10 10 0 0 0 .372-.292a.07.07 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.07.07 0 0 1 .078.01q.181.149.373.292a.077.077 0 0 1-.006.127a12.3 12.3 0 0 1-1.873.892a.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.08.08 0 0 0 .084.028a19.8 19.8 0 0 0 6.002-3.03a.08.08 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.06.06 0 0 0-.031-.03M8.02 15.33c-1.182 0-2.157-1.085-2.157-2.419c0-1.333.956-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.956 2.418-2.157 2.418m7.975 0c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.955-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.946 2.418-2.157 2.418"
19+
/>
20+
</svg>
21+
</a>
22+
{:else}
23+
<svg
24+
xmlns="http://www.w3.org/2000/svg"
25+
width="24"
26+
height="24"
27+
viewBox="0 0 24 24"
28+
class={className}
29+
>
30+
<path
31+
fill="currentColor"
32+
d="M20.317 4.37a19.8 19.8 0 0 0-4.885-1.515a.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.3 18.3 0 0 0-5.487 0a13 13 0 0 0-.617-1.25a.08.08 0 0 0-.079-.037A19.7 19.7 0 0 0 3.677 4.37a.1.1 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.08.08 0 0 0 .031.057a19.9 19.9 0 0 0 5.993 3.03a.08.08 0 0 0 .084-.028a14 14 0 0 0 1.226-1.994a.076.076 0 0 0-.041-.106a13 13 0 0 1-1.872-.892a.077.077 0 0 1-.008-.128a10 10 0 0 0 .372-.292a.07.07 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.07.07 0 0 1 .078.01q.181.149.373.292a.077.077 0 0 1-.006.127a12.3 12.3 0 0 1-1.873.892a.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.08.08 0 0 0 .084.028a19.8 19.8 0 0 0 6.002-3.03a.08.08 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.06.06 0 0 0-.031-.03M8.02 15.33c-1.182 0-2.157-1.085-2.157-2.419c0-1.333.956-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.956 2.418-2.157 2.418m7.975 0c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.955-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.946 2.418-2.157 2.418"
33+
/>
34+
</svg>
35+
{/if}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<script lang="ts">
2+
import type { HTMLAttributes } from "svelte/elements";
3+
4+
let { href, class: className }: HTMLAttributes<SVGElement> & { href?: string } = $props();
5+
</script>
6+
7+
{#if href}
8+
<a {href} aria-label="Social Icon" target="_blank" rel="noopener noreferrer">
9+
<svg
10+
xmlns="http://www.w3.org/2000/svg"
11+
width="24"
12+
height="24"
13+
viewBox="0 0 24 24"
14+
class={className}
15+
>
16+
<path
17+
fill="currentColor"
18+
d="M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
19+
/>
20+
</svg>
21+
</a>
22+
{:else}
23+
<svg
24+
xmlns="http://www.w3.org/2000/svg"
25+
width="24"
26+
height="24"
27+
viewBox="0 0 24 24"
28+
class={className}
29+
>
30+
<path
31+
fill="currentColor"
32+
d="M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
33+
/>
34+
</svg>
35+
{/if}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<script lang="ts">
2+
import type { HTMLAttributes } from "svelte/elements";
3+
4+
let { href, class: className }: HTMLAttributes<SVGElement> & { href?: string } = $props();
5+
</script>
6+
7+
{#if href}
8+
<a {href} aria-label="Social Icon" target="_blank" rel="noopener noreferrer">
9+
<svg
10+
xmlns="http://www.w3.org/2000/svg"
11+
width="24"
12+
height="24"
13+
viewBox="0 0 24 24"
14+
class={className}
15+
>
16+
<path
17+
fill="currentColor"
18+
d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12a12 12 0 0 0 12-12A12 12 0 0 0 12 0zm4.962 7.224c.1-.002.321.023.465.14a.5.5 0 0 1 .171.325c.016.093.036.306.02.472c-.18 1.898-.962 6.502-1.36 8.627c-.168.9-.499 1.201-.82 1.23c-.696.065-1.225-.46-1.9-.902c-1.056-.693-1.653-1.124-2.678-1.8c-1.185-.78-.417-1.21.258-1.91c.177-.184 3.247-2.977 3.307-3.23c.007-.032.014-.15-.056-.212s-.174-.041-.249-.024q-.159.037-5.061 3.345q-.72.495-1.302.48c-.428-.008-1.252-.241-1.865-.44c-.752-.245-1.349-.374-1.297-.789q.04-.324.893-.663q5.247-2.286 6.998-3.014c3.332-1.386 4.025-1.627 4.476-1.635"
19+
/>
20+
</svg>
21+
</a>
22+
{:else}
23+
<svg
24+
xmlns="http://www.w3.org/2000/svg"
25+
width="24"
26+
height="24"
27+
viewBox="0 0 24 24"
28+
class={className}
29+
>
30+
<path
31+
fill="currentColor"
32+
d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12a12 12 0 0 0 12-12A12 12 0 0 0 12 0zm4.962 7.224c.1-.002.321.023.465.14a.5.5 0 0 1 .171.325c.016.093.036.306.02.472c-.18 1.898-.962 6.502-1.36 8.627c-.168.9-.499 1.201-.82 1.23c-.696.065-1.225-.46-1.9-.902c-1.056-.693-1.653-1.124-2.678-1.8c-1.185-.78-.417-1.21.258-1.91c.177-.184 3.247-2.977 3.307-3.23c.007-.032.014-.15-.056-.212s-.174-.041-.249-.024q-.159.037-5.061 3.345q-.72.495-1.302.48c-.428-.008-1.252-.241-1.865-.44c-.752-.245-1.349-.374-1.297-.789q.04-.324.893-.663q5.247-2.286 6.998-3.014c3.332-1.386 4.025-1.627 4.476-1.635"
33+
/>
34+
</svg>
35+
{/if}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<script lang="ts">
2+
import type { HTMLAttributes } from "svelte/elements";
3+
4+
let { href, class: className }: HTMLAttributes<SVGElement> & { href?: string } = $props();
5+
</script>
6+
7+
{#if href}
8+
<a {href} aria-label="Social Icon" target="_blank" rel="noopener noreferrer">
9+
<svg
10+
xmlns="http://www.w3.org/2000/svg"
11+
width="24"
12+
height="24"
13+
viewBox="0 0 24 24"
14+
class={className}
15+
>
16+
<path
17+
fill="currentColor"
18+
d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584l-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"
19+
/>
20+
</svg>
21+
</a>
22+
{:else}
23+
<svg
24+
xmlns="http://www.w3.org/2000/svg"
25+
width="24"
26+
height="24"
27+
viewBox="0 0 24 24"
28+
class={className}
29+
>
30+
<path
31+
fill="currentColor"
32+
d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584l-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"
33+
/>
34+
</svg>
35+
{/if}

src/lib/components/ui/avatar/avatar-image.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
bind:ref
1616
{src}
1717
{alt}
18-
class={cn("aspect-square h-full w-full", className)}
18+
class={cn("aspect-square h-full w-full object-cover", className)}
1919
draggable={false}
2020
{...restProps}
2121
/>

src/lib/components/ui/avatar/avatar.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@
1313
<AvatarPrimitive.Root
1414
bind:loadingStatus
1515
bind:ref
16-
class={cn("relative flex size-10 shrink-0 overflow-hidden rounded-full", className)}
16+
class={cn("relative flex size-10 shrink-0 overflow-hidden rounded-full border-2 border-muted", className)}
1717
{...restProps}
1818
/>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<script lang="ts">
2+
import { Dialog as DialogPrimitive, type WithoutChildrenOrChild } from "bits-ui";
3+
import X from "lucide-svelte/icons/x";
4+
import type { Snippet } from "svelte";
5+
import * as Dialog from "./index";
6+
import { cn } from "$utils";
7+
8+
let {
9+
ref = $bindable(null),
10+
class: className,
11+
portalProps,
12+
children,
13+
...restProps
14+
}: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
15+
portalProps?: DialogPrimitive.PortalProps;
16+
children: Snippet;
17+
} = $props();
18+
</script>
19+
20+
<Dialog.Portal {...portalProps}>
21+
<Dialog.Overlay />
22+
<DialogPrimitive.Content
23+
bind:ref
24+
class={cn(
25+
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
26+
className
27+
)}
28+
{...restProps}
29+
>
30+
{@render children?.()}
31+
<DialogPrimitive.Close
32+
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
33+
>
34+
<X class="size-4" />
35+
<span class="sr-only">Close</span>
36+
</DialogPrimitive.Close>
37+
</DialogPrimitive.Content>
38+
</Dialog.Portal>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<script lang="ts">
2+
import { Dialog as DialogPrimitive } from "bits-ui";
3+
import { cn } from "$utils";
4+
5+
let {
6+
ref = $bindable(null),
7+
class: className,
8+
...restProps
9+
}: DialogPrimitive.DescriptionProps = $props();
10+
</script>
11+
12+
<DialogPrimitive.Description
13+
bind:ref
14+
class={cn("text-sm text-muted-foreground", className)}
15+
{...restProps}
16+
/>

0 commit comments

Comments
 (0)