feat(accounts): add precise service filtering
Add an explicit service selector to the account creation dialog while keeping the text field focused on access types such as API and web login. Preserve the result area dimensions during filtering and allow Enter to choose the first visible account type. Cover filtering, keyboard selection, translations, and stable list geometry with focused regression tests.
This commit is contained in:
@@ -23,7 +23,6 @@ import {
|
||||
getAccountTableMinWidth,
|
||||
getSettingsSelectNavigationIndex,
|
||||
resizeAccountTableColumn,
|
||||
type AccountAddFilter,
|
||||
type AccountAddOption,
|
||||
type AccountRowViewModel,
|
||||
type AccountTableColumnId,
|
||||
@@ -176,10 +175,11 @@ export interface AccountDialogField {
|
||||
secretBusy?: boolean;
|
||||
}
|
||||
|
||||
export interface AccountAddDialogModel {
|
||||
open: boolean;
|
||||
query: string;
|
||||
filter: AccountAddFilter;
|
||||
export interface AccountAddDialogModel {
|
||||
open: boolean;
|
||||
query: string;
|
||||
serviceFilter: string;
|
||||
serviceFilters: readonly string[];
|
||||
options: readonly AccountAddOption[];
|
||||
selectedOptionId: string | null;
|
||||
fields: readonly AccountDialogField[];
|
||||
@@ -187,9 +187,9 @@ export interface AccountAddDialogModel {
|
||||
busy: boolean;
|
||||
}
|
||||
|
||||
export interface AccountAddDialogActions {
|
||||
onQueryChange: (value: string) => void;
|
||||
onFilterChange: (filter: AccountAddFilter) => void;
|
||||
export interface AccountAddDialogActions {
|
||||
onQueryChange: (value: string) => void;
|
||||
onServiceFilterChange: (service: string) => void;
|
||||
onOptionSelect: (optionId: string) => void;
|
||||
onFieldChange: (fieldId: string, value: string) => void;
|
||||
onClose: () => void;
|
||||
@@ -667,16 +667,34 @@ export function AccountAddDialog({
|
||||
>
|
||||
<div className="settings-account-picker-selector">
|
||||
<span>Dienst / Zugangstyp</span>
|
||||
<input
|
||||
aria-controls={model.options.length === 0 ? "settings-account-picker-empty" : "settings-account-picker-results"}
|
||||
aria-describedby={model.options.length === 0 ? "settings-account-picker-empty" : undefined}
|
||||
aria-label="Dienst oder Zugangstyp suchen"
|
||||
className="settings-control"
|
||||
onChange={(event) => actions.onQueryChange(event.target.value)}
|
||||
placeholder="Dienst oder Zugangstyp suchen"
|
||||
type="search"
|
||||
value={model.query}
|
||||
/>
|
||||
<div className="settings-account-picker-controls">
|
||||
<input
|
||||
aria-controls={model.options.length === 0 ? "settings-account-picker-empty" : "settings-account-picker-results"}
|
||||
aria-describedby={model.options.length === 0 ? "settings-account-picker-empty" : undefined}
|
||||
aria-label="Dienst oder Zugangstyp suchen"
|
||||
className="settings-control"
|
||||
onChange={(event) => actions.onQueryChange(event.target.value)}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key !== "Enter" || !model.options[0]) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
actions.onOptionSelect(model.options[0].id);
|
||||
}}
|
||||
placeholder="Zugangstyp suchen, z. B. API oder Web"
|
||||
type="search"
|
||||
value={model.query}
|
||||
/>
|
||||
<select
|
||||
aria-label="Dienst filtern"
|
||||
className="settings-control settings-account-picker-service-filter"
|
||||
onChange={(event) => actions.onServiceFilterChange(event.target.value)}
|
||||
value={model.serviceFilter}
|
||||
>
|
||||
<option value="all">Alle Dienste</option>
|
||||
{model.serviceFilters.map((service) => <option key={service} value={service}>{service}</option>)}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-account-picker-table">
|
||||
<div aria-hidden="true" className="settings-account-picker-header">
|
||||
|
||||
@@ -936,6 +936,16 @@
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.settings-account-picker-controls {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 190px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.settings-account-picker-service-filter {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.settings-account-picker-table {
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--ui-border);
|
||||
@@ -968,13 +978,14 @@
|
||||
}
|
||||
|
||||
.settings-account-picker-list {
|
||||
max-height: 190px;
|
||||
height: 190px;
|
||||
overflow-y: auto;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
.settings-account-picker-empty {
|
||||
display: grid;
|
||||
min-height: 72px;
|
||||
height: 190px;
|
||||
padding: 16px;
|
||||
place-items: center;
|
||||
color: var(--ui-text-muted);
|
||||
@@ -1159,6 +1170,7 @@
|
||||
}
|
||||
|
||||
.settings-theme-options,
|
||||
.settings-account-picker-controls,
|
||||
.settings-account-picker-header,
|
||||
.settings-account-picker-row {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
|
||||
Reference in New Issue
Block a user