Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/shadcn/components.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"$schema": "https://ui.shadcn.com/schema/index.json",
"style": "default",
"style": "base-vega",
"rsc": false,
"tsx": true,
"iconLibrary": "lucide",
"tailwind": {
"css": "src/style.css",
"baseColor": "slate",
Expand Down
11 changes: 1 addition & 10 deletions packages/shadcn/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,16 @@
"clean": "rimraf dist && rimraf types"
},
"dependencies": {
"@base-ui/react": "^1.6.0",
"@blocknote/core": "workspace:^",
"@blocknote/react": "workspace:^",
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-toggle": "^1.1.10",
"@radix-ui/react-tooltip": "^1.2.8",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.525.0",
"react-hook-form": "^7.65.0",
"tailwind-merge": "^2.6.0"
},
"devDependencies": {
"@radix-ui/colors": "^3.0.0",
"@types/node": "^20.19.22",
"@types/react": "^19.2.3",
"@types/react-dom": "^19.2.3",
Expand Down
2 changes: 2 additions & 0 deletions packages/shadcn/src/ShadCNComponentsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
DropdownMenu as ShadCNDropdownMenu,
DropdownMenuCheckboxItem as ShadCNDropdownMenuCheckboxItem,
DropdownMenuContent as ShadCNDropdownMenuContent,
DropdownMenuGroup as ShadCNDropdownMenuGroup,
DropdownMenuItem as ShadCNDropdownMenuItem,
DropdownMenuLabel as ShadCNDropdownMenuLabel,
DropdownMenuSeparator as ShadCNDropdownMenuSeparator,
Expand Down Expand Up @@ -73,6 +74,7 @@ export const ShadCNDefaultComponents = {
DropdownMenu: ShadCNDropdownMenu,
DropdownMenuCheckboxItem: ShadCNDropdownMenuCheckboxItem,
DropdownMenuContent: ShadCNDropdownMenuContent,
DropdownMenuGroup: ShadCNDropdownMenuGroup,
DropdownMenuItem: ShadCNDropdownMenuItem,
DropdownMenuLabel: ShadCNDropdownMenuLabel,
DropdownMenuSeparator: ShadCNDropdownMenuSeparator,
Expand Down
13 changes: 8 additions & 5 deletions packages/shadcn/src/badge/Badge.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assertEmpty } from "@blocknote/core";
import { ComponentProps } from "@blocknote/react";
import { ComponentProps, useBlockNoteEditor } from "@blocknote/react";
import { forwardRef } from "react";

import { cn } from "../lib/utils.js";
Expand All @@ -25,6 +25,10 @@ export const Badge = forwardRef<

const ShadCNComponents = useShadCNComponentsContext()!;

// Portal the tooltip into the editor's portal element so it inherits the
// editor's light/dark color scheme instead of the document body's.
const editor = useBlockNoteEditor();

const badge = (
<ShadCNComponents.Button.Button
variant={isSelected ? "secondary" : "outline"}
Expand All @@ -47,10 +51,9 @@ export const Badge = forwardRef<

return (
<ShadCNComponents.Tooltip.Tooltip>
<ShadCNComponents.Tooltip.TooltipTrigger asChild>
{badge}
</ShadCNComponents.Tooltip.TooltipTrigger>
<ShadCNComponents.Tooltip.TooltipTrigger render={badge} />
<ShadCNComponents.Tooltip.TooltipContent
container={editor.portalElement}
className={"flex flex-col items-center whitespace-pre-wrap"}
>
<span>{mainTooltip}</span>
Expand All @@ -71,7 +74,7 @@ export const BadgeGroup = forwardRef<
const ShadCNComponents = useShadCNComponentsContext()!;

return (
<ShadCNComponents.Tooltip.TooltipProvider delayDuration={0}>
<ShadCNComponents.Tooltip.TooltipProvider delay={0}>
<div
className={cn(className, "flex w-full flex-row flex-wrap gap-1")}
ref={ref}
Expand Down
80 changes: 67 additions & 13 deletions packages/shadcn/src/components/ui/avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
"use client";

import * as React from "react";
import * as AvatarPrimitive from "@radix-ui/react-avatar";
import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's mark changes in generated components with comments


import { cn } from "../../lib/utils";

function Avatar({
className,
size = "default",
...props
}: React.ComponentProps<typeof AvatarPrimitive.Root>) {
}: AvatarPrimitive.Root.Props & {
size?: "default" | "sm" | "lg";
}) {
return (
<AvatarPrimitive.Root
data-slot="avatar"
data-size={size}
className={cn(
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
"group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
className,
)}
{...props}
/>
);
}

function AvatarImage({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {
return (
<AvatarPrimitive.Image
data-slot="avatar-image"
className={cn("aspect-square size-full", className)}
className={cn(
"aspect-square size-full rounded-full object-cover",
className,
)}
{...props}
/>
);
Expand All @@ -37,17 +39,69 @@ function AvatarImage({
function AvatarFallback({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
}: AvatarPrimitive.Fallback.Props) {
return (
<AvatarPrimitive.Fallback
data-slot="avatar-fallback"
className={cn(
"bg-muted flex size-full items-center justify-center rounded-full",
"flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
className,
)}
{...props}
/>
);
}

function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
return (
<span
data-slot="avatar-badge"
className={cn(
"absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none",
"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
className,
)}
{...props}
/>
);
}

function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="avatar-group"
className={cn(
"group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
className,
)}
{...props}
/>
);
}

function AvatarGroupCount({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="avatar-group-count"
className={cn(
"relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
className,
)}
{...props}
/>
);
}

export { Avatar, AvatarImage, AvatarFallback };
export {
Avatar,
AvatarImage,
AvatarFallback,
AvatarGroup,
AvatarGroupCount,
AvatarBadge,
};
48 changes: 27 additions & 21 deletions packages/shadcn/src/components/ui/badge.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cva, type VariantProps } from "class-variance-authority";

import { cn } from "../../lib/utils";

const badgeVariants = cva(
"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
"group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
outline:
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
ghost:
"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
link: "text-primary underline-offset-4 hover:underline",
},
},
defaultVariants: {
Expand All @@ -27,20 +29,24 @@ const badgeVariants = cva(

function Badge({
className,
variant,
asChild = false,
variant = "default",
render,
...props
}: React.ComponentProps<"span"> &
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
const Comp = asChild ? Slot : "span";

return (
<Comp
data-slot="badge"
className={cn(badgeVariants({ variant }), className)}
{...props}
/>
);
}: useRender.ComponentProps<"span"> & VariantProps<typeof badgeVariants>) {
return useRender({
defaultTagName: "span",
props: mergeProps<"span">(
{
className: cn(badgeVariants({ variant }), className),
},
props,
),
render,
state: {
slot: "badge",
variant,
},
});
}

export { Badge, badgeVariants };
45 changes: 22 additions & 23 deletions packages/shadcn/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { Button as ButtonPrimitive } from "@base-ui/react/button";
import { cva, type VariantProps } from "class-variance-authority";

import { cn } from "../../lib/utils";

const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*=size-])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
destructive:
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
default: "bg-primary text-primary-foreground hover:bg-primary/80",
outline:
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
"border-border bg-background shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
secondary:
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
ghost:
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
destructive:
"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
default:
"h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
xs: "h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
sm: "h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5",
lg: "h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
icon: "size-9",
"icon-xs":
"size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3",
"icon-sm":
"size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md",
"icon-lg": "size-10",
},
},
defaultVariants: {
Expand All @@ -37,18 +42,12 @@ const buttonVariants = cva(

function Button({
className,
variant,
size,
asChild = false,
variant = "default",
size = "default",
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean;
}) {
const Comp = asChild ? Slot : "button";

}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
return (
<Comp
<ButtonPrimitive
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
{...props}
Expand Down
Loading
Loading