Skip to content

Commit 927c110

Browse files
authored
Avatar improvements (#2577)
1 parent 0c7dfc9 commit 927c110

File tree

6 files changed

+370
-271
lines changed

6 files changed

+370
-271
lines changed

.changeset/modern-teams-change.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@sl-design-system/avatar': minor
3+
---
4+
5+
Various improvements:
6+
- Add `shape` property that defaults to `circle` but can be set to `square`
7+
- Add `color` property that works the same as in `<sl-badge>`
8+
- Add `emphasis` property that works the same as in `<sl-badge>`
9+
- Use relative font sizes & line heights
10+
- Refactor to use contextual tokens

chromatic/.storybook/stories/all.stories.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { updateTheme } from '../../../.storybook/themes.js';
22
import { All as AllAccordion } from '../../../packages/components/accordion/src/accordion.stories';
3-
import { All as AllAvatar } from '../../../packages/components/avatar/src/avatar.stories';
3+
import { Colors, Sizes } from '../../../packages/components/avatar/src/avatar.stories';
44
import { All as AllBadge } from '../../../packages/components/badge/src/badge.stories';
55
import { All as AllBreadcrumbs } from '../../../packages/components/breadcrumbs/src/breadcrumbs.stories';
66
import { All as AllButton } from '../../../packages/components/button/src/button.stories';
@@ -63,7 +63,8 @@ export default {
6363
* The All story always needs its own `render` function, otherwise this doesn't work.
6464
*/
6565
export const Accordion = { render: AllAccordion.render };
66-
export const Avatar = { render: AllAvatar.render };
66+
export const AvatarColors = { render: Colors.render };
67+
export const AvatarSizes = { render: Sizes.render };
6768
export const Badge = { render: AllBadge.render };
6869
export const Breadcrumbs = { render: AllBreadcrumbs.render };
6970
export const Button = { render: AllButton.render };

packages/components/avatar/src/avatar.scss

Lines changed: 173 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,113 @@
11
:host {
2-
--_badge-inset: var(--sl-space-avatar-badge-inset-md);
3-
--_badge-margin: var(--sl-space-avatar-badge-margin);
4-
--_block-gap: var(--sl-space-avatar-block-md);
5-
--_icon-size: var(--sl-size-icon-md);
6-
--_inline-gap: var(--sl-space-avatar-inline-md);
7-
--_heading-font: var(--sl-text-avatar-header-md);
8-
--_initials-font: var(--sl-text-avatar-initials-md);
9-
--_outline: var(--sl-border-width-focusring-default) solid var(--sl-color-focusring-default);
10-
--_outline-offset: calc(var(--sl-border-width-focusring-offset) * 2);
11-
--_outline-radius: var(--sl-border-radius-focusring-default);
12-
--_picture-size: var(--sl-size-avatar-md);
13-
--_subheading-font: var(--sl-text-avatar-subheader-md);
2+
--_badge-inset: calc(var(--sl-size-025) * -1);
3+
--_background: var(--sl-color-background-accent-grey-subtle);
4+
--_color: var(--sl-color-foreground-accent-grey-bold);
5+
--_gap-block: var(--sl-size-100);
6+
--_gap-inline: var(--sl-size-100);
7+
--_heading-fontSize: 1em;
8+
--_heading-lineHeight: calc((18 / 14) * 1em);
9+
--_icon-size: var(--sl-size-200);
10+
--_initials-fontSize: calc((12 / 14) * 1em);
11+
--_initials-lineHeight: calc((16 / 12) * 1em);
12+
--_picture-size: var(--sl-size-400);
13+
--_subheading-fontSize: calc((12 / 14) * 1em);
14+
--_subheading-lineHeight: calc((16 / 12) * 1em);
1415

1516
display: inline-flex;
16-
outline: 0;
17+
outline: transparent solid var(--sl-size-borderWidth-focusRing);
18+
outline-offset: var(--sl-size-outlineOffset-default);
19+
}
20+
21+
:host([color='blue']) {
22+
--_background: var(--sl-color-background-accent-blue-subtle);
23+
--_color: var(--sl-color-foreground-accent-blue-bold);
24+
}
25+
26+
:host([color='blue'][emphasis='bold']) {
27+
--_background: var(--sl-color-background-accent-blue-bold);
28+
--_color: var(--sl-color-foreground-accent-blue-onBold);
29+
}
30+
31+
:host([color='green']) {
32+
--_background: var(--sl-color-background-accent-green-subtle);
33+
--_color: var(--sl-color-foreground-accent-green-bold);
34+
}
35+
36+
:host([color='green'][emphasis='bold']) {
37+
--_background: var(--sl-color-background-accent-green-bold);
38+
--_color: var(--sl-color-foreground-accent-green-onBold);
39+
}
40+
41+
:host([color='orange']) {
42+
--_background: var(--sl-color-background-accent-orange-subtle);
43+
--_color: var(--sl-color-foreground-accent-orange-bold);
44+
}
45+
46+
:host([color='orange'][emphasis='bold']) {
47+
--_background: var(--sl-color-background-accent-orange-bold);
48+
--_color: var(--sl-color-foreground-accent-orange-onBold);
49+
}
50+
51+
:host([color='purple']) {
52+
--_background: var(--sl-color-background-accent-purple-subtle);
53+
--_color: var(--sl-color-foreground-accent-purple-bold);
54+
}
55+
56+
:host([color='purple'][emphasis='bold']) {
57+
--_background: var(--sl-color-background-accent-purple-bold);
58+
--_color: var(--sl-color-foreground-accent-purple-onBold);
59+
}
60+
61+
:host([color='red']) {
62+
--_background: var(--sl-color-background-accent-red-subtle);
63+
--_color: var(--sl-color-foreground-accent-red-bold);
64+
}
65+
66+
:host([color='red'][emphasis='bold']) {
67+
--_background: var(--sl-color-background-accent-red-bold);
68+
--_color: var(--sl-color-foreground-accent-red-onBold);
69+
}
70+
71+
:host([color='teal']) {
72+
--_background: var(--sl-color-background-accent-teal-subtle);
73+
--_color: var(--sl-color-foreground-accent-teal-bold);
74+
}
75+
76+
:host([color='teal'][emphasis='bold']) {
77+
--_background: var(--sl-color-background-accent-teal-bold);
78+
--_color: var(--sl-color-foreground-accent-teal-onBold);
79+
}
80+
81+
:host([color='yellow']) {
82+
--_background: var(--sl-color-background-accent-yellow-subtle);
83+
--_color: var(--sl-color-foreground-accent-yellow-bold);
84+
}
85+
86+
:host([color='yellow'][emphasis='bold']) {
87+
--_background: var(--sl-color-background-accent-yellow-bold);
88+
--_color: var(--sl-color-foreground-accent-yellow-onBold);
89+
}
90+
91+
:host([emphasis='bold']) {
92+
--_background: var(--sl-color-background-accent-grey-bold);
93+
--_color: var(--sl-color-foreground-accent-grey-onBold);
1794
}
1895

1996
:host(:focus-visible) {
20-
outline: var(--_outline);
21-
outline-offset: var(--sl-border-width-focusring-offset);
97+
outline-color: var(--sl-color-border-focused);
98+
}
99+
100+
:host([shape='square']) [part='picture'] {
101+
border-radius: var(--sl-size-borderRadius-default);
22102
}
23103

24104
:host([size='sm']) {
25-
--_block-gap: var(--sl-space-avatar-block-sm);
26-
--_inline-gap: var(--sl-space-avatar-inline-sm);
27-
--_heading-font: var(--sl-text-avatar-header-sm);
28-
--_picture-size: var(--sl-size-avatar-sm);
105+
--_picture-size: var(--sl-size-300);
29106
}
30107

31-
:host([size='sm']),
32-
:host([size='md']) {
108+
:host(:where([size='sm'], [size='md'])) {
33109
[part='wrapper'] {
34-
grid-template: 'picture spacer name' auto / auto var(--_inline-gap) 1fr;
110+
grid-template: 'picture spacer name' auto / auto var(--_gap-inline) 1fr;
35111
}
36112

37113
[part='name'] {
@@ -44,58 +120,74 @@
44120
}
45121

46122
:host([size='lg']) {
47-
--_badge-inset: var(--sl-space-avatar-badge-inset-lg);
48-
--_block-gap: var(--sl-space-avatar-block-lg);
49-
--_icon-size: var(--sl-size-icon-lg);
50-
--_inline-gap: var(--sl-space-avatar-inline-lg);
51-
--_heading-font: var(--sl-text-avatar-header-lg);
52-
--_initials-font: var(--sl-text-avatar-initials-lg);
53-
--_picture-size: var(--sl-size-avatar-lg);
54-
--_subheading-font: var(--sl-text-avatar-subheader-lg);
123+
--_icon-size: var(--sl-size-250);
124+
--_initials-fontSize: 1em;
125+
--_initials-lineHeight: calc((20 / 14) * 1em);
126+
--_picture-size: var(--sl-size-500);
127+
}
128+
129+
:host(:where([size='lg'], [size='xl'])) {
130+
--_badge-inset: calc(var(--sl-size-050) * -1);
131+
}
132+
133+
:host(:where([size='lg'], [size='xl'], [size='2xl'], [size='3xl'], [size='4xl'])) {
134+
--_gap-inline: var(--sl-size-200);
55135
}
56136

57137
:host([size='xl']) {
58-
--_badge-inset: var(--sl-space-avatar-badge-inset-xl);
59-
--_block-gap: var(--sl-space-avatar-block-xl);
60-
--_icon-size: var(--sl-size-icon-xl);
61-
--_inline-gap: var(--sl-space-avatar-inline-xl);
62-
--_heading-font: var(--sl-text-avatar-header-xl);
63-
--_initials-font: var(--sl-text-avatar-initials-xl);
64-
--_picture-size: var(--sl-size-avatar-xl);
65-
--_subheading-font: var(--sl-text-avatar-subheader-xl);
138+
--_icon-size: var(--sl-size-300);
139+
--_initials-fontSize: calc((18 / 14) * 1em);
140+
--_initials-lineHeight: calc((28 / 18) * 1em);
141+
--_picture-size: var(--sl-size-600);
142+
}
143+
144+
:host(:where([size='xl'], [size='2xl'], [size='3xl'])) {
145+
--_subheading-fontSize: 1em;
146+
--_subheading-lineHeight: 1lh;
66147
}
67148

68149
:host([size='2xl']) {
69-
--_badge-inset: var(--sl-space-avatar-badge-inset-2xl);
70-
--_block-gap: var(--sl-space-avatar-block-2xl);
71-
--_icon-size: var(--sl-size-icon-2xl);
72-
--_inline-gap: var(--sl-space-avatar-inline-2xl);
73-
--_heading-font: var(--sl-text-avatar-header-2xl);
74-
--_initials-font: var(--sl-text-avatar-initials-2xl);
75-
--_picture-size: var(--sl-size-avatar-2xl);
76-
--_subheading-font: var(--sl-text-avatar-subheader-2xl);
150+
--_icon-size: var(--sl-size-400);
151+
--_initials-fontSize: calc((24 / 14) * 1em);
152+
--_initials-lineHeight: calc((34 / 24) * 1em);
153+
--_picture-size: var(--sl-size-800);
154+
}
155+
156+
:host(:where([size='2xl'], [size='3xl'])) {
157+
--_badge-inset: 0px;
158+
--_heading-fontSize: calc((16 / 14) * 1em);
159+
--_heading-lineHeight: calc((20 / 16) * 1em);
77160
}
78161

79162
:host([size='3xl']) {
80-
--_badge-inset: var(--sl-space-avatar-badge-inset-3xl);
81-
--_block-gap: var(--sl-space-avatar-block-3xl);
82-
--_icon-size: var(--sl-size-icon-3xl);
83-
--_inline-gap: var(--sl-space-avatar-inline-3xl);
84-
--_heading-font: var(--sl-text-avatar-header-3xl);
85-
--_initials-font: var(--sl-text-avatar-initials-3xl);
86-
--_picture-size: var(--sl-size-avatar-3xl);
87-
--_subheading-font: var(--sl-text-avatar-subheader-3xl);
163+
--_icon-size: var(--sl-size-600);
164+
--_initials-fontSize: calc((32 / 14) * 1em);
165+
--_initials-lineHeight: calc((34 / 32) * 1em);
166+
--_picture-size: var(--sl-size-1000);
88167
}
89168

90169
:host([size='4xl']) {
91-
--_badge-inset: var(--sl-space-avatar-badge-inset-4xl);
92-
--_block-gap: var(--sl-space-avatar-block-3xl);
93-
--_icon-size: var(--sl-size-icon-4xl);
94-
--_inline-gap: var(--sl-space-avatar-inline-3xl);
95-
--_heading-font: var(--sl-text-avatar-header-4xl);
96-
--_initials-font: var(--sl-text-avatar-initials-4xl);
97-
--_picture-size: var(--sl-size-avatar-4xl);
98-
--_subheading-font: var(--sl-text-avatar-subheader-4xl);
170+
--_badge-inset: var(--sl-size-150);
171+
--_heading-fontSize: calc((20 / 14) * 1em);
172+
--_heading-lineHeight: calc((24 / 20) * 1em);
173+
--_icon-size: var(--sl-size-800);
174+
--_initials-fontSize: calc((64 / 14) * 1em);
175+
--_initials-lineHeight: 1em;
176+
--_picture-size: calc(2 * var(--sl-size-1000)); // 2 * 80px = 160px
177+
--_subheading-fontSize: calc((16 / 14) * 1em);
178+
--_subheading-lineHeight: calc((24 / 16) * 1em);
179+
}
180+
181+
:host([shape='square']) {
182+
--_badge-inset: calc(var(--sl-size-050) * -1);
183+
}
184+
185+
:host([shape='square']:where([size='lg'], [size='xl'], [size='2xl'])) {
186+
--_badge-inset: calc(var(--sl-size-075) * -1);
187+
}
188+
189+
:host([shape='square']:where([size='3xl'], [size='4xl'])) {
190+
--_badge-inset: calc(var(--sl-size-150) * -1);
99191
}
100192

101193
:host([image-only]) {
@@ -107,7 +199,7 @@
107199
}
108200

109201
:host([vertical]) [part='wrapper'] {
110-
grid-template: 'picture' auto 'spacer' var(--_block-gap) 'name' auto 'subheader' auto / 1fr;
202+
grid-template: 'picture' auto 'spacer' var(--_gap-block) 'name' auto 'subheader' auto / 1fr;
111203
justify-items: center;
112204
text-align: center;
113205

@@ -119,30 +211,31 @@
119211

120212
[part='wrapper'] {
121213
align-items: center;
122-
border-radius: var(--_outline-radius);
214+
border-radius: var(--sl-size-borderRadius-default);
123215
display: grid;
124-
grid-template: 'picture spacer name' auto 'picture spacer subheader' auto / auto var(--_inline-gap) 1fr;
216+
grid-template: 'picture spacer name' auto 'picture spacer subheader' auto / auto var(--_gap-inline) 1fr;
125217
}
126218

127219
a {
128220
color: currentcolor;
221+
outline: transparent solid var(--sl-size-borderWidth-focusRing);
222+
outline-offset: var(--sl-size-outlineOffset-default);
129223
text-decoration: none;
130224

131225
&:hover [part='name'] {
132-
color: var(--sl-color-href-hover-foreground);
226+
color: var(--sl-color-link-hover);
133227
}
134228

135229
&:active [part='name'] {
136-
color: var(--sl-color-href-active-foreground);
230+
color: var(--sl-color-link-active);
137231
}
138232

139233
&:focus-visible {
140-
outline: var(--_outline);
141-
outline-offset: var(--_outline-offset);
234+
outline-color: var(--sl-color-border-focused);
142235
}
143236

144237
[part='name'] {
145-
color: var(--sl-color-href-idle-foreground);
238+
color: var(--sl-color-link-idle);
146239
text-decoration: underline;
147240
}
148241
}
@@ -160,10 +253,10 @@ a {
160253
}
161254

162255
[part='picture'] {
163-
background: var(--sl-color-avatar-background);
256+
background: var(--_background);
164257
block-size: var(--_picture-size);
165258
border-radius: 50%;
166-
color: var(--sl-color-avatar-foreground);
259+
color: var(--_color);
167260
display: inline-flex;
168261
inline-size: var(--_picture-size);
169262
overflow: clip;
@@ -187,25 +280,29 @@ slot[name='fallback'] {
187280
}
188281

189282
[part='initials'] {
190-
font: var(--_initials-font);
283+
font-size: var(--_initials-fontSize);
284+
font-weight: var(--sl-text-new-typeset-fontWeight-semiBold);
285+
line-height: var(--_initials-lineHeight);
191286
}
192287

193288
[part='name'] {
194289
align-self: end;
195290
display: block;
196-
font: var(--_heading-font);
291+
font-size: var(--_heading-fontSize);
197292
grid-area: name;
293+
line-height: var(--_heading-lineHeight);
198294
overflow: hidden;
199295
text-overflow: ellipsis;
200296
white-space: nowrap;
201297
}
202298

203299
slot:not([name]) {
204300
align-self: start;
205-
color: var(--sl-color-avatar-subheader);
301+
color: var(--sl-color-foreground-subtlest);
206302
display: block;
207-
font: var(--_subheading-font);
303+
font-size: var(--_subheading-fontSize);
208304
grid-area: subheader;
305+
line-height: var(--_subheading-lineHeight);
209306
overflow: hidden;
210307
text-overflow: ellipsis;
211308
white-space: nowrap;

0 commit comments

Comments
 (0)