From c380ea810c3e628ed65c120ccc1cbe02ee4d4ed9 Mon Sep 17 00:00:00 2001 From: Pasquale Vitiello Date: Fri, 9 Jan 2026 11:42:23 +0100 Subject: [PATCH] feat: rename --font-cal to --font-heading + use Cal Sans UI (#26064) * feat: rename --font-cal to --font-heading + use Cal Sans UI * chore: remove font-weight from font-heading elements and CSS variables Co-Authored-By: pasquale@cal.com * chore: remove unneeded css vars * fix: cubic issues --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: pasquale@cal.com Co-authored-by: Rajiv Sahal --- .../(main-nav)/ShellMainAppDir.tsx | 2 +- .../routing-forms/[...pages]/RoutingLink.tsx | 2 +- .../availability/[schedule]/skeleton.tsx | 2 +- .../roles/_components/PbacOptInModal.tsx | 2 +- apps/web/app/icons/IconGrid.tsx | 2 +- apps/web/app/icons/page.tsx | 33 ++++-------- apps/web/app/layout.tsx | 21 +------- apps/web/app/notFoundClient.tsx | 4 +- apps/web/components/PageWrapper.tsx | 17 ------ apps/web/components/apps/AppPage.tsx | 2 +- .../apps/installation/StepHeader.tsx | 2 +- .../apps/routing-forms/FormActions.tsx | 2 +- apps/web/components/dialog/RerouteDialog.tsx | 2 +- apps/web/components/error/error-page.tsx | 2 +- .../security/DisableUserImpersonation.tsx | 2 +- .../security/TwoFactorAuthSection.tsx | 2 +- .../security/TwoFactorModalHeader.tsx | 2 +- .../dashboard/oauth-clients-list/index.tsx | 2 +- apps/web/components/setup/ChooseLicense.tsx | 4 +- .../web/components/setup/LicenseSelection.tsx | 4 +- apps/web/components/ui/AuthContainer.tsx | 2 +- .../[id]/forgot-password-single-view.tsx | 4 +- apps/web/modules/auth/verify-view.tsx | 2 +- .../BookEventForm/BookFormAsModal.tsx | 2 +- .../bookings/components/Unavailable.tsx | 2 +- .../bookings/views/bookings-single-view.tsx | 2 +- .../api-keys/components/ApiKeyDialogForm.tsx | 4 +- .../ee/dsync/components/CreateDirectory.tsx | 2 +- .../attributes/attributes-create-view.tsx | 2 +- .../attributes/attributes-edit-view.tsx | 2 +- .../attributes/attributes-list-view.tsx | 2 +- .../components/CreateANewOrganizationForm.tsx | 2 +- .../WelcomeToOrganizationsModal.tsx | 2 +- .../new/_components/PaymentStatusView.tsx | 4 +- .../ee/sso/components/OIDCConnection.tsx | 2 +- .../ee/sso/components/SAMLConnection.tsx | 2 +- .../components/MemberChangeRoleModal.tsx | 2 +- .../ee/workflows/components/EmptyScreen.tsx | 2 +- apps/web/modules/embed/components/Embed.tsx | 2 +- .../[[...step]]/onboarding-view.tsx | 2 +- .../onboarding/components/OnboardingCard.tsx | 4 +- .../onboarding-invite-browser-view.tsx | 2 +- .../organization/invite/csv-upload-modal.tsx | 2 +- .../personal/_components/OnboardingCard.tsx | 2 +- .../teams/invite/csv-upload-modal.tsx | 2 +- .../[clientId]/edit/edit-view.tsx | 2 +- .../[clientId]/edit/edit-webhooks-view.tsx | 2 +- .../oauth-clients/create-new-view.tsx | 2 +- .../settings/security/password-view.tsx | 2 +- apps/web/modules/shell/Shell.tsx | 2 +- apps/web/modules/shell/UpgradeTip.tsx | 4 +- .../shell/components/WelcomeToCalcomModal.tsx | 2 +- apps/web/modules/signup-view.tsx | 2 +- apps/web/modules/team/team-view.tsx | 4 +- .../modules/users/views/users-public-view.tsx | 2 +- .../videos-meeting-ended-single-view.tsx | 2 +- .../videos/views/videos-single-view.tsx | 2 +- apps/web/pages/_document.tsx | 3 +- .../_components/AppNotInstalledMessage.tsx | 2 +- .../giphy/components/SearchDialog.tsx | 2 +- packages/config/theme/tokens.css | 2 +- packages/coss-ui/package.json | 3 +- .../coss-ui/src}/fonts/CalSans-SemiBold.woff2 | Bin .../src/fonts/CalSansUI[MODE,wght].woff2 | Bin 0 -> 66368 bytes packages/coss-ui/src/fonts/README.md | 49 ++++++++++++++++++ packages/coss-ui/src/fonts/index.ts | 13 +++++ .../settings/appDir/SettingsHeader.tsx | 2 +- packages/platform/atoms/globals.css | 13 +++-- packages/ui/components/card/Card.tsx | 4 +- .../dialog/ConfirmationDialogContent.tsx | 2 +- packages/ui/components/dialog/Dialog.tsx | 2 +- .../components/empty-screen/EmptyScreen.tsx | 2 +- .../ui/components/form/wizard/WizardForm.tsx | 2 +- .../ui/components/layout/WizardLayout.tsx | 2 +- 74 files changed, 159 insertions(+), 141 deletions(-) rename {apps/web => packages/coss-ui/src}/fonts/CalSans-SemiBold.woff2 (100%) create mode 100644 packages/coss-ui/src/fonts/CalSansUI[MODE,wght].woff2 create mode 100644 packages/coss-ui/src/fonts/README.md create mode 100644 packages/coss-ui/src/fonts/index.ts diff --git a/apps/web/app/(use-page-wrapper)/(main-nav)/ShellMainAppDir.tsx b/apps/web/app/(use-page-wrapper)/(main-nav)/ShellMainAppDir.tsx index 8c09fb5bb5..25ff92a191 100644 --- a/apps/web/app/(use-page-wrapper)/(main-nav)/ShellMainAppDir.tsx +++ b/apps/web/app/(use-page-wrapper)/(main-nav)/ShellMainAppDir.tsx @@ -27,7 +27,7 @@ export function ShellMainAppDir(props: LayoutProps) { {props.heading && (

{props.heading} diff --git a/apps/web/app/(use-page-wrapper)/apps/routing-forms/[...pages]/RoutingLink.tsx b/apps/web/app/(use-page-wrapper)/apps/routing-forms/[...pages]/RoutingLink.tsx index 66dd20ea4b..3296ffb101 100644 --- a/apps/web/app/(use-page-wrapper)/apps/routing-forms/[...pages]/RoutingLink.tsx +++ b/apps/web/app/(use-page-wrapper)/apps/routing-forms/[...pages]/RoutingLink.tsx @@ -183,7 +183,7 @@ function RoutingForm({ form, profile, ...restProps }: Props) {
-

+

{form.name}

{form.description ? ( diff --git a/apps/web/app/(use-page-wrapper)/availability/[schedule]/skeleton.tsx b/apps/web/app/(use-page-wrapper)/availability/[schedule]/skeleton.tsx index 126be37323..5fd5aec102 100644 --- a/apps/web/app/(use-page-wrapper)/availability/[schedule]/skeleton.tsx +++ b/apps/web/app/(use-page-wrapper)/availability/[schedule]/skeleton.tsx @@ -19,7 +19,7 @@ export function AvailabilityScheduleSkeleton() { {/* Title section */}
- + {/* Title */} {/* Subtitle */}
diff --git a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/roles/_components/PbacOptInModal.tsx b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/roles/_components/PbacOptInModal.tsx index 373a9de136..42bad0b630 100644 --- a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/roles/_components/PbacOptInModal.tsx +++ b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/roles/_components/PbacOptInModal.tsx @@ -51,7 +51,7 @@ export function PbacOptInModal({ open, onOpenChange, revalidateRolesPath }: Pbac
-

{t("pbac_opt_in_title")}

+

{t("pbac_opt_in_title")}

{t("pbac_opt_in_description")}

diff --git a/apps/web/app/icons/IconGrid.tsx b/apps/web/app/icons/IconGrid.tsx index 7a3f8d896c..690ead0165 100644 --- a/apps/web/app/icons/IconGrid.tsx +++ b/apps/web/app/icons/IconGrid.tsx @@ -10,7 +10,7 @@ export const IconGrid = (props: { iconClassName?: string; }) => (
-

{props.title}

+

{props.title}

{props.icons.map((icon) => { return ( diff --git a/apps/web/app/icons/page.tsx b/apps/web/app/icons/page.tsx index b15b850488..43a9efe812 100644 --- a/apps/web/app/icons/page.tsx +++ b/apps/web/app/icons/page.tsx @@ -15,32 +15,21 @@ export async function generateMetadata(): Promise { return await _generateMetadataForStaticPage("Icons Showcase", "", undefined, undefined, "/icons"); } -const interFont = Inter({ subsets: ["latin"], variable: "--font-sans", preload: true, display: "swap" }); -const calFont = localFont({ - src: "../../fonts/CalSans-SemiBold.woff2", - variable: "--font-cal", - preload: true, - display: "swap", - weight: "600", -}); - export default function IconsPage() { const icons = Array.from(lucideIconList).sort() as IconName[]; return ( -
-
- -
-

Icons Showcase

- - -
+
+ +
+

Icons Showcase

+ +
); diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index 70491f4800..f3d1730209 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -1,6 +1,4 @@ import { dir } from "i18next"; -import { Inter } from "next/font/google"; -import localFont from "next/font/local"; import { headers, cookies } from "next/headers"; import React from "react"; @@ -15,14 +13,7 @@ import { AppRouterI18nProvider } from "./AppRouterI18nProvider"; import { SpeculationRules } from "./SpeculationRules"; import { Providers } from "./providers"; -const interFont = Inter({ subsets: ["latin"], variable: "--font-sans", preload: true, display: "swap" }); -const calFont = localFont({ - src: "../fonts/CalSans-SemiBold.woff2", - variable: "--font-cal", - preload: true, - display: "block", - weight: "600", -}); +import { fontHeading, fontSans } from "@coss/ui/fonts"; export const viewport = { width: "device-width", @@ -114,16 +105,8 @@ export default async function RootLayout({ children }: { children: React.ReactNo style={embedColorScheme ? { colorScheme: embedColorScheme as string } : undefined} suppressHydrationWarning data-nextjs-router="app"> - - -

{t("error_404")}

-

+

{t("feature_currently_disabled") ?? "Feature is currently disabled"}

@@ -114,7 +114,7 @@ export function NotFound({ host }: { host: string }) {

{t("error_404")}

-

+

{isBookingSuccessPage ? "Booking not found" : t("page_doesnt_exist")}

{isSubpage && pageType !== PageType.TEAM ? ( diff --git a/apps/web/components/PageWrapper.tsx b/apps/web/components/PageWrapper.tsx index 9a689a1dac..a024215090 100644 --- a/apps/web/components/PageWrapper.tsx +++ b/apps/web/components/PageWrapper.tsx @@ -10,8 +10,6 @@ "use client"; import { DefaultSeo } from "next-seo"; -import { Inter } from "next/font/google"; -import localFont from "next/font/local"; import Head from "next/head"; import Script from "next/script"; @@ -33,15 +31,6 @@ export interface CalPageWrapper { PageWrapper?: AppProps["Component"]["PageWrapper"]; } -const interFont = Inter({ subsets: ["latin"], variable: "--font-sans", preload: true, display: "swap" }); -const calFont = localFont({ - src: "../fonts/CalSans-SemiBold.woff2", - variable: "--font-cal", - preload: true, - display: "swap", - weight: "600", -}); - function PageWrapper(props: AppProps) { const { Component, pageProps, err, router } = props; let pageStatus = "200"; @@ -87,12 +76,6 @@ function PageWrapper(props: AppProps) { dangerouslySetInnerHTML={{ __html: `window.CalComPageStatus = '${pageStatus}'` }} /> - {getLayout( diff --git a/apps/web/components/apps/AppPage.tsx b/apps/web/components/apps/AppPage.tsx index 61d9428a6b..6d0891efcc 100644 --- a/apps/web/components/apps/AppPage.tsx +++ b/apps/web/components/apps/AppPage.tsx @@ -343,7 +343,7 @@ export const AppPage = ({ src={logo} alt={name} /> -

{name}

+

{name}

= ({ children, title, subtitle }) = return (
-

{title}

+

{title}

{subtitle}

diff --git a/apps/web/components/apps/routing-forms/FormActions.tsx b/apps/web/components/apps/routing-forms/FormActions.tsx index cb78efa728..19a816164a 100644 --- a/apps/web/components/apps/routing-forms/FormActions.tsx +++ b/apps/web/components/apps/routing-forms/FormActions.tsx @@ -95,7 +95,7 @@ function NewFormDialog({ !open && setNewFormDialogState(null)}>
-
diff --git a/apps/web/components/dialog/RerouteDialog.tsx b/apps/web/components/dialog/RerouteDialog.tsx index 837db6f9a3..5953ed557d 100644 --- a/apps/web/components/dialog/RerouteDialog.tsx +++ b/apps/web/components/dialog/RerouteDialog.tsx @@ -804,7 +804,7 @@ const RerouteDialogContentAndFooterWithFormResponse = ({
{form.name} diff --git a/apps/web/components/error/error-page.tsx b/apps/web/components/error/error-page.tsx index 7111803332..8afd26bb5a 100644 --- a/apps/web/components/error/error-page.tsx +++ b/apps/web/components/error/error-page.tsx @@ -71,7 +71,7 @@ export const ErrorPage: React.FC = (props) => { <>
-

{statusCode}

+

{statusCode}

It's not you, it's us.

diff --git a/apps/web/components/security/DisableUserImpersonation.tsx b/apps/web/components/security/DisableUserImpersonation.tsx index b20c0573d8..c0e2c02a83 100644 --- a/apps/web/components/security/DisableUserImpersonation.tsx +++ b/apps/web/components/security/DisableUserImpersonation.tsx @@ -21,7 +21,7 @@ const DisableUserImpersonation = ({ disableImpersonation }: { disableImpersonati
-

+

{t("user_impersonation_heading")}

diff --git a/apps/web/components/security/TwoFactorAuthSection.tsx b/apps/web/components/security/TwoFactorAuthSection.tsx index 59928e33be..d61a341342 100644 --- a/apps/web/components/security/TwoFactorAuthSection.tsx +++ b/apps/web/components/security/TwoFactorAuthSection.tsx @@ -18,7 +18,7 @@ const TwoFactorAuthSection = ({ twoFactorEnabled }: { twoFactorEnabled: boolean
-

{t("2fa")}

+

{t("2fa")}

{enabled ? t("enabled") : t("disabled")} diff --git a/apps/web/components/security/TwoFactorModalHeader.tsx b/apps/web/components/security/TwoFactorModalHeader.tsx index 0fbad2a581..5b48c1b49f 100644 --- a/apps/web/components/security/TwoFactorModalHeader.tsx +++ b/apps/web/components/security/TwoFactorModalHeader.tsx @@ -7,7 +7,7 @@ const TwoFactorModalHeader = ({ title, description }: { title: string; descripti
-

{description}

diff --git a/apps/web/components/settings/platform/dashboard/oauth-clients-list/index.tsx b/apps/web/components/settings/platform/dashboard/oauth-clients-list/index.tsx index bfbf086ae4..39c03c26f0 100644 --- a/apps/web/components/settings/platform/dashboard/oauth-clients-list/index.tsx +++ b/apps/web/components/settings/platform/dashboard/oauth-clients-list/index.tsx @@ -17,7 +17,7 @@ export const OAuthClientsList = ({ oauthClients, isDeleting, handleDelete }: OAu
-

+

OAuth Clients

diff --git a/apps/web/components/setup/ChooseLicense.tsx b/apps/web/components/setup/ChooseLicense.tsx index e7168fb46e..a95dc24f0c 100644 --- a/apps/web/components/setup/ChooseLicense.tsx +++ b/apps/web/components/setup/ChooseLicense.tsx @@ -39,7 +39,7 @@ const ChooseLicense = ( "bg-default cursor-pointer stack-y-2 rounded-md border p-4 hover:border-black", value === "FREE" && "ring-2 ring-black" )}> -

{t("agplv3_license")}

+

{t("agplv3_license")}

{t("free_license_fee")}

{t("forever_open_and_free")}

    @@ -52,7 +52,7 @@ const ChooseLicense = (
    -

    {t("custom_plan")}

    +

    {t("custom_plan")}

    {t("contact_sales")}

    Build on top of Cal.com

      diff --git a/apps/web/components/setup/LicenseSelection.tsx b/apps/web/components/setup/LicenseSelection.tsx index 5250018464..17109e940e 100644 --- a/apps/web/components/setup/LicenseSelection.tsx +++ b/apps/web/components/setup/LicenseSelection.tsx @@ -122,7 +122,7 @@ const LicenseSelection = ( "bg-default h-full cursor-pointer stack-y-2 rounded-md border p-4 hover:border-black", value === "FREE" && "ring-2 ring-black" )}> -

      {t("agplv3_license")}

      +

      {t("agplv3_license")}

      {t("free_license_fee")}

      {t("forever_open_and_free")}

        @@ -139,7 +139,7 @@ const LicenseSelection = ( "bg-default h-full cursor-pointer stack-y-2 rounded-md border p-4 hover:border-black", value === "EXISTING" && "ring-2 ring-black" )}> -

        {t("enter_license_key")}

        +

        {t("enter_license_key")}

        {t("enter_existing_license")}

        {t("enter_your_license_key")}

        diff --git a/apps/web/components/ui/AuthContainer.tsx b/apps/web/components/ui/AuthContainer.tsx index 3846d94447..feebaad064 100644 --- a/apps/web/components/ui/AuthContainer.tsx +++ b/apps/web/components/ui/AuthContainer.tsx @@ -17,7 +17,7 @@ export default function AuthContainer(props: React.PropsWithChildren) { {props.showLogo && }

        - {props.heading &&

        {props.heading}

        } + {props.heading &&

        {props.heading}

        }
        {props.loading && (
        diff --git a/apps/web/modules/auth/forgot-password/[id]/forgot-password-single-view.tsx b/apps/web/modules/auth/forgot-password/[id]/forgot-password-single-view.tsx index 66056bf1f4..5d096d9a07 100644 --- a/apps/web/modules/auth/forgot-password/[id]/forgot-password-single-view.tsx +++ b/apps/web/modules/auth/forgot-password/[id]/forgot-password-single-view.tsx @@ -23,7 +23,7 @@ function Success() { <>
        -

        +

        {t("password_updated")}

        @@ -41,7 +41,7 @@ function Expired() { <>
        -

        {t("whoops")}

        +

        {t("whoops")}

        {t("request_is_expired")}

        {t("request_is_expired_instructions")}

        diff --git a/apps/web/modules/auth/verify-view.tsx b/apps/web/modules/auth/verify-view.tsx index 36ab3dca21..c025cb4386 100644 --- a/apps/web/modules/auth/verify-view.tsx +++ b/apps/web/modules/auth/verify-view.tsx @@ -172,7 +172,7 @@ export default function Verify({ EMAIL_FROM }: { EMAIL_FROM?: string }) { ) : ( )} -

        +

        {hasPaymentFailed ? t("your_payment_failed") : isPremiumUsername diff --git a/apps/web/modules/bookings/components/BookEventForm/BookFormAsModal.tsx b/apps/web/modules/bookings/components/BookEventForm/BookFormAsModal.tsx index 4c1c565de0..77a5af5db0 100644 --- a/apps/web/modules/bookings/components/BookEventForm/BookFormAsModal.tsx +++ b/apps/web/modules/bookings/components/BookEventForm/BookFormAsModal.tsx @@ -53,7 +53,7 @@ export const BookEventFormWrapperComponent = ({ } return ( <> -

        {t("confirm_your_details")}

        +

        {t("confirm_your_details")}

        (
        -

        {title}

        +

        {title}

        {children}
        diff --git a/apps/web/modules/bookings/views/bookings-single-view.tsx b/apps/web/modules/bookings/views/bookings-single-view.tsx index c7d50efd98..6a8b95325f 100644 --- a/apps/web/modules/bookings/views/bookings-single-view.tsx +++ b/apps/web/modules/bookings/views/bookings-single-view.tsx @@ -1061,7 +1061,7 @@ export default function Success(props: PageProps) { ))}
        -

        {t("submitted_feedback")}

        +

        {t("submitted_feedback")}

        {rateValue < 4 ? t("how_can_we_improve") : t("most_liked")}