Type component attributes with a covariant Attributes alias

Twin of the children fix: builders annotated ``attributes`` as
``list[HTMLAttribute] | None``, and ``list`` is invariant, so passing the
``list[tuple[str, str]]`` a caller naturally writes was a type error.

Add ``Attributes = Sequence[HTMLAttribute]`` (covariant) and use it for the
``attributes`` parameter of every builder. Locals that get appended/concatenated
stay a concrete ``list[HTMLAttribute]`` via the new ``as_attributes()``
normaliser, mirroring ``as_children()`` — builders call it once up front so
``attributes + [...]`` keeps working on a real list.

Pyright on common/components drops 45 → 42; the remaining errors are all
pre-existing and unrelated (django-stubs model access, the ``mark_safe``
``_Wrapped`` return type, and the separate ``FilterSelect`` options-list
invariance). Full suite green (443).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 18:20:57 +02:00
parent 7104605c06
commit 544da26a9d
3 changed files with 38 additions and 19 deletions
+3 -3
View File
@@ -22,7 +22,7 @@ from collections.abc import Callable, Iterable
from typing import TypedDict
from common.components.core import Element, HTMLAttribute, Media, Node
from common.components.core import Attributes, Element, HTMLAttribute, Media, Node
from common.components.primitives import Div, Input, Pill, Span, Template
# Both comboboxes are wired by search_select.js.
@@ -176,9 +176,9 @@ def _option_row(option: SearchSelectOption) -> Node:
def _combobox_shell(
*,
container_attributes: list[HTMLAttribute],
container_attributes: Attributes,
pills: Node,
search_attributes: list[HTMLAttribute],
search_attributes: Attributes,
options_children: list[Node],
always_visible: bool,
items_visible: int,