fix(ui): a picture that fails to load shows the card's own frame, then retries
A bare <img> sent a Referer that Google's image CDNs refuse and had no retry and no fallback, so a Home shelf card showed the browser's broken-image mark. ui/RemoteImage gathers what Avatar, the channel banner and the download rows had each hand-rolled: no Referer, up to three retries past the browser's negative cache, the caller's fallback (by default the card's empty frame) instead of the broken mark, the failure remembered by URL. Every picture now goes through it; a lint rule refuses a bare <img>.
This commit is contained in:
@@ -18,6 +18,18 @@ describe("a native select", () => {
|
||||
});
|
||||
});
|
||||
|
||||
// A bare <img> left the broken-image mark on a card whose picture failed (ui/RemoteImage's header).
|
||||
describe("a bare img", () => {
|
||||
it("is refused; ui/RemoteImage is not", async () => {
|
||||
const lint = async (source: string) =>
|
||||
(
|
||||
await eslint.lintText(source, { filePath: "src/components/__probe.tsx" })
|
||||
)[0]?.messages.filter((m) => m.message.startsWith("No bare <img>")).length;
|
||||
expect(await lint('export const A = () => <img src="x" alt="" />;\n')).toBe(1);
|
||||
expect(await lint('export const B = () => <RemoteImage src="x" alt="" />;\n')).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
// `enabled:hover:` is blind to a focused FocusSafeButton (aria-disabled, not the native attribute; `act:` is not),
|
||||
// which then lit up on hover as if a click would work.
|
||||
describe("a hover gated on `enabled:` alone", () => {
|
||||
|
||||
@@ -756,6 +756,10 @@
|
||||
"message": "No native <select>: use ui/SegmentedToggle for a short fixed set, ui/FilterSelect for a longer one or a user's own list.",
|
||||
"selector": "JSXOpeningElement[name.name='select']"
|
||||
},
|
||||
{
|
||||
"message": "No bare <img>: use ui/RemoteImage — no Referer, a retry past the browser's negative cache, and a fallback instead of the broken-image mark.",
|
||||
"selector": "JSXOpeningElement[name.name='img']"
|
||||
},
|
||||
{
|
||||
"message": "px-frozen font size doesn't scale with --font-scale: use text-2xs/text-3xs or text-[Nrem], not text-[Npx].",
|
||||
"selector": "Literal[value=/text-\\[[\\d.]+px\\]/]"
|
||||
|
||||
Reference in New Issue
Block a user