* docs(web): refresh screenshots for v0.15 sidebar settings UI Recapture product and settings gallery shots against the searchable sidebar settings dialog, keeping the previous asset filenames and exact pixel dimensions with wallpaper padding around each window. * fix(web): correct screenshot semantics after adversarial review Keep the existing transcription and tray images because the replacements did not show their claimed flows. Populate the Logs dialog and unlock Advanced settings so those refreshed images demonstrate the features described by the gallery. * fix(web): retake screenshots as square crops with uniform padding Resize settings dialogs to a near 1:1 window, capture with ~28px wallpaper padding on all sides, open About from the tray menu, and skip redoing the awkward XFCE system-tray asset. * docs(web): retake v0.15 screenshots on GNOME (light/dark) Window-only captures from Ubuntu/GNOME at 960x720 for settings and logs, with matching dark variants under screenshots/dark/. Replace the old Shortcuts shot with Performance to match the sidebar. * feat(web): theme-aware light/dark screenshot switching Serve paired GNOME captures and swap them with the site theme via dark:hidden / hidden dark:block. Replace Shortcuts gallery entry with Performance to match the v0.15 sidebar. * docs(web): refresh screenshots after About moves into Settings Rebase onto main brought the in-app update checker: About is now a sidebar settings page. Recapture light/dark GNOME panels at 960x720 and update gallery copy/metadata accordingly. * docs: use single screenshot source for README and website Point README images at web/public/screenshots so product shots live in one place, drop the unused resources/screenshots tree (including the old demo video and about-updates set), and replace the missing shortcuts shot with performance. * docs(web): refresh light/dark screenshots and product grid Replace the screenshot set with fresh captures for both themes, and lay out the three Product shots in a single equal-height row. * fix(web): align screenshot metadata, sizes, and theme loading Restore dictation copy for the 00-transcription asset, set width/height from the recaptured PNGs, preload only the light next/image twin when priority is set, and eager-load both theme variants by default so dark mode does not flash empty on first toggle. * fix(web): show full settings screenshot without crop Use object-contain so the homepage settings dialog fits the frame instead of object-cover clipping the sidebar.
115 lines
2.7 KiB
TypeScript
115 lines
2.7 KiB
TypeScript
"use client";
|
|
|
|
import Image, { type ImageProps } from "next/image";
|
|
import React from "react";
|
|
|
|
type CommonProps = {
|
|
src: string;
|
|
srcDark: string;
|
|
alt: string;
|
|
className?: string;
|
|
};
|
|
|
|
/**
|
|
* Renders light and dark screenshot variants. Visibility follows the
|
|
* `dark` class on `<html>` from next-themes, so the active theme's image
|
|
* shows without a hydration flash.
|
|
*
|
|
* Default loading is "eager" for both siblings so the inactive theme is
|
|
* already fetched when the user toggles. Callers can still pass "lazy"
|
|
* for below-the-fold galleries (both siblings share the value).
|
|
*/
|
|
export function ThemeScreenshotImg({
|
|
src,
|
|
srcDark,
|
|
alt,
|
|
width,
|
|
height,
|
|
className = "",
|
|
loading = "eager",
|
|
}: CommonProps & {
|
|
width: number;
|
|
height: number;
|
|
loading?: "lazy" | "eager";
|
|
}) {
|
|
const shared = `${className}`.trim();
|
|
return (
|
|
<>
|
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
<img
|
|
src={src}
|
|
alt={alt}
|
|
width={width}
|
|
height={height}
|
|
className={`${shared} dark:hidden`.trim()}
|
|
loading={loading}
|
|
decoding="async"
|
|
/>
|
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
<img
|
|
src={srcDark}
|
|
alt={alt}
|
|
width={width}
|
|
height={height}
|
|
className={`${shared} hidden dark:block`.trim()}
|
|
loading={loading}
|
|
decoding="async"
|
|
/>
|
|
</>
|
|
);
|
|
}
|
|
|
|
type ThemeScreenshotNextProps = CommonProps &
|
|
Omit<ImageProps, "src" | "alt"> & {
|
|
src: string;
|
|
srcDark: string;
|
|
alt: string;
|
|
};
|
|
|
|
/**
|
|
* next/image twin for homepage embeds that already use Image.
|
|
*
|
|
* `priority` only applies to the light (default) image so Next preloads a
|
|
* single LCP candidate. The dark twin uses eager loading so theme toggles
|
|
* still have the asset ready without a second priority preload.
|
|
*/
|
|
export function ThemeScreenshotImage({
|
|
src,
|
|
srcDark,
|
|
alt,
|
|
className = "",
|
|
priority,
|
|
loading,
|
|
...rest
|
|
}: ThemeScreenshotNextProps) {
|
|
const shared = `${className}`.trim();
|
|
const darkLoading = priority ? "eager" : loading;
|
|
return (
|
|
<>
|
|
<Image
|
|
src={src}
|
|
alt={alt}
|
|
className={`${shared} dark:hidden`.trim()}
|
|
priority={priority}
|
|
loading={priority ? undefined : loading}
|
|
{...rest}
|
|
/>
|
|
<Image
|
|
src={srcDark}
|
|
alt={alt}
|
|
className={`${shared} hidden dark:block`.trim()}
|
|
loading={darkLoading}
|
|
{...rest}
|
|
/>
|
|
</>
|
|
);
|
|
}
|
|
|
|
/** Derive `/screenshots/dark/<file>` from a light `/screenshots/<file>` path. */
|
|
export function darkScreenshotPath(src: string): string {
|
|
if (src.includes("/dark/")) {
|
|
return src;
|
|
}
|
|
return src.replace("/screenshots/", "/screenshots/dark/");
|
|
}
|