fix: ux audit changes (#26875)

* fix: ux audit changes

* fix: remove locale-insensitive toLowerCase() on translation

Remove .toLowerCase() call on t('minutes') translation as it is
locale-insensitive and can corrupt translations (e.g., Turkish
dotted/dotless 'i'). The translation itself should provide the
desired casing.

Addresses Cubic AI review feedback with confidence 9/10.

Co-Authored-By: unknown <>

* fix: redirect url tool tip not working

* fix: type check

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Amit Sharma
2026-02-05 13:37:59 -03:00
committed by GitHub
co-authored by unknown Devin AI
parent b0835e8ae3
commit 7226f1e4c0
15 changed files with 92 additions and 82 deletions
@@ -159,8 +159,8 @@ export default function RoutingForms({ appUrl }: { appUrl: string }) {
subtitle={t("routing_forms_description")}>
<UpgradeTip
plan="team"
title={t("teams_plan_required")}
description={t("routing_forms_are_a_great_way")}
title={t("routing_that_grows_with_you")}
description={t("routing_forms_upgrade_description")}
features={features}
background="/tips/routing-forms"
isParentLoading={<SkeletonLoaderTeamList />}
@@ -168,7 +168,7 @@ export default function RoutingForms({ appUrl }: { appUrl: string }) {
<div className="stack-y-2 rtl:space-x-reverse sm:space-x-2">
<ButtonGroup>
<Button color="primary" href={`${WEBAPP_URL}/settings/teams/new`}>
{t("upgrade")}
{t("get_started")}
</Button>
<Button color="minimal" href="https://cal.com/routing" target="_blank">
{t("learn_more")}
@@ -169,8 +169,8 @@ export function CalendarListContainer({
})}
description={t(`no_category_apps_description_calendar`)}
buttonRaw={
<Button color="secondary" data-testid="connect-calendar-apps" href="/apps/categories/calendar">
{t(`connect_calendar_apps`)}
<Button EndIcon="external-link" color="secondary" data-testid="connect-calendar-apps" href="/apps/categories/calendar">
{t("connect_your_first_calendar")}
</Button>
}
/>
@@ -173,10 +173,7 @@ export const FormActionsDropdown = ({
type="button"
variant="icon"
color="secondary"
className={classNames(
disabled && "opacity-30",
"ltr:radix-state-open:rounded-r-(--btn-group-radius) rtl:radix-state-open:rounded-l-(--btn-group-radius)"
)}
className={classNames(disabled && "opacity-30")}
StartIcon="ellipsis"
/>
</DropdownMenuTrigger>
@@ -173,7 +173,8 @@ export function DataTable<TData>({
width: `var(--header-${kebabCase(header?.id)}-size)`,
}}
className={classNames(
"relative flex shrink-0 items-center",
"relative flex items-center",
column.columnDef.meta?.autoWidth ? "grow" : "shrink-0",
"bg-cal-muted",
column.getIsPinned() && "top-0 z-20 sm:sticky"
)}>
@@ -143,7 +143,7 @@ export const AddActionDialog = (props: IAddActionDialog) => {
return (
<Dialog open={isOpenDialog} onOpenChange={setIsOpenDialog}>
<DialogContent type="creation" title={t("add_action")}>
<div className="-mt-3 space-x-3">
<div className="space-x-3">
<Form
form={form}
handleSubmit={(values) => {
@@ -168,7 +168,7 @@ export function WorkflowCreationDialog({
type="button"
onClick={handleContinue}
loading={createMutation.isPending || isLoading}>
{t("continue")}
{t("create")}
</Button>
</DialogFooter>
</DialogContent>
@@ -135,7 +135,7 @@ function EventTypeSingleLayout({
formMethods.watch("hidden") ? t("show_eventtype_on_profile") : t("hide_from_profile")
}
side="bottom">
<div className="self-center rounded-md p-2">
<div className="self-center rounded-md">
<Switch
id="hiddenSwitch"
disabled={eventTypesLockedByOrg}
@@ -15,6 +15,7 @@ import { Tooltip } from "@calcom/ui/components/tooltip";
import { UpgradeTeamsBadgeWebWrapper as UpgradeTeamsBadge } from "@calcom/web/modules/billing/components/UpgradeTeamsBadgeWebWrapper";
import { useHasTeamPlan } from "@calcom/web/modules/billing/hooks/useHasPaidPlan";
import LocationSettingsContainer from "@calcom/web/modules/event-types/components/locations/LocationSettingsContainer";
import { InfoBadge } from "@calcom/ui/components/badge";
const CalVideoSettings = ({ calVideoSettings }: { calVideoSettings?: CalVideoSettingsType }) => {
const { t } = useLocale();
@@ -30,7 +31,7 @@ const CalVideoSettings = ({ calVideoSettings }: { calVideoSettings?: CalVideoSet
aria-expanded={isExpanded}
onClick={() => setIsExpanded(!isExpanded)}
className={classNames(
"todesktop:py-[7px] text-default group flex w-full items-center rounded-md px-2 py-1.5 text-sm font-medium transition",
"cursor-pointer todesktop:py-[7px] text-default group flex w-full items-center rounded-md px-2 pt-1.5 text-sm font-medium transition",
"[&[aria-current='page']]:!bg-transparent",
"[&[aria-current='page']]:text-emphasis mt-0.5 text-sm"
)}>
@@ -169,7 +170,7 @@ const CalVideoSettings = ({ calVideoSettings }: { calVideoSettings?: CalVideoSet
/>
<TextField
label={t("enter_redirect_url_on_exit_description")}
label={<div className="flex gap-1 items-center">{t("redirect_url")}<InfoBadge content={t("enter_redirect_url_on_exit_description")} /></div>}
defaultValue={calVideoSettings?.redirectUrlOnExit || ""}
data-testid="calVideoSettings.redirectUrlOnExit"
containerClassName="mt-4"
@@ -24,6 +24,7 @@ import { showToast } from "@calcom/ui/components/toast";
import { revalidateTravelSchedules } from "@calcom/web/app/cache/travelSchedule";
import TravelScheduleModal from "@components/settings/TravelScheduleModal";
import { Icon } from "@calcom/ui/components/icon";
export type FormValues = {
locale: {
@@ -317,6 +318,7 @@ const GeneralView = ({ user, travelSchedules }: GeneralViewProps) => {
)}
/>
<div className="text-gray text-subtle mt-2 flex items-center text-xs">
<Icon name="info" className="mr-2" />
{t("timeformat_profile_hint")}
</div>
<Controller
+9 -9
View File
@@ -400,7 +400,7 @@ export default function Signup({
</p>
)}
{IS_CALCOM && (
<div className="mt-4">
<div className="mt-12">
<SelectField
label={t("data_region")}
value={{
@@ -453,7 +453,7 @@ export default function Signup({
{/* Form Container */}
{displayEmailForm && (
<div className="mt-12">
<div className="mt-6">
<Form
className="flex flex-col gap-4"
form={formMethods}
@@ -614,10 +614,10 @@ export default function Signup({
</div>
)}
{!displayEmailForm && (
<div className="mt-12">
<div className="mt-8 flex flex-col gap-6">
{/* Upper Row */}
<div className="mt-6 flex flex-col gap-2 md:flex-row">
{isGoogleLoginEnabled ? (
{isGoogleLoginEnabled && (
<div className="flex flex-col gap-2 md:flex-row">
<Button
color="primary"
loading={isGoogleLoading}
@@ -664,11 +664,11 @@ export default function Signup({
}}>
{t("continue_with_google")}
</Button>
) : null}
</div>
</div>
)}
{isGoogleLoginEnabled && (
<div className="mt-6">
<div>
<div className="relative flex items-center">
<div className="border-subtle grow border-t" />
<span className="text-subtle mx-2 shrink text-sm font-normal leading-none">
@@ -680,7 +680,7 @@ export default function Signup({
)}
{/* Lower Row */}
<div className="mt-6 flex flex-col gap-2">
<div className="flex flex-col gap-2">
<Button
color="secondary"
disabled={isGoogleLoading}
@@ -195,7 +195,7 @@ export function AvailabilityEditSheetForm(props: Props & { data: Data; isPending
</div>
)}
<SheetBody className="mt-4 flex flex-col stack-y-4">
<SheetBody className="mt-4 flex flex-col stack-y-8">
<div>
<Label className="text-emphasis">
<>{t("timezone")}</>
@@ -234,13 +234,13 @@ export function AvailabilityEditSheetForm(props: Props & { data: Data; isPending
</SheetBody>
<SheetFooter>
<SheetClose asChild>
<Button color="secondary" className="w-full justify-center">
<Button color="secondary" className="justify-center">
{t("cancel")}
</Button>
</SheetClose>
<Button
disabled={!hasEditPermission || !data.hasDefaultSchedule}
className="w-full justify-center"
className="justify-center"
type="submit"
loading={updateMutation.isPending}
form="availability-form">
@@ -23,7 +23,7 @@ export function EventScheduleItem() {
return (
<div>
<Label>Availability Schedule</Label>
<Label>{t("availability_schedule")}</Label>
<TroubleshooterListItemHeader
className="group rounded-md border-b"
prefixSlot={<div className="w-4 rounded-[4px] bg-black" />}
@@ -192,7 +192,7 @@ export function EditForm({
<SheetHeader>
<SheetTitle>{t("update_profile")}</SheetTitle>
</SheetHeader>
<SheetBody className="bg-cal-muted border-subtle mt-6 gap-4 rounded-xl border p-4">
<SheetBody className="bg-cal-muted border-subtle mt-6 gap-4 rounded-xl border p-4 stack-y-6">
<div className="">
<Controller
control={form.control}
@@ -217,40 +217,43 @@ export function EditForm({
/>
</div>
<Divider />
<TextField label={t("name")} {...form.register("name")} className="mb-6" />
<TextField label={t("username")} {...form.register("username")} className="mb-6" />
<TextAreaField label={t("about")} {...form.register("bio")} className="min-h-24 mb-6" />
<div className="mb-6">
<Label>{t("role")}</Label>
{teamRoles?.length > 0 ? (
<SelectField
defaultValue={membershipOptions.find(
(option) => option.value === (selectedUser?.role ?? "MEMBER")
)}
value={membershipOptions.find((option) => option.value === form.watch("role"))}
options={membershipOptions}
onChange={(option) => {
if (option) {
form.setValue("role", option.value);
}
}}
/>
) : (
<ToggleGroup
isFullWidth
defaultValue={selectedUser?.role ?? "MEMBER"}
value={form.watch("role")}
options={membershipOptions}
onValueChange={(value) => {
form.setValue("role", value);
}}
/>
)}
</div>
<div className="mb-6">
<Label>{t("timezone")}</Label>
<TimezoneSelect value={watchTimezone ?? "America/Los_Angeles"} />
<div className="stack-y-3">
<TextField label={t("name")} {...form.register("name")} />
<TextField label={t("username")} {...form.register("username")} />
<TextAreaField label={t("about")} {...form.register("bio")} />
<div>
<Label>{t("role")}</Label>
{teamRoles?.length > 0 ? (
<SelectField
defaultValue={membershipOptions.find(
(option) => option.value === (selectedUser?.role ?? "MEMBER")
)}
value={membershipOptions.find((option) => option.value === form.watch("role"))}
options={membershipOptions}
onChange={(option) => {
if (option) {
form.setValue("role", option.value);
}
}}
/>
) : (
<ToggleGroup
isFullWidth
defaultValue={selectedUser?.role ?? "MEMBER"}
value={form.watch("role")}
options={membershipOptions}
onValueChange={(value) => {
form.setValue("role", value);
}}
/>
)}
</div>
<div>
<Label>{t("timezone")}</Label>
<TimezoneSelect value={watchTimezone ?? "America/Los_Angeles"} />
</div>
</div>
{canEditAttributesForUser && (
<>
<Divider />
@@ -262,14 +265,14 @@ export function EditForm({
<Button
color="secondary"
type="button"
className="justify-center md:w-1/5"
className="justify-center"
onClick={() => {
setEditMode(false);
}}>
{t("cancel")}
</Button>
<Button type="submit" className="w-full justify-center">
<Button type="submit" className="justify-center">
{t("update")}
</Button>
</SheetFooter>
@@ -299,9 +302,9 @@ function AttributesList(props: { selectedUserId: number }) {
const attribute = attributes?.find((attr) => attr.id === attributeId);
return attribute
? attribute.options.map((option) => ({
value: option.id,
label: option.value,
}))
value: option.id,
label: option.value,
}))
: [];
};
@@ -403,17 +406,17 @@ function AttributesList(props: { selectedUserId: number }) {
const updatedOptions =
attr.type === "MULTI_SELECT"
? valueAsArray.map((v) => ({
label: v.label,
value: v.value,
weight: v.weight || 100,
}))
label: v.label,
value: v.value,
weight: v.weight || 100,
}))
: [
{
label: valueAsArray[0].label,
value: valueAsArray[0].value,
weight: valueAsArray[0].weight || 100,
},
];
{
label: valueAsArray[0].label,
value: valueAsArray[0].value,
weight: valueAsArray[0].weight || 100,
},
];
field.onChange({
id: attr.id,
+10 -4
View File
@@ -1296,7 +1296,7 @@
"apps_description": "Here you can find a list of your apps",
"apps_listing": "App listing",
"category_apps": "{{category}} apps",
"app_store": "App Store",
"app_store": "App store",
"app_store_description": "Connecting people, technology and the workplace.",
"connect_your_video": "Connect your video conferencing app",
"settings": "Settings",
@@ -1850,6 +1850,7 @@
"apply_to_all_teams": "Apply to all team and user event types",
"which_team_apply": "Which team will this apply to?",
"no_workflows_description": "Workflows enable simple automation to send notifications & reminders enabling you to build processes around your events.",
"no_workflows_description_v2": "Automate event reminders and notifications",
"timeformat_profile_hint": "This is an internal setting and will not affect how times are displayed on public booking pages for you or anyone booking you.",
"create_workflow": "Create a workflow",
"do_this": "Do this",
@@ -2050,8 +2051,8 @@
"exchange_version_2015": "2015",
"exchange_version_2016": "2016",
"routing": "Routing",
"routing_forms_description": "Create forms to direct attendees to the correct destinations",
"routing_forms_send_email_owner": "Send Email to Owner",
"routing_forms_description": "Create forms to direct attendees to the correct hosts",
"routing_forms_send_email_owner": "Send email to owner",
"routing_forms_send_email_owner_description": "Sends an email to the owner when the form is submitted",
"routing_forms_send_email_to": "Send Email to",
"add_new_form": "Add new form",
@@ -2469,6 +2470,7 @@
"no_entries_description": "Add an email/domain to get started.",
"duplicate_email": "Email is duplicate",
"enter_redirect_url_on_exit_description": "Enter a redirect URL to which the attendee will be sent once they leave the meeting.",
"redirect_url": "Redirect URL",
"booking_with_payment_cancelled": "Paying for this event is no longer possible",
"booking_with_payment_cancelled_already_paid": "A refund for this booking payment is on its way.",
"booking_with_payment_cancelled_refunded": "This booking payment has been refunded.",
@@ -3130,7 +3132,7 @@
"organization_price_per_user_month": "$37 per user per month",
"privacy_organization_description": "Manage privacy settings for your organization",
"privacy": "Privacy",
"privacy_and_security": "Privacy & Security",
"privacy_and_security": "Privacy & security",
"team_will_be_under_org": "New teams will be under your organization",
"add_group_name": "Add group name",
"group_name": "Group name",
@@ -4533,6 +4535,10 @@
"enabled_via_auto_opt_in": "Enabled via auto opt-in",
"account_already_exists_please_login": "An account with this email already exists. Please log in to accept the invitation.",
"unverified_email_oauth_error": "Please verify your email address before signing in with Google or SAML. Sign in with your password to resend the verification email.",
"availability_schedule": "Availability schedule",
"connect_your_first_calendar": "Connect your first calendar",
"routing_that_grows_with_you": "Routing that grows with you",
"routing_forms_upgrade_description": "Create simple forms that guide bookings to the right person, team, or event. Start solo, then seamlessly route meetings as more people or use cases come into play. Available on the Teams plan.",
"pbac_resource_feature_opt_in": "Feature Opt-In",
"pbac_desc_view_feature_opt_in": "View feature opt-in settings",
"pbac_desc_update_feature_opt_in": "Manage feature opt-in settings",
@@ -305,7 +305,7 @@ export const MultiOptionInput = <TFieldValues extends FieldValues>({
color={addOptionButtonColor}
StartIcon="plus"
onClick={addOption}
className="mt-4 border-none"
className="border-none"
disabled={disabled}>
{addOptionLabel}
</Button>