Skip to content

Commit a13b469

Browse files
committed
Add shared input, skeleton, and tooltip UI modules
1 parent f5678ad commit a13b469

10 files changed

Lines changed: 182 additions & 0 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Root from "./input.svelte";
2+
3+
export {
4+
Root,
5+
//
6+
Root as Input,
7+
};
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<script lang="ts">
2+
import type { HTMLInputAttributes, HTMLInputTypeAttribute } from "svelte/elements";
3+
import { cn, type WithElementRef } from "$lib/utils.js";
4+
5+
type InputType = Exclude<HTMLInputTypeAttribute, "file">;
6+
7+
type Props = WithElementRef<
8+
Omit<HTMLInputAttributes, "type"> &
9+
({ type: "file"; files?: FileList } | { type?: InputType; files?: undefined })
10+
>;
11+
12+
let {
13+
ref = $bindable(null),
14+
value = $bindable(),
15+
type,
16+
files = $bindable(),
17+
class: className,
18+
"data-slot": dataSlot = "input",
19+
...restProps
20+
}: Props = $props();
21+
</script>
22+
23+
{#if type === "file"}
24+
<input
25+
bind:this={ref}
26+
data-slot={dataSlot}
27+
class={cn(
28+
"selection:bg-primary dark:bg-input/30 selection:text-primary-foreground border-input ring-offset-background placeholder:text-muted-foreground flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 pt-1.5 text-sm font-medium shadow-xs transition-[color,box-shadow] outline-none disabled:cursor-not-allowed disabled:opacity-50",
29+
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
30+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
31+
className
32+
)}
33+
type="file"
34+
bind:files
35+
bind:value
36+
{...restProps}
37+
/>
38+
{:else}
39+
<input
40+
bind:this={ref}
41+
data-slot={dataSlot}
42+
class={cn(
43+
"border-input bg-background selection:bg-primary dark:bg-input/30 selection:text-primary-foreground ring-offset-background placeholder:text-muted-foreground flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
44+
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
45+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
46+
className
47+
)}
48+
{type}
49+
bind:value
50+
{...restProps}
51+
/>
52+
{/if}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Root from "./skeleton.svelte";
2+
3+
export {
4+
Root,
5+
//
6+
Root as Skeleton,
7+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script lang="ts">
2+
import { cn, type WithElementRef, type WithoutChildren } from "$lib/utils.js";
3+
import type { HTMLAttributes } from "svelte/elements";
4+
5+
let {
6+
ref = $bindable(null),
7+
class: className,
8+
...restProps
9+
}: WithoutChildren<WithElementRef<HTMLAttributes<HTMLDivElement>>> = $props();
10+
</script>
11+
12+
<div
13+
bind:this={ref}
14+
data-slot="skeleton"
15+
class={cn("bg-accent animate-pulse rounded-md", className)}
16+
{...restProps}
17+
></div>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import Root from "./tooltip.svelte";
2+
import Trigger from "./tooltip-trigger.svelte";
3+
import Content from "./tooltip-content.svelte";
4+
import Provider from "./tooltip-provider.svelte";
5+
import Portal from "./tooltip-portal.svelte";
6+
7+
export {
8+
Root,
9+
Trigger,
10+
Content,
11+
Provider,
12+
Portal,
13+
//
14+
Root as Tooltip,
15+
Content as TooltipContent,
16+
Trigger as TooltipTrigger,
17+
Provider as TooltipProvider,
18+
Portal as TooltipPortal,
19+
};
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<script lang="ts">
2+
import { Tooltip as TooltipPrimitive } from "bits-ui";
3+
import { cn } from "$lib/utils.js";
4+
import TooltipPortal from "./tooltip-portal.svelte";
5+
import type { ComponentProps } from "svelte";
6+
import type { WithoutChildrenOrChild } from "$lib/utils.js";
7+
8+
let {
9+
ref = $bindable(null),
10+
class: className,
11+
sideOffset = 0,
12+
side = "top",
13+
children,
14+
arrowClasses,
15+
portalProps,
16+
...restProps
17+
}: TooltipPrimitive.ContentProps & {
18+
arrowClasses?: string;
19+
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof TooltipPortal>>;
20+
} = $props();
21+
</script>
22+
23+
<TooltipPortal {...portalProps}>
24+
<TooltipPrimitive.Content
25+
bind:ref
26+
data-slot="tooltip-content"
27+
{sideOffset}
28+
{side}
29+
class={cn(
30+
"bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-end-2 data-[side=right]:slide-in-from-start-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--bits-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
31+
className
32+
)}
33+
{...restProps}
34+
>
35+
{@render children?.()}
36+
<TooltipPrimitive.Arrow>
37+
{#snippet child({ props })}
38+
<div
39+
class={cn(
40+
"bg-foreground z-50 size-2.5 rotate-45 rounded-[2px]",
41+
"data-[side=top]:translate-x-1/2 data-[side=top]:translate-y-[calc(-50%_+_2px)]",
42+
"data-[side=bottom]:-translate-x-1/2 data-[side=bottom]:-translate-y-[calc(-50%_+_1px)]",
43+
"data-[side=right]:translate-x-[calc(50%_+_2px)] data-[side=right]:translate-y-1/2",
44+
"data-[side=left]:-translate-y-[calc(50%_-_3px)]",
45+
arrowClasses
46+
)}
47+
{...props}
48+
></div>
49+
{/snippet}
50+
</TooltipPrimitive.Arrow>
51+
</TooltipPrimitive.Content>
52+
</TooltipPortal>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script lang="ts">
2+
import { Tooltip as TooltipPrimitive } from "bits-ui";
3+
4+
let { ...restProps }: TooltipPrimitive.PortalProps = $props();
5+
</script>
6+
7+
<TooltipPrimitive.Portal {...restProps} />
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script lang="ts">
2+
import { Tooltip as TooltipPrimitive } from "bits-ui";
3+
4+
let { ...restProps }: TooltipPrimitive.ProviderProps = $props();
5+
</script>
6+
7+
<TooltipPrimitive.Provider {...restProps} />
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script lang="ts">
2+
import { Tooltip as TooltipPrimitive } from "bits-ui";
3+
4+
let { ref = $bindable(null), ...restProps }: TooltipPrimitive.TriggerProps = $props();
5+
</script>
6+
7+
<TooltipPrimitive.Trigger bind:ref data-slot="tooltip-trigger" {...restProps} />
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script lang="ts">
2+
import { Tooltip as TooltipPrimitive } from "bits-ui";
3+
4+
let { open = $bindable(false), ...restProps }: TooltipPrimitive.RootProps = $props();
5+
</script>
6+
7+
<TooltipPrimitive.Root bind:open {...restProps} />

0 commit comments

Comments
 (0)