diff --git a/frontend/src/lib/components/ui/ConfirmDialog.svelte b/frontend/src/lib/components/ui/ConfirmDialog.svelte
new file mode 100644
index 0000000..3a838f0
--- /dev/null
+++ b/frontend/src/lib/components/ui/ConfirmDialog.svelte
@@ -0,0 +1,52 @@
+
+
+
+ {message}
+
+ {#snippet footer()}
+
+
+ {/snippet}
+
diff --git a/frontend/src/lib/components/ui/Drawer.svelte b/frontend/src/lib/components/ui/Drawer.svelte
new file mode 100644
index 0000000..d57a994
--- /dev/null
+++ b/frontend/src/lib/components/ui/Drawer.svelte
@@ -0,0 +1,62 @@
+
+
+{#if open}
+
+
+
+
+
+
+
+{/if}
diff --git a/frontend/src/lib/components/ui/Modal.svelte b/frontend/src/lib/components/ui/Modal.svelte
new file mode 100644
index 0000000..46fecc2
--- /dev/null
+++ b/frontend/src/lib/components/ui/Modal.svelte
@@ -0,0 +1,137 @@
+
+
+{#if open}
+
+
+
+
+
+
+ {#if title || closable}
+
+ {#if title}
+ {title}
+ {:else}
+
+ {/if}
+ {#if closable}
+
+ {/if}
+
+ {/if}
+
+
+ {@render children?.()}
+
+
+ {#if footer}
+
+ {/if}
+
+
+{/if}
diff --git a/frontend/src/lib/components/ui/Tabs.svelte b/frontend/src/lib/components/ui/Tabs.svelte
new file mode 100644
index 0000000..35cfe57
--- /dev/null
+++ b/frontend/src/lib/components/ui/Tabs.svelte
@@ -0,0 +1,111 @@
+
+
+
+
+ {#each tabs as tab (tab.id)}
+ {@const active = tab.id === value}
+
+ {/each}
+
+
+
+ {@render children?.(value)}
+
+