Skip to content

Commit 1afc875

Browse files
committed
refactor: reset only AvatarImage when key changes
1 parent 66d4905 commit 1afc875

3 files changed

Lines changed: 169 additions & 122 deletions

File tree

src/avatar/avatar.module.css

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -127,110 +127,126 @@
127127
background-color: var(--reactist-avatar-meta-fill);
128128
}
129129

130-
.meta-color-0 {
130+
.meta-color-0,
131+
.avatar:has(.meta-color-0) {
131132
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-0-fill);
132133
--reactist-avatar-initials-color: var(--reactist-avatar-meta-0-on-idle-tint);
133134
}
134135

135-
.meta-color-1 {
136+
.meta-color-1,
137+
.avatar:has(.meta-color-1) {
136138
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-1-fill);
137139
--reactist-avatar-initials-color: var(--reactist-avatar-meta-1-on-idle-tint);
138140
}
139141

140-
.meta-color-2 {
142+
.meta-color-2,
143+
.avatar:has(.meta-color-2) {
141144
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-2-fill);
142145
--reactist-avatar-initials-color: var(--reactist-avatar-meta-2-on-idle-tint);
143146
}
144147

145-
.meta-color-3 {
148+
.meta-color-3,
149+
.avatar:has(.meta-color-3) {
146150
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-3-fill);
147151
--reactist-avatar-initials-color: var(--reactist-avatar-meta-3-on-idle-tint);
148152
}
149153

150-
.meta-color-4 {
154+
.meta-color-4,
155+
.avatar:has(.meta-color-4) {
151156
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-4-fill);
152157
--reactist-avatar-initials-color: var(--reactist-avatar-meta-4-on-idle-tint);
153158
}
154159

155-
.meta-color-5 {
160+
.meta-color-5,
161+
.avatar:has(.meta-color-5) {
156162
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-5-fill);
157163
--reactist-avatar-initials-color: var(--reactist-avatar-meta-5-on-idle-tint);
158164
}
159165

160-
.meta-color-6 {
166+
.meta-color-6,
167+
.avatar:has(.meta-color-6) {
161168
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-6-fill);
162169
--reactist-avatar-initials-color: var(--reactist-avatar-meta-6-on-idle-tint);
163170
}
164171

165-
.meta-color-7 {
172+
.meta-color-7,
173+
.avatar:has(.meta-color-7) {
166174
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-7-fill);
167175
--reactist-avatar-initials-color: var(--reactist-avatar-meta-7-on-idle-tint);
168176
}
169177

170-
.meta-color-8 {
178+
.meta-color-8,
179+
.avatar:has(.meta-color-8) {
171180
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-8-fill);
172181
--reactist-avatar-initials-color: var(--reactist-avatar-meta-8-on-idle-tint);
173182
}
174183

175-
.meta-color-9 {
184+
.meta-color-9,
185+
.avatar:has(.meta-color-9) {
176186
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-9-fill);
177187
--reactist-avatar-initials-color: var(--reactist-avatar-meta-9-on-idle-tint);
178188
}
179189

180-
.meta-color-10 {
190+
.meta-color-10,
191+
.avatar:has(.meta-color-10) {
181192
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-10-fill);
182193
--reactist-avatar-initials-color: var(--reactist-avatar-meta-10-on-idle-tint);
183194
}
184195

185-
.meta-color-11 {
196+
.meta-color-11,
197+
.avatar:has(.meta-color-11) {
186198
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-11-fill);
187199
--reactist-avatar-initials-color: var(--reactist-avatar-meta-11-on-idle-tint);
188200
}
189201

190-
.meta-color-12 {
202+
.meta-color-12,
203+
.avatar:has(.meta-color-12) {
191204
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-12-fill);
192205
--reactist-avatar-initials-color: var(--reactist-avatar-meta-12-on-idle-tint);
193206
}
194207

195-
.meta-color-13 {
208+
.meta-color-13,
209+
.avatar:has(.meta-color-13) {
196210
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-13-fill);
197211
--reactist-avatar-initials-color: var(--reactist-avatar-meta-13-on-idle-tint);
198212
}
199213

200-
.meta-color-14 {
214+
.meta-color-14,
215+
.avatar:has(.meta-color-14) {
201216
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-14-fill);
202217
--reactist-avatar-initials-color: var(--reactist-avatar-meta-14-on-idle-tint);
203218
}
204219

205-
.meta-color-15 {
220+
.meta-color-15,
221+
.avatar:has(.meta-color-15) {
206222
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-15-fill);
207223
--reactist-avatar-initials-color: var(--reactist-avatar-meta-15-on-idle-tint);
208224
}
209225

210-
.meta-color-16 {
226+
.meta-color-16,
227+
.avatar:has(.meta-color-16) {
211228
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-16-fill);
212229
--reactist-avatar-initials-color: var(--reactist-avatar-meta-16-on-idle-tint);
213230
}
214231

215-
.meta-color-17 {
232+
.meta-color-17,
233+
.avatar:has(.meta-color-17) {
216234
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-17-fill);
217235
--reactist-avatar-initials-color: var(--reactist-avatar-meta-17-on-idle-tint);
218236
}
219237

220-
.meta-color-18 {
238+
.meta-color-18,
239+
.avatar:has(.meta-color-18) {
221240
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-18-fill);
222241
--reactist-avatar-initials-color: var(--reactist-avatar-meta-18-on-idle-tint);
223242
}
224243

225-
.meta-color-19 {
244+
.meta-color-19,
245+
.avatar:has(.meta-color-19) {
226246
--reactist-avatar-meta-fill: var(--reactist-avatar-meta-19-fill);
227247
--reactist-avatar-initials-color: var(--reactist-avatar-meta-19-on-idle-tint);
228248
}
229249

230-
.empty {
231-
background-color: var(--reactist-avatar-empty-fill);
232-
}
233-
234250
.shape-circle {
235251
border-radius: 50%;
236252
}

src/avatar/avatar.test.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,15 @@ describe('Avatar', () => {
5757
it('falls back to initials when no image is provided', () => {
5858
render(<Avatar data-testid="avatar" size={36} name="Jane Doe" />)
5959

60-
expect(screen.getByRole('img', { name: 'Jane Doe' })).toHaveTextContent('JD')
61-
expect(screen.getByTestId('avatar')).toHaveClass('meta-color-0')
60+
const initials = screen.getByRole('img', { name: 'Jane Doe' })
61+
expect(initials).toHaveTextContent('JD')
62+
expect(initials).toHaveClass('meta-color-0')
6263
})
6364

6465
it('applies the deterministic meta color class for the avatar name', () => {
6566
render(<Avatar data-testid="avatar" size={36} name="John Doe" />)
6667

67-
expect(screen.getByTestId('avatar')).toHaveClass('meta-color-9')
68+
expect(screen.getByRole('img', { name: 'John Doe' })).toHaveClass('meta-color-9')
6869
})
6970

7071
it('falls back to initials when image source map is empty', () => {
@@ -92,6 +93,20 @@ describe('Avatar', () => {
9293
expect(screen.getByRole('img', { name: 'Jane Doe' })).toHaveAttribute('src', 'avatar.png')
9394
})
9495

96+
it('keeps the root element mounted when resetting failed image state', () => {
97+
const { rerender } = render(
98+
<Avatar data-testid="avatar" size={36} name="Jane Doe" image="missing.png" />,
99+
)
100+
const avatarRoot = screen.getByTestId('avatar')
101+
102+
fireEvent.error(screen.getByRole('img', { name: 'Jane Doe' }))
103+
104+
rerender(<Avatar data-testid="avatar" size={36} name="Jane Doe" image="avatar.png" />)
105+
106+
expect(screen.getByTestId('avatar')).toBe(avatarRoot)
107+
expect(screen.getByRole('img', { name: 'Jane Doe' })).toHaveAttribute('src', 'avatar.png')
108+
})
109+
95110
it('removes a failed source-map candidate and retries with the remaining candidates', () => {
96111
render(
97112
<Avatar
@@ -187,8 +202,9 @@ describe('Avatar', () => {
187202
it('renders a neutral empty avatar when no name or image is provided', () => {
188203
render(<Avatar data-testid="avatar" size={36} />)
189204

190-
expect(screen.getByTestId('avatar')).toHaveClass('empty')
205+
expect(screen.getByTestId('avatar')).not.toHaveClass('meta-color-0')
191206
expect(screen.getByTestId('avatar')).toHaveTextContent('')
207+
expect(screen.queryByRole('img')).not.toBeInTheDocument()
192208
})
193209

194210
it('can render the root as a different element', () => {

0 commit comments

Comments
 (0)