Skip to content

Conversation list

The reader's past conversations, grouped by date, each with a menu to rename, pin, archive or delete it.

  • <aparte-conversation-list>
On this page
Open

<aparte-conversation-list> draws the rows; it is not a store. You assign the conversations property and set active-id, it renders them and tells you what the reader picked. As soon as an item carries updatedAt, the rows are grouped by date: Pinned, Today, Yesterday, Previous 7 days, Previous 30 days, then one heading per month. flat keeps your order with no headings.

Each row is two buttons: its title, which selects it, and a ⋯ that opens its menu.

Press ⋯ on a row above: rename, pin or unpin, archive or unarchive, delete. Every item fires an event and stops. Rename turns the title into a field (Enter or leaving it commits, Escape cancels); delete asks first, inside the menu, because it is the one action you cannot undo.

Open

loading shows skeleton rows until your store answers: a list that is not there yet is not an empty list. An empty list draws nothing.

html
<aparte-conversation-list flat=""></aparte-conversation-list>
js
el.addEventListener('aparte-conversation-select', (e) => use(e.detail));

Installation and the framework-specific traps: React · Vue · Svelte · Angular.

The events carry the conversation’s id (and the new title, for a rename); the array stays as it was until you assign it again. To have the list carry out the menu’s actions itself, register a conversation manager with setConversationManager() and set manage: renaming, pinning, archiving and deleting then happen on that manager, and preventDefault() on the event still takes the gesture back. manage does not select: a click sends aparte-conversation-select, which a chat bound to the manager answers by opening that conversation.

The rows come from the array, so the element takes no children: put the new-chat button and the search field around it, in the sidebar.

<aparte-conversation-list> · class AparteConversationList

Attributes

AttributeDescription
active-idThe id of the conversation to render as selected.
flatRender the rows flat, in host order, with no date headings.
loadingThe list is on its way: six skeleton rows stand where the rows will be, the element is aria-busy and a visually hidden line names the wait. A list that is not there yet is not an empty list. Set it while your store answers, clear it when you assign conversations.
manageLet the list finish the gesture: rename, pin, unpin, archive, unarchive and delete are performed on the conversation manager registered with setConversationManager(), instead of leaving you six listeners to write. The event still fires first, and preventDefault() on it takes the gesture back. Off by default, and selecting stays yours either way.

Properties

PropertyTypeDescription
loadingbooleanThe list is on its way: rows of the kit’s skeleton stand where the rows will be, the element is aria-busy, and a visually hidden line names the wait. Reflected as the loading attribute, so a site sets it while its store answers and clears it when conversations is set. A list that is not there yet is not an empty list.
managebooleanLet the list finish the gesture through the registered conversation manager. Reflected as the manage attribute. The property is not a nicety here: this is the attribute that authorises a WRITE, and Vue and both Sveltes stringify a bound false onto an element that has no property of that name — manage="false", which hasAttribute reads as on. So turning management off turned it on, and a delete the host meant to handle itself was also done by the list. presenceOn, like loading above it.
conversationsAparteConversationListItem[]Set the list of conversations to display. Triggers a re-render.

Events

EventTypeDescription
aparte-conversation-selectCustomEvent<AparteConversationSelectDetail>A row’s title was activated; the host loads that conversation.
aparte-conversation-renameCustomEvent<AparteConversationRenameDetail>A rename was committed with a new, non-empty title. Cancelable: preventDefault() takes the gesture back from manage.
aparte-conversation-pinCustomEvent<AparteConversationPinDetail>The pin item was chosen on an unpinned row. Cancelable: preventDefault() takes the gesture back from manage.
aparte-conversation-unpinCustomEvent<AparteConversationPinDetail>The same item on a pinned row; same detail shape, opposite intent. Cancelable, like the rest.
aparte-conversation-archiveCustomEvent<AparteConversationArchiveDetail>The archive item was chosen on a live conversation. Cancelable: preventDefault() takes the gesture back from manage.
aparte-conversation-unarchiveCustomEvent<AparteConversationArchiveDetail>The same item on an already-archived one; same detail shape, opposite intent. Cancelable, like the rest.
aparte-conversation-deleteCustomEvent<AparteConversationDeleteDetail>The delete was confirmed. Cancelable: preventDefault() takes the gesture back from manage.

CSS variables

VariableDefaultDescription
--aparte-conv-list-gapvar(--aparte-space-1)Vertical gap between rows, and between a group’s heading and its rows.
--aparte-conv-item-paddingvar(--aparte-space-4) var(--aparte-space-5)Padding of a row’s title button.
--aparte-conv-item-gapvar(--aparte-space-3)Gap between a row’s title and its ⋯ button.
--aparte-conv-item-radiusvar(--aparte-radius-md)Corner radius of a row.
--aparte-conv-item-font-sizevar(--aparte-font-size-md)Font size of a row’s title.
--aparte-conv-item-colorvar(--aparte-text)Title colour of an inactive row.
--aparte-conv-item-bg-hovervar(--aparte-surface-3)Row background on hover.
--aparte-conv-item-bg-activevar(--aparte-surface-3)Background of the row matching active-id.
--aparte-conv-item-color-activevar(--aparte-text)Title colour of the active row.
--aparte-conv-item-font-weight-activevar(--aparte-font-weight-medium)Title weight of the active row.
--aparte-conv-action-btn-sizevar(--aparte-btn-size-sm)Square size of the ⋯ button (the recipe’s small step). Under (pointer: coarse) the stylesheet redeclares it as the touch target size on the button itself, so a value set on the element does not reach it there; the button also stays visible instead of appearing on hover.
  • The list is a navigation landmark named from the conversationList locale key (“Conversations”), unless you give it an aria-label or aria-labelledby of your own.
  • Each date group is a group named by its heading; the selected row is marked aria-current.
  • The ⋯ button announces a menu and whether it is open; the menu’s items are menu items.
  • While loading, the list is aria-busy and a status line says the conversations are loading.