0006 — String props use AttrValue
- Status: accepted
- Date: 2026-07-11
- Supersedes: 0001
Context
ADR 0001 fixed NavLink’s class / active_class as &'static str,
trading runtime composition away for zero-allocation literals. The same
type then spread by imitation to every string-ish prop in the crate:
id, text, toggle_text, href, variant, role, aria_label.
Two things changed the balance:
- The zero-cost argument no longer discriminates. Yew’s
AttrValueis a two-variant handle:AttrValue::Static(&'static str)— the exact same pointer ADR 0001 optimized for — orRc<str>for runtime strings.html!converts string literals intoAttrValue::Staticwith no allocation, so the 99% literal case costs the same as before. Yew’s own documentation recommendsAttrValueoverString/&strfor props. - The restriction turned out to bite in practice.
PageLink’shref: Option<&'static str>makes a pagination link’s URL impossible to build at runtime —format!("/page/{n}")cannot become&'static strwithout leaking. What was a stylistic trade for class slots is a functional hole for URL slots.
Decision
All string-valued props take AttrValue (Option<AttrValue> when
optional). Defaults use AttrValue::Static, keeping the literal path
allocation-free. Class-list props that benefit from composition and
deduplication stay Classes, as before.
Consequences
Positive
- Runtime values work everywhere they should — most importantly
PageLink::href. - Props match the idiom the Yew book teaches, so consumers coming from other Yew code find no surprises.
- Cloning props stays cheap:
AttrValueclones are a pointer copy (Static) or anRcrefcount bump.
Negative
- The type-level guarantee that a class name is a compile-time constant is gone; a consumer can now funnel a runtime string into a class slot. The escaping behaviour of the DOM layer still prevents HTML injection.
- One-time semver break: struct-literal constructions of props must wrap
literals in
AttrValue::Static(inhtml!nothing changes).
Cost to reverse
Moderate and symmetric to ADR 0001’s estimate: signature changes across public props, one-line fixes per call site.