@vvedantb/ui 0.34.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +50 -6
  2. package/package.json +10 -2
  3. package/src/ai-elements/activity-shared.tsx +1 -1
  4. package/src/ai-elements/activity-tasks.tsx +5 -19
  5. package/src/ai-elements/attachments.tsx +2 -2
  6. package/src/ai-elements/code-block.tsx +3 -1
  7. package/src/ai-elements/conversation.tsx +10 -4
  8. package/src/ai-elements/prompt-input.tsx +5 -4
  9. package/src/client.ts +3 -0
  10. package/src/icons/animated/animated-bell-icon.tsx +68 -0
  11. package/src/icons/animated/animated-counter.tsx +45 -0
  12. package/src/icons/animated/animated-key-icon.tsx +79 -0
  13. package/src/icons/animated/animated-notification-icon.tsx +202 -0
  14. package/src/icons/animated/animated-progress.tsx +74 -0
  15. package/src/icons/animated/animated-status-dot.tsx +98 -0
  16. package/src/icons/animated/index.ts +22 -0
  17. package/src/icons/animated/morphing-menu-icon.tsx +71 -0
  18. package/src/icons/animated/morphing-mic-icon.tsx +52 -0
  19. package/src/icons/animated/pulsing-rings.tsx +50 -0
  20. package/src/index.ts +3 -0
  21. package/src/logos/chrome-icon.tsx +29 -0
  22. package/src/logos/claude-icon.tsx +13 -0
  23. package/src/logos/convex-icon.tsx +21 -0
  24. package/src/logos/cursor-icon.tsx +10 -0
  25. package/src/logos/dropbox-icon.tsx +14 -0
  26. package/src/logos/figma-icon.tsx +26 -0
  27. package/src/logos/github-icon.tsx +10 -0
  28. package/src/logos/gmail-icon.tsx +34 -0
  29. package/src/logos/google-drive-icon.tsx +33 -0
  30. package/src/logos/index.ts +19 -0
  31. package/src/logos/linear-icon.tsx +13 -0
  32. package/src/logos/logo-svg.tsx +32 -0
  33. package/src/logos/notion-icon.tsx +19 -0
  34. package/src/logos/onedrive-icon.tsx +165 -0
  35. package/src/logos/sharepoint-icon.tsx +222 -0
  36. package/src/logos/slack-icon.tsx +25 -0
  37. package/src/logos/vercel-icon.tsx +10 -0
  38. package/src/ui/_menu-parts.tsx +1 -1
  39. package/src/ui/button-group.tsx +1 -1
  40. package/src/ui/clear-input.tsx +2 -2
  41. package/src/ui/command.tsx +2 -2
  42. package/src/ui/context-menu.tsx +3 -3
  43. package/src/ui/dropdown-menu.tsx +1 -1
  44. package/src/ui/hover-card.tsx +3 -3
  45. package/src/ui/input-group.tsx +4 -4
  46. package/src/ui/popover.tsx +3 -5
  47. package/src/ui/search-input.tsx +1 -1
  48. package/src/ui/select.tsx +5 -5
  49. package/src/ui/sonner.tsx +3 -0
  50. package/src/ui/tooltip.tsx +3 -3
@@ -150,7 +150,7 @@ const CommandList = React.forwardRef<
150
150
  return (
151
151
  <CommandPrimitive.List
152
152
  ref={ref}
153
- className={merge(list ?? "max-h-80 overflow-y-auto overflow-x-hidden pb-2", className)}
153
+ className={merge(list ?? "max-h-80 max-sm:max-h-[60dvh] overflow-y-auto overflow-x-hidden pb-2", className)}
154
154
  {...props}
155
155
  />
156
156
  );
@@ -225,7 +225,7 @@ const CommandItem = React.forwardRef<
225
225
  ref={ref}
226
226
  className={merge(
227
227
  item ??
228
- "relative flex cursor-default gap-2 select-none items-center rounded-menu-item px-2.5 py-2 text-sm outline-none transition-colors data-[disabled=true]:pointer-events-none data-[selected=true]:bg-surface-tertiary/80 data-[selected=true]:text-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
228
+ "relative flex cursor-default gap-2 select-none items-center rounded-menu-item px-2.5 py-2 max-sm:min-h-10 text-sm outline-none transition-colors data-[disabled=true]:pointer-events-none data-[selected=true]:bg-surface-tertiary/80 data-[selected=true]:text-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
229
229
  className,
230
230
  )}
231
231
  {...props}
@@ -24,7 +24,7 @@ import { useCn, useUiConfig } from "./ui-config";
24
24
 
25
25
  /** App defaults for `ContextMenu*` (see `UiConfigProvider`). */
26
26
  export interface ContextMenuConfig extends MenuConfig {
27
- /** Default for `ContextMenuSubContent` `portal`. */
27
+ /** Default for `ContextMenuSubContent` `portal` (built-in: `true`). */
28
28
  subContentPortal?: boolean;
29
29
  }
30
30
 
@@ -88,7 +88,7 @@ const ContextMenuSubContent = React.forwardRef<
88
88
  {...props}
89
89
  />
90
90
  );
91
- return (portal ?? config?.subContentPortal) ? (
91
+ return (portal ?? config?.subContentPortal ?? true) ? (
92
92
  <ContextMenuPrimitive.Portal>{content}</ContextMenuPrimitive.Portal>
93
93
  ) : (
94
94
  content
@@ -109,7 +109,7 @@ const ContextMenuContent = React.forwardRef<
109
109
  <ContextMenuPrimitive.Portal>
110
110
  <ContextMenuPrimitive.Content
111
111
  ref={ref}
112
- collisionPadding={collisionPadding ?? config?.collisionPadding}
112
+ collisionPadding={collisionPadding ?? config?.collisionPadding ?? 8}
113
113
  className={merge(config?.classes?.content ?? [menuContentClass, "w-40"], className)}
114
114
  onKeyDown={suppressAltKey ? suppressAltKeyDown(onKeyDown) : onKeyDown}
115
115
  {...props}
@@ -127,7 +127,7 @@ const DropdownMenuContent = React.forwardRef<
127
127
  <DropdownMenuPrimitive.Content
128
128
  ref={ref}
129
129
  sideOffset={sideOffset ?? config?.sideOffset ?? 4}
130
- collisionPadding={collisionPadding ?? config?.collisionPadding}
130
+ collisionPadding={collisionPadding ?? config?.collisionPadding ?? 8}
131
131
  className={merge(
132
132
  config?.classes?.content ?? menuContentClass,
133
133
  fitViewport && fitViewportClass,
@@ -16,7 +16,7 @@ export interface HoverCardConfig {
16
16
  closeDelay?: number;
17
17
  /** Default for `HoverCardContent` `sideOffset`. */
18
18
  sideOffset?: number;
19
- /** Default for `HoverCardContent` `portal`. */
19
+ /** Default for `HoverCardContent` `portal` (built-in: `true`). */
20
20
  portal?: boolean;
21
21
  }
22
22
 
@@ -40,7 +40,7 @@ const HoverCardTrigger = HoverCardPrimitive.Trigger;
40
40
  const HoverCardContent = React.forwardRef<
41
41
  React.ComponentRef<typeof HoverCardPrimitive.Content>,
42
42
  React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content> & {
43
- /** Render into `document.body` so a clipping parent cannot cut it off. */
43
+ /** Render into `document.body` so a clipping parent cannot cut it off (default `true`). */
44
44
  portal?: boolean;
45
45
  }
46
46
  >(({ className, align = "center", sideOffset, portal, ...props }, ref) => {
@@ -62,7 +62,7 @@ const HoverCardContent = React.forwardRef<
62
62
  {...props}
63
63
  />
64
64
  );
65
- return (portal ?? config?.portal) ? (
65
+ return (portal ?? config?.portal ?? true) ? (
66
66
  <HoverCardPrimitive.Portal>{content}</HoverCardPrimitive.Portal>
67
67
  ) : (
68
68
  content
@@ -116,10 +116,10 @@ function InputGroupAddon({
116
116
  const inputGroupButtonBaseClasses = "text-sm shadow-none flex gap-2 items-center";
117
117
 
118
118
  const inputGroupButtonSizeClasses = {
119
- xs: "h-7 gap-1 rounded-lg px-2 text-xs [&>svg:not([class*='size-'])]:size-3.5 has-[>svg]:px-2",
120
- sm: "h-8 rounded-lg px-2.5 gap-1.5 text-xs has-[>svg]:px-2.5",
121
- "icon-xs": "size-7 rounded-lg p-0 has-[>svg]:p-0",
122
- "icon-sm": "size-8 rounded-lg p-0 has-[>svg]:p-0",
119
+ xs: "h-7 gap-1 rounded-lg px-2 text-xs [&>svg:not([class*='size-'])]:size-3.5 has-[>svg]:px-2 max-sm:hit-target",
120
+ sm: "h-8 rounded-lg px-2.5 gap-1.5 text-xs has-[>svg]:px-2.5 max-sm:hit-target",
121
+ "icon-xs": "size-7 rounded-lg p-0 has-[>svg]:p-0 max-sm:hit-target",
122
+ "icon-sm": "size-8 rounded-lg p-0 has-[>svg]:p-0 max-sm:hit-target",
123
123
  };
124
124
 
125
125
  const inputGroupButtonVariants = cva(inputGroupButtonBaseClasses, {
@@ -15,7 +15,7 @@ export interface PopoverConfig {
15
15
  classes?: { trigger?: string; content?: string };
16
16
  /** Default for `PopoverContent` `sideOffset`. */
17
17
  sideOffset?: number;
18
- /** Default for `PopoverContent` `collisionPadding`. */
18
+ /** Default for `PopoverContent` `collisionPadding` (built-in: `8`). */
19
19
  collisionPadding?: PopoverContentProps["collisionPadding"];
20
20
  }
21
21
 
@@ -40,22 +40,20 @@ const PopoverContent = React.forwardRef<
40
40
  React.ComponentRef<typeof PopoverPrimitive.Content>,
41
41
  PopoverContentProps & {
42
42
  /**
43
- * Grow from the trigger, keep 8px from the viewport edge (unless
44
- * `collisionPadding` is set) and, on small screens, cap width and height.
43
+ * Grow from the trigger and, on small screens, cap width and height.
45
44
  */
46
45
  fitViewport?: boolean;
47
46
  }
48
47
  >(({ className, align = "center", sideOffset, fitViewport, collisionPadding, ...props }, ref) => {
49
48
  const config = useUiConfig("Popover");
50
49
  const merge = useCn();
51
- const padding = collisionPadding ?? config?.collisionPadding;
52
50
  return (
53
51
  <PopoverPrimitive.Portal>
54
52
  <PopoverPrimitive.Content
55
53
  ref={ref}
56
54
  align={align}
57
55
  sideOffset={sideOffset ?? config?.sideOffset ?? 6}
58
- collisionPadding={fitViewport ? (padding ?? 8) : padding}
56
+ collisionPadding={collisionPadding ?? config?.collisionPadding ?? 8}
59
57
  className={merge(
60
58
  config?.classes?.content ?? [
61
59
  "z-50 w-72 max-sm:max-w-[calc(100vw-2rem)] max-sm:max-h-[85dvh] max-sm:overflow-y-auto p-4 outline-none",
@@ -7,7 +7,7 @@ import { Kbd } from "./kbd";
7
7
  import { useCn, useUiConfig } from "./ui-config";
8
8
 
9
9
  const sizeClasses = {
10
- sm: { input: "h-8 pl-8 text-sm", icon: "left-2" },
10
+ sm: { input: "h-8 pl-8 text-base sm:text-sm", icon: "left-2" },
11
11
  md: { input: "h-10 pl-9", icon: "left-3" },
12
12
  };
13
13
 
package/src/ui/select.tsx CHANGED
@@ -33,9 +33,9 @@ export interface SelectConfig {
33
33
  /** `SelectItem` indicator. */
34
34
  check?: React.ReactNode;
35
35
  };
36
- /** Adds `data-slot="select-trigger"` to the trigger, for parent selectors such as `ButtonGroup`'s. */
36
+ /** Adds `data-slot="select-trigger"` to the trigger, for parent selectors such as `ButtonGroup`'s (built-in: `true`). */
37
37
  triggerSlot?: boolean;
38
- /** Default for `SelectContent` `collisionPadding`. */
38
+ /** Default for `SelectContent` `collisionPadding` (built-in: `8`). */
39
39
  collisionPadding?: number | Partial<Record<"top" | "right" | "bottom" | "left", number>>;
40
40
  }
41
41
 
@@ -52,7 +52,7 @@ const SelectTrigger = React.forwardRef<
52
52
  return (
53
53
  <SelectPrimitive.Trigger
54
54
  ref={ref}
55
- data-slot={config?.triggerSlot ? "select-trigger" : undefined}
55
+ data-slot={(config?.triggerSlot ?? true) ? "select-trigger" : undefined}
56
56
  className={merge(
57
57
  config?.classes?.trigger ?? [
58
58
  "flex h-10 w-full max-sm:min-w-0 items-center justify-between whitespace-nowrap rounded-field border border-border bg-field-background px-3.5 py-2 text-base sm:text-sm ring-offset-background placeholder:text-field-placeholder transition-[border-color,box-shadow,background-color] duration-200 ease-smooth disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
@@ -127,10 +127,10 @@ const SelectContent = React.forwardRef<
127
127
  <SelectPrimitive.Portal>
128
128
  <SelectPrimitive.Content
129
129
  ref={ref}
130
- collisionPadding={collisionPadding ?? config?.collisionPadding}
130
+ collisionPadding={collisionPadding ?? config?.collisionPadding ?? 8}
131
131
  className={merge(
132
132
  classes?.content ?? [
133
- "relative z-50 max-h-96 min-w-32 overflow-hidden outline-none",
133
+ "relative z-50 max-h-96 max-sm:max-h-[85dvh] min-w-32 overflow-hidden outline-none",
134
134
  floatingSurfaceClass,
135
135
  floatingSurfaceAnimateClass,
136
136
  ],
package/src/ui/sonner.tsx CHANGED
@@ -135,6 +135,9 @@ function createToasterClassNames({
135
135
  // `unstyled` drops sonner's `[data-content]` grow, so the text column grows
136
136
  // here and the action and cancel buttons sit at the right edge.
137
137
  content: "flex min-w-0 grow flex-col",
138
+ // `unstyled` also drops sonner's `position: relative` on `[data-icon]`, so
139
+ // the absolutely positioned `.sonner-loader` anchors here, not to the toast.
140
+ icon: "relative",
138
141
  title: titleLeading === "5" ? "font-medium leading-5" : "font-medium leading-snug",
139
142
  description: descriptionMuted
140
143
  ? `${descriptionSize} leading-snug text-muted-foreground!`
@@ -10,7 +10,7 @@ export interface TooltipConfig {
10
10
  delayDuration?: number;
11
11
  /** Default for `TooltipContent` `sideOffset`. */
12
12
  sideOffset?: number;
13
- /** Default for `TooltipContent` `portal`. */
13
+ /** Default for `TooltipContent` `portal` (built-in: `true`). */
14
14
  portal?: boolean;
15
15
  }
16
16
 
@@ -32,7 +32,7 @@ const TooltipTrigger = TooltipPrimitive.Trigger;
32
32
  const TooltipContent = React.forwardRef<
33
33
  React.ComponentRef<typeof TooltipPrimitive.Content>,
34
34
  React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> & {
35
- /** Render into `document.body` so a clipping parent cannot cut it off. */
35
+ /** Render into `document.body` so a clipping parent cannot cut it off (default `true`). */
36
36
  portal?: boolean;
37
37
  }
38
38
  >(({ className, sideOffset, portal, ...props }, ref) => {
@@ -50,7 +50,7 @@ const TooltipContent = React.forwardRef<
50
50
  {...props}
51
51
  />
52
52
  );
53
- return (portal ?? config?.portal) ? (
53
+ return (portal ?? config?.portal ?? true) ? (
54
54
  <TooltipPrimitive.Portal>{content}</TooltipPrimitive.Portal>
55
55
  ) : (
56
56
  content