fix(web): wrap long record values in diff and zone view (no horizontal overflow)
RecordRow now splits into a top line (badge/name/read-only, unaffected by value length) and a plain block-level values line below it, so a ~400-char unbreakable DKIM key wraps via break-all instead of stretching the flex row and forcing page-wide horizontal scroll. Zone records table gets break-all on the values cell too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BwxdSt4reTm7Dj1oxRvpP3
This commit is contained in:
@@ -27,6 +27,30 @@ test("marks read-only records", () => {
|
|||||||
expect(screen.getByText(/NS/)).toBeInTheDocument()
|
expect(screen.getByText(/NS/)).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("renders a very long unbreakable value (DKIM key) without crashing", () => {
|
||||||
|
// Real DKIM records ship a ~400-char unbroken p= blob. This must not
|
||||||
|
// throw and the value must land in the DOM (wrapping itself is a CSS
|
||||||
|
// concern verified manually, not via jsdom layout).
|
||||||
|
const longValue = "v=DKIM1; k=rsa; p=" + "A".repeat(400)
|
||||||
|
const csWithDkim: ChangesetResponse = {
|
||||||
|
updates: [
|
||||||
|
{
|
||||||
|
kind: "update",
|
||||||
|
type: "TXT",
|
||||||
|
name: "default._domainkey.example.com.",
|
||||||
|
desired: [longValue],
|
||||||
|
actual: [],
|
||||||
|
readOnly: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
prunes: [],
|
||||||
|
readOnly: [],
|
||||||
|
inSyncCount: 0,
|
||||||
|
}
|
||||||
|
render(<DiffView changeset={csWithDkim} />)
|
||||||
|
expect(screen.getByText(new RegExp(longValue))).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
test("does not crash when changeset fields are null", () => {
|
test("does not crash when changeset fields are null", () => {
|
||||||
// An empty changeset from an older/edge backend can arrive with null slices
|
// An empty changeset from an older/edge backend can arrive with null slices
|
||||||
// instead of []. DiffView must normalise them, not blow up on .length/.map.
|
// instead of []. DiffView must normalise them, not blow up on .length/.map.
|
||||||
|
|||||||
@@ -47,43 +47,56 @@ function RecordRow({ record, tone }: { record: RecordView; tone: Tone }) {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"group/row flex items-center gap-3 border-l-2 px-3 py-2.5 transition-colors",
|
"group/row flex flex-col gap-1.5 border-l-2 px-3 py-2.5 transition-colors",
|
||||||
"hover:bg-foreground/[0.025]",
|
"hover:bg-foreground/[0.025]",
|
||||||
)}
|
)}
|
||||||
style={{ borderLeftColor: meta.dot }}
|
style={{ borderLeftColor: meta.dot }}
|
||||||
>
|
>
|
||||||
<Badge
|
{/* Top line: type badge, name, read-only flag — always single-line,
|
||||||
variant="outline"
|
never affected by how long the record values are. */}
|
||||||
className="font-dns w-11 shrink-0 justify-center border-border text-[10px] tracking-wide text-muted-foreground"
|
<div className="flex items-center gap-3">
|
||||||
>
|
<Badge
|
||||||
{record.type}
|
variant="outline"
|
||||||
</Badge>
|
className="font-dns w-11 shrink-0 justify-center border-border text-[10px] tracking-wide text-muted-foreground"
|
||||||
|
>
|
||||||
|
{record.type}
|
||||||
|
</Badge>
|
||||||
|
|
||||||
<span className="font-dns min-w-0 flex-1 truncate text-sm text-foreground">
|
<span className="font-dns min-w-0 flex-1 truncate text-sm text-foreground">
|
||||||
{record.name}
|
{record.name}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span className="font-dns hidden shrink-0 items-center gap-1.5 text-xs text-muted-foreground sm:flex">
|
{record.readOnly && (
|
||||||
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
className="shrink-0 gap-1 bg-muted text-[10px] text-muted-foreground"
|
||||||
|
>
|
||||||
|
<Lock className="size-2.5" strokeWidth={2} />
|
||||||
|
read-only
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Values line: plain block-level text (not flex) so a long
|
||||||
|
unbreakable value like a DKIM key wraps within the row's own
|
||||||
|
width instead of stretching it — a flex item's content can
|
||||||
|
otherwise refuse to shrink below its intrinsic width. Indented
|
||||||
|
to align under the name (badge width + gap). */}
|
||||||
|
<div className="font-dns hidden pl-14 text-xs leading-relaxed break-all text-muted-foreground sm:block">
|
||||||
<Values values={record.actual} />
|
<Values values={record.actual} />
|
||||||
{showArrow && (
|
{showArrow && (
|
||||||
<>
|
<>
|
||||||
<ArrowRight className="size-3 text-muted-foreground/50" strokeWidth={1.75} />
|
{" "}
|
||||||
|
<ArrowRight
|
||||||
|
className="mx-1 inline-block size-3 align-[-2px] text-muted-foreground/50"
|
||||||
|
strokeWidth={1.75}
|
||||||
|
/>{" "}
|
||||||
<span style={{ color: meta.dot }}>
|
<span style={{ color: meta.dot }}>
|
||||||
<Values values={record.desired} />
|
<Values values={record.desired} />
|
||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</span>
|
</div>
|
||||||
|
|
||||||
{record.readOnly && (
|
|
||||||
<Badge
|
|
||||||
variant="secondary"
|
|
||||||
className="ml-1 shrink-0 gap-1 bg-muted text-[10px] text-muted-foreground"
|
|
||||||
>
|
|
||||||
<Lock className="size-2.5" strokeWidth={2} />
|
|
||||||
read-only
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,7 +167,9 @@ export function DomainDiffPage() {
|
|||||||
<TableCell className="font-dns">{r.type}</TableCell>
|
<TableCell className="font-dns">{r.type}</TableCell>
|
||||||
<TableCell className="font-dns">{r.name}</TableCell>
|
<TableCell className="font-dns">{r.name}</TableCell>
|
||||||
<TableCell className="font-dns">{r.ttl}</TableCell>
|
<TableCell className="font-dns">{r.ttl}</TableCell>
|
||||||
<TableCell className="font-dns whitespace-pre-line">{r.values.join("\n")}</TableCell>
|
<TableCell className="font-dns whitespace-pre-line break-all">
|
||||||
|
{r.values.join("\n")}
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
|
|||||||
Reference in New Issue
Block a user