7
7
StarIcon ,
8
8
} from "@heroicons/react/20/solid" ;
9
9
import { type Prisma } from "@trigger.dev/database" ;
10
- import { useLayoutEffect , useRef , useState } from "react" ;
11
10
import { z } from "zod" ;
12
11
import { useOrganization } from "~/hooks/useOrganizations" ;
13
12
import { logger } from "~/services/logger.server" ;
@@ -53,22 +52,21 @@ export function parseAvatar(json: Prisma.JsonValue, defaultAvatar: Avatar): Avat
53
52
54
53
export function Avatar ( {
55
54
avatar,
56
- className ,
55
+ size ,
57
56
includePadding,
58
57
} : {
59
58
avatar : Avatar ;
60
- className ?: string ;
59
+ /** Size in rems of the icon */
60
+ size : number ;
61
61
includePadding ?: boolean ;
62
62
} ) {
63
63
switch ( avatar . type ) {
64
64
case "icon" :
65
- return < AvatarIcon avatar = { avatar } className = { className } includePadding = { includePadding } /> ;
65
+ return < AvatarIcon avatar = { avatar } size = { size } includePadding = { includePadding } /> ;
66
66
case "letters" :
67
- return (
68
- < AvatarLetters avatar = { avatar } className = { className } includePadding = { includePadding } />
69
- ) ;
67
+ return < AvatarLetters avatar = { avatar } size = { size } includePadding = { includePadding } /> ;
70
68
case "image" :
71
- return < AvatarImage avatar = { avatar } className = { className } /> ;
69
+ return < AvatarImage avatar = { avatar } size = { size } /> ;
72
70
}
73
71
}
74
72
@@ -101,65 +99,48 @@ export const defaultAvatar: Avatar = {
101
99
hex : defaultAvatarHex ,
102
100
} ;
103
101
102
+ function styleFromSize ( size : number ) {
103
+ return {
104
+ width : `${ size } rem` ,
105
+ height : `${ size } rem` ,
106
+ } ;
107
+ }
108
+
104
109
function AvatarLetters ( {
105
110
avatar,
106
- className ,
111
+ size ,
107
112
includePadding,
108
113
} : {
109
114
avatar : LettersAvatar ;
110
- className ?: string ;
115
+ size : number ;
111
116
includePadding ?: boolean ;
112
117
} ) {
113
118
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
-
144
119
const letters = organization . title . slice ( 0 , 2 ) ;
145
120
146
- const classes = cn ( "grid place-items-center" , className ) ;
147
121
const style = {
148
122
backgroundColor : avatar . hex ,
149
123
} ;
150
124
125
+ const scaleFactor = includePadding ? 0.8 : 1 ;
126
+
151
127
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
+ >
153
132
{ /* This is the square container */ }
154
133
< span
155
- ref = { containerRef }
156
134
className = { cn (
157
135
"relative grid place-items-center overflow-hidden rounded-[10%] font-semibold" ,
158
136
includePadding ? "size-[80%]" : "size-[100%]"
159
137
) }
160
138
style = { style }
161
139
>
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
+ >
163
144
{ letters }
164
145
</ span >
165
146
</ span >
@@ -169,29 +150,28 @@ function AvatarLetters({
169
150
170
151
function AvatarIcon ( {
171
152
avatar,
172
- className ,
153
+ size ,
173
154
includePadding,
174
155
} : {
175
156
avatar : IconAvatar ;
176
- className ?: string ;
157
+ size : number ;
177
158
includePadding ?: boolean ;
178
159
} ) {
179
- const classes = cn ( "aspect-square" , className ) ;
180
160
const style = {
181
161
color : avatar . hex ,
182
162
} ;
183
163
184
164
const IconComponent = avatarIcons [ avatar . name ] ;
185
165
return (
186
- < span className = { cn ( "grid place-items-center" , classes ) } >
166
+ < span className = "grid aspect-square place-items-center" style = { styleFromSize ( size ) } >
187
167
< IconComponent className = { includePadding ? "size-[80%]" : "size-[100%]" } style = { style } />
188
168
</ span >
189
169
) ;
190
170
}
191
171
192
- function AvatarImage ( { avatar, className } : { avatar : ImageAvatar ; className ?: string } ) {
172
+ function AvatarImage ( { avatar, size } : { avatar : ImageAvatar ; size : number } ) {
193
173
return (
194
- < span className = "grid place-items-center" >
174
+ < span className = "grid place-items-center" style = { styleFromSize ( size ) } >
195
175
< img src = { avatar . url } alt = "Organization avatar" className = "size-6" />
196
176
</ span >
197
177
) ;
0 commit comments