11import type { ReactNode } from 'react' ;
2+ import { ExternalLink } from 'lucide-react' ;
23
34const fieldMetaStyle = { fontSize : 'var(--gt-settings-meta-size, 8px)' } as const ;
45const bodyTextStyle = { fontSize : 'var(--gt-settings-body-size, 9px)' } as const ;
@@ -15,10 +16,16 @@ interface SettingsReleasePanelProps {
1516 cliProxyApiGitHashLabel : string ;
1617 latestReleaseTitle : string ;
1718 latestReleaseLabel : string ;
19+ latestReleaseGitHubURL : string ;
1820 updateAssetTitle : string ;
1921 updateAssetName : string ;
2022 updateChannelTitle : string ;
2123 updateChannelHint : ReactNode ;
24+ currentReleaseGitHubURL : string ;
25+ gitHashGitHubURL : string ;
26+ cliProxyApiGitHashGitHubURL : string ;
27+ openGitHubLabel : string ;
28+ onOpenGitHubURL : ( url : string ) => void ;
2229 updateMessage : string ;
2330 checkUpdateLabel : string ;
2431 checkingUpdateLabel : string ;
@@ -42,10 +49,16 @@ export default function SettingsReleasePanel({
4249 cliProxyApiGitHashLabel,
4350 latestReleaseTitle,
4451 latestReleaseLabel,
52+ latestReleaseGitHubURL,
4553 updateAssetTitle,
4654 updateAssetName,
4755 updateChannelTitle,
4856 updateChannelHint,
57+ currentReleaseGitHubURL,
58+ gitHashGitHubURL,
59+ cliProxyApiGitHashGitHubURL,
60+ openGitHubLabel,
61+ onOpenGitHubURL,
4962 updateMessage,
5063 checkUpdateLabel,
5164 checkingUpdateLabel,
@@ -59,26 +72,54 @@ export default function SettingsReleasePanel({
5972} : SettingsReleasePanelProps ) {
6073 return (
6174 < div
62- className = "card-swiss bg-[var(--bg-surface)] !p-5 "
75+ className = "card-swiss overflow-hidden bg-[var(--bg-surface)] !p-0 "
6376 data-design-system-component = "true"
6477 data-design-system-component-name = "SettingsReleasePanel"
6578 data-design-system-git-hash = { gitHashLabel }
6679 >
67- < div className = "grid gap-5 md:grid-cols-[1.1fr_0.9fr]" >
68- < div className = "space-y-4" >
69- < div className = "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4" >
70- < SettingsReleaseValue title = { currentVersionTitle } value = { currentVersionLabel } />
80+ < div className = "grid md:grid-cols-[minmax(0,1fr)_17rem]" >
81+ < div className = "min-w-0" >
82+ < div className = "grid grid-cols-1 border-b border-dashed border-[var(--border-color)] sm:grid-cols-2 lg:grid-cols-4" >
83+ < SettingsReleaseValue
84+ title = { currentVersionTitle }
85+ value = { currentVersionLabel }
86+ actionURL = { currentReleaseGitHubURL }
87+ actionLabel = { openGitHubLabel }
88+ onOpenURL = { onOpenGitHubURL }
89+ strong
90+ />
7191 < SettingsReleaseValue title = { releaseLabelTitle } value = { releaseLabel } />
72- < SettingsReleaseValue title = { gitHashTitle } value = { gitHashLabel } mono />
73- < SettingsReleaseValue title = { cliProxyApiGitHashTitle } value = { cliProxyApiGitHashLabel } mono />
92+ < SettingsReleaseValue
93+ title = { gitHashTitle }
94+ value = { gitHashLabel }
95+ mono
96+ actionURL = { gitHashGitHubURL }
97+ actionLabel = { openGitHubLabel }
98+ onOpenURL = { onOpenGitHubURL }
99+ />
100+ < SettingsReleaseValue
101+ title = { cliProxyApiGitHashTitle }
102+ value = { cliProxyApiGitHashLabel }
103+ mono
104+ actionURL = { cliProxyApiGitHashGitHubURL }
105+ actionLabel = { openGitHubLabel }
106+ onOpenURL = { onOpenGitHubURL }
107+ />
74108 </ div >
75109
76- < div className = "grid grid-cols-1 gap-4 border-t border-dashed border-[var(--border-color)] pt-4 sm:grid-cols-2" >
77- < SettingsReleaseValue title = { latestReleaseTitle } value = { latestReleaseLabel } />
110+ < div className = "grid grid-cols-1 border-b border-dashed border-[var(--border-color)] sm:grid-cols-2" >
111+ < SettingsReleaseValue
112+ title = { latestReleaseTitle }
113+ value = { latestReleaseLabel }
114+ actionURL = { latestReleaseGitHubURL }
115+ actionLabel = { openGitHubLabel }
116+ onOpenURL = { onOpenGitHubURL }
117+ strong
118+ />
78119 < SettingsReleaseValue title = { updateAssetTitle } value = { updateAssetName } mono body />
79120 </ div >
80121
81- < div className = "border-t border-dashed border-[var(--border-color)] pt -4" >
122+ < div className = "px-4 py -4" >
82123 < div className = "font-bold uppercase tracking-widest text-[var(--text-muted)]" style = { fieldMetaStyle } >
83124 { updateChannelTitle }
84125 </ div >
@@ -96,7 +137,7 @@ export default function SettingsReleasePanel({
96137 </ div >
97138 </ div >
98139
99- < div className = "space-y -3 border-t border-dashed border-[var(--border-color)] pt- 4 md:border-l md:border-t-0 md:pl-5 md:pt -0" >
140+ < div className = "grid content-start gap -3 border-t border-dashed border-[var(--border-color)] bg-[var(--bg-main)] p- 4 md:border-l md:border-t-0" >
100141 < button className = "btn-swiss w-full" onClick = { onCheckUpdate } disabled = { isCheckingUpdate } >
101142 { isCheckingUpdate ? checkingUpdateLabel : checkUpdateLabel }
102143 </ button >
@@ -119,22 +160,45 @@ function SettingsReleaseValue({
119160 value,
120161 mono = false ,
121162 body = false ,
163+ strong = false ,
164+ actionURL = '' ,
165+ actionLabel = '' ,
166+ onOpenURL,
122167} : {
123168 title : string ;
124169 value : string ;
125170 mono ?: boolean ;
126171 body ?: boolean ;
172+ strong ?: boolean ;
173+ actionURL ?: string ;
174+ actionLabel ?: string ;
175+ onOpenURL ?: ( url : string ) => void ;
127176} ) {
128177 const valueClassName = mono
129178 ? 'break-all font-mono font-bold text-[var(--text-primary)]'
130- : 'font-black uppercase italic text-[var(--text-primary)]' ;
179+ : strong
180+ ? 'font-black uppercase italic text-[var(--text-primary)]'
181+ : 'font-bold uppercase text-[var(--text-primary)]' ;
131182
132183 return (
133- < div className = "min-w-0 space-y-1" >
134- < div className = "font-bold uppercase tracking-widest text-[var(--text-muted)]" style = { fieldMetaStyle } >
135- { title }
184+ < div className = "min-w-0 border-b border-dashed border-[var(--border-color)] px-4 py-3 last:border-b-0 sm:border-b-0 sm:border-r sm:last:border-r-0 lg:border-r lg:[&:nth-child(4n)]:border-r-0" >
185+ < div className = "flex min-h-6 items-center justify-between gap-2" >
186+ < div className = "font-bold uppercase tracking-widest text-[var(--text-muted)]" style = { fieldMetaStyle } >
187+ { title }
188+ </ div >
189+ { actionURL && onOpenURL ? (
190+ < button
191+ type = "button"
192+ className = "inline-flex h-6 w-6 shrink-0 items-center justify-center border border-[var(--border-color)] bg-[var(--bg-main)] text-[var(--text-primary)] transition active:scale-95 hover:bg-[var(--bg-surface)]"
193+ aria-label = { `${ actionLabel } : ${ value } ` }
194+ title = { actionLabel }
195+ onClick = { ( ) => onOpenURL ( actionURL ) }
196+ >
197+ < ExternalLink className = "h-3.5 w-3.5" aria-hidden = "true" />
198+ </ button >
199+ ) : null }
136200 </ div >
137- < div className = { valueClassName } style = { body ? bodyTextStyle : valueTextStyle } >
201+ < div className = { `mt-1 ${ valueClassName } ` } style = { body ? bodyTextStyle : valueTextStyle } >
138202 { value }
139203 </ div >
140204 </ div >
0 commit comments