@dialpad/dialtone-css
Version:
Dialpad's design system
411 lines (362 loc) • 14.9 kB
text/less
//
// DIALTONE
// COMPONENTS: Avatars
//
// These are avatars classes for Dialpad's design system Dialtone.
// For further documentation of these and other classes,
// visit https://dialtone.dialpad.com/components/avatars
//
// TABLE OF CONTENTS
// • BASE STYLE
// • COLOR VARIANTS
// • CHILDREN
// • SIZES
// • VARIANTS
//
// ============================================================================
// $ BASE STYLE
// ----------------------------------------------------------------------------
.d-avatar {
// Component CSS Vars
// ------------------------------------------------------------------------
--avatar-color-background: var(--dt-avatar-color-background-000);
--avatar-color-text: var(--dt-avatar-color-foreground);
--avatar-size-shape: var(--dt-size-600);
--avatar-size-image: var(--dt-size-100-percent);
--avatar-size-text: var(--dt-font-size-200);
--avatar-presence-position-right: var(--dt-space-200-negative);
--avatar-presence-position-bottom: var(--dt-space-200-negative);
--avatar-count-color-shadow: var(--dt-shell-color-surface-default);
--avatar-presence-mask-size: calc(var(--dt-size-450) + var(--dt-size-50));
position: relative;
display: flex;
color: var(--avatar-color-text);
// -- COLOR VARIANTS
// ------------------------------------------------------------------------
&--color-000 { --avatar-color-background: var(--dt-avatar-color-background-000); }
&--color-100 { --avatar-color-background: var(--dt-avatar-color-background-100); }
&--color-200 { --avatar-color-background: var(--dt-avatar-color-background-200); }
&--color-300 { --avatar-color-background: var(--dt-avatar-color-background-300); }
&--color-400 { --avatar-color-background: var(--dt-avatar-color-background-400); }
&--color-500 { --avatar-color-background: var(--dt-avatar-color-background-500); }
&--color-600 { --avatar-color-background: var(--dt-avatar-color-background-600); }
&--color-700 { --avatar-color-background: var(--dt-avatar-color-background-700); }
&--color-800 { --avatar-color-background: var(--dt-avatar-color-background-800); }
&--color-900 { --avatar-color-background: var(--dt-avatar-color-background-900); }
&--color-1000 { --avatar-color-background: var(--dt-avatar-color-background-1000); }
&--color-1100 { --avatar-color-background: var(--dt-avatar-color-background-1100); }
&--color-1200 { --avatar-color-background: var(--dt-avatar-color-background-1200); }
&--color-1300 { --avatar-color-background: var(--dt-avatar-color-background-1300); }
&--color-1400 { --avatar-color-background: var(--dt-avatar-color-background-1400); }
&--color-1500 { --avatar-color-background: var(--dt-avatar-color-background-1500); }
&--color-1600 { --avatar-color-background: var(--dt-avatar-color-background-1600); }
&--color-1700 { --avatar-color-background: var(--dt-avatar-color-background-1700); }
&--color-1800 { --avatar-color-background: var(--dt-avatar-color-background-1800); }
// -- CHILDREN
// ------------------------------------------------------------------------
&__canvas {
display: flex;
align-items: center;
justify-content: center;
inline-size: var(--avatar-size-shape);
block-size: var(--avatar-size-shape);
overflow: hidden;
background-color: var(--avatar-color-background);
border-radius: var(--dt-size-radius-pill);
}
&__image {
inline-size: var(--avatar-size-image);
block-size: var(--avatar-size-image);
object-fit: cover;
border-radius: var(--dt-size-radius-pill);
}
&--image-loaded {
background-color: var(--dt-color-neutral-transparent);
background-image: unset;
}
&__initials {
position: absolute;
z-index: var(--zi-base);
font-weight: var(--dt-font-weight-bold);
font-size: var(--avatar-size-text);
line-height: var(--dt-font-line-height-100);
text-transform: uppercase;
user-select: none;
}
&__icon {
display: flex;
}
&__presence {
position: absolute;
right: var(--avatar-presence-position-right);
bottom: var(--avatar-presence-position-bottom);
z-index: var(--zi-base);
display: flex;
}
&__count {
position: absolute;
right: var(--dt-space-0);
bottom: var(--dt-space-0);
z-index: var(--zi-base);
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
min-width: calc(var(--dt-size-300) * 3.5);
padding: var(--dt-space-200) calc(var(--dt-space-200) + var(--dt-space-100));
color: var(--dt-color-foreground-primary-inverted);
font-weight: var(--dt-font-weight-bold);
font-size: calc(var(--dt-font-size-100) - var(--dt-size-200));
line-height: var(--dt-font-line-height-100);
white-space: nowrap;
text-align: center;
background-color: var(--dt-color-surface-strong);
border-radius: var(--dt-size-radius-pill);
box-shadow: 0 0 0 var(--dt-size-200) var(--avatar-count-color-shadow);
.d-recipe-leftbar-row--selected &,
.d-recipe-leftbar-row__primary:hover & {
--avatar-count-color-shadow: var(--dt-shell-action-color-background-primary-hover);
}
--avatar-count-color-shadow: var(--dt-color-neutral-transparent);
}
&--clickable {
--avatar-color-border: var(--dt-color-neutral-transparent);
padding: 0;
background-color: var(--dt-color-neutral-transparent);
border: var(--dt-size-border-100) solid var(--avatar-color-border);
border-radius: var(--dt-size-radius-circle);
cursor: pointer;
&:focus-visible {
outline: none;
box-shadow: var(--dt-shadow-focus);
}
&:hover {
--avatar-color-border: var(--dt-color-border-default);
}
&:active {
--avatar-color-border: var(--dt-color-border-moderate);
transform: scale(0.98);
}
}
&__overlay {
position: absolute;
z-index: var(--zi-base);
display: flex;
align-items: center;
justify-content: center;
inline-size: var(--dt-size-100-percent);
block-size: var(--dt-size-100-percent);
background-color: var(--dt-color-surface-contrast-opaque);
border-radius: var(--dt-size-radius-circle);
opacity: var(--dt-opacity-900);
&-icon {
inline-size: var(--dt-size-100-percent);
color: var(--dt-color-foreground-primary-inverted);
}
&-text {
inline-size: var(--dt-size-100-percent);
color: var(--dt-color-foreground-primary-inverted);
font-weight: var(--dt-font-weight-bold);
font-size: var(--dt-font-size-200);
text-align: center;
}
}
// -- SIZES
// ------------------------------------------------------------------------
&--xs {
--avatar-size-shape: calc(var(--dt-size-500) + var(--dt-size-200));
--avatar-presence-position-right: var(--dt-space-300-negative);
--avatar-presence-position-bottom: var(--dt-space-300-negative);
--avatar-presence-mask-offset-x: var(--dt-space-200);
--avatar-presence-mask-offset-y: var(--dt-space-200);
}
&--sm {
--avatar-size-shape: var(--dt-size-550);
--avatar-size-text: var(--dt-font-size-100);
--avatar-presence-position-right: var(--dt-space-200-negative);
--avatar-presence-position-bottom: var(--dt-space-200-negative);
--avatar-presence-mask-offset-x: var(--dt-space-300);
--avatar-presence-mask-offset-y: var(--dt-space-300);
}
&--md {
--avatar-size-shape: var(--dt-size-600);
--avatar-size-text: var(--dt-font-size-200);
--avatar-presence-position-right: var(--dt-space-100-negative);
--avatar-presence-position-bottom: var(--dt-space-100-negative);
--avatar-presence-mask-offset-x: calc(
var(--dt-space-350) - var(--dt-space-100)
);
--avatar-presence-mask-offset-y: calc(
var(--dt-space-350) - var(--dt-space-100)
);
}
&--lg {
--avatar-size-shape: var(--dt-size-650);
--avatar-size-text: var(--dt-font-size-300);
--avatar-presence-position-right: var(--dt-space-100);
--avatar-presence-position-bottom: var(--dt-space-100);
--avatar-presence-mask-offset-x: calc(
var(--dt-space-400) - var(--dt-space-100)
);
--avatar-presence-mask-offset-y: calc(
var(--dt-space-400) - var(--dt-space-100)
);
}
&--xl {
--avatar-size-shape: var(--dt-size-700);
--avatar-size-text: var(--dt-font-size-400);
--avatar-presence-position-right: var(--dt-space-300);
--avatar-presence-position-bottom: var(--dt-space-300);
--avatar-presence-mask-offset-x: calc(
var(--dt-space-450) - var(--dt-space-200)
);
--avatar-presence-mask-offset-y: calc(
var(--dt-space-450) - var(--dt-space-200)
);
}
// -- PRESENCE
// ------------------------------------------------------------------------
&--presence {
> .d-avatar__canvas,
> .d-avatar__overlay {
mask: radial-gradient(
circle calc(var(--avatar-presence-mask-size) / 2) at
calc(var(--dt-size-100-percent) - var(--avatar-presence-mask-offset-x))
calc(var(--dt-size-100-percent) - var(--avatar-presence-mask-offset-y)),
var(--dt-color-neutral-transparent) 92%, // less than 99% to smooth the edges
var(--dt-color-neutral-white) var(--dt-size-100-percent)
);
}
&.d-avatar--clickable {
border-color: var(--dt-color-neutral-transparent);
// The clickable border causes issues with masking
// Use a pseudo-element to simulate the clickable border and mask as needed
&::before {
position: absolute;
background-color: var(--dt-color-neutral-transparent);
border: var(--dt-size-border-100) solid var(--avatar-color-border);
border-radius: var(--dt-size-radius-circle);
content: "";
inset: calc(var(--dt-space-100) * -1);
mask: radial-gradient(
circle calc(var(--avatar-presence-mask-size) / 2) at
calc(
var(--dt-size-100-percent) - var(--avatar-presence-mask-offset-x) - var(--dt-size-100)
)
calc(
var(--dt-size-100-percent) - var(--avatar-presence-mask-offset-y) - var(--dt-size-100)
),
var(--dt-color-neutral-transparent) 92%, // less than 99% to smooth the edges
var(--dt-color-neutral-white) var(--dt-size-100-percent)
);
}
}
// override default presence border
> .d-presence {
--presence-color-border-base: var(--dt-color-neutral-transparent);
}
}
// Recipe overrides (Leftbar states)
.d-recipe-leftbar-row--selected &,
.d-recipe-leftbar-row:hover &,
.d-recipe-leftbar-row:focus-within &,
.d-recipe-leftbar-row__primary:hover & {
&--presence {
.d-presence {
--presence-color-border-base: var(--dt-color-neutral-transparent);
}
}
}
// -- GROUP
// ------------------------------------------------------------------------
&--group {
--avatar-size-shape: calc(var(--dt-size-300) * 4.5);
inline-size: var(--dt-size-550);
block-size: var(--dt-size-550);
--avatar-count-mask-size: calc(
var(--dt-size-500) + var(--dt-size-200) + var(--dt-size-100)
);
--avatar-count-mask-outer-circle-radius: calc(
var(--dt-size-400) + var(--dt-size-100)
);
--avatar-count-mask-outer-circle-x: calc(
var(--dt-size-400) + var(--dt-size-100)
);
--avatar-count-mask-outer-circle-y: calc(
var(--dt-size-400) + var(--dt-size-100)
);
--avatar-count-mask-offset-x: var(--dt-space-100);
--avatar-count-mask-offset-y: var(--dt-space-100);
--avatar-count-mask-svg-w: calc(var(--dt-size-625) - var(--dt-size-200));
--avatar-count-mask-svg-h: calc(var(--dt-size-500) + var(--dt-size-200));
--avatar-count-color-shadow: var(--dt-color-neutral-transparent);
&.d-avatar--clickable {
border: none ;
}
> .d-avatar__canvas,
> .d-avatar__overlay {
mask: radial-gradient(
circle calc(var(--avatar-count-mask-size) / 2) at
calc(var(--dt-size-100-percent) - var(--avatar-count-mask-offset-x))
calc(var(--dt-size-100-percent) - var(--avatar-count-mask-offset-y)),
var(--dt-color-neutral-transparent) 92%, // less than 99% to smooth the edges
var(--dt-color-neutral-white) var(--dt-size-100-percent)
);
will-change: transform;
}
// These modifiers set the mask and count size and must be used together with `d-avatar--group`.
// Example: <div class="d-avatar d-avatar--group d-avatar--group-digits-2">
&-digits-2 {
--avatar-count-mask-offset-x: var(--dt-space-300);
--avatar-count-mask-offset-y: var(--dt-space-400);
> .d-avatar__canvas,
> .d-avatar__overlay {
mask:
radial-gradient(
circle var(--avatar-count-mask-outer-circle-radius) at
var(--avatar-count-mask-outer-circle-x)
var(--avatar-count-mask-outer-circle-y),
var(--dt-color-neutral-white) 99%,
var(--dt-color-neutral-transparent) var(--dt-size-100-percent)
),
url('data:image/svg+xml,<svg width="40" height="18" viewBox="0 0 40 18" fill="white" xmlns="http://www.w3.org/2000/svg"><rect width="40" height="18" rx="9" fill="white"/></svg>')
var(--avatar-count-mask-offset-x)
var(--avatar-count-mask-offset-y) / var(--avatar-count-mask-svg-w)
var(--avatar-count-mask-svg-h) no-repeat;
-webkit-mask-composite: subtract;
mask-composite: subtract;
will-change: transform;
}
> .d-avatar__count {
padding-inline: var(--dt-space-0);
inline-size: calc(var(--dt-size-500) + var(--dt-size-200));
}
}
&-digits-3 {
--avatar-count-mask-offset-x: var(--dt-space-300-negative);
--avatar-count-mask-offset-y: var(--dt-space-400);
> .d-avatar__canvas,
> .d-avatar__overlay {
mask:
radial-gradient(
circle var(--avatar-count-mask-outer-circle-radius) at
var(--avatar-count-mask-outer-circle-x)
var(--avatar-count-mask-outer-circle-y),
var(--dt-color-neutral-white) 99%,
var(--dt-color-neutral-transparent) var(--dt-size-100-percent)
),
url('data:image/svg+xml,<svg width="40" height="18" viewBox="0 0 40 18" fill="white" xmlns="http://www.w3.org/2000/svg"><rect width="40" height="18" rx="9" /></svg>')
var(--avatar-count-mask-offset-x)
var(--avatar-count-mask-offset-y) / var(--avatar-count-mask-svg-w)
var(--avatar-count-mask-svg-h) no-repeat;
-webkit-mask-composite: subtract;
mask-composite: subtract;
will-change: transform;
}
> .d-avatar__count {
padding-inline: var(--dt-space-0);
inline-size: calc(var(--dt-size-550) + var(--dt-size-200));
}
}
}
}