Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.0.0-alpha.3] - 2026-10-10

### Added
- Accessibility: Duct aims to meet WCAG 2.2 AA, and publishes a conformance report (VPAT®) at duct.tensflare.com/legal/accessibility. Text and field borders meet the contrast minimums; focus is always visible; there's a Skip to content link; the documents list is a table for screen readers; the number of results is announced. In a document, ↑ and ↓ select a paragraph and Enter adds it to a notebook, and ⌘⇧N / Ctrl+Shift+N adds any selection. Everything reflows at 400% zoom. The / shortcut can be turned off (Settings › Features › Keyboard), and the mascot stops moving within 5 seconds. `npm run a11y` checks every main screen with axe-core, and CI runs it.
- Search results are grouped by document. A PDF that matches on several pages is one result with its best passage, links to the other pages ("Also on p. 2, p. 7") and its other passages a click away; the heading counts documents and passages. Quick search shows one row per document.
- Open shows the document inside Duct, on its own, with your notebooks beside it; **Open in app** hands it to the program it belongs to. Closing one of two documents in the workspace leaves the other full width, and **One / Side by side / Stacked** switches between them.
- Selected text can go to any notebook: the pop-up says **Add to "<notebook>"**, and its menu lists every notebook you can add to, or starts a new one named after the document.
Expand Down
2 changes: 2 additions & 0 deletions assets/ui/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,8 @@ function renderResults() {
const docs = state.cards.length
$('#resultsTitle').textContent = !results.length ? 'No results for “' + state.query + '”'
: plural(docs, 'document') + (results.length > docs ? ' · ' + plural(results.length, 'passage') : '') + ' for “' + state.query + '”'
// Screen readers hear the count when a search finishes (WCAG 4.1.3).
$('#resultsStatus').textContent = $('#resultsTitle').textContent
$('#results').innerHTML = state.cards.map((idx, card) => {
const r = results[idx[0]]
const c = r.chunk
Expand Down
1 change: 1 addition & 0 deletions assets/ui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ <h1 id="homeTitle"></h1>
<section id="viewResults" class="view" hidden aria-label="Results">
<div class="results-head">
<h2 id="resultsTitle"></h2>
<p id="resultsStatus" class="sr-only" role="status" aria-live="polite"></p>
<div class="scope-chips" id="scopeChips"></div>
<div class="results-tools">
<button class="btn btn-sm" data-action="show-collected" id="collectedBtn" hidden>Collected <span class="count" data-bind="collectedCount">0</span></button>
Expand Down
33 changes: 33 additions & 0 deletions docs/accessibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Accessibility

Duct aims to meet WCAG 2.2 at level AA. The conformance report (VPAT® 2.5, WCAG edition) is published at
https://duct.tensflare.com/legal/accessibility/ and must stay true: when a change affects a criterion, update it
(`duct-site/src/accessibility.mjs`).

## Automated

`npm run build && npm run a11y` (`scripts/a11y-electron.cjs`) starts Duct with a small sample library, opens every main
screen in Chromium (Electron) and runs axe-core with the WCAG 2.2 A and AA rules. Any violation fails it, and CI runs it
on macOS for every pull request. Add a screen to the list in that script when you add one to the app.

## By hand, before a release

axe-core can't judge these, so check them when the related screens change:

- **Keyboard only:** search, open a result, step through matches (Enter, Shift+Enter), switch layouts, close a pane,
and add a quote: Tab to the document, ↑ ↓ to select a paragraph, Enter. ⌘⇧N / Ctrl+Shift+N adds any selection,
⌘⇧M / Ctrl+Shift+M opens the notebook menu.
- **Focus** is always visible, and dialogs give focus back when they close.
- **Reflow:** at 400% zoom in a 1280-pixel window (320 CSS pixels), nothing scrolls sideways except wide tables.
- **Text spacing:** with line height 1.5, letter spacing 0.12em, word spacing 0.16em and paragraph spacing 2em,
nothing is clipped.
- **Contrast:** new colours meet 4.5:1 for text and 3:1 for field borders on every panel they sit on
(`--muted` and `--field-border` in `assets/ui/app.css` are the floors).
- **Motion:** animations stop within 5 seconds and don't play with reduced motion.
- **Status messages** use a live region (`role="status"`).

## Known gaps

- Selecting part of a paragraph needs a pointer or a screen reader's own selection (WCAG 2.1.1, partially supported).
- Resizing two documents to an exact size without dragging needs the arrow keys (2.5.7, partially supported).
- Not yet tested with people who use screen readers every day; planned before 1.0.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@docfide/duct",
"version": "1.0.0-alpha.2",
"version": "1.0.0-alpha.3",
"description": "Document intelligence pipeline — extract, chunk, embed, and search any document format",
"type": "module",
"bin": {
Expand Down
Loading