mirror of
https://github.com/mattermost/mattermost.git
synced 2026-09-01 15:00:08 +08:00
Match ranked 'Add values…' affordance to select/multiselect
The ranked values cell now mirrors the select/multiselect CreatableSelect cell for consistency across field types: - Tab commits a pending value (keeping focus in the input for the next one) when it's non-empty and not a duplicate, matching the select cell; a blank/duplicate input lets Tab move focus away normally. - The empty-state placeholder uses the shared 'Add values… (required)' text and matches react-select's placeholder color (full-opacity neutral50) and 10px content inset, so size, color, and left alignment line up with the select cell. - The placeholder is hidden once values exist, mirroring react-select. - The chips well gets the same hover/focus background tint and text cursor as the select control. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+29
-3
@@ -8,8 +8,21 @@
|
||||
min-height: 40px;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
|
||||
// 10px matches react-select's content inset on the select/multiselect
|
||||
// cell (valueContainer's 8px padding + the 2px margin on each chip and on
|
||||
// the placeholder), so chips and the "Add values…" input line up across
|
||||
// field types.
|
||||
padding: 8px 10px;
|
||||
cursor: text;
|
||||
gap: 6px;
|
||||
|
||||
// Match the select/multiselect values cell's hover/focus affordance so the
|
||||
// empty state (and the populated cell) read identically across field types.
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
background: rgba(var(--button-bg-rgb), 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
// The chip is a pill split into three flush regions: the rank badge fills the
|
||||
@@ -82,15 +95,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Match the select/multiselect CreatableSelect's "Add values…" input exactly:
|
||||
// react-select sets `fontSize: inherit` on its input (so it follows the cell
|
||||
// size rather than the larger UA default a bare <input> would use). No left
|
||||
// padding here — the chips container's 10px inset already aligns this with the
|
||||
// react-select placeholder/value position.
|
||||
.user-property-rank-values__add-input {
|
||||
min-width: 120px;
|
||||
height: 24px;
|
||||
flex: 1;
|
||||
padding: 0 4px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--center-channel-color);
|
||||
font-size: 12px;
|
||||
font-size: inherit;
|
||||
|
||||
// react-select renders its placeholder as a plain <div> at full opacity in
|
||||
// theme.colors.neutral50; a native <input>'s ::placeholder is dimmed by the
|
||||
// browser's default opacity, so reset it to 1 to match the grey exactly.
|
||||
&::placeholder {
|
||||
color: hsl(0, 0%, 50%);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
|
||||
+15
-5
@@ -107,11 +107,18 @@ const UserPropertyRankValues = ({field, updateField, autoFocus}: Props) => {
|
||||
}, [trimmedQuery, isDuplicate, options, setOptions]);
|
||||
|
||||
const handleQueryKeyDown = useCallback((event: KeyboardEvent<HTMLInputElement>) => {
|
||||
// Commit the pending value on Enter, and on Tab when there's a valid value
|
||||
// to add — keeping focus in the input for the next value, mirroring the
|
||||
// select/multiselect values cell. A blank or duplicate input lets Tab move
|
||||
// focus away normally.
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
addValue();
|
||||
} else if (event.key === 'Tab' && trimmedQuery && !isDuplicate) {
|
||||
event.preventDefault();
|
||||
addValue();
|
||||
}
|
||||
}, [addValue]);
|
||||
}, [addValue, trimmedQuery, isDuplicate]);
|
||||
|
||||
return (
|
||||
<div className='user-property-rank-values'>
|
||||
@@ -136,10 +143,13 @@ const UserPropertyRankValues = ({field, updateField, autoFocus}: Props) => {
|
||||
className='user-property-rank-values__add-input'
|
||||
value={query}
|
||||
maxLength={Constants.MAX_CUSTOM_ATTRIBUTE_LENGTH}
|
||||
placeholder={formatMessage({
|
||||
id: 'admin.system_properties.user_properties.rank_values.add_placeholder',
|
||||
defaultMessage: 'Add value…',
|
||||
})}
|
||||
|
||||
// Mirror react-select: the placeholder only shows in the
|
||||
// empty state, not once values have been added.
|
||||
placeholder={ascOptions.length === 0 ? formatMessage({
|
||||
id: 'admin.system_properties.user_properties.table.values.placeholder',
|
||||
defaultMessage: 'Add values… (required)',
|
||||
}) : undefined}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
onKeyDown={handleQueryKeyDown}
|
||||
onBlur={addValue}
|
||||
|
||||
Reference in New Issue
Block a user