Requirements
This document captures what yew-nav-link is contractually expected to do
(functional requirements) and the constraints under which it does it
(non-functional requirements). Anything claimed here is exercised by the
test suite, the demo, or the CI pipeline.
1. Functional requirements
1.1 NavLink<R>
FR-NL-1. Render a yew-router Link<R> with the same target and child
content. The component is a wrapper, never a replacement.
FR-NL-2. Compute an active state by comparing the current route to the target on every render:
partial | Match condition |
|---|---|
false (default) | exact equality between current and to |
true | to.to_path() is a path-segment prefix of current.to_path() |
FR-NL-3. Apply two CSS classes to the rendered anchor:
- The base class — defaults to
"nav-link", overridable via theclassprop (&'static str). - The active class — defaults to
"active", overridable via theactive_classprop (&'static str). Only emitted when active per FR-NL-2.
FR-NL-4. When the user clicks the link, the browser history is updated
to to and the framework re-renders dependent hooks. Behaviour is delegated
to yew_router::Link; the wrapper does not intercept clicks.
1.2 nav_link() function
FR-FN-1. Return an Html value that contains a NavLink<R> whose
partial flag is derived from a Match argument:
Match::Exact → partial = false, Match::Partial → partial = true.
FR-FN-2. Accept the link text as &str; it is rendered as a single
text child.
1.3 Reactive hooks
FR-HK-1. use_route_info::<R>() -> Option<R> returns the currently
matched route, or None when no registered route matches.
FR-HK-2. use_is_active(route) and the use_is_exact_active(route)
alias return true iff the current route equals route.
FR-HK-3. use_is_partial_active(route) returns true iff
route.to_path() is a path-segment prefix of the current path.
FR-HK-4. use_navigation::<R>() -> Navigation<R> returns a value-type
struct exposing pre-built callbacks: push_callback, replace_callback,
go_callback, go_back, go_forward. Each callback is Callback<()>
(or Callback<i32> for go_callback) so consumers can adapt with
.reform(...) for onclick handlers.
FR-HK-5. use_query_params() -> HashMap<String, String> parses the
current URL’s query string into a flat map; reactive on every URL change.
FR-HK-6. use_breadcrumbs::<R>() -> Vec<BreadcrumbItem<R>> builds a
breadcrumb trail from the current path. The label of each item comes from a
BreadcrumbLabelProvider injected into the tree via
BreadcrumbLabelProviderContext. When no provider is present the path
itself is used as the label. The last item has is_active == true.
1.4 Components
The crate ships UI components that are render-only — they hold no business logic and accept all required state through props.
| Component | Role |
|---|---|
NavList | <ul> with sensible ARIA defaults |
NavItem | <li> |
NavDivider | <hr> |
NavHeader | section heading inside a list |
NavText | inert text inside a list |
NavBadge | inline pill, variant + optional pill=true |
NavIcon, NavLinkWithIcon | icon container + paired layout helper |
NavTabs, NavTab, NavTabPanel | tab strip; consumer drives active |
NavDropdown, NavDropdownItem, NavDropdownDivider | self-managed open/close menu |
Pagination, PageItem, PageLink | full pagination renderer + lower-level building blocks |
1.5 Errors
FR-ER-1. NavError is a #[non_exhaustive] pub enum. As of 0.10
it has three variants: RouteNotFound, InvalidRoute(String),
NavigationCancelled. It implements std::fmt::Display,
std::error::Error, Clone, PartialEq, Eq, and Debug. Future
minor releases may add new variants without bumping the major version;
consumer matches must include a _ => arm.
FR-ER-2. NavResult<T> is a public alias for Result<T, NavError>.
1.6 Utilities
FR-UT-1. is_absolute(path) returns true iff path starts with a
URL scheme (scheme://...).
FR-UT-2. join_paths(a, b) concatenates two path segments,
collapsing duplicate separators.
FR-UT-3. normalize_path(path) resolves . and .. segments without
escaping the root.
FR-UT-4. urlencoding_encode percent-encodes a string;
urlencoding_decode returns Option<String> (None on malformed input).
2. Non-functional requirements
2.1 Compatibility
| Requirement | Value |
|---|---|
| MSRV | Rust 1.95+, enforced by CI’s MSRV matrix on Linux/macOS/Windows |
| Edition | 2024 |
| Yew | 0.23+ |
| yew-router | 0.20+ |
no_std | Not supported. The Yew runtime requires std; this is a deliberate non-goal documented in CI’s no_std job. |
| Browser support | Whatever Yew CSR + wasm32-unknown-unknown supports |
2.2 Versioning
NFR-V-1. The crate adheres to Semantic Versioning 2.0.0 and to the
Cargo 0.x interpretation: while the major version is 0, every
breaking change increases the minor (0.x → 0.(x+1)); additive changes
increase the patch (0.x.y → 0.x.(y+1)).
NFR-V-2. Every release is tagged on main (vX.Y.Z), published to
crates.io, and published as a GitHub release whose body reproduces the
matching CHANGELOG.md section.
NFR-V-3. CHANGELOG.md follows
Keep a Changelog and is written
ahead of the merge that tags the release.
2.3 Quality gates
NFR-Q-1. Every commit on main was produced by a PR whose CI passed
the following gates:
cargo +nightly fmt --all -- --checkcargo clippy --workspace --all-targets --all-features -- -D warnings -W clippy::pedantic -W clippy::nurserycargo nextest run --all-features --profile cicargo test --doc --all-featurescargo llvm-covupload to Codecovcargo deny checkcargo auditreuse lintactionlinttrunk build --releaseagainstexample/- Lighthouse CI thresholds (perf 0.85, a11y 0.9, best-practices 0.9, SEO 0.9)
NFR-Q-2. No unsafe blocks in src/ or tests/.
NFR-Q-3. No unwrap() or expect() outside #[cfg(test)] in the
public crate — error handling uses ?, Option::map_or_else,
Option::unwrap_or, etc.
NFR-Q-4. Every public item carries a /// doc comment and a doctest
where it makes sense.
2.4 Accessibility
NFR-A-1. Library components emit ARIA attributes appropriate to their
role: NavList carries role="navigation" + aria-label, NavTabs set
role="tab" / aria-selected / aria-controls, etc.
NFR-A-2. The bundled demo (example/) honours prefers-color-scheme: dark, prefers-reduced-motion: reduce, ships a skip-to-content link, and
maintains a visible :focus-visible ring across the whole UI.
2.5 Security
NFR-S-1. Every supply-chain advisory surfaced by cargo audit or
cargo deny check blocks the release pipeline. Two unmaintained warnings
on transitive proc-macro-error (pulled through yew-macro) are
acknowledged in CI as informational; they do not have a known exploit path.
NFR-S-2. Disclosure policy lives in SECURITY.md.
2.6 Licensing
NFR-L-1. The crate is MIT-licensed. Every Rust, SCSS, HTML, YAML,
and Markdown file carries SPDX-FileCopyrightText and
SPDX-License-Identifier headers, and reuse lint passes in CI.
3. Out-of-scope
- Server-side rendering — Yew SSR is supported by yew-router, but
yew-nav-link’s active-state computation has only been tested under CSR. - A custom router — the crate is a companion to
yew-router, not a replacement. - Internationalisation of breadcrumb labels — provided by the consumer via
BreadcrumbLabelProvider. - Telemetry / analytics integration.