Ctrl K
ComunidadGuías…

DESIGN.md

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Design Conventions

UI and visual conventions for the admin and members portals. Read this when working on ActiveAdmin pages, members views, or CSS.

## CSS

Native CSS. Propshaft serves `admin.css` and `member.css`, which `@import` sheets under `shared/`, `admin/`, and `members/`. Save and refresh.

**New widget.** Add a file next to its siblings, `@import` it from the portal entry, name the thing (`.panel-action-row`). Do not attach a long class string to a one-off `div`.

- Colors and space live in `shared/tokens.css`. Change them there. Numbered greys/greens stay put. Semantic names flip on `html.dark` / `.dark`. Do not invent a token for a 1–2× pair, a hover-only green, a status inversion, or CodeJar hex.
- Stored preference is `system|light|dark` on `html[data-theme]`. Paint via `html.dark` / `.dark`. Do not switch to `@media (prefers-color-scheme)` or `light-dark()`.
- Markup we own uses semantic classes (`.btn`, `.status-tag`, `.panel`). Name the thing, not the paint.
- Prefix members layout chrome (`member-app`, `member-nav`) and Stimulus maps (`member-menu-open`). Admin chrome uses `admin-` the same way. Page widgets do not (`shop-cart`, `billing-card`).
- Tiny utilities live in `shared/utilities.css` (`is-*`, `cluster` / `stack`, `icon-*`, type helpers). Read that file. Do not grow a spacing scale in HTML. Tooltip/menu visibility is nested (`.tooltip.is-visible`).
- ActiveAdmin gem HTML is styled with descendant selectors. Do not fork gem templates to rename their classes.
- Members page gutter is `--inline-space` (`1rem` on mobile, `1ch` from `48rem`) on rewritten chrome, with matching bleeds. Formtastic and tables stay `rem`. Do not find-replace rem.
- `@media` repeats rem (`48rem` / `64rem` / `40rem`). `var()` is invalid in queries. `@custom-media` waits for a later Safari floor (today 16.6).
- Icons: Lucide SVGs via `icon("name")`. Size and mute them in CSS.

## Icons in Panels and Form Fieldsets

Both `panel` and `f.inputs` support the `icon:` option:

```ruby
panel "Title", icon: "icon-name" do
  # ...
end

f.inputs "Title", icon: "icon-name" do
  f.input :field
end
```

Icons render at half opacity at `1.25rem` (`.icon-5` / `.panel-title-icon`) — a muted visual cue, not a distraction.

**Only titled fieldsets get icons** — bare `f.inputs do` blocks (no title string) should never receive an icon.

When a fieldset has extra options, place `icon:` before them:

```ruby
f.inputs "Title", icon: "icon-name", data: { controller: "..." } do
f.inputs "Title", icon: "icon-name", "data-controller" => "..." do
```

Use the same icon for the same concept everywhere (panels, fieldsets, nav).

### Icon Mapping

All icons are sourced from [Lucide](https://lucide.dev), stored as SVGs in
`app/assets/images/icons/`. Two custom exceptions are noted below.

The panel icon for a concept **must** match the nav icon when one exists.

#### Resource / Model Icons

| Concept            | Icon Name          | Nav | Notes                                 |
| ------------------ | ------------------ | :-: | ------------------------------------- |
| Member             | `users`            |  ✓  | Plural for collections                |
| Producer           | `user-round-group` |     | Shared shop and basket content source |
| Membership         | `calendar-range`   |  ✓  |                                       |
| Delivery           | `calendar`         |     |                                       |
| Basket             | `shopping-bag`     |  ✓  | Paniers nav (basket_content.rb)       |
| Shop / Shop Orders | `shopping-basket`  |  ✓  | Shop nav (active_admin.rb)            |
| Activity           | `handshake`        |  ✓  | Nav uses same icon                    |
| Invoice / Billing  | `banknotes`        |  ✓  | ⚠️ Custom Heroicon (no Lucide plural) |
| Payment            | `banknotes`        |  ✓  | Same as above                         |
| Absence            | `tent`             |     |                                       |
| Temporary address  | `clock-fading`     |     | Overlay row; CTA uses `map-pin-house` |
| Email / Mails      | `mails`            |  ✓  | Plural; nav uses `mail`               |
| Newsletter         | `megaphone`        |     |                                       |
| Mail Template      | `clipboard`        |     |                                       |
| Announcement       | `megaphone`        |     | Same as newsletter                    |
| Bidding Round      | `scale`            |     |                                       |
| Shares             | `receipt-text`     |     |                                       |
| Basket Content     | `sprout`           |     |                                       |
| Price reduction    | `ticket-percent`   |     | Not the shop tag icon                 |

#### Non-Model / Generic Panel Icons

| Concept             | Icon Name                | Notes                       |
| ------------------- | ------------------------ | --------------------------- |
| Details             | `notebook-text`          | ID, dates, validation info  |
| Contact             | `contact-round`          | Name, email, phone, address |
| Billing (panel)     | `banknotes`              | ⚠️ Custom Heroicon          |
| Amount / Pricing    | `receipt-text`           | Monetary breakdown          |
| Notes               | `notepad-text`           | Free-text notes             |
| Comments            | `message-square-text`    | ActiveAdmin comments        |
| Waiting / Pending   | `clock`                  | Waiting membership          |
| Config / Settings   | `sliders-horizontal`     | Configuration options       |
| Renewal             | `refresh-cw`             | Membership renewal          |
| Sheets / PDF        | `file-spreadsheet`       | PDF sheet documents         |
| Attachments         | `paperclip`              | File attachments            |
| Notifications       | `mail-check`             | Email notifications         |
| Registration / Form | `form`                   | Member registration form    |
| Recipients          | `users`                  | Mail recipients list        |
| Preview             | `eye`                    | Content preview             |
| Carpooling          | `car`                    | Carpooling info             |
| State / Status      | `circle-check-big`       | State/validation info       |
| Address / Location  | `map`                    | Physical address            |
| Overdue Notices     | `mail-warning`           | Overdue/reminder notices    |
| Periods             | `calendar-days`          | Delivery cycle periods      |
| Information         | `info`                   | Info/help text              |
| Missing Deliveries  | `triangle-alert`         | Warning/missing data        |
| Support             | `life-buoy`              | Help / support              |
| Updates             | `gift`                   | What's new                  |
| Analytics           | `chart-no-axes-combined` | Historical year-over-year   |

### Custom Icons

Two icons in `app/assets/images/icons/` are **not** from Lucide:

- **`banknotes`** — Custom Heroicon (stacked bills). Lucide only has singular `banknote`.
  Used for billing/payment panels and nav.
- **`redo-off`** — Custom icon (redo arrow with slash). Hand-made for "no renewal" state.

### Adding New Icons

1. Find the icon on [Lucide](https://lucide.dev)
2. Download the SVG and save to `app/assets/images/icons/{name}.svg`
3. Set `stroke-width="1.5"` and remove the `class` attribute
4. Use via `icon("name")`, `panel "Title", icon: "name"`, or `f.inputs "Title", icon: "name"`

### Style Guidelines

- **Lucide only** — all icons come from Lucide (two custom exceptions noted above)
- **24px / stroke 1.5** — all SVGs use `width="24" height="24"` and `stroke-width="1.5"`
- **Match nav icons** — if a concept has a nav icon, the panel must use the same one
- **One icon per concept** — same concept = same icon everywhere