Merge pull request #10035 from shadcn-ui/fix/registry-font-dependency

Add dependency field to font schema
This commit is contained in:
shadcn
2026-03-14 15:49:51 +04:00
committed by GitHub
5 changed files with 41 additions and 129 deletions

View File

@@ -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[]

View File

@@ -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.

View File

@@ -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,
{

View File

@@ -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")
})
})

View File

@@ -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
}
}