d662b50925
Big batch — every secondary page now wears the same glass-card hero that landed on Providers earlier: - notification-trackers, tracking-configs, template-configs - command-trackers, command-configs, command-template-configs - targets (with active-tab title), actions - bots (telegram / email / matrix tabs) - settings, settings/backup, users Each page picks an italic-em emphasis word, an editorial crumb (e.g. 'Routing · Notification', 'Operators · Bots', 'System · Maintenance'), a count meter, and entity-specific status pills derived from live data: 'X armed / Y paused' for trackers and actions, 'X types' for configs/templates, 'X channels' or '$N receivers' for targets. Other changes in this commit: - Button.svelte: redesigned. Primary variant becomes a real Aurora CTA — gradient lavender → orchid pill, 40px tall md / 34px sm, inset highlight, lift + glow on hover. Secondary, danger, ghost variants reworked to match. The 'Add <Type>' button on every page now reads as the page's primary action instead of a flat lavender rectangle. - JinjaEditor: overrode oneDark's hardcoded background with !important so the editor surface picks up var(--color-input-bg). Gutters / scroller / selection / autocomplete tooltip all match Aurora glass tokens now. Template editors stop visually clashing with the surrounding panel. - Aurora pulse dot: rewritten as a self-contained box-shadow glow pulse (no transform, no pseudo-element). The dot's bounding box is now stable so ancestors with overflow:hidden can never clip the visible dot — only the (decorative) outer glow halo. Fixes the 'half-moon clipping' on the dashboard 'On watch' deck. - topbar-action.svelte.ts left in tree but unused (topbar CTA was reverted per your call). Will clean up in a later commit. - Form input baseline styling moved into app.css (rounded 0.625rem, glass background, hover/focus rings) so untouched filter inputs on the per-type pages stop looking out of place. i18n: emphasis / countLabel / armed / paused / receiver / receivers / channelsCount keys added across en + ru. Build clean: 0 errors, 61 pre-existing a11y warnings unchanged.
121 lines
2.9 KiB
Svelte
121 lines
2.9 KiB
Svelte
<script lang="ts">
|
|
import type { Snippet } from 'svelte';
|
|
|
|
let {
|
|
variant = 'primary',
|
|
size = 'md',
|
|
disabled = false,
|
|
type = 'button',
|
|
href,
|
|
onclick,
|
|
children,
|
|
class: extraClass = '',
|
|
}: {
|
|
variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
|
|
size?: 'sm' | 'md';
|
|
disabled?: boolean;
|
|
type?: 'button' | 'submit';
|
|
href?: string;
|
|
onclick?: (e: MouseEvent) => void;
|
|
children: Snippet;
|
|
class?: string;
|
|
} = $props();
|
|
|
|
const baseClasses = 'aurora-btn inline-flex items-center justify-center gap-2 font-medium transition-all disabled:opacity-50 disabled:pointer-events-none';
|
|
const sizeClasses: Record<string, string> = {
|
|
sm: 'aurora-btn--sm',
|
|
md: 'aurora-btn--md',
|
|
};
|
|
const variantClasses: Record<string, string> = {
|
|
primary: 'btn-primary',
|
|
secondary: 'btn-secondary',
|
|
danger: 'btn-danger',
|
|
ghost: 'btn-ghost',
|
|
};
|
|
|
|
const classes = $derived(
|
|
`${baseClasses} ${sizeClasses[size]} ${variantClasses[variant]} ${extraClass}`.trim()
|
|
);
|
|
</script>
|
|
|
|
{#if href && !disabled}
|
|
<a {href} class={classes} onclick={onclick}>
|
|
{@render children()}
|
|
</a>
|
|
{:else}
|
|
<button {type} {disabled} class={classes} onclick={onclick}>
|
|
{@render children()}
|
|
</button>
|
|
{/if}
|
|
|
|
<style>
|
|
.aurora-btn {
|
|
border-radius: 12px;
|
|
letter-spacing: -0.005em;
|
|
cursor: pointer;
|
|
font-family: inherit;
|
|
white-space: nowrap;
|
|
}
|
|
.aurora-btn--sm {
|
|
padding: 0 0.95rem;
|
|
height: 34px;
|
|
font-size: 0.82rem;
|
|
}
|
|
.aurora-btn--md {
|
|
padding: 0 1.15rem;
|
|
height: 40px;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
/* Primary — gradient lavender→orchid pill, the page's main CTA. */
|
|
.btn-primary {
|
|
background: linear-gradient(135deg, var(--color-primary), var(--color-orchid));
|
|
color: white;
|
|
border: 0;
|
|
box-shadow:
|
|
0 6px 20px -8px var(--color-glow-strong),
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.35);
|
|
font-weight: 600;
|
|
}
|
|
.btn-primary:hover:not(:disabled) {
|
|
transform: translateY(-1px);
|
|
box-shadow:
|
|
0 10px 28px -10px var(--color-glow-strong),
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.4);
|
|
}
|
|
.btn-primary:active:not(:disabled) { transform: translateY(0); }
|
|
|
|
.btn-secondary {
|
|
background: var(--color-glass-strong);
|
|
color: var(--color-foreground);
|
|
border: 1px solid var(--color-rule-strong);
|
|
}
|
|
.btn-secondary:hover:not(:disabled) {
|
|
background: var(--color-glass-elev);
|
|
border-color: var(--color-rule-strong);
|
|
}
|
|
|
|
.btn-danger {
|
|
background: var(--color-error-fg);
|
|
color: white;
|
|
border: 0;
|
|
font-weight: 600;
|
|
box-shadow: 0 6px 20px -8px color-mix(in srgb, var(--color-error-fg) 50%, transparent);
|
|
}
|
|
.btn-danger:hover:not(:disabled) {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 10px 28px -10px color-mix(in srgb, var(--color-error-fg) 60%, transparent);
|
|
}
|
|
|
|
.btn-ghost {
|
|
background: transparent;
|
|
color: var(--color-muted-foreground);
|
|
border: 1px solid transparent;
|
|
}
|
|
.btn-ghost:hover:not(:disabled) {
|
|
background: var(--color-glass-strong);
|
|
color: var(--color-foreground);
|
|
border-color: var(--color-border);
|
|
}
|
|
</style>
|