Commit Graph
784 Commits
Author SHA1 Message Date
G30 e58245d5b4 fix: place model editor capability checkboxes directly before their labels (#27788) 2026-08-11 11:13:04 -06:00
Timothy Jaeryang BaekandClassic298 c8f8fa451a a11y
Co-Authored-By: Classic298 <27028174+Classic298@users.noreply.github.com>
2026-08-11 01:25:20 -06:00
Timothy Jaeryang Baek 385d08bea5 refac 2026-08-10 19:42:05 -06:00
Timothy Jaeryang Baek d4461bd6f3 refac 2026-08-10 18:52:18 -06:00
Timothy Jaeryang Baek 8fbfd14a8b refac 2026-08-10 01:38:32 -06:00
Timothy Jaeryang Baek 810378c0b8 refac 2026-07-27 19:39:36 -04:00
Timothy Jaeryang Baek 75e54bf46b refac 2026-07-27 01:21:00 -04:00
Classic298 7e96c53a20 feat: multiselect valve input type with static or dynamic options (#26884)
Adds a multiselect input type for Valves and UserValves so plugin authors can let users pick multiple values from static or runtime-resolved options instead of maintaining comma-separated text fields with hardcoded allowed-value lists in the description.

ENABLED_ITEMS: list[str] = Field(
    default=["foo"],
    json_schema_extra={"input": {"type": "multiselect", "options": "get_item_options"}},
)

@classmethod
def get_item_options(cls):
    return [{"value": "foo", "label": "Foo"}, {"value": "bar", "label": "Bar"}]

Options accept the same shapes as the existing select input: either a static list (strings or {value, label} dicts) or a classmethod name resolved at request time (including __user__ context for UserValves). No backend changes are needed because resolve_valves_schema_options already resolves options independently of the input type.

The new MultiSelect component follows the existing Select portal dropdown pattern and renders checkbox rows that stay open while toggling, with the selected labels shown in the trigger. Values bind as a real string array end to end: the array-to-comma-string conversions in the chat controls valves panel and the valves modal are skipped for multiselect fields, so the stored valve is a native list[str] validated by Pydantic.

Requested in #26848.
2026-07-27 01:11:38 -04:00
Timothy Jaeryang Baek 6732852ce6 refac 2026-07-27 01:05:52 -04:00
Timothy Jaeryang Baek 57e60423b9 refac 2026-07-27 00:27:38 -04:00
Timothy Jaeryang Baek 20647bd2d5 chore: format 2026-07-27 00:12:47 -04:00
G30 771540f3de feat: sortable title and updated at columns on the knowledge workspace page (#27457) 2026-07-26 18:19:31 -04:00
Timothy Jaeryang Baek 1f0dc90abe refac 2026-07-26 18:06:03 -04:00
Classic298 2725ae6d6c fix: expose Checkbox as a checkbox with a name and state (WCAG 4.1.2) (#27494)
On latest `dev`, `common/Checkbox.svelte` renders a `<button type="button">` containing only `aria-hidden="true"` SVGs. It has no `role`, no `aria-checked` and no accessible name, and the component has no `$$restProps` spread, so a caller cannot supply a name either.

Assistive technology announces every one of these as an unnamed "button". A screen reader user cannot tell that the control is a checkbox, cannot tell whether it is on or off, and cannot tell what it toggles. The visible label is always an unassociated sibling element, for example `Capabilities.svelte` puts it in a preceding `<div>` with no `id`, and `Groups/Users.svelte` puts it in a different table cell from the checkbox.

Breaks WCAG 4.1.2 Name, Role, Value (Level A) on all three counts at once.

Fix: expose `role="checkbox"` and `aria-checked` on the control, add an `ariaLabel` prop, and pass the label text that is already in scope at each call site. `aria-checked` mirrors the component's existing icon logic exactly, so the indeterminate dash reports `mixed` rather than `false`. The `ariaLabel={ariaLabel || undefined}` shape matches the sibling `common/Switch.svelte`. Every label expression is the same one that renders the visible text next to the checkbox, so the accessible name always matches what is on screen.

Three call sites are deliberately left out of this PR, because they nest `Checkbox` inside another `<button>`, which is invalid HTML and independently broken:

- `workspace/Knowledge/KnowledgeBase.svelte` — the Checkbox's `on:change` sets `includeContent = true` and then the same click bubbles to the outer button, which flips it back with `includeContent = !includeContent`. Clicking the checkbox square is a no-op today, only the text label works. Giving it a confident name would advertise a control that does nothing.
- `workspace/common/MemberSelector.svelte` (two instances) — the inner Checkbox has no `on:change` at all and only works because its click bubbles to the row button. Naming it would create two focusable controls per row with the same name.

Both need the nesting resolved first, so that the row button carries the checkbox semantics. That is a behavioural fix and belongs in its own PR.

Severity: Serious. Affects model capabilities, default features, builtin tools, tool/filter/skill/action selectors and group membership.

### Contributor License Agreement

<!--
🚨 DO NOT DELETE THE TEXT BELOW 🚨
Keep the "Contributor License Agreement" confirmation text intact.
Deleting it will trigger the CLA-Bot to INVALIDATE your PR.

Your PR will NOT be reviewed or merged until you check the box below confirming that you have read and agree to the terms of the CLA.
-->

- [x] By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms.

> [!NOTE]
> Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in.
2026-07-26 17:37:06 -04:00
Timothy Jaeryang Baek 212eec408c refac 2026-07-24 01:44:30 -04:00
Timothy Jaeryang Baek ce831f7b85 refac 2026-07-24 01:25:52 -04:00
Timothy Jaeryang Baek 8cbb7f765c refac 2026-07-24 00:47:12 -04:00
Timothy Jaeryang Baek 381ababeba refac 2026-07-24 00:40:21 -04:00
Timothy Jaeryang Baek 49abfbdd15 refac 2026-07-23 13:18:04 -04:00
Timothy Jaeryang Baek 48625e657f refac 2026-07-23 03:54:19 -04:00
Timothy Jaeryang Baek 1428a4ddce refac 2026-07-20 21:44:12 -04:00
Timothy Jaeryang Baek f192657dc9 refac 2026-07-17 06:35:24 -04:00
Timothy Jaeryang Baek 9281adc564 refac 2026-07-17 06:34:17 -04:00
Timothy Jaeryang Baek fd07e3a8e3 refac 2026-07-17 06:30:04 -04:00
Timothy Jaeryang Baek ff49217206 refac 2026-07-17 06:22:15 -04:00
Timothy Jaeryang Baek 1bf05ebc7d refac 2026-07-17 06:06:23 -04:00
Timothy Jaeryang Baek cda5bdb9d4 refac 2026-07-17 05:51:39 -04:00
Timothy Jaeryang Baek ea2e3d0afc refac 2026-07-17 05:48:41 -04:00
Timothy Jaeryang Baek 437c06c479 refac 2026-07-17 05:46:09 -04:00
Timothy Jaeryang Baek d027a32ed1 refac 2026-07-17 05:40:40 -04:00
Timothy Jaeryang Baek 21e180182a refac 2026-07-17 05:34:00 -04:00
Timothy Jaeryang Baek d0bea60581 refac 2026-07-17 05:31:32 -04:00
Timothy Jaeryang Baek 421da67446 refac 2026-07-17 05:15:09 -04:00
Timothy Jaeryang Baek 5424ac5891 refac 2026-07-17 05:09:29 -04:00
Timothy Jaeryang Baek 3316ba76aa refac 2026-07-17 04:54:44 -04:00
Timothy Jaeryang Baek e5e2cd7876 refac 2026-07-17 04:48:21 -04:00
Timothy Jaeryang Baek a213355785 refac 2026-07-17 04:09:33 -04:00
Timothy Jaeryang Baek c55e373b99 refac 2026-07-16 00:58:34 -04:00
Timothy Jaeryang Baek 933ab1e1cd refac 2026-07-15 18:03:36 -04:00
Timothy Jaeryang Baek db934a3b4f refac 2026-07-15 16:51:08 -04:00
Timothy Jaeryang Baek 3ce3c52936 refac 2026-07-15 05:17:41 -04:00
Timothy Jaeryang Baek a3908f1281 refac 2026-07-15 04:55:38 -04:00
Timothy Jaeryang Baek 343eb1d659 refac 2026-07-15 04:52:06 -04:00
Timothy Jaeryang Baek 1760b073c7 refac 2026-07-15 04:39:37 -04:00
Timothy Jaeryang Baek 91277726cd refac 2026-07-15 04:35:52 -04:00
Timothy Jaeryang Baek 59fc600b52 refac 2026-07-15 04:33:06 -04:00
Timothy Jaeryang Baek 9499587c33 refac 2026-07-15 04:25:51 -04:00
Timothy Jaeryang Baek 2018546a7b refac 2026-07-15 04:18:56 -04:00
Timothy Jaeryang Baek f8350360df refac 2026-07-15 04:12:11 -04:00
Timothy Jaeryang Baek 05e3f71317 refac 2026-07-15 04:01:23 -04:00