Skip to content

Commit

Permalink
Correct width of AvatarStack (#4082)
Browse files Browse the repository at this point in the history
* corrects width of avatar stack

* adds changeset
  • Loading branch information
mperrotti authored Dec 20, 2023
1 parent f46c071 commit c2809d6
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 23 deletions.
8 changes: 8 additions & 0 deletions .changeset/cool-buckets-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@primer/react': patch
---

- Corrects the math to calculate the width of AvatarStack containers.
- Prevents `.pc-AvatarStackBody` from being removed from document flow by `position: absolute`. This isn't strictly necessary now that we're correctly setting the width of the stack, but it's an extra level of safety for preserving the correct layout.

<!-- Changed components: AvatarStack -->
45 changes: 30 additions & 15 deletions src/AvatarStack/AvatarStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,14 @@ const AvatarStackWrapper = styled.span<StyledAvatarStackWrapperProps>`
--avatar-two-margin: calc(var(--avatar-stack-size) * -0.55);
--avatar-three-margin: calc(var(--avatar-stack-size) * -0.85);
// this calc explained:
// 1. avatar size + the non-overlapping part of the second avatar
// 2. + the non-overlapping part of the second and third avatar
// 3. + the border widths of all previous avatars
--avatar-stack-three-plus-min-width: calc(
var(--avatar-stack-size) +
calc(
calc(var(--avatar-stack-size) + var(--avatar-two-margin)) +
calc(var(--avatar-stack-size) + var(--avatar-three-margin)) * 2
) + calc(var(--avatar-border-width) * 3)
);
display: flex;
position: relative;
height: var(--avatar-stack-size);
min-width: ${props => (props.count === 1 ? 'var(--avatar-stack-size)' : props.count === 2 ? '30px' : '38px')};
min-width: var(--avatar-stack-size);
.pc-AvatarStackBody {
display: flex;
position: absolute;
width: var(--avatar-stack-three-plus-min-width);
}
.pc-AvatarItem {
Expand Down Expand Up @@ -92,8 +80,30 @@ const AvatarStackWrapper = styled.span<StyledAvatarStackWrapperProps>`
);
}
&.pc-AvatarStack--three {
// this calc explained:
// 1. avatar size + the non-overlapping part of the second avatar
// 2. + the non-overlapping part of the third avatar
min-width: calc(
var(--avatar-stack-size) +
calc(
calc(var(--avatar-stack-size) + var(--avatar-two-margin)) +
calc(var(--avatar-stack-size) + var(--avatar-three-margin))
)
);
}
&.pc-AvatarStack--three-plus {
min-width: var(--avatar-stack-three-plus-min-width);
// this calc explained:
// 1. avatar size + the non-overlapping part of the second avatar
// 2. + the non-overlapping part of the third and fourth avatar
min-width: calc(
var(--avatar-stack-size) +
calc(
calc(var(--avatar-stack-size) + var(--avatar-two-margin)) +
calc(var(--avatar-stack-size) + var(--avatar-three-margin)) * 2
)
);
}
&.pc-AvatarStack--right {
Expand Down Expand Up @@ -150,6 +160,10 @@ const AvatarStackWrapper = styled.span<StyledAvatarStackWrapperProps>`
}
}
.pc-AvatarStack--disableExpand {
position: relative;
}
${sx};
`
const transformChildren = (children: React.ReactNode) => {
Expand All @@ -173,7 +187,8 @@ const AvatarStack = ({children, alignRight, disableExpand, size, sx: sxProp = de
const count = React.Children.count(children)
const wrapperClassNames = clsx({
'pc-AvatarStack--two': count === 2,
'pc-AvatarStack--three-plus': count > 2,
'pc-AvatarStack--three': count === 3,
'pc-AvatarStack--three-plus': count > 3,
'pc-AvatarStack--right': alignRight,
})
const bodyClassNames = clsx('pc-AvatarStackBody', {
Expand Down
28 changes: 20 additions & 8 deletions src/__tests__/__snapshots__/AvatarStack.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ exports[`Avatar renders consistently 1`] = `
--avatar-border-width: 1px;
--avatar-two-margin: calc(var(--avatar-stack-size) * -0.55);
--avatar-three-margin: calc(var(--avatar-stack-size) * -0.85);
--avatar-stack-three-plus-min-width: calc( var(--avatar-stack-size) + calc( calc(var(--avatar-stack-size) + var(--avatar-two-margin)) + calc(var(--avatar-stack-size) + var(--avatar-three-margin)) * 2 ) + calc(var(--avatar-border-width) * 3) );
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
position: relative;
height: var(--avatar-stack-size);
min-width: 38px;
min-width: var(--avatar-stack-size);
--avatar-stack-size: 20px;
}
Expand All @@ -22,7 +21,6 @@ exports[`Avatar renders consistently 1`] = `
display: -ms-flexbox;
display: flex;
position: absolute;
width: var(--avatar-stack-three-plus-min-width);
}
.c0 .pc-AvatarItem {
Expand Down Expand Up @@ -72,8 +70,12 @@ exports[`Avatar renders consistently 1`] = `
min-width: calc( var(--avatar-stack-size) + calc(var(--avatar-stack-size) + var(--avatar-two-margin)) + var(--avatar-border-width) );
}
.c0.pc-AvatarStack--three {
min-width: calc( var(--avatar-stack-size) + calc( calc(var(--avatar-stack-size) + var(--avatar-two-margin)) + calc(var(--avatar-stack-size) + var(--avatar-three-margin)) ) );
}
.c0.pc-AvatarStack--three-plus {
min-width: var(--avatar-stack-three-plus-min-width);
min-width: calc( var(--avatar-stack-size) + calc( calc(var(--avatar-stack-size) + var(--avatar-two-margin)) + calc(var(--avatar-stack-size) + var(--avatar-three-margin)) * 2 ) );
}
.c0.pc-AvatarStack--right {
Expand Down Expand Up @@ -134,6 +136,10 @@ exports[`Avatar renders consistently 1`] = `
margin-left: 0;
}
.c0 .pc-AvatarStack--disableExpand {
position: relative;
}
<span
className="c0 pc-AvatarStack--three-plus"
>
Expand Down Expand Up @@ -170,14 +176,13 @@ exports[`Avatar respects alignRight props 1`] = `
--avatar-border-width: 1px;
--avatar-two-margin: calc(var(--avatar-stack-size) * -0.55);
--avatar-three-margin: calc(var(--avatar-stack-size) * -0.85);
--avatar-stack-three-plus-min-width: calc( var(--avatar-stack-size) + calc( calc(var(--avatar-stack-size) + var(--avatar-two-margin)) + calc(var(--avatar-stack-size) + var(--avatar-three-margin)) * 2 ) + calc(var(--avatar-border-width) * 3) );
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
position: relative;
height: var(--avatar-stack-size);
min-width: 38px;
min-width: var(--avatar-stack-size);
--avatar-stack-size: 20px;
}
Expand All @@ -187,7 +192,6 @@ exports[`Avatar respects alignRight props 1`] = `
display: -ms-flexbox;
display: flex;
position: absolute;
width: var(--avatar-stack-three-plus-min-width);
}
.c0 .pc-AvatarItem {
Expand Down Expand Up @@ -237,8 +241,12 @@ exports[`Avatar respects alignRight props 1`] = `
min-width: calc( var(--avatar-stack-size) + calc(var(--avatar-stack-size) + var(--avatar-two-margin)) + var(--avatar-border-width) );
}
.c0.pc-AvatarStack--three {
min-width: calc( var(--avatar-stack-size) + calc( calc(var(--avatar-stack-size) + var(--avatar-two-margin)) + calc(var(--avatar-stack-size) + var(--avatar-three-margin)) ) );
}
.c0.pc-AvatarStack--three-plus {
min-width: var(--avatar-stack-three-plus-min-width);
min-width: calc( var(--avatar-stack-size) + calc( calc(var(--avatar-stack-size) + var(--avatar-two-margin)) + calc(var(--avatar-stack-size) + var(--avatar-three-margin)) * 2 ) );
}
.c0.pc-AvatarStack--right {
Expand Down Expand Up @@ -299,6 +307,10 @@ exports[`Avatar respects alignRight props 1`] = `
margin-left: 0;
}
.c0 .pc-AvatarStack--disableExpand {
position: relative;
}
<span
className="c0 pc-AvatarStack--three-plus pc-AvatarStack--right"
>
Expand Down

0 comments on commit c2809d6

Please sign in to comment.