Skip to content

Commit 5b569e6

Browse files
authored
Add hover tool tips with issue links (#85 closes #69)
2 parents abbd4cb + 7ac99f4 commit 5b569e6

File tree

7 files changed

+134
-40
lines changed

7 files changed

+134
-40
lines changed

src/components/Badge.tsx

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
1+
import { type JSX, useState } from 'react'
12
import { twMerge } from 'tailwind-merge'
23
import type { VariantProps } from 'tailwind-variants'
3-
import { badgeCVA, typeIcons } from '@/components/design'
4+
import { badgeCVA, typeColors, typeIcons } from '@/components/design'
5+
6+
import { CodePreview } from './BadgePreviews/CodePreview'
7+
import { ImagePreview } from './BadgePreviews/ImagePreview'
8+
import { LinkPreview } from './BadgePreviews/LinkPreview'
9+
import { TextPreview } from './BadgePreviews/TextPreview'
10+
import { TimePreview } from './BadgePreviews/TimePreview'
11+
12+
const typeTooltips = {
13+
code: CodePreview,
14+
image: ImagePreview,
15+
link: LinkPreview,
16+
text: TextPreview,
17+
time: TimePreview,
18+
} satisfies Partial<Record<keyof typeof typeIcons, () => JSX.Element>>
419

520
export type BadgeProps = VariantProps<typeof badgeCVA> & {
621
type: keyof typeof typeIcons
@@ -9,17 +24,38 @@ export type BadgeProps = VariantProps<typeof badgeCVA> & {
924

1025
const Badge = ({ text, type }: BadgeProps) => {
1126
const Icon = typeIcons[type]
27+
const [showTooltip, setShowTooltip] = useState(false)
28+
const TooltipComponent =
29+
showTooltip && type in typeTooltips && typeTooltips[type as keyof typeof typeTooltips]
1230
return (
13-
<span
14-
className={twMerge(
15-
badgeCVA({
16-
type,
17-
}),
18-
)}
31+
<button
32+
type='button'
33+
className='relative'
34+
onMouseEnter={() => setShowTooltip(true)}
35+
onMouseLeave={() => setShowTooltip(false)}
1936
>
20-
{type === 'blank' || <Icon className='h-3 w-3' />}
21-
{text || type}
22-
</span>
37+
<span
38+
className={twMerge(
39+
badgeCVA({
40+
clickable: type in typeTooltips,
41+
type,
42+
}),
43+
)}
44+
>
45+
{type === 'blank' || <Icon className='h-3 w-3' />}
46+
{text || type}
47+
</span>
48+
{TooltipComponent && (
49+
<div
50+
className={twMerge(
51+
'absolute top-full z-10 w-30 rounded border px-2 py-1 text-left text-xs shadow-lg',
52+
typeColors[type],
53+
)}
54+
>
55+
<TooltipComponent />
56+
</div>
57+
)}
58+
</button>
2359
)
2460
}
2561

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export function CodePreview() {
2+
return (
3+
<>
4+
TODO{' '}
5+
<a href='https://github.com/diffplug/gitcasso/issues/81' className='underline'>
6+
#81
7+
</a>
8+
: show every codeblock in the draft
9+
</>
10+
)
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export function ImagePreview() {
2+
return (
3+
<>
4+
TODO{' '}
5+
<a href='https://github.com/diffplug/gitcasso/issues/80' className='underline'>
6+
#80
7+
</a>
8+
: show every image in the draft
9+
</>
10+
)
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export function LinkPreview() {
2+
return (
3+
<>
4+
TODO{' '}
5+
<a href='https://github.com/diffplug/gitcasso/issues/79' className='underline'>
6+
#79
7+
</a>
8+
: show text, url, and preview info for every link in the draft
9+
</>
10+
)
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export function TextPreview() {
2+
return (
3+
<>
4+
TODO{' '}
5+
<a href='https://github.com/diffplug/gitcasso/issues/82' className='underline'>
6+
#82
7+
</a>
8+
: show the syntax-highlighted markdown of the latest draft
9+
</>
10+
)
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export function TimePreview() {
2+
return (
3+
<>
4+
TODO{' '}
5+
<a href='https://github.com/diffplug/gitcasso/issues/83' className='underline'>
6+
#83
7+
</a>
8+
: show the revision history of the comment
9+
</>
10+
)
11+
}

src/components/design.tsx

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,38 @@ import {
1313
} from 'lucide-react'
1414
import { tv } from 'tailwind-variants'
1515

16+
// Map types to their icons - source of truth for badge types
17+
export const typeIcons = {
18+
blank: Code,
19+
code: Code,
20+
hideTrashed: EyeOff,
21+
image: Image,
22+
link: Link,
23+
open: Monitor,
24+
sent: MailCheck,
25+
settings: Settings,
26+
text: TextSelect,
27+
time: Clock,
28+
trashed: Trash2,
29+
unsent: MessageSquareDashed,
30+
} as const
31+
32+
// Type colors definition - must be exhaustive with typeIcons
33+
export const typeColors = {
34+
blank: 'bg-transparent text-gray-700',
35+
code: 'bg-pink-50 text-pink-700',
36+
hideTrashed: 'bg-transparent text-gray-700',
37+
image: 'bg-purple-50 text-purple-700',
38+
link: 'bg-blue-50 text-blue-700',
39+
open: 'bg-cyan-50 text-cyan-700',
40+
sent: 'bg-green-50 text-green-700',
41+
settings: 'bg-gray-50 text-gray-700',
42+
text: 'bg-gray-50 text-gray-700',
43+
time: 'bg-gray-50 text-gray-700',
44+
trashed: 'bg-gray-50 text-yellow-700',
45+
unsent: 'bg-amber-100 text-amber-700',
46+
} as const satisfies Record<keyof typeof typeIcons, string>
47+
1648
// TV configuration for stat badges
1749
export const badgeCVA = tv({
1850
base: 'inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs font-normal h-5',
@@ -28,35 +60,6 @@ export const badgeCVA = tv({
2860
false: '',
2961
true: '!border-solid !border-current',
3062
},
31-
type: {
32-
blank: 'bg-transparent text-gray-700',
33-
code: 'bg-pink-50 text-pink-700',
34-
hideTrashed: 'bg-transparent text-gray-700',
35-
image: 'bg-purple-50 text-purple-700',
36-
link: 'bg-blue-50 text-blue-700',
37-
open: 'bg-cyan-50 text-cyan-700',
38-
sent: 'bg-green-50 text-green-700',
39-
settings: 'bg-gray-50 text-gray-700',
40-
text: 'bg-gray-50 text-gray-700',
41-
time: 'bg-gray-50 text-gray-700',
42-
trashed: 'bg-gray-50 text-yellow-700',
43-
unsent: 'bg-amber-100 text-amber-700',
44-
},
63+
type: typeColors,
4564
},
4665
})
47-
48-
// Map types to their icons
49-
export const typeIcons = {
50-
blank: Code,
51-
code: Code,
52-
hideTrashed: EyeOff,
53-
image: Image,
54-
link: Link,
55-
open: Monitor,
56-
sent: MailCheck,
57-
settings: Settings,
58-
text: TextSelect,
59-
time: Clock,
60-
trashed: Trash2,
61-
unsent: MessageSquareDashed,
62-
} as const

0 commit comments

Comments
 (0)