refactor: migrate and consolidate UI templates to compile-time Askama component macros

This commit is contained in:
2026-05-30 12:28:47 +05:00
parent f42a5f05b2
commit 110fc61fa2
16 changed files with 697 additions and 598 deletions
+130
View File
@@ -0,0 +1,130 @@
# Detailed Project Architecture & Design System Reference Manual
This document provides a comprehensive technical overview of the **Stick** template, detailing its vertical structure, core dependencies, event delegation contracts, component reuse solutions, and our current implementation plan.
---
## 📁 1. Project Directory Layout & Vertical Architecture
Unlike traditional MVC applications that split code horizontally (e.g., separating all controllers, all models, and all views), Stick is organized by **vertical features (use-cases)**. Every business module contains its own Rust handler logic, database schemas, repository queries, and custom routing.
### Directory Mapping
```text
stick/
├── Cargo.toml # Rust dependency management
├── package.json # Node assets configuration (optional tooling)
├── src/
│ ├── main.rs # Core composition, shared state, and route merging
│ ├── common/ # Shared utilities & configurations
│ │ ├── config.rs # Configuration parsed from environment variables (.env)
│ │ ├── database.rs # MongoDB initialization and connections
│ │ └── errors.rs # AppError implementation wrapping custom responses
│ ├── auth/ # AUTH USE-CASE (Users, Passwords, Session cookies)
│ │ ├── extractors.rs # Native Axum extractors for authentication state
│ │ ├── handlers.rs # Login and registration endpoint handlers
│ │ ├── models.rs # User database schemas
│ │ └── repository.rs # MongoDB operations for authentication
│ ├── tasks/ # TASKS USE-CASE (CRUD tasks, dashboard view)
│ │ ├── handlers.rs
│ │ ├── models.rs
│ │ └── repository.rs
│ ├── developers/ # DEVELOPERS USE-CASE (HTMX-based assignee autocomplete query)
│ │ ├── handlers.rs
│ │ ├── models.rs
│ │ └── repository.rs
│ ├── main_view/ # STATIC VIEWS & GLOBAL ASSET ENDPOINTS
│ │ └── mod.rs # Serves index.html, static css, and static javascript files
│ ├── components/ # WIKI & INTERACTIVE DESIGN SYSTEM
│ │ ├── mod.rs # Wiki routing table
│ │ └── handlers.rs # Handlers serving reference pages
│ └── input.css # Tailwind CSS v4 custom theme mappings and custom scrollbars
├── static/ # Raw assets compiled/included in compilation
│ ├── tailwind.css # Output/input css rules
│ └── js/
│ ├── components.js # Main component event delegation system
│ └── combobox.js # HTMX-friendly autocomplete combobox scripts
└── templates/ # Raw HTML template layout files (Askama templates)
├── base.html # Global HTML layout wrapper (injects headers, navigation)
├── auth/ # Login / registration markup
├── tasks/ # Task management layouts
├── main_view/ # Landing page layout
└── components/ # Component Wiki pages (Buttons, Modals, Comboboxes, etc.)
```
### Route Composition
In [src/main.rs](file:///home/enciphered/Desktop/Code/stick/src/main.rs), routers from each vertical module are instantiated and merged using Axum's `.merge()` method:
```rust
let app = Router::new()
.merge(main_view::router())
.merge(components::router())
.merge(auth::router())
.merge(tasks::router())
.merge(developers::router())
.with_state(state);
```
---
## 🛠️ 2. Core Technical Dependencies
* **Web Server**: `axum = "0.8.9"` — Native asynchronous routing with type-safe extractor traits.
* **Database**: `mongodb = "3.7.0"` — Offical Rust driver, using `bson = "3.1.0"` with serde serialization.
* **Template Rendering**: `askama = "0.16.0"` — Compile-time type safety; views are compiled directly into the binary.
* **Styling Engine**: Tailwind CSS (v4) — Uses native CSS variables and `@import "tailwindcss"` rather than complex configuration JSONs.
* **Security & JWT**: `jsonwebtoken = "10.4.0"` (via `rust_crypto` backend) + `bcrypt = "0.19.1"` for password hashing. JWTs are stored in secure `HttpOnly` cookie wrappers.
---
## 🎨 3. JavaScript & HTML Event Delegation Contract
Rather than attaching individual event listeners to elements upon page load (which degrades performance and fails when elements are swapped dynamically via HTMX), Stick uses **document-level event delegation** via [static/js/components.js](file:///home/enciphered/Desktop/Code/stick/static/js/components.js) and [static/js/combobox.js](file:///home/enciphered/Desktop/Code/stick/static/js/combobox.js).
### Active Binding Attributes & Hooks
To make components function, developers must preserve specific HTML attributes and class structures that JavaScript expects:
| Component Type | JavaScript Trigger / Hook | Expected Target / Functional Structure |
| :--- | :--- | :--- |
| **Modal / Dialog** | `[data-modal-target="id"]` | `.modal-dialog` (wrapper), `.modal-backdrop`, `.modal-close` |
| **Sheets / Drawers** | `[data-sheet-target="id"]` | `.sheet-dialog` (wrapper), `.sheet-backdrop`, `.sheet-close` |
| **Custom Dropdowns** | `.dropdown-trigger` | `.dropdown-menu` (container), `.dropdown-content` |
| **Interactive Tabs**| `[data-tab-target="pane-id"]` | `[data-tab-group="group-name"]` on buttons & content wrappers |
| **Accordions** | `.accordion-trigger` | `.accordion-item` (container), `.accordion-content`, `.accordion-chevron` |
| **Custom Select** | `.select-trigger` | `.custom-select` (container), `.select-popover`, `.select-item`, `.select-value` |
| **Autocomplete Combobox**| `.combobox-input` | `.autocomplete-combobox` (container), `.combobox-results`, `.combobox-value` |
*Any customized styling classes (colors, borders, rounded corners) can be freely added or changed. However, the core class naming hierarchy listed above must remain intact to preserve interaction animations and keyboard controls.*
---
## 🧩 4. Proposed Scalability & Code Reuse Solutions
### Solution 1: Askama Macros (Selected Demo)
Consolidate UI components into a global macros registry template.
* *Pros*: Safe compilation (missing variables or typos are checked at build time), zero performance cost.
* *Cons*: Complex child structures (e.g. slots or dynamic SVG parameters) require passing strings/blocks, which can look verbose.
### Solution 2: CSS Component Classes
Define custom components in [src/input.css](file:///home/enciphered/Desktop/Code/stick/src/input.css) using Tailwind CSS v4's components layer (e.g. `@apply btn btn-primary`).
* *Pros*: Clear, descriptive markup syntax; easily consumable by pure front-end web developers.
* *Cons*: Partially moves styling definitions out of HTML files and back into stylesheet files.
### Solution 3: Rust Struct Components
Represent reusable buttons, grids, or select widgets as Rust structs that implement Askama's `Template` trait.
* *Pros*: Advanced data-driven structures and type constraints managed entirely in Rust code.
* *Cons*: Visual updates require recompiling Rust binaries, which limits swift CSS experimentation.
---
## 🚀 5. Action Plan: Askama Macros Implementation
We are implementing a demo showcasing Askama Macros in a new git branch:
1. **Branch Setup**: Create `demo/askama-macros`.
2. **Define Macros**: Create `templates/components/macros.html` to define reusable snippets for:
* **Button**: Primary, secondary, outline, destructive, status indicators.
* **Modal**: Accessibility markup, background overlays, closing controls.
* **Autocomplete Combobox**: Dynamic HTMX data queries and search hooks.
3. **Refactor Views**: Replace manual HTML blocks in [dashboard.html](file:///home/enciphered/Desktop/Code/stick/templates/tasks/dashboard.html) with:
```html
{% import "components/macros.html" as ui %}
{{ ui::button("Submit", "primary") }}
```