Every component of the two core views as copy-paste HTML with documented .tp-* classes, all states enumerated, mapped to suggested Django partials with the HTMX seams marked. Companion: reference.css (the class contract) · index.html (the interactive kit) · app.js (business-logic spec). Roadmap: root Product Surface Plan.html.
priority_hub codebase:
tp- prefixed (same pattern as the app's .og-* layer); single-use inner elements are scoped descendants (.tp-row .nm). States are .is-* / .on / .active; .is-hover mirrors :hover for testing.reference.css → static/css/tax_prep.css (loads after the DaisyUI/PTR token layers, like og_dashboard.css); add the new app to input.css @source; npm run build:css.hx-* attrs below are the documented contract, per marketing_platform patterns): filter bar + quick tabs swap the list region #tp-list; row click loads Case Detail into the tab region #tp-tab-region with hx-push-url; star/flag/status writes hx-post and swap the smallest owning fragment (outerHTML on the row / table region); modals fetch as fragments (Phase 3).--space-* / --shadow-* / duration tokens. Buttons and fields are DaisyUI classes (btn / input / select / textarea / checkbox — previewed via daisy.css, supplied by the DaisyUI plugin in real builds); pills, empty state, filter bar and toast ship from package/product.css (v0.2). Each class's Phase-2 fate — collapse onto DaisyUI, move to the shared package layer, or stay app-custom — is mapped in §7._status_pill.html — context: label, groupclasses .tp-pill .tp-pill--{group}--case-{group}-bg/-fg in package/brand.css (shipped July 17)info group; the rule is gray = no action, red = negative action, amber = pending/waiting, blue = in-between, green = done. The working-25 grouping is a proposal — the wireframe only styled 10 of them (rest fell back to gray). E-001.7 reconciled best-judgment (July 17): the STATUS filter uses the finalized 17 (matches per-year statuses) and the Overall TP pill displays the working value mapped through WORKING_TO_FINAL (one re-mappable table in app.js / the templatetag; raw Logics value in the pill tooltip). The 25→17 mapping below needs business sign-off. the group → status map is one table in _status_pill.html's templatetag, so re-mapping is a one-line-per-status change._doc_dots.html · _scope_chips.html_filter_bar.htmlstatus list finalized-17 (E-001.7 reconciled July 17) — matches per-year statuseshtmx seam whole bar is a form: each control hx-gets the list view, hx-target="#tp-list", hx-include="closest .tp-filters"; search debounces keyup changed delay:300ms_quick_tabs.html — context: tabs (key, label, count, warn), active_keyhtmx seam hx-get the list with ?quick={key}, target #tp-liststates default · active · warn+active_group_header.html · _case_row.htmlhtmx seams row: hx-get Case Detail → hx-target="#tp-tab-region" + hx-push-url; star/flag: hx-post → hx-target="closest .tp-row" hx-swap="outerHTML"alpine checkbox multi-select is client state (x-model on a selection array)_empty_state.html — context: title, body, optional icon block)_doc_legend.html)_case_header.htmlnote Case Status is read-only from Logics; "Remind client" / "Request docs" are undefined (E-004.6/.7) — render disabled or behind a flag until spec'd_year_status_table.html (region #tp-year-table)htmx seams status select: hx-post on change → swap #tp-year-table; add-state select + add-year form: hx-post → same swapmodel per-year × return-type (personal/business) × jurisdiction (federal + per-state) — E-001.2/E-003.1.tp-ystat--{group})._doc_progress.html · _notes_card.htmlhtmx seams action buttons hx-post → swap the card body; note tabs hx-get the list; add-note hx-post hx-swap="beforeend" on the list + clear input_financial_card.html · _contact_attempts.html · _linked_systems.htmlnote IRS/State split source unconfirmed (E-005.9); attempts ring % is an inline style driven by the server valuecomponents/sidebar_nav.html · partials/case_tabs.htmlhtmx seam nav + tabs hx-get the view into #tp-tab-region with hx-push-url; open-tab list is server session state so tabs survive reloadstates nav: default · hover · active · with count — tab: pinned · active · closableforms.htmlstates default · error (.tp-fld.err) · read-only/locked| Block | Suggested partial | HTMX seam |
|---|---|---|
| Inbox view | tax_prep/inbox.html (extends the app base) | Full page; owns #tp-list + #tp-tab-region |
| Filter bar | partials/_filter_bar.html | Controls hx-get list view → #tp-list, hx-include siblings; search delay:300ms |
| Quick tabs | partials/_quick_tabs.html | hx-get ?quick={key} → #tp-list |
| Group + rows list | partials/_case_list.html (loops _group_header.html + _case_row.html) | The swap payload for every filter/tab change |
| Case row | partials/_case_row.html | Row hx-get detail → #tp-tab-region + hx-push-url; star/flag hx-post → closest .tp-row outerHTML; checkbox = Alpine |
| Status pill | partials/_status_pill.html | None (render-only); group map lives in one templatetag |
| Doc dots / scope chips / legend / empty state | _doc_dots.html · _scope_chips.html · _doc_legend.html · _empty_state.html | None (render-only) |
| Case Detail | tax_prep/case_detail.html — served as a fragment for #tp-tab-region, full page on direct URL (HX-Request header check) | Composes the cards below |
| Case header | partials/_case_header.html | Action buttons hx-post; undefined actions disabled (E-004.6/.7) |
| Year/status table | partials/_year_status_table.html | All writes hx-post → swap #tp-year-table |
| Docs & signatures | partials/_doc_progress.html | Buttons hx-post → swap card body |
| Financial / attempts / linked systems | _financial_card.html · _contact_attempts.html · _linked_systems.html | Render-only (data from Logics sync) |
| Notes | partials/_notes_card.html | Tabs hx-get → #tp-notes; add hx-post beforeend |
| Shell | components/header.html · components/sidebar_nav.html · partials/case_tabs.html | Nav/tabs hx-get → #tp-tab-region + hx-push-url; tab list in session |
| Modals (3 tracking forms) | §8 (forms.html): partials/_tracking_form.html · _handpull_form.html · _bk_form.html (+ _form_field.html, _bk_points_bar.html) | hx-get open → #tp-modal + showModal() · delayed inline validation · submit → close + toast + owning-region swap |
package/product.css (shared layer, v0.2) · 3) app-prefixed CSS only for the truly bespoke, tokens never hex. Target: ~30 surviving .tp-* classes.| .tp-* class(es) | Collapses onto (Phase 2) | Notes |
|---|---|---|
tp-btn + --primary/--ghost/--sm | DaisyUI btn btn-primary / btn-ghost / btn-sm | Drops the class entirely |
tp-inp · tp-ta · tp-fsel · tp-add-state | input / textarea / select (+ select-sm) | 2px borders + 4/4/8 radii from the theme; dashed add-state stays a thin modifier |
tp-chk · tp-chkbox · tp-chkline | checkbox checkbox-primary + label | Real <input type="checkbox"> — also fixes a11y |
tp-pill + 8 group modifiers | DaisyUI badge shape + --case-{group}-bg/-fg tokens | Moves to package/product.css — shared with any status-bearing surface |
tp-qtab · tp-ntab · tp-ptab | tabs / btn btn-xs patterns (per the app's division-filter tiles) | Pinned-tab pin icon stays custom |
tp-toggle · tp-segchoice · tp-seg-togs · tp-ytog · tp-optchip | btn group / join + btn-active | Selected-state colors from theme tokens |
tp-card (+ .ch/.cb/.note) · tp-filters | card / bg-base-100 border border-base-300 rounded-… utility pattern | Matches the app's existing card idiom |
| Modal shells (Phase 3 forms) | DaisyUI modal + <dialog> | As the app already does (.modal[open]) |
tp-msel · tp-chip · tp-fld error/hint states | Partly — badge chips + DaisyUI validator classes | Multi-select shell likely survives as .tp-msel |
tp-empty · toast · tp-legend | package/product.css (shared vocabulary) | The app hand-built its own (.og-empty-state, .og-toast) — converge, don't copy |
tp-row grid + states · tp-who/tp-debt/tp-fee/tp-upd/tp-docp | Stays .tp-* | Bespoke responsive case-row grid — no DaisyUI equivalent |
tp-yr-row · tp-juris-line(s) · tp-ret-head · tp-rl-tag · tp-ystat + tints | Stays .tp-* | Year × return-type × jurisdiction table — the product's core bespoke component |
tp-dot · tp-scope · tp-ro-badge · tp-ctype · tp-bk-badge | Stays — candidates for product.css if a second surface needs them | Tokens only, no hex, per budget rule 3 |
tp-ghead · tp-cd-* · tp-doc-row · tp-fin · tp-att · tp-ls-* · tp-note-* | Stays .tp-* (layout-only, thin) | Mostly flex/grid scaffolding around DaisyUI pieces |
Sibling specimen: forms.html — per-form field tables (name, type, required, conditional-on, error copy lifted verbatim from app.js), copy-paste modal markup on DaisyUI modal + native <dialog> (the §7 collapse, applied — the interactive kit now runs the same <dialog> shells, logic untouched), and the HTMX contract: open as fragment → #tp-modal + showModal(), delayed inline validation, submit → close + toast + owning-region swap (#tp-year-table / case row / transcripts card / bookkeeping card). Bookkeeping points recompute server-side — BK_PTS weights are sample values, backend-configured.