diff --git a/apps/v4/content/docs/(root)/changelog.mdx b/apps/v4/content/docs/(root)/changelog.mdx index 45ce4cc9510..09dc98ac7e8 100644 --- a/apps/v4/content/docs/(root)/changelog.mdx +++ b/apps/v4/content/docs/(root)/changelog.mdx @@ -4,6 +4,37 @@ description: Latest updates and announcements. toc: false --- +## November 2025 - Fixes + +### Default style button icons + +We shipped the `icon-sm` and `icon-lg` sizes for the **New York** button back +in September, but the `default` style was still missing those variants. This +release adds both icon sizes to the default style so that icon-only buttons +look consistent regardless of the style you pick. + +Run the following command to update your project: + +```bash +npx shadcn@latest add button --overwrite +``` + +Or manually add the new variants under `size` in `buttonVariants`: + +```tsx showLineNumbers title="components/ui/button.tsx" +const buttonVariants = cva("...", { + variants: { + size: { + icon: "h-10 w-10", + "icon-sm": "h-9 w-9", + "icon-lg": "h-11 w-11", + }, + }, +}) +``` + +Fixes: [#8757](https://github.com/shadcn-ui/ui/issues/8757) + ## October 2025 - New Components For this round of components, I looked at what we build every day, the boring stuff we rebuild over and over, and made reusable abstractions you can actually use. diff --git a/apps/v4/public/r/styles/default/button.json b/apps/v4/public/r/styles/default/button.json index 1f2df4e6c27..f4588fffd49 100644 --- a/apps/v4/public/r/styles/default/button.json +++ b/apps/v4/public/r/styles/default/button.json @@ -9,7 +9,7 @@ "files": [ { "path": "ui/button.tsx", - "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-10 w-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes,\n VariantProps {\n asChild?: boolean\n}\n\nconst Button = React.forwardRef(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\"\n return (\n \n )\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n", + "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-10 w-10\",\n \"icon-sm\": \"h-9 w-9\",\n \"icon-lg\": \"h-11 w-11\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes,\n VariantProps {\n asChild?: boolean\n}\n\nconst Button = React.forwardRef(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\"\n return (\n \n )\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n", "type": "registry:ui", "target": "" } diff --git a/apps/v4/registry/new-york-v4/ui/select.tsx b/apps/v4/registry/new-york-v4/ui/select.tsx index 25e54394d5f..28377b1a955 100644 --- a/apps/v4/registry/new-york-v4/ui/select.tsx +++ b/apps/v4/registry/new-york-v4/ui/select.tsx @@ -151,6 +151,7 @@ function SelectScrollUpButton({ {...props} > + Scroll up ) } @@ -169,6 +170,7 @@ function SelectScrollDownButton({ {...props} > + Scroll down ) } diff --git a/deprecated/www/public/r/styles/default/button.json b/deprecated/www/public/r/styles/default/button.json index 1f2df4e6c27..f4588fffd49 100644 --- a/deprecated/www/public/r/styles/default/button.json +++ b/deprecated/www/public/r/styles/default/button.json @@ -9,7 +9,7 @@ "files": [ { "path": "ui/button.tsx", - "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-10 w-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes,\n VariantProps {\n asChild?: boolean\n}\n\nconst Button = React.forwardRef(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\"\n return (\n \n )\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n", + "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-10 w-10\",\n \"icon-sm\": \"h-9 w-9\",\n \"icon-lg\": \"h-11 w-11\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes,\n VariantProps {\n asChild?: boolean\n}\n\nconst Button = React.forwardRef(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\"\n return (\n \n )\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n", "type": "registry:ui", "target": "" } diff --git a/deprecated/www/public/registry/styles/default/button.json b/deprecated/www/public/registry/styles/default/button.json index b292cab4316..1d6065c57f6 100644 --- a/deprecated/www/public/registry/styles/default/button.json +++ b/deprecated/www/public/registry/styles/default/button.json @@ -6,7 +6,7 @@ "files": [ { "name": "button.tsx", - "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-10 w-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes,\n VariantProps {\n asChild?: boolean\n}\n\nconst Button = React.forwardRef(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\"\n return (\n \n )\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n" + "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-10 w-10\",\n \"icon-sm\": \"h-9 w-9\",\n \"icon-lg\": \"h-11 w-11\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes,\n VariantProps {\n asChild?: boolean\n}\n\nconst Button = React.forwardRef(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\"\n return (\n \n )\n }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n" } ], "type": "components:ui" diff --git a/deprecated/www/registry/default/ui/button.tsx b/deprecated/www/registry/default/ui/button.tsx index 36496a28727..96a0256be3f 100644 --- a/deprecated/www/registry/default/ui/button.tsx +++ b/deprecated/www/registry/default/ui/button.tsx @@ -24,6 +24,8 @@ const buttonVariants = cva( sm: "h-9 rounded-md px-3", lg: "h-11 rounded-md px-8", icon: "h-10 w-10", + "icon-sm": "h-9 w-9", + "icon-lg": "h-11 w-11", }, }, defaultVariants: { diff --git a/packages/tests/src/tests/add.test.ts b/packages/tests/src/tests/add.test.ts index 43ec6cbaa82..817fdd49c49 100644 --- a/packages/tests/src/tests/add.test.ts +++ b/packages/tests/src/tests/add.test.ts @@ -22,6 +22,26 @@ describe("shadcn add", () => { ).toBe(true) }) + it("should add icon button sizes when using the default style", async () => { + const fixturePath = await createFixtureTestDirectory("next-app") + await npxShadcn(fixturePath, ["init", "--base-color=neutral"]) + + const componentsJsonPath = path.join(fixturePath, "components.json") + const componentsJson = await fs.readJson(componentsJsonPath) + componentsJson.style = "default" + await fs.writeJson(componentsJsonPath, componentsJson, { spaces: 2 }) + + await npxShadcn(fixturePath, ["add", "button"]) + + const buttonContent = await fs.readFile( + path.join(fixturePath, "components/ui/button.tsx"), + "utf-8" + ) + + expect(buttonContent).toContain('"icon-sm": "h-9 w-9"') + expect(buttonContent).toContain('"icon-lg": "h-11 w-11"') + }) + it("should add multiple items to project", async () => { const fixturePath = await createFixtureTestDirectory("next-app") await npxShadcn(fixturePath, ["init", "--base-color=neutral"])