77 StarIcon ,
88} from "@heroicons/react/20/solid" ;
99import { type Prisma } from "@trigger.dev/database" ;
10- import { useLayoutEffect , useRef , useState } from "react" ;
1110import { z } from "zod" ;
1211import { useOrganization } from "~/hooks/useOrganizations" ;
1312import { logger } from "~/services/logger.server" ;
@@ -53,22 +52,21 @@ export function parseAvatar(json: Prisma.JsonValue, defaultAvatar: Avatar): Avat
5352
5453export function Avatar ( {
5554 avatar,
56- className ,
55+ size ,
5756 includePadding,
5857} : {
5958 avatar : Avatar ;
60- className ?: string ;
59+ /** Size in rems of the icon */
60+ size : number ;
6161 includePadding ?: boolean ;
6262} ) {
6363 switch ( avatar . type ) {
6464 case "icon" :
65- return < AvatarIcon avatar = { avatar } className = { className } includePadding = { includePadding } /> ;
65+ return < AvatarIcon avatar = { avatar } size = { size } includePadding = { includePadding } /> ;
6666 case "letters" :
67- return (
68- < AvatarLetters avatar = { avatar } className = { className } includePadding = { includePadding } />
69- ) ;
67+ return < AvatarLetters avatar = { avatar } size = { size } includePadding = { includePadding } /> ;
7068 case "image" :
71- return < AvatarImage avatar = { avatar } className = { className } /> ;
69+ return < AvatarImage avatar = { avatar } size = { size } /> ;
7270 }
7371}
7472
@@ -101,65 +99,48 @@ export const defaultAvatar: Avatar = {
10199 hex : defaultAvatarHex ,
102100} ;
103101
102+ function styleFromSize ( size : number ) {
103+ return {
104+ width : `${ size } rem` ,
105+ height : `${ size } rem` ,
106+ } ;
107+ }
108+
104109function AvatarLetters ( {
105110 avatar,
106- className ,
111+ size ,
107112 includePadding,
108113} : {
109114 avatar : LettersAvatar ;
110- className ?: string ;
115+ size : number ;
111116 includePadding ?: boolean ;
112117} ) {
113118 const organization = useOrganization ( ) ;
114- const containerRef = useRef < HTMLSpanElement > ( null ) ;
115- const textRef = useRef < HTMLSpanElement > ( null ) ;
116- const [ fontSize , setFontSize ] = useState ( "1rem" ) ;
117-
118- useLayoutEffect ( ( ) => {
119- if ( containerRef . current ) {
120- const containerWidth = containerRef . current . offsetWidth ;
121- // Set font size to 60% of container width (adjust as needed)
122- setFontSize ( `${ containerWidth * 0.6 } px` ) ;
123- }
124-
125- // Optional: Create a ResizeObserver for dynamic resizing
126- const resizeObserver = new ResizeObserver ( ( entries ) => {
127- for ( const entry of entries ) {
128- if ( entry . target === containerRef . current ) {
129- const containerWidth = entry . contentRect . width ;
130- setFontSize ( `${ containerWidth * 0.6 } px` ) ;
131- }
132- }
133- } ) ;
134-
135- if ( containerRef . current ) {
136- resizeObserver . observe ( containerRef . current ) ;
137- }
138-
139- return ( ) => {
140- resizeObserver . disconnect ( ) ;
141- } ;
142- } , [ ] ) ;
143-
144119 const letters = organization . title . slice ( 0 , 2 ) ;
145120
146- const classes = cn ( "grid place-items-center" , className ) ;
147121 const style = {
148122 backgroundColor : avatar . hex ,
149123 } ;
150124
125+ const scaleFactor = includePadding ? 0.8 : 1 ;
126+
151127 return (
152- < span className = { cn ( "grid place-items-center overflow-hidden text-charcoal-750" , classes ) } >
128+ < span
129+ className = "grid place-items-center overflow-hidden text-charcoal-750"
130+ style = { styleFromSize ( size ) }
131+ >
153132 { /* This is the square container */ }
154133 < span
155- ref = { containerRef }
156134 className = { cn (
157135 "relative grid place-items-center overflow-hidden rounded-[10%] font-semibold" ,
158136 includePadding ? "size-[80%]" : "size-[100%]"
159137 ) }
160138 style = { style }
161139 >
162- < span ref = { textRef } className = "font-bold leading-none" style = { { fontSize } } >
140+ < span
141+ className = "font-bold leading-none"
142+ style = { { fontSize : `${ size * 0.6 * scaleFactor } rem` } }
143+ >
163144 { letters }
164145 </ span >
165146 </ span >
@@ -169,29 +150,28 @@ function AvatarLetters({
169150
170151function AvatarIcon ( {
171152 avatar,
172- className ,
153+ size ,
173154 includePadding,
174155} : {
175156 avatar : IconAvatar ;
176- className ?: string ;
157+ size : number ;
177158 includePadding ?: boolean ;
178159} ) {
179- const classes = cn ( "aspect-square" , className ) ;
180160 const style = {
181161 color : avatar . hex ,
182162 } ;
183163
184164 const IconComponent = avatarIcons [ avatar . name ] ;
185165 return (
186- < span className = { cn ( "grid place-items-center" , classes ) } >
166+ < span className = "grid aspect-square place-items-center" style = { styleFromSize ( size ) } >
187167 < IconComponent className = { includePadding ? "size-[80%]" : "size-[100%]" } style = { style } />
188168 </ span >
189169 ) ;
190170}
191171
192- function AvatarImage ( { avatar, className } : { avatar : ImageAvatar ; className ?: string } ) {
172+ function AvatarImage ( { avatar, size } : { avatar : ImageAvatar ; size : number } ) {
193173 return (
194- < span className = "grid place-items-center" >
174+ < span className = "grid place-items-center" style = { styleFromSize ( size ) } >
195175 < img src = { avatar . url } alt = "Organization avatar" className = "size-6" />
196176 </ span >
197177 ) ;
0 commit comments