From 406921ac6ad8b5e83f3b9767d4e9e7bb5d94a9e9 Mon Sep 17 00:00:00 2001 From: claude_code Date: Fri, 26 Jun 2026 21:05:23 +0300 Subject: [PATCH] fix(share): tighten and restyle custom-address prefix input The "Custom address" slug field sized its leftSection with a character-count heuristic (label.length * 7 + 12), which over-estimated the real width of the small dimmed domain prefix and left an ugly empty gap between "docs.../l/" and the input text. - Measure the real prefix width via a ref + useLayoutEffect (scrollWidth) and feed it to leftSectionWidth so the slug sits flush against the prefix, regardless of host length or font metrics. - Restyle the prefix as an attached addon: subtle background, a right divider border and input-matching left corner radii. - Minor spacing tidy: description mb 4->6, action buttons mt xs->sm. No behavior change: validation, availability probe, save/remove and the reassign modal are untouched. Co-Authored-By: Claude Opus 4.8 --- .../share/components/share-alias-section.tsx | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/apps/client/src/features/share/components/share-alias-section.tsx b/apps/client/src/features/share/components/share-alias-section.tsx index 870c360b..53420d79 100644 --- a/apps/client/src/features/share/components/share-alias-section.tsx +++ b/apps/client/src/features/share/components/share-alias-section.tsx @@ -1,5 +1,6 @@ import { ActionIcon, + Box, Button, Group, Modal, @@ -7,7 +8,7 @@ import { TextInput, } from "@mantine/core"; import { IconExternalLink } from "@tabler/icons-react"; -import { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import CopyTextButton from "@/components/common/copy.tsx"; import { getAppUrl } from "@/lib/config.ts"; @@ -122,12 +123,25 @@ export default function ShareAliasSection({ const showTaken = isValid && !unchanged && availability && !availability.available; + // The slug prefix (e.g. "docs.example.com/l/") is static for the session. + const prefixLabel = aliasPrefixLabel(); + const prefixRef = useRef(null); + const [prefixWidth, setPrefixWidth] = useState(0); + + // Measure the real rendered width of the prefix so the slug input sits flush + // next to it, instead of after an over-estimated character-counted gap. + useLayoutEffect(() => { + if (prefixRef.current) { + setPrefixWidth(Math.ceil(prefixRef.current.scrollWidth) + 1); + } + }, [prefixLabel]); + return ( <> {t("Custom address")} - + {t("A short, memorable link you can point at any shared page.")} @@ -159,11 +173,27 @@ export default function ShareAliasSection({ // visibly to what gets stored. onBlur={() => setValue(normalized)} leftSection={ - - {aliasPrefixLabel()} - + + {prefixLabel} + } - leftSectionWidth={Math.min(aliasPrefixLabel().length * 7 + 12, 180)} + leftSectionWidth={prefixWidth || undefined} placeholder={t("my-page")} disabled={readOnly} error={ @@ -175,7 +205,7 @@ export default function ShareAliasSection({ } /> - +