brumate/ui

TokenField

A field of text with tokens in it, such as mentions, tags or commands, which the user types and the field turns into tokens.

Ask ​@ada​ about ​#launch​
Type a @name or a #tag, then a space.

Tokens: @ada, #launch.

<script>
  import { $bind, $memo, $signal } from 'brumate/signals';
  import Label from '@brumate/ui/Label.brm';
  import Text from '@brumate/ui/Text.brm';
  import Token from '@brumate/ui/Token.brm';
  import TokenField from '@brumate/ui/TokenField.brm';
  import TokenInput from '@brumate/ui/TokenInput.brm';
  import type { TokenSegment } from '@brumate/ui/token-field.ts';

  let message = $signal<TokenSegment[]>([
    { type: 'text', text: 'Ask ' },
    { type: 'token', text: '@ada' },
    { type: 'text', text: ' about ' },
    { type: 'token', text: '#launch' },
    { type: 'text', text: ' ' },
  ]);
  const tokens = $memo(message.filter((segment) => segment.type === 'token').map((one) => one.text));
</script>

<TokenField class="ui-field" pattern="[#@]\S+" placeholder="Write a message" value=$bind(message)>
  <Label class="ui-label">Message</Label>
  <TokenInput class="ui-input ui-token-input" token=chip />
  <Text slot="description" class="ui-description">Type a @name or a #tag, then a space.</Text>
</TokenField>
<p>Tokens: {tokens.join(', ') || 'none'}.</p>

#template chip(segment: TokenSegment) {
  <Token class=(segment.text.startsWith('@') ? 'ui-token ui-mention' : 'ui-token')>{segment.text}</Token>
}
<TokenField pattern="[#@]\S+" placeholder="Write a message" value=$bind(message)>
  <Label>Message</Label>
  <TokenInput token=chip />
  <Text slot="description">Type a @name or a #tag, then a space.</Text>
</TokenField>

#template chip(segment: TokenSegment) {
  <Token>{segment.text}</Token>
}

Editing