Pattern · Prompt Input
NewCommand Composer SwiftUI Block
A message composer with slash commands and at mentions: a filtered suggestion panel, chips for picks, and structured tokens on send.
A composer pinned above the keyboard that opens a suggestion panel when a word starts with / or @. Commands filter as you type, mentions search through your closure with Searching, no matches and Retry, and a pick becomes a chip above the text that onSend receives as a structured token.
- SwiftUI
- iOS 17.0+
- composer-mentions
$199 once, every piece included. See how installing works · Sign in
01
What's included
SwiftUI source you own, built on Apple frameworks only.
- / opens commands with a symbol, name and line, filtered as you type
- @ searches people and files through your closure
- Searching, no matches and a failure with Retry in the panel
- Picks become chips that remove with x or Delete
- onSend gets the text and the tokens, and Send turns into Stop
02
Implementation notes
How it behaves, what it handles, and the decisions behind it.
The composer is one card pinned above the keyboard, with a field that grows from one line to six and Send. Typing / at the start of a word opens a Commands panel above the card, each row a symbol, the command's name, a line about what it does and the command as typed, the first row highlighted; typing on filters it, so "sum" leaves Summarize. Typing @ opens People and files and searches through your closure a moment after typing pauses, showing Searching, the results, "No people or files match" or a failure with Retry. Tap a row or press Return to take the highlighted one: the typed word leaves the field and the pick becomes a chip on a row above the text, with its symbol and an x. Delete at the start of the field removes the last chip. With a hardware keyboard the arrow keys move the highlight and Escape closes the panel. Send stays off until there is text or a chip; while your onSend runs, Stop takes its place, and a failed send hands the text and chips back with the error under the card.
Notes
CommandComposer(commands:placeholder:onSearchMentions:onSend:). OnlyonSendis required. It is a section: no navigation stack, background, padding or scroll view of its own. Pin it with.safeAreaInset(edge: .bottom)and.padding(.horizontal, 20)on atheme.color.bgbackground; the panel grows upward from the card.CommandComposer.Commandis anid(what is typed after the slash, lowercased), atitle, a one-linedetailand an SF Symbol..summarize,.rewrite,.translate,.actionItemsand.explainare ready, andCommand.sampleslists them. Commands already used are left out of the panel. An empty list turns/into plain text.CommandComposer.Mentionis anid, akind(.personor.file), aname, adetail(a role, or where the file lives) and an optional symbol,person.crop.circleordocby default.Mention.samplesholds two people and three files.onSearchMentionsreceives what was typed after the@, empty right after it, about 180 milliseconds after typing pauses. A newer query cancels the one running. Return up to six matches. Throw to show the error's description, or "Couldn't search. Try again.", with Retry. Nil turns@into plain text.onSendreceivesCommandComposer.Message: thetext, trimmed and without the typed triggers, andtokens, an array ofToken(.commandor.mention) in the order they were picked, withcommandsandmentionsfor convenience.Token.labelis "/summarize" or "@Q3 Report.pdf".- Stop cancels the task and frees the composer at once. Any other thrown error shows its
errorDescription, or "Couldn't send. Try again.", and hands back the text and chips. - The panel follows the last word typed. Returns typed while it is open take the highlighted row instead of starting a new line.
- Haptics: a selection tick when the highlight moves or a chip is added, a light impact on Send, an error when a send fails.
- VoiceOver reads the panel's title as a header, each row as its name and line with the highlighted one selected, and each chip with a Remove button; adding and removing chips is announced. Every control has a 44 point target, except the chips' x, which sits in a 32 point chip and is also reached as its own button.
- Reduce Motion turns the panel and chips into short fades.
CommandComposerExampleat the end ofCommandComposer.swiftis the Workspace thread from the preview: five commands, a search over two people and three files that takes a moment, and a reply held for a couple of seconds so Stop can be tried. PasswrapsInNavigationStack: falseto push it in your own stack.
Theming
- Reads
SPThemefrom@Environment(\.spTheme)and requires thedesign-systemitem. - The card and the panel are
color.surfacewithradius.lgand 1 pointseparatorhairlines; the card's turns totextPrimarywhile the field is focused. The field istype.bodyintextPrimary, its prompttextTertiary. - Panel rows are at least 52 points: a 24 point symbol column in
textSecondary, names intype.body, lines intype.footnotetextSecondary, the typed command in monospacedtype.footnotetextTertiary. The highlighted row sits onfillatradius.md. The panel title istype.footnoteintextSecondary. - Chips are
fillcapsules 32 points tall withtype.subheadmedium labels intextPrimaryand symbols intextSecondary. - Send is the only accent: an
accentcircle with anaccentOnarrow,fillwithtextTertiarywhile off. Errors aretype.footnoteindanger. - State changes use
motion.smoothandmotion.snappy, and become short fades under Reduce Motion.
03
Keep building
Pieces that work well next to this one.