stillerman commited on
Commit
5b7f9a5
·
1 Parent(s): b59ef58
package.json CHANGED
@@ -19,6 +19,7 @@
19
  "@radix-ui/react-select": "^2.2.2",
20
  "@radix-ui/react-slot": "^1.2.0",
21
  "@radix-ui/react-tabs": "^1.1.9",
 
22
  "@tailwindcss/vite": "^4.1.5",
23
  "@tanstack/react-virtual": "^3.13.6",
24
  "class-variance-authority": "^0.7.1",
 
19
  "@radix-ui/react-select": "^2.2.2",
20
  "@radix-ui/react-slot": "^1.2.0",
21
  "@radix-ui/react-tabs": "^1.1.9",
22
+ "@radix-ui/react-tooltip": "^1.2.5",
23
  "@tailwindcss/vite": "^4.1.5",
24
  "@tanstack/react-virtual": "^3.13.6",
25
  "class-variance-authority": "^0.7.1",
src/components/game-component.tsx CHANGED
@@ -3,11 +3,50 @@
3
  import { useState, useEffect, useCallback, useRef } from "react";
4
  import { Card } from "@/components/ui/card";
5
  import { Button } from "@/components/ui/button";
6
- import { Flag, Clock, Hash, ArrowRight, Bot, User, ChevronDown, ChevronUp } from "lucide-react";
7
  import { useInference } from "@/lib/inference";
 
 
 
 
 
 
 
 
8
 
9
  import { API_BASE } from "@/lib/constants";
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  type Message = {
13
  role: "user" | "assistant";
@@ -73,6 +112,7 @@ export default function GameComponent({
73
  const [gameStatus, setGameStatus] = useState<"playing" | "won" | "lost">(
74
  "playing"
75
  );
 
76
 
77
  const [convo, setConvo] = useState<Message[]>([]);
78
  const [expandedMessages, setExpandedMessages] = useState<Record<number, boolean>>({});
@@ -215,206 +255,285 @@ export default function GameComponent({
215
  }));
216
  };
217
 
218
- return (
219
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4 h-[calc(100vh-200px)]">
220
- <Card className="p-4 flex col-span-2">
221
- <h2 className="text-xl font-bold">Game Status</h2>
222
- <div className="grid grid-cols-4 gap-4 mb-4">
223
- <div className="bg-muted/30 p-3 rounded-md">
224
- <div className="flex items-center gap-2 text-sm font-medium text-muted-foreground mb-1">
225
- <ArrowRight className="h-4 w-4" /> Current
226
- </div>
227
- <div className="font-medium">{currentPage}</div>
228
- </div>
229
- <div className="bg-muted/30 p-3 rounded-md">
230
- <div className="flex items-center gap-2 text-sm font-medium text-muted-foreground mb-1">
231
- <Flag className="h-4 w-4" /> Target
232
- </div>
233
- <div className="font-medium">{targetPage}</div>
234
- </div>
235
 
236
- <div className="bg-muted/30 p-3 rounded-md">
237
- <div className="flex items-center gap-2 text-sm font-medium text-muted-foreground mb-1">
238
- <Hash className="h-4 w-4" /> Hops
 
 
 
 
 
 
239
  </div>
240
- <div className="font-medium">
241
- {hops} / {maxHops}
 
242
  </div>
243
- </div>
244
-
245
- <div className="bg-muted/30 p-3 rounded-md">
246
- <div className="flex items-center gap-2 text-sm font-medium text-muted-foreground mb-1">
247
- <Clock className="h-4 w-4" /> Time
 
 
 
 
 
 
248
  </div>
249
- <div className="font-medium">{formatTime(timeElapsed)}</div>
250
- </div>
251
- </div>
252
-
253
- {player === "model" && (
254
- <div className="mb-4 bg-blue-50 border border-blue-200 rounded-md p-3">
255
- <div className="flex items-center gap-2">
256
- <Bot className="h-4 w-4 text-blue-500" />
257
- <span className="font-medium text-blue-700">
258
- {model} {modelStatus === "thinking" ? "is thinking..." : "is playing"}
259
  </span>
260
  </div>
261
  </div>
262
- )}
263
- </Card>
264
- {/* Left pane - Current page and available links */}
265
- <Card className="p-4 flex flex-col h-full overflow-hidden">
266
- <h2 className="text-xl font-bold">Available Links</h2>
267
- <div className="flex justify-between items-center mb-4">
268
- {gameStatus !== "playing" && (
269
- <Button onClick={onReset} variant="outline">
270
- New Game
271
- </Button>
272
- )}
273
- </div>
274
 
275
- {/* Available links */}
276
- {gameStatus === "playing" && (
277
- <>
278
- <div className="grid grid-cols-2 sm:grid-cols-3 gap-2 mb-4 overflow-y-auto max-h-[200px]">
279
- {currentPageLinks
280
- .sort((a, b) => a.localeCompare(b))
281
- .map((link) => (
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  <Button
283
- key={link}
284
- variant="outline"
285
  size="sm"
286
- className="justify-start overflow-hidden text-ellipsis whitespace-nowrap"
287
- onClick={() => handleLinkClick(link)}
288
- disabled={player === "model" || modelStatus === "thinking"}
289
  >
290
- {link}
291
  </Button>
292
- ))}
293
- </div>
 
294
 
295
- {player === "model" && (
296
  <Button
297
- onClick={makeModelMove}
298
- disabled={modelStatus === "thinking" || linksLoading}
 
 
299
  >
300
- Make Move
301
  </Button>
302
  )}
303
- </>
304
- )}
305
-
306
- {gameStatus === "playing" && player === "me" && (
307
- <Button
308
- onClick={handleGiveUp}
309
- variant="destructive"
310
- className="mt-auto"
311
- >
312
- Give Up
313
- </Button>
314
- )}
315
-
316
- {gameStatus === "won" && (
317
- <div className="bg-green-100 text-green-800 p-4 rounded-md mt-auto">
318
- <h3 className="font-bold">
319
- {player === "model" ? `${model} won!` : "You won!"}
320
- </h3>
321
- <p>
322
- {player === "model" ? "It" : "You"} reached {targetPage} in {hops}{" "}
323
- hops.
324
- </p>
325
  </div>
326
- )}
 
327
 
328
- {gameStatus === "lost" && (
329
- <div className="bg-red-100 text-red-800 p-4 rounded-md mt-auto">
330
- <h3 className="font-bold">Game Over</h3>
331
- <p>
332
- {player === "model" ? `${model} didn't` : "You didn't"} reach{" "}
333
- {targetPage} within {maxHops} hops.
334
- </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
  </div>
336
  )}
337
  </Card>
338
 
339
- <Card className="p-4 flex flex-col h-full overflow-hidden">
340
- <h2 className="text-xl font-bold mb-4">LLM Reasoning</h2>
341
- <div className="flex-1 overflow-y-auto space-y-4 pr-2">
342
- {convo.map((message, index) => {
343
- const isExpanded = expandedMessages[index] || false;
344
- const isLongUserMessage = message.role === "user" && message.content.length > 300;
345
- const shouldTruncate = isLongUserMessage && !isExpanded;
346
-
347
- return (
348
- <div
349
- key={index}
350
- className={`p-3 rounded-lg ${
351
- message.role === "assistant"
352
- ? "bg-blue-50 border border-blue-100"
353
- : "bg-gray-50 border border-gray-100"
354
- }`}
355
- >
356
- <div className="flex items-center gap-2 mb-1 text-sm font-medium text-muted-foreground">
357
- {message.role === "assistant" ? (
358
- <>
359
- <Bot className="h-4 w-4" />
360
- <span>Assistant</span>
361
- </>
362
- ) : (
363
- <>
364
- <User className="h-4 w-4" />
365
- <span>User</span>
366
- </>
367
- )}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  </div>
369
-
370
- <div>
371
- <p className="whitespace-pre-wrap text-sm">
372
- {shouldTruncate
373
- ? message.content.substring(0, 300) + "..."
374
- : message.content
375
- }
376
- </p>
377
-
378
- {isLongUserMessage && (
379
- <Button
380
- variant="ghost"
381
- size="sm"
382
- className="mt-1 h-6 text-xs flex items-center gap-1 text-muted-foreground hover:text-foreground"
383
- onClick={() => toggleMessageExpand(index)}
384
- >
385
- {isExpanded
386
- ? <><ChevronUp className="h-3 w-3" /> Show less</>
387
- : <><ChevronDown className="h-3 w-3" /> Show more</>
388
- }
389
- </Button>
390
- )}
391
  </div>
 
392
  </div>
393
- );
394
- })}
395
-
396
- {modelStatus === "thinking" && (
397
- <div className="p-3 rounded-lg bg-blue-50 border border-blue-100">
398
- <div className="flex items-center gap-2 mb-1 text-sm font-medium text-muted-foreground">
399
- <Bot className="h-4 w-4" />
400
- <span className="animate-pulse">Thinking...</span>
401
- </div>
402
- <p className="whitespace-pre-wrap text-sm">{partialText}</p>
403
- </div>
404
- )}
405
- <div ref={messagesEndRef} />
406
- </div>
407
- </Card>
408
-
409
- {/* <Card className="p-4 flex flex-col max-h-[500px] overflow-y-auto">
410
- <iframe
411
- src={`https://simple.wikipedia.org/wiki/${currentPage.replace(
412
- /\s+/g,
413
- "_"
414
- )}`}
415
- className="w-full h-full"
416
- />
417
- </Card> */}
418
  </div>
419
  );
420
  }
 
3
  import { useState, useEffect, useCallback, useRef } from "react";
4
  import { Card } from "@/components/ui/card";
5
  import { Button } from "@/components/ui/button";
6
+ import { Flag, Clock, Hash, ArrowRight, Bot, User, ChevronDown, ChevronUp, Info } from "lucide-react";
7
  import { useInference } from "@/lib/inference";
8
+ import { Label } from "@/components/ui/label";
9
+ import { cn } from "@/lib/utils";
10
+ import {
11
+ Tooltip,
12
+ TooltipContent,
13
+ TooltipProvider,
14
+ TooltipTrigger,
15
+ } from "@/components/ui/tooltip";
16
 
17
  import { API_BASE } from "@/lib/constants";
18
 
19
+ // Simple Switch component since it's not available in the UI components
20
+ const Switch = ({ checked, onCheckedChange, disabled, id }: {
21
+ checked: boolean;
22
+ onCheckedChange: (checked: boolean) => void;
23
+ disabled?: boolean;
24
+ id?: string;
25
+ }) => {
26
+ return (
27
+ <button
28
+ id={id}
29
+ type="button"
30
+ role="switch"
31
+ aria-checked={checked}
32
+ data-state={checked ? "checked" : "unchecked"}
33
+ disabled={disabled}
34
+ onClick={() => onCheckedChange(!checked)}
35
+ className={cn(
36
+ "focus-visible:ring-ring/50 peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50",
37
+ checked ? "bg-primary" : "bg-input"
38
+ )}
39
+ >
40
+ <span
41
+ data-state={checked ? "checked" : "unchecked"}
42
+ className={cn(
43
+ "pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform",
44
+ checked ? "translate-x-4" : "translate-x-0"
45
+ )}
46
+ />
47
+ </button>
48
+ );
49
+ };
50
 
51
  type Message = {
52
  role: "user" | "assistant";
 
112
  const [gameStatus, setGameStatus] = useState<"playing" | "won" | "lost">(
113
  "playing"
114
  );
115
+ const [continuousPlay, setContinuousPlay] = useState<boolean>(false);
116
 
117
  const [convo, setConvo] = useState<Message[]>([]);
118
  const [expandedMessages, setExpandedMessages] = useState<Record<number, boolean>>({});
 
255
  }));
256
  };
257
 
258
+ // Effect for continuous play mode
259
+ useEffect(() => {
260
+ if (continuousPlay && player === "model" && gameStatus === "playing" && modelStatus !== "thinking" && !linksLoading) {
261
+ const timer = setTimeout(() => {
262
+ makeModelMove();
263
+ }, 1000);
264
+
265
+ return () => clearTimeout(timer);
266
+ }
267
+ }, [continuousPlay, player, gameStatus, modelStatus, linksLoading, currentPage]);
 
 
 
 
 
 
 
268
 
269
+ return (
270
+ <div className="grid grid-cols-1 md:grid-cols-12 gap-2 h-[calc(100vh-200px)] grid-rows-[auto_1fr]">
271
+ {/* Condensed Game Status Card */}
272
+ <Card className="p-2 col-span-12 h-12 row-start-1">
273
+ <div className="flex items-center justify-between h-full">
274
+ <div className="flex items-center gap-4">
275
+ <div className="flex items-center gap-1">
276
+ <ArrowRight className="h-4 w-4 text-muted-foreground" />
277
+ <span className="text-sm font-medium">{currentPage}</span>
278
  </div>
279
+ <div className="flex items-center gap-1">
280
+ <Flag className="h-4 w-4 text-muted-foreground" />
281
+ <span className="text-sm font-medium">{targetPage}</span>
282
  </div>
283
+ <div
284
+ className="flex items-center gap-1 cursor-help relative group"
285
+ title="Path history"
286
+ >
287
+ <Hash className="h-4 w-4 text-muted-foreground" />
288
+ <span className="text-sm font-medium">
289
+ {hops} / {maxHops}
290
+ </span>
291
+ <div className="invisible absolute bottom-full left-0 mb-2 p-2 bg-popover border rounded-md shadow-md text-xs max-w-[300px] z-50 group-hover:visible whitespace-pre-wrap">
292
+ Path: {visitedNodes.join(" → ")}
293
+ </div>
294
  </div>
295
+ <div className="flex items-center gap-1">
296
+ <Clock className="h-4 w-4 text-muted-foreground" />
297
+ <span className="text-sm font-medium">
298
+ {formatTime(timeElapsed)}
 
 
 
 
 
 
299
  </span>
300
  </div>
301
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
302
 
303
+ <div className="flex items-center gap-2">
304
+ {gameStatus === "playing" && (
305
+ <>
306
+ {player === "model" && (
307
+ <>
308
+ <Button
309
+ onClick={makeModelMove}
310
+ disabled={modelStatus === "thinking" || linksLoading}
311
+ size="sm"
312
+ className="h-8"
313
+ >
314
+ Make Move
315
+ </Button>
316
+
317
+ <div className="flex items-center gap-1 ml-1">
318
+ <Switch
319
+ id="continuous-play"
320
+ checked={continuousPlay}
321
+ onCheckedChange={setContinuousPlay}
322
+ disabled={modelStatus === "thinking" || linksLoading}
323
+ />
324
+ <Label htmlFor="continuous-play" className="text-xs">
325
+ Auto
326
+ </Label>
327
+ </div>
328
+ </>
329
+ )}
330
+
331
+ {player === "me" && (
332
  <Button
333
+ onClick={handleGiveUp}
334
+ variant="destructive"
335
  size="sm"
336
+ className="h-8"
 
 
337
  >
338
+ Give Up
339
  </Button>
340
+ )}
341
+ </>
342
+ )}
343
 
344
+ {gameStatus !== "playing" && (
345
  <Button
346
+ onClick={onReset}
347
+ variant="outline"
348
+ size="sm"
349
+ className="h-8"
350
  >
351
+ New Game
352
  </Button>
353
  )}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
  </div>
355
+ </div>
356
+ </Card>
357
 
358
+ {/* Links panel - larger now */}
359
+ <Card className="p-3 md:col-span-6 h-full overflow-hidden row-start-2">
360
+ <h2 className="text-lg font-bold mb-2">
361
+ Available Links
362
+ <TooltipProvider>
363
+ <Tooltip>
364
+ <TooltipTrigger asChild>
365
+ <span className="ml-2 text-xs text-muted-foreground cursor-help inline-flex items-center">
366
+ <Info className="h-3 w-3 mr-1" />
367
+ Why are some links missing?
368
+ </span>
369
+ </TooltipTrigger>
370
+ <TooltipContent className="max-w-[300px] p-3">
371
+ <p>
372
+ We're playing on a pruned version of Simple Wikipedia so that
373
+ every path between articles is possible. See dataset details{" "}
374
+ <a
375
+ href="https://huggingface.co/datasets/HuggingFaceTB/simplewiki-pruned-350k"
376
+ target="_blank"
377
+ rel="noopener noreferrer"
378
+ className="text-blue-600 underline hover:text-blue-800"
379
+ >
380
+ here
381
+ </a>
382
+ .
383
+ </p>
384
+ </TooltipContent>
385
+ </Tooltip>
386
+ </TooltipProvider>
387
+ </h2>
388
+
389
+ {gameStatus === "playing" ? (
390
+ <div className="grid grid-cols-3 gap-x-1 gap-y-0 overflow-y-auto h-[calc(100%-2.5rem)]">
391
+ {currentPageLinks
392
+ .sort((a, b) => a.localeCompare(b))
393
+ .map((link) => (
394
+ <Button
395
+ key={link}
396
+ variant="outline"
397
+ size="sm"
398
+ className="justify-start overflow-hidden text-ellipsis whitespace-nowrap"
399
+ onClick={() => handleLinkClick(link)}
400
+ disabled={player === "model" || modelStatus === "thinking"}
401
+ >
402
+ {link}
403
+ </Button>
404
+ ))}
405
+ </div>
406
+ ) : (
407
+ <div className="flex items-center justify-center h-[calc(100%-2.5rem)]">
408
+ {gameStatus === "won" ? (
409
+ <div className="bg-green-100 text-green-800 p-4 rounded-md w-full">
410
+ <h3 className="font-bold">
411
+ {player === "model" ? `${model} won!` : "You won!"}
412
+ </h3>
413
+ <p>
414
+ {player === "model" ? "It" : "You"} reached {targetPage} in{" "}
415
+ {hops} hops.
416
+ </p>
417
+ <Button
418
+ onClick={onReset}
419
+ variant="outline"
420
+ size="sm"
421
+ className="mt-2"
422
+ >
423
+ New Game
424
+ </Button>
425
+ </div>
426
+ ) : (
427
+ <div className="bg-red-100 text-red-800 p-4 rounded-md w-full">
428
+ <h3 className="font-bold">Game Over</h3>
429
+ <p>
430
+ {player === "model" ? `${model} didn't` : "You didn't"} reach{" "}
431
+ {targetPage} within {maxHops} hops.
432
+ </p>
433
+ <Button
434
+ onClick={onReset}
435
+ variant="outline"
436
+ size="sm"
437
+ className="mt-2"
438
+ >
439
+ New Game
440
+ </Button>
441
+ </div>
442
+ )}
443
  </div>
444
  )}
445
  </Card>
446
 
447
+ {/* Reasoning panel - larger now */}
448
+ {player === "model" && (
449
+ <Card className="p-3 md:col-span-6 h-full overflow-hidden row-start-2">
450
+ <h2 className="text-lg font-bold mb-2">LLM Reasoning</h2>
451
+ <div className="overflow-y-auto h-[calc(100%-2.5rem)] space-y-2 pr-2">
452
+ {convo.map((message, index) => {
453
+ const isExpanded = expandedMessages[index] || false;
454
+ const isLongUserMessage =
455
+ message.role === "user" && message.content.length > 300;
456
+ const shouldTruncate = isLongUserMessage && !isExpanded;
457
+
458
+ return (
459
+ <div
460
+ key={index}
461
+ className={`p-2 rounded-lg text-xs ${
462
+ message.role === "assistant"
463
+ ? "bg-blue-50 border border-blue-100"
464
+ : "bg-gray-50 border border-gray-100"
465
+ }`}
466
+ >
467
+ <div className="flex items-center gap-1 mb-1 text-xs font-medium text-muted-foreground">
468
+ {message.role === "assistant" ? (
469
+ <>
470
+ <Bot className="h-3 w-3" />
471
+ <span>Assistant</span>
472
+ </>
473
+ ) : (
474
+ <>
475
+ <User className="h-3 w-3" />
476
+ <span>User</span>
477
+ </>
478
+ )}
479
+ </div>
480
+
481
+ <div>
482
+ <p className="whitespace-pre-wrap text-xs">
483
+ {shouldTruncate
484
+ ? message.content.substring(0, 300) + "..."
485
+ : message.content}
486
+ </p>
487
+
488
+ {isLongUserMessage && (
489
+ <Button
490
+ variant="ghost"
491
+ size="sm"
492
+ className="mt-1 h-5 text-xs flex items-center gap-1 text-muted-foreground hover:text-foreground"
493
+ onClick={() => toggleMessageExpand(index)}
494
+ >
495
+ {isExpanded ? (
496
+ <>
497
+ <ChevronUp className="h-3 w-3" /> Show less
498
+ </>
499
+ ) : (
500
+ <>
501
+ <ChevronDown className="h-3 w-3" /> Show more
502
+ </>
503
+ )}
504
+ </Button>
505
+ )}
506
+ </div>
507
  </div>
508
+ );
509
+ })}
510
+
511
+ {modelStatus === "thinking" && (
512
+ <div className="p-2 rounded-lg bg-blue-50 border border-blue-100 text-xs">
513
+ <div className="flex items-center gap-1 mb-1 text-xs font-medium text-muted-foreground">
514
+ <Bot className="h-3 w-3" />
515
+ <span className="animate-pulse">Thinking...</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
516
  </div>
517
+ <p className="whitespace-pre-wrap text-xs">{partialText}</p>
518
  </div>
519
+ )}
520
+ <div ref={messagesEndRef} />
521
+ </div>
522
+ </Card>
523
+ )}
524
+
525
+ {player === "me" && (
526
+ <Card className="p-3 md:col-span-6 h-full overflow-hidden row-start-2">
527
+ <h2 className="text-lg font-bold mb-2">Wikipedia View</h2>
528
+ <iframe
529
+ src={`https://simple.wikipedia.org/wiki/${currentPage.replace(
530
+ " ",
531
+ "_"
532
+ )}`}
533
+ className="w-full h-full"
534
+ />
535
+ </Card>
536
+ )}
 
 
 
 
 
 
 
537
  </div>
538
  );
539
  }
src/components/ui/tooltip.tsx ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as React from "react"
2
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ function TooltipProvider({
7
+ delayDuration = 0,
8
+ ...props
9
+ }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
10
+ return (
11
+ <TooltipPrimitive.Provider
12
+ data-slot="tooltip-provider"
13
+ delayDuration={delayDuration}
14
+ {...props}
15
+ />
16
+ )
17
+ }
18
+
19
+ function Tooltip({
20
+ ...props
21
+ }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
22
+ return (
23
+ <TooltipProvider>
24
+ <TooltipPrimitive.Root data-slot="tooltip" {...props} />
25
+ </TooltipProvider>
26
+ )
27
+ }
28
+
29
+ function TooltipTrigger({
30
+ ...props
31
+ }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
32
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
33
+ }
34
+
35
+ function TooltipContent({
36
+ className,
37
+ sideOffset = 0,
38
+ children,
39
+ ...props
40
+ }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
41
+ return (
42
+ <TooltipPrimitive.Portal>
43
+ <TooltipPrimitive.Content
44
+ data-slot="tooltip-content"
45
+ sideOffset={sideOffset}
46
+ className={cn(
47
+ "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
48
+ className
49
+ )}
50
+ {...props}
51
+ >
52
+ {children}
53
+ <TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
54
+ </TooltipPrimitive.Content>
55
+ </TooltipPrimitive.Portal>
56
+ )
57
+ }
58
+
59
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
yarn.lock CHANGED
@@ -556,6 +556,13 @@
556
  dependencies:
557
  "@radix-ui/react-primitive" "2.1.0"
558
 
 
 
 
 
 
 
 
559
  "@radix-ui/[email protected]":
560
  version "1.1.4"
561
  resolved "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.4.tgz"
@@ -612,6 +619,17 @@
612
  "@radix-ui/react-use-callback-ref" "1.1.1"
613
  "@radix-ui/react-use-escape-keydown" "1.1.1"
614
 
 
 
 
 
 
 
 
 
 
 
 
615
  "@radix-ui/[email protected]":
616
  version "1.1.2"
617
  resolved "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz"
@@ -677,6 +695,22 @@
677
  "@radix-ui/react-use-size" "1.1.1"
678
  "@radix-ui/rect" "1.1.1"
679
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
680
  "@radix-ui/[email protected]":
681
  version "1.1.6"
682
  resolved "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.6.tgz"
@@ -685,6 +719,14 @@
685
  "@radix-ui/react-primitive" "2.1.0"
686
  "@radix-ui/react-use-layout-effect" "1.1.1"
687
 
 
 
 
 
 
 
 
 
688
  "@radix-ui/[email protected]":
689
  version "1.1.4"
690
  resolved "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz"
@@ -700,6 +742,13 @@
700
  dependencies:
701
  "@radix-ui/react-slot" "1.2.0"
702
 
 
 
 
 
 
 
 
703
  "@radix-ui/[email protected]":
704
  version "1.1.7"
705
  resolved "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.7.tgz"
@@ -742,17 +791,17 @@
742
  aria-hidden "^1.2.4"
743
  react-remove-scroll "^2.6.3"
744
 
745
- "@radix-ui/[email protected]":
746
  version "1.2.0"
747
  resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz"
748
  integrity sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==
749
  dependencies:
750
  "@radix-ui/react-compose-refs" "1.1.2"
751
 
752
- "@radix-ui/react-slot@^1.2.0":
753
- version "1.2.0"
754
- resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.2.0.tgz#57727fc186ddb40724ccfbe294e1a351d92462ba"
755
- integrity sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==
756
  dependencies:
757
  "@radix-ui/react-compose-refs" "1.1.2"
758
 
@@ -770,6 +819,24 @@
770
  "@radix-ui/react-roving-focus" "1.1.7"
771
  "@radix-ui/react-use-controllable-state" "1.2.2"
772
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
773
  "@radix-ui/[email protected]":
774
  version "1.1.1"
775
  resolved "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz"
@@ -828,6 +895,13 @@
828
  dependencies:
829
  "@radix-ui/react-primitive" "2.1.0"
830
 
 
 
 
 
 
 
 
831
  "@radix-ui/[email protected]":
832
  version "1.1.1"
833
  resolved "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz"
 
556
  dependencies:
557
  "@radix-ui/react-primitive" "2.1.0"
558
 
559
+ "@radix-ui/[email protected]":
560
+ version "1.1.5"
561
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.5.tgz#3d8974c45f7bd18914132d52f786c2891bddcd4a"
562
+ integrity sha512-GRdeRWdAH6gTTJQRGjyD5aHnhaxY6nsoAOlP8gozThGOMIloorbS70fc7jbBlFBtyA1uLAkdiy/3JF5eVzJVXw==
563
+ dependencies:
564
+ "@radix-ui/react-primitive" "2.1.1"
565
+
566
  "@radix-ui/[email protected]":
567
  version "1.1.4"
568
  resolved "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.4.tgz"
 
619
  "@radix-ui/react-use-callback-ref" "1.1.1"
620
  "@radix-ui/react-use-escape-keydown" "1.1.1"
621
 
622
+ "@radix-ui/[email protected]":
623
+ version "1.1.8"
624
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.8.tgz#cf46f40aa90d2eb14e3c07d1993f5c9616734d94"
625
+ integrity sha512-md5dYvyWDY6884yKjXZA8c+iezVMW5rkdxGwwZJ/TieN5al6UBI5YQGZzkuHbA45S3WqrfG6YwDBMxk4BqmbuA==
626
+ dependencies:
627
+ "@radix-ui/primitive" "1.1.2"
628
+ "@radix-ui/react-compose-refs" "1.1.2"
629
+ "@radix-ui/react-primitive" "2.1.1"
630
+ "@radix-ui/react-use-callback-ref" "1.1.1"
631
+ "@radix-ui/react-use-escape-keydown" "1.1.1"
632
+
633
  "@radix-ui/[email protected]":
634
  version "1.1.2"
635
  resolved "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz"
 
695
  "@radix-ui/react-use-size" "1.1.1"
696
  "@radix-ui/rect" "1.1.1"
697
 
698
+ "@radix-ui/[email protected]":
699
+ version "1.2.5"
700
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.5.tgz#7c670749d4fa943b3462f008c4618df494751dfb"
701
+ integrity sha512-in8+gtEL5YCEm6pflDr8JBsy8+7DPYPNAYaMj/sorPT/BhzOQRWYXWrzJi1wxahPYTc1EzYuhz0oP/QQU2XHwQ==
702
+ dependencies:
703
+ "@floating-ui/react-dom" "^2.0.0"
704
+ "@radix-ui/react-arrow" "1.1.5"
705
+ "@radix-ui/react-compose-refs" "1.1.2"
706
+ "@radix-ui/react-context" "1.1.2"
707
+ "@radix-ui/react-primitive" "2.1.1"
708
+ "@radix-ui/react-use-callback-ref" "1.1.1"
709
+ "@radix-ui/react-use-layout-effect" "1.1.1"
710
+ "@radix-ui/react-use-rect" "1.1.1"
711
+ "@radix-ui/react-use-size" "1.1.1"
712
+ "@radix-ui/rect" "1.1.1"
713
+
714
  "@radix-ui/[email protected]":
715
  version "1.1.6"
716
  resolved "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.6.tgz"
 
719
  "@radix-ui/react-primitive" "2.1.0"
720
  "@radix-ui/react-use-layout-effect" "1.1.1"
721
 
722
+ "@radix-ui/[email protected]":
723
+ version "1.1.7"
724
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.7.tgz#0d2636ff90d53a2eadd2f16a031e06eb9741a044"
725
+ integrity sha512-r2Cpk0yzycgplKYq+X9mo+2o3g12RpTeTZslQocXrAsSY9cz8HJ/QAVb6kxFOhd9U6eq9zTACw1X3JZeLQHj2A==
726
+ dependencies:
727
+ "@radix-ui/react-primitive" "2.1.1"
728
+ "@radix-ui/react-use-layout-effect" "1.1.1"
729
+
730
  "@radix-ui/[email protected]":
731
  version "1.1.4"
732
  resolved "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz"
 
742
  dependencies:
743
  "@radix-ui/react-slot" "1.2.0"
744
 
745
+ "@radix-ui/[email protected]":
746
+ version "2.1.1"
747
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.1.1.tgz#0c8f175b3fed173e42a3a4efa81e3abebe1172e4"
748
+ integrity sha512-+YilAeO2cNOSdE7hh0lp5AJCRI8bwl2sNVWRdl9aQN3JUXZ1/TNZomOAHFvXamLXj1/KPSyjA2p+/Evl6rRrqA==
749
+ dependencies:
750
+ "@radix-ui/react-slot" "1.2.1"
751
+
752
  "@radix-ui/[email protected]":
753
  version "1.1.7"
754
  resolved "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.7.tgz"
 
791
  aria-hidden "^1.2.4"
792
  react-remove-scroll "^2.6.3"
793
 
794
+ "@radix-ui/[email protected]", "@radix-ui/react-slot@^1.2.0":
795
  version "1.2.0"
796
  resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz"
797
  integrity sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==
798
  dependencies:
799
  "@radix-ui/react-compose-refs" "1.1.2"
800
 
801
+ "@radix-ui/react-slot@1.2.1":
802
+ version "1.2.1"
803
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.2.1.tgz#fe4da1b681623c0cfed48fff339652b1482a0d21"
804
+ integrity sha512-RJMUK12Fr2fUEK18xtbY9akYytRqhPzbeTTlWZoCNfXjxCGDnprfBzpobZBS2oWHNtVZnrfTQ2iC8sdUFG3SvQ==
805
  dependencies:
806
  "@radix-ui/react-compose-refs" "1.1.2"
807
 
 
819
  "@radix-ui/react-roving-focus" "1.1.7"
820
  "@radix-ui/react-use-controllable-state" "1.2.2"
821
 
822
+ "@radix-ui/react-tooltip@^1.2.5":
823
+ version "1.2.5"
824
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.2.5.tgz#65701091e7f4eb8694137241a42a903efb57e485"
825
+ integrity sha512-DytUixNBREorQPBbd11UCx3sf/eVwWYgfCsDf1Oa3T6c5TtvcoX+SmyEAOMC1qK+B21GAOl+sepb9/l9wTMb7w==
826
+ dependencies:
827
+ "@radix-ui/primitive" "1.1.2"
828
+ "@radix-ui/react-compose-refs" "1.1.2"
829
+ "@radix-ui/react-context" "1.1.2"
830
+ "@radix-ui/react-dismissable-layer" "1.1.8"
831
+ "@radix-ui/react-id" "1.1.1"
832
+ "@radix-ui/react-popper" "1.2.5"
833
+ "@radix-ui/react-portal" "1.1.7"
834
+ "@radix-ui/react-presence" "1.1.4"
835
+ "@radix-ui/react-primitive" "2.1.1"
836
+ "@radix-ui/react-slot" "1.2.1"
837
+ "@radix-ui/react-use-controllable-state" "1.2.2"
838
+ "@radix-ui/react-visually-hidden" "1.2.1"
839
+
840
  "@radix-ui/[email protected]":
841
  version "1.1.1"
842
  resolved "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz"
 
895
  dependencies:
896
  "@radix-ui/react-primitive" "2.1.0"
897
 
898
+ "@radix-ui/[email protected]":
899
+ version "1.2.1"
900
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.1.tgz#172b632aba219c2522a31aa9b878e195a0c0192d"
901
+ integrity sha512-hXUlAF2piqSSf6WrCb19zDJQpF3FZcN/OX/WErY8J9t5opf3aBp3KNU84tdTAnpDdkOCmzt6fJvzQBICLXYL3w==
902
+ dependencies:
903
+ "@radix-ui/react-primitive" "2.1.1"
904
+
905
  "@radix-ui/[email protected]":
906
  version "1.1.1"
907
  resolved "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz"