diff --git a/apps/v4/registry/fonts.ts b/apps/v4/registry/fonts.ts index 139d09079b..431d2570b8 100644 --- a/apps/v4/registry/fonts.ts +++ b/apps/v4/registry/fonts.ts @@ -11,6 +11,7 @@ export const fonts = [ variable: "--font-sans", subsets: ["latin"], import: "Geist", + dependency: "@fontsource-variable/geist", }, }, { @@ -23,6 +24,7 @@ export const fonts = [ variable: "--font-sans", subsets: ["latin"], import: "Inter", + dependency: "@fontsource-variable/inter", }, }, { @@ -34,6 +36,7 @@ export const fonts = [ provider: "google", variable: "--font-sans", import: "Noto_Sans", + dependency: "@fontsource-variable/noto-sans", }, }, { @@ -45,6 +48,7 @@ export const fonts = [ provider: "google", variable: "--font-sans", import: "Nunito_Sans", + dependency: "@fontsource-variable/nunito-sans", }, }, { @@ -57,6 +61,7 @@ export const fonts = [ variable: "--font-sans", subsets: ["latin"], import: "Figtree", + dependency: "@fontsource-variable/figtree", }, }, { @@ -69,6 +74,7 @@ export const fonts = [ variable: "--font-sans", subsets: ["latin"], import: "Roboto", + dependency: "@fontsource-variable/roboto", }, }, { @@ -81,6 +87,7 @@ export const fonts = [ variable: "--font-sans", subsets: ["latin"], import: "Raleway", + dependency: "@fontsource-variable/raleway", }, }, { @@ -93,6 +100,7 @@ export const fonts = [ variable: "--font-sans", subsets: ["latin"], import: "DM_Sans", + dependency: "@fontsource-variable/dm-sans", }, }, { @@ -105,6 +113,7 @@ export const fonts = [ variable: "--font-sans", subsets: ["latin"], import: "Public_Sans", + dependency: "@fontsource-variable/public-sans", }, }, { @@ -117,6 +126,7 @@ export const fonts = [ variable: "--font-sans", subsets: ["latin"], import: "Outfit", + dependency: "@fontsource-variable/outfit", }, }, { @@ -129,6 +139,7 @@ export const fonts = [ variable: "--font-mono", subsets: ["latin"], import: "JetBrains_Mono", + dependency: "@fontsource-variable/jetbrains-mono", }, }, { @@ -141,6 +152,7 @@ export const fonts = [ variable: "--font-mono", subsets: ["latin"], import: "Geist_Mono", + dependency: "@fontsource-variable/geist-mono", }, }, { @@ -153,6 +165,7 @@ export const fonts = [ variable: "--font-serif", subsets: ["latin"], import: "Noto_Serif", + dependency: "@fontsource-variable/noto-serif", }, }, { @@ -165,6 +178,7 @@ export const fonts = [ variable: "--font-serif", subsets: ["latin"], import: "Roboto_Slab", + dependency: "@fontsource-variable/roboto-slab", }, }, { @@ -177,6 +191,7 @@ export const fonts = [ variable: "--font-serif", subsets: ["latin"], import: "Merriweather", + dependency: "@fontsource-variable/merriweather", }, }, { @@ -189,6 +204,7 @@ export const fonts = [ variable: "--font-serif", subsets: ["latin"], import: "Lora", + dependency: "@fontsource-variable/lora", }, }, { @@ -201,6 +217,7 @@ export const fonts = [ variable: "--font-serif", subsets: ["latin"], import: "Playfair_Display", + dependency: "@fontsource-variable/playfair-display", }, }, ] satisfies RegistryItem[] diff --git a/packages/shadcn/src/registry/schema.ts b/packages/shadcn/src/registry/schema.ts index 7501eb2cdf..9bab2e84fe 100644 --- a/packages/shadcn/src/registry/schema.ts +++ b/packages/shadcn/src/registry/schema.ts @@ -151,6 +151,7 @@ export const registryItemFontSchema = z.object({ weight: z.array(z.string()).optional(), subsets: z.array(z.string()).optional(), selector: z.string().optional(), + dependency: z.string().optional(), }) // Common fields shared by all registry items. diff --git a/packages/shadcn/src/templates/monorepo.ts b/packages/shadcn/src/templates/monorepo.ts index ca3dc60517..5168ff9ff7 100644 --- a/packages/shadcn/src/templates/monorepo.ts +++ b/packages/shadcn/src/templates/monorepo.ts @@ -98,23 +98,23 @@ export async function fontsourceMonorepoInit(options: TemplateInitOptions) { ) if (tree?.fonts?.length) { const [fontSans] = tree.fonts + // Add fontsource dependency. const fontName = fontSans.name.replace("font-", "") - const fontSourceBase = `@fontsource/${fontName}` - const fontSourceVariable = `@fontsource-variable/${fontName}` + const fontSourceDependency = + fontSans.font.dependency ?? `@fontsource-variable/${fontName}` await updateDependencies( - [fontSourceBase, fontSourceVariable], + [fontSourceDependency], [], resolvedPackagesUiConfig, { silent: true } ) // Add font CSS variable to @theme inline in packages/ui CSS. - const baseFamily = fontSans.font.family.replace(" Variable", "") await updateCssVars( { theme: { - [fontSans.font.variable]: baseFamily, + [fontSans.font.variable]: fontSans.font.family, }, }, resolvedPackagesUiConfig, @@ -128,13 +128,7 @@ export async function fontsourceMonorepoInit(options: TemplateInitOptions) { // Add fontsource import to packages/ui CSS. await updateCss( { - [`@import "${fontSourceBase}"`]: {}, - [`@import "${fontSourceVariable}"`]: {}, - "@supports (font-variation-settings: normal)": { - ":root": { - [fontSans.font.variable]: fontSans.font.family, - }, - }, + [`@import "${fontSourceDependency}"`]: {}, }, resolvedPackagesUiConfig, { diff --git a/packages/shadcn/src/utils/updaters/update-fonts.test.ts b/packages/shadcn/src/utils/updaters/update-fonts.test.ts index 0890efae96..fd96686503 100644 --- a/packages/shadcn/src/utils/updaters/update-fonts.test.ts +++ b/packages/shadcn/src/utils/updaters/update-fonts.test.ts @@ -1402,19 +1402,19 @@ describe("massageTreeForFonts", () => { }) }) - - it("should add both base and variable fontsource dependencies", async () => { + it("should install non-variable font using dependency field", async () => { const tree = { fonts: [ { - name: "font-inter", + name: "font-lato", type: "registry:font" as const, font: { - family: "'Inter Variable', sans-serif", + family: "'Lato', sans-serif", provider: "google" as const, - import: "Inter", + import: "Lato", variable: "--font-sans", - subsets: ["latin"], + weight: ["400", "700"], + dependency: "@fontsource/lato", }, }, ], @@ -1424,11 +1424,13 @@ describe("massageTreeForFonts", () => { resolvedPaths: { cwd: "/test" }, } as any) - expect(result.dependencies).toContain("@fontsource/inter") - expect(result.dependencies).toContain("@fontsource-variable/inter") + expect(result.dependencies).toContain("@fontsource/lato") + expect(result.dependencies).not.toContain("@fontsource-variable/lato") + expect(result.css).toHaveProperty('@import "@fontsource/lato"') + expect(result.cssVars!.theme!["--font-sans"]).toBe("'Lato', sans-serif") }) - it("should add both CSS imports", async () => { + it("should fall back to @fontsource-variable when no dependency is specified", async () => { const tree = { fonts: [ { @@ -1449,97 +1451,7 @@ describe("massageTreeForFonts", () => { resolvedPaths: { cwd: "/test" }, } as any) - expect(result.css).toHaveProperty('@import "@fontsource/inter"') + expect(result.dependencies).toContain("@fontsource-variable/inter") expect(result.css).toHaveProperty('@import "@fontsource-variable/inter"') }) - - it("should set base font family without Variable suffix in cssVars", async () => { - const tree = { - fonts: [ - { - name: "font-inter", - type: "registry:font" as const, - font: { - family: "'Inter Variable', sans-serif", - provider: "google" as const, - import: "Inter", - variable: "--font-sans", - subsets: ["latin"], - }, - }, - ], - } as any - - const result = await massageTreeForFonts(tree, { - resolvedPaths: { cwd: "/test" }, - } as any) - - expect(result.cssVars!.theme!["--font-sans"]).toBe("'Inter', sans-serif") - }) - - it("should add @supports block with variable font override", async () => { - const tree = { - fonts: [ - { - name: "font-inter", - type: "registry:font" as const, - font: { - family: "'Inter Variable', sans-serif", - provider: "google" as const, - import: "Inter", - variable: "--font-sans", - subsets: ["latin"], - }, - }, - ], - } as any - - const result = await massageTreeForFonts(tree, { - resolvedPaths: { cwd: "/test" }, - } as any) - - expect( - result.css!["@supports (font-variation-settings: normal)"][":root"][ - "--font-sans" - ] - ).toBe("'Inter Variable', sans-serif") - }) - - it("should accumulate multiple fonts in @supports block", async () => { - const tree = { - fonts: [ - { - name: "font-inter", - type: "registry:font" as const, - font: { - family: "'Inter Variable', sans-serif", - provider: "google" as const, - import: "Inter", - variable: "--font-sans", - subsets: ["latin"], - }, - }, - { - name: "font-lora", - type: "registry:font" as const, - font: { - family: "'Lora Variable', serif", - provider: "google" as const, - import: "Lora", - variable: "--font-serif", - subsets: ["latin"], - }, - }, - ], - } as any - - const result = await massageTreeForFonts(tree, { - resolvedPaths: { cwd: "/test" }, - } as any) - - const supportsRoot = - result.css!["@supports (font-variation-settings: normal)"][":root"] - expect(supportsRoot["--font-sans"]).toBe("'Inter Variable', sans-serif") - expect(supportsRoot["--font-serif"]).toBe("'Lora Variable', serif") - }) }) diff --git a/packages/shadcn/src/utils/updaters/update-fonts.ts b/packages/shadcn/src/utils/updaters/update-fonts.ts index 5d96f09fdb..a4e3bd06fd 100644 --- a/packages/shadcn/src/utils/updaters/update-fonts.ts +++ b/packages/shadcn/src/utils/updaters/update-fonts.ts @@ -44,25 +44,13 @@ export async function massageTreeForFonts( } else { // Other frameworks will use fontsource for now. const fontName = font.name.replace("font-", "") - const fontSourceBase = `@fontsource/${fontName}` - const fontSourceVariable = `@fontsource-variable/${fontName}` - + const fontSourceDependency = + font.font.dependency ?? `@fontsource-variable/${fontName}` tree.dependencies ??= [] - tree.dependencies.push(fontSourceBase) - tree.dependencies.push(fontSourceVariable) - + tree.dependencies.push(fontSourceDependency) tree.css ??= {} - tree.css[`@import "${fontSourceBase}"`] = {} - tree.css[`@import "${fontSourceVariable}"`] = {} - - const baseFamily = font.font.family.replace(" Variable", "") - tree.cssVars.theme[font.font.variable] = baseFamily - - tree.css["@supports (font-variation-settings: normal)"] ??= {} - tree.css["@supports (font-variation-settings: normal)"][":root"] ??= {} - tree.css["@supports (font-variation-settings: normal)"][":root"][ - font.font.variable - ] = font.font.family + tree.css[`@import "${fontSourceDependency}"`] = {} + tree.cssVars.theme[font.font.variable] = font.font.family } }