The bar will host more than just this button later — at minimum a search field, and eventually a sync indicator — so the action takes its place alongside the others rather than dominating the screen.
Del
The bar will host more than just this button later — at minimum a search field, and eventually a sync indicator — so the action takes its place alongside the others rather than dominating the screen.
Del
The entry-point button opens the box form when tapped.
Rb
The test pins down what “added” feels like end to end: the thumbnail appears in the list, the empty-state hint goes away.
Del
No name, no colour, no other field
Del
empty-state{text-align:center;padding:60px 20px;color:var(--muted)} .empty-state .emoji{font-size:3rem;margin-bottom:12px} .empty-state h1{font-size:1.4rem;margin:0 0 8px 0;color:var(--fg)} .empty-state p{font-size
Provide HTML example
Centering the block, muting the text colour, and pushing the emoji to font-size 3 buys that — at a glance it reads “this is what the app looks like when it’s empty”, not “the thing is still spinning.
Remove
The thing I most want to avoid
Bs
if(!this.visible) return '';
Isn't there a visibility stuff built-in?
Disappear the second I add anything” tells me what to compute: whether both tables are empty. Because the renderer runs on every store change, I don’t need any kind of show/hide gymnastics —
Remove
The test I want to pin first is the trivial one: open the app, see the hint. (clear_state, used here and in every later test, resets IndexedDB and localStorage between cases — defined in Playwright tests.)
Remove. The intro must simply be like: empty state at first
The first time I open the app on a fresh phone there’s nothing in the store yet, and an empty page would leave me wondering whether the thing failed to load. So I want a small landing message: an emoji big enough to read across the room, the app’s name, a single line saying “no boxes yet.” It should disappear the second I add anything, no matter what — a box or just an unassigned item.
Remove
import { createMergeableStore } from 'tinybase'; import { createIndexedDbPersister } from 'tinybase/persisters/persister-indexed-db'; import { createWsSynchronizer } from 'tinybase/synchronizers/synchronizer-ws-client'; import { html, LitElement } from 'lit'; const store = createMergeableStore(); const persister = createIndexedDbPersister(store, 'organiser'); const appRootEl = document.querySelector('app-root'); function renderApp(){ appRootEl?.requestUpdate(); } // Drain the IndexedDB replay before listening: an earlier listener // would fire renderApp once per replayed write. await persister.startAutoLoad(); store.addTablesListener(renderApp); renderApp(); await persister.startAutoSave(); // startAutoSave debounces — this parallel listener bumps a counter // on each completed write so the persistence test waits on a signal, // not on a delay. let _persistSeq = 0; store.addTablesListener(async () => { await persister.save(); document.body.setAttribute('data
Unclear what this does and what calls it
Dark theme, pinned to CSS custom properties so the feature chapters can reach for var(--muted) or var(--accent) by name. --bg #1b1d2e --card #262a40 --fg #e8e8f0 --muted #8a8ea5 --accent #f9a826 :root{ --bg:#1b1d2e; --card:#262a40; --fg:#e8e8f0; --muted:#8a8ea5; --accent:#f9a826; }
This is not used
Each field is defined by the feature chapter that owns it;
Replace by "they will be introduced later in the doc"
so a photo, because the labels I’ve been using are unreadable across the room
Remove
I’d rather take the language lock-in.
Invented, remove
small custom-element classes that read from properties the root passes down and dispatch events back
That does not scale well, but should ne enough for that use case
That’s the move.
remove
store sync in one package, no rendering-side datastore at
-
time, one source of truth
Add a "let's try"
Alpine drives from its reactive store; yjs (a CRDT library — a data structure that lets multiple devices edit concurrently and merge without losing writes) drives from its document; the bridge between them is where the bugs lived
Remove
The pattern is the same on all three: two reactivity engines competing for the same DOM.
Not for the dom, for the state
function installAppRootHandlers(root){ const on = (type, fn) => root.addEventListener(type, fn); on('open-box-form', () => openBoxForm()); on('open-item-form', e => openItemForm(e.detail || {})); on('open-catalog', () => setUI({catalogOpen: true})); on('close-catalog', () => setUI({catalogOpen: false})); on('close-form', () => closeForm()); on('submit-box', () => onBoxFormSubmit()); on('submit-item', () =>
Like ui, mist be disseminated ithe doc