port of the new penguinui placing

This commit is contained in:
Priec
2026-06-18 10:51:07 +02:00
parent ee944ed5ce
commit 9a3c68eae5
7 changed files with 47 additions and 32 deletions

View File

@@ -59,7 +59,7 @@
class="fixed inset-y-0 left-0 z-40 flex w-60 flex-col border-r border-outline bg-surface-alt transition-transform duration-300 md:translate-x-0 dark:border-outline-dark dark:bg-surface-dark-alt">
{# Sidebar nav links — adapted from the vendored Penguin UI component
assets/views/penguinui/sidebar/simple-sidebar.html: Penguin's link
penguinui-components/sidebar/simple-sidebar.html: Penguin's link
treatment (hover:bg-primary/5, focus-visible:underline) with the active
state (bg-primary/10 + text-on-surface-strong) mapped onto our
data-nav / aria-current so markActiveNav() keeps driving it. #}

View File

@@ -153,7 +153,7 @@
<!-- toast notifications: fire from anywhere with toast('message').
Adapted from the vendored Penguin UI component
(assets/views/penguinui/toast-notification/stacking-toast-notification.html):
(penguinui-components/toast-notification/stacking-toast-notification.html):
the docs-only demo trigger buttons are omitted and the malformed quotes on
the upstream dismiss-button <svg> tags are fixed. -->
<div x-data="{

View File

@@ -1,6 +1,6 @@
{# Reusable UI macros adapted from vendored Penguin UI components.
These are OUR adaptation layer; the byte-for-byte upstream sources live under
assets/views/penguinui/. Tailwind sees the full literal class strings here
penguinui-components/. Tailwind sees the full literal class strings here
(assets/css/app.css has @source "../views"), so every branch must spell its
classes out in full — never build class names by concatenation.

View File

@@ -2,7 +2,7 @@
to kill the former ~100-line copy-paste duplication.
Adapted from the vendored Penguin UI component
assets/views/penguinui/dropdowns/dropdown-with-click.html: Penguin's dropdown
penguinui-components/dropdowns/dropdown-with-click.html: Penguin's dropdown
menu container + item treatment. Deviations: kept our gear icon-only trigger
and our core-Alpine open / @click.outside toggle (upstream's x-trap / $focus
need the Alpine Focus plugin, which we don't bundle); item hover uses

View File

@@ -1,5 +1,5 @@
{# Adapted from the vendored Penguin UI component
(assets/views/penguinui/card/ecommerce-product-card.html):
(penguinui-components/card/ecommerce-product-card.html):
wired to our product data + i18n + htmx add-to-cart + toast. The demo rating
stars, hardcoded title/price/description/image and the `max-w-sm` (which fights
the shop grid) are dropped; the whole card links to the product page. #}

View File

@@ -7,7 +7,7 @@
one of its subcategories.
Adapted from the vendored Penguin UI component
assets/views/penguinui/sidebar/sidebar-with-collapsible-menus.html: Penguin's
penguinui-components/sidebar/sidebar-with-collapsible-menus.html: Penguin's
link treatment + active state + chevron-down rotation. Deviations: the group
row keeps our link + toggle split (categories are navigable, not just
expandable), and we use x-show/x-transition instead of upstream's x-collapse

View File

@@ -5,20 +5,35 @@
## Vendoring convention
When a Penguin UI component can replace a handcoded one, we vendor its source
and then use it (instead of hand-rolling):
The full library is now vendored locally at repo-root
`penguinui-components/` (177 component `.html` files, moved there
2026-06-18). Read components from there — **NO** network/curl/WebFetch
needed anymore.
1. Copy the component's source **byte-for-byte** from the [Penguin UI repo](https://github.com/SalarHoushvand/penguinui-components/tree/main)
into `assets/views/penguinui/`, **mirroring the upstream repo hierarchy**
(e.g. `toast-notification/stacking-toast-notification.html`). This directory
is reserved exclusively for vendored Penguin UI components and is kept an
**exact, unmodified mirror** of upstream — demo triggers, bugs and all. It's
a reference, not the rendered markup.
2. Adapt it where it's actually used (strip docs-only demo triggers, fix obvious
upstream bugs, wire data bindings). Note the deviations in a comment next to
the adapted copy.
3. Rebuild Tailwind (`make css`) so any new utility classes get compiled.
4. Mark the section below as ✅ **DONE**.
### HARD RULE — read-only, never edit
`penguinui-components/` is a read-only third-party library, **NOT our
code**. Never edit, never `{% include %}`, never adapt in place. It is
reference only; **copy markup OUT** of it and adapt at the use-site.
When a Penguin UI component can replace a handcoded one:
1. Find the component in the local `penguinui-components/` directory.
2. Copy its markup **out** into the appropriate `assets/views/` location,
adapting it where used (strip docs-only demo triggers, fix obvious
upstream bugs, wire data bindings, map Penguin classes to our design
tokens). Note the deviations in a comment next to the adapted copy.
3. Keep the original `penguinui-components/` file **untouched** — it stays
as a byte-for-byte reference snapshot.
4. Rebuild Tailwind (`make css`) so any new utility classes get compiled.
5. Mark the section below as ✅ **DONE**.
### Why it's at repo root + the build guard
Moved OUT of `assets/views/` to repo root because Tailwind v4 auto-detects
sources from the project root — so `assets/css/app.css` carries
`@source not "../../penguinui-components";` to explicitly exclude it
from the build. If the build ever balloons, check that exclusion is intact.
---
@@ -26,7 +41,7 @@ and then use it (instead of hand-rolling):
**Penguin UI: `toast-notification/stacking-toast-notification.html`**
- Exact upstream mirror at `assets/views/penguinui/toast-notification/stacking-toast-notification.html` (reference only)
- Exact upstream mirror at `penguinui-components/toast-notification/stacking-toast-notification.html` (reference only)
- Adapted/rendered copy lives inline in `assets/views/base.html` (demo triggers
removed; the upstream dismiss-button `<svg>` quote bugs fixed)
- The global `toast('message')` JS helper now dispatches the component's
@@ -58,7 +73,7 @@ and then use it (instead of hand-rolling):
## 2. Sidebar (Admin) — ✅ DONE
**Penguin UI: `sidebar/simple-sidebar.html`**
- Exact upstream mirror at `assets/views/penguinui/sidebar/simple-sidebar.html` (reference only)
- Exact upstream mirror at `penguinui-components/sidebar/simple-sidebar.html` (reference only)
- Adapted at use-site in `assets/views/admin/base.html`: the nav links + bottom
exit/logout now use Penguin's link treatment (`hover:bg-primary/5`,
`underline-offset-2 focus-visible:underline focus:outline-hidden`) and the
@@ -73,7 +88,7 @@ and then use it (instead of hand-rolling):
## 3. Sidebar (Category Accordion) — ✅ DONE
**Penguin UI: `sidebar/sidebar-with-collapsible-menus.html`**
- Exact upstream mirror at `assets/views/penguinui/sidebar/sidebar-with-collapsible-menus.html` (reference only)
- Exact upstream mirror at `penguinui-components/sidebar/sidebar-with-collapsible-menus.html` (reference only)
- Adapted at use-site in `assets/views/shop/_sidebar.html`: Penguin link treatment +
active state + chevron-down rotation (`rotate-180`); child items now sit in a
bordered/indented list instead of the old `padding-left:28px` + `↳`. Kept our
@@ -90,7 +105,7 @@ and then use it (instead of hand-rolling):
## 4. Dropdown (Settings) — ✅ DONE
**Penguin UI: `dropdowns/dropdown-with-click.html`**
- Exact upstream mirror at `assets/views/penguinui/dropdowns/dropdown-with-click.html` (reference only)
- Exact upstream mirror at `penguinui-components/dropdowns/dropdown-with-click.html` (reference only)
- **De-duplicated**: the ~103-line copy-paste is now one shared partial
`assets/views/partials/settings_dropdown.html`, included by both `base.html`
and `admin/base.html` (each host keeps its own positioning wrapper
@@ -125,7 +140,7 @@ and then use it (instead of hand-rolling):
## 6. Product Card — ✅ DONE
**Penguin UI: `card/ecommerce-product-card.html`**
- Exact upstream mirror at `assets/views/penguinui/card/ecommerce-product-card.html` (reference only)
- Exact upstream mirror at `penguinui-components/card/ecommerce-product-card.html` (reference only)
- Adapted/rendered copy is `assets/views/shop/_card.html`: `<article>` shell + Penguin
image/title/price layout and the cart-icon add-to-cart button, wired to our product
data + i18n + htmx `hx-post` add-to-cart + `toast()`. Demo-only rating stars,
@@ -171,7 +186,7 @@ and then use it (instead of hand-rolling):
## 9. Checkbox — ✅ DONE
**Penguin UI: `checkbox/default-checkbox.html`**
- Exact upstream mirror at `assets/views/penguinui/checkbox/default-checkbox.html` (reference only)
- Exact upstream mirror at `penguinui-components/checkbox/default-checkbox.html` (reference only)
- `ui::checkbox(name, label, id, value="on", checked, attrs)` macro in `macros/ui.html`
(full Penguin control: custom box + check-icon + label, `has-checked:`/`peer` variants).
- Adopted: product/category "Published" + shipping "Enabled".
@@ -179,7 +194,7 @@ and then use it (instead of hand-rolling):
## 10. Text Input — ✅ DONE
**Penguin UI: `text-input/default-text-input.html`**
- Exact upstream mirror at `assets/views/penguinui/text-input/default-text-input.html` (reference only)
- Exact upstream mirror at `penguinui-components/text-input/default-text-input.html` (reference only)
- `ui::input(name, type, id, value, placeholder, required, autocomplete, attrs, extra, width="w-full")`
macro — **verbatim** Penguin classes (`bg-surface-alt`, `focus-visible:outline-*`).
Adopted at every text/email/number/password input: login (2), checkout (email,
@@ -193,14 +208,14 @@ and then use it (instead of hand-rolling):
## 11. Textarea — ✅ DONE
**Penguin UI: `text-area/default-textarea.html`**
- Exact upstream mirror at `assets/views/penguinui/text-area/default-textarea.html` (reference only)
- Exact upstream mirror at `penguinui-components/text-area/default-textarea.html` (reference only)
- `ui::textarea(name, id, value, rows, placeholder, required, attrs, extra)` macro.
- Adopted: checkout note, product & category description.
## 12. Select/Dropdown (Native) — ✅ DONE
**Penguin UI: `select/default-select.html`**
- Exact upstream mirror at `assets/views/penguinui/select/default-select.html` (reference only)
- Exact upstream mirror at `penguinui-components/select/default-select.html` (reference only)
- Adopted inline (3 sites: product category, category parent, order status) — Penguin
`appearance-none` select on `bg-surface-alt` wrapped in `relative` with the chevron
SVG. Inline rather than a macro because the `<option>` set is caller-specific.
@@ -208,7 +223,7 @@ and then use it (instead of hand-rolling):
## 13. File Input — ✅ DONE
**Penguin UI: `file-input/default-file-input.html`**
- Exact upstream mirror at `assets/views/penguinui/file-input/default-file-input.html` (reference only)
- Exact upstream mirror at `penguinui-components/file-input/default-file-input.html` (reference only)
- `ui::file_input(name, id, accept, attrs, extra)` macro (verbatim Penguin `file:` styling).
- Adopted: product & category image upload.
@@ -239,7 +254,7 @@ This is copy-pasted 5 times.
## 15. Alert / Error Banner — ✅ DONE
**Penguin UI: `alert/default-alert.html`**
- Exact upstream mirror at `assets/views/penguinui/alert/default-alert.html` (reference only)
- Exact upstream mirror at `penguinui-components/alert/default-alert.html` (reference only)
- Adapted into the `ui::alert_danger(message, extra="")` macro in
`assets/views/macros/ui.html` (compact one-line danger alert + danger icon).
- Adopted at both sites: `admin/login.html` (login error) and
@@ -250,7 +265,7 @@ This is copy-pasted 5 times.
## 16. Badge / Status Pill — ✅ DONE
**Penguin UI: `badge/soft-color-badge.html`**
- Exact upstream mirror at `assets/views/penguinui/badge/soft-color-badge.html` (reference only)
- Exact upstream mirror at `penguinui-components/badge/soft-color-badge.html` (reference only)
- Adapted into the `ui::badge(label, variant)` macro in `assets/views/macros/ui.html`
(variants: success | danger | warning | info | primary | neutral).
- Adopted at the status-pill sites: "Auth" badge (`admin/login.html`), order status
@@ -265,7 +280,7 @@ This is copy-pasted 5 times.
## 17. Buttons — ✅ DONE
**Penguin UI: `buttons/default-button.html`, `outline-button.html`, `ghost-button.html`, `button-with-icon.html`**
- Exact upstream mirrors at `assets/views/penguinui/buttons/*.html` (reference only).
- Exact upstream mirrors at `penguinui-components/buttons/*.html` (reference only).
- Macros in `assets/views/macros/ui.html`:
`ui::button(label, variant="primary", type, href, attrs, extra, icon, size="px-4 py-2 text-sm")`
and `ui::icon_button(icon, variant="ghost-secondary", aria_label, attrs, …)`.