theming done for now

This commit is contained in:
Paul Lützner committed 2026-07-23 16:09:03 +02:00
1 parent 6a4adb3274
commit a947c4aaac
50 files changed
+134 -157

No files matched your search

-18
View File
@@ -1,21 +1,3 @@
import './stimulus_bootstrap.js';
import './styles/app.css';
import '@fortawesome/fontawesome-free/css/all.css';
document.addEventListener('turbo:load', function() {
// User menu toggle
const btn = document.getElementById('user-menu-btn');
const menu = document.getElementById('user-menu');
if (btn && menu) {
btn.addEventListener('click', function() {
menu.classList.toggle('hidden');
});
document.addEventListener('click', function(event) {
if (!btn.contains(event.target) && !menu.contains(event.target)) {
menu.classList.add('hidden');
}
});
}
});
@@ -60,13 +60,9 @@ export default class extends Controller {
highlightActive() {
this.linkTargets.forEach((link) => {
const isActive = window.location.pathname === new URL(link.href).pathname;
link.classList.toggle('bg-blue-50', isActive);
link.classList.toggle('dark:bg-blue-950/40', isActive);
link.classList.toggle('text-blue-700', isActive);
link.classList.toggle('dark:text-blue-400', isActive);
link.classList.toggle('font-medium', isActive);
link.classList.toggle('text-gray-500', !isActive);
link.classList.toggle('dark:text-gray-400', !isActive);
link.classList.toggle('bg-accent-soft', isActive);
link.classList.toggle('text-accent', isActive);
link.classList.toggle('text-ink-muted', !isActive);
});
}
}
@@ -18,14 +18,11 @@ export default class extends Controller {
_activate(panelName) {
this.tabTargets.forEach(tab => {
const isActive = tab.dataset.panel === panelName;
tab.classList.toggle("border-blue-500", isActive);
tab.classList.toggle("text-blue-600", isActive);
tab.classList.toggle("dark:text-blue-400", isActive);
tab.classList.toggle("border-transparent", !isActive);
tab.classList.toggle("text-zinc-500", !isActive);
tab.classList.toggle("dark:text-zinc-400", !isActive);
tab.classList.toggle("hover:text-zinc-700", !isActive);
tab.classList.toggle("dark:hover:text-zinc-200", !isActive);
tab.classList.toggle("border-accent", isActive);
tab.classList.toggle("text-accent", isActive);
tab.classList.toggle("text-ink-muted", !isActive);
tab.classList.toggle("hover:text-ink-soft", !isActive);
});
this.panelTargets.forEach(panel => {
+12 -3
View File
@@ -8,8 +8,7 @@ export default class extends Controller {
resetUrl: String,
};
static targets = ['paneAlpha', 'paneBlur', 'radius', 'scrimAlpha', 'accent', 'importInput', 'uploadInput'];
static targets = ['paneAlpha', 'paneBlur', 'radius', 'scrimAlpha', 'accent', 'theme', 'importInput', 'uploadInput'];
connect() {
this.root = document.documentElement;
this.pending = null;
@@ -34,6 +33,8 @@ export default class extends Controller {
const theme = event.currentTarget.dataset.theme;
const isDark = event.currentTarget.dataset.dark === '1';
this.themeTarget.value = theme;
this.root.dataset.theme = theme;
this.root.classList.toggle('dark', isDark);
@@ -61,7 +62,15 @@ export default class extends Controller {
this.queue();
}
pickBackground() {
pickBackground(event) {
if (event.currentTarget.dataset.appearanceField === 'backgroundPreset') {
const kindInput = this.element.querySelector('[data-appearance-field="backgroundKind"][value="preset"]');
if (kindInput) {
kindInput.checked = true;
}
}
this.queue(0);
}
+9 -11
View File
@@ -278,10 +278,8 @@ export default class extends Controller {
this.fromDropdownTarget.querySelectorAll('button').forEach(b => {
const selected = b.dataset.value === value;
b.classList.toggle('bg-blue-50', selected);
b.classList.toggle('dark:bg-blue-500/10', selected);
b.classList.toggle('text-blue-600', selected);
b.classList.toggle('dark:text-blue-300', selected);
b.classList.toggle('bg-accent-soft', selected);
b.classList.toggle('text-accent', selected);
});
this._closeFromDropdown();
@@ -321,11 +319,11 @@ export default class extends Controller {
const url = this.hasDraftUrlValue ? this.draftUrlValue : form.action;
const status = this.hasSaveStatusTarget ? this.saveStatusTarget : null;
const STATUS_CLASSES = ['text-ink-faint', 'text-danger', 'text-success'];
if (status) {
status.textContent = 'Saving…';
status.classList.remove('text-red-500', 'text-green-600');
status.classList.add('text-gray-400');
status.classList.remove(...STATUS_CLASSES);
status.classList.add('text-ink-faint');
}
try {
@@ -355,8 +353,8 @@ export default class extends Controller {
}
status.textContent = 'Draft saved';
status.classList.remove('text-gray-400', 'text-red-500');
status.classList.add('text-green-600');
status.classList.remove(...STATUS_CLASSES);
status.classList.add('text-success');
}
} else {
throw new Error('Server error');
@@ -364,8 +362,8 @@ export default class extends Controller {
} catch (_) {
if (status) {
status.textContent = 'Failed to save';
status.classList.remove('text-gray-400', 'text-green-600');
status.classList.add('text-red-500');
status.classList.remove(...STATUS_CLASSES);
status.classList.add('text-danger');
}
}
}
@@ -401,10 +401,8 @@ export default class extends Controller {
const capitalized = targetName.charAt(0).toUpperCase() + targetName.slice(1);
if (!this[`has${capitalized}Target`]) { return; }
const target = this[`${targetName}Target`];
target.classList.toggle('bg-gray-200', active);
target.classList.toggle('dark:bg-gray-600', active);
target.classList.toggle('text-gray-900', active);
target.classList.toggle('dark:text-white', active);
target.classList.toggle('bg-raised', active);
target.classList.toggle('text-ink', active);
}
// ── Sync contenteditable → hidden input ───────────────────────────
@@ -11,8 +11,8 @@
import { Controller } from "@hotwired/stimulus";
// Classes applied to the checkbox button in each state
const CB_BASE = "border-gray-400 dark:border-gray-500 bg-white dark:bg-gray-800";
const CB_ACTIVE = "border-blue-600 bg-blue-600 dark:border-blue-500 dark:bg-blue-500";
const CB_BASE = "border-field bg-field";
const CB_ACTIVE = "border-accent bg-accent";
// Base path prefix for all status actions — must match Symfony routing.
// Individual action URLs are built as: STATUS_BASE + "/thread/{id}/{action}"
+4 -4
View File
@@ -154,18 +154,18 @@ export default class extends Controller {
data-query="${this._escape(r)}"
data-action="click->search#selectRecent"
class="group w-full flex items-center gap-2.5 px-3 py-2
text-sm text-gray-700 dark:text-gray-300
hover:bg-gray-50 dark:hover:bg-gray-800
text-sm text-ink-soft
hover:bg-hover
transition-colors text-left"
>
<i class="fa-solid fa-clock-rotate-left text-gray-300 dark:text-gray-600 w-3.5 flex-shrink-0" aria-hidden="true"></i>
<i class="fa-solid fa-clock-rotate-left text-ink-faint w-3.5 flex-shrink-0" aria-hidden="true"></i>
<span class="flex-1 truncate">${this._escape(r)}</span>
<span
role="button"
tabindex="0"
data-action="click->search#removeRecent"
class="opacity-0 group-hover:opacity-100 p-0.5 rounded
text-gray-400 hover:text-gray-600 dark:hover:text-gray-200
text-ink-faint hover:text-ink-soft
transition-opacity"
aria-label="Remove"
>
+2 -3
View File
@@ -1,8 +1,7 @@
import { Controller } from "@hotwired/stimulus";
const ACTIVE_CLASSES = ["bg-blue-50", "dark:bg-blue-950/40", "text-blue-700", "dark:text-blue-400", "font-medium"];
const INACTIVE_CLASSES = ["text-gray-600", "dark:text-gray-400", "hover:bg-gray-100", "dark:hover:bg-gray-800"];
const ACTIVE_CLASSES = ["bg-accent-soft", "text-accent", "font-medium"];
const INACTIVE_CLASSES = ["text-ink-muted", "hover:bg-hover"];
export default class extends Controller {
static targets = ["link"];
@@ -0,0 +1,25 @@
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['menu'];
connect() {
this.onDocumentClick = this.onDocumentClick.bind(this);
document.addEventListener('click', this.onDocumentClick);
}
disconnect() {
document.removeEventListener('click', this.onDocumentClick);
}
toggle(event) {
event.stopPropagation();
this.menuTarget.classList.toggle('hidden');
}
onDocumentClick(event) {
if (false === this.element.contains(event.target)) {
this.menuTarget.classList.add('hidden');
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

+8 -31
View File
@@ -6,35 +6,12 @@ FILES=$(find templates -name '*.html.twig')
sweep() {
perl -0777 -pi -e "s{(?<![\\w:./-])$1}{$2}g" $FILES
}
# ── Muted → strong hover pairs ──────────────────────────────────────────────
sweep 'text-zinc-300\s+hover:text-zinc-500\s+dark:text-zinc-600\s+dark:hover:text-zinc-400' 'text-ink-faint hover:text-ink-muted'
sweep 'text-ink-muted\s+hover:text-gray-800\s+dark:hover:text-white' 'text-ink-muted hover:text-ink'
sweep 'hover:text-zinc-200\s+dark:hover:text-zinc-300' 'hover:text-ink'
sweep 'hover:text-blue-600\s+dark:hover:text-blue-300' 'hover:text-accent'
sweep 'hover:text-red-500\s+dark:hover:text-red-400' 'hover:text-danger'
sweep 'text-zinc-900\s+dark:text-zinc-300' 'text-ink'
# ── Hovers ──────────────────────────────────────────────────────────────────
sweep 'hover:bg-gray-100\s+dark:hover:bg-white/10' 'hover:bg-hover'
sweep 'hover:bg-zinc-50\s+dark:hover:bg-zinc-700' 'hover:bg-hover'
sweep 'hover:bg-white/70\s+dark:hover:bg-white/10' 'hover:bg-hover'
sweep 'focus:bg-white\s+dark:focus:bg-gray-700' 'focus:bg-field'
# ── Borders ─────────────────────────────────────────────────────────────────
sweep 'border-gray-100/80\s+dark:border-white/\[0\.06\]' 'border-line'
# ── Status dots (bg-line is too faint at 0.06 — use ink-faint) ──────────────
sweep 'bg-zinc-300 dark:bg-zinc-600' 'bg-ink-faint'
sweep 'bg-gray-300 dark:bg-gray-700' 'bg-ink-faint'
# ── Toast (inverted surface) ────────────────────────────────────────────────
sweep 'bg-zinc-900\s+dark:bg-zinc-100\s+text-zinc-100\s+dark:text-zinc-900' 'bg-inverse text-inverse-ink'
# ── Search filter pill ──────────────────────────────────────────────────────
sweep 'bg-blue-50\s+dark:bg-blue-950/40\s+text-blue-700\s+dark:text-blue-300\s*\n?\s*border\s+border-blue-200/60\s+dark:border-blue-700/40' 'bg-accent-soft text-accent border border-accent/20'
# ── Avatar button ───────────────────────────────────────────────────────────
sweep 'bg-blue-600\s+hover:ring-2\s+hover:ring-blue-400\s+hover:ring-offset-1\s+dark:hover:ring-offset-gray-900' 'bg-accent hover:ring-2 hover:ring-accent/60 hover:ring-offset-1 ring-offset-surface'
sweep 'bg-blue-600(?!\s+hover)' 'bg-accent'
sweep 'text-blue-600\s+border-blue-600' 'text-accent border-accent'
sweep 'focus:ring-blue-500' 'focus:ring-accent'
sweep 'focus-visible:ring-blue-500' 'focus-visible:ring-accent'
sweep 'hover:border-blue-500' 'hover:border-accent'
sweep 'focus:border-blue-500' 'focus:border-accent'
sweep 'text-blue-500' 'text-accent'
sweep 'bg-blue-500(?![/\w-])' 'bg-accent'
echo "Done. Now: git diff"
+2 -2
View File
@@ -1508,8 +1508,8 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
* }
* @psalm-type MercureConfig = array{
* hubs?: array<string, array{ // Default: []
* url?: scalar|Param|null, // URL of the hub's publish endpoint
* public_url?: scalar|Param|null, // URL of the hub's public endpoint // Default: null
* url?: scalar|Param|null, // URL of the hub's publish endpoint // Default: null
* public_url?: scalar|Param|null, // URL of the hub's public endpoint
* jwt?: string|array{ // JSON Web Token configuration.
* value?: scalar|Param|null, // JSON Web Token to use to publish to this hub.
* provider?: scalar|Param|null, // The ID of a service to call to provide the JSON Web Token.
+8 -8
View File
@@ -172,36 +172,36 @@ final class Appearance
}
if (true === isset($data['paneAlpha'])) {
$this->setPaneAlpha($data['paneAlpha']);
$this->setPaneAlpha(floatval($data['paneAlpha']));
}
if (true === isset($data['paneBlur'])) {
$this->setPaneBlur($data['paneBlur']);
$this->setPaneBlur(intval($data['paneBlur']));
}
if (true === isset($data['radius'])) {
$this->setRadius($data['radius']);
$this->setRadius(floatval($data['radius']));
}
if (true === isset($data['density'])) {
$this->setDensity(Density::tryFrom((string) $data['density']) ?? $this->density);
$this->setDensity(Density::tryFrom($data['density']) ?? $this->density);
}
if (true === isset($data['backgroundKind'])) {
$this->setBackgroundKind(BackgroundKind::tryFrom((string) $data['backgroundKind']) ?? $this->backgroundKind);
$this->setBackgroundKind(BackgroundKind::tryFrom($data['backgroundKind']) ?? $this->backgroundKind);
}
if (true === array_key_exists('backgroundPreset', $data)) {
$this->setBackgroundPreset(BackgroundPreset::tryFrom((string) $data['backgroundPreset']));
$this->setBackgroundPreset(BackgroundPreset::tryFrom( $data['backgroundPreset']));
}
if (true === array_key_exists('backgroundSolid', $data)) {
$solid = (string) $data['backgroundSolid'];
$solid = $data['backgroundSolid'];
$this->setBackgroundSolid(1 === preg_match('/^#[0-9a-fA-F]{6}$/', $solid) ? strtolower($solid) : null);
}
if (true === isset($data['scrimAlpha'])) {
$this->setScrimAlpha((float) $data['scrimAlpha']);
$this->setScrimAlpha(floatval($data['scrimAlpha']));
}
return $this;
+2 -2
View File
@@ -48,13 +48,13 @@ Pagination variables expected from the controller (all optional, fallback to 0/1
{% include '_partials/_sidebar.html.twig' with { _drawerMode: true } %}
</div>
<div class="flex h-full flex-col p-3 gap-3">
<div class="flex h-full flex-col p-gutter gap-gutter">
{# Full-width topbar — passes burger button context #}
{% include '_partials/_topbar.html.twig' with { _showBurger: true } %}
{# Sidebar + content #}
<div class="flex flex-1 gap-3 overflow-hidden">
<div class="flex flex-1 gap-gutter overflow-hidden">
{# Sidebar — desktop only (hidden on mobile, shown in drawer) #}
<div class="hidden md:flex">
+2 -9
View File
@@ -7,10 +7,9 @@
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 32 32%22><text y=%221em%22 font-size=%2224%22>✉️</text></svg>">
{# Must be first thing in <head> to avoid flash of wrong theme #}
<script>
if (localStorage.getItem('theme') === 'dark' ||
(!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
if (document.documentElement.dataset.theme === 'system' &&
window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
}
</script>
@@ -42,11 +41,5 @@
{% include '_partials/_modal.html.twig' %}
<turbo-frame id="compose_dock" class="fixed bottom-4 right-6 flex items-end gap-3"></turbo-frame>
<div id="toast-region" class="fixed bottom-4 left-4 z-[60] flex flex-col gap-2 items-end"></div>
<script>
if (document.documentElement.dataset.theme === 'system' &&
window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
}
</script>
</body>
</html>
@@ -33,7 +33,7 @@
px-3 text-sm text-ink
placeholder:text-ink-faint
shadow-sm shadow-zinc-950/5
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent
focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent
transition-colors duration-100
disabled:opacity-50 disabled:cursor-not-allowed
' ~ (attr.class ?? '')
@@ -55,7 +55,7 @@
px-3 text-sm text-ink
placeholder:text-ink-faint
shadow-sm shadow-zinc-950/5
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent
focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent
transition-colors duration-100
disabled:opacity-50 disabled:cursor-not-allowed
[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none
@@ -74,7 +74,7 @@
px-3 py-2 text-sm text-ink
placeholder:text-ink-faint
shadow-sm shadow-zinc-950/5
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent
focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent
resize-y transition-colors duration-100
disabled:opacity-50 disabled:cursor-not-allowed
' ~ (attr.class ?? ''),
@@ -90,7 +90,7 @@
bg-field
pl-3 pr-8 text-sm text-ink
shadow-sm shadow-zinc-950/5 appearance-none
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent
focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent
transition-colors duration-100
cursor-pointer
disabled:opacity-50 disabled:cursor-not-allowed
@@ -125,7 +125,7 @@
class: 'size-4 rounded border-field
text-accent
bg-field
focus:ring-2 focus:ring-blue-500 focus:ring-offset-0
focus:ring-2 focus:ring-accent focus:ring-offset-0
cursor-pointer
' ~ (attr.class ?? '')
}) %}
+2 -2
View File
@@ -121,8 +121,8 @@ The button itself carries `group` and `relative`.
border border-field
bg-field
cursor-pointer transition-colors duration-100
hover:border-blue-500 focus-visible:outline-none
focus-visible:ring-2 focus-visible:ring-blue-500"
hover:border-accent focus-visible:outline-none
focus-visible:ring-2 focus-visible:ring-accent"
aria-label="{{ 'toolbar.select_all'|trans }}"
>
{# Checkmark — shown when all selected #}
+1 -1
View File
@@ -52,7 +52,7 @@
text-ink-faint
hover:text-ink
hover:bg-hover
transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500
transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent
"
>
<i class="fa-solid fa-xmark text-sm" aria-hidden="true"></i>
+2 -2
View File
@@ -44,7 +44,7 @@
bg-field
border border-field
hover:bg-hover
focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-1
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1
transition-colors duration-100"
>{{ cancel_label }}</button>
@@ -56,7 +56,7 @@
{% if danger %}
bg-red-600 hover:bg-red-700 active:bg-red-800 focus-visible:ring-red-500
{% else %}
bg-accent hover:bg-accent-strong active:bg-blue-800 focus-visible:ring-blue-500
bg-accent hover:bg-accent-strong active:bg-blue-800 focus-visible:ring-accent
{% endif %}"
>{{ submit_label }}</button>
</div>
+4 -4
View File
@@ -1,6 +1,6 @@
{% macro unread_badge(count) %}
{% if count > 0 %}
<span class="text-xs font-semibold px-1.5 py-0.5 rounded-full bg-blue-600 text-white">
<span class="text-xs font-semibold px-1.5 py-0.5 rounded-full bg-accent text-white">
{{ count }}
</span>
{% endif %}
@@ -15,7 +15,7 @@
'amber': 'bg-amber-500',
'green': 'bg-green-500',
'teal': 'bg-teal-500',
'blue': 'bg-blue-500',
'blue': 'bg-accent',
'violet': 'bg-violet-500',
'pink': 'bg-pink-500',
}[color ?? 'gray'] ?? 'bg-ink-faint' }}"
@@ -74,14 +74,14 @@ When true, nav links also dispatch a close action to the parent sidebar-drawer c
<aside id="{{ _drawerMode is defined and _drawerMode ? 'sidebar-drawer-inner' : 'sidebar' }}"
{% if not (_drawerMode is defined and _drawerMode) %}data-turbo-permanent{% endif %}
data-controller="sidebar"
class="flex flex-col w-56 h-full flex-shrink-0 bg-surface rounded-pane shadow-pop border border-line">
class="flex flex-col w-56 h-full flex-shrink-0 pane">
{# Compose #}
<div class="px-3 py-3 border-b border-line">
<a href="{{ path('app_compose_new') }}"
data-turbo-frame="compose_dock"
data-action="{{ _drawerClose }}"
class="w-full flex items-center justify-center gap-2 bg-accent hover:bg-accent-strong text-white text-sm font-medium rounded-lg px-3 py-2 transition-colors">
class="w-full flex items-center justify-center gap-2 bg-accent hover:bg-accent-strong text-white text-sm font-medium rounded-lg px-3 py-row transition-colors">
<i class="fa-solid fa-plus w-4 h-4" aria-hidden="true"></i>
{{ 'sidebar.compose'|trans }}
</a>
+1 -1
View File
@@ -20,7 +20,7 @@ Variables:
'amber': 'bg-amber-500',
'green': 'bg-green-500',
'teal': 'bg-teal-500',
'blue': 'bg-blue-500',
'blue': 'bg-accent',
'violet': 'bg-violet-500',
'pink': 'bg-pink-500',
}[chipLabel.color ?? 'gray'] ?? 'bg-ink-faint' }}"
+2 -2
View File
@@ -54,7 +54,7 @@
></a>
<div
class="pointer-events-auto flex items-center gap-3 pl-3 pr-4 py-2.5 cursor-pointer transition-colors
class="pointer-events-auto flex items-center gap-3 pl-3 pr-4 py-row cursor-pointer transition-colors
{{ unread ? 'bg-raised' : 'bg-transparent' }}
hover:bg-hover"
>
@@ -63,7 +63,7 @@
type="checkbox"
data-action="change->message-row#toggleSelect"
data-thread-select value="{{ rowId }}"
class="z-10 w-4 h-4 rounded border-field text-blue-600 focus:ring-blue-500 focus:ring-offset-0 cursor-pointer flex-shrink-0"
class="z-10 w-4 h-4 rounded border-field accent-accent focus:ring-accent focus:ring-offset-0 cursor-pointer flex-shrink-0"
aria-label="{{ 'thread_row.select'|trans({'%subject%': subject}) }}"
>
+4 -3
View File
@@ -58,7 +58,7 @@
border border-transparent rounded-xl
text-ink
placeholder:text-ink-faint
focus:outline-none focus:ring-2 focus:ring-blue-500
focus:outline-none focus:ring-2 focus:ring-accent
focus:bg-field
transition-colors"
>
@@ -89,15 +89,16 @@
{# Right actions #}
<div class="flex items-center gap-1 flex-shrink-0">
{# User menu #}
<div class="relative ml-1">
<div class="relative ml-1" data-controller="user-menu">
<button id="user-menu-btn"
data-action="click->user-menu#toggle"
class="flex cursor-pointer items-center justify-center w-8 h-8 rounded-full bg-accent hover:ring-2 hover:ring-accent/60 hover:ring-offset-1 ring-offset-surface text-white text-xs font-semibold transition-all"
aria-label="{{ 'header.user_menu.label'|trans({ '%email%': app.user.email }) }}"
title="{{ app.user.email }}">
{{ app.user.email | first | upper }}
</button>
<div id="user-menu" class="hidden absolute right-0 mt-2 w-56 bg-surface border border-line rounded-xl shadow-lg py-1 z-[200]">
<div id="user-menu" data-user-menu-target="menu" class="hidden absolute right-0 mt-2 w-56 bg-surface border border-line rounded-xl shadow-lg py-1 z-[200]">
<div class="px-4 py-2.5 border-b border-line">
<p class="text-xs text-gray-400">{{ 'header.user_menu.signed_in_as'|trans }}</p>
<p class="text-sm font-medium text-ink truncate">{{ app.user.email }}</p>
+4 -4
View File
@@ -38,7 +38,7 @@
<div role="alert" class="mx-5 mt-5 flex items-start gap-2.5 rounded-xl
alert-danger
px-3.5 py-3 text-sm text-danger">
<i class="fa-solid fa-circle-exclamation mt-0.5 shrink-0 text-red-500/80" aria-hidden="true"></i>
<i class="fa-solid fa-circle-exclamation mt-0.5 shrink-0 text-danger opacity-80" aria-hidden="true"></i>
<div class="space-y-0.5">
{% for error in form.vars.errors %}<p class="leading-snug">{{ error.message }}</p>{% endfor %}
</div>
@@ -96,7 +96,7 @@
<div class="flex items-start gap-3 rounded-xl
alert-info
px-4 py-3 text-sm text-accent">
<i class="fa-solid fa-circle-info mt-0.5 shrink-0 text-blue-500/70" aria-hidden="true"></i>
<i class="fa-solid fa-circle-info mt-0.5 shrink-0 text-accent/70" aria-hidden="true"></i>
<p>{{ 'account.oauth.info'|trans }}</p>
</div>
@@ -161,7 +161,7 @@
bg-sunken
border border-line
hover:bg-hover
focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-1
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1
transition-colors duration-100 cursor-pointer"
>{{ 'form.cancel'|trans }}</button>
@@ -170,7 +170,7 @@
data-account-form-target="submitBtn"
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-white
bg-blue-600 hover:bg-blue-500 active:bg-blue-700
focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-1
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1
transition-colors duration-100 cursor-pointer"
>{{ 'account.add_title'|trans }}</button>
</div>
+2 -2
View File
@@ -20,11 +20,11 @@
{% include '_partials/_sidebar.html.twig' with { _drawerMode: true } %}
</div>
<div class="flex h-full flex-col p-3 gap-3">
<div class="flex h-full flex-col p-gutter gap-gutter">
{% include '_partials/_topbar.html.twig' with { _showBurger: true } %}
<div class="flex flex-1 gap-3 overflow-hidden">
<div class="flex flex-1 gap-gutter overflow-hidden">
{# Sidebar — desktop #}
<div class="hidden md:flex">
+2 -2
View File
@@ -242,7 +242,7 @@
hover:bg-hover cursor-pointer relative">
<span class="font-semibold">A</span>
<span data-compose-toolbar-target="colorSwatch"
class="block w-3.5 h-[3px] bg-blue-500 rounded-sm"></span>
class="block w-3.5 h-[3px] bg-accent rounded-sm"></span>
<input type="color" data-action="input->compose-toolbar#changeColor"
class="absolute opacity-0 w-0 h-0 pointer-events-none" tabindex="-1">
</label>
@@ -286,7 +286,7 @@
{# Action bar #}
<div class="flex items-center gap-1">
<div class="flex items-center rounded-full overflow-hidden bg-blue-600 mr-2 shrink-0">
<div class="flex items-center rounded-full overflow-hidden bg-accent mr-2 shrink-0">
<button type="submit"
class="text-white text-sm font-semibold px-4 py-1.5 hover:bg-white/10 transition-colors">
Send
+4 -4
View File
@@ -8,7 +8,7 @@ account form). Frosted-glass design language, zinc form fields, Tailwind only.
{{ form_label(form.name, null, { label_attr: { class: 'block text-xs font-medium text-ink-muted mb-1' } }) }}
{{ form_widget(form.name, { attr: {
class: 'w-full rounded-lg bg-sunken border border-transparent
focus:border-blue-500 focus:ring-0 text-sm px-3 py-2
focus:border-accent focus:ring-0 text-sm px-3 py-2
text-ink placeholder-gray-400'
} }) }}
{{ form_errors(form.name) }}
@@ -18,7 +18,7 @@ account form). Frosted-glass design language, zinc form fields, Tailwind only.
{{ form_label(form.account, null, { label_attr: { class: 'block text-xs font-medium text-ink-muted mb-1' } }) }}
{{ form_widget(form.account, { attr: {
class: 'w-full rounded-lg bg-sunken border border-transparent
focus:border-blue-500 focus:ring-0 text-sm px-3 py-2
focus:border-accent focus:ring-0 text-sm px-3 py-2
text-ink'
} }) }}
{{ form_errors(form.account) }}
@@ -28,7 +28,7 @@ account form). Frosted-glass design language, zinc form fields, Tailwind only.
{{ form_label(form.parent, null, { label_attr: { class: 'block text-xs font-medium text-ink-muted mb-1' } }) }}
{{ form_widget(form.parent, { attr: {
class: 'w-full rounded-lg bg-sunken border border-transparent
focus:border-blue-500 focus:ring-0 text-sm px-3 py-2
focus:border-accent focus:ring-0 text-sm px-3 py-2
text-ink'
} }) }}
{{ form_errors(form.parent) }}
@@ -38,7 +38,7 @@ account form). Frosted-glass design language, zinc form fields, Tailwind only.
{{ form_label(form.color, null, { label_attr: { class: 'block text-xs font-medium text-ink-muted mb-1' } }) }}
{{ form_widget(form.color, { attr: {
class: 'w-full rounded-lg bg-sunken border border-transparent
focus:border-blue-500 focus:ring-0 text-sm px-3 py-2
focus:border-accent focus:ring-0 text-sm px-3 py-2
text-ink'
} }) }}
{{ form_errors(form.color) }}
+1 -1
View File
@@ -17,7 +17,7 @@
{% if not label.isSystem %}
{% set _unread = sidebarCounts.forLabel(label) %}
{% if _unread > 0 %}
<span class="text-xs font-semibold px-1.5 py-0.5 rounded-full bg-blue-600 text-white">
<span class="text-xs font-semibold px-1.5 py-0.5 rounded-full bg-accent text-white">
{{ _unread }}
</span>
{% endif %}
+2 -2
View File
@@ -16,11 +16,11 @@
<a
href="{{ path('app_mail_inbox', {tab: tabCase.value}) }}"
data-turbo-frame="inbox-list-frame"
class="px-4 py-3 font-medium border-b-2 -mb-px transition-colors {{ isActive ? 'text-blue-600 border-blue-600' : 'text-ink-muted hover:text-gray-700 border-transparent hover:border-gray-300' }}"
class="px-4 py-3 font-medium border-b-2 -mb-px transition-colors {{ isActive ? 'text-accent border-accent' : 'text-ink-muted hover:text-gray-700 border-transparent hover:border-gray-300' }}"
>
{{ ('tabs.' ~ tabCase.value)|trans }}
{% if unreadCount > 0 %}
<span class="ml-1 text-xs {{ isActive ? 'text-blue-600' : 'text-gray-400' }}">{{ unreadCount }}</span>
<span class="ml-1 text-xs {{ isActive ? 'text-accent opacity-70' : 'text-gray-400' }}">{{ unreadCount }}</span>
{% endif %}
</a>
{% endfor %}
+4 -4
View File
@@ -10,7 +10,7 @@
{# Logo #}
<div class="flex flex-col items-center mb-8">
<div class="flex items-center gap-2 mb-2">
<i class="fa-solid fa-envelope text-blue-600 text-2xl" aria-hidden="true"></i>
<i class="fa-solid fa-envelope text-accent text-2xl" aria-hidden="true"></i>
<span class="text-xl font-semibold text-ink">{{ 'app.name'|trans }}</span>
</div>
<p class="text-sm text-ink-muted">{{ 'login.tagline'|trans }}</p>
@@ -41,7 +41,7 @@
autocomplete="email"
autofocus
required
class="w-full px-3 py-2 text-sm rounded-lg border border-field bg-field text-ink placeholder:text-ink-faint focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
class="w-full px-3 py-2 text-sm rounded-lg border border-field bg-field text-ink placeholder:text-ink-faint focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-colors"
placeholder="you@example.com"
>
</div>
@@ -62,7 +62,7 @@
autocomplete="current-password"
required
value="{{ 'APP_DEV_USER_PASSWORD'|get_env }}"
class="w-full px-3 py-2 text-sm rounded-lg border border-field bg-field text-ink placeholder:text-ink-faint focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors"
class="w-full px-3 py-2 text-sm rounded-lg border border-field bg-field text-ink placeholder:text-ink-faint focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent transition-colors"
placeholder="••••••••"
>
</div>
@@ -72,7 +72,7 @@
<button
type="submit"
class="mt-6 w-full bg-accent hover:bg-accent-strong text-white text-sm font-medium py-2 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 ring-offset-surface"
class="mt-6 w-full bg-accent hover:bg-accent-strong text-white text-sm font-medium py-2 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 ring-offset-surface"
>
{{ 'login.form.submit'|trans }}
</button>
+2 -2
View File
@@ -30,7 +30,7 @@
</button>
{% endfor %}
</div>
<input type="hidden" data-appearance-field="theme" value="{{ a.theme.value }}">
<input type="hidden" data-appearance-target="theme" data-appearance-field="theme" value="{{ a.theme.value }}">
</section>
{# ── Glass ─────────────────────────────────────────────────────────── #}
@@ -109,7 +109,7 @@
<div class="grid grid-cols-3 sm:grid-cols-5 gap-3 mb-4">
<label class="cursor-pointer">
<input type="radio" name="backgroundKind" class="peer sr-only" value="theme"
<input type="radio" name="backgroundKind" class="sr-only" value="preset"
data-appearance-field="backgroundKind"
data-action="change->appearance#pickBackground"
{{ a.backgroundKind.value == 'theme' ? 'checked' : '' }}>
+2 -2
View File
@@ -39,7 +39,7 @@ Variables:
'amber': 'bg-amber-500',
'green': 'bg-green-500',
'teal': 'bg-teal-500',
'blue': 'bg-blue-500',
'blue': 'bg-accent',
'violet': 'bg-violet-500',
'pink': 'bg-pink-500',
}[label.color ?? 'gray'] ?? 'bg-ink-faint' }}"
@@ -65,7 +65,7 @@ Variables:
aria-label="{{ label.isVisible ? 'settings.labels.hide'|trans : 'settings.labels.show'|trans }}"
title="{{ label.isVisible ? 'settings.labels.hide'|trans : 'settings.labels.show'|trans }}"
>
<i class="fa-solid {{ label.isVisible ? 'fa-eye text-blue-500' : 'fa-eye-slash' }} text-sm" aria-hidden="true"></i>
<i class="fa-solid {{ label.isVisible ? 'fa-eye text-accent' : 'fa-eye-slash' }} text-sm" aria-hidden="true"></i>
</button>
</form>
</li>
+2 -2
View File
@@ -17,11 +17,11 @@
{% include '_partials/_sidebar.html.twig' with { _drawerMode: true } %}
</div>
<div class="flex h-full flex-col p-3 gap-3">
<div class="flex h-full flex-col p-gutter gap-gutter">
{% include '_partials/_topbar.html.twig' with { _showBurger: true } %}
<div class="flex flex-1 gap-3 overflow-hidden">
<div class="flex flex-1 gap-gutter overflow-hidden">
{# Sidebar — desktop #}
<div class="hidden md:flex">
+2
View File
@@ -134,6 +134,7 @@ tabs:
promotions: Promotions
updates: Updates
social: Social
forums: Forums
inbox:
empty: No messages in this tab.
@@ -156,6 +157,7 @@ trash:
thread_row:
no_subject: (no subject)
select: Select
message_count: "({ count })"
star: Star this message
unstar: Unstar this message