The analysis-and-research.md content has markdown tables (ציר דיוני) and inline formatting like **label:** strong runs, which were rendering as raw pipes and dashes because the compose page used whitespace-pre-line on plain text. Add a reusable <Markdown> component backed by react-markdown + remark-gfm with a custom `components` map that styles paragraphs, lists, blockquotes, strong runs, and especially GFM tables for RTL + aligned columns: - table: table-auto + border-collapse, wrapped in overflow-x-auto so very wide tables don't push the parent card out - th: whitespace-nowrap so the header row sets column widths and every row border lines up row-to-row - everything text-right + the whole block gets dir="rtl" at the root Use it in three places on the compose screen: - ProseSection (represented_party, procedural_background, agreed_facts, disputed_facts) - Conclusions card - SubsectionCard field content — threshold_claims and issues have the same markdown shape in their fields[] react-markdown + remark-gfm added (~30KB gzipped). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
109 lines
3.5 KiB
TypeScript
109 lines
3.5 KiB
TypeScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
import { ChevronDown } from "lucide-react";
|
||
import { ChairEditor } from "@/components/compose/chair-editor";
|
||
import { PrecedentsSection } from "@/components/compose/precedents-section";
|
||
import { Markdown } from "@/components/ui/markdown";
|
||
import type { ResearchSubsection } from "@/lib/api/research";
|
||
import type { CasePrecedent } from "@/lib/api/precedents";
|
||
import type { PracticeArea } from "@/lib/practice-area";
|
||
|
||
export function SubsectionCard({
|
||
caseNumber,
|
||
item,
|
||
defaultOpen = false,
|
||
precedents = [],
|
||
practiceArea,
|
||
}: {
|
||
caseNumber: string;
|
||
item: ResearchSubsection;
|
||
defaultOpen?: boolean;
|
||
precedents?: CasePrecedent[];
|
||
practiceArea?: PracticeArea | null;
|
||
}) {
|
||
const [open, setOpen] = useState(defaultOpen);
|
||
const isFilled = Boolean(item.chair_position?.trim());
|
||
|
||
return (
|
||
<article className="rounded-lg border border-rule bg-surface shadow-sm overflow-hidden">
|
||
<button
|
||
type="button"
|
||
onClick={() => setOpen((o) => !o)}
|
||
className="
|
||
w-full flex items-center gap-3 px-4 py-3 text-right
|
||
hover:bg-gold-wash/30 transition-colors
|
||
focus:outline-none focus-visible:bg-gold-wash/40
|
||
"
|
||
aria-expanded={open}
|
||
>
|
||
<span
|
||
className="
|
||
inline-flex items-center justify-center shrink-0
|
||
w-7 h-7 rounded-full
|
||
bg-navy text-parchment font-display font-bold text-sm
|
||
tabular-nums
|
||
"
|
||
>
|
||
{item.number}
|
||
</span>
|
||
<span className="flex-1 text-navy font-semibold text-base leading-snug">
|
||
{item.title}
|
||
</span>
|
||
<span
|
||
className={`
|
||
text-[0.72rem] rounded-full px-2.5 py-0.5 border shrink-0
|
||
${
|
||
isFilled
|
||
? "bg-success-bg text-success border-success/40"
|
||
: "bg-rule-soft text-ink-muted border-rule"
|
||
}
|
||
`}
|
||
>
|
||
{isFilled ? "✓ עמדה נקבעה" : "ממתין לעמדה"}
|
||
</span>
|
||
<ChevronDown
|
||
className={`w-4 h-4 text-ink-muted transition-transform ${open ? "rotate-180" : ""}`}
|
||
aria-hidden
|
||
/>
|
||
</button>
|
||
|
||
{open && (
|
||
<div className="border-t border-rule px-5 py-4 space-y-4 bg-parchment/40">
|
||
{item.fields.length > 0 && (
|
||
<dl className="space-y-3">
|
||
{item.fields.map((f, i) => (
|
||
<div key={i}>
|
||
<dt className="text-[0.72rem] uppercase tracking-wider text-gold-deep font-semibold mb-1">
|
||
{f.label}
|
||
</dt>
|
||
<dd>
|
||
<Markdown content={f.content} />
|
||
</dd>
|
||
</div>
|
||
))}
|
||
</dl>
|
||
)}
|
||
<ChairEditor
|
||
caseNumber={caseNumber}
|
||
sectionId={item.id}
|
||
initialValue={item.chair_position ?? ""}
|
||
/>
|
||
<div className="border-t border-rule pt-4 mt-2">
|
||
<h4 className="text-[0.78rem] uppercase tracking-wider text-gold-deep font-semibold mb-2">
|
||
פסיקה תומכת
|
||
</h4>
|
||
<PrecedentsSection
|
||
caseNumber={caseNumber}
|
||
sectionId={item.id}
|
||
precedents={precedents}
|
||
practiceArea={practiceArea}
|
||
emptyHelperText="עדיין לא צורפה פסיקה לסעיף זה"
|
||
/>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</article>
|
||
);
|
||
}
|