Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 46 additions & 10 deletions src/components/Badge.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
import { type JSX, useState } from 'react'
import { twMerge } from 'tailwind-merge'
import type { VariantProps } from 'tailwind-variants'
import { badgeCVA, typeIcons } from '@/components/design'
import { badgeCVA, typeColors, typeIcons } from '@/components/design'

import { CodePreview } from './BadgePreviews/CodePreview'
import { ImagePreview } from './BadgePreviews/ImagePreview'
import { LinkPreview } from './BadgePreviews/LinkPreview'
import { TextPreview } from './BadgePreviews/TextPreview'
import { TimePreview } from './BadgePreviews/TimePreview'

const typeTooltips = {
code: CodePreview,
image: ImagePreview,
link: LinkPreview,
text: TextPreview,
time: TimePreview,
} satisfies Partial<Record<keyof typeof typeIcons, () => JSX.Element>>

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

const Badge = ({ text, type }: BadgeProps) => {
const Icon = typeIcons[type]
const [showTooltip, setShowTooltip] = useState(false)
const TooltipComponent =
showTooltip && type in typeTooltips && typeTooltips[type as keyof typeof typeTooltips]
return (
<span
className={twMerge(
badgeCVA({
type,
}),
)}
<button
type='button'
className='relative'
onMouseEnter={() => setShowTooltip(true)}
onMouseLeave={() => setShowTooltip(false)}
>
{type === 'blank' || <Icon className='h-3 w-3' />}
{text || type}
</span>
<span
className={twMerge(
badgeCVA({
clickable: type in typeTooltips,
type,
}),
)}
>
{type === 'blank' || <Icon className='h-3 w-3' />}
{text || type}
</span>
{TooltipComponent && (
<div
className={twMerge(
'absolute top-full z-10 w-30 rounded border px-2 py-1 text-left text-xs shadow-lg',
typeColors[type],
)}
>
<TooltipComponent />
</div>
)}
</button>
)
}

Expand Down
11 changes: 11 additions & 0 deletions src/components/BadgePreviews/CodePreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function CodePreview() {
return (
<>
TODO{' '}
<a href='https://github.com/diffplug/gitcasso/issues/81' className='underline'>
#81
</a>
: show every codeblock in the draft
</>
)
}
11 changes: 11 additions & 0 deletions src/components/BadgePreviews/ImagePreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function ImagePreview() {
return (
<>
TODO{' '}
<a href='https://github.com/diffplug/gitcasso/issues/80' className='underline'>
#80
</a>
: show every image in the draft
</>
)
}
11 changes: 11 additions & 0 deletions src/components/BadgePreviews/LinkPreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function LinkPreview() {
return (
<>
TODO{' '}
<a href='https://github.com/diffplug/gitcasso/issues/79' className='underline'>
#79
</a>
: show text, url, and preview info for every link in the draft
</>
)
}
11 changes: 11 additions & 0 deletions src/components/BadgePreviews/TextPreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function TextPreview() {
return (
<>
TODO{' '}
<a href='https://github.com/diffplug/gitcasso/issues/82' className='underline'>
#82
</a>
: show the syntax-highlighted markdown of the latest draft
</>
)
}
11 changes: 11 additions & 0 deletions src/components/BadgePreviews/TimePreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function TimePreview() {
return (
<>
TODO{' '}
<a href='https://github.com/diffplug/gitcasso/issues/83' className='underline'>
#83
</a>
: show the revision history of the comment
</>
)
}
63 changes: 33 additions & 30 deletions src/components/design.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,38 @@ import {
} from 'lucide-react'
import { tv } from 'tailwind-variants'

// Map types to their icons - source of truth for badge types
export const typeIcons = {
blank: Code,
code: Code,
hideTrashed: EyeOff,
image: Image,
link: Link,
open: Monitor,
sent: MailCheck,
settings: Settings,
text: TextSelect,
time: Clock,
trashed: Trash2,
unsent: MessageSquareDashed,
} as const

// Type colors definition - must be exhaustive with typeIcons
export const typeColors = {
blank: 'bg-transparent text-gray-700',
code: 'bg-pink-50 text-pink-700',
hideTrashed: 'bg-transparent text-gray-700',
image: 'bg-purple-50 text-purple-700',
link: 'bg-blue-50 text-blue-700',
open: 'bg-cyan-50 text-cyan-700',
sent: 'bg-green-50 text-green-700',
settings: 'bg-gray-50 text-gray-700',
text: 'bg-gray-50 text-gray-700',
time: 'bg-gray-50 text-gray-700',
trashed: 'bg-gray-50 text-yellow-700',
unsent: 'bg-amber-100 text-amber-700',
} as const satisfies Record<keyof typeof typeIcons, string>

// TV configuration for stat badges
export const badgeCVA = tv({
base: 'inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs font-normal h-5',
Expand All @@ -28,35 +60,6 @@ export const badgeCVA = tv({
false: '',
true: '!border-solid !border-current',
},
type: {
blank: 'bg-transparent text-gray-700',
code: 'bg-pink-50 text-pink-700',
hideTrashed: 'bg-transparent text-gray-700',
image: 'bg-purple-50 text-purple-700',
link: 'bg-blue-50 text-blue-700',
open: 'bg-cyan-50 text-cyan-700',
sent: 'bg-green-50 text-green-700',
settings: 'bg-gray-50 text-gray-700',
text: 'bg-gray-50 text-gray-700',
time: 'bg-gray-50 text-gray-700',
trashed: 'bg-gray-50 text-yellow-700',
unsent: 'bg-amber-100 text-amber-700',
},
type: typeColors,
},
})

// Map types to their icons
export const typeIcons = {
blank: Code,
code: Code,
hideTrashed: EyeOff,
image: Image,
link: Link,
open: Monitor,
sent: MailCheck,
settings: Settings,
text: TextSelect,
time: Clock,
trashed: Trash2,
unsent: MessageSquareDashed,
} as const