Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 62 additions & 6 deletions apps/web/src/components/PrecedentDrawer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
}

const COURT_ORDER: CaseAnnotation['court'][] = ['SCOTUS', 'Appellate', 'District'];
// Use custom theme colors (--color-amber, --color-teal, --color-slate) for consistency
const COURT_COLORS: Record<CaseAnnotation['court'], string> = {
SCOTUS: 'text-amber dark:text-amber',
Appellate: 'text-teal dark:text-teal-bright',
Expand Down Expand Up @@ -43,22 +42,28 @@
</script>

{#if annotations.length > 0}
<!-- Toggle button -->
<!--
Persistent 3-column panel at 2xl (≥1440px):
Shows as a static sidebar column, no toggle needed.
Below 2xl: reverts to fixed overlay drawer behavior.
-->

<!-- Toggle button — hidden at 2xl (persistent panel replaces it) -->
<button
onclick={() => (open = !open)}
class="fixed right-0 top-1/2 z-40 -translate-y-1/2 rounded-l-md bg-teal px-2 py-3 text-xs font-semibold text-white shadow-lg hover:opacity-90 transition-opacity"
class="fixed right-0 top-1/2 z-40 -translate-y-1/2 rounded-l-md bg-teal px-2 py-3 text-xs font-semibold text-white shadow-lg hover:opacity-90 transition-opacity 2xl:hidden"
aria-label={open ? 'Close precedent drawer' : 'Open precedent drawer'}
aria-expanded={open}
aria-controls="precedent-drawer-panel"
>
{open ? '›' : '‹'} Cases ({annotations.length})
</button>

<!-- Drawer panel -->
<!-- Overlay drawer — below 2xl only -->
{#if open}
<aside
id="precedent-drawer-panel"
class="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto border-l border-gray-200 bg-white p-5 shadow-xl sm:w-[400px] dark:border-gray-700 dark:bg-gray-950"
class="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto border-l border-gray-200 bg-white p-5 shadow-xl sm:w-[400px] dark:border-gray-700 dark:bg-gray-950 2xl:hidden"
aria-label="Precedent annotations"
>
<div class="mb-4 flex items-center justify-between">
Expand All @@ -81,7 +86,7 @@
{court} ({cases.length})
</h3>
<ul class="space-y-3">
{#each cases as c, i}
{#each cases as c}
{@const globalIdx = annotations.indexOf(c)}
<li class="rounded border border-gray-100 p-3 dark:border-gray-700">
<a
Expand Down Expand Up @@ -113,4 +118,55 @@
{/each}
</aside>
{/if}

<!-- Persistent panel — visible at 2xl (≥1440px) as third column -->
<aside
class="hidden 2xl:block 2xl:w-80 2xl:shrink-0 2xl:overflow-y-auto 2xl:border-l 2xl:border-gray-200 2xl:bg-warm-white 2xl:p-5 dark:2xl:border-gray-800 dark:2xl:bg-[#0B1926]"
aria-label="Precedent annotations"
>
<div class="sticky top-0 bg-warm-white pb-2 dark:bg-[#0B1926]">
<h2 class="text-base font-bold text-navy dark:text-amber">
Precedent <code class="text-xs font-mono text-slate dark:text-gray-400">§{sectionId}</code>
</h2>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
{annotations.length} annotation{annotations.length !== 1 ? 's' : ''}
</p>
</div>

{#each [...grouped()] as [court, cases]}
<h3 class="mt-4 mb-2 text-xs font-bold uppercase tracking-wide {COURT_COLORS[court]}">
{court} ({cases.length})
</h3>
<ul class="space-y-3">
{#each cases as c}
{@const globalIdx = annotations.indexOf(c)}
<li class="rounded border border-gray-100 p-3 dark:border-gray-700">
<a
href={c.sourceUrl}
target="_blank"
rel="noopener noreferrer"
class="text-sm font-medium text-teal underline-offset-2 hover:underline dark:text-teal-bright"
>{c.caseName}</a>
<div class="mt-1 flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400">
<span>{c.citation} · {c.court} · {c.date}</span>
<span class="inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium {IMPACT_COLORS[c.impact]}">
{c.impact}
</span>
</div>
<p class="mt-1 text-xs leading-relaxed text-gray-600 dark:text-gray-300"
class:line-clamp-2={!expandedHoldings.has(globalIdx)}
>
{c.holdingSummary}
</p>
{#if c.holdingSummary.length > 120}
<button
onclick={() => toggleHolding(globalIdx)}
class="mt-1 text-xs text-teal hover:underline dark:text-teal-bright"
>{expandedHoldings.has(globalIdx) ? 'show less' : 'show more'}</button>
{/if}
</li>
{/each}
</ul>
{/each}
</aside>
{/if}
10 changes: 5 additions & 5 deletions apps/web/src/layouts/BaseLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ const titleEntries = Object.entries(TITLE_NAMES)
Skip to content
</a>
<div class="flex h-full flex-col lg:flex-row">
<!-- Sidebar -->
<aside class="w-full border-b border-gray-200 bg-warm-gray font-sans lg:w-64 lg:flex-shrink-0 lg:border-b-0 lg:border-r dark:border-gray-800 dark:bg-[#0B1926] lg:flex lg:flex-col lg:h-full">
<!-- Sidebar — nav column -->
<aside class="w-full border-b border-gray-200 bg-warm-gray font-sans lg:w-64 lg:flex-shrink-0 lg:border-b-0 lg:border-r dark:border-gray-800 dark:bg-[#0B1926] lg:flex lg:flex-col lg:h-full 2xl:w-60">
<div class="flex items-center justify-between p-4 lg:flex-col lg:items-start lg:gap-4">
<a href={base} class="text-lg font-bold text-navy dark:text-amber">
US Code Tracker
Expand Down Expand Up @@ -118,9 +118,9 @@ const titleEntries = Object.entries(TITLE_NAMES)
</nav>
</aside>

<!-- Main content -->
<main id="main-content" class="min-h-0 flex-1 overflow-y-auto">
<article class="prose prose-lg prose-gray mx-auto max-w-3xl p-6 font-serif leading-relaxed dark:prose-invert lg:p-10">
<!-- Main content — becomes flex at 2xl for 3-column precedent panel -->
<main id="main-content" class="min-h-0 flex-1 overflow-y-auto 2xl:flex 2xl:flex-row">
<article class="prose prose-lg prose-gray mx-auto max-w-3xl p-6 font-serif leading-relaxed dark:prose-invert lg:p-10 2xl:mx-0 2xl:flex-1 2xl:min-w-0">
<slot />
</article>

Expand Down
4 changes: 4 additions & 0 deletions apps/web/src/pages/statute/[...slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { getCollection, getEntry, render } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';
import DiffViewer from '../../components/DiffViewer.svelte';
import PrecedentDrawer from '../../components/PrecedentDrawer.svelte';
import Breadcrumbs from '../../components/Breadcrumbs.astro';
import ArticleToc from '../../components/ArticleToc.svelte';

Expand Down Expand Up @@ -490,4 +491,7 @@ const readingTimeMin = Math.max(1, Math.round(wordCount / 200));
<kbd class="ml-2 rounded border border-gray-200 bg-gray-50 px-1.5 py-0.5 font-mono text-[10px] dark:border-gray-700 dark:bg-gray-800">/</kbd>
search
</div>

<!-- Precedent drawer: persistent 3rd column at 2xl, overlay below -->
<PrecedentDrawer client:idle sectionId={usc_section} annotations={precedentCases} />
</BaseLayout>
Loading