porting to the use of penguinui
This commit is contained in:
@@ -50,9 +50,15 @@ from the build. If the build ever balloons, check that exclusion is intact.
|
||||
|
||||
---
|
||||
|
||||
## 1. Navbar
|
||||
## 1. Navbar — PENDING
|
||||
**Penguin UI: `navbar/`**
|
||||
|
||||
> **Priority: MEDIUM** | ~143 lines across2 sites.
|
||||
> Penguin match: `navbar/default-navbar.html` — provides mobile-responsive structure,
|
||||
> hamburger animation, and link treatment that would replace our hand-rolled `<nav>`.
|
||||
> **Watch out:** tight integration needed for cart badge, settings dropdown partial,
|
||||
> language switcher, and Alpine mobile toggle — don't lose any of those.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
| 1 | `assets/views/base.html:63-191` | Full site navbar: brand, desktop nav links, cart icon+badge, settings dropdown, mobile hamburger → mobile panel | ~130 lines |
|
||||
@@ -117,8 +123,19 @@ from the build. If the build ever balloons, check that exclusion is intact.
|
||||
|
||||
---
|
||||
|
||||
## 5. Country / Phone Combobox
|
||||
**Penguin UI: `text-input/` + custom dropdown list**
|
||||
## 5. Country / Phone Combobox — ⛔ WON'T PORT (conscious deviation)
|
||||
**Penguin UI: `combobox/phone-number-input-with-country-code-dropdown.html`**
|
||||
|
||||
> **Decision 2026-06-18:** keep our lightweight hand-rolled comboboxes; do NOT
|
||||
> port the Penguin one. The Penguin combobox depends on the **Alpine Focus
|
||||
> plugin** (`x-trap`, `$focus.wrap().next()`) which this build does not bundle
|
||||
> (same reason the settings dropdown & category accordion deviate), ships a
|
||||
> 240-country `allOptions` list + `flagcdn.com` remote flag images, and a search
|
||||
> field — far heavier than our deliberate 9-prefix / 6-country editable inputs.
|
||||
> Our versions already use the Penguin design tokens (`bg-surface`, `border-outline`,
|
||||
> `focus:outline-primary`) and emoji flags, so they look on-brand. Net: porting
|
||||
> would add a JS dependency and external image loads for negative UX value.
|
||||
> Revisit only if we adopt the Alpine Focus plugin project-wide.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
@@ -149,37 +166,38 @@ from the build. If the build ever balloons, check that exclusion is intact.
|
||||
|
||||
---
|
||||
|
||||
## 7. Product Image Gallery
|
||||
**Penguin UI: `carousel/` (3 variants)**
|
||||
## 7. Product Image Gallery — ✅ DONE
|
||||
**Penguin UI: `carousel/default-carousel.html`**
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
| 12 | `assets/views/shop/show.html:8-26` | Image gallery with main image + thumbnail strip, Alpine `x-data="{ active: 0 }"` | ~19 lines |
|
||||
|
||||
**Details:**
|
||||
- Main image: `x-show="active === {{ loop.index0 }}"` with `object-cover`
|
||||
- Thumbnail buttons: border changes to indicate active state
|
||||
- No transition/animation between images — just x-show toggling
|
||||
- Exact upstream mirror at `penguinui-components/carousel/default-carousel.html` (reference only)
|
||||
- Adapted at use-site in `assets/views/shop/show.html`: added Penguin's overlay
|
||||
prev/next arrow buttons (`bg-surface/40` rounded, verbatim chevron SVGs) and
|
||||
`x-transition.opacity.duration.300ms` fade between images. Added `prev()`/`next()`
|
||||
with wraparound to the gallery `x-data`; arrows + transitions only render when
|
||||
`images | length > 1`.
|
||||
- Deviations: kept our **product thumbnail strip** (more useful than carousel
|
||||
dot indicators for a product page) and our **0-based `active`** index (Penguin
|
||||
uses 1-based `currentSlideIndex`); main images switched to `absolute inset-0`
|
||||
so the fade cross-dissolves inside the `aspect-square` frame. New i18n keys
|
||||
`gallery-prev`/`gallery-next` (sk + en) for the arrow `aria-label`s.
|
||||
|
||||
---
|
||||
|
||||
## 8. Radio-Button Groups
|
||||
**Penguin UI: radio (part of form inputs)**
|
||||
## 8. Radio-Button Groups — ✅ DONE
|
||||
**Penguin UI: `radio/radio-with-container.html`**
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
| 13 | `assets/views/shop/checkout.html:133-165` | Carrier selection radio group (each option shows name + price) | ~33 lines |
|
||||
| 14 | `assets/views/shop/checkout.html:167-180` | Payment method radio group (COD + bank transfer) | ~14 lines |
|
||||
|
||||
**Details for #13:**
|
||||
- `{% for m in shipping_methods %}` loop
|
||||
- Each `<label>` is a styled card with `has-[:checked]:border-primary` border highlight
|
||||
- Radio input triggers `@change` to update Alpine state (carrier, carrierPrice, requiresPoint)
|
||||
- Pickup-point sub-panel shown via `x-show="requiresPoint"`
|
||||
|
||||
**Details for #14:**
|
||||
- Two hardcoded radio options: COD and bank_transfer
|
||||
- `x-model="paymentMethod"` binding
|
||||
- Exact upstream mirror at `penguinui-components/radio/radio-with-container.html` (reference only)
|
||||
- New `ui::radio(name, value, id, checked, attrs, extra)` macro in `macros/ui.html`
|
||||
emits **only** the Penguin custom radio-dot `<input>` (verbatim `appearance-none`
|
||||
+ `before:` dot + `checked:bg-primary`). Callers keep their own card-style
|
||||
`<label>` wrapper — we kept our `has-[:checked]:border-primary` card highlight,
|
||||
which is richer than Penguin's plain `bg-surface-alt` container.
|
||||
- Adopted at `shop/checkout.html`: both **payment** radios (`ui::radio` with
|
||||
`attrs='required x-model="paymentMethod"'`). The **carrier** radio (in the
|
||||
`{% for m in shipping_methods %}` loop) keeps the same Penguin dot class **inline**
|
||||
because its `@change="carrier='{{ m.code }}'; …"` mixes nested single+double
|
||||
quotes that can't pass through a Tera macro arg (same convention as the cart
|
||||
qty input). Native `text-primary` radios are gone.
|
||||
|
||||
---
|
||||
|
||||
@@ -229,8 +247,13 @@ from the build. If the build ever balloons, check that exclusion is intact.
|
||||
|
||||
---
|
||||
|
||||
## 14. Table
|
||||
**Penguin UI: `table/` (7 variants)**
|
||||
## 14. Table — PENDING
|
||||
**Penguin UI: `table/` (5 variants)**
|
||||
|
||||
> **Priority: HIGH** | ~196 lines across5 instances.
|
||||
> The same class structure is copy-pasted5 times. Penguin match:
|
||||
> `table/default-table.html` for basic tables, `table-with-action.html` for
|
||||
> row actions. Consider a `ui::table_header()` + `ui::table_row()` macro.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
@@ -324,8 +347,14 @@ This is copy-pasted 5 times.
|
||||
|
||||
---
|
||||
|
||||
## 18. Toggle / Switch
|
||||
**Penguin UI: `toggle/` (2 variants)**
|
||||
## 18. Toggle / Switch — LOW PRIORITY (de-duplication, not replacement)
|
||||
**Penguin UI: `toggle/` (3 variants)**
|
||||
|
||||
> **Priority: LOW** | ~36 lines,100% duplicated between `base.html` and `admin/base.html`.
|
||||
> This is JavaScript theme-switching logic (`applyTheme`, `setTheme`, `matchMedia`),
|
||||
> not a CSS toggle component. Penguin's `toggle/default-toggle.html` is a visual
|
||||
> on/off switch — not applicable here.
|
||||
> **Action:** de-duplicate the JS into a shared partial rather than porting.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
@@ -339,9 +368,14 @@ This is copy-pasted 5 times.
|
||||
|
||||
---
|
||||
|
||||
## 19. Inline SVG Icons
|
||||
## 19. Inline SVG Icons — LOW PRIORITY
|
||||
**Penguin UI: none (Penguin uses Heroicons-equivalent inline SVGs)**
|
||||
|
||||
> **Priority: LOW** | ~50 lines,8 distinct icons.
|
||||
> Penguin doesn't provide an icon library. Icons are already inlined where used.
|
||||
> Possible follow-up: extract into a `ui::icon(name)` macro for dedup, but
|
||||
> this is purely cosmetic — no functional gain.
|
||||
|
||||
| # | Location | Icon | Occurrences |
|
||||
|---|----------|------|-------------|
|
||||
| 55 | `base.html:70-72,168-170` | Hamburger (3-line menu) | 2 |
|
||||
@@ -357,8 +391,12 @@ All are raw inline `<svg>` with hardcoded `<path d="...">` — no icon library,
|
||||
|
||||
---
|
||||
|
||||
## 20. Empty State
|
||||
**Penguin UI: no direct component, but table empty states exist in Penguin tables**
|
||||
## 20. Empty State — LOW PRIORITY
|
||||
**Penguin UI: no dedicated empty-state component**
|
||||
|
||||
> **Priority: LOW** | ~22 lines across5 sites.
|
||||
> These are simple `<div>` messages, often with a CTA button already using
|
||||
> `ui::button`. Nothing to port — already consistent with project styling.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
@@ -370,8 +408,13 @@ All are raw inline `<svg>` with hardcoded `<path d="...">` — no icon library,
|
||||
|
||||
---
|
||||
|
||||
## 21. Dashboard Navigation Cards
|
||||
**Penguin UI: `card/`**
|
||||
## 21. Dashboard Navigation Cards — LOW PRIORITY
|
||||
**Penguin UI: `card/default-card.html` or `card/card-with-button.html`**
|
||||
|
||||
> **Priority: LOW** | ~16 lines.
|
||||
> Already uses card styling (`rounded-radius border border-outline hover:border-primary`).
|
||||
> Penguin's `default-card.html` adds a structured header/body layout — adopt if
|
||||
> cards ever grow beyond a title+description link.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
@@ -383,8 +426,13 @@ All are raw inline `<svg>` with hardcoded `<path d="...">` — no icon library,
|
||||
|
||||
---
|
||||
|
||||
## 22. Checkout Order Summary
|
||||
**Penguin UI: `card/` (ecommerce-summary style)**
|
||||
## 22. Checkout Order Summary — LOW PRIORITY
|
||||
**Penguin UI: `card/`**
|
||||
|
||||
> **Priority: LOW** | ~29 lines.
|
||||
> Already uses card-like styling with `tabular-nums`. All internal buttons use
|
||||
> `ui::button`. The only handcoded part is the outer `<div>` wrapper and line-item
|
||||
> layout. Penguin doesn't have an ecommerce-specific summary component.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
@@ -398,8 +446,14 @@ All are raw inline `<svg>` with hardcoded `<path d="...">` — no icon library,
|
||||
|
||||
---
|
||||
|
||||
## 23. Login Card
|
||||
**Penguin UI: `card/`**
|
||||
## 23. Login Card — LOW PRIORITY
|
||||
**Penguin UI: `card/default-card.html`**
|
||||
|
||||
> **Priority: LOW** | ~56 lines.
|
||||
> Already fully uses Penguin macros inside: `ui::input`, `ui::button`,
|
||||
> `ui::badge`, `ui::alert_danger`. Only the outer card wrapper (border,
|
||||
> bg-surface-alt, shadow-sm) is handcoded. Adopting `default-card.html`
|
||||
> would add visual polish but little functional gain.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
@@ -407,9 +461,15 @@ All are raw inline `<svg>` with hardcoded `<path d="...">` — no icon library,
|
||||
|
||||
---
|
||||
|
||||
## 24. Checkout Fieldset Cards
|
||||
## 24. Checkout Fieldset Cards — LOW PRIORITY
|
||||
**Penguin UI: `card/`**
|
||||
|
||||
> **Priority: LOW** | ~142 lines across4 fieldsets.
|
||||
> Already uses card styling (`rounded-radius border border-outline bg-surface p-6`)
|
||||
> and all internal form controls use Penguin macros (`ui::input`, `ui::textarea`,
|
||||
> `ui::button`). Only the `<fieldset>` + `<legend>` wrapping is handcoded.
|
||||
> Low value in replacing — fieldset semantics are correct here.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
| 71 | `assets/views/shop/checkout.html:34-79` | Contact info fieldset (email, name, phone+prefix) | ~46 lines |
|
||||
@@ -421,9 +481,14 @@ Each fieldset uses `<fieldset>` + `<legend>` with the same `rounded-radius borde
|
||||
|
||||
---
|
||||
|
||||
## 25. Order Detail Info Panel
|
||||
## 25. Order Detail Info Panel — LOW PRIORITY
|
||||
**Penguin UI: `card/`**
|
||||
|
||||
> **Priority: LOW** | ~64 lines across3 panels.
|
||||
> Already card-styled (`rounded-radius border border-outline bg-surface p-5`)
|
||||
> with Penguin macros inside. Deviating from this simple structure would
|
||||
> make the dense info layout harder to scan.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
| 75 | `assets/views/admin/orders/show.html:49-77` | Customer + shipping + payment info panel | ~29 lines |
|
||||
@@ -432,18 +497,27 @@ Each fieldset uses `<fieldset>` + `<legend>` with the same `rounded-radius borde
|
||||
|
||||
---
|
||||
|
||||
## 26. Shipping Method Settings Row
|
||||
## 26. Shipping Method Settings Row — LOW PRIORITY
|
||||
**Penguin UI: `card/`**
|
||||
|
||||
> **Priority: LOW** | ~21 lines.
|
||||
> Already fully uses Penguin macros: `ui::input`, `ui::checkbox`, `ui::button`.
|
||||
> The card wrapper is the same pattern as other admin panels. Nothing to port.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
| 78 | `assets/views/admin/shipping/index.html:14-34` | Per-carrier settings: name label, price input, enabled checkbox, save button | ~21 lines |
|
||||
|
||||
---
|
||||
|
||||
## 27. Product/Category Form Wrapper
|
||||
## 27. Product/Category Form Wrapper — LOW PRIORITY
|
||||
**Penguin UI: `card/`**
|
||||
|
||||
> **Priority: LOW** | ~150 lines across2 forms.
|
||||
> Already fully uses Penguin macros: `ui::input`, `ui::textarea`, `ui::select`,
|
||||
> `ui::file_input`, `ui::checkbox`, `ui::button`. The `<form>` card wrapper is
|
||||
> the same border/bg pattern. Penguin doesn't have a form-specific layout component.
|
||||
|
||||
| # | Location | What it is | Size |
|
||||
|---|----------|------------|------|
|
||||
| 79 | `assets/views/admin/catalog/product_form.html:15-99` | Full product edit/create form with all fields | ~84 lines |
|
||||
@@ -453,43 +527,99 @@ Both are wrapped in a single card-style `<form>`.
|
||||
|
||||
---
|
||||
|
||||
## Porting Roadmap (priority order)
|
||||
|
||||
### Phase 1 — HIGH (direct Penguin matches, clear win)
|
||||
|
||||
| # | Component | Penguin match | Est. effort | Lines saved |
|
||||
|---|-----------|---------------|-------------|-------------|
|
||||
| ~~5~~ | ~~Country/Phone Combobox~~ | ⛔ WON'T PORT — needs Alpine Focus plugin; our lightweight version kept | — | — |
|
||||
| ~~7~~ | ~~Image Gallery~~ | ✅ DONE — `carousel/default-carousel.html` | Small | ~19 |
|
||||
| ~~8~~ | ~~Radio Groups~~ | ✅ DONE — `radio/radio-with-container.html` | Small | ~47 |
|
||||
| 14 | Table | `table/default-table.html` | Medium | ~196 |
|
||||
|
||||
### Phase 2 — MEDIUM (good match, more integration risk)
|
||||
|
||||
| # | Component | Penguin match | Est. effort | Lines saved |
|
||||
|---|-----------|---------------|-------------|-------------|
|
||||
| 1 | Navbar | `navbar/default-navbar.html` | Large | ~143 |
|
||||
|
||||
### Phase 3 — LOW (mostly already Penguin, or no good match)
|
||||
|
||||
| # | Component | Action |
|
||||
|---|-----------|--------|
|
||||
| 18 | Toggle/Switch | De-duplicate JS into shared partial (not a Penguin port) |
|
||||
| 19 | Inline SVG Icons | Optional: extract `ui::icon(name)` macro |
|
||||
| 20 | Empty State | Already fine — nothing to port |
|
||||
| 21 | Dashboard Cards | Adopt `card/default-card.html` if cards grow |
|
||||
| 22 | Checkout Summary | Already fine — nothing to port |
|
||||
| 23 | Login Card | Already fine — only outer wrapper is handcoded |
|
||||
| 24 | Checkout Fieldsets | Already fine — only `<fieldset>` wrapper is handcoded |
|
||||
| 25 | Order Info Panels | Already fine — only card wrappers are handcoded |
|
||||
| 26 | Shipping Settings Row | Already fully uses Penguin macros |
|
||||
| 27 | Form Wrappers | Already fully uses Penguin macros |
|
||||
|
||||
### Already DONE (15 of 27)
|
||||
|
||||
| # | Component |
|
||||
|---|-----------|
|
||||
| 0 | Toast |
|
||||
| 2 | Sidebar (Admin) |
|
||||
| 3 | Sidebar (Category Accordion) |
|
||||
| 4 | Dropdown (Settings) |
|
||||
| 6 | Product Card |
|
||||
| 7 | Image Gallery |
|
||||
| 8 | Radio Groups |
|
||||
| 9 | Checkbox |
|
||||
| 10 | Text Input |
|
||||
| 11 | Textarea |
|
||||
| 12 | Select/Dropdown |
|
||||
| 13 | File Input |
|
||||
| 15 | Alert / Error Banner |
|
||||
| 16 | Badge / Status Pill |
|
||||
| 17 | Buttons |
|
||||
|
||||
**Remaining real ports: just #14 Table (~196 lines, Medium) and #1 Navbar
|
||||
(~143 lines, Large).** #5 Combobox is a conscious WON'T-PORT (Alpine Focus
|
||||
plugin dependency). The Phase-3 items are already internally Penguin-adapted
|
||||
or have no applicable component.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| # | Component | Penguin UI Directory | Handcoded Instances | Total Lines |
|
||||
|---|-----------|---------------------|--------------------|-------------|
|
||||
| 1 | Navbar | `navbar/` | 2 | ~143 |
|
||||
| 2 | Sidebar (admin) | `sidebar/` | 2 | ~46 |
|
||||
| 3 | Sidebar (category accordion) | `sidebar/` | 2 | ~62 |
|
||||
| 4 | Dropdown (settings) | `dropdown-menu/` | **2 duplicates** | ~103 |
|
||||
| 5 | Country/Phone combobox | `text-input/` | 2 | ~51 |
|
||||
| 6 | Product card | `card/` | 1 | ~30 |
|
||||
| 7 | Image gallery | `carousel/` | 1 | ~19 |
|
||||
| 8 | Radio groups | (form inputs) | 2 | ~47 |
|
||||
| 9 | Checkbox | `checkbox/` | 3 | ~15 |
|
||||
| 10 | Text input | `text-input/` | 8 | ~146 |
|
||||
| 11 | Textarea | `textarea/` | 3 | ~10 |
|
||||
| 12 | Select | `select/` | 3 | ~23 |
|
||||
| 13 | File input | `file-input/` | 2 | ~12 |
|
||||
| 14 | Table | `table/` | 5 | ~196 |
|
||||
| 15 | Alert/Error | `alert/` | 2 | ~9 |
|
||||
| 16 | Badge/Pill | `badge/` | 6 | ~17 |
|
||||
| 17 | Button | `buttons/` | 50+ occurrences | ~200+ |
|
||||
| 18 | Toggle (theme) | `toggle/` | **2 duplicates** | ~36 |
|
||||
| 19 | Inline SVG icons | N/A | 8 distinct icons | ~50 |
|
||||
| 20 | Empty state | (table variants) | 5 | ~22 |
|
||||
| 21 | Dashboard cards | `card/` | 1 | ~16 |
|
||||
| 22 | Checkout summary | `card/` | 1 | ~29 |
|
||||
| 23 | Login card | `card/` | 1 | ~56 |
|
||||
| 24 | Checkout fieldsets | `card/` | 4 | ~142 |
|
||||
| 25 | Order info panels | `card/` | 3 | ~64 |
|
||||
| 26 | Shipping settings row | `card/` | 1 | ~21 |
|
||||
| 27 | Form wrappers | `card/` | 2 | ~150 |
|
||||
| # | Component | Penguin UI Directory | Status | Lines |
|
||||
|---|-----------|---------------------|--------|-------|
|
||||
| 0 | Toast | `toast-notification/` | ✅ DONE | — |
|
||||
| 1 | Navbar | `navbar/` | PENDING (MED) | ~143 |
|
||||
| 2 | Sidebar (admin) | `sidebar/` | ✅ DONE | ~46 |
|
||||
| 3 | Sidebar (category accordion) | `sidebar/` | ✅ DONE | ~62 |
|
||||
| 4 | Dropdown (settings) | `dropdowns/` | ✅ DONE | ~103 |
|
||||
| 5 | Country/Phone combobox | `combobox/` | ⛔ WON'T PORT | ~51 |
|
||||
| 6 | Product card | `card/` | ✅ DONE | ~30 |
|
||||
| 7 | Image gallery | `carousel/` | ✅ DONE | ~19 |
|
||||
| 8 | Radio groups | `radio/` | ✅ DONE | ~47 |
|
||||
| 9 | Checkbox | `checkbox/` | ✅ DONE | ~15 |
|
||||
| 10 | Text input | `text-input/` | ✅ DONE | ~146 |
|
||||
| 11 | Textarea | `text-area/` | ✅ DONE | ~10 |
|
||||
| 12 | Select | `select/` | ✅ DONE | ~23 |
|
||||
| 13 | File input | `file-input/` | ✅ DONE | ~12 |
|
||||
| 14 | Table | `table/` | **HIGH** | ~196 |
|
||||
| 15 | Alert/Error | `alert/` | ✅ DONE | ~9 |
|
||||
| 16 | Badge/Pill | `badge/` | ✅ DONE | ~17 |
|
||||
| 17 | Button | `buttons/` | ✅ DONE | ~200+ |
|
||||
| 18 | Toggle (theme) | `toggle/` | LOW (dedup) | ~36 |
|
||||
| 19 | Inline SVG icons | N/A | LOW | ~50 |
|
||||
| 20 | Empty state | N/A | LOW | ~22 |
|
||||
| 21 | Dashboard cards | `card/` | LOW | ~16 |
|
||||
| 22 | Checkout summary | `card/` | LOW | ~29 |
|
||||
| 23 | Login card | `card/` | LOW | ~56 |
|
||||
| 24 | Checkout fieldsets | `card/` | LOW | ~142 |
|
||||
| 25 | Order info panels | `card/` | LOW | ~64 |
|
||||
| 26 | Shipping settings row | `card/` | LOW | ~21 |
|
||||
| 27 | Form wrappers | `card/` | LOW | ~150 |
|
||||
|
||||
**Grand total: ~27 distinct handcoded UI component types across ~80 instances, representing approximately 1,600+ lines of handcoded HTML/Tailwind/Alpine that could be replaced by Penguin UI components.**
|
||||
|
||||
### Duplication hotspots:
|
||||
- **Settings dropdown** (`base.html:110-162` and `admin/base.html:117-166`) — 100% copy-paste
|
||||
- **Theme toggle JS** (`base.html:13-30` and `admin/base.html:13-30`) — 100% copy-paste
|
||||
- **Text input class string** — same 80-character Tailwind string appears 15+ times
|
||||
- **Table class strings** (thead, tbody, tr) — copy-pasted 5 times
|
||||
- **Button variants** — inconsistent `hover:opacity-75` vs `hover:opacity-90`
|
||||
**Status: 15 of 27 components fully ported to Penguin UI. Only 2 real ports
|
||||
remain — #14 Table (HIGH) and #1 Navbar (MED). #5 Combobox is a conscious
|
||||
WON'T-PORT (Alpine Focus plugin dependency). The remaining Phase-3 items are
|
||||
already internally Penguin-adapted or have no applicable match.**
|
||||
|
||||
Reference in New Issue
Block a user