Channel typeahead: ~ to link a channel, like @ for people #274

Closed
opened 2026-08-09 13:49:52 +00:00 by robbertbos · 0 comments
Owner

Typing @ in the composer opens a people picker and inserts @username. Mattermost has the same affordance for channels — ~channel-name renders as a channel link — but we have no typeahead for it, so you have to know and type the exact slug.

Feasible, and mostly cheap

Checked while working on #168:

  • The candidate list already exists. GET /api/mm/targets?account_id=… returns every channel and conversation for the account and is already cached for 30s (useTargets, used by the composer's "Aan" picker). Filtering can be client-side, so no request per keystroke.
  • The typeahead machinery is trigger-agnostic. On the NLDD engine the @ and : lists are one consumer-owned component driven by a regex plus a fetcher; a third trigger is a small addition. On the Tiptap engine @tiptap/suggestion takes a char option, so ~ is a second configured instance of what mentionSuggest.ts already does.

One thing that is not free

~ links resolve on the channel slug, not the display name (~town-square, not ~Town Square). Target currently carries display_name but no slug (backend/waggle/schemas/mm_targets.py:20-36), so the backend has to expose it — probably channel_name, straight from the MM channel's name.

So: one backend field, one frontend typeahead, per engine.

Depends on the escaping fix

Worth noting these interact: until recently the composer sent ~town-square as \~town-square, because tiptap-markdown escapes every tilde. Mattermost's channel autolinking then did not resolve it. Fixed in #271 — a ~ typeahead that inserted a link Mattermost would not resolve would have been worse than none.

Scope note

Only channels are linkable this way (kind === 'channel'); DMs and group conversations have no ~ form, so they should not appear in the list.

Typing `@` in the composer opens a people picker and inserts `@username`. Mattermost has the same affordance for channels — `~channel-name` renders as a channel link — but we have no typeahead for it, so you have to know and type the exact slug. ## Feasible, and mostly cheap Checked while working on #168: - **The candidate list already exists.** `GET /api/mm/targets?account_id=…` returns every channel and conversation for the account and is already cached for 30s (`useTargets`, used by the composer's "Aan" picker). Filtering can be client-side, so no request per keystroke. - **The typeahead machinery is trigger-agnostic.** On the NLDD engine the `@` and `:` lists are one consumer-owned component driven by a regex plus a fetcher; a third trigger is a small addition. On the Tiptap engine `@tiptap/suggestion` takes a `char` option, so `~` is a second configured instance of what `mentionSuggest.ts` already does. ## One thing that is not free `~` links resolve on the channel **slug**, not the display name (`~town-square`, not `~Town Square`). `Target` currently carries `display_name` but no slug (`backend/waggle/schemas/mm_targets.py:20-36`), so the backend has to expose it — probably `channel_name`, straight from the MM channel's `name`. So: one backend field, one frontend typeahead, per engine. ## Depends on the escaping fix Worth noting these interact: until recently the composer sent `~town-square` as `\~town-square`, because tiptap-markdown escapes every tilde. Mattermost's channel autolinking then did not resolve it. Fixed in #271 — a `~` typeahead that inserted a link Mattermost would not resolve would have been worse than none. ## Scope note Only channels are linkable this way (`kind === 'channel'`); DMs and group conversations have no `~` form, so they should not appear in the list.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
robbertbos/waggle#274
No description provided.