Examples · Panelith 0.1.0 · plain HTML edition; the interactive edition has search and live examples
Examples
On this page 6 sections
What has been built with the framework, in rough order of size. A Show button opens the thing in this process, beside this page; Open ↗ runs a separate app in a new tab.
Hello#
The smallest thing that uses every surface of the shell: a brand, three kinds (a sub-tabbed text buffer, a markdown About, a key-value System pane with a refresh command), two commands, one list with facets and a status mark. examples/hello.py, 137 lines.
class SystemInfo(Pane):
kind = "sysinfo"
label = "System"
glyph = "gear"
family = "assessment"
widget = "keyvalue"
tip = "Facts about the machine running Python"
def initial_state(self, ctx):
return widgets.keyvalue(
{
"Python": platform.python_version(),
"Platform": platform.platform(),
"Now": dt.datetime.now().isoformat(timespec="seconds"),
}
)
@event("refresh")
def refresh(self, ctx, payload):
return a.set_state(ctx.cid, self.initial_state(ctx))
The Tour#
One pane per widget, the sample that runs at lineshanley.com/panelith: a Welcome page that opens the Boggle board beside itself (as a tab on a phone), the Playground, a word table fed from the same rows as the drawer, a Scorer form writing into an output pane, and a Server pane pushed every five seconds. examples/tour/, 388 lines.
Super Boggle#
A 5×5 word hunt in two layouts from one game core: a board with trace rules, a live peek while the finger is down, a browser-side judge with fingerprinted solutions, a countdown that ends the round, and a score pane rendered as a thin strip or a full tab. All Python; the JavaScript plugin it replaced is gone. It is the Board inside the Tour. examples/boggle/, 394 lines and a word list.
class Board(Pane):
kind = "board"
label = "Board"
glyph = "grid"
widget = "blocks"
tip = "A grid with a trace gesture and a headerless child below"
children = [Child("strip", placement="below", size=0.25)]
def children_for(self, ctx):
# A phone has no room for a split: the strip becomes a second tab.
return [Child("strip", placement="tab")] if ctx.narrow else self.children
def initial_state(self, ctx):
return {"last": None, "count": 0}
def view(self, state):
last = state.get("last")
msg = b.message(last.upper(), "traced", tone="ok", key=last + str(state["count"])) if last else b.message(hint="Drag across three or more letters")
return b.view(b.grid(BOARD, 3, trace=b.trace_rules(event="trace", adjacency=8, min_cells=3), message=msg, height=200))
@event("trace")
def trace(self, ctx, payload):
word = "".join(BOARD[i] for i in payload.get("path") or []).lower()
patch = {"last": word, "count": ctx.pane.state.get("count", 0) + 1}
out = [a.patch_state(ctx.cid, **patch)]
for child in ctx.children_of(ctx.cid, "strip"):
out.append(a.patch_state(child.cid, **patch))
return out
Starboard#
A local mock-interview coach built on Panelith: it listens to an answer (Whisper), has a local model judge it against a rubric (Ollama), speaks the next question (Piper), and tracks progress across sessions. Nothing leaves the machine. Private repository.
Math, You#
The dashboard Panelith was extracted from: a LeetCode-style trainer for scientific Python with a code editor, a math pad, problems in a drawer, and tethered output panes. Its canvas, command bar, hotkeys and drawer are the shell you are looking at. It runs at lineshanley.com/mathyou.