79724b5bc9
Add a reusable multiselect dropdown component inspired by the issue
sidebar label picker, but decoupled from issue-specific logic.
Components:
- templates/shared/combolist.tmpl — generic template accepting Items,
Name, Title, SelectedValues parameters
- web_src/js/features/combo-multiselect.ts — lightweight JS init that
handles check/uncheck, search, and hidden input updates
- web_src/css/modules/combo-multiselect.css — check-mark visibility
and selected-items list styling
Usage in any template:
{{template "shared/combolist" dict
"Name" "channels"
"Title" "Update Channels"
"Items" .AvailableChannels
"SelectedValues" .SelectedChannelIDs
}}
Items must have .Value and .Label fields.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
47 lines
1.9 KiB
Handlebars
47 lines
1.9 KiB
Handlebars
{{/*
|
|
Generic multiselect combo list component.
|
|
Provides a dropdown with search, checkable items, and a selected-items display list.
|
|
|
|
Parameters:
|
|
Name - form input name (required)
|
|
Title - display label (required)
|
|
Items - slice of items, each must have .Value and .Label fields
|
|
SelectedValues - comma-separated string of selected values
|
|
Placeholder - search input placeholder (optional, defaults to "Filter...")
|
|
EmptyText - text when nothing is selected (optional)
|
|
Disabled - whether the control is disabled (optional)
|
|
Icon - gear icon shown next to title (optional, defaults to "octicon-gear")
|
|
*/}}
|
|
<div class="combo-multiselect" data-field-name="{{.Name}}">
|
|
<input class="combo-value" name="{{.Name}}" type="hidden" value="{{.SelectedValues}}">
|
|
<div class="ui dropdown full-width {{if .Disabled}}disabled{{end}}">
|
|
<a class="fixed-text muted">
|
|
<strong>{{.Title}}</strong> {{if not .Disabled}}{{svg (or .Icon "octicon-gear")}}{{end}}
|
|
</a>
|
|
<div class="menu">
|
|
{{if .Items}}
|
|
<div class="ui icon search input">
|
|
<i class="icon">{{svg "octicon-search" 16}}</i>
|
|
<input type="text" placeholder="{{or .Placeholder (ctx.Locale.Tr "search.filter")}}">
|
|
</div>
|
|
<div class="scrolling menu">
|
|
<a class="item clear-selection" href="#">{{ctx.Locale.Tr "repo.issues.new.clear_labels"}}</a>
|
|
<div class="divider"></div>
|
|
{{range .Items}}
|
|
<a class="item" data-value="{{.Value}}">
|
|
<span class="item-check-mark">{{svg "octicon-check" 16}}</span>
|
|
<span class="item-label">{{.Label}}</span>
|
|
</a>
|
|
{{end}}
|
|
</div>
|
|
{{else}}
|
|
<div class="item disabled">{{or .EmptyText (ctx.Locale.Tr "repo.issues.new.no_items")}}</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ui list combo-multiselect-list">
|
|
<span class="item empty-list">{{or .EmptyText "None"}}</span>
|
|
</div>
|
|
</div>
|