import React, {useContext, useState} from 'react'; import {ThemeContext} from '../contexts/contexts'; import { ActionInput, Button, Card, CardGroup, Confirm, Header, Icon, IconButton, Label, Loader, Loading, Message, Modal, Pagination, Panel, Placeholder, Progress, SearchBox, Select, Statistic, StatisticGroup, TabBar, tabClassName, Status, Table, TextInput, Textarea, Checkbox, ThemePicker, Toggle, Tooltip, toast, } from './ui'; import {semanticColorNames} from '../themes/mantine'; /* * A gallery of every component in the library, in the current theme. * * Reachable at /theme-sample and linked from Settings, so a user can see a theme * before committing to it. * * EVERY new component belongs here. It is how we review the design and how we * catch a component that only looks wrong in one of the four themes — which has * already happened more than once. */ const Section = ({label, children}) =>

{label}

{children}
; const Row = ({children}) =>
{children}
; export function ThemeSamplePage() { const {theme} = useContext(ThemeContext); const [confirmOpen, setConfirmOpen] = useState(false); const [comments, setComments] = useState(true); const [hotspot, setHotspot] = useState(true); const [dismissed, setDismissed] = useState(false); const [modalOpen, setModalOpen] = useState(false); const [realColors, setRealColors] = useState(false); const [search, setSearch] = useState(''); const [activeTab, setActiveTab] = useState('Videos'); const [page, setPage] = useState(3); return

Component gallery

Every component in the WROLPi interface library, rendered in the {theme} theme. Switch themes here or from the navigation bar.

The same picker the Settings page uses. The navigation bar has a compact version; both read the same list of themes.

{/* A real , so it goes through whatever filter the current theme applies — this is the only way to see the filter working without leaving the page. The unfiltered copy beside it opts out with `night-unfiltered`, so the two can be compared side by side. */} The WROLPi logo, filtered like any other media

Filtered

{/* Kept behind a click: an unfiltered image is a bright patch, and leaving one on screen in night mode would cost a user the dark adaptation they came here to protect. They can ask for it. */} {realColors ? The WROLPi logo, unfiltered : }

Real colors

Images, video, PDFs, embedded pages, and the map canvas cannot read theme tokens, so a monochrome theme remaps them with an SVG color matrix instead. Night filters to red unless you turn it off; amber tints to match only if you ask. Light and dark offer no filter, so both images look the same here.

Use the toggle in the theme picker above to see the difference. An element can opt out with night-unfiltered — that is what the right-hand copy does, which is why it is behind a click: an unfiltered image is a bright patch, and night mode should not spring one on you.

Page title (h1)
Section (h2)
With an icon and a divider (h3)
Subsection (h4)
Smallest (h5)

The level picks the size, so the type scale stays a scale: call sites choose a heading level for the document outline, never a font size.

setConfirmOpen(true)}/>

In night mode Delete drops its fill for a dashed red outline; dashed means destructive or failed, and nothing else uses it.

Indexing the media directory. This can take several minutes. Channel settings were written to config/channels.yaml. Downloads will resume tomorrow at 00:00. HTTP 403 from the remote server after 3 attempts. Retry, or check the URL. setDismissed(true)}> {dismissed ? 'Dismissed — it would be gone in the real interface.' : 'A nudge the user can clear. Only offer dismiss when clearing it is harmless.'}
{}}>URL {}}>Downloader Progress Status Size Actions youtube.com/watch?v=hT6Rkfahyg video complete 312 MiB youtube.com/watch?v=Zk91nq2rrE video downloading 198 MiB example.org/prepping/water-storage.html archive failed — wikipedia_en_all_maxi_2026-06.zim zim pending 104 GiB