@@ -19,12 +19,16 @@ const MAX_DISPLAYED_VERSIONS = TRUNCATION_THRESHOLD - 1;
1919const HOVER_DELAY = 200 ;
2020const TOOLTIP_OPEN_DELAY = 200 ;
2121
22+ type VersionsBarSize = 's' | 'm' ;
23+
2224interface VersionsBarProps {
2325 preparedVersions : PreparedVersion [ ] ;
26+ withTitles ?: boolean ;
27+ size ?: VersionsBarSize ;
2428}
2529
26- export function VersionsBar ( { preparedVersions} : VersionsBarProps ) {
27- const shouldTruncateVersions = preparedVersions . length > TRUNCATION_THRESHOLD ;
30+ export function VersionsBar ( { preparedVersions, withTitles = true , size = 's' } : VersionsBarProps ) {
31+ const shouldTruncateVersions = preparedVersions . length > TRUNCATION_THRESHOLD && size === 's' ;
2832
2933 const [ hoveredVersion , setHoveredVersion ] = React . useState < string | undefined > ( ) ;
3034 const [ allVersionsDisplayed , setAllVersionsDisplayed ] = React . useState < boolean > ( false ) ;
@@ -72,15 +76,25 @@ export function VersionsBar({preparedVersions}: VersionsBarProps) {
7276
7377 if ( allVersionsDisplayed ) {
7478 return (
75- < Button view = "flat-secondary" size = { 's' } onClick = { handleHideAllVersions } >
79+ < Button
80+ view = "flat-secondary"
81+ size = { 's' }
82+ onClick = { handleHideAllVersions }
83+ className = { b ( 'button' ) }
84+ >
7685 { i18n ( 'action_hide' , {
7786 count : truncatedVersionsCount ,
7887 } ) }
7988 </ Button >
8089 ) ;
8190 } else {
8291 return (
83- < Button view = "flat-secondary" size = { 's' } onClick = { handleShowAllVersions } >
92+ < Button
93+ view = "flat-secondary"
94+ size = { 's' }
95+ onClick = { handleShowAllVersions }
96+ className = { b ( 'button' ) }
97+ >
8498 { i18n ( 'action_show_more' , {
8599 count : truncatedVersionsCount ,
86100 } ) }
@@ -103,12 +117,12 @@ export function VersionsBar({preparedVersions}: VersionsBarProps) {
103117 } , [ handleMouseEnter ] ) ;
104118
105119 const isDimmed = ( version : string ) => {
106- return hoveredVersion && hoveredVersion !== version ;
120+ return Boolean ( hoveredVersion && hoveredVersion !== version ) ;
107121 } ;
108122
109123 return (
110- < Flex gap = { 2 } direction = { 'column' } className = { b ( null ) } wrap >
111- < Flex className = { b ( 'bar' ) } grow = { 1 } gap = { 0.5 } >
124+ < Flex direction = { 'column' } className = { b ( 'bar-wrapper' , { size } ) } wrap >
125+ < Flex className = { b ( 'bar' , { size } ) } grow = { 1 } >
112126 { displayedVersions . map ( ( item ) => (
113127 < Tooltip
114128 key = { item . version }
@@ -119,54 +133,103 @@ export function VersionsBar({preparedVersions}: VersionsBarProps) {
119133 { item . version }
120134 </ React . Fragment >
121135 }
122- placement = { 'top-start' }
136+ placement = { size === 'm' ? 'auto' : 'top-start' }
123137 openDelay = { TOOLTIP_OPEN_DELAY }
124138 >
125139 < span
126140 onMouseEnter = { ( ) => {
127141 handleMouseEnter ( item . version ) ;
128142 } }
129143 onMouseLeave = { handleMouseLeave }
130- className = { b ( 'version' , { dimmed : isDimmed ( item . version ) } ) }
144+ className = { b ( 'version' , { dimmed : isDimmed ( item . version ) , size } ) }
131145 style = { { backgroundColor : item . color , width : `${ item . value } %` } }
132146 />
133147 </ Tooltip >
134148 ) ) }
135149 </ Flex >
136150
137- < Flex gap = { 0.5 } direction = { 'column' } >
138- { truncatedDisplayedVersions . map ( ( item ) => (
139- < Tooltip
140- key = { item . version }
141- content = { i18n ( 'tooltip_nodes' , { count : item . count } ) }
142- placement = { 'bottom-end' }
143- openDelay = { TOOLTIP_OPEN_DELAY }
144- >
145- < Flex gap = { 1 } alignItems = { 'center' } className = { b ( 'titles-wrapper' ) } >
146- < svg
147- xmlns = "http://www.w3.org/2000/svg"
148- width = "6"
149- height = "6"
150- viewBox = "0 0 6 6"
151- fill = "none"
152- className = { b ( 'version-icon' , { dimmed : isDimmed ( item . version ) } ) }
153- >
154- < circle cx = "3" cy = "3" r = "3" fill = { item . color } />
155- </ svg >
156- < div
157- className = { b ( 'title' , { dimmed : isDimmed ( item . version ) } ) }
158- onMouseEnter = { ( ) => {
159- handleMouseEnter ( item . version ) ;
160- } }
161- onMouseLeave = { handleMouseLeave }
162- >
163- { item . version }
164- </ div >
165- </ Flex >
166- </ Tooltip >
167- ) ) }
168- < Flex > { renderButton ( ) } </ Flex >
169- </ Flex >
151+ { withTitles && (
152+ < Flex className = { b ( 'titles-wrapper' , { size} ) } >
153+ { truncatedDisplayedVersions . map ( ( item ) => (
154+ < VersionTitle
155+ key = { item . version }
156+ version = { item . version }
157+ color = { item . color || '' }
158+ count = { item . count }
159+ isDimmed = { isDimmed ( item . version ) }
160+ onMouseEnter = { ( ) => {
161+ handleMouseEnter ( item . version ) ;
162+ } }
163+ onMouseLeave = { handleMouseLeave }
164+ size = { size }
165+ />
166+ ) ) }
167+ { renderButton ( ) }
168+ </ Flex >
169+ ) }
170170 </ Flex >
171171 ) ;
172172}
173+
174+ interface VersionTitleProps {
175+ version : string ;
176+ color : string ;
177+ count ?: number ;
178+ isDimmed : boolean ;
179+ onMouseEnter : VoidFunction ;
180+ onMouseLeave : VoidFunction ;
181+ size : VersionsBarSize ;
182+ }
183+
184+ function VersionTitle ( {
185+ version,
186+ color,
187+ count,
188+ isDimmed,
189+ onMouseEnter,
190+ onMouseLeave,
191+ size,
192+ } : VersionTitleProps ) {
193+ return (
194+ < Tooltip
195+ content = { i18n ( 'tooltip_nodes' , { count : count } ) }
196+ placement = { 'bottom-end' }
197+ openDelay = { TOOLTIP_OPEN_DELAY }
198+ >
199+ < Flex alignItems = { 'center' } className = { b ( 'title' , { size} ) } >
200+ < VersionCircle size = { size } dimmed = { isDimmed } color = { color } />
201+ < div
202+ className = { b ( 'title-text' , { dimmed : isDimmed , size} ) }
203+ onMouseEnter = { onMouseEnter }
204+ onMouseLeave = { onMouseLeave }
205+ >
206+ { version }
207+ </ div >
208+ </ Flex >
209+ </ Tooltip >
210+ ) ;
211+ }
212+
213+ interface VersionCircleProps {
214+ size : VersionsBarSize ;
215+ dimmed : boolean ;
216+ color : string ;
217+ }
218+
219+ function VersionCircle ( { size, dimmed, color} : VersionCircleProps ) {
220+ const numericSize = size === 'm' ? 8 : 6 ;
221+ const radius = numericSize / 2 ;
222+
223+ return (
224+ < svg
225+ xmlns = "http://www.w3.org/2000/svg"
226+ width = { numericSize }
227+ height = { numericSize }
228+ viewBox = { `0 0 ${ numericSize } ${ numericSize } ` }
229+ fill = "none"
230+ className = { b ( 'version-icon' , { dimmed} ) }
231+ >
232+ < circle cx = { radius } cy = { radius } r = { radius } fill = { color } />
233+ </ svg >
234+ ) ;
235+ }
0 commit comments