The director is paid a fixed fee for twelve shooting days and a day rate for pickups.
Sofie Lindqvist
09:12
Can we look at the fee clause again? Twelve shooting days feels short for this one.
Mikkel Sørensen
09:20
Agreed. The schedule we sent has fourteen, with two pickup days.
HEEx
<div class="h-[28rem] w-xl">
<ConnieUI.Typography.muted size="md">
The director is paid a fixed fee for
<span class="comment-anchor-selected">twelve shooting days</span>
and a day rate for pickups.
</ConnieUI.Typography.muted>
<ConnieUI.CrdtEditor.comment_popover
anchor={@anchor}
close={JS.push("comment:close")}
id="catalog-comment-popover"
>
<ConnieUI.Layouts.vstack gap="md">
<ConnieUI.Chat.comment_message
:for={message <- Enum.take(@thread.messages, 2)}
name={message.author}
>
<:avatar>
<ConnieUI.Avatars.avatar image={message.image} size="size-6" />
</:avatar>
<:meta>{message.at}</:meta>
{message.body}
</ConnieUI.Chat.comment_message>
</ConnieUI.Layouts.vstack>
</ConnieUI.CrdtEditor.comment_popover>
</div>
Variant matrix
Every combination of one or two attributes, side by side.
Controls
Set by the example
anchor close class
Docs
Floating surface for one comment thread, anchored over the editor.
`anchor` is the box the panel belongs to, in viewport pixels: the comment's
passage for a thread (`comment:open`) and the Comment button for a new one
(`comment:start`), both of which send the same four edges, so one popover
serves both. The panel is fixed rather than scrolled with the document. What
goes in it is the host's business: this component knows nothing about threads.
Placement is Floating UI's: below the anchor and lined up with its start,
flipped above it when there is no room below, shifted to stay on screen, with
an arrow on the edge that faces the anchor, pointing at it. The server renders
the unflipped position, so the panel is where it belongs before the hook has
run.
The panel follows its passage. The box the server was sent is where the
passage was when it opened; once the hook runs it measures the lit passage
itself (`.comment-anchor-selected`, which the editor draws on the open
thread's words and on the words a new comment is about) and keeps the panel
on it as the document scrolls, hiding it while the passage is out of view.
The sent box stands in only when nothing is lit, which is a thread whose
words have been deleted.
It opens out of its arrow, scaling up from where the arrow's tip is as it
fades in, and shrinks back into it on the way out, the way Figma's comment
composer does. A reader who asked for reduced motion gets the fade alone.
`variant` says whether the popover draws the panel (`:thread`) or what it
holds is the surface (`:composer`, the pill a new comment is written in).
The arrow is a square turned on its corner, the two edges facing the anchor
drawn in the panel's ring colour and the rest over the panel, so it covers the
ring where the two meet and reads as one outline. The panel opens over the
paper, which is the same white it is, so neither is told apart by its fill:
the panel by its shadow and a `primary` ring, and the arrow by the same ring
colour and a shadow of its own, cast away from the panel so it never falls
on the conversation.
A composer a reader's selection opened by itself (`keep_selection`) leaves the
focus where it was, so the selection is still there to copy. The first key
they type without Cmd, Ctrl or Alt goes to the composer, so writing the
comment needs no click (`forwardFirstKey/2` in `popover.js`).
It carries no close button. A comment panel is read alongside the document
rather than instead of it, so it goes away on Escape or as soon as the reader
presses something else on the page. Escape closes the innermost thing first:
with the @ menu or a message's menu open, it closes that and keeps the draft,
and the next one closes the panel (`closesPanel/2` in
`comment_popover_keys.js`). What counts as "something else" is
`isOutside/2` in `popover.js`, which keeps the panel up for the flyouts its
own controls open and for the anchors that move it to another thread.
| Attribute | Type | Default | Description |
|---|---|---|---|
| No data found. | |||
| id | :string | "comment-popover" |
|
| anchor * | :map |
`%{top:, left:, bottom:, right:}` in viewport pixels
|
|
| close * | {:struct, Phoenix.LiveView.JS} |
how the panel is dismissed. Required: it is the dialog's only way out, by Escape or by pressing anything on the page that is not part of the panel. There is no close button, so a host that does not pass this leaves the reader with a panel they cannot put away
|
|
| label | :string | "Comment thread" |
|
| keep_selection | :boolean | false |
opens without taking the focus, so the selection it opened over stays live to be copied. The first key typed goes to the composer inside instead
|
| variant | :atom | :thread |
`:thread` is a panel the host's conversation sits in. `:composer` draws no panel: what it holds (`ConnieUI.Chat.composer_form/1`'s `:pill`) is the surface, and the arrow is drawn as part of it, turning brand with its ring while it has the focus
:thread | :composer
|
| class | :any | nil |
|
| Slot | Slot attributes | Description |
|---|---|---|
| No data found. | ||
| inner_block * | ||