penguinui

This commit is contained in:
Priec
2026-08-03 17:25:12 +02:00
parent 0e6d764702
commit 00121874a7
9 changed files with 383 additions and 149 deletions

View File

@@ -11,8 +11,57 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}Komp Accounting{% endblock %} · Komp Accounting</title>
{#
Cascade order, declared before anything ships CSS so that it is this line
that decides it. `app` is static/app.css, which is wrapped in that layer:
it sits above Tailwind's preflight — so the reset cannot touch the site's
own look — and below Tailwind's utilities, so a utility class put on an
element still wins. That is what makes Tailwind usable here one element at
a time, without converting the stylesheet.
#}
<style>@layer theme, base, app, components, utilities;</style>
<link rel="stylesheet" href="/static/app.css">
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2/dist/htmx.min.js"></script>
{#
Penguin UI (https://www.penguinui.com) is Tailwind + Alpine, and its
components are what this app uses for anything the user has to be told:
ui/alert.html and ui/dialog.html. The focus plugin is what x-trap in the
dialog needs, and it has to load before Alpine itself.
#}
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<style type="text/tailwindcss">
/* Penguin UI's "modern" theme setup: its semantic names, this app's palette. */
@theme {
--color-surface: #ffffff;
--color-surfaceAlt: #f3f5f7;
--color-surfaceDark: #152238;
--color-onSurface: #465267;
--color-onSurfaceStrong: #17202a;
--color-outline: #d9dfe7;
--color-primary: #2563eb;
--color-onPrimary: #ffffff;
--color-danger: #9d342d;
--color-success: #21643a;
}
</style>
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/focus@3/dist/cdn.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js"></script>
<script>
// htmx only swaps 2xx responses. Every form in this app answers a failure
// with a status that says so — 422 for a rejected draft, 403 for a lost
// session, 502 for an unreachable backend — so the markup explaining the
// failure was rendered, returned, and then thrown away, and the page did
// nothing at all. Swap it instead; the response body is the explanation.
document.addEventListener('htmx:beforeSwap', function (event) {
if (event.detail.xhr.status >= 400) {
event.detail.shouldSwap = true;
event.detail.isError = false;
}
});
</script>
{% block head %}{% endblock %}
</head>
<body>