@retailcrm/embed-ui-v1-components 0.9.13 → 0.9.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/AGENTS.md +126 -0
  2. package/README.md +24 -0
  3. package/assets/stylesheets/palette.less +11 -6
  4. package/bin/embed-ui-v1-components.mjs +209 -0
  5. package/bin/postinstall.mjs +37 -0
  6. package/dist/host.cjs +1900 -590
  7. package/dist/host.css +659 -6
  8. package/dist/host.d.ts +2374 -50
  9. package/dist/host.js +1901 -591
  10. package/dist/remote.cjs +610 -33
  11. package/dist/remote.d.ts +729 -48
  12. package/dist/remote.js +612 -35
  13. package/docs/AI.md +106 -0
  14. package/docs/COMPONENTS.md +96 -0
  15. package/docs/FORMAT.md +248 -0
  16. package/docs/PROFILES.md +64 -0
  17. package/docs/README.md +65 -0
  18. package/docs/STYLING.md +156 -0
  19. package/docs/profiles/UiAddButton.yml +45 -0
  20. package/docs/profiles/UiAlert.yml +36 -0
  21. package/docs/profiles/UiAvatar.yml +36 -0
  22. package/docs/profiles/UiAvatarList.yml +30 -0
  23. package/docs/profiles/UiButton.yml +221 -0
  24. package/docs/profiles/UiCalendar.yml +36 -0
  25. package/docs/profiles/UiCheckbox.yml +41 -0
  26. package/docs/profiles/UiCollapse.yml +28 -0
  27. package/docs/profiles/UiCollapseBox.yml +39 -0
  28. package/docs/profiles/UiCollapseGroup.yml +27 -0
  29. package/docs/profiles/UiCopyButton.yml +40 -0
  30. package/docs/profiles/UiDate.yml +26 -0
  31. package/docs/profiles/UiDatePicker.yml +47 -0
  32. package/docs/profiles/UiError.yml +20 -0
  33. package/docs/profiles/UiField.yml +229 -0
  34. package/docs/profiles/UiImage.yml +27 -0
  35. package/docs/profiles/UiInfobox.yml +33 -0
  36. package/docs/profiles/UiLink.yml +39 -0
  37. package/docs/profiles/UiLoader.yml +26 -0
  38. package/docs/profiles/UiMenuItem.yml +45 -0
  39. package/docs/profiles/UiMenuItemGroup.yml +38 -0
  40. package/docs/profiles/UiModalSidebar.yml +34 -0
  41. package/docs/profiles/UiModalWindow.yml +32 -0
  42. package/docs/profiles/UiModalWindowSurface.yml +29 -0
  43. package/docs/profiles/UiNumberStepper.yml +40 -0
  44. package/docs/profiles/UiPageHeader.yml +240 -0
  45. package/docs/profiles/UiPopper.yml +197 -0
  46. package/docs/profiles/UiPopperConnector.yml +109 -0
  47. package/docs/profiles/UiPopperTarget.yml +112 -0
  48. package/docs/profiles/UiRadio.yml +26 -0
  49. package/docs/profiles/UiRadioSwitch.yml +224 -0
  50. package/docs/profiles/UiRadioSwitchOption.yml +113 -0
  51. package/docs/profiles/UiScrollBox.yml +19 -0
  52. package/docs/profiles/UiSelect.yml +318 -0
  53. package/docs/profiles/UiSelectOption.yml +32 -0
  54. package/docs/profiles/UiSelectOptionGroup.yml +26 -0
  55. package/docs/profiles/UiSlider.yml +26 -0
  56. package/docs/profiles/UiSwitch.yml +25 -0
  57. package/docs/profiles/UiTab.yml +114 -0
  58. package/docs/profiles/UiTabGroup.yml +233 -0
  59. package/docs/profiles/UiTable.yml +148 -0
  60. package/docs/profiles/UiTableBodyCell.yml +35 -0
  61. package/docs/profiles/UiTableColumn.yml +38 -0
  62. package/docs/profiles/UiTableFooterButton.yml +32 -0
  63. package/docs/profiles/UiTableFooterSection.yml +26 -0
  64. package/docs/profiles/UiTableHeadCell.yml +32 -0
  65. package/docs/profiles/UiTableSorter.yml +33 -0
  66. package/docs/profiles/UiTag.yml +29 -0
  67. package/docs/profiles/UiTextbox.yml +388 -0
  68. package/docs/profiles/UiTimePicker.yml +34 -0
  69. package/docs/profiles/UiToolbarButton.yml +25 -0
  70. package/docs/profiles/UiToolbarLink.yml +20 -0
  71. package/docs/profiles/UiTooltip.yml +31 -0
  72. package/docs/profiles/UiTransition.yml +15 -0
  73. package/docs/profiles/UiYandexMap.yml +17 -0
  74. package/package.json +11 -2
@@ -0,0 +1,26 @@
1
+ component: UiRadio
2
+ summary: >
3
+ UiRadio is the single-choice selection control for exclusive option sets.
4
+ It is the radio-style counterpart to UiCheckbox.
5
+
6
+ public_import:
7
+ from: '@retailcrm/embed-ui-v1-components/remote'
8
+ named:
9
+ - UiRadio
10
+
11
+ use_when:
12
+ - You need one selected value from a fixed set.
13
+
14
+ avoid_when:
15
+ - You need multiple independent selections, use UiCheckbox instead.
16
+
17
+ api:
18
+ key_props:
19
+ - name: model
20
+ - name: value
21
+ - name: required
22
+ - name: disabled
23
+ methods:
24
+ - name: click
25
+ - name: focus
26
+ - name: blur
@@ -0,0 +1,224 @@
1
+ component: UiRadioSwitch
2
+ summary: >
3
+ UiRadioSwitch is a single-choice segmented control with two practical modes:
4
+ a compact inline switch and a richer section-card layout. It is useful when the
5
+ choice set is small and always visible. For richer per-option content, compose it
6
+ with UiRadioSwitchOption instead of relying only on the options array.
7
+
8
+ public_import:
9
+ from: '@retailcrm/embed-ui-v1-components/remote'
10
+ named:
11
+ - UiRadioSwitch
12
+ - UiRadioSwitchOption
13
+
14
+ related_components:
15
+ - UiRadio
16
+ - UiField
17
+ - UiRadioSwitchOption
18
+
19
+ use_when:
20
+ - You need one selected value from a small fixed set.
21
+ - You want a segmented control instead of classic radio circles.
22
+ - You need a card-like section switch with descriptions.
23
+ - You need object values and must compare them through equalFn.
24
+
25
+ avoid_when:
26
+ - You need multiple independent selections.
27
+ - You need dozens of options or searchable choice, use UiSelect instead.
28
+ - You need free-form content unrelated to a single-choice switch.
29
+
30
+ api:
31
+ key_props:
32
+ - name: value
33
+ notes: Current selected value.
34
+ - name: options
35
+ notes: Quick array-based way to declare simple options.
36
+ - name: equalFn
37
+ notes: Important when option values are objects or other non-primitives.
38
+ - name: appearance
39
+ notes: Switches between default inline mode and section card mode.
40
+ - name: size
41
+ notes: Controls option height and icon sizing in default mode.
42
+ - name: rubber
43
+ notes: Makes the root behave like inline-flex instead of stretching full width.
44
+ props:
45
+ - name: value
46
+ notes: Works as the single selected model value.
47
+ - name: options
48
+ notes: Expects array items shaped as { label, value, disabled }.
49
+ - name: equalFn
50
+ notes: Defaults to strict equality.
51
+ - name: appearance
52
+ notes: Supports default and section.
53
+ - name: size
54
+ notes: Supports sm, md, lg.
55
+ - name: rubber
56
+ notes: Useful when the switch should size to content.
57
+ child_components:
58
+ - name: UiRadioSwitchOption
59
+ key_props:
60
+ - value
61
+ - label
62
+ - description
63
+ - disabled
64
+ notes: >
65
+ Use it when an option needs description, custom icon, custom label, or
66
+ custom checkmark content.
67
+ slots:
68
+ - name: default
69
+ zone: option tree
70
+ creates: Replaces array-based options with manually declared UiRadioSwitchOption nodes.
71
+ accepts:
72
+ recommended:
73
+ - UiRadioSwitchOption
74
+ avoid:
75
+ - arbitrary interactive controls
76
+ - unrelated wrappers
77
+ notes: >
78
+ The simplest path is options for plain labels, and default slot for richer
79
+ option markup.
80
+ - name: icon
81
+ zone: shared option icon in options mode
82
+ notes: >
83
+ Used only when options array mode renders generated options. For per-option
84
+ rich composition, use UiRadioSwitchOption slots instead.
85
+ emits:
86
+ - name: change
87
+ payload: unknown
88
+ notes: Fired when the selected value changes.
89
+ - name: update:value
90
+ payload: unknown
91
+ notes: Main v-model channel.
92
+
93
+ rendered_structure:
94
+ descriptive_only: true
95
+ notes: >
96
+ The component renders as one radiogroup root and a list of option shells with
97
+ radio semantics. This section is for mental modeling and debugging, not as a
98
+ stable styling contract.
99
+ composition:
100
+ - UiRadioSwitch root with role=radiogroup
101
+ - UiRadioSwitchOption shells with role=radio
102
+ - section mode can add description and selected-state checkmark
103
+ classes:
104
+ - .ui-v1-radio-switch
105
+ - .ui-v1-radio-switch_borderless
106
+ - .ui-v1-radio-switch_rubber
107
+ - .ui-v1-radio-switch-option
108
+ - .ui-v1-radio-switch-option_default
109
+ - .ui-v1-radio-switch-option_standalone
110
+ - .ui-v1-radio-switch-option_active
111
+ - .ui-v1-radio-switch-option_disabled
112
+
113
+ geometry:
114
+ layout: flex row for default mode, wrapping card row for section mode
115
+ notes:
116
+ - Default appearance behaves like a segmented control with adjacent options.
117
+ - Section appearance removes the outer border and lets cards wrap to a new line.
118
+ - rubber makes the root inline-sized instead of full-width.
119
+ - In section mode each option has a large minimum width and card-like padding.
120
+
121
+ styling:
122
+ notes:
123
+ - Current classes describe host DOM structure and states.
124
+ - Prefer appearance, size, and rubber over selector-level customization.
125
+ root_classes:
126
+ - .ui-v1-radio-switch
127
+ - .ui-v1-radio-switch-option
128
+ state_classes:
129
+ - .ui-v1-radio-switch_borderless
130
+ - .ui-v1-radio-switch_rubber
131
+ - .ui-v1-radio-switch-option_default
132
+ - .ui-v1-radio-switch-option_standalone
133
+ - .ui-v1-radio-switch-option_active
134
+ - .ui-v1-radio-switch-option_disabled
135
+ zones:
136
+ - .ui-v1-radio-switch-option__head
137
+ - .ui-v1-radio-switch-option__icon
138
+ - .ui-v1-radio-switch-option__label
139
+ - .ui-v1-radio-switch-option__description
140
+ - .ui-v1-radio-switch-option__done
141
+ typography:
142
+ default:
143
+ notes:
144
+ - Default mode uses regular text sizing.
145
+ - Section mode uses accent heading-like styling for the main label.
146
+
147
+ behavior:
148
+ states:
149
+ - name: appearance=default
150
+ notes: Renders a compact segmented control.
151
+ - name: appearance=section
152
+ notes: Renders standalone cards with optional description and selected checkmark.
153
+ - name: disabled
154
+ notes: Disabled options cannot be selected or focused by keyboard navigation.
155
+ - name: rubber
156
+ notes: Keeps the root content-sized.
157
+ selection_and_matching:
158
+ - The component is always single-select.
159
+ - update:value and change are emitted together on selection change.
160
+ - equalFn should usually be provided when values are objects.
161
+ - In options mode the component generates UiRadioSwitchOption nodes internally.
162
+ keyboard:
163
+ - One tab stop is used for the whole group.
164
+ - ArrowLeft, ArrowRight, ArrowUp, and ArrowDown move focus and selection across enabled options.
165
+ - Home and End jump to the first or last enabled option.
166
+ - Space and Enter select the currently focused option.
167
+
168
+ accessibility:
169
+ notes:
170
+ - The root acts as radiogroup.
171
+ - Each option acts as radio and exposes aria-checked and aria-disabled.
172
+ - The current implementation uses roving tabindex so only one option is tabbable.
173
+
174
+ composition:
175
+ works_well_with:
176
+ - UiField
177
+ - UiRadioSwitchOption
178
+ patterns:
179
+ - title: Simple mode switch
180
+ notes: Use options for a small plain-text set such as view or status mode.
181
+ - title: Section cards
182
+ notes: Use UiRadioSwitchOption when each choice needs icon, description, or custom checkmark.
183
+
184
+ examples:
185
+ - title: Simple options array
186
+ goal: Build a compact single-choice segmented control.
187
+ code: |
188
+ <UiRadioSwitch
189
+ v-model:value="mode"
190
+ :options="[
191
+ { label: 'Auto', value: 'auto' },
192
+ { label: 'Manual', value: 'manual' },
193
+ ]"
194
+ />
195
+ - title: Rich card options
196
+ goal: Render section cards with object values and descriptions.
197
+ code: |
198
+ <UiRadioSwitch
199
+ v-model:value="mode"
200
+ appearance="section"
201
+ rubber
202
+ :equal-fn="(a, b) => a?.key === b?.key"
203
+ >
204
+ <UiRadioSwitchOption
205
+ label="Auto"
206
+ :value="{ key: 'auto' }"
207
+ description="Automatic mode"
208
+ />
209
+
210
+ <UiRadioSwitchOption
211
+ label="Manual"
212
+ :value="{ key: 'manual' }"
213
+ description="Manual setup"
214
+ />
215
+ </UiRadioSwitch>
216
+
217
+ ai_notes:
218
+ do:
219
+ - Use options for simple text-only cases.
220
+ - Switch to UiRadioSwitchOption when a choice needs richer content.
221
+ - Provide equalFn for object values instead of relying on reference equality.
222
+ avoid:
223
+ - Do not use it for multi-select flows.
224
+ - Do not treat internal .ui-v1-* classes as a stable extension styling API.
@@ -0,0 +1,113 @@
1
+ component: UiRadioSwitchOption
2
+ summary: >
3
+ UiRadioSwitchOption is the declarative option child of UiRadioSwitch. It is the
4
+ richer alternative to the plain options array and is used when one option needs
5
+ custom icon, label, description, or selected-state checkmark content.
6
+
7
+ public_import:
8
+ from: '@retailcrm/embed-ui-v1-components/remote'
9
+ named:
10
+ - UiRadioSwitchOption
11
+ - UiRadioSwitch
12
+
13
+ related_components:
14
+ - UiRadioSwitch
15
+
16
+ use_when:
17
+ - You need one manually declared option inside UiRadioSwitch.
18
+ - One option needs description or custom slot content.
19
+ - You need per-option icon or custom selected-state mark.
20
+
21
+ avoid_when:
22
+ - A simple options array on UiRadioSwitch is enough.
23
+ - You need standalone radio semantics outside UiRadioSwitch.
24
+
25
+ api:
26
+ key_props:
27
+ - name: value
28
+ notes: Required option value.
29
+ - name: label
30
+ notes: Plain-text fallback label.
31
+ - name: description
32
+ notes: Secondary copy for section appearance.
33
+ - name: disabled
34
+ notes: Marks this option as non-interactive.
35
+ props:
36
+ - name: id
37
+ notes: Optional explicit id, otherwise generated automatically.
38
+ - name: value
39
+ notes: Required and passed back through UiRadioSwitch selection updates.
40
+ - name: label
41
+ notes: Optional when label slot is used.
42
+ - name: description
43
+ notes: Primarily useful for appearance=section.
44
+ - name: disabled
45
+ notes: Excluded from selection and keyboard navigation.
46
+ slots:
47
+ - name: default
48
+ zone: full option body
49
+ notes: Replaces the whole internal option layout.
50
+ - name: icon
51
+ zone: leading icon
52
+ notes: Custom leading icon for the option header.
53
+ - name: label
54
+ zone: main label
55
+ notes: Overrides the plain label prop.
56
+ - name: description
57
+ zone: secondary description
58
+ notes: Used mainly in section mode.
59
+ - name: checkmark
60
+ zone: selected-state indicator
61
+ notes: Replaces the default selected-state icon in section mode.
62
+
63
+ rendered_structure:
64
+ descriptive_only: true
65
+ notes: >
66
+ UiRadioSwitchOption does not own the whole selection model. It is rendered inside
67
+ UiRadioSwitch and becomes one radio node within the parent radiogroup.
68
+
69
+ behavior:
70
+ states:
71
+ - name: disabled
72
+ notes: Cannot be selected and is skipped by keyboard navigation.
73
+ - name: checked
74
+ notes: Managed by the parent UiRadioSwitch.
75
+ - name: appearance=section
76
+ notes: Can show description and selected-state checkmark.
77
+ notes:
78
+ - Click selects the option through the parent group.
79
+ - Space and Enter select the focused option.
80
+ - Arrow keys delegate focus and selection movement through the parent group.
81
+
82
+ accessibility:
83
+ notes:
84
+ - The parent group applies radio semantics to the option shell.
85
+ - The current implementation participates in roving tabindex managed by UiRadioSwitch.
86
+
87
+ composition:
88
+ works_well_with:
89
+ - UiRadioSwitch
90
+ patterns:
91
+ - title: Rich switch option
92
+ notes: Use when one option needs icon, label, description, and custom selected state.
93
+
94
+ examples:
95
+ - title: Section option
96
+ goal: Define one rich option inside a radio switch.
97
+ code: |
98
+ <UiRadioSwitchOption
99
+ label="Manual"
100
+ :value="{ key: 'manual' }"
101
+ description="Manual setup"
102
+ >
103
+ <template #icon>
104
+ <IconStar />
105
+ </template>
106
+ </UiRadioSwitchOption>
107
+
108
+ ai_notes:
109
+ do:
110
+ - Use inside UiRadioSwitch when one option needs richer content than the options array allows.
111
+ - Prefer label and description props for simple content and slots for richer custom markup.
112
+ avoid:
113
+ - Do not use it as a standalone control outside UiRadioSwitch.
@@ -0,0 +1,19 @@
1
+ component: UiScrollBox
2
+ summary: >
3
+ UiScrollBox is a scrollable container for constrained content areas. Use it when content
4
+ should remain inside a dedicated scrolling region instead of growing the whole page.
5
+
6
+ public_import:
7
+ from: '@retailcrm/embed-ui-v1-components/remote'
8
+ named:
9
+ - UiScrollBox
10
+
11
+ use_when:
12
+ - You need a bounded scroll area.
13
+ - You need long content inside a fixed-height or fixed-width region.
14
+
15
+ avoid_when:
16
+ - You need normal page scrolling.
17
+
18
+ api:
19
+ key_props: []
@@ -0,0 +1,318 @@
1
+ component: UiSelect
2
+ summary: >
3
+ UiSelect is a dropdown component for single-select and multi-select flows. It combines
4
+ a textbox-like trigger with a popper-based option layer. For a correct mental model,
5
+ read it together with UiPopper, UiPopperConnector, and UiPopperTarget.
6
+
7
+ public_import:
8
+ from: '@retailcrm/embed-ui-v1-components/remote'
9
+ named:
10
+ - UiSelect
11
+ - UiSelectOption
12
+ - UiSelectOptionGroup
13
+
14
+ related_components:
15
+ - UiField
16
+ - UiTextbox
17
+ - UiPopper
18
+ - UiPopperConnector
19
+ - UiPopperTarget
20
+
21
+ use_when:
22
+ - You need to choose one value from a list.
23
+ - You need multi-select behavior.
24
+ - You need filtering over option labels or descriptions.
25
+ - You need grouped options.
26
+ - You need field semantics plus a dropdown selector.
27
+
28
+ avoid_when:
29
+ - You need free-form text input.
30
+ - You need a button menu without a value model.
31
+ - You need a custom async-search UX outside the documented select flow.
32
+
33
+ api:
34
+ key_props:
35
+ - name: value
36
+ notes: Selected value or array of values in multiple mode.
37
+ - name: placeholder
38
+ notes: Trigger text for empty state.
39
+ - name: multiple
40
+ notes: Switches to an array-based value model.
41
+ - name: filterable
42
+ notes: Enables typed filtering.
43
+ - name: clearable
44
+ notes: Enables a clear action for selection or filter text.
45
+ - name: equalsFn
46
+ notes: Critical for object values.
47
+ - name: placement
48
+ notes: Controls where the popper is positioned.
49
+ - name: popperFitTrigger
50
+ notes: Keeps the dropdown at least as wide as the trigger.
51
+ - name: expanded
52
+ notes: Lets the parent control open state.
53
+ props:
54
+ - name: invalid
55
+ notes: Enables error state on the textbox-like trigger.
56
+ - name: readonly
57
+ notes: Keeps the current value visible but blocks changes.
58
+ - name: disabled
59
+ notes: Disables both trigger and dropdown interaction.
60
+ - name: placeholderOnly
61
+ notes: Forces the trigger to show only placeholder text.
62
+ - name: textboxSize
63
+ notes: Controls the trigger size.
64
+ - name: targetTriggers
65
+ notes: Popper trigger rules on the target side.
66
+ - name: popperTriggers
67
+ notes: Popper trigger rules on the dropdown side.
68
+ - name: popperClass
69
+ notes: Extra class for the dropdown layer.
70
+ - name: popperOptions
71
+ notes: Low-level floating behavior options.
72
+ - name: ticker
73
+ notes: Technical signal for relayout or selection updates.
74
+ child_components:
75
+ - name: UiSelectOption
76
+ key_props:
77
+ - value
78
+ - label
79
+ - description
80
+ - disabled
81
+ - counter
82
+ - accent
83
+ notes: Base selectable option node.
84
+ - name: UiSelectOptionGroup
85
+ key_props:
86
+ - label
87
+ notes: Groups related options together.
88
+ slots:
89
+ - name: default
90
+ zone: option tree inside popper content
91
+ creates: The option registry and the visible option tree inside the dropdown.
92
+ accepts:
93
+ recommended:
94
+ - UiSelectOption
95
+ - UiSelectOptionGroup
96
+ avoid:
97
+ - arbitrary div wrappers
98
+ - form controls
99
+ - unrelated custom layout
100
+ layout_effect: Child nodes become dropdown content and participate in selection, filtering, and keyboard navigation.
101
+ notes: >
102
+ The safe path is to build the option tree from UiSelectOption and UiSelectOptionGroup.
103
+ Arbitrary children can break selection, keyboard navigation, and active-option flow.
104
+ emits:
105
+ - name: update:value
106
+ payload: unknown
107
+ notes: Main selection update channel.
108
+ - name: input
109
+ payload: Event
110
+ notes: Comes from the textbox-like trigger.
111
+ - name: focus
112
+ payload: FocusEvent
113
+ notes: Trigger focus.
114
+ - name: blur
115
+ payload: FocusEvent
116
+ notes: Trigger blur.
117
+ - name: clear
118
+ payload: undefined
119
+ notes: Fired when the clear action is used.
120
+ - name: update:expanded
121
+ payload: boolean
122
+ notes: Open-state update channel.
123
+ - name: keydown
124
+ payload: KeyboardEvent
125
+ notes: Main keyboard navigation channel.
126
+ - name: show
127
+ payload: undefined
128
+ notes: The dropdown starts opening.
129
+ - name: hide
130
+ payload: undefined
131
+ notes: The dropdown starts closing.
132
+ - name: shown
133
+ payload: undefined
134
+ notes: The dropdown is open.
135
+ - name: hidden
136
+ payload: undefined
137
+ notes: The dropdown is closed.
138
+ - name: dispose
139
+ payload: undefined
140
+ notes: The dropdown layer is disposed.
141
+
142
+ rendered_structure:
143
+ descriptive_only: true
144
+ notes: >
145
+ Select is not a single DOM node in practice. Trigger and dropdown live in separate layers.
146
+ composition:
147
+ - UiPopperConnector as shared context
148
+ - UiSelectTrigger as textbox-like trigger
149
+ - UiSelectPopper as dropdown layer
150
+ - no-results text when filterable and no match exists
151
+ - default slot with the option tree
152
+ classes:
153
+ - .ui-v1-select for trigger root
154
+ - .ui-v1-select__popper for dropdown root
155
+ - .ui-v1-select-option for option root
156
+ - .ui-v1-select-option-group for option group
157
+
158
+ geometry:
159
+ trigger_layout: textbox-like, fit-content, max-width 100%
160
+ dropdown_layout: popper layer outside normal document flow
161
+ notes:
162
+ - The trigger behaves visually like a textbox.
163
+ - The dropdown is rendered in a popper layer outside normal flow.
164
+ - The dropdown content has max-height and internal scrolling.
165
+ - popperFitTrigger is useful when the dropdown should not be narrower than the trigger.
166
+ - In multiple mode the trigger may collapse into a summary label when selected labels do not fit.
167
+
168
+ styling:
169
+ notes:
170
+ - The trigger reuses the textbox visual model.
171
+ - The dropdown reuses popper variables for padding, radius, and floating surface geometry.
172
+ - Classes are descriptive implementation hooks, not a stable external styling contract.
173
+ root_classes:
174
+ - .ui-v1-select
175
+ - .ui-v1-select__trigger
176
+ - .ui-v1-select__touchstone
177
+ - .ui-v1-select__input
178
+ - .ui-v1-select__popper
179
+ - .ui-v1-select__content
180
+ - .ui-v1-select__no-results-text
181
+ - .ui-v1-select-option
182
+ - .ui-v1-select-option-group
183
+ state_classes:
184
+ - .ui-v1-select_active
185
+ - .ui-v1-select_filterable
186
+ - .ui-v1-select__content_locked
187
+ - .ui-v1-select-option_hidden
188
+ - .ui-v1-select-option-group_hidden
189
+ css_variables:
190
+ public_theme_variables:
191
+ - name: --ui-v1-popper-padding
192
+ effect: Dropdown content padding.
193
+ - name: --ui-v1-popper-roundings
194
+ effect: Dropdown surface corner radius.
195
+ inherited_component_variables:
196
+ - name: --ui-v1-textbox-primary-color
197
+ effect: Active trigger underline and caret color.
198
+ internal_layout_variables:
199
+ - name: --border-color
200
+ effect: Trigger border or underline color inherited from UiTextbox.
201
+ - name: --active-color
202
+ effect: Trigger active color inherited from UiTextbox.
203
+ typography:
204
+ trigger:
205
+ notes:
206
+ - Trigger typography follows UiTextbox and therefore depends on textboxSize.
207
+ - The default trigger size is the textbox default size unless textboxSize changes it.
208
+ dropdown:
209
+ font_family: shared ui font family
210
+ notes:
211
+ - No-results text uses the dropdown text styling rather than heading typography.
212
+ - Option and group rows should be treated as compact list content, not heading-scale content.
213
+
214
+ behavior:
215
+ states:
216
+ - name: multiple
217
+ notes: Switches the value model to an array and enables multi-selection.
218
+ - name: filterable
219
+ notes: Enables typed filtering by label or description.
220
+ - name: clearable
221
+ notes: Enables a clear action for selection or filter text.
222
+ - name: readonly
223
+ notes: Prevents changes while keeping display intact.
224
+ - name: disabled
225
+ notes: Disables both trigger and dropdown interaction.
226
+ - name: invalid
227
+ notes: Enables error styling on the trigger.
228
+ - name: placeholderOnly
229
+ notes: Forces placeholder display instead of selected labels.
230
+ selection_and_matching:
231
+ - If option values are objects, equalsFn is usually required.
232
+ - In single-select mode the dropdown closes after selecting an option.
233
+ - In multiple mode values are toggled inside the array model.
234
+ - Filtering matches option labels and descriptions.
235
+ - If nothing matches, a no-result block is shown.
236
+ keyboard:
237
+ - Arrow keys move the active highlight.
238
+ - Escape closes the dropdown.
239
+ - Tab closes the dropdown and lets focus move on.
240
+ - The active option is auto-scrolled into view when needed.
241
+
242
+ accessibility:
243
+ notes:
244
+ - The trigger uses role=combobox.
245
+ - The trigger manages aria-expanded, aria-controls, aria-haspopup, and aria-activedescendant.
246
+ - The dropdown acts as a listbox-like layer.
247
+ - In multiple mode it is marked as aria-multiselectable=true.
248
+
249
+ composition:
250
+ works_well_with:
251
+ - UiField
252
+ - UiSelectOption
253
+ - UiSelectOptionGroup
254
+ - UiPopper
255
+ - UiPopperConnector
256
+ - UiPopperTarget
257
+ patterns:
258
+ - title: Form field select
259
+ notes: Put UiSelect inside UiField for labeled required choices.
260
+ - title: Object value selection
261
+ notes: Use equalsFn explicitly for object values.
262
+ - title: Popper mental model
263
+ notes: Think of UiSelect as target plus floating dropdown, not as a single inline control.
264
+
265
+ examples:
266
+ - title: Standard select in a field
267
+ goal: Build a labeled select with field semantics.
268
+ code: |
269
+ <UiField id="assignee" label="Assignee">
270
+ <template #default="field">
271
+ <UiSelect
272
+ :id="field.id"
273
+ :invalid="field.invalid"
274
+ :placeholder="'Select assignee'"
275
+ v-model:value="assignee"
276
+ >
277
+ <UiSelectOption value="kyle" label="Kyle Simmons" />
278
+ <UiSelectOption value="eduardo" label="Eduardo Henry" />
279
+ </UiSelect>
280
+ </template>
281
+ </UiField>
282
+ - title: Grouped options
283
+ goal: Build a grouped option tree through the safe child components.
284
+ code: |
285
+ <UiSelect placeholder="Employee">
286
+ <UiSelectOptionGroup label="Sales">
287
+ <UiSelectOption value="kyle" label="Kyle Simmons" />
288
+ </UiSelectOptionGroup>
289
+
290
+ <UiSelectOptionGroup label="Support">
291
+ <UiSelectOption value="philip" label="Philip Williamson" />
292
+ </UiSelectOptionGroup>
293
+ </UiSelect>
294
+ - title: Object values with equalsFn
295
+ goal: Avoid object comparison by reference.
296
+ code: |
297
+ <UiSelect
298
+ v-model:value="selectedUser"
299
+ :equals-fn="(left, right) => left?.id === right?.id"
300
+ placeholder="Employee"
301
+ >
302
+ <UiSelectOption
303
+ v-for="user in users"
304
+ :key="user.id"
305
+ :value="user"
306
+ :label="user.name"
307
+ />
308
+ </UiSelect>
309
+
310
+ ai_notes:
311
+ do:
312
+ - Set equalsFn for object values in most cases.
313
+ - Use only UiSelectOption and UiSelectOptionGroup in the default slot.
314
+ - Read this profile together with UiPopper, UiPopperConnector, and UiPopperTarget.
315
+ avoid:
316
+ - Do not place arbitrary div wrappers inside the option tree.
317
+ - Do not choose UiSelect when free text input is the real need.
318
+ - Do not assume the dropdown lives in normal document flow next to the trigger.