fix(web): stop long tokens and button rows overflowing on mobile
Server Deploy / deploy (push) Successful in 1m40s
Server Deploy / deploy (push) Successful in 1m40s
Three root causes behind five reported overflows: - Td below sm is a flex row, and a flex item's default min-width:auto is its min-content width. A fingerprint or target URL is one unbreakable token, so the value could not shrink and spilled out of the card. The value now sits in a min-w-0 break-words wrapper that is display:contents above sm, leaving the desktop table untouched. Fixes /keys, /monitors and the installed-keys table on /servers/[id] in one place. - The ESO read URL and the secrets group endpoint are unbreakable tokens in prose with the default overflow-wrap:normal. Both paragraphs now break-words. - Three page headers (servers/[id], keys/[id], monitors/[id]) held an unwrapped button row. They stack below sm and the clusters wrap. These used items-start, which is why the earlier responsive sweep — matching items-center — skipped all three; only one was reported. Verified: tsc clean, next build clean, and the compiled stylesheet confirms max-sm:min-w-0 / max-sm:break-words land in the below-640px query and sm:contents in the above-640px one.
This commit is contained in:
@@ -248,20 +248,22 @@ export default function KeyDetailPage() {
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="mb-6 flex items-start justify-between">
|
||||
<div>
|
||||
<div className="mb-6 flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div className="min-w-0">
|
||||
<Link href="/keys" className="text-text-secondary hover:text-text-primary text-sm">
|
||||
← SSH Keys
|
||||
</Link>
|
||||
<div className="mt-2 flex items-center gap-3">
|
||||
<div className="mt-2 flex flex-wrap items-center gap-3">
|
||||
<h1 className="text-2xl font-bold text-text-primary">{key.label}</h1>
|
||||
<Badge variant={key.source === "generated" ? "accent" : "neutral"}>
|
||||
{key.source}
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-xs text-text-secondary">{key.fingerprint}</p>
|
||||
{/* A fingerprint is one unbreakable token; without break-all it
|
||||
overflows the column rather than wrapping. */}
|
||||
<p className="mt-1 break-all font-mono text-xs text-text-secondary">{key.fingerprint}</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button variant="secondary" onClick={() => setShowAssign(true)}>
|
||||
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||
|
||||
@@ -97,12 +97,12 @@ export default function MonitorDetailPage() {
|
||||
|
||||
return (
|
||||
<div className="p-4 sm:p-6 lg:p-8">
|
||||
<div className="mb-6 flex items-start justify-between">
|
||||
<div>
|
||||
<div className="mb-6 flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div className="min-w-0">
|
||||
<Link href="/monitors" className="text-sm text-text-secondary hover:text-text-primary">
|
||||
← Monitors
|
||||
</Link>
|
||||
<div className="mt-2 flex items-center gap-3">
|
||||
<div className="mt-2 flex flex-wrap items-center gap-3">
|
||||
<h1 className="text-2xl font-bold text-text-primary">{monitor.name}</h1>
|
||||
<Badge variant={statusVariant(monitor.state.status)}>{monitor.state.status}</Badge>
|
||||
<Badge variant="neutral">{monitor.type}</Badge>
|
||||
@@ -110,7 +110,7 @@ export default function MonitorDetailPage() {
|
||||
</div>
|
||||
{monitor.state.message && <p className="mt-1 text-sm text-text-secondary">{monitor.state.message}</p>}
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Link href={`/monitors/${monitorId}/edit`}>
|
||||
<Button variant="secondary">Edit</Button>
|
||||
</Link>
|
||||
|
||||
@@ -249,13 +249,13 @@ export default function SecretGroupPage() {
|
||||
</Link>
|
||||
|
||||
<div className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div>
|
||||
<h1 className="font-mono text-2xl font-bold text-text-primary">{group}</h1>
|
||||
<p className="mt-1 text-sm text-text-secondary">
|
||||
<div className="min-w-0">
|
||||
<h1 className="break-all font-mono text-2xl font-bold text-text-primary">{group}</h1>
|
||||
<p className="mt-1 break-words text-sm text-text-secondary">
|
||||
ESO reads this group at <span className="font-mono">GET /api/secrets/{group}/values</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<Button variant="ghost" onClick={() => setShowYaml(true)}>
|
||||
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5" />
|
||||
|
||||
@@ -385,7 +385,7 @@ export default function ServerDetailPage() {
|
||||
<UpdatesModal updates={server.available_updates} onClose={() => setShowUpdatesModal(false)} onApply={() => applyUpdates()} isApplying={isApplying} applySuccess={applySuccess} />
|
||||
)}
|
||||
|
||||
<div className="mb-6 flex items-start justify-between">
|
||||
<div className="mb-6 flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Link href="/servers" className="text-text-secondary hover:text-text-primary text-sm">
|
||||
@@ -398,7 +398,7 @@ export default function ServerDetailPage() {
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-sm text-text-secondary">{server.ip_address}</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{/* Rendered disabled rather than hidden when the licence does not
|
||||
include the console: a customer cannot buy what they cannot see,
|
||||
and a feature that vanishes reads as a bug. */}
|
||||
|
||||
@@ -86,7 +86,9 @@ function SecretsTokenCard({ tokenSet, rotatedAt }: { tokenSet: boolean; rotatedA
|
||||
|
||||
return (
|
||||
<SectionCard title="Secrets read token (ESO)" description="Kubernetes External Secrets Operator authenticates to the read endpoint with this bearer token." icon={<KeyIcon />}>
|
||||
<p className="mb-4 text-sm text-text-secondary">
|
||||
{/* break-words, not the default: the read URL is one unbreakable
|
||||
token, so on a narrow card it overflows rather than wrapping. */}
|
||||
<p className="mb-4 break-words text-sm text-text-secondary">
|
||||
Point your <span className="font-mono">ClusterSecretStore</span> at <span className="font-mono text-text-primary">{readUrl}</span>.
|
||||
</p>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user