Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/web/DESIGN.md

Large diffs are not rendered by default.

65 changes: 46 additions & 19 deletions apps/web/src/chat/actions/message-actions.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,16 @@
*/

.chat-message-body {
/* How far the highlight reaches above the message: a little, or up over the name line of the first. */
--chat-highlight-top: 0.25rem;
/*
* A row's pitch, as Slack's: its shade and its hit area reach halfway across the gap to the row
* before it and to the row after it, so the shades of neighbouring rows meet with no band between
* them and none over another. Messages of a group are 4px apart; the transcript's rows are 16px.
*/
--chat-row-half: calc(var(--spacing) * 2);
--chat-gap-above: calc(var(--spacing) / 2);
--chat-gap-below: calc(var(--spacing) / 2);
/* How far the highlight reaches above the message: to the gap's middle, or over the name line. */
--chat-highlight-top: var(--chat-gap-above);
/* Slack's gutter: a 36px avatar and 8px beside it, and the row's 12px beyond that. */
--chat-bleed-start: 3.5rem;
--chat-bleed-end: 0.75rem;
Expand Down Expand Up @@ -83,11 +91,22 @@
}

/*
* Slack's row is shaded 8px above its name line and 8px below its last line
* (`c-message_kit__gutter`); a message after the first of its group, 4px above it.
* A group's first message reaches to the middle of the 16px before its row, and its last to the
* middle of the 16px after it; a message that heads its group reaches over its name line, which
* stands 2px above the row, to the same middle (`c-message_kit__gutter`).
*/
.chat-message-body:first-child {
--chat-gap-above: var(--chat-row-half);
}

.chat-message-body:last-child {
--chat-gap-below: var(--chat-row-half);
}

.chat-message-body[data-chat-headed] {
--chat-highlight-top: calc(var(--text-base) * var(--text-base--line-height) + var(--spacing) * 2);
--chat-highlight-top: calc(
var(--text-base) * var(--text-base--line-height) - var(--spacing) / 2 + var(--chat-row-half)
);
}

/*
Expand All @@ -106,24 +125,35 @@
}

/*
* The whole message as one row as wide as the pane, square, as Slack shades a hovered message: a
* darker step of whatever the transcript lies on, never a lighter one.
* The whole message as one row as wide as the pane and as tall as its pitch, square, as Slack
* shades a hovered message: a darker step of whatever the transcript lies on, never a lighter one.
*/
.chat-message-body::before {
content: "";
position: absolute;
z-index: -1;
inset-block: calc(-1 * var(--chat-highlight-top)) calc(-1 * var(--spacing));
inset-block: calc(-1 * var(--chat-highlight-top)) calc(-1 * var(--chat-gap-below));
inset-inline: calc(-1 * var(--chat-shade-start) - 100vw) calc(-1 * var(--chat-shade-end) - 100vw);
background: var(--color-chat-row-hover);
opacity: 0;
pointer-events: none;
transition: opacity var(--chat-fade) var(--ease-out);
}

/* The last message of a group is shaded 8px below, to the gap before the next. */
.chat-message-body:last-child::before {
inset-block-end: calc(-1 * var(--spacing) * 2);
/*
* Under a mouse the shade is also where the pointer finds its row, behind its content, and so is
* the avatar, as in Slack: a pointer moving down the transcript passes from one row's shade straight
* into the next one's. Only inside a transcript, whose stack clips the shade at its sides. A touch
* screen keeps the rows' own boxes, so a reaction's 44px target past its row still takes the tap.
*/
@media (hover: hover) and (pointer: fine) {
[data-chat-stack] .chat-message-body::before {
pointer-events: auto;
}

[data-chat-entry] > [data-chat-avatar] {
pointer-events: none;
}
}

/*
Expand All @@ -133,17 +163,13 @@
.chat-source-tint {
position: absolute;
z-index: -1;
inset-block: calc(-1 * var(--chat-highlight-top)) calc(-1 * var(--spacing));
inset-block: calc(-1 * var(--chat-highlight-top)) calc(-1 * var(--chat-gap-below));
inset-inline: calc(-1 * var(--chat-shade-start) - 100vw) calc(-1 * var(--chat-shade-end) - 100vw);
background: var(--color-brand-wash);
pointer-events: none;
animation: chat-source-tint calc(var(--duration-linger) * 2) var(--ease-out) forwards;
}

.chat-message-body:last-child > .chat-source-tint {
inset-block-end: calc(-1 * var(--spacing) * 2);
}

@keyframes chat-source-tint {
0%,
40% {
Expand Down Expand Up @@ -339,7 +365,7 @@
.chat-message-body[data-chat-engaged],
.chat-message-body:has(:focus-visible) {
margin-block-start: var(--chat-toolbar-lane);
--chat-highlight-top: calc(var(--chat-toolbar-lane) + 0.25rem);
--chat-highlight-top: calc(var(--chat-toolbar-lane) + var(--chat-gap-above));
}

/*
Expand All @@ -350,8 +376,9 @@
.chat-message-body[data-chat-headed]:has(:focus-visible) {
margin-block-start: calc(var(--chat-toolbar-lane) + var(--spacing));
--chat-highlight-top: calc(
var(--chat-toolbar-lane) + var(--text-base) * var(--text-base--line-height) +
var(--spacing) * 3
var(--chat-toolbar-lane) + var(--spacing) + var(--text-base) * var(--text-base--line-height) -
var(--spacing) / 2 +
var(--chat-row-half)
);
}

Expand Down
3 changes: 2 additions & 1 deletion apps/web/src/chat/run-card.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
}
}

.run-row + .run-row {
/* The hairline between runs is the line's own, so the pointer on it is on the line (run-row.css). */
.run-row + .run-row > .run-head {
border-top: var(--edge-width) solid var(--color-edge);
}

Expand Down
8 changes: 7 additions & 1 deletion apps/web/src/chat/run-row.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/*
* A run's line in the workflow card is shaded across the card's whole width under the pointer,
* square, as a Chat row is across Chat; the card's own corners round the first line and the last.
* The toggle keeps its own box for its hit area and focus ring.
* The hairline above a line is its own and the shade runs under it, so lines meet with no band
* between them and a pointer moving down the card shades one line after the next. The toggle keeps
* its own box for its hit area and focus ring.
*/
.run-stack {
isolation: isolate;
Expand All @@ -24,6 +26,10 @@
transition: opacity var(--duration-fast) var(--ease-out);
}

.run-row + .run-row > .run-head::before {
inset-block-start: calc(-1 * var(--edge-width));
}

.run-head:hover::before {
opacity: 1;
}
Expand Down
5 changes: 5 additions & 0 deletions apps/web/src/chat/threads/thread-panel.css
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
line-height: 1.4;
}

/* The root's row reaches halfway to the provenance above it and to the replies' rule below it. */
[data-thread-root-message] .chat-message-body {
--chat-row-half: calc(var(--spacing) * 1.5);
}

.thread-replies-rule {
display: flex;
align-items: center;
Expand Down
19 changes: 5 additions & 14 deletions apps/web/src/theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -1186,11 +1186,11 @@ body {

/*
* Split Chat is a track: its width moves the document, and Chat slides under its clip.
* Only the width clips, so the composer's focus ring can pass the panel's bottom edge, and only
* beyond the frame's gutters, which Chat's rows are shaded across (workspace-sizing.css). Its top
* and foot are unbounded, not merely far: an image's lazy loading counts a clip path's edges, and
* one a screen above and below Chat kept the images further up from loading. (An overflow clip's
* margin would do, but Chromium draws one only where both axes clip.)
* Only the width clips, so the composer's focus ring can pass the panel's bottom edge, and at its
* start only beyond the frame's gutter, which Chat's rows are shaded across (workspace-sizing.css).
* Its top and foot are unbounded, not merely far: an image's lazy loading counts a clip path's
* edges, and one a screen above and below Chat kept the images further up from loading. (An
* overflow clip's margin would do, but Chromium draws one only where both axes clip.)
*/
.workspace-root[data-workspace-mode="split"] .workspace-chat-panel {
overflow: visible;
Expand All @@ -1211,15 +1211,6 @@ body {
width: var(--chat-width, 0px);
}

.workspace-root[data-workspace-mode="split"][data-document-collapsed] .workspace-chat-panel {
clip-path: inset(
calc(-1px * infinity)
calc(-1 * (var(--spacing) * 3 + env(safe-area-inset-right)))
calc(-1px * infinity)
calc(-1 * (var(--spacing) * 3 + env(safe-area-inset-left)))
);
}

.workspace-root[data-workspace-mode="split"] .workspace-chat-panel.is-open {
width: var(--chat-width, 0px);
}
Expand Down
16 changes: 9 additions & 7 deletions apps/web/src/workspace-sizing.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,9 @@
/*
* Split Chat lies on the ground from the sidebar's edge (or the window's) to the document's sheet,
* and a shown row is shaded across all of it, as Slack shades its message pane. The pane keeps its
* box and its track; its clip lets it draw into the frame's gutter before it, and the one after it
* while the document is folded to its bar (theme.css). Each transcript reaches into the gutters
* beside it and into the 8px before the sheet, and its rows keep their 20px gutter inside that, so
* the text stays where it was (overlay-scrollbar.css).
* box and its track; its clip lets it draw into the frame's gutter before it (theme.css). Each
* transcript reaches into the gutter beside it and into the 8px before the sheet, and its rows keep
* their 20px gutter inside that, so the text stays where it was (overlay-scrollbar.css).
*
* The 8px before the sheet is where Resize chat is taken: rows are shaded across it, and the thumb
* stays clear of it, where it was. While a thread is open they are the thread's, and main Chat ends
Expand Down Expand Up @@ -104,17 +103,20 @@
inset-inline-end: 0;
}

/* With the document folded to its bar, the thread reaches the window's edge, and so does its thumb. */
/*
* With the document folded to its bar there is no sheet: the thread ends at its own panel's edge,
* where its header's rule ends, and so does its thumb.
*/
.workspace-root[data-workspace-mode="split"][data-document-collapsed]
.chat-split-thread
.chat-scroll-host {
margin-inline-end: calc(-1 * (var(--spacing) * 5 + env(safe-area-inset-right)));
margin-inline-end: 0;
}

.workspace-root[data-workspace-mode="split"][data-document-collapsed]
.chat-split-thread
[data-chat-stack] {
padding-inline-end: calc(var(--spacing) * 10 + env(safe-area-inset-right));
padding-inline-end: calc(var(--spacing) * 5);
}

.workspace-root[data-workspace-mode="split"][data-document-collapsed]
Expand Down
Loading
Loading