@@ -14,10 +14,9 @@ import {
1414 * Manage a Space's base directories.
1515 *
1616 * A base dir scopes any workspace root opened at or under it to this Space:
17- * an unmapped folder there falls back to this Space's Starter set, and the
18- * self-optimize meta-tools + mapping popup restrict to this Space. Longest
19- * match wins when base dirs nest across Spaces, and a folder can belong to
20- * only one Space.
17+ * an unmapped folder there uses this Space's tools, and self-optimize stays
18+ * in this Space. Longest match wins when base dirs nest, and a folder can
19+ * belong to only one Space.
2120 */
2221export function SpaceBaseDirsModal ( {
2322 space,
@@ -29,7 +28,7 @@ export function SpaceBaseDirsModal({
2928 const [ dirs , setDirs ] = useState < SpaceBaseDir [ ] > ( [ ] ) ;
3029 const [ loading , setLoading ] = useState ( false ) ;
3130 const [ busy , setBusy ] = useState ( false ) ;
32- const { toasts, success , error : showError , dismiss } = useToast ( ) ;
31+ const { toasts, error : showError , dismiss } = useToast ( ) ;
3332
3433 const spaceId = space ?. id ?? null ;
3534
@@ -66,26 +65,18 @@ export function SpaceBaseDirsModal({
6665 return ;
6766 }
6867 const paths = Array . isArray ( picked ) ? picked : picked ? [ picked ] : [ ] ;
69- if ( paths . length === 0 ) return ;
68+ if ( paths . length === 0 ) return ; // cancelled — nothing added
7069
7170 setBusy ( true ) ;
72- let added = 0 ;
7371 for ( const p of paths ) {
7472 try {
7573 await addSpaceBaseDir ( spaceId , p ) ;
76- added ++ ;
7774 } catch ( e ) {
7875 showError ( 'Could not add folder' , e instanceof Error ? e . message : String ( e ) ) ;
7976 }
8077 }
8178 await load ( ) ;
8279 setBusy ( false ) ;
83- if ( added > 0 ) {
84- success (
85- added === 1 ? 'Base directory added' : `${ added } base directories added` ,
86- 'Folders here are now scoped to this space.'
87- ) ;
88- }
8980 } ;
9081
9182 const handleRemove = async ( dir : SpaceBaseDir ) => {
@@ -109,10 +100,11 @@ export function SpaceBaseDirsModal({
109100 onClick = { onClose }
110101 >
111102 < div
112- className = "animate-slide-up flex max-h-[80vh] w-full max-w-lg flex-col rounded-2xl border border-[rgb(var(--border))] bg-[rgb(var(--background))] shadow-2xl"
103+ className = "flex max-h-[80vh] w-full max-w-lg flex-col rounded-2xl border border-[rgb(var(--border))] bg-[rgb(var(--background))] shadow-2xl"
113104 onClick = { ( e ) => e . stopPropagation ( ) }
114105 data-testid = "space-base-dirs-modal"
115106 >
107+ { /* Header */ }
116108 < div className = "flex items-start justify-between border-b border-[rgb(var(--border-subtle))] p-5" >
117109 < div className = "flex items-center gap-3" >
118110 < div className = "flex h-10 w-10 items-center justify-center rounded-lg border border-[rgb(var(--border-subtle))] bg-[rgb(var(--surface))] text-xl" >
@@ -121,77 +113,95 @@ export function SpaceBaseDirsModal({
121113 < div >
122114 < h2 className = "text-lg font-semibold" > Base directories</ h2 >
123115 < p className = "text-xs text-[rgb(var(--muted))]" >
124- Folders scoped to < span className = "font-medium" > { space . name } </ span >
116+ Scoped to < span className = "font-medium" > { space . name } </ span >
125117 </ p >
126118 </ div >
127119 </ div >
128120 < button
129121 onClick = { onClose }
130122 className = "rounded-lg p-1.5 text-[rgb(var(--muted))] transition-colors hover:bg-[rgb(var(--surface))] hover:text-[rgb(var(--foreground))]"
131123 aria-label = "Close"
124+ data-testid = "space-base-dirs-close"
132125 >
133126 < X className = "h-5 w-5" />
134127 </ button >
135128 </ div >
136129
130+ { /* Body */ }
137131 < div className = "min-h-0 flex-1 overflow-y-auto p-5" >
138132 < p className = "mb-4 text-sm text-[rgb(var(--muted))]" >
139- Any folder you open here (or under it) is scoped to this space — it uses this
140- space's tools by default, and self-optimize only sees this space. The most specific
141- base directory wins, and a folder can belong to only one space.
133+ Folders you open here (or under them) are scoped to this space.
142134 </ p >
143135
144136 { loading ? (
145- < div className = "flex items-center justify-center py-10 text-[rgb(var(--muted))]" >
137+ < div className = "flex items-center justify-center py-8 text-[rgb(var(--muted))]" >
146138 < Loader2 className = "h-5 w-5 animate-spin" />
147139 </ div >
148- ) : dirs . length === 0 ? (
149- < div className = "rounded-xl border border-dashed border-[rgb(var(--border))] px-4 py-8 text-center text-sm text-[rgb(var(--muted))]" >
150- No base directories yet. Add one to scope its folders to this space.
151- </ div >
152140 ) : (
153- < ul className = "space-y-2" data-testid = "space-base-dirs-list" >
154- { dirs . map ( ( dir ) => (
155- < li
156- key = { dir . id }
157- className = "flex items-center gap-3 rounded-xl border border-[rgb(var(--border-subtle))] bg-[rgb(var(--surface))] px-3 py-2.5"
158- >
159- < FolderOpen className = "text-primary-500 h-4 w-4 flex-shrink-0" />
160- < span
161- className = "min-w-0 flex-1 truncate font-mono text-xs text-[rgb(var(--foreground))]"
162- title = { dir . path }
163- >
164- { dir . path }
165- </ span >
166- < button
167- onClick = { ( ) => handleRemove ( dir ) }
168- disabled = { busy }
169- className = "flex-shrink-0 rounded-lg p-1.5 text-[rgb(var(--muted))] transition-colors hover:bg-red-50 hover:text-red-500 disabled:opacity-50 dark:hover:bg-red-900/20"
170- title = "Remove base directory"
171- data-testid = { `remove-base-dir-${ dir . id } ` }
172- >
173- < Trash2 className = "h-4 w-4" />
174- </ button >
175- </ li >
176- ) ) }
177- </ ul >
141+ < >
142+ { dirs . length > 0 && (
143+ < ul className = "mb-3 space-y-2" data-testid = "space-base-dirs-list" >
144+ { dirs . map ( ( dir ) => (
145+ < li
146+ key = { dir . id }
147+ className = "flex items-center gap-3 rounded-xl border border-[rgb(var(--border-subtle))] bg-[rgb(var(--surface))] px-3 py-2.5"
148+ >
149+ < FolderOpen className = "text-primary-500 h-4 w-4 flex-shrink-0" />
150+ < span
151+ className = "min-w-0 flex-1 truncate font-mono text-xs text-[rgb(var(--foreground))]"
152+ title = { dir . path }
153+ >
154+ { dir . path }
155+ </ span >
156+ < button
157+ onClick = { ( ) => handleRemove ( dir ) }
158+ disabled = { busy }
159+ className = "flex-shrink-0 rounded-lg p-1.5 text-[rgb(var(--muted))] transition-colors hover:bg-red-50 hover:text-red-500 disabled:opacity-50 dark:hover:bg-red-900/20"
160+ title = "Remove this folder"
161+ aria-label = { `Remove ${ dir . path } ` }
162+ data-testid = { `remove-base-dir-${ dir . id } ` }
163+ >
164+ < Trash2 className = "h-4 w-4" />
165+ </ button >
166+ </ li >
167+ ) ) }
168+ </ ul >
169+ ) }
170+
171+ { /* Add row — a clearly optional action, not the only way out. */ }
172+ < button
173+ type = "button"
174+ onClick = { handleAdd }
175+ disabled = { busy }
176+ className = "hover:border-primary-400 hover:text-primary-600 dark:hover:text-primary-400 flex w-full items-center justify-center gap-2 rounded-xl border border-dashed border-[rgb(var(--border))] px-3 py-3 text-sm font-medium text-[rgb(var(--muted))] transition-colors disabled:opacity-50"
177+ data-testid = "add-base-dir-btn"
178+ >
179+ { busy ? (
180+ < Loader2 className = "h-4 w-4 animate-spin" />
181+ ) : (
182+ < FolderPlus className = "h-4 w-4" />
183+ ) }
184+ Add folder…
185+ </ button >
186+
187+ { dirs . length === 0 && ! busy && (
188+ < p className = "mt-3 text-center text-xs text-[rgb(var(--muted))]" >
189+ No base directories yet.
190+ </ p >
191+ ) }
192+ </ >
178193 ) }
179194 </ div >
180195
181- < div className = "border-t border-[rgb(var(--border-subtle))] p-5" >
196+ { /* Footer — close without adding. */ }
197+ < div className = "flex justify-end border-t border-[rgb(var(--border-subtle))] p-4" >
182198 < Button
183199 variant = "primary"
184- className = "w-full"
185- onClick = { handleAdd }
186- disabled = { busy }
187- data-testid = "add-base-dir-btn"
200+ onClick = { onClose }
201+ className = "px-6"
202+ data-testid = "space-base-dirs-done"
188203 >
189- { busy ? (
190- < Loader2 className = "mr-2 h-4 w-4 animate-spin" />
191- ) : (
192- < FolderPlus className = "mr-2 h-4 w-4" />
193- ) }
194- Add folder…
204+ Done
195205 </ Button >
196206 </ div >
197207 </ div >
0 commit comments