Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
8992ff2
Reject oversized data-URI base64 before allocating
thedancingdeveloper Oct 26, 2026
353b693
Fix slider painting and a11y from the pre-input value.
thedancingdeveloper Oct 26, 2026
20baec4
fix: keep slider geometry finite on extreme ranges
thedancingdeveloper Oct 26, 2026
91a3052
fix(combobox): freeform Enter commits an arrow-key selection
thedancingdeveloper Oct 26, 2026
560a2e2
Name comboboxes from their label or the enclosing Field.
thedancingdeveloper Oct 26, 2026
604d0ff
Decouple dialog action ids from display labels.
thedancingdeveloper Oct 26, 2026
361d981
Slider sizes come from theme tokens, and disabled paint uses disabled…
thedancingdeveloper Oct 26, 2026
8e3691b
Rename DialogKind::NonModal to Dismissible
thedancingdeveloper Oct 26, 2026
1f6ecc1
combobox: borrow options and cache the filter
thedancingdeveloper Oct 26, 2026
a0a022e
Stop re-running CI on push to main
thedancingdeveloper Oct 26, 2026
65a4ea9
Move #148 and #151 changelog notes into fragments and record #152
thedancingdeveloper Oct 26, 2026
d795dcd
fix: invalidate combobox slice filter cache when options change
thedancingdeveloper Oct 26, 2026
69ec69d
Fix docs drift and mark the hosted gallery unavailable.
thedancingdeveloper Oct 26, 2026
5b00b44
Test slider theme paint and decoder bounds
thedancingdeveloper Oct 26, 2026
16a34e9
Make PR CI scoping dependency-aware (gh-159)
thedancingdeveloper Oct 26, 2026
dff63e2
Make crate publishing resumable, guarded and licence-checked.
thedancingdeveloper Oct 26, 2026
ca4f9c7
ci: icon drift check and cargo-deny advisories
thedancingdeveloper Oct 26, 2026
97fea08
Add per-feature downstream build fixtures (minimal, wasm, MSRV).
thedancingdeveloper Oct 26, 2026
13f1b2b
Meet WCAG contrast on recorded exception pairs
thedancingdeveloper Oct 26, 2026
608542e
Enforce the gallery wasm size budget and add large-view benches.
thedancingdeveloper Oct 26, 2026
55bb3a0
Fix review blockers on the gallery batch: changelog fragment, toolcha…
thedancingdeveloper Oct 26, 2026
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
226 changes: 184 additions & 42 deletions .github/workflows/ci.yml

Large diffs are not rendered by default.

17 changes: 8 additions & 9 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,16 @@ jobs:
needs: gates
if: github.event_name == 'workflow_dispatch' && inputs.publish_crates && startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
environment: crates-io
concurrency:
group: crates-io-publish
cancel-in-progress: false
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
# Dependency order. crates.io indexes each crate before the next one resolves it; cargo
# publish waits for that by default.
- run: cargo publish -p fluent2-tokens
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: cargo publish -p fluent2-icons
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
- run: cargo publish -p fluent2-egui
- uses: EmbarkStudios/cargo-deny-action@3c6349835b2b7b196a839186cb8b78e02f7b5f25 # v2
# scripts/publish-crates.sh checks the tag, a clean tree, licences, and
# skips a crate whose version is already on crates.io.
- run: scripts/publish-crates.sh --publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module layout, the component API, theming, testing and gates.
1. Find the item in Vogt (index: `docs/BACKLOG.md`) and read it fully. It names the files to create or change, the upstream references
(pinned URLs), the acceptance criteria and the commands to run.
2. Branch `wi-<number>-<short-slug>` from `main`, or from the branch the item says it stacks on.
3. Touch only the files the item lists, plus `CHANGELOG.md`. If you need to touch more, or need
3. Touch only the files the item lists, plus a fragment in `changelog.d/` (see [`changelog.d/README.md`](changelog.d/README.md) and [`docs/ci.md`](docs/ci.md)). Do not edit `CHANGELOG.md`; the release PR folds fragments in. If you need to touch more, or need
a design choice the item and `docs/ARCHITECTURE.md` don't settle, **stop and ask on the work
item**. Do not guess.
4. Run the gates in `docs/ARCHITECTURE.md` until they pass.
Expand Down
82 changes: 82 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
resolver = "3"
members = ["crates/*", "xtask"]
members = ["crates/*", "xtask", "fixtures/*"]

[workspace.package]
version = "0.2.0"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ the pieces desktop productivity apps need: title bar, quick access toolbar, ribb
backstage/File view, command bar, status bar, data grid and tree view. It runs natively on
Windows and Linux, and on the web through wasm.

**Live gallery:** https://thedancingdeveloper.github.io/fluent2-egui/
**Hosted gallery:** unavailable. GitHub Pages is not enabled on this repository, so there is no live site. Run the gallery locally with `cargo run -p gallery`. The wasm build in `.github/workflows/pages.yml` still runs; its deploy step is quarantined until Pages is turned on (see [`docs/ci.md`](docs/ci.md)).

**Status: 0.2.0.** Milestones:

Expand Down Expand Up @@ -169,7 +169,6 @@ What the crate offers, by module, mapped to Fluent 2. Rows are sorted by type na

| Fluent 2 | status |
|---|---|
| Accordion | WI-1937 |
| Toolbar, Rating, InfoLabel, Image, Select, SwatchPicker, Carousel, TeachingPopover | not planned yet |

## Crates
Expand All @@ -185,6 +184,7 @@ What the crate offers, by module, mapped to Fluent 2. Rows are sorted by type na
| fluent2-egui | egui |
|---|---|
| 0.1.x | 0.36 |
| 0.2.x | 0.36 |

## CI

Expand Down
2 changes: 2 additions & 0 deletions changelog.d/gh-147-dialog-action-ids.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### Changed
- Dialog actions take a stable id and a display text (`DialogActions::primary(id, text)` and `secondary`). `CloseReason::Button` carries that id, and the button's widget id is derived from it, so two actions may share a label and a translated label still closes as the same action. This is a breaking change: call sites that passed only a label now pass an id as well, and `CloseReason` is no longer `Copy` (gh:TheDancingDeveloper-org/fluent2-egui#147).
2 changes: 2 additions & 0 deletions changelog.d/gh-148-dialog-dismissible.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### Changed
- Dialogs are always modal. `DialogKind` only chooses what dismisses the surface: `Modal` closes on a backdrop click and on Escape, `Dismissible` on Escape only, `Alert` on neither. `DialogKind::NonModal` remains as a deprecated alias of `Dismissible`; it never let background input through (gh:TheDancingDeveloper-org/fluent2-egui#148).
2 changes: 2 additions & 0 deletions changelog.d/gh-150-contrast.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### Changed
- Light and dark theme strokes, status borders and the dark primary fill now meet WCAG 2.2 contrast (3:1 non-text, 4.5:1 text) instead of keeping Fluent colours that failed those pairs (issue #150).
2 changes: 2 additions & 0 deletions changelog.d/gh-151-slider-tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### Changed
- Slider rail, thumb and inner-dot sizes come from `Theme.slider` (`SliderMetrics`). A disabled slider paints the disabled alias colours for the rail, fill and thumb instead of the resting brand colours (issue #151).
5 changes: 5 additions & 0 deletions changelog.d/gh-152-combobox-borrowed-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### Changed
- `Combobox<'a, T = &'a str>` gains a generic parameter. Options are borrowed for `'a` and are not copied into the widget. `ComboboxOptions`, `SliceOptions` and `ModelCombobox` are new, and `filter_probe` counts real filter passes for tests (gh:TheDancingDeveloper-org/fluent2-egui#152).

### Fixed
- Combobox filter cache for a plain slice (`Combobox::new`) was keyed only on the query, so a caller that rebuilt the option slice while the popup stayed open reused stale indexes and could panic. The cache now fingerprints the slice, and a cached index past the list is dropped. Closed popups still do not filter (gh:TheDancingDeveloper-org/fluent2-egui#152).
7 changes: 7 additions & 0 deletions changelog.d/gh-153-wasm-budget.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### Changed

- The gallery wasm size budget is enforced. `gallery-wasm` runs `scripts/wasm-size-check.sh` against `ci/wasm-budget.txt` (gzip and brotli, each 4,500,000 bytes) and uploads the size report. Raise the budget in that file when a change needs the room (gh:TheDancingDeveloper-org/fluent2-egui#153).

### Added

- `cargo bench -p fluent2-egui --bench large_views` prints frame time for a 10,000-row list, a 10,000-row data grid and a combobox of 10,000 options. It is not a required check (gh:TheDancingDeveloper-org/fluent2-egui#153).
2 changes: 2 additions & 0 deletions changelog.d/gh-154-feature-fixtures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### Added
- Downstream build fixtures check fluent2-egui with default features off, each optional feature on its own, a wasm consumer, and the declared MSRV (gh:TheDancingDeveloper-org/fluent2-egui#154).
3 changes: 3 additions & 0 deletions changelog.d/gh-163-docs-drift.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Fixed

- Docs now match the changelog-fragment rule, the Dialog `show` signature, Field parent naming, and the README: Accordion is listed only as shipped, the egui table includes 0.2, and the hosted gallery is marked unavailable because GitHub Pages is not enabled.
6 changes: 6 additions & 0 deletions ci/wasm-budget.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Gallery wasm compressed-size budget (issue #153).
# scripts/wasm-size-check.sh fails when a measured size is over its line.
# Raise a number here in the same change that grows the wasm, and say why in
# docs/wasm-size.md. Bytes, not megabytes.
gzip 4500000
brotli 4500000
7 changes: 7 additions & 0 deletions crates/fluent2-egui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,15 @@ zbus = { version = "5", optional = true, default-features = false, features = ["

[dev-dependencies]
egui_kittest = "0.36"
# Property tests for numeric and parser boundaries. Dev-only; not a published dependency.
proptest = { version = "1", default-features = false, features = ["std"] }

# Text layout needs a font: without egui's default fonts every galley is empty and has no size,
# so selection tests (tests/text_selection.rs) could not drag across glyphs.
egui = { workspace = true, features = ["default_fonts"] }
# Round-trips the serde state in tests (the `serde` feature).
serde_json = "1"

[[bench]]
name = "large_views"
harness = false
87 changes: 87 additions & 0 deletions crates/fluent2-egui/benches/large_views.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//! Frame time for large data views (issue #153).
//!
//! Not a required CI check. From the workspace root:
//!
//! ```sh
//! cargo bench -p fluent2-egui --bench large_views
//! ```
//!
//! Each case paints a 10 000-row view for 60 frames in a fixed-size harness and prints the
//! wall time per frame. The first frame is not timed: it pays for font setup and the first
//! layout. The numbers are a record, not a gate. A few percent either way between machines
//! is expected. Allocation counts are not measured here: the library forbids `unsafe`, and a
//! counting allocator needs it.

use std::cell::RefCell;
use std::time::Instant;

use egui::Vec2;
use egui_kittest::Harness;
use fluent2_egui::Combobox;
use fluent2_egui::data::data_grid::{Column, DataGrid, DataGridState};
use fluent2_egui::data::list::{List, ListState};
use fluent2_egui::{Theme, install};

const ROWS: usize = 10_000;
const FRAMES: u32 = 60;

fn theme(ui: &mut egui::Ui) {
install(ui.ctx(), &Theme::light(fluent2_tokens::FLUENT));
}

fn bench(name: &str, mut step: impl FnMut()) {
step();
let start = Instant::now();
for _ in 0..FRAMES {
step();
}
let per_frame = start.elapsed() / FRAMES;
println!("{name}: {per_frame:?}/frame over {FRAMES} frames ({ROWS} rows)");
}

fn main() {
let options: Vec<String> = (0..ROWS).map(|i| format!("Option {i}")).collect();

let list_state = RefCell::new(ListState::default());
let mut list = Harness::builder()
.with_size(Vec2::new(480.0, 640.0))
.build_ui(move |ui| {
theme(ui);
let mut state = list_state.borrow_mut();
List::new("bench-list", ROWS)
.label("Bench list")
.show(ui, &mut state, |cell, ui| {
ui.label(format!("Row {}", cell.row));
});
});

let grid_state = RefCell::new(DataGridState::default());
let mut grid = Harness::builder()
.with_size(Vec2::new(640.0, 480.0))
.build_ui(move |ui| {
theme(ui);
let columns = [
Column::new("name", "Name"),
Column::new("value", "Value"),
];
let mut state = grid_state.borrow_mut();
DataGrid::new("bench-grid", &columns, ROWS)
.label("Bench grid")
.show(ui, &mut state, |cell, ui| {
ui.label(format!("{} {}", cell.column, cell.row));
});
});

let text = RefCell::new(String::new());
let mut combo = Harness::builder()
.with_size(Vec2::new(320.0, 480.0))
.build_ui(move |ui| {
theme(ui);
let mut value = text.borrow_mut();
ui.add(Combobox::new("bench-combo", &mut value, options.as_slice()).label("Bench"));
});

bench("list-10k", || list.step());
bench("data-grid-10k", || grid.step());
bench("combobox-10k", || combo.step());
}
Loading
Loading