diff --git a/CHANGELOG.md b/CHANGELOG.md index f6bb05d..5f00a47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ content repos pin the tag they run (see the end of this file). - A state can grant a group: `grants: ` beside its `event`, so an approval that means membership does not also need somebody to remember to invite them afterwards. The lint requires the forms that fill such a bucket to collect a required name and email, because by the time a desk presses approve there is nobody left to ask. - A state can be moved by a clock: `after: { days, to }`, swept hourly, measured from the record's last move (`src/deadlines.rs`). A deadline may only do what a person could have done - `after.to` is held to the same declared edge as a desk button - and the move fires the same mail and publishes the same event, stamped `deadline`. - Documentation moved out of the README into `docs/`: architecture, content reference, state machines, access, operations. +- A page says nothing until it has something to say. The Suspense fallback on a question was the whole served page - no header, no wordmark - so the first and only thing a visitor or a crawler read was the word "loading…", which is true and is not about them. It now holds the space and stays quiet, with `aria-busy` for a reader that would otherwise find an empty document. +- Gone: the `gitea_org_repos` resource kind, which no site ever named. `gitea_starred` and `gitea_releases` stay. ## 0.4.0 (2026-09-24) diff --git a/docs/content-reference.md b/docs/content-reference.md index eb0c35c..f935070 100644 --- a/docs/content-reference.md +++ b/docs/content-reference.md @@ -210,7 +210,7 @@ reads is never a client-supplied parameter. - { from: complete, to: on_hearing, label: Send it out } ``` -`source.kind` is one of `kv`, `gitea_starred`, `gitea_org_repos`, +`source.kind` is one of `kv`, `gitea_starred`, `gitea_releases`, `url`. A spec with neither `public: true` nor `requires_group` is diff --git a/src/app.rs b/src/app.rs index ad48d02..5d5b5ab 100644 --- a/src/app.rs +++ b/src/app.rs @@ -244,12 +244,16 @@ fn QuestionPage() -> impl IntoView { let site = expect_context::>>(); view! { + // Nothing is written here on purpose. This fallback is the + // whole served page until the question resolves - no header, + // no wordmark - so any word in it is the first and only thing + // a visitor, or a crawler, reads about the site. It used to + // say "loading…", which is true and is not about them. The + // space is held so the page does not jump when the words + // arrive, and `aria-busy` says what is happening to anyone + // whose reader would otherwise find an empty document. -

"loading…"

- - } + view! {
} }> {move || { // Both read unconditionally (not nested inside the match @@ -1620,7 +1624,7 @@ fn ResourceFeature( view! {
- "loading…"

}> +

}> {move || { let feature_name = feature_name.clone(); let transitions = transitions.clone(); @@ -1877,7 +1881,7 @@ fn SelectField( view! {
- "loading…"

}> +

}> {move || { let id_field = id_field.clone(); data.get() diff --git a/src/content/mod.rs b/src/content/mod.rs index fc3e489..75ba36c 100644 --- a/src/content/mod.rs +++ b/src/content/mod.rs @@ -446,7 +446,6 @@ pub struct ResourceSpec { pub enum ResourceSource { Kv { bucket: String }, GiteaStarred { username: String }, - GiteaOrgRepos { org: String }, /// A repo's releases - fetched with `GITEA_API_TOKEN`, so it works /// for private repos too (shape the link with jq: a private /// release's html_url 404s for anonymous visitors, so map it to @@ -466,7 +465,6 @@ impl ResourceSpec { match &self.source { ResourceSource::Kv { bucket } => Some(bucket), ResourceSource::GiteaStarred { .. } - | ResourceSource::GiteaOrgRepos { .. } | ResourceSource::GiteaReleases { .. } | ResourceSource::Url { .. } => None, } diff --git a/src/resource.rs b/src/resource.rs index 6be697a..f34eb21 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -13,7 +13,7 @@ use leptos::prelude::*; /// `public: true` nor `requires_group` set is unreachable, not "open" /// by omission. `params` are the requesting form's current field /// values (if any) - forwarded as query parameters to a live external -/// fetch (`GiteaStarred`/`GiteaOrgRepos`/`Url`), the mechanism behind +/// fetch (`GiteaStarred`/`GiteaReleases`/`Url`), the mechanism behind /// "a resource parameterized by other form fields"; a `Kv` resource /// ignores them entirely, same as today. #[server(endpoint = "get_resource")] @@ -295,9 +295,6 @@ async fn fetch_resource_value( ResourceSource::GiteaStarred { username } => { fetch_gitea_json(state, &format!("/api/v1/users/{username}/starred"), params).await? } - ResourceSource::GiteaOrgRepos { org } => { - fetch_gitea_json(state, &format!("/api/v1/orgs/{org}/repos"), params).await? - } ResourceSource::GiteaReleases { owner, repo } => { fetch_gitea_json(state, &format!("/api/v1/repos/{owner}/{repo}/releases"), params) .await? diff --git a/style/main.css b/style/main.css index 799fda3..91734e2 100644 --- a/style/main.css +++ b/style/main.css @@ -1227,3 +1227,10 @@ textarea:focus { font-size: 0.9em; color: var(--ink-dim); } + +/* A loading slot holds its line's worth of space and says nothing. + The words that belong here have not arrived yet, and "loading…" is + not one of them. */ +.resource-loading { + min-height: 1.4em; +}