11'use client'
22
3- import { useCallback , useEffect , useMemo , useState } from 'react'
3+ import { useCallback , useEffect , useId , useMemo , useState } from 'react'
44import {
55 Badge ,
66 Chip ,
77 ChipCombobox ,
88 ChipInput ,
9- ChipTextarea ,
9+ ChipModalField ,
1010 type ComboboxOption ,
11- cn ,
12- Label ,
1311 Skeleton ,
1412} from '@sim/emcn'
1513import { createLogger } from '@sim/logger'
@@ -133,6 +131,7 @@ export function McpDeploy({
133131 onActiveServerChange,
134132} : McpDeployProps ) {
135133 const params = useParams ( )
134+ const toolNameId = useId ( )
136135 const workspaceId = params . workspaceId as string
137136 const [ showCreateModal , setShowCreateModal ] = useState ( false )
138137
@@ -480,7 +479,7 @@ export function McpDeploy({
480479
481480 if ( isLoadingServers || ( isLoadingDeployedState && ! deployedState ) ) {
482481 return (
483- < div className = '-mx-1 space-y-4 px-1 ' >
482+ < div className = 'space-y-4 px-2 ' >
484483 < div className = 'space-y-3' >
485484 < div >
486485 < Skeleton className = 'mb-[6.5px] h-[16px] w-[70px]' />
@@ -522,7 +521,7 @@ export function McpDeploy({
522521 return (
523522 < form
524523 id = 'mcp-deploy-form'
525- className = '-mx-1 space-y-3 px-1 '
524+ className = 'space-y-3'
526525 onSubmit = { ( e ) => {
527526 e . preventDefault ( )
528527 handleSave ( )
@@ -540,49 +539,41 @@ export function McpDeploy({
540539 />
541540 ) ) }
542541
543- < div >
544- < Label className = 'mb-[6.5px] block pl-0.5 text-[var(--text-primary)] text-small' >
545- Tool name
546- </ Label >
547- < ChipInput
548- value = { toolName }
549- onChange = { ( e ) => setToolName ( e . target . value ) }
550- placeholder = 'e.g., book_flight'
551- aria-invalid = { ! ! toolNameError }
552- error = { Boolean ( toolNameError ) }
553- />
554- < p
555- className = { cn (
556- 'mt-[6.5px] text-xs' ,
557- toolNameError ? 'text-[var(--text-error)]' : 'text-[var(--text-secondary)]'
558- ) }
559- >
560- { toolNameError ?? 'Use lowercase letters, numbers, and underscores only' }
561- </ p >
562- </ div >
563-
564- < div >
565- < Label className = 'mb-[6.5px] block pl-0.5 text-[var(--text-primary)] text-small' >
566- Description
567- </ Label >
568- < ChipTextarea
569- placeholder = {
570- workflowDescriptionFallback
571- ? `Defaults to the workflow description: ${ workflowDescriptionFallback } `
572- : 'Describe what this tool does...'
573- }
574- className = 'min-h-[100px]'
575- value = { toolDescription }
576- onChange = { ( e ) => setToolDescription ( e . target . value ) }
577- />
578- </ div >
542+ < ChipModalField
543+ type = 'custom'
544+ title = 'Tool name'
545+ htmlFor = { toolNameId }
546+ error = { toolNameError }
547+ hint = 'Use lowercase letters, numbers, and underscores only'
548+ >
549+ { ( aria ) => (
550+ < ChipInput
551+ id = { toolNameId }
552+ value = { toolName }
553+ onChange = { ( e ) => setToolName ( e . target . value ) }
554+ placeholder = 'e.g., book_flight'
555+ error = { Boolean ( toolNameError ) }
556+ { ...aria }
557+ />
558+ ) }
559+ </ ChipModalField >
560+
561+ < ChipModalField
562+ type = 'textarea'
563+ title = 'Description'
564+ placeholder = {
565+ workflowDescriptionFallback
566+ ? `Defaults to the workflow description: ${ workflowDescriptionFallback } `
567+ : 'Describe what this tool does...'
568+ }
569+ minHeight = { 100 }
570+ value = { toolDescription }
571+ onChange = { setToolDescription }
572+ />
579573
580574 { inputFormat . length > 0 && (
581- < div >
582- < Label className = 'mb-[6.5px] block pl-0.5 text-[var(--text-primary)] text-small' >
583- Parameters ({ inputFormat . length } )
584- </ Label >
585- < p className = 'mb-[6.5px] pl-0.5 text-[var(--text-secondary)] text-xs' >
575+ < ChipModalField type = 'custom' title = { `Parameters (${ inputFormat . length } )` } >
576+ < p className = 'pl-0.5 text-[var(--text-secondary)] text-xs' >
586577 Descriptions default to your Start block inputs; edit to override for this tool.
587578 </ p >
588579 < div className = 'flex flex-col gap-2' >
@@ -602,60 +593,61 @@ export function McpDeploy({
602593 </ div >
603594 </ div >
604595 < div className = 'rounded-b-[4px] border-[var(--border-1)] border-t bg-[var(--surface-2)] px-2.5 pt-1.5 pb-2.5' >
605- < div className = 'flex flex-col gap-1.5' >
606- < Label className = 'text-small' > Description</ Label >
607- < ChipInput
608- value = {
609- parameterDescriptions [ field . name ] ??
610- startBlockDescriptions [ field . name ] ??
611- ''
612- }
613- onChange = { ( e ) =>
614- setParameterDescriptions ( ( prev ) => ( {
615- ...prev ,
616- [ field . name ] : e . target . value ,
617- } ) )
618- }
619- placeholder = { startBlockDescriptions [ field . name ] || `Describe ${ field . name } ` }
620- />
621- </ div >
596+ < ChipModalField
597+ type = 'input'
598+ title = 'Description'
599+ flush
600+ value = {
601+ parameterDescriptions [ field . name ] ?? startBlockDescriptions [ field . name ] ?? ''
602+ }
603+ onChange = { ( value ) =>
604+ setParameterDescriptions ( ( prev ) => ( {
605+ ...prev ,
606+ [ field . name ] : value ,
607+ } ) )
608+ }
609+ placeholder = { startBlockDescriptions [ field . name ] || `Describe ${ field . name } ` }
610+ />
622611 </ div >
623612 </ div >
624613 ) ) }
625614 </ div >
626- </ div >
615+ </ ChipModalField >
627616 ) }
628617
629- < div >
630- < Label className = 'mb-[6.5px] block pl-0.5 text-[var(--text-primary)] text-small' >
631- Servers
632- </ Label >
633- < ChipCombobox
634- options = { serverOptions }
635- multiSelect
636- multiSelectValues = { selectedServerIdsForForm }
637- onMultiSelectChange = { handleServerSelectionChange }
638- placeholder = 'Select servers...'
639- searchable
640- searchPlaceholder = 'Search servers...'
641- disabled = { ! toolName . trim ( ) || ! ! toolNameError || isPending }
642- overlayContent = {
643- < span className = 'truncate text-[var(--text-primary)]' > { selectedServersLabel } </ span >
644- }
645- />
646- { ! toolName . trim ( ) ? (
647- < p className = 'mt-[6.5px] text-[var(--text-secondary)] text-xs' >
648- Enter a tool name to select servers
649- </ p >
650- ) : toolNameError ? (
651- < p className = 'mt-[6.5px] text-[var(--text-secondary)] text-xs' >
652- Fix the tool name to select servers
653- </ p >
654- ) : null }
655- </ div >
618+ < ChipModalField
619+ type = 'custom'
620+ title = 'Servers'
621+ submitOnEnter = { false }
622+ hint = {
623+ ! toolName . trim ( )
624+ ? 'Enter a tool name to select servers'
625+ : toolNameError
626+ ? 'Fix the tool name to select servers'
627+ : undefined
628+ }
629+ >
630+ { ( aria ) => (
631+ < ChipCombobox
632+ aria-label = 'Servers'
633+ { ...aria }
634+ options = { serverOptions }
635+ multiSelect
636+ multiSelectValues = { selectedServerIdsForForm }
637+ onMultiSelectChange = { handleServerSelectionChange }
638+ placeholder = 'Select servers...'
639+ searchable
640+ searchPlaceholder = 'Search servers...'
641+ disabled = { ! toolName . trim ( ) || ! ! toolNameError || isPending }
642+ overlayContent = {
643+ < span className = 'truncate text-[var(--text-primary)]' > { selectedServersLabel } </ span >
644+ }
645+ />
646+ ) }
647+ </ ChipModalField >
656648
657649 { saveErrors . length > 0 && (
658- < div className = 'mt-[6.5px] flex flex-col gap-0.5' >
650+ < div className = 'mt-[6.5px] flex flex-col gap-0.5 px-2 ' >
659651 { saveErrors . map ( ( error ) => (
660652 < p key = { error } className = 'text-[var(--text-error)] text-caption' >
661653 { error }
0 commit comments