71dc46455c
The brand accent was rune gold. It is now mallorn green: --gold becomes
--leaf in tokens.css and everywhere it resolved, and the mark's wafer is
the green of the leaves lembas travels wrapped in rather than the biscuit
inside. Yellow is left to mean exactly one thing in the interface -- a
warning -- instead of two.
Two knock-on choices the rename forced:
- Code keywords move from the brand accent to --warning. Strings are
--success, which is green; keywords in leaf green beside them is not
a colour scheme.
- --success itself leans teal now. Two greens a hue apart read as one
colour rendered badly, and an unread dot has to be tellable from a
brand badge at a glance.
The mark is redrawn, not just recoloured. The blade is ovate -- widest a
third up from the base, rounded where the stem meets it, drawn out only
at the tip -- because the old one was pointed at both ends and read as an
eye. It is also much larger relative to the tile: at 16px the silhouette
is all that survives, and a small leaf on a large tile is a green square
with a smudge on it. Veins sweep towards the tip and shorten as the blade
narrows. The score cross is thinner and fainter so it stays texture.
A single diagonal score was tried first and rejected: behind a diagonal
leaf it does not read as scoring, it reads as a line struck through the
mark.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
106 lines
3.7 KiB
HTML
106 lines
3.7 KiB
HTML
{% from "_macros.html" import icon, brand, model_avatar %}
|
|
{#
|
|
Sidebar: brand, new chat, pinned models, the folder tree, then unfiled chats.
|
|
|
|
"New chat" is a link, not a button that creates a row. The chat is written
|
|
when the first message is sent, so opening one and walking away leaves
|
|
nothing behind.
|
|
#}
|
|
<aside class="sidebar" id="sidebar">
|
|
<div class="sidebar__header">
|
|
{{ brand(uid="side") }}
|
|
</div>
|
|
|
|
{% if can.get("chat.create") or can.get("folder.manage") %}
|
|
<div class="sidebar__actions">
|
|
{% if can.get("chat.create") %}
|
|
<a class="btn btn--primary btn--grow" href="/chat">
|
|
{{ icon("plus", "icon--sm") }} New chat
|
|
</a>
|
|
{% endif %}
|
|
{% if can.get("folder.manage") %}
|
|
<button class="btn btn--icon" hx-post="/api/folders" hx-swap="none"
|
|
hx-vals='{"name": "New folder"}' aria-label="New folder" title="New folder">
|
|
{{ icon("folder") }}
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Every 10s, refresh the unread dots and announce anything that finished
|
|
while this page was showing something else. Out-of-band spans only, so the
|
|
folder tree keeps its open/closed state. #}
|
|
<div hidden hx-get="/api/chats/unread" hx-trigger="every 10s"
|
|
hx-swap="none"></div>
|
|
|
|
<nav class="sidebar__scroll" id="sidebar-tree" aria-label="Chats">
|
|
{% if pinned_models and can.get("chat.create") %}
|
|
{# Shortcuts to start a chat with a particular model. These link rather than
|
|
post, so no chat exists until something is actually said. #}
|
|
<div class="nav-group">
|
|
<div class="nav-group__label">Pinned models</div>
|
|
{% for model in pinned_models %}
|
|
<a class="nav-item nav-item--model" href="/chat?model={{ model.model_id }}">
|
|
{{ model_avatar(model, cls="nav-item__avatar") }}
|
|
<span class="nav-item__label">{{ model.label }}</span>
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if folders %}
|
|
<div class="nav-group">
|
|
<div class="nav-group__label">Folders</div>
|
|
{% for folder in folders %}
|
|
{% include "partials/_folder.html" %}
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="nav-group">
|
|
<div class="nav-group__label">Chats</div>
|
|
{% if unfiled_chats %}
|
|
{% for chat_item in unfiled_chats %}
|
|
{% include "partials/_chat_link.html" %}
|
|
{% endfor %}
|
|
{% else %}
|
|
<p class="nav-empty">No chats yet. The road begins here.</p>
|
|
{% endif %}
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="sidebar__footer">
|
|
{% if can.get("library.use") %}
|
|
<a class="nav-item" href="/library/knowledge">
|
|
{{ icon("archive", "icon--sm") }}
|
|
<span class="nav-item__label">Library</span>
|
|
</a>
|
|
{% endif %}
|
|
|
|
<a class="nav-item" href="/settings">
|
|
{{ icon("user", "icon--sm") }}
|
|
<span class="nav-item__label">{{ user.name }}</span>
|
|
{% if user.is_admin %}<span class="badge badge--leaf">admin</span>{% endif %}
|
|
</a>
|
|
|
|
<div class="sidebar__tools">
|
|
{% if user.is_admin %}
|
|
<a class="btn btn--icon" href="/admin" aria-label="Admin settings" title="Admin settings">
|
|
{{ icon("shield") }}
|
|
</a>
|
|
{% endif %}
|
|
<button class="btn btn--icon" type="button" data-theme-toggle
|
|
aria-label="Switch theme" title="Switch theme">
|
|
<span class="theme-icon theme-icon--dark">{{ icon("moon") }}</span>
|
|
<span class="theme-icon theme-icon--light">{{ icon("sun") }}</span>
|
|
</button>
|
|
<span class="spacer"></span>
|
|
<form method="post" action="/auth/logout">
|
|
<button class="btn btn--icon" type="submit" aria-label="Sign out" title="Sign out">
|
|
{{ icon("logout") }}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</aside>
|