Skip to content

Commit 1053154

Browse files
authored
feat: enhance sidebar and build/release item rows with tooltips and dropdowns (#2507)
1 parent 8f29dbb commit 1053154

3 files changed

Lines changed: 126 additions & 34 deletions

File tree

src/components/ViewPackagePage/components/sidebar-releases-section.tsx

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
import { Tag, Clock } from "lucide-react"
1+
import { Tag, Clock, Globe } from "lucide-react"
22
import { Skeleton } from "@/components/ui/skeleton"
3+
import {
4+
Tooltip,
5+
TooltipContent,
6+
TooltipProvider,
7+
TooltipTrigger,
8+
} from "@/components/ui/tooltip"
39
import { useCurrentPackageInfo } from "@/hooks/use-current-package-info"
410
import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
511
import { timeAgo } from "@/lib/utils/timeAgo"
6-
import { getBuildStatus, StatusIcon } from "@/components/preview"
12+
import { getBuildStatus } from "@/components/preview"
713
import { Link } from "wouter"
814
import { usePackageBuild } from "@/hooks/use-package-builds"
915

@@ -44,26 +50,36 @@ export default function SidebarReleasesSection() {
4450
</h2>
4551
<div className="flex flex-col space-y-2">
4652
<Link
47-
href={`/${packageInfo?.name}/releases`}
53+
href={`/${packageInfo?.name}/releases/${packageRelease.version}`}
4854
className="flex items-center hover:underline"
4955
>
50-
<Tag className="h-4 w-4 mr-2 text-gray-500 dark:text-[#8b949e]" />
56+
<Tag className="h-4 w-4 mr-2 text-gray-500" />
5157
<span className="text-sm font-medium">v{packageRelease.version}</span>
5258
</Link>
5359
<div className="flex items-center">
54-
<Clock className="h-4 w-4 mr-2 text-gray-500 dark:text-[#8b949e]" />
55-
<span className="text-sm text-gray-500 dark:text-[#8b949e]">
56-
{timeAgo(new Date(packageRelease.created_at))}
57-
</span>
60+
<Clock className="h-4 w-4 mr-2 text-gray-500" />
61+
<TooltipProvider>
62+
<Tooltip>
63+
<TooltipTrigger asChild>
64+
<span className="text-sm text-gray-500 cursor-default">
65+
{timeAgo(new Date(packageRelease.created_at))}
66+
</span>
67+
</TooltipTrigger>
68+
<TooltipContent>
69+
{new Date(packageRelease.created_at).toLocaleString()}
70+
</TooltipContent>
71+
</Tooltip>
72+
</TooltipProvider>
5873
</div>
59-
{latestBuild && packageInfo && (
60-
<Link
61-
href={`/${packageInfo?.name}/releases`}
62-
className="flex items-center gap-2 text-sm text-gray-500 dark:text-[#8b949e]"
74+
{packageRelease?.package_release_website_url && (
75+
<a
76+
href={packageRelease.package_release_website_url}
77+
target="_blank"
78+
className="flex items-center gap-2 text-sm text-gray-500 cursor-pointer"
6379
>
64-
<StatusIcon status={status} />
65-
<span>Package Preview {label}</span>
66-
</Link>
80+
<Globe className={`size-4 text-gray-500`} />
81+
<span>Package Preview</span>
82+
</a>
6783
)}
6884
</div>
6985
</div>

src/components/preview/BuildItemRow.tsx

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ export const BuildItemRow = ({
4141
errorMessage,
4242
}: BuildItemRowProps) => {
4343
const [copied, setCopied] = useState(false)
44+
const [isMobileDropdownOpen, setIsMobileDropdownOpen] = useState(false)
45+
const [isDesktopDropdownOpen, setIsDesktopDropdownOpen] = useState(false)
4446

4547
const handleCopy = (e: React.MouseEvent) => {
4648
e.stopPropagation()
@@ -97,16 +99,49 @@ export const BuildItemRow = ({
9799
</div>
98100
)}
99101

100-
<div className="flex justify-between items-end">
101-
<div className="space-y-1">
102-
<div className="text-xs font-medium text-gray-500">
103-
{formatTimeAgo(createdAt)}
104-
</div>
102+
<div className="flex justify-between items-center">
103+
<div className="text-xs font-medium text-gray-500">
104+
{formatTimeAgo(createdAt)}
105105
</div>
106-
<div className="text-right">
107-
<div className="text-xs font-medium text-gray-700">
106+
<div className="flex items-center gap-1.5">
107+
<span className="text-xs font-medium text-gray-700">
108108
{duration || "—"}
109-
</div>
109+
</span>
110+
{dropdownActions && dropdownActions.length > 0 && (
111+
<DropdownMenu
112+
open={isMobileDropdownOpen}
113+
onOpenChange={setIsMobileDropdownOpen}
114+
>
115+
<DropdownMenuTrigger asChild>
116+
<Button
117+
variant="ghost"
118+
size="sm"
119+
className="h-6 w-6 p-0 -mr-1"
120+
onClick={(e) => {
121+
e.stopPropagation()
122+
}}
123+
>
124+
<MoreHorizontal className="w-4 h-4 text-gray-500" />
125+
</Button>
126+
</DropdownMenuTrigger>
127+
<DropdownMenuContent align="end">
128+
{dropdownActions
129+
.filter((action) => !action.hidden)
130+
.map((action) => (
131+
<DropdownMenuItem
132+
key={action.label}
133+
onClick={(e) => {
134+
e.stopPropagation()
135+
setIsMobileDropdownOpen(false)
136+
action.onClick(e)
137+
}}
138+
>
139+
{action.label}
140+
</DropdownMenuItem>
141+
))}
142+
</DropdownMenuContent>
143+
</DropdownMenu>
144+
)}
110145
</div>
111146
</div>
112147
</div>
@@ -182,13 +217,18 @@ export const BuildItemRow = ({
182217
</div>
183218

184219
{dropdownActions && dropdownActions.length > 0 && (
185-
<DropdownMenu>
220+
<DropdownMenu
221+
open={isDesktopDropdownOpen}
222+
onOpenChange={setIsDesktopDropdownOpen}
223+
>
186224
<DropdownMenuTrigger asChild>
187225
<Button
188226
variant="ghost"
189227
size="sm"
190228
className="h-8 w-8 p-0 opacity-0 group-hover:opacity-100 transition-opacity"
191-
onClick={(e) => e.stopPropagation()}
229+
onClick={(e) => {
230+
e.stopPropagation()
231+
}}
192232
>
193233
<MoreHorizontal className="w-4 h-4 text-gray-500" />
194234
</Button>
@@ -201,6 +241,7 @@ export const BuildItemRow = ({
201241
key={action.label}
202242
onClick={(e) => {
203243
e.stopPropagation()
244+
setIsDesktopDropdownOpen(false)
204245
action.onClick(e)
205246
}}
206247
>

src/components/preview/ReleaseItemRow.tsx

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ export const ReleaseItemRow = ({
4545
errorMessage,
4646
}: ReleaseItemRowProps) => {
4747
const [copied, setCopied] = useState(false)
48-
const [isDropdownOpen, setIsDropdownOpen] = useState(false)
48+
const [isMobileDropdownOpen, setIsMobileDropdownOpen] = useState(false)
49+
const [isDesktopDropdownOpen, setIsDesktopDropdownOpen] = useState(false)
4950

5051
const handleCopy = (e: React.MouseEvent) => {
5152
e.stopPropagation()
@@ -130,12 +131,47 @@ export const ReleaseItemRow = ({
130131
</div>
131132
)}
132133

133-
<div className="flex justify-between items-end">
134+
<div className="flex justify-between items-center">
134135
<div className="flex-1 min-w-0 pr-4">{renderGitInfo()}</div>
135-
<div className="flex flex-col items-end flex-shrink-0">
136-
<div className="text-xs font-medium text-gray-500">
136+
<div className="flex items-center gap-1.5 flex-shrink-0">
137+
<span className="text-xs font-medium text-gray-500">
137138
{formatTimeAgo(release.created_at)}
138-
</div>
139+
</span>
140+
{dropdownActions && dropdownActions.length > 0 && (
141+
<DropdownMenu
142+
open={isMobileDropdownOpen}
143+
onOpenChange={setIsMobileDropdownOpen}
144+
>
145+
<DropdownMenuTrigger asChild>
146+
<Button
147+
variant="ghost"
148+
size="sm"
149+
className="h-6 w-6 p-0 -mr-1"
150+
onClick={(e) => {
151+
e.stopPropagation()
152+
}}
153+
>
154+
<MoreHorizontal className="w-4 h-4 text-gray-500" />
155+
</Button>
156+
</DropdownMenuTrigger>
157+
<DropdownMenuContent align="end">
158+
{dropdownActions
159+
.filter((action) => !action.hidden)
160+
.map((action) => (
161+
<DropdownMenuItem
162+
key={action.label}
163+
onClick={(e) => {
164+
e.stopPropagation()
165+
setIsMobileDropdownOpen(false)
166+
action.onClick(e)
167+
}}
168+
>
169+
{action.label}
170+
</DropdownMenuItem>
171+
))}
172+
</DropdownMenuContent>
173+
</DropdownMenu>
174+
)}
139175
</div>
140176
</div>
141177
</div>
@@ -206,8 +242,8 @@ export const ReleaseItemRow = ({
206242

207243
{dropdownActions && dropdownActions.length > 0 && (
208244
<DropdownMenu
209-
open={isDropdownOpen}
210-
onOpenChange={setIsDropdownOpen}
245+
open={isDesktopDropdownOpen}
246+
onOpenChange={setIsDesktopDropdownOpen}
211247
>
212248
<DropdownMenuTrigger asChild>
213249
<Button
@@ -216,7 +252,6 @@ export const ReleaseItemRow = ({
216252
className="h-8 w-8 p-0 opacity-0 group-hover:opacity-100 transition-opacity"
217253
onClick={(e) => {
218254
e.stopPropagation()
219-
setIsDropdownOpen(true)
220255
}}
221256
>
222257
<MoreHorizontal className="w-4 h-4 text-gray-500" />
@@ -230,7 +265,7 @@ export const ReleaseItemRow = ({
230265
key={action.label}
231266
onClick={(e) => {
232267
e.stopPropagation()
233-
setIsDropdownOpen(false)
268+
setIsDesktopDropdownOpen(false)
234269
action.onClick(e)
235270
}}
236271
>

0 commit comments

Comments
 (0)