version 0.2.0 replaces fromer version!
Some checks failed
ci / check (push) Has been cancelled
ci / release (push) Has been cancelled

This commit is contained in:
2026-05-25 19:32:22 +02:00
parent 9419f166ce
commit 80252baf53
33 changed files with 3434 additions and 478 deletions

56
adapters/django/README.md Normal file
View File

@@ -0,0 +1,56 @@
# Django partials
Optional Layer 3 — `{% include %}`-ready templates that wrap the canonical web components in conveniences for Django teams.
## How to use
Copy this folder into your Django app's templates directory:
```sh
cp -r adapters/django/templates/whynot myapp/templates/whynot
```
Then reference partials by their template name:
```django
{% include "whynot/_prototype_card.html" with p=prototype %}
{% include "whynot/_page_header.html" with eyebrow="whynot · signals" title="Signals" %}
{% include "whynot/_pipeline.html" with active_idx=3 %}
```
**Don't** add `adapters/django/` to `TEMPLATES.DIRS` directly — that couples your `INSTALLED_APPS` to the design-system repo layout. Copy what you need.
## What's in here
| Partial | Component it wraps | Context variables |
|---|---|---|
| `_base_head.html` | (none — `<link>` + `<script>` tags) | — |
| `_button.html` | `<wn-button>` | `variant`, `icon`, `label`, `href`, `type` |
| `_eyebrow.html` | `<wn-eyebrow>` | `text` |
| `_tag.html` | `<wn-tag>` | `text`, `active`, `draft` |
| `_stage_dot.html` | `<wn-stage-dot>` | `level`, `label` |
| `_page_header.html` | `<wn-page-header>` | `eyebrow`, `title`, `lede` |
| `_pipeline.html` | `<wn-pipeline>` | `active_idx` |
| `_field_row.html` | `<wn-field-row>` | `label`, `value`, `aside` |
| `_prototype_card.html` | `<wn-prototype-card>` | `p` (a prototype object) |
| `_banner.html` | `<wn-banner>` | `variant`, `title`, `body`, `dismissible` |
| `_empty_state.html` | `<wn-empty-state>` | `icon`, `title`, `body`, `cta_label`, `cta_href` |
These partials are deliberately thin. If you need more flexibility, write the component HTML inline in your template — `<wn-button>` is no less ergonomic than `{% include %}`.
## What they don't do
- They don't validate inputs.
- They don't auto-escape — Django does that.
- They don't carry app-specific styling overrides — those go in your app, not here.
## Updating after a design system bump
After `pnpm up @whynot/design`:
```sh
# Diff the upstream partials against your local copies.
diff -r node_modules/@whynot/design/adapters/django/templates/whynot/ myapp/templates/whynot/
# Cherry-pick changes you want. The partials are stable but may gain new optional context vars across minor versions.
```

View File

@@ -0,0 +1,6 @@
{# Banner.
{% include "whynot/_banner.html" with variant="success" title="Promoted" body="WNO-017 was promoted to Helix." %} #}
<wn-banner variant="{{ variant|default:'info' }}"{% if title %} title="{{ title }}"{% endif %}{% if dismissible %} dismissible{% endif %}>
{{ body }}
</wn-banner>

View File

@@ -0,0 +1,9 @@
{# Link & register the design system. Include in <head> of your base template.
{% include "whynot/_base_head.html" %}
Customise STATIC_URL prefix if your collectstatic layout differs. #}
{% load static %}
<link rel="stylesheet" href="{% static 'whynot/colors_and_type.css' %}">
<link rel="stylesheet" href="{% static 'whynot/components.css' %}">
<script type="module" src="{% static 'whynot/index.js' %}" defer></script>

View File

@@ -0,0 +1,6 @@
{# Button.
{% include "whynot/_button.html" with label="Promote" variant="primary" icon="arrow-right" %}
{% include "whynot/_button.html" with label="Cancel" %}
{% include "whynot/_button.html" with label="Read" href="/docs" variant="ghost" %} #}
<wn-button{% if variant %} variant="{{ variant }}"{% endif %}{% if icon %} icon="{{ icon }}"{% endif %}{% if href %} href="{{ href }}"{% endif %}{% if type %} type="{{ type }}"{% endif %}{% if disabled %} disabled{% endif %}>{{ label }}</wn-button>

View File

@@ -0,0 +1,9 @@
{# Empty state.
{% include "whynot/_empty_state.html" with icon="activity" title="No signals yet." body="Lack of signal is also information." cta_label="Record a signal" cta_href="/signals/new/" %} #}
<wn-empty-state{% if icon %} icon="{{ icon }}"{% endif %}{% if title %} title="{{ title }}"{% endif %}>
{{ body }}
{% if cta_label %}
<wn-button slot="cta" variant="primary"{% if cta_href %} href="{{ cta_href }}"{% endif %}>{{ cta_label }}</wn-button>
{% endif %}
</wn-empty-state>

View File

@@ -0,0 +1,4 @@
{# Eyebrow label.
{% include "whynot/_eyebrow.html" with text="Stage 3 · Experiment" %} #}
<wn-eyebrow{% if strong %} strong{% endif %}>{{ text }}</wn-eyebrow>

View File

@@ -0,0 +1,10 @@
{# Field row — label / value (+ optional aside).
{% include "whynot/_field_row.html" with label="Learning question" value=prototype.learning_question %}
{% include "whynot/_field_row.html" with label="Target" value=prototype.target aside="2026-04-01" %}
For arbitrary value markup, write <wn-field-row> inline and slot children. #}
<wn-field-row label="{{ label }}"{% if stacked %} stacked{% endif %}{% if narrow %} narrow{% endif %}>
{{ value }}
{% if aside %}<span slot="aside">{{ aside }}</span>{% endif %}
</wn-field-row>

View File

@@ -0,0 +1,6 @@
{# Page header with eyebrow, title, optional lede.
{% include "whynot/_page_header.html" with eyebrow="whynot · prototypes" title="Prototypes" lede="Structured prototype cards." %}
For actions, write the component inline rather than using this partial. #}
<wn-page-header{% if eyebrow %} eyebrow="{{ eyebrow }}"{% endif %} title="{{ title }}"{% if lede %} lede="{{ lede }}"{% endif %}></wn-page-header>

View File

@@ -0,0 +1,4 @@
{# Pipeline strip — 5 stages, active index 04.
{% include "whynot/_pipeline.html" with active_idx=3 %} #}
<wn-pipeline active-idx="{{ active_idx|default:0 }}"></wn-pipeline>

View File

@@ -0,0 +1,12 @@
{# Prototype card.
Context: `p` — a prototype-like object with attributes:
id, signal, stage_label, pitch, learning, smallest_test, target, href
{% include "whynot/_prototype_card.html" with p=prototype %} #}
<wn-prototype-card card-id="{{ p.id }}" signal="{{ p.signal }}" stage-label="{{ p.stage_label }}"{% if p.href %} href="{{ p.href }}"{% endif %}>
<span slot="pitch">{{ p.pitch }}</span>
<span slot="learning">{{ p.learning }}</span>
<span slot="test">{{ p.smallest_test }}</span>
<span slot="target">→ {{ p.target }}</span>
</wn-prototype-card>

View File

@@ -0,0 +1,4 @@
{# Signal-strength dot.
{% include "whynot/_stage_dot.html" with level="S2" label="Medium" %} #}
<wn-stage-dot level="{{ level }}">{% if label %}{{ label }}{% else %}{{ level }}{% endif %}</wn-stage-dot>

View File

@@ -0,0 +1,4 @@
{# Tag pill.
{% include "whynot/_tag.html" with text="Experiment" active=True %} #}
<wn-tag{% if active %} active{% endif %}{% if draft %} draft{% endif %}>{{ text }}</wn-tag>