Skip to content

Commit 874acc1

Browse files
committed
Use CVA to make our little badge things more maintainable.
1 parent 856f3c5 commit 874acc1

File tree

1 file changed

+60
-47
lines changed

1 file changed

+60
-47
lines changed

browser-extension/tests/playground/claude.tsx

Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,52 @@
11
//import { DraftStats } from '@/lib/enhancers/draftStats'
2-
import { CommentSpot } from '@/lib/enhancer'
3-
import { DraftStats } from '@/lib/enhancers/draftStats'
2+
43
import { GitPullRequestIcon, IssueOpenedIcon } from '@primer/octicons-react'
4+
import { cva, type VariantProps } from 'class-variance-authority'
55
import { Clock, Code, Filter, Image, Link, Search, TextSelect } from 'lucide-react'
66
import { useMemo, useState } from 'react'
7+
import type { CommentSpot } from '@/lib/enhancer'
8+
import type { DraftStats } from '@/lib/enhancers/draftStats'
9+
10+
// CVA configuration for stat badges
11+
const statBadge = cva('inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs', {
12+
defaultVariants: {
13+
type: 'text',
14+
},
15+
variants: {
16+
type: {
17+
code: 'bg-pink-50 text-pink-700',
18+
image: 'bg-purple-50 text-purple-700',
19+
link: 'bg-blue-50 text-blue-700',
20+
text: 'bg-gray-50 text-gray-700',
21+
time: 'bg-gray-50 text-gray-700',
22+
},
23+
},
24+
})
25+
26+
// Map types to their icons
27+
const typeIcons = {
28+
code: Code,
29+
image: Image,
30+
link: Link,
31+
text: TextSelect,
32+
time: Clock,
33+
} as const
34+
35+
// StatBadge component
36+
type BadgeProps = VariantProps<typeof statBadge> & {
37+
text: number | string
38+
type: keyof typeof typeIcons
39+
}
40+
41+
const Badge = ({ text, type }: BadgeProps) => {
42+
const Icon = typeIcons[type]
43+
return (
44+
<span className={statBadge({ type })}>
45+
<Icon className='w-3 h-3' />
46+
{text}
47+
</span>
48+
)
49+
}
750

851
/*
952
interface GitHubIssueAddCommentSpot extends CommentSpot {
@@ -48,8 +91,8 @@ interface RedditDraft extends BaseDraft {
4891
}
4992

5093
interface LatestDraft {
51-
spot: BaseDraft,
52-
draft: string,
94+
spot: BaseDraft
95+
draft: string
5396
time: number
5497
draftStats: DraftStats
5598
}
@@ -70,69 +113,69 @@ const generateMockDrafts = (): Draft[] => [
70113
codeCount: 3,
71114
content:
72115
'This PR addresses the memory leak issue reported in #1233. The problem was caused by event listeners not being properly disposed...',
73-
unique_key: '1',
74116
imageCount: 2,
75117
lastEdit: Date.now() - 1000 * 60 * 30,
76118
linkCount: 2,
77119
number: 1234,
78120
slug: 'microsoft/vscode',
79121
title: 'Fix memory leak in extension host',
80122
type: 'PR',
123+
unique_key: '1',
81124
} satisfies GitHubDraft,
82125
{
83126
charCount: 180,
84127
codeCount: 0,
85128
content:
86129
"I've been using GitLens for years and it's absolutely essential for my workflow. The inline blame annotations are incredibly helpful when...",
87-
unique_key: '2',
88130
imageCount: 0,
89131
lastEdit: Date.now() - 1000 * 60 * 60 * 2,
90132
linkCount: 1,
91133
subreddit: 'programming',
92134
title: "Re: What's your favorite VS Code extension?",
93135
type: 'REDDIT',
136+
unique_key: '2',
94137
} satisfies RedditDraft,
95138
{
96139
charCount: 456,
97140
codeCount: 1,
98141
content:
99142
"When using useEffect with async functions, the cleanup function doesn't seem to be called correctly in certain edge cases...",
100-
unique_key: '3',
101143
imageCount: 0,
102144
lastEdit: Date.now() - 1000 * 60 * 60 * 5,
103145
linkCount: 0,
104146
number: 5678,
105147
slug: 'facebook/react',
106148
title: 'Unexpected behavior with useEffect cleanup',
107149
type: 'ISSUE',
150+
unique_key: '3',
108151
} satisfies GitHubDraft,
109152
{
110153
charCount: 322,
111154
codeCount: 0,
112155
content:
113156
'LGTM! Just a few minor suggestions about the examples in the routing section. Consider adding more context about...',
114-
unique_key: '4',
115157
imageCount: 4,
116158
lastEdit: Date.now() - 1000 * 60 * 60 * 24,
117159
linkCount: 3,
118160
number: 9012,
119161
slug: 'vercel/next.js',
120162
title: 'Update routing documentation',
121163
type: 'PR',
164+
unique_key: '4',
122165
} satisfies GitHubDraft,
123166
{
124167
charCount: 678,
125168
codeCount: 7,
126169
content:
127170
'This PR implements ESM support in worker threads as discussed in the last TSC meeting. The implementation follows...',
128-
unique_key: '5',
129171
imageCount: 1,
130172
lastEdit: Date.now() - 1000 * 60 * 60 * 48,
131173
linkCount: 5,
132174
number: 3456,
133175
slug: 'nodejs/node',
134176
title: 'Add support for ESM in worker threads',
135177
type: 'PR',
178+
unique_key: '5',
136179
} satisfies GitHubDraft,
137180
]
138181

@@ -372,10 +415,7 @@ export const ClaudePrototype = () => {
372415
onChange={(e) => setHasLinkFilter(e.target.checked)}
373416
className='rounded'
374417
/>
375-
<span className='inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs bg-blue-50 text-blue-700'>
376-
<Link className='w-3 h-3' />
377-
links
378-
</span>
418+
<Badge type='link' text='links' />
379419
</label>
380420
<label className='flex items-center gap-2 cursor-pointer'>
381421
<input
@@ -384,10 +424,7 @@ export const ClaudePrototype = () => {
384424
onChange={(e) => setHasImageFilter(e.target.checked)}
385425
className='rounded'
386426
/>
387-
<span className='inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs bg-purple-50 text-purple-700'>
388-
<Image className='w-3 h-3' />
389-
images
390-
</span>
427+
<Badge type='image' text='images' />
391428
</label>
392429
<label className='flex items-center gap-2 cursor-pointer'>
393430
<input
@@ -396,10 +433,7 @@ export const ClaudePrototype = () => {
396433
onChange={(e) => setHasCodeFilter(e.target.checked)}
397434
className='rounded'
398435
/>
399-
<span className='inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs bg-pink-50 text-pink-700'>
400-
<Code className='w-3 h-3' />
401-
code
402-
</span>
436+
<Badge type='code' text='code' />
403437
</label>
404438
</div>
405439
</div>
@@ -467,32 +501,11 @@ function commentRow(
467501
)}
468502
</div>
469503
<div className='flex items-center gap-1 flex-shrink-0'>
470-
{draft.linkCount > 0 && (
471-
<span className='inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs bg-blue-50 text-blue-700'>
472-
<Link className='w-3 h-3' />
473-
{draft.linkCount}
474-
</span>
475-
)}
476-
{draft.imageCount > 0 && (
477-
<span className='inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs bg-purple-50 text-purple-700'>
478-
<Image className='w-3 h-3' />
479-
{draft.imageCount}
480-
</span>
481-
)}
482-
{draft.codeCount > 0 && (
483-
<span className='inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs bg-pink-50 text-pink-700'>
484-
<Code className='w-3 h-3' />
485-
{draft.codeCount}
486-
</span>
487-
)}
488-
<span className='inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs bg-gray-50 text-gray-700'>
489-
<TextSelect className='w-3 h-3' />
490-
{draft.charCount}
491-
</span>
492-
<span className='inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs bg-gray-50 text-gray-700'>
493-
<Clock className='w-3 h-3' />
494-
{timeAgo(draft.lastEdit)}
495-
</span>
504+
{draft.linkCount > 0 && <Badge type='link' text={draft.linkCount} />}
505+
{draft.imageCount > 0 && <Badge type='image' text={draft.imageCount} />}
506+
{draft.codeCount > 0 && <Badge type='code' text={draft.codeCount} />}
507+
<Badge type='text' text={draft.charCount} />
508+
<Badge type='time' text={timeAgo(draft.lastEdit)} />
496509
</div>
497510
</div>
498511

0 commit comments

Comments
 (0)