Tag Visualisation
How tags are rendered across godocs and how to reuse the patterns in other projects (e.g. godocs-inbox).
Rendering patterns
Tags appear in five contexts, each with a different size/interaction level:
| Context | Template | Size | Interactive | Notes |
|---|---|---|---|---|
| Document card | partials/document_card.html |
.tag-chip (tiny) |
No | Truncated to 7ch, sidebar column |
| Document view | document.html |
.tag.is-medium |
No | Read-only display |
| Document edit | document_edit.html |
.tag (medium) |
Delete button | Each tag has an inline remove form |
| Quick tags | partials/quick_tags.html |
.button.is-small |
Add on click | Greyed out with tick when assigned |
| Archive table | archive.html |
.tag.is-small |
No | Inline in table cell |
Common markup
Every tag uses inline style for its colour rather than a CSS class, because colours are user-defined per tag:
<span class="tag" style="background-color: {{ tag.Color }}; color: white;">
{{ tag.Name }}
</span>
Variants differ only in Bulma size modifier (is-small, is-medium) and whether a delete/add control is included.
Card chip (partials/document_card.html)
Compact tag shown in the card sidebar. Truncated with ellipsis to avoid overflow:
<span class="tag tag-chip"
style="background-color: {{ tag.Color }}; color: white;"
title="{{ tag.Name }}">{{ tag.Name }}</span>
CSS (defined in base.html and webapp.css):
.tag-chip {
font-size: 0.7rem;
max-width: 7ch;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
Editable tag (document_edit.html)
Tag with an inline form for removal:
<span class="tag" style="background-color: {{ tag.Color }}; color: white;">
{{ tag.Name }}
<form method="POST" action="/document/{{ doc.ULID }}/tags/{{ tag.ID }}/remove"
style="display:inline; margin:0; padding:0;">
<button type="submit" class="delete is-small"></button>
</form>
</span>
Quick tag button (partials/quick_tags.html)
Top-15 most-used tags shown as clickable buttons. Already-assigned tags are greyed out:
<!-- Assigned -->
<span class="button is-small is-static" style="opacity: 0.5; ...">
✓ {{ qt.Name }}
</span>
<!-- Available — click to add -->
<form method="POST" action="{{ form_action_prefix }}/tags">
<input type="hidden" name="tag_id" value="{{ qt.ID }}">
<button type="submit" class="button is-small"
style="background-color: {{ qt.Color }}; color: white;">
{{ qt.Name }}
</button>
</form>
Composability with godocs-inbox
godocs-inbox needs to display and assign tags during the upload/triage workflow. The goal is to share tag rendering logic rather than duplicate it.
What can be reused
-
Tag data model -- godocs-inbox fetches tags via
GET /api/tagsand gets the same{id, name, color, tag_group}objects. -
Display-only chip -- the card chip and read-only tag markup are pure HTML+CSS with no godocs-specific dependencies. Any pongo2 template can render them given a tag object with
NameandColor. -
Quick tags partial --
partials/quick_tags.htmlis parameterised viaform_action_prefixso it already works for different form targets. godocs-inbox can include it directly if it uses pongo2 templates, or replicate the pattern with its own form action.
What needs adaptation
-
Remove/add forms -- form actions (
/document/:ulid/tags/:id/remove) are godocs-specific routes. godocs-inbox needs its own endpoints or should call the godocs API directly. -
Tag group enforcement -- the one-tag-per-group constraint is enforced by a DB trigger in godocs. External tools adding grouped tags via the API get the same enforcement. Tools that pre-filter available tags should call
GET /api/tags/groupsto understand the group structure.
Recommended approach
Keep tag rendering as partials with minimal assumptions:
partials/tag_chip.html-- display-only, needstag.Nameandtag.Colorpartials/tag_editable.html-- needstag,doc.ULID, and aremove_actionURLpartials/quick_tags.html-- already parameterised viaform_action_prefix
External projects (godocs-inbox) can either:
- Include the partials if they embed godocs templates
- Copy the HTML pattern -- it's 3-5 lines of Bulma markup per variant
- Use the API -- fetch tags, render client-side using the same colour/name fields
Tag group visualisation
Tags in groups are visually indistinguishable from free tags on document cards (both use the same chip). The group structure is visible in:
- Tag manager (
/tags) -- tags are grouped bytag_groupin the table - Document edit -- grouped tags appear alongside free tags; the DB trigger prevents assigning two tags from the same group
.tags.jsonsidecar -- separatestags(free) fromtag_groups(grouped)
For richer group visualisation (e.g. showing group headers on cards), a future partial could render grouped tags separately.