Skip to content

Commit 68ecd2f

Browse files
thomasahleclaude
andcommitted
Fix sidebar layout: header above sidebar, no mobile backdrop
- sidebar.svelte: position:absolute (was fixed) + h-full (was h-svh) so the desktop panel is contained within the below-header content row, not spanning the full viewport height - +layout.svelte: SidebarProvider is now flex-col; header is the first (full-width) child; sidebar+content row is the second child with relative overflow-hidden so the absolute panel is clipped correctly - sheet-content.svelte: add overlayClass prop so callers can style the backdrop independently of the sheet panel - sidebar.svelte: mobile sheet uses overlayClass="bg-transparent pointer-events-none" — panel slides in without dark backdrop Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e8b087d commit 68ecd2f

3 files changed

Lines changed: 75 additions & 11 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<script lang="ts" module>
2+
import { tv, type VariantProps } from "tailwind-variants";
3+
export const sheetVariants = tv({
4+
base: "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
5+
variants: {
6+
side: {
7+
top: "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
8+
bottom: "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
9+
left: "data-[state=closed]:slide-out-to-start data-[state=open]:slide-in-from-start inset-y-0 start-0 h-full w-3/4 border-e sm:max-w-sm",
10+
right: "data-[state=closed]:slide-out-to-end data-[state=open]:slide-in-from-end inset-y-0 end-0 h-full w-3/4 border-s sm:max-w-sm",
11+
},
12+
},
13+
defaultVariants: {
14+
side: "right",
15+
},
16+
});
17+
18+
export type Side = VariantProps<typeof sheetVariants>["side"];
19+
</script>
20+
21+
<script lang="ts">
22+
import { Dialog as SheetPrimitive } from "bits-ui";
23+
import XIcon from "@lucide/svelte/icons/x";
24+
import type { Snippet } from "svelte";
25+
import SheetPortal from "./sheet-portal.svelte";
26+
import SheetOverlay from "./sheet-overlay.svelte";
27+
import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
28+
import type { ComponentProps } from "svelte";
29+
30+
let {
31+
ref = $bindable(null),
32+
class: className,
33+
side = "right",
34+
portalProps,
35+
overlayClass,
36+
children,
37+
...restProps
38+
}: WithoutChildrenOrChild<SheetPrimitive.ContentProps> & {
39+
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof SheetPortal>>;
40+
side?: Side;
41+
overlayClass?: string;
42+
children: Snippet;
43+
} = $props();
44+
</script>
45+
46+
<SheetPortal {...portalProps}>
47+
<SheetOverlay class={overlayClass} />
48+
<SheetPrimitive.Content
49+
bind:ref
50+
data-slot="sheet-content"
51+
class={cn(sheetVariants({ side }), className)}
52+
{...restProps}
53+
>
54+
{@render children?.()}
55+
<SheetPrimitive.Close
56+
class="ring-offset-background focus-visible:ring-ring absolute end-4 top-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:pointer-events-none"
57+
>
58+
<XIcon class="size-4" />
59+
<span class="sr-only">Close</span>
60+
</SheetPrimitive.Close>
61+
</SheetPrimitive.Content>
62+
</SheetPortal>

src/lib/components/ui/sidebar/sidebar.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
data-slot="sidebar"
4444
data-mobile="true"
4545
class="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
46+
overlayClass="bg-transparent pointer-events-none"
4647
style="--sidebar-width: {SIDEBAR_WIDTH_MOBILE};"
4748
{side}
4849
>
@@ -80,7 +81,7 @@
8081
<div
8182
data-slot="sidebar-container"
8283
class={cn(
83-
"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear narrow:flex",
84+
"absolute inset-y-0 z-10 hidden h-full w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear narrow:flex",
8485
side === "left"
8586
? "start-0 group-data-[collapsible=offcanvas]:start-[calc(var(--sidebar-width)*-1)]"
8687
: "end-0 group-data-[collapsible=offcanvas]:end-[calc(var(--sidebar-width)*-1)]",

src/routes/+layout.svelte

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,16 +115,10 @@
115115
</div>
116116
{/snippet}
117117
118-
<SidebarProvider bind:open={sidebarOpen} class="h-dvh overflow-hidden font-sans">
119-
<Sidebar collapsible="offcanvas">
120-
<SidebarContent>
121-
{@render navItems()}
122-
</SidebarContent>
123-
</Sidebar>
118+
<SidebarProvider bind:open={sidebarOpen} class="h-dvh overflow-hidden flex-col font-sans p-3 gap-[0.7rem] max-narrow:p-0 max-narrow:gap-0">
124119
125-
<!-- Main area: header + lesson content -->
126-
<div class="flex-1 min-w-0 flex flex-col h-dvh overflow-hidden p-3 gap-[0.7rem] max-narrow:p-0 max-narrow:gap-0">
127-
<header class="bg-surface border border-border rounded-[14px] shadow-app flex flex-col max-narrow:rounded-none max-narrow:border-x-0 max-narrow:border-t-0">
120+
<!-- Header spans full width above the sidebar+content row -->
121+
<header class="bg-surface border border-border rounded-[14px] shadow-app flex flex-col flex-shrink-0 max-narrow:rounded-none max-narrow:border-x-0 max-narrow:border-t-0">
128122
<!-- Row 1: logo + title + utility buttons -->
129123
<div class="flex items-center justify-between px-4 py-[0.6rem]">
130124
<div class="flex items-center gap-2">
@@ -194,8 +188,15 @@
194188
</button>
195189
<span class="text-[0.82rem] text-muted-foreground">{breadcrumbs}</span>
196190
</div>
197-
</header>
191+
</header>
198192
193+
<!-- Sidebar + lesson content row (relative so the absolute sidebar is contained here) -->
194+
<div class="flex flex-1 min-h-0 relative overflow-hidden">
195+
<Sidebar collapsible="offcanvas">
196+
<SidebarContent>
197+
{@render navItems()}
198+
</SidebarContent>
199+
</Sidebar>
199200
{@render children()}
200201
</div>
201202
</SidebarProvider>

0 commit comments

Comments
 (0)