-
Notifications
You must be signed in to change notification settings - Fork 130
Use shadcn InputGroup in ProjectSwitcher
#2810
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@inkeep/agents-manage-ui": patch | ||
| --- | ||
|
|
||
| Add InputGroup compound component and use it in ProjectSwitcher search input |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,158 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| 'use client'; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| import { cva, type VariantProps } from 'class-variance-authority'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import type * as React from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { Button } from '@/components/ui/button'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { Input } from '@/components/ui/input'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { Textarea } from '@/components/ui/textarea'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { cn } from '@/lib/utils'; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| function InputGroup({ className, ...props }: React.ComponentProps<'div'>) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||||||
| data-slot="input-group" | ||||||||||||||||||||||||||||||||||||||||||||||
| role="group" | ||||||||||||||||||||||||||||||||||||||||||||||
| className={cn( | ||||||||||||||||||||||||||||||||||||||||||||||
| 'group/input-group relative flex w-full items-center rounded-md border border-input shadow-xs transition-[color,box-shadow] outline-none dark:bg-input/30', | ||||||||||||||||||||||||||||||||||||||||||||||
| 'h-9 min-w-0 has-[>textarea]:h-auto', | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Variants based on alignment. | ||||||||||||||||||||||||||||||||||||||||||||||
| 'has-[>[data-align=inline-start]]:[&>input]:pl-2', | ||||||||||||||||||||||||||||||||||||||||||||||
| 'has-[>[data-align=inline-end]]:[&>input]:pr-2', | ||||||||||||||||||||||||||||||||||||||||||||||
| 'has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3', | ||||||||||||||||||||||||||||||||||||||||||||||
| 'has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3', | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Focus state. | ||||||||||||||||||||||||||||||||||||||||||||||
| 'has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-[3px] has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50', | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Error state. | ||||||||||||||||||||||||||||||||||||||||||||||
| 'has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40', | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| className | ||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||
| {...props} | ||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const inputGroupAddonVariants = cva( | ||||||||||||||||||||||||||||||||||||||||||||||
| "flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4", | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| variants: { | ||||||||||||||||||||||||||||||||||||||||||||||
| align: { | ||||||||||||||||||||||||||||||||||||||||||||||
| 'inline-start': 'order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]', | ||||||||||||||||||||||||||||||||||||||||||||||
| 'inline-end': 'order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]', | ||||||||||||||||||||||||||||||||||||||||||||||
| 'block-start': | ||||||||||||||||||||||||||||||||||||||||||||||
| 'order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-2.5 [.border-b]:pb-3', | ||||||||||||||||||||||||||||||||||||||||||||||
| 'block-end': | ||||||||||||||||||||||||||||||||||||||||||||||
| 'order-last w-full justify-start px-3 pb-3 group-has-[>input]/input-group:pb-2.5 [.border-t]:pt-3', | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| defaultVariants: { | ||||||||||||||||||||||||||||||||||||||||||||||
| align: 'inline-start', | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| function InputGroupAddon({ | ||||||||||||||||||||||||||||||||||||||||||||||
| className, | ||||||||||||||||||||||||||||||||||||||||||||||
| align = 'inline-start', | ||||||||||||||||||||||||||||||||||||||||||||||
| ...props | ||||||||||||||||||||||||||||||||||||||||||||||
| }: React.ComponentProps<'div'> & VariantProps<typeof inputGroupAddonVariants>) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||
| // biome-ignore lint/a11y/useKeyWithClickEvents: use official shadcn example, todo: maybe refactor in the future | ||||||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||||||
| role="group" | ||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Minor: Redundant Issue: Why: Using incorrect ARIA roles can confuse assistive technology users about the element's purpose. A Fix: Remove
Suggested change
Refs: |
||||||||||||||||||||||||||||||||||||||||||||||
| data-slot="input-group-addon" | ||||||||||||||||||||||||||||||||||||||||||||||
| data-align={align} | ||||||||||||||||||||||||||||||||||||||||||||||
| className={cn(inputGroupAddonVariants({ align }), className)} | ||||||||||||||||||||||||||||||||||||||||||||||
| onClick={(e) => { | ||||||||||||||||||||||||||||||||||||||||||||||
| if ((e.target as HTMLElement).closest('button')) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| e.currentTarget.parentElement?.querySelector('input')?.focus(); | ||||||||||||||||||||||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||||||||||||||||||||||
| {...props} | ||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const inputGroupButtonVariants = cva('flex items-center gap-2 text-sm shadow-none', { | ||||||||||||||||||||||||||||||||||||||||||||||
| variants: { | ||||||||||||||||||||||||||||||||||||||||||||||
| size: { | ||||||||||||||||||||||||||||||||||||||||||||||
| xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-2 has-[>svg]:px-2 [&>svg:not([class*='size-'])]:size-3.5", | ||||||||||||||||||||||||||||||||||||||||||||||
| sm: 'h-8 gap-1.5 rounded-md px-2.5 has-[>svg]:px-2.5', | ||||||||||||||||||||||||||||||||||||||||||||||
| 'icon-xs': 'size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0', | ||||||||||||||||||||||||||||||||||||||||||||||
| 'icon-sm': 'size-8 p-0 has-[>svg]:p-0', | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| defaultVariants: { | ||||||||||||||||||||||||||||||||||||||||||||||
| size: 'xs', | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| function InputGroupButton({ | ||||||||||||||||||||||||||||||||||||||||||||||
| className, | ||||||||||||||||||||||||||||||||||||||||||||||
| type = 'button', | ||||||||||||||||||||||||||||||||||||||||||||||
| variant = 'ghost', | ||||||||||||||||||||||||||||||||||||||||||||||
| size = 'xs', | ||||||||||||||||||||||||||||||||||||||||||||||
| ...props | ||||||||||||||||||||||||||||||||||||||||||||||
| }: Omit<React.ComponentProps<typeof Button>, 'size'> & | ||||||||||||||||||||||||||||||||||||||||||||||
| VariantProps<typeof inputGroupButtonVariants>) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||
| <Button | ||||||||||||||||||||||||||||||||||||||||||||||
| type={type} | ||||||||||||||||||||||||||||||||||||||||||||||
| data-size={size} | ||||||||||||||||||||||||||||||||||||||||||||||
| variant={variant} | ||||||||||||||||||||||||||||||||||||||||||||||
| className={cn(inputGroupButtonVariants({ size }), className)} | ||||||||||||||||||||||||||||||||||||||||||||||
| {...props} | ||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| function InputGroupText({ className, ...props }: React.ComponentProps<'span'>) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||
| <span | ||||||||||||||||||||||||||||||||||||||||||||||
| className={cn( | ||||||||||||||||||||||||||||||||||||||||||||||
| "flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4", | ||||||||||||||||||||||||||||||||||||||||||||||
| className | ||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||
| {...props} | ||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+113
to
+122
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💭 Consider: Add Issue: Why: Most compound component parts use Fix: Consider adding
Suggested change
Refs: |
||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| function InputGroupInput({ className, ...props }: React.ComponentProps<'input'>) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||
| <Input | ||||||||||||||||||||||||||||||||||||||||||||||
| data-slot="input-group-control" | ||||||||||||||||||||||||||||||||||||||||||||||
| className={cn( | ||||||||||||||||||||||||||||||||||||||||||||||
| 'flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent', | ||||||||||||||||||||||||||||||||||||||||||||||
| className | ||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||
| {...props} | ||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| function InputGroupTextarea({ className, ...props }: React.ComponentProps<'textarea'>) { | ||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||
| <Textarea | ||||||||||||||||||||||||||||||||||||||||||||||
| data-slot="input-group-control" | ||||||||||||||||||||||||||||||||||||||||||||||
| className={cn( | ||||||||||||||||||||||||||||||||||||||||||||||
| 'flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent', | ||||||||||||||||||||||||||||||||||||||||||||||
| className | ||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||
| {...props} | ||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| export { | ||||||||||||||||||||||||||||||||||||||||||||||
| InputGroup, | ||||||||||||||||||||||||||||||||||||||||||||||
| InputGroupAddon, | ||||||||||||||||||||||||||||||||||||||||||||||
| InputGroupButton, | ||||||||||||||||||||||||||||||||||||||||||||||
| InputGroupText, | ||||||||||||||||||||||||||||||||||||||||||||||
| InputGroupInput, | ||||||||||||||||||||||||||||||||||||||||||||||
| InputGroupTextarea, | ||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The checked-out file shows this import ended up on line 20, after
@/lib/query/projects. Biome'sorganizeImportsexpects@/components/ui/input-groupto sort before@/components/ui/sidebar. Runpnpm formatto auto-fix.