URL Field
Responsive URL editor with centralized prefix splitting and mobile context.
Use the URL field composition for editable usernames, slugs, team URLs, and similar values whose static prefix can vary by environment or tenant.
import { UrlFieldLabelRow, UrlInputWithAddon } from "@coss/ui/shared/url-field";
import { getUrlFieldAddonParts } from "@coss/ui/shared/url-field-addon-parts";getUrlFieldAddonParts decides which static URL text belongs in the addon and, for long domains, which
domain text moves beside the label. UrlInputWithAddon then:
- hides the addon below
sm; - restores normal input padding on mobile;
- renders the complete current URL in
UrlFieldDescription; - keeps separators adjacent to the truncatable addon text;
- falls back to a plain
InputGroupwhen there is no addon.
Do not copy this behavior into call sites. Read the Input addons and URL fields guide and choose one of the policies below.
Profile policy: keep the full prefix
Profile and username fields keep the full static prefix in the desktop addon, even when it is long.
Pass splitLongDomain: false.
acme-enterprise.cal.com/team/customer-success
const urlParts = getUrlFieldAddonParts(domain, "team", {
splitLongDomain: false,
});
<Field>
<FieldLabel>{t("team_url")}</FieldLabel>
<UrlInputWithAddon
addonText={urlParts.addonText}
fullStaticText={urlParts.fullPrefixDisplay}
value={slug}
>
<InputGroupInput value={slug} onChange={onChange} />
</UrlInputWithAddon>
</Field>Conventional URL policy: split long domains
Create, duplicate, and setup flows use the default helper policy. Domains with at least
URL_PREFIX_SPLIT_MIN_LENGTH characters are shown beside the label; the path remains in the desktop
addon. Short domains remain together in the addon.
acme-enterprise.cal.com/team/customer-success/15min
const urlParts = getUrlFieldAddonParts(domain, "team/customer-success");
<Field>
<UrlFieldLabelRow domainDisplay={urlParts.domainDisplay}>
<FieldLabel>{t("url")}</FieldLabel>
</UrlFieldLabelRow>
<UrlInputWithAddon
addonText={urlParts.addonText}
fullStaticText={urlParts.fullPrefixDisplay}
value={slug}
>
<InputGroupInput value={slug} onChange={onChange} />
</UrlInputWithAddon>
</Field>UrlFieldLabelRow marks the split domain as decorative, truncates it, adds the full value as title,
and hides it on mobile. Keep the actual FieldLabel as the control's accessible name.
Separators and placement
The default composition is static/value. Separators are explicit so punctuation is not coupled to URL
paths:
| Result | Props |
|---|---|
cal.com/team/acme | default separator="/", align="before" |
acme.cal.com | separator=".", align="after" |
Pass fullStaticText without the separator. The component uses the same separator and placement for the
desktop addon and the complete mobile preview.
Use plain InputWithAddonText when a suffix such as .cal.com
is fixed, bounded, and should stay visible on mobile. Use UrlInputWithAddon when the complete mobile URL
preview is required.
Props
UrlInputWithAddon
| Prop | Default | Notes |
|---|---|---|
addonText | — | Static desktop addon; null renders a plain InputGroup |
fullStaticText | — | Complete static portion, without the separator |
value | — | Current editable portion used in the mobile preview |
separator | "/" | Join character such as / or . |
align | "before" | Static text before or after the editable value |
endAddon | — | Optional trailing control or status |
showDescription | true | Set false only when layout requires placing UrlFieldDescription outside |
textProps / className | — | Pass-through |
UrlFieldLabelRow
| Prop | Notes |
|---|---|
domainDisplay | Domain returned by getUrlFieldAddonParts; omitted when no split is needed |
children | The real FieldLabel and any label-owned controls |
domainClassName / className | Layout overrides for exceptional existing surfaces |
Call sites
| File | Policy |
|---|---|
apps/web/modules/event-types/components/create-event-type-form.tsx | Split long domain |
packages/features/eventtypes/components/tabs/setup/EventSetupTab.tsx | Split long domain |
apps/web/modules/ee/teams/views/components/team-profile-form-card.tsx | Keep full profile prefix |
apps/web/components/ui/UsernameAvailability/UsernameTextfield.tsx | Keep full username prefix |
apps/web/modules/settings/admin/impersonation-view.tsx | Description placed outside a grouped layout |
Example URLs
Not exhaustive — open these locally from http://localhost:3000.
| Path | Notes |
|---|---|
/event-types | Create / duplicate URL field |
/event-types/<eventTypeId>?tabName=setup | Event setup URL |
/settings/teams/<teamId>/profile | Team profile URL |