@gmickel/gno 0.35.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gmickel/gno",
3
- "version": "0.35.0",
3
+ "version": "0.36.0",
4
4
  "description": "Local semantic search for your documents. Index Markdown, PDF, and Office files with hybrid BM25 + vector search.",
5
5
  "keywords": [
6
6
  "embeddings",
@@ -220,7 +220,8 @@ function AppContent({
220
220
  }
221
221
 
222
222
  function App() {
223
- const initialLocation = window.location.pathname + window.location.search;
223
+ const initialLocation =
224
+ window.location.pathname + window.location.search + window.location.hash;
224
225
  const [workspace, setWorkspace] = useState<WorkspaceState>(() =>
225
226
  loadWorkspaceState(initialLocation)
226
227
  );
@@ -231,7 +232,8 @@ function App() {
231
232
  const location = activeTab?.location ?? "/";
232
233
 
233
234
  useEffect(() => {
234
- const currentLocation = window.location.pathname + window.location.search;
235
+ const currentLocation =
236
+ window.location.pathname + window.location.search + window.location.hash;
235
237
  if (location !== currentLocation) {
236
238
  window.history.replaceState({}, "", location);
237
239
  }
@@ -242,7 +244,9 @@ function App() {
242
244
  setWorkspace((current) =>
243
245
  updateActiveTabLocation(
244
246
  current,
245
- window.location.pathname + window.location.search
247
+ window.location.pathname +
248
+ window.location.search +
249
+ window.location.hash
246
250
  )
247
251
  );
248
252
  };
@@ -43,6 +43,19 @@ export function BrowseDetailPane({
43
43
  selectedPath: string;
44
44
  total: number;
45
45
  }) {
46
+ const formatModified = (value?: string) => {
47
+ if (!value) return "—";
48
+ try {
49
+ return new Date(value).toLocaleDateString("en-US", {
50
+ month: "short",
51
+ day: "numeric",
52
+ year: "numeric",
53
+ });
54
+ } catch {
55
+ return value;
56
+ }
57
+ };
58
+
46
59
  if (docsLoading && docs.length === 0) {
47
60
  return (
48
61
  <div className="flex flex-col items-center justify-center gap-4 py-20">
@@ -107,7 +120,8 @@ export function BrowseDetailPane({
107
120
  <Table className="table-fixed">
108
121
  <TableHeader>
109
122
  <TableRow>
110
- <TableHead className="w-[68%]">Document</TableHead>
123
+ <TableHead className="w-[56%]">Document</TableHead>
124
+ <TableHead className="w-[130px]">Modified</TableHead>
111
125
  <TableHead className="w-[220px]">Collection</TableHead>
112
126
  <TableHead className="w-[72px] text-right">Type</TableHead>
113
127
  </TableRow>
@@ -151,6 +165,9 @@ export function BrowseDetailPane({
151
165
  <ChevronRight className="ml-auto size-4 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100" />
152
166
  </div>
153
167
  </TableCell>
168
+ <TableCell className="align-top whitespace-normal text-muted-foreground text-xs">
169
+ {formatModified(doc.updatedAt)}
170
+ </TableCell>
154
171
  <TableCell className="align-top whitespace-normal">
155
172
  <Badge
156
173
  className="inline-flex min-h-[2.5rem] max-w-[180px] cursor-pointer items-center px-3 py-1 text-center whitespace-normal break-words font-mono text-xs leading-tight transition-colors hover:border-primary hover:text-primary"
@@ -158,7 +158,19 @@ export function QuickSwitcher({
158
158
  return () => clearTimeout(timer);
159
159
  }, [open, query]);
160
160
 
161
- const recentItems = useMemo(() => recentDocs.slice(0, 6), [recentDocs]);
161
+ const recentItems = useMemo(() => {
162
+ const seenHref = new Set<string>();
163
+ const seenUri = new Set<string>();
164
+ return recentDocs
165
+ .filter((doc) => {
166
+ if (seenHref.has(doc.href) || seenUri.has(doc.uri)) return false;
167
+ seenHref.add(doc.href);
168
+ seenUri.add(doc.uri);
169
+ return true;
170
+ })
171
+ .slice(0, 6);
172
+ }, [recentDocs]);
173
+ const normalizedQuery = query.trim().toLowerCase();
162
174
  const favoriteDocItems = useMemo(
163
175
  () => favoriteDocs.slice(0, 6),
164
176
  [favoriteDocs]
@@ -167,12 +179,63 @@ export function QuickSwitcher({
167
179
  () => favoriteCollections.slice(0, 6),
168
180
  [favoriteCollections]
169
181
  );
182
+ const filteredRecentItems = useMemo(
183
+ () =>
184
+ recentItems.filter(
185
+ (item) =>
186
+ !normalizedQuery ||
187
+ item.label.toLowerCase().includes(normalizedQuery) ||
188
+ item.uri.toLowerCase().includes(normalizedQuery)
189
+ ),
190
+ [normalizedQuery, recentItems]
191
+ );
192
+ const filteredFavoriteDocItems = useMemo(
193
+ () =>
194
+ favoriteDocItems.filter(
195
+ (item) =>
196
+ !normalizedQuery ||
197
+ item.label.toLowerCase().includes(normalizedQuery) ||
198
+ item.uri.toLowerCase().includes(normalizedQuery)
199
+ ),
200
+ [favoriteDocItems, normalizedQuery]
201
+ );
202
+ const filteredFavoriteCollectionItems = useMemo(
203
+ () =>
204
+ favoriteCollectionItems.filter(
205
+ (item) =>
206
+ !normalizedQuery || item.label.toLowerCase().includes(normalizedQuery)
207
+ ),
208
+ [favoriteCollectionItems, normalizedQuery]
209
+ );
170
210
  const workspaceActions = useMemo(
171
211
  () => getWorkspaceActions({ location }),
172
212
  [location]
173
213
  );
214
+ const matchingWorkspaceActions = useMemo(
215
+ () =>
216
+ workspaceActions.filter((action) => {
217
+ if (
218
+ ["new-note", "new-note-in-context", "create-folder-here"].includes(
219
+ action.id
220
+ )
221
+ ) {
222
+ return true;
223
+ }
224
+ if (!normalizedQuery) {
225
+ return true;
226
+ }
227
+ const haystack = [
228
+ action.label,
229
+ action.description ?? "",
230
+ ...action.keywords,
231
+ ]
232
+ .join(" ")
233
+ .toLowerCase();
234
+ return haystack.includes(normalizedQuery);
235
+ }),
236
+ [normalizedQuery, workspaceActions]
237
+ );
174
238
  const exactResult = useMemo(() => {
175
- const normalizedQuery = query.trim().toLowerCase();
176
239
  if (!normalizedQuery) {
177
240
  return null;
178
241
  }
@@ -191,7 +254,7 @@ export function QuickSwitcher({
191
254
  );
192
255
  }) ?? null
193
256
  );
194
- }, [query, results]);
257
+ }, [normalizedQuery, results]);
195
258
 
196
259
  const openTarget = useCallback(
197
260
  (target: { uri: string; lineStart?: number; lineEnd?: number }) => {
@@ -234,12 +297,31 @@ export function QuickSwitcher({
234
297
  section.title.toLowerCase().includes(normalizedQuery)
235
298
  );
236
299
  }, [query, sections]);
300
+ const hasQuery = query.trim().length > 0;
301
+ const hasPriorityMatches =
302
+ filteredSections.length > 0 ||
303
+ results.length > 0 ||
304
+ filteredRecentItems.length > 0 ||
305
+ filteredFavoriteDocItems.length > 0 ||
306
+ filteredFavoriteCollectionItems.length > 0;
307
+ const commandKey = useMemo(
308
+ () =>
309
+ [
310
+ normalizedQuery || "__empty__",
311
+ filteredSections.map((section) => section.anchor).join(","),
312
+ results.map((result) => result.docid).join(","),
313
+ filteredRecentItems.map((item) => item.href).join(","),
314
+ ].join("|"),
315
+ [filteredRecentItems, filteredSections, normalizedQuery, results]
316
+ );
237
317
 
238
318
  return (
239
319
  <CommandDialog
320
+ commandKey={commandKey}
240
321
  description="Jump to notes, open recent documents, or create a new note."
241
322
  onOpenChange={onOpenChange}
242
323
  open={open}
324
+ shouldFilter={false}
243
325
  title="Quick Switcher"
244
326
  >
245
327
  <CommandInput
@@ -253,16 +335,87 @@ export function QuickSwitcher({
253
335
  {loading ? "Searching..." : "No matching documents."}
254
336
  </CommandEmpty>
255
337
 
256
- {recentItems.length > 0 && !query.trim() && (
338
+ {hasQuery && filteredSections.length > 0 && (
339
+ <CommandGroup heading="Sections">
340
+ {filteredSections.map((section) => {
341
+ const target = parseDocumentDeepLink(
342
+ location.includes("?") ? `?${location.split("?")[1] ?? ""}` : ""
343
+ );
344
+ if (!target.uri) {
345
+ return null;
346
+ }
347
+ return (
348
+ <CommandItem
349
+ key={section.anchor}
350
+ onSelect={() => {
351
+ navigate(
352
+ `${buildDocDeepLink({
353
+ uri: target.uri,
354
+ view: "rendered",
355
+ })}#${section.anchor}`
356
+ );
357
+ onOpenChange(false);
358
+ }}
359
+ value={`${section.title} section heading outline`}
360
+ >
361
+ <SearchIcon />
362
+ <span>{section.title}</span>
363
+ <CommandShortcut>{`H${section.level}`}</CommandShortcut>
364
+ </CommandItem>
365
+ );
366
+ })}
367
+ </CommandGroup>
368
+ )}
369
+
370
+ {hasQuery && results.length > 0 && (
371
+ <CommandGroup heading="Documents">
372
+ {results.map((result) => (
373
+ <CommandItem
374
+ key={result.docid}
375
+ onSelect={() =>
376
+ openTarget({
377
+ uri: result.uri,
378
+ lineStart: result.snippetRange?.startLine,
379
+ lineEnd: result.snippetRange?.endLine,
380
+ })
381
+ }
382
+ value={`${result.title ?? result.uri} ${result.uri}`}
383
+ >
384
+ {loading ? (
385
+ <Loader2Icon className="animate-spin" />
386
+ ) : (
387
+ <SearchIcon />
388
+ )}
389
+ <div className="min-w-0 flex-1">
390
+ <div className="truncate">{result.title || result.uri}</div>
391
+ <div className="truncate text-muted-foreground text-xs">
392
+ {result.uri}
393
+ </div>
394
+ </div>
395
+ {result.snippetRange && (
396
+ <CommandShortcut>
397
+ L{result.snippetRange.startLine}
398
+ {result.snippetRange.endLine !==
399
+ result.snippetRange.startLine
400
+ ? `-${result.snippetRange.endLine}`
401
+ : ""}
402
+ </CommandShortcut>
403
+ )}
404
+ </CommandItem>
405
+ ))}
406
+ </CommandGroup>
407
+ )}
408
+
409
+ {!hasQuery && filteredRecentItems.length > 0 && (
257
410
  <CommandGroup heading="Recent">
258
- {recentItems.map((item) => (
411
+ {filteredRecentItems.map((item) => (
259
412
  <CommandItem
260
413
  key={item.href}
261
414
  onSelect={() => {
262
415
  navigate(item.href);
263
416
  onOpenChange(false);
264
417
  }}
265
- value={item.label}
418
+ value={`recent-${item.href}-${item.label}`}
266
419
  >
267
420
  <FileTextIcon />
268
421
  <span>{item.label}</span>
@@ -272,34 +425,34 @@ export function QuickSwitcher({
272
425
  </CommandGroup>
273
426
  )}
274
427
 
275
- {!query.trim() &&
276
- (favoriteDocItems.length > 0 ||
277
- favoriteCollectionItems.length > 0) && (
428
+ {!hasQuery &&
429
+ (filteredFavoriteDocItems.length > 0 ||
430
+ filteredFavoriteCollectionItems.length > 0) && (
278
431
  <>
279
432
  <CommandSeparator />
280
433
  <CommandGroup heading="Favorites">
281
- {favoriteDocItems.map((item) => (
434
+ {filteredFavoriteDocItems.map((item) => (
282
435
  <CommandItem
283
436
  key={item.href}
284
437
  onSelect={() => {
285
438
  navigate(item.href);
286
439
  onOpenChange(false);
287
440
  }}
288
- value={`favorite-doc-${item.label}`}
441
+ value={`favorite-doc-${item.href}`}
289
442
  >
290
443
  <StarIcon />
291
444
  <span>{item.label}</span>
292
445
  <CommandShortcut>Doc</CommandShortcut>
293
446
  </CommandItem>
294
447
  ))}
295
- {favoriteCollectionItems.map((item) => (
448
+ {filteredFavoriteCollectionItems.map((item) => (
296
449
  <CommandItem
297
450
  key={item.href}
298
451
  onSelect={() => {
299
452
  navigate(item.href);
300
453
  onOpenChange(false);
301
454
  }}
302
- value={`favorite-collection-${item.label}`}
455
+ value={`favorite-collection-${item.href}`}
303
456
  >
304
457
  <FolderIcon />
305
458
  <span>{item.label}</span>
@@ -310,7 +463,58 @@ export function QuickSwitcher({
310
463
  </>
311
464
  )}
312
465
 
313
- {showCreateAction && (
466
+ {!hasQuery && filteredSections.length > 0 && (
467
+ <CommandGroup heading="Sections">
468
+ {filteredSections.map((section) => {
469
+ const target = parseDocumentDeepLink(
470
+ location.includes("?") ? `?${location.split("?")[1] ?? ""}` : ""
471
+ );
472
+ if (!target.uri) {
473
+ return null;
474
+ }
475
+ return (
476
+ <CommandItem
477
+ key={section.anchor}
478
+ onSelect={() => {
479
+ navigate(
480
+ `${buildDocDeepLink({
481
+ uri: target.uri,
482
+ view: "rendered",
483
+ })}#${section.anchor}`
484
+ );
485
+ onOpenChange(false);
486
+ }}
487
+ value={`${section.title} section heading outline`}
488
+ >
489
+ <SearchIcon />
490
+ <span>{section.title}</span>
491
+ <CommandShortcut>{`H${section.level}`}</CommandShortcut>
492
+ </CommandItem>
493
+ );
494
+ })}
495
+ </CommandGroup>
496
+ )}
497
+
498
+ {hasQuery && filteredRecentItems.length > 0 && (
499
+ <CommandGroup heading="Recent">
500
+ {filteredRecentItems.map((item) => (
501
+ <CommandItem
502
+ key={item.href}
503
+ onSelect={() => {
504
+ navigate(item.href);
505
+ onOpenChange(false);
506
+ }}
507
+ value={`recent-${item.href}-${item.label}`}
508
+ >
509
+ <FileTextIcon />
510
+ <span>{item.label}</span>
511
+ <CommandShortcut>Recent</CommandShortcut>
512
+ </CommandItem>
513
+ ))}
514
+ </CommandGroup>
515
+ )}
516
+
517
+ {showCreateAction && (!hasQuery || !hasPriorityMatches) && (
314
518
  <>
315
519
  <CommandGroup heading="Actions">
316
520
  {exactResult && (
@@ -338,7 +542,7 @@ export function QuickSwitcher({
338
542
  <span>Create new note</span>
339
543
  <CommandShortcut>{query.trim()}</CommandShortcut>
340
544
  </CommandItem>
341
- {workspaceActions
545
+ {matchingWorkspaceActions
342
546
  .filter((action) =>
343
547
  [
344
548
  "new-note-in-context",
@@ -360,7 +564,12 @@ export function QuickSwitcher({
360
564
  query.trim()
361
565
  )
362
566
  }
363
- value={`${action.label} ${action.keywords.join(" ")} ${query}`}
567
+ value={`${
568
+ action.id === "new-note-in-context" ||
569
+ action.id === "new-note"
570
+ ? `${action.label} ${action.keywords.join(" ")} ${query}`
571
+ : `${action.label} ${action.keywords.join(" ")}`
572
+ }`}
364
573
  >
365
574
  <FolderIcon />
366
575
  <span>{action.label}</span>
@@ -377,7 +586,7 @@ export function QuickSwitcher({
377
586
  )}
378
587
 
379
588
  <CommandGroup heading="Go To">
380
- {workspaceActions
589
+ {matchingWorkspaceActions
381
590
  .filter((action) => action.group === "Go To" && action.available)
382
591
  .map((action) => (
383
592
  <CommandItem
@@ -420,78 +629,7 @@ export function QuickSwitcher({
420
629
  </CommandGroup>
421
630
  )}
422
631
 
423
- {filteredSections.length > 0 && (
424
- <CommandGroup heading="Sections">
425
- {filteredSections.map((section) => {
426
- const target = parseDocumentDeepLink(
427
- location.includes("?") ? `?${location.split("?")[1] ?? ""}` : ""
428
- );
429
- if (!target.uri) {
430
- return null;
431
- }
432
- return (
433
- <CommandItem
434
- key={section.anchor}
435
- onSelect={() => {
436
- navigate(
437
- `${buildDocDeepLink({
438
- uri: target.uri,
439
- view: "rendered",
440
- })}#${section.anchor}`
441
- );
442
- onOpenChange(false);
443
- }}
444
- value={`${section.title} section heading outline`}
445
- >
446
- <SearchIcon />
447
- <span>{section.title}</span>
448
- <CommandShortcut>{`H${section.level}`}</CommandShortcut>
449
- </CommandItem>
450
- );
451
- })}
452
- </CommandGroup>
453
- )}
454
-
455
632
  {!query.trim() && <CommandSeparator />}
456
-
457
- {query.trim() && (
458
- <CommandGroup heading="Documents">
459
- {results.map((result) => (
460
- <CommandItem
461
- key={result.docid}
462
- onSelect={() =>
463
- openTarget({
464
- uri: result.uri,
465
- lineStart: result.snippetRange?.startLine,
466
- lineEnd: result.snippetRange?.endLine,
467
- })
468
- }
469
- value={`${result.title ?? result.uri} ${result.uri}`}
470
- >
471
- {loading ? (
472
- <Loader2Icon className="animate-spin" />
473
- ) : (
474
- <SearchIcon />
475
- )}
476
- <div className="min-w-0 flex-1">
477
- <div className="truncate">{result.title || result.uri}</div>
478
- <div className="truncate text-muted-foreground text-xs">
479
- {result.uri}
480
- </div>
481
- </div>
482
- {result.snippetRange && (
483
- <CommandShortcut>
484
- L{result.snippetRange.startLine}
485
- {result.snippetRange.endLine !==
486
- result.snippetRange.startLine
487
- ? `-${result.snippetRange.endLine}`
488
- : ""}
489
- </CommandShortcut>
490
- )}
491
- </CommandItem>
492
- ))}
493
- </CommandGroup>
494
- )}
495
633
  </CommandList>
496
634
  </CommandDialog>
497
635
  );
@@ -22,6 +22,7 @@ function Command({
22
22
  "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
23
23
  className
24
24
  )}
25
+ cmdk-root=""
25
26
  data-slot="command"
26
27
  {...props}
27
28
  />
@@ -33,13 +34,17 @@ function CommandDialog({
33
34
  description = "Search for a command to run...",
34
35
  children,
35
36
  className,
37
+ commandKey,
36
38
  showCloseButton = true,
39
+ shouldFilter = true,
37
40
  ...props
38
41
  }: React.ComponentProps<typeof Dialog> & {
39
42
  title?: string;
40
43
  description?: string;
41
44
  className?: string;
45
+ commandKey?: React.Key;
42
46
  showCloseButton?: boolean;
47
+ shouldFilter?: boolean;
43
48
  }) {
44
49
  return (
45
50
  <Dialog {...props}>
@@ -48,10 +53,14 @@ function CommandDialog({
48
53
  <DialogDescription>{description}</DialogDescription>
49
54
  </DialogHeader>
50
55
  <DialogContent
51
- className={cn("overflow-hidden p-0", className)}
56
+ className={cn("overflow-hidden border-none p-0 shadow-2xl", className)}
52
57
  showCloseButton={showCloseButton}
53
58
  >
54
- <Command className="**:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
59
+ <Command
60
+ className="**:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-4 [&_[cmdk-input-wrapper]_svg]:w-4 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-1.5 [&_[cmdk-item]_svg]:h-4 [&_[cmdk-item]_svg]:w-4"
61
+ key={commandKey}
62
+ shouldFilter={shouldFilter}
63
+ >
55
64
  {children}
56
65
  </Command>
57
66
  </DialogContent>
@@ -65,16 +74,17 @@ function CommandInput({
65
74
  }: React.ComponentProps<typeof CommandPrimitive.Input>) {
66
75
  return (
67
76
  <div
68
- className="flex h-11 items-center gap-2 rounded-t-md border-border/60 border-b bg-muted/10 px-3 focus-within:bg-background/80"
77
+ className="flex h-11 items-center gap-2 border-border/20 border-b bg-muted/10 px-3 ring-0 shadow-none outline-none focus-within:border-border/20 focus-within:bg-background/95 focus-within:ring-0 focus-within:shadow-none focus-within:outline-none"
69
78
  data-slot="command-input-wrapper"
70
79
  >
71
- <SearchIcon className="size-4 shrink-0 opacity-50" />
80
+ <SearchIcon className="size-4 shrink-0 text-muted-foreground/50" />
72
81
  <CommandPrimitive.Input
73
82
  className={cn(
74
- "flex h-10 w-full rounded-md border-none bg-transparent py-3 text-sm outline-none ring-0 placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0 disabled:cursor-not-allowed disabled:opacity-50",
83
+ "appearance-none flex h-10 w-full rounded-none border-none bg-transparent px-0 py-3 text-sm placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
75
84
  className
76
85
  )}
77
86
  data-slot="command-input"
87
+ style={{ boxShadow: "none", outline: "none" }}
78
88
  {...props}
79
89
  />
80
90
  </div>
@@ -116,7 +126,7 @@ function CommandGroup({
116
126
  return (
117
127
  <CommandPrimitive.Group
118
128
  className={cn(
119
- "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:text-xs",
129
+ "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:font-mono [&_[cmdk-group-heading]]:text-[10px] [&_[cmdk-group-heading]]:text-muted-foreground/60 [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-[0.15em]",
120
130
  className
121
131
  )}
122
132
  data-slot="command-group"
@@ -131,7 +141,7 @@ function CommandSeparator({
131
141
  }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
132
142
  return (
133
143
  <CommandPrimitive.Separator
134
- className={cn("-mx-1 h-px bg-border", className)}
144
+ className={cn("-mx-1 h-px bg-border/20", className)}
135
145
  data-slot="command-separator"
136
146
  {...props}
137
147
  />
@@ -145,7 +155,7 @@ function CommandItem({
145
155
  return (
146
156
  <CommandPrimitive.Item
147
157
  className={cn(
148
- "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0",
158
+ "relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm data-[disabled=true]:pointer-events-none data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0",
149
159
  className
150
160
  )}
151
161
  data-slot="command-item"
@@ -161,7 +171,7 @@ function CommandShortcut({
161
171
  return (
162
172
  <span
163
173
  className={cn(
164
- "ml-auto text-muted-foreground text-xs tracking-widest",
174
+ "ml-auto font-mono text-[10px] text-muted-foreground/50 tabular-nums",
165
175
  className
166
176
  )}
167
177
  data-slot="command-shortcut"
@@ -58,7 +58,7 @@ function DialogContent({
58
58
  <DialogOverlay />
59
59
  <DialogPrimitive.Content
60
60
  className={cn(
61
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-[#0f1115] p-6 shadow-lg outline-none duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:max-w-lg",
61
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border border-border/40 bg-[#0f1115] p-6 shadow-lg outline-none duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:max-w-lg",
62
62
  className
63
63
  )}
64
64
  data-slot="dialog-content"