Skip to content

Commit 266590b

Browse files
committed
use more typechecking
1 parent 15a4050 commit 266590b

File tree

2 files changed

+28
-26
lines changed

2 files changed

+28
-26
lines changed

src/components/Badge.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useState } from 'react'
22
import { twMerge } from 'tailwind-merge'
33
import type { VariantProps } from 'tailwind-variants'
4-
import { badgeCVA, typeIcons, typeTooltips } from '@/components/design'
4+
import { badgeCVA, typeColors, typeIcons, typeTooltips } from '@/components/design'
55

66
export type BadgeProps = VariantProps<typeof badgeCVA> & {
77
type: keyof typeof typeIcons
@@ -11,7 +11,8 @@ export type BadgeProps = VariantProps<typeof badgeCVA> & {
1111
const Badge = ({ text, type }: BadgeProps) => {
1212
const Icon = typeIcons[type]
1313
const [showTooltip, setShowTooltip] = useState(false)
14-
const TooltipComponent = showTooltip && typeTooltips[type]
14+
const TooltipComponent =
15+
showTooltip && type in typeTooltips && typeTooltips[type as keyof typeof typeTooltips]
1516
return (
1617
<button
1718
type='button'
@@ -22,7 +23,7 @@ const Badge = ({ text, type }: BadgeProps) => {
2223
<span
2324
className={twMerge(
2425
badgeCVA({
25-
clickable: !!typeTooltips[type],
26+
clickable: type in typeTooltips,
2627
type,
2728
}),
2829
)}
@@ -32,9 +33,10 @@ const Badge = ({ text, type }: BadgeProps) => {
3233
</span>
3334
{TooltipComponent && (
3435
<div
35-
className={
36-
'absolute top-full z-10 w-max rounded bg-gray-800 px-2 py-1 text-white text-xs shadow-lg'
37-
}
36+
className={twMerge(
37+
'absolute top-full z-10 w-50 rounded border px-2 py-1 text-xs shadow-lg',
38+
typeColors[type],
39+
)}
3840
>
3941
<TooltipComponent />
4042
</div>

src/components/design.tsx

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,23 @@ import { LinkPreview } from './BadgePreviews/LinkPreview'
1919
import { TextPreview } from './BadgePreviews/TextPreview'
2020
import { TimePreview } from './BadgePreviews/TimePreview'
2121

22-
// Type colors definition - single source of truth
22+
// Map types to their icons - source of truth for badge types
23+
export const typeIcons = {
24+
blank: Code,
25+
code: Code,
26+
hideTrashed: EyeOff,
27+
image: Image,
28+
link: Link,
29+
open: Monitor,
30+
sent: MailCheck,
31+
settings: Settings,
32+
text: TextSelect,
33+
time: Clock,
34+
trashed: Trash2,
35+
unsent: MessageSquareDashed,
36+
} as const
37+
38+
// Type colors definition - must be exhaustive with typeIcons
2339
export const typeColors = {
2440
blank: 'bg-transparent text-gray-700',
2541
code: 'bg-pink-50 text-pink-700',
@@ -33,7 +49,7 @@ export const typeColors = {
3349
time: 'bg-gray-50 text-gray-700',
3450
trashed: 'bg-gray-50 text-yellow-700',
3551
unsent: 'bg-amber-100 text-amber-700',
36-
} as const
52+
} as const satisfies Record<keyof typeof typeIcons, string>
3753

3854
// TV configuration for stat badges
3955
export const badgeCVA = tv({
@@ -54,26 +70,10 @@ export const badgeCVA = tv({
5470
},
5571
})
5672

57-
// Map types to their icons
58-
export const typeIcons = {
59-
blank: Code,
60-
code: Code,
61-
hideTrashed: EyeOff,
62-
image: Image,
63-
link: Link,
64-
open: Monitor,
65-
sent: MailCheck,
66-
settings: Settings,
67-
text: TextSelect,
68-
time: Clock,
69-
trashed: Trash2,
70-
unsent: MessageSquareDashed,
71-
} as const
72-
73-
export const typeTooltips: { [key: string]: () => JSX.Element | undefined } = {
73+
export const typeTooltips = {
7474
code: CodePreview,
7575
image: ImagePreview,
7676
link: LinkPreview,
7777
text: TextPreview,
7878
time: TimePreview,
79-
}
79+
} satisfies Partial<Record<keyof typeof typeIcons, () => JSX.Element | undefined>>

0 commit comments

Comments
 (0)