@liveblocks/react-ui
Version:
A set of React pre-built components for the Liveblocks products. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.
2,130 lines (1,798 loc) • 47.3 kB
CSS
@import "./utils";
@import "./constants";
.lb-root {
/**
* Basic
*/
--lb-radius: 0.5em;
--lb-spacing: 1em;
--lb-accent: #17f;
--lb-accent-foreground: #fff;
--lb-destructive: #f45;
--lb-destructive-foreground: #fff;
--lb-background: #fff;
--lb-foreground: #111;
/**
* Advanced
*/
--lb-line-height: 1.5;
--lb-icon-size: 20px;
--lb-icon-weight: 1.5px;
--lb-avatar-radius: 50%;
--lb-button-radius: calc(0.75 * var(--lb-radius));
--lb-transition-duration: 0.1s;
--lb-transition-easing: cubic-bezier(0.4, 0, 0.2, 1);
--lb-highlight-shadow: inset 0 0 0 1px rgb(0 0 0 / 10%);
--lb-elevation-shadow: $lb-elevation-shadow;
--lb-tooltip-shadow: $lb-tooltip-shadow;
--lb-accent-contrast: 8%;
--lb-destructive-contrast: 8%;
--lb-foreground-contrast: 8%;
/**
* Colors
*/
--lb-background-foreground-faint: color-mix-scale(
var(--lb-background),
var(--lb-foreground),
var(--lb-foreground-contrast),
50
);
--lb-background-accent-faint: color-mix-scale(
var(--lb-background),
var(--lb-accent),
var(--lb-accent-contrast),
50
);
--lb-background-accent-subtle: color-mix-scale(
var(--lb-background),
var(--lb-accent),
var(--lb-accent-contrast),
100
);
--lb-background-destructive-faint: color-mix-scale(
var(--lb-background),
var(--lb-destructive),
var(--lb-destructive-contrast),
50
);
--lb-background-destructive-subtle: color-mix-scale(
var(--lb-background),
var(--lb-destructive),
var(--lb-destructive-contrast),
100
);
--lb-accent-subtle: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-accent),
var(--lb-accent-contrast),
100
);
--lb-accent-moderate: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-accent),
var(--lb-accent-contrast),
400
);
--lb-accent-tertiary: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-accent),
var(--lb-accent-contrast),
600
);
--lb-accent-secondary: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-accent),
var(--lb-accent-contrast),
800
);
--lb-destructive-subtle: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-destructive),
var(--lb-destructive-contrast),
100
);
--lb-destructive-moderate: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-destructive),
var(--lb-destructive-contrast),
400
);
--lb-destructive-tertiary: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-destructive),
var(--lb-destructive-contrast),
600
);
--lb-destructive-secondary: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-destructive),
var(--lb-destructive-contrast),
800
);
--lb-foreground-subtle: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-foreground),
var(--lb-foreground-contrast),
100
);
--lb-foreground-moderate: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-foreground),
var(--lb-foreground-contrast),
400
);
--lb-foreground-tertiary: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-foreground),
var(--lb-foreground-contrast),
600
);
--lb-foreground-secondary: color-mix-scale(
var(--lb-dynamic-background),
var(--lb-foreground),
var(--lb-foreground-contrast),
800
);
--lb-selection: color-mix(in srgb, var(--lb-accent) 40%, transparent);
overflow-wrap: break-word;
accent-color: var(--lb-accent);
text-size-adjust: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
&,
*,
::before,
::after {
box-sizing: border-box;
transition: none var(--lb-transition-duration) var(--lb-transition-easing);
}
/* Define some variables only on first .lb-root instances */
&:where(:not(& &)) {
--lb-dynamic-background: var(--lb-background);
}
}
/*************************************
* States *
*************************************/
.lb-loading,
.lb-empty,
.lb-error {
position: absolute;
inset: 0;
display: flex;
justify-content: center;
align-items: center;
}
.lb-loading {
color: var(--lb-foreground-moderate);
}
.lb-empty,
.lb-error {
padding: var(--lb-spacing);
color: var(--lb-foreground-tertiary);
font-size: 0.875em;
text-align: center;
text-wrap: balance;
}
/*************************************
* Icon *
*************************************/
.lb-icon-container,
.lb-icon {
inline-size: var(--lb-icon-size);
block-size: var(--lb-icon-size);
}
.lb-icon-container {
display: flex;
justify-content: center;
align-items: center;
}
.lb-icon {
--lb-icon-background: var(--lb-dynamic-background);
* {
stroke-width: var(--lb-icon-weight);
vector-effect: non-scaling-stroke;
}
}
.lb-icon-spinner {
transform-origin: center;
animation: lb-animation-spin 0.75s linear infinite;
}
/*************************************
* Button *
*************************************/
.lb-button {
--lb-button-background: var(--lb-dynamic-background);
@include button;
display: flex;
justify-content: center;
align-items: center;
padding: calc(0.25 * var(--lb-spacing));
border-radius: var(--lb-button-radius);
background: var(--lb-button-background);
color: var(--lb-foreground-moderate);
&:where(.lb-button\:non-disableable:disabled) {
cursor: default;
}
&:where(:not(.lb-button\:non-disableable):disabled) {
opacity: 0.5;
cursor: not-allowed;
}
&:where(
:enabled:hover,
:enabled:focus-visible,
[aria-expanded="true"],
[aria-selected="true"]
) {
--lb-button-background: var(--lb-foreground-subtle);
color: var(--lb-foreground-tertiary);
}
&:where(
[data-variant="default"]:not(
:is(
:enabled:hover,
:enabled:focus-visible,
[aria-expanded="true"],
[aria-selected="true"],
[aria-pressed]
)
)
) {
background: transparent;
}
&:where([data-variant="primary"]) {
--lb-button-background: var(--lb-accent);
color: var(--lb-accent-foreground);
&:where(
:enabled:hover,
:enabled:focus-visible,
[aria-expanded="true"],
[aria-selected="true"]
) {
--lb-button-background: var(--lb-accent-secondary);
color: var(--lb-accent-foreground);
}
}
&:where([data-variant="outline"]) {
box-shadow: inset 0 0 0 1px var(--lb-foreground-subtle);
transition-property: background, color, opacity, box-shadow;
}
&:where(:has(.lb-button-label)) {
gap: calc(0.175 * var(--lb-spacing));
padding-inline: calc(0.55 * var(--lb-spacing));
&:where(:has(.lb-icon-container)) {
padding-inline-start: calc(0.4 * var(--lb-spacing));
}
}
&:where([data-variant="toolbar"]) {
color: var(--lb-foreground-tertiary);
&:where([aria-pressed="true"]) {
--lb-button-background: var(--lb-foreground-subtle);
color: var(--lb-foreground-secondary);
:where(.lb-icon *) {
stroke-width: calc(1.25 * var(--lb-icon-weight));
}
}
}
&:where([data-variant="secondary"]) {
--lb-button-background: var(--lb-foreground-subtle);
color: var(--lb-foreground-tertiary);
&:where(
:enabled:hover,
:enabled:focus-visible,
[aria-expanded="true"],
[aria-selected="true"]
) {
--lb-button-background: var(--lb-foreground);
color: var(--lb-dynamic-background);
}
}
&:where([data-size="large"]) {
padding: calc(0.5 * var(--lb-spacing));
&:where(:has(.lb-button-label)) {
gap: calc(0.35 * var(--lb-spacing));
padding-inline: calc(0.7 * var(--lb-spacing));
&:where(:has(.lb-icon-container)) {
padding-inline-start: calc(0.6 * var(--lb-spacing));
}
}
}
:where(.lb-icon-container) {
flex: none;
}
:where(.lb-icon) {
--lb-icon-background: var(--lb-button-background);
}
}
.lb-button-label {
display: inline-flex;
flex: none;
align-items: center;
block-size: var(--lb-icon-size);
font-weight: 500;
font-size: calc(0.7 * var(--lb-icon-size));
line-height: 1;
}
/*************************************
* Dropdown *
*************************************/
.lb-dropdown {
min-inline-size: 160px;
}
.lb-dropdown-label {
padding: calc(0.875 * var(--lb-spacing)) calc(0.625 * var(--lb-spacing))
calc(0.125 * var(--lb-spacing));
color: var(--lb-foreground-tertiary);
font-weight: 600;
font-size: 0.675em;
text-transform: uppercase;
pointer-events: none;
user-select: none;
&:where(:first-child) {
padding-block-start: var(--lb-spacing);
}
}
.lb-dropdown-separator {
block-size: 1px;
margin: $lb-elevation-padding calc(-1 * $lb-elevation-padding);
background: var(--lb-foreground-subtle);
}
.lb-dropdown-item {
:where(.lb-icon-container) {
margin-inline-start: calc(-0.125 * var(--lb-spacing));
margin-inline-end: calc(0.375 * var(--lb-spacing));
color: var(--lb-foreground-moderate);
transition-property: color;
}
}
.lb-dropdown-item:where(
:is(
[data-highlighted]:not([data-highlighted="false"]),
[data-selected]:not([data-selected="false"]),
[data-active]:not([data-active="false"])
)
) {
:where(.lb-icon-container) {
color: var(--lb-foreground-tertiary);
}
}
.lb-dropdown-item:where(:has(.lb-dropdown-item-accessory)) {
:where(.lb-dropdown-item-label) {
margin-inline-end: calc(0.375 * var(--lb-spacing));
}
}
.lb-dropdown-item-accessory {
margin-inline-start: auto;
margin-inline-end: calc(-0.25 * var(--lb-spacing));
}
/* If a dropdown has at least one icon, all items should be aligned has if they had an icon */
.lb-dropdown:where(:has(.lb-dropdown-item-icon))
:where(.lb-dropdown-item:not(:has(.lb-dropdown-item-icon)))
:where(.lb-dropdown-item-label) {
margin-inline-start: calc(
var(--lb-icon-size) + (0.375 - 0.125) * var(--lb-spacing)
);
}
/*************************************
* Select *
*************************************/
.lb-select-button {
min-inline-size: 0;
:where(.lb-button-label) {
@include truncate;
flex: 1;
}
}
.lb-select-button-chevron {
flex: none;
margin-inline-end: calc(-0.25 * var(--lb-spacing));
opacity: 0.75;
}
/*************************************
* Composer suggestions *
*************************************/
.lb-composer-suggestions-list {
margin: 0;
padding: 0;
list-style: none;
}
.lb-composer-suggestions-list-item {
scroll-margin-block: $lb-elevation-padding;
}
/*************************************
* Composer mention suggestions *
*************************************/
.lb-composer-mention-suggestions {
--lb-composer-mention-suggestion-avatar-size: 1.25rem;
}
.lb-composer-mention-suggestion {
padding: calc(0.375 * var(--lb-spacing)) calc(0.625 * var(--lb-spacing));
}
.lb-composer-mention-suggestion-avatar {
inline-size: var(--lb-composer-mention-suggestion-avatar-size);
margin-inline-start: calc(-0.125 * var(--lb-spacing));
margin-inline-end: calc(0.5 * var(--lb-spacing));
margin-block: calc(0.125 * var(--lb-spacing));
background: var(--lb-foreground-subtle);
color: var(--lb-foreground-moderate);
}
/*************************************
* List *
*************************************/
.lb-list {
display: contents;
:where(:first-child) {
@include capitalize;
}
}
/*************************************
* Date *
*************************************/
.lb-date {
@include capitalize;
}
/*************************************
* Emoji *
*************************************/
@include safari-only {
.lb-emoji {
transform: scale(0.825);
will-change: transform;
}
}
/*************************************
* Emoji picker *
*************************************/
.lb-emoji-picker {
--lb-emoji-picker-padding: $lb-emoji-picker-padding;
--lb-emoji-picker-offset-padding: calc(
$lb-emoji-picker-padding + 0.375 * var(--lb-spacing)
);
display: flex;
flex-direction: column;
inline-size: 100%;
max-inline-size: var(--frimousse-viewport-width);
block-size: 374px;
color: var(--lb-foreground);
}
.lb-emoji-picker-header {
flex: none;
border-block-end: 1px solid var(--lb-foreground-subtle);
}
.lb-emoji-picker-footer {
display: flex;
flex: none;
gap: calc(0.5 * var(--lb-spacing));
align-items: center;
inline-size: 100%;
padding: calc(0.5 * var(--lb-spacing));
border-block-start: 1px solid var(--lb-foreground-subtle);
}
.lb-emoji-picker-active-emoji {
display: flex;
flex: none;
justify-content: center;
align-items: center;
inline-size: 1.25em;
block-size: 1.25em;
font-size: 1.25em;
}
.lb-emoji-picker-active-emoji-label {
@include truncate;
flex: 1;
color: var(--lb-foreground-secondary);
font-weight: 500;
font-size: 0.8125em;
}
.lb-emoji-picker-active-emoji-label-placeholder {
margin-inline-start: calc(0.5 * var(--lb-spacing));
color: var(--lb-foreground-moderate);
}
.lb-emoji-picker-skin-tone-selector {
display: flex;
flex: none;
justify-content: center;
align-items: center;
inline-size: calc(1.75 * var(--lb-spacing));
block-size: calc(1.75 * var(--lb-spacing));
margin-inline-start: auto;
}
.lb-emoji-picker-search-container {
position: relative;
display: flex;
align-items: center;
:where(.lb-icon) {
position: absolute;
inset-inline-start: var(--lb-emoji-picker-offset-padding);
color: var(--lb-foreground-moderate);
pointer-events: none;
}
}
.lb-emoji-picker-search {
all: unset;
box-sizing: inherit;
inline-size: 100%;
padding: var(--lb-emoji-picker-offset-padding);
padding-inline-start: calc(
var(--lb-icon-size) + var(--lb-emoji-picker-offset-padding) + 0.375 *
var(--lb-spacing)
);
background: transparent;
outline: none;
appearance: textfield;
&::placeholder {
color: var(--lb-foreground-moderate);
}
&::-webkit-search-cancel-button {
display: none;
}
}
.lb-emoji-picker-content {
position: relative;
flex: 1;
outline: none;
}
.lb-emoji-picker-category-header {
padding: var(--lb-emoji-picker-padding) var(--lb-emoji-picker-offset-padding);
background: var(--lb-dynamic-background);
}
.lb-emoji-picker-category-header-title {
color: var(--lb-foreground-tertiary);
font-weight: 600;
font-size: 0.675em;
text-transform: uppercase;
}
.lb-emoji-picker-list {
padding-block-end: var(--lb-emoji-picker-padding);
animation: lb-animation-appear var(--lb-transition-duration)
var(--lb-transition-easing) both;
}
.lb-emoji-picker-row {
display: flex;
padding-inline: var(--lb-emoji-picker-padding);
scroll-margin-block-end: var(--lb-emoji-picker-padding);
}
.lb-emoji-picker-emoji {
all: unset;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
box-sizing: inherit;
aspect-ratio: 1;
padding: calc(0.375 * var(--lb-spacing));
border-radius: calc(var(--lb-radius) - 0.75 * $lb-emoji-picker-padding);
text-align: center;
}
/*************************************
* Tooltip *
*************************************/
.lb-tooltip {
--lb-background: #222;
--lb-foreground: #fff;
--lb-foreground-contrast: 10%;
position: relative;
display: flex;
align-items: center;
max-inline-size: 300px;
min-block-size: calc(
$lb-tooltip-shortcut-height + 2 * $lb-tooltip-additional-padding
);
padding-inline: $lb-tooltip-horizontal-padding;
border-radius: var(--lb-radius);
background: var(--lb-dynamic-background);
color: var(--lb-foreground);
box-shadow: var(--lb-tooltip-shadow);
font-size: 0.75rem;
line-height: 1;
overflow-wrap: anywhere;
pointer-events: none;
&::after {
content: "";
position: absolute;
inset: 0;
z-index: 1;
border-radius: inherit;
box-shadow: var(--lb-inset-shadow);
pointer-events: none;
}
}
.lb-tooltip\:multiline {
justify-content: center;
padding-block: calc(
$lb-tooltip-vertical-padding * (1 / $lb-tooltip-line-height)
);
line-height: $lb-tooltip-line-height;
text-align: center;
}
.lb-tooltip-shortcut {
display: flex;
gap: calc(0.125 * var(--lb-spacing));
justify-content: center;
align-items: center;
block-size: $lb-tooltip-shortcut-height;
margin-inline-start: $lb-tooltip-horizontal-padding;
margin-inline-end: calc(
-1 * $lb-tooltip-horizontal-padding + $lb-tooltip-additional-padding
);
padding-inline: calc(0.25 * var(--lb-spacing));
border-radius: calc(
var(--lb-radius) - 0.625 * $lb-tooltip-additional-padding
);
background: var(--lb-foreground-subtle);
color: var(--lb-foreground-tertiary);
font-family: inherit;
line-height: 1;
text-transform: uppercase;
:where(abbr) {
all: unset;
}
}
/*************************************
* Avatar *
*************************************/
.lb-avatar {
position: relative;
container-type: inline-size;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
aspect-ratio: 1;
border-radius: var(--lb-avatar-radius);
background: var(--lb-foreground-subtle);
color: var(--lb-foreground-moderate);
&:where([data-loading]) {
background: var(--lb-foreground);
opacity: $lb-loading-opacity;
}
}
.lb-avatar-image {
position: absolute;
inset: 0;
object-fit: cover;
inline-size: 100%;
block-size: 100%;
}
.lb-avatar-fallback {
font-weight: 500;
font-size: 35cqi;
white-space: nowrap;
/**
* Progressive enhancement: Only show the fallback when container queries are supported
*/
@supports not (container-type: inline-size) {
display: none;
}
}
/*************************************
* Name *
*************************************/
.lb-name {
display: inline-block;
&:where([data-loading]) {
&::before {
content: "\FEFF";
display: inline-block;
vertical-align: middle;
inline-size: 8ch;
block-size: 1.75ex;
border-radius: calc(0.5 * var(--lb-radius));
background: currentcolor;
opacity: $lb-loading-opacity;
user-select: none;
}
}
}
/*************************************
* Loading *
*************************************/
:is(.lb-avatar, .lb-name):where([data-loading]) {
animation: lb-animation-shimmer 8s linear infinite;
}
/*************************************
* Body *
*************************************/
:is(.lb-comment-body, .lb-composer-editor) {
color: var(--lb-foreground-secondary);
&,
* {
line-height: var(--lb-line-height);
}
:where(p) {
--lb-line-height-crop: calc(1lh - 1em) / -2;
margin-block-start: 0.25em;
margin-block-end: 0.25em;
/* Cancel out the impact of line-height on margins/paddings */
&:where(:first-of-type) {
margin-block-start: calc(0.125em + var(--lb-line-height-crop));
}
/* Cancel out the impact of line-height on margins/paddings */
&:where(:last-of-type) {
margin-block-end: calc(0.125em + var(--lb-line-height-crop));
}
}
:where(strong) {
font-weight: 600;
}
}
.lb-comment-mention,
.lb-composer-mention {
color: var(--lb-accent);
box-decoration-break: clone;
font-weight: 500;
}
:is(.lb-comment-link, .lb-composer-link) {
color: var(--lb-foreground);
outline: none;
font-weight: 500;
transition-property: color, text-decoration-color;
text-decoration-line: underline;
text-decoration-color: var(--lb-foreground-moderate);
text-underline-offset: 2px;
&:where([href]):where(:hover, :focus-visible) {
color: var(--lb-accent);
text-decoration-color: var(--lb-accent-moderate);
}
}
.lb-comment-mention:where([data-self]),
.lb-composer-mention {
padding: 0.1em 0.3em;
border-radius: calc(0.675 * var(--lb-radius));
background: var(--lb-accent-subtle);
}
/*************************************
* Composer *
*************************************/
.lb-composer {
position: relative;
background: var(--lb-dynamic-background);
color: var(--lb-foreground);
transition-property: background;
}
.lb-composer-form {
margin: 0;
}
.lb-composer:where(:has(.lb-composer-editor:not(:focus-visible))) {
:where(.lb-button[data-variant="primary"]) {
--lb-button-background: var(--lb-foreground-subtle);
color: var(--lb-foreground-tertiary);
&:where(:enabled:hover, :enabled:focus-visible) {
--lb-button-background: var(--lb-accent);
color: var(--lb-accent-foreground);
}
}
}
.lb-composer-editor {
padding: var(--lb-spacing);
outline: none;
&:where([data-disabled]:not([data-disabled="false"])) {
opacity: 0.5;
cursor: not-allowed;
}
:where(.lb-composer-editor-container:has(.lb-composer-attachments)) & {
padding-block-end: calc(0.25 * var(--lb-spacing));
}
:where([data-placeholder]) {
color: var(--lb-foreground-moderate);
}
}
.lb-composer-mention {
@include invisible-selection;
&:where([data-selected]:not([data-selected="false"])) {
background: var(--lb-accent);
color: var(--lb-accent-foreground);
}
}
.lb-composer-footer {
display: flex;
gap: calc(0.75 * var(--lb-spacing));
align-items: center;
block-size: calc($lb-button-size + var(--lb-spacing));
margin-block-start: calc(-0.125 * var(--lb-spacing));
padding: 0 var(--lb-spacing) var(--lb-spacing);
}
.lb-composer-actions,
.lb-composer-editor-actions {
display: flex;
gap: calc(0.125 * var(--lb-spacing));
align-items: center;
}
.lb-composer-editor-actions {
margin-inline-end: auto;
}
.lb-composer-attribution {
color: var(--lb-foreground-moderate);
outline: none;
transition-property: color;
&:where(:hover, :focus-visible) {
color: var(--lb-foreground-tertiary);
}
:where(svg) {
block-size: calc(0.75 * $lb-button-size);
}
}
.lb-composer-attachments {
padding-inline: var(--lb-spacing);
padding-block-start: calc(0.75 * var(--lb-spacing));
padding-block-end: var(--lb-spacing);
}
.lb-composer-editor-container:where([data-drop]) * {
pointer-events: none;
}
.lb-composer-attachments-drop-area {
position: absolute;
inset: 0;
display: flex;
place-content: center;
place-items: center;
color: var(--lb-accent);
&::before,
&::after {
content: "";
position: absolute;
inset: calc(0.5 * var(--lb-spacing));
z-index: 0;
border-radius: calc(0.75 * var(--lb-radius));
}
&::before {
background: currentcolor;
opacity: calc(1 * var(--lb-accent-contrast));
}
&::after {
border: 2px dashed currentcolor;
opacity: calc(2 * var(--lb-accent-contrast));
}
}
.lb-composer-attachments-drop-area-label {
position: relative;
display: flex;
gap: calc(0.25 * var(--lb-spacing));
place-items: center;
padding: calc(0.375 * var(--lb-spacing)) calc(0.5 * var(--lb-spacing));
border-radius: calc(0.75 * var(--lb-radius));
background: var(--lb-accent);
color: var(--lb-accent-foreground);
font-weight: 500;
pointer-events: none;
}
/*************************************
* Floating Toolbar *
*************************************/
.lb-composer-floating-toolbar {
display: flex;
flex-direction: row;
gap: $lb-elevation-padding;
padding: $lb-elevation-padding;
user-select: none;
/* Invisibly increase the buttons' hit target size */
:where(.lb-button) {
&::before {
content: "";
position: absolute;
inset: calc(-1 * $lb-elevation-padding);
z-index: -1;
border-radius: inherit;
}
&:where(:not(:first-of-type))::before {
inset-inline-start: calc(-0.5 * $lb-elevation-padding);
}
&:where(:not(:last-of-type))::before {
inset-inline-end: calc(-0.5 * $lb-elevation-padding);
}
}
}
/*************************************
* Comment *
*************************************/
.lb-comment {
--lb-comment-avatar-size: $lb-button-size;
position: relative;
padding: var(--lb-spacing);
background: var(--lb-dynamic-background);
color: var(--lb-foreground);
font-weight: 400;
scroll-margin: var(--lb-spacing);
@media (hover: hover) {
&:where(.lb-comment\:show-actions-hover) {
:where(.lb-comment-actions) {
position: absolute;
inset-inline-end: 0;
opacity: 0;
transition-property: opacity;
}
&:where(:is(:hover, :focus-within, .lb-comment\:action-open)) {
:where(.lb-comment-actions) {
position: relative;
opacity: 1;
}
}
}
}
&:where(:target, [data-target]) {
--lb-dynamic-background: var(--lb-background-accent-faint);
}
&:where([data-editing]) {
--lb-dynamic-background: var(--lb-background-foreground-faint);
}
}
.lb-comment-header {
position: relative;
display: flex;
gap: calc(0.75 * var(--lb-spacing));
align-items: center;
block-size: var(--lb-comment-avatar-size);
margin-block-end: calc(0.75 * var(--lb-spacing));
}
.lb-comment-details {
display: flex;
gap: calc(0.75 * var(--lb-spacing));
align-items: center;
min-inline-size: 0;
}
.lb-comment-avatar {
flex: none;
inline-size: var(--lb-comment-avatar-size);
}
.lb-comment-details-labels {
display: flex;
gap: calc(0.5 * var(--lb-spacing));
align-items: baseline;
min-inline-size: 0;
}
.lb-comment-author,
.lb-comment-date {
@include truncate;
@include capitalize;
}
.lb-comment-author {
font-weight: 500;
}
.lb-comment-date {
color: var(--lb-foreground-tertiary);
font-size: 0.875em;
}
.lb-comment-date-created,
.lb-comment-date-edited {
display: contents;
}
.lb-comment-actions {
display: flex;
gap: calc(0.125 * var(--lb-spacing));
margin-inline-start: auto;
}
.lb-comment-composer {
margin: calc(-1 * var(--lb-spacing));
background: unset;
}
.lb-comment-body {
/**
* Prevent empty lines from collapsing
*/
:where(p span:only-child:empty)::before {
content: "\FEFF";
user-select: none;
}
}
.lb-comment-attachments {
margin-block-start: calc(0.75 * var(--lb-spacing));
}
.lb-comment-reactions {
display: flex;
flex-wrap: wrap;
gap: calc(0.375 * var(--lb-spacing));
margin-block-start: calc(0.75 * var(--lb-spacing));
}
.lb-comment-reaction {
gap: calc(0.375 * var(--lb-spacing));
block-size: $lb-button-size;
padding-inline: calc(0.575 * var(--lb-spacing));
border-radius: $lb-radius-full;
&:where([data-self]) {
background: var(--lb-accent-subtle);
color: var(--lb-accent-secondary);
box-shadow: inset 0 0 0 1px var(--lb-accent-moderate);
&:where(
:enabled:hover,
:enabled:focus-visible,
[aria-expanded="true"],
[aria-selected="true"]
) {
color: var(--lb-accent);
}
}
}
.lb-comment-reaction-count {
font-weight: 500;
font-size: 0.75em;
font-variant-numeric: tabular-nums;
}
.lb-comment-reaction-tooltip {
max-inline-size: 200px;
}
.lb-comment-deleted {
color: var(--lb-foreground-tertiary);
font-size: 0.875em;
}
.lb-comment\:indent-content {
min-block-size: calc(var(--lb-comment-avatar-size) + 2 * var(--lb-spacing));
:where(.lb-comment-header) {
block-size: $lb-button-size;
margin-block-end: calc(0.25 * var(--lb-spacing));
}
:where(.lb-comment-avatar) {
position: absolute;
inset-inline-start: 0;
inset-block-start: 0;
}
:where(.lb-comment-details-labels) {
margin-inline-start: calc(
var(--lb-comment-avatar-size) + 0.75 * var(--lb-spacing)
);
}
:where(.lb-comment-content) {
padding-inline-start: calc(
var(--lb-comment-avatar-size) + 0.75 * var(--lb-spacing)
);
}
}
/*************************************
* Thread *
*************************************/
.lb-thread {
background: var(--lb-dynamic-background);
color: var(--lb-foreground);
transition-property: background;
@media (hover: hover) {
&:where(.lb-thread\:show-actions-hover :is(:hover, :focus-within)) {
:where(.lb-thread-actions) {
opacity: 1;
}
}
}
}
.lb-thread-comments {
position: relative;
z-index: 0;
display: flex;
flex-direction: column;
}
.lb-thread-comment {
z-index: 0;
padding-block: calc(0.6 * var(--lb-spacing));
transition-property: background;
&:where(.lb-comment\:indent-content) {
min-block-size: calc(var(--lb-comment-avatar-size) + var(--lb-spacing));
}
&:where(:first-of-type, [data-editing]) {
padding-block-start: var(--lb-spacing);
&:where(.lb-comment\:indent-content) {
min-block-size: calc(
var(--lb-comment-avatar-size) + 1.5 * var(--lb-spacing)
);
}
}
&:where(:last-of-type, [data-editing]) {
padding-block-end: var(--lb-spacing);
&:where(.lb-comment\:indent-content) {
min-block-size: calc(
var(--lb-comment-avatar-size) + 1.75 * var(--lb-spacing)
);
}
}
}
.lb-thread-new-indicator {
position: relative;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
block-size: 0;
&::before,
&::after {
content: "";
z-index: 0;
flex: 1;
block-size: 0;
border-block-start: 1px solid var(--lb-foreground-subtle);
transition-property: border;
}
}
.lb-thread-new-indicator-label {
z-index: 1;
display: flex;
flex: none;
gap: calc(0.325 * var(--lb-spacing));
align-items: center;
padding: calc(0.25 * var(--lb-spacing)) var(--lb-spacing);
color: var(--lb-accent);
font-weight: 600;
font-size: 0.675em;
text-transform: uppercase;
}
.lb-thread-new-indicator-label-icon {
inline-size: calc(0.6 * var(--lb-icon-size));
block-size: calc(0.6 * var(--lb-icon-size));
}
.lb-thread-composer {
position: relative;
&::after {
content: "";
position: absolute;
inset: 0;
inline-size: 100%;
block-size: 100%;
border-block-start: 1px solid var(--lb-foreground-subtle);
pointer-events: none;
transition-property: border;
}
}
/*************************************
* Attachments *
*************************************/
.lb-comment-attachments,
.lb-composer-attachments {
display: flex;
flex-direction: column;
gap: calc(0.75 * var(--lb-spacing));
}
.lb-attachments {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr));
gap: calc(0.75 * var(--lb-spacing));
}
.lb-attachment,
.lb-attachment-delete {
@include button;
}
.lb-attachment {
position: relative;
display: flex;
inline-size: 100%;
min-inline-size: 0;
border-radius: var(--lb-radius);
background: var(--lb-dynamic-background);
box-shadow: inset 0 0 0 1px var(--lb-foreground-subtle);
&:where([tabindex="-1"]) {
cursor: default;
}
&:where(:not([tabindex="-1"])) {
&:where(:hover, :focus-visible) {
background: var(--lb-foreground-subtle);
}
}
}
.lb-attachment-delete {
position: absolute;
inset-inline-end: -0.35rem;
inset-block-start: -0.35rem;
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
inline-size: 1.1rem;
block-size: 1.1rem;
border-radius: 50%;
background: var(--lb-foreground-subtle);
color: var(--lb-foreground-secondary);
box-shadow: 0 0 0 2px var(--lb-dynamic-background);
opacity: 0;
/* Invisibly increase the button's hit target size */
&::before {
content: "";
position: absolute;
inset: -4px;
z-index: -1;
border-radius: inherit;
}
&:where(:hover, :focus-visible) {
background: var(--lb-foreground-secondary);
color: var(--lb-dynamic-background);
}
:where(.lb-attachment:focus-within, .lb-attachment:hover) & {
opacity: 1;
}
:where(.lb-icon) {
inline-size: 0.75rem;
}
}
.lb-attachment-details {
position: relative;
display: flex;
flex-direction: column;
gap: calc(0.25 * var(--lb-spacing));
justify-content: center;
min-inline-size: 0;
font-size: 0.875em;
}
.lb-attachment-name {
display: flex;
font-weight: 500;
}
.lb-attachment-name-base,
.lb-attachment-description {
@include truncate;
transition-property: color;
}
.lb-attachment-preview {
position: relative;
display: flex;
flex: none;
justify-content: center;
align-items: center;
overflow: hidden;
background: color-mix(
in srgb,
transparent,
var(--lb-foreground) var(--lb-foreground-contrast)
);
color: var(--lb-foreground-tertiary);
transition-property: background, color;
}
.lb-attachment-preview-media {
border-radius: inherit;
transition-property: opacity;
&,
&::after,
img,
video {
position: absolute;
inset: 0;
inline-size: 100%;
block-size: 100%;
}
img,
video {
object-fit: cover;
pointer-events: none;
}
&::after {
content: "";
border-radius: inherit;
box-shadow: var(--lb-highlight-shadow);
pointer-events: none;
}
&:where([data-hidden]) {
opacity: 0;
}
}
.lb-attachment-icon {
flex: none;
overflow: visible;
color: var(--lb-foreground);
}
.lb-attachment-icon-glyph {
fill: var(--lb-foreground-moderate);
}
.lb-attachment-icon-background {
fill: var(--lb-background);
}
.lb-attachment-icon-fold {
fill-opacity: calc(0.75 * var(--lb-foreground-contrast));
}
.lb-attachment-icon-shadow {
filter: blur(6px);
fill-opacity: var(--lb-foreground-contrast);
}
.lb-file-attachment {
gap: calc(0.5 * var(--lb-spacing));
padding: calc(0.5 * var(--lb-spacing));
padding-inline-end: calc(0.65 * var(--lb-spacing));
:where(.lb-attachment-preview) {
aspect-ratio: 1;
inline-size: 2.5rem;
border-radius: calc(0.5 * var(--lb-radius));
}
:where(.lb-attachment-name) {
color: var(--lb-foreground-secondary);
}
:where(.lb-attachment-description) {
color: var(--lb-foreground-tertiary);
}
&:where(:not([tabindex="-1"])) {
&:where(:hover, :focus-visible, :focus-within) {
:where(.lb-attachment-name) {
color: var(--lb-foreground);
}
:where(.lb-attachment-description) {
color: var(--lb-foreground-secondary);
}
}
}
}
.lb-media-attachment {
aspect-ratio: 16 / 10;
:where(.lb-attachment-preview) {
position: absolute;
inset: 0;
border-radius: inherit;
}
:where(.lb-attachment-details) {
position: absolute;
inset-inline: 0;
inset-block-end: 0;
padding: calc(0.75 * var(--lb-spacing));
border-end-start-radius: inherit;
border-end-end-radius: inherit;
background: linear-gradient(to bottom, transparent, rgba(0 0 0 / 80%));
text-shadow: 0 0 2px rgba(0 0 0 / 40%);
opacity: 0;
transition-property: opacity;
}
:where(.lb-attachment-name) {
color: #fff;
}
:where(.lb-attachment-description) {
color: rgba(255 255 255 / 80%);
}
&:where(:not([tabindex="-1"])) {
&:where(:hover, :focus-visible, :focus-within) {
:where(.lb-attachment-details) {
opacity: 1;
}
}
}
}
.lb-attachment:where([data-error]) {
:where(.lb-attachment-preview) {
background: var(--lb-destructive);
color: var(--lb-destructive-foreground);
}
}
/*************************************
* Inbox Notification *
*************************************/
.lb-inbox-notification {
--lb-inbox-notification-aside-size: 36px;
position: relative;
display: flex;
gap: calc(0.75 * var(--lb-spacing));
overflow: hidden;
padding: var(--lb-spacing);
background: var(--lb-dynamic-background);
color: var(--lb-foreground);
font-weight: 400;
text-decoration: inherit;
transition-property: background;
/* Highlight missing notifications during development */
&:where([data-missing]) {
--lb-accent: var(--lb-destructive) ;
--lb-accent-foreground: var(--lb-destructive-foreground) ;
--lb-accent-contrast: var(--lb-destructive-contrast) ;
--lb-dynamic-background: var(--lb-background-accent-faint);
}
&:where([data-unread]) {
--lb-dynamic-background: var(--lb-background-accent-faint);
}
&:where([href]) {
cursor: pointer;
&:where(:hover, :focus-visible, :focus-within) {
--lb-dynamic-background: var(--lb-background-foreground-faint);
}
&:where([data-unread]) {
&:where(:hover, :focus-visible, :focus-within) {
--lb-dynamic-background: var(--lb-background-accent-subtle);
}
}
}
@media (hover: hover) {
&:where(.lb-inbox-notification\:show-actions-hover) {
:where(.lb-inbox-notification-header) {
display: grid;
grid-template: "title secondary" / 1fr max-content;
}
:where(.lb-inbox-notification-details) {
opacity: 1;
transition-property: opacity;
}
:where(.lb-inbox-notification-actions) {
opacity: 0;
transition-property: opacity;
}
&:where(:is(:hover, :focus-within, .lb-inbox-notification\:action-open)) {
:where(.lb-inbox-notification-details) {
opacity: 0;
}
:where(.lb-inbox-notification-actions) {
opacity: 1;
}
}
:where(.lb-inbox-notification-details),
:where(.lb-inbox-notification-actions) {
grid-area: secondary;
justify-self: end;
}
}
}
}
.lb-inbox-notification-aside {
flex: none;
inline-size: var(--lb-inbox-notification-aside-size);
}
.lb-inbox-notification-icon {
display: flex;
justify-content: center;
place-items: center;
aspect-ratio: 1;
border-radius: 50%;
background: var(--lb-foreground-subtle);
.lb-inbox-notification:where([data-missing]) :where(&) {
background: var(--lb-accent-subtle);
color: var(--lb-accent);
}
}
.lb-inbox-notification-content {
flex: 1;
}
.lb-inbox-notification-content,
.lb-inbox-notification-body {
min-inline-size: 0;
max-inline-size: 100%;
}
.lb-inbox-notification-header {
display: flex;
gap: calc(0.75 * var(--lb-spacing));
align-items: center;
margin-block-start: calc(0.25 * var(--lb-spacing));
margin-block-end: calc(0.5 * var(--lb-spacing));
}
.lb-inbox-notification-title {
@include capitalize;
min-block-size: $lb-button-size;
:where(strong, .lb-list, .lb-name) {
font-weight: 500;
}
}
.lb-inbox-notification-details {
flex: none;
align-self: start;
min-inline-size: 0;
block-size: $lb-button-size;
margin-inline-start: auto;
}
.lb-inbox-notification-details-labels {
display: flex;
align-items: baseline;
min-inline-size: 0;
&::before {
content: "\FEFF";
}
}
.lb-inbox-notification-actions {
display: flex;
grid-area: actions;
gap: calc(0.125 * var(--lb-spacing));
align-self: start;
}
.lb-inbox-notification-comments {
display: flex;
flex-direction: column;
gap: var(--lb-spacing);
}
.lb-inbox-notification-comment {
padding: 0;
background: transparent;
:where(.lb-comment-header) {
block-size: auto;
color: var(--lb-foreground-tertiary);
font-size: 0.875rem;
}
:where(.lb-comment-reaction),
:where(.lb-comment-attachment) {
pointer-events: none;
}
}
.lb-inbox-notification-date {
color: var(--lb-foreground-tertiary);
font-size: 0.875em;
}
.lb-inbox-notification-unread-indicator {
align-self: center;
inline-size: 10px;
block-size: 10px;
margin-inline-start: calc(0.5 * var(--lb-spacing));
border-radius: 50%;
background: var(--lb-accent);
}
/*************************************
* History Version Summary *
*************************************/
.lb-history-version-summary {
position: relative;
display: flex;
flex-direction: column;
gap: calc(0.25 * var(--lb-spacing));
justify-content: center;
inline-size: 100%;
min-inline-size: 0;
padding: var(--lb-spacing);
background: var(--lb-dynamic-background);
transition-property: background;
&:where(
:hover,
:focus-visible,
:focus-within,
[data-selected]:not([data-selected="false"])
) {
--lb-dynamic-background: var(--lb-background-foreground-faint);
}
}
.lb-history-version-summary-date,
.lb-history-version-summary-authors {
@include truncate;
@include capitalize;
min-inline-size: 0;
max-inline-size: 100%;
}
.lb-history-version-summary-date {
color: var(--lb-foreground-secondary);
font-weight: 500;
}
.lb-history-version-summary-authors {
color: var(--lb-foreground-tertiary);
}
/*************************************
* History Version Previe *
*************************************/
.lb-history-version-preview {
position: relative;
display: flex;
flex-direction: column;
background: var(--lb-dynamic-background);
/* overflow-block: auto; doesn't work as expected */
/* stylelint-disable-next-line plugin/use-logical-properties-and-values */
overflow-y: auto;
}
.lb-history-version-preview-content {
flex: 1 0 auto;
padding: var(--lb-spacing);
}
.lb-history-version-preview-footer {
position: sticky;
inset-block-end: 0;
display: flex;
flex: none;
gap: var(--lb-spacing);
align-items: center;
margin-block-start: auto;
padding: var(--lb-spacing);
border-block-start: 1px solid var(--lb-foreground-subtle);
background: var(--lb-dynamic-background);
}
.lb-history-version-preview-authors {
@include truncate;
flex: 1 1 auto;
min-inline-size: 0;
color: var(--lb-foreground-tertiary);
}
.lb-history-version-preview-actions {
display: flex;
flex: none;
gap: calc(0.35 * var(--lb-spacing));
align-items: center;
margin-inline-start: auto;
}
/*************************************
* Lists *
*************************************/
.lb-inbox-notification-list,
.lb-history-version-summary-list {
margin: 0;
padding: 0;
list-style: none;
}
.lb-inbox-notification-list-item,
.lb-history-version-summary-list-item {
&:where(:not(:last-of-type)) {
border-block-end: 1px solid var(--lb-foreground-subtle);
}
}
/*************************************
* Inline code *
*************************************/
:is(.lb-root) {
:where(code) {
padding: 0.2em 0.4em;
border-radius: calc(0.75 * var(--lb-radius));
background: var(--lb-foreground-subtle);
box-decoration-break: clone;
font-size: 85%;
line-height: 1;
}
/**
* Merge adjacent inline code elements
*/
:where(span:has(code) + span code) {
padding-inline-start: 0;
border-start-start-radius: 0;
border-end-start-radius: 0;
}
:where(span:has(code):has(+ span code) code) {
padding-inline-end: 0;
border-start-end-radius: 0;
border-end-end-radius: 0;
}
}
/* 0,0,0 specificity to inherit any styles applied to `code` elements */
:where(:is(.lb-root) code) {
font-family: ui-monospace, Menlo, Monaco, "Roboto Mono", "Cascadia Code",
"Source Code Pro", Consolas, "DejaVu Sans Mono", monospace;
}
/*************************************
* Elevation *
*************************************/
.lb-elevation {
position: relative;
overflow: hidden;
border-radius: var(--lb-radius);
background: var(--lb-dynamic-background);
box-shadow: var(--lb-elevation-shadow);
&::after {
content: "";
position: absolute;
inset: 0;
z-index: 1;
border-radius: inherit;
box-shadow: var(--lb-inset-shadow);
pointer-events: none;
}
}
/*************************************
* Elevation lists *
*************************************/
.lb-dropdown,
.lb-composer-suggestions {
padding: $lb-elevation-padding;
/* overflow-block: auto; doesn't work as expected */
/* stylelint-disable-next-line plugin/use-logical-properties-and-values */
overflow-y: auto;
&:where([data-hidden]) {
opacity: 0;
}
}
.lb-dropdown-item,
.lb-composer-suggestions-list-item {
display: flex;
align-items: center;
padding: calc(0.25 * var(--lb-spacing)) calc(0.5 * var(--lb-spacing));
font-size: 0.875rem;
}
.lb-dropdown-item,
.lb-composer-suggestions-list-item,
.lb-emoji-picker-emoji {
border-radius: calc(var(--lb-radius) - 0.75 * $lb-elevation-padding);
color: var(--lb-foreground-secondary);
outline: none;
cursor: pointer;
user-select: none;
transition-property: background, color, opacity;
}
:is(
.lb-dropdown-item,
.lb-composer-suggestions-list-item,
.lb-emoji-picker-emoji
) {
&:where(
[data-highlighted]:not([data-highlighted="false"]),
[data-selected]:not([data-selected="false"]),
[data-active]:not([data-active="false"])
) {
background: var(--lb-foreground-subtle);
transition-duration: calc(var(--lb-transition-duration) / 2);
}
&:where(:disabled, [data-disabled]:not([data-disabled="false"])) {
opacity: 0.5;
cursor: not-allowed;
}
}
/*************************************
* Floating animations *
*************************************/
.lb-dropdown,
.lb-composer-suggestions,
.lb-composer-floating-toolbar,
.lb-tooltip,
.lb-emoji-picker {
animation-duration: var(--lb-transition-duration);
animation-timing-function: var(--lb-transition-easing);
will-change: transform, opacity;
}
:is(
.lb-dropdown,
.lb-emoji-picker,
.lb-tooltip:where([data-state="delayed-open"]),
.lb-composer-suggestions,
.lb-composer-floating-toolbar
) {
&:where([data-side="top"]) {
animation-name: lb-animation-slide-up;
}
&:where([data-side="bottom"]) {
animation-name: lb-animation-slide-down;
}
}
:is(
.lb-dropdown,
.lb-emoji-picker,
.lb-tooltip,
.lb-composer-suggestions,
.lb-composer-floating-toolbar
) {
&:where([data-state="closed"]) {
animation-name: lb-animation-disappear;
}
}
@media (prefers-reduced-motion) {
.lb-dropdown:where(:not([data-state="closed"])),
.lb-emoji-picker:where(:not([data-state="closed"])),
.lb-tooltip:where([data-state="delayed-open"]:not([data-state="closed"])),
.lb-composer-suggestions:where(:not([data-state="closed"])) {
animation-name: lb-animation-appear;
}
}
/*************************************
* Animations *
*************************************/
@keyframes lb-animation-slide-down {
from {
opacity: 0;
transform: translateY(-4px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes lb-animation-slide-up {
from {
opacity: 0;
transform: translateY(4px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes lb-animation-appear {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes lb-animation-disappear {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@keyframes lb-animation-shimmer {
from,
to {
mask-image: linear-gradient(
90deg,
rgb(0 0 0 / 50%),
#000,
#000,
rgb(0 0 0 / 50%)
);
mask-size: 400% 100%;
}
from {
mask-position: 200% 0;
}
to {
mask-position: -200% 0;
}
}
@keyframes lb-animation-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}