Files
beaver-plugin-obsidian/src/tailwind.css
T
hh a04ad0094f fix(css): an icon-only grid button centres its icon again
Obsidian styles every `button` with `justify-content: center`, so the reset
answers with `flex-start` - which also lands on a grid button and overrides
the inline half of its `place-items: center`. The rail's connection dot came
out pinned 12px left of centre inside its own hit area.
2026-09-05 00:28:50 +02:00

489 lines
14 KiB
CSS

@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/utilities.css" layer(utilities) important;
@import "../../beaver-gateway/ui/src/lib/panel/panel.css";
@source "./";
@source "../../beaver-gateway/ui/src/lib";
@custom-variant dark (&:where(.theme-dark, .theme-dark *));
/* The panel's tokens are Obsidian's own variables, exactly as beaver-calendar
maps them onto .bcal-root: the theme, the accent, the font and the radii
come from the app and the user's theme. The msos palette never enters. */
.beaver-root {
--background: var(--background-primary);
--foreground: var(--text-normal);
--card: var(--background-primary-alt);
--card-foreground: var(--text-normal);
--popover: var(--background-secondary);
--popover-foreground: var(--text-normal);
--primary: var(--color-accent);
--primary-foreground: var(--text-on-accent);
--secondary: var(--background-modifier-hover);
--secondary-foreground: var(--text-normal);
--muted: var(--background-modifier-hover);
--muted-foreground: var(--text-muted);
--accent: var(--background-modifier-hover);
--accent-foreground: var(--text-normal);
--destructive: var(--text-error);
--destructive-foreground: var(--text-on-accent);
--border: var(--background-modifier-border);
--input: var(--background-modifier-border);
--ring: var(--color-accent);
--icon: var(--text-muted);
--signal: var(--color-accent);
--link: var(--link-color, var(--text-accent));
--note: oklch(0.52 0.13 78);
--warn: oklch(0.55 0.13 75);
--status-new: var(--color-accent);
--status-done: oklch(0.55 0.14 155);
--status-skip: var(--text-faint);
--status-reply: oklch(0.55 0.14 235);
--status-snooze: oklch(0.66 0.13 75);
--status-meeting: oklch(0.5 0.2 300);
--status-work: oklch(0.55 0.13 195);
--sidebar: var(--background-secondary);
--sidebar-accent: var(--background-modifier-hover);
--rack: var(--background-secondary);
--strip: var(--background-primary);
--attention: oklch(0.72 0.16 72);
--attention-foreground: oklch(0.5 0.14 70);
--shadow-lift:
0 6px 16px -10px rgb(0 0 0 / 0.35), 0 1px 2px rgb(0 0 0 / 0.08);
--shadow-float:
0 20px 50px -20px rgb(0 0 0 / 0.5), 0 2px 6px rgb(0 0 0 / 0.1);
--radius: 0.45rem;
}
.theme-dark .beaver-root {
--attention: oklch(0.8 0.15 75);
--attention-foreground: oklch(0.85 0.14 78);
--strip: var(--background-primary-alt);
--note: oklch(0.84 0.14 88);
--warn: oklch(0.8 0.13 75);
--status-done: oklch(0.74 0.14 155);
--status-reply: oklch(0.72 0.13 235);
--status-snooze: oklch(0.8 0.13 75);
--status-meeting: oklch(0.72 0.16 300);
--status-work: oklch(0.75 0.12 195);
}
@theme inline {
--font-sans: var(--font-interface);
--text-xs: 0.75rem;
--text-sm: 0.8125rem;
--text-base: 0.875rem;
--text-lg: 1rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--color-icon: var(--icon);
--color-signal: var(--signal);
--color-note: var(--note);
--color-sidebar: var(--sidebar);
--color-sidebar-accent: var(--sidebar-accent);
--color-rack: var(--rack);
--color-strip: var(--strip);
--color-attention: var(--attention);
--color-attention-foreground: var(--attention-foreground);
--shadow-lift: var(--shadow-lift);
--shadow-float: var(--shadow-float);
--color-status-new: var(--status-new);
--color-status-done: var(--status-done);
--color-status-skip: var(--status-skip);
--color-status-reply: var(--status-reply);
--color-status-snooze: var(--status-snooze);
--color-status-meeting: var(--status-meeting);
--color-status-work: var(--status-work);
--color-ring: var(--ring);
--color-input: var(--input);
--color-border: var(--border);
--color-destructive-foreground: var(--destructive-foreground);
--color-destructive: var(--destructive);
--color-accent-foreground: var(--accent-foreground);
--color-accent: var(--accent);
--color-muted-foreground: var(--muted-foreground);
--color-muted: var(--muted);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary: var(--secondary);
--color-primary-foreground: var(--primary-foreground);
--color-primary: var(--primary);
--color-popover-foreground: var(--popover-foreground);
--color-popover: var(--popover);
--color-card-foreground: var(--card-foreground);
--color-card: var(--card);
--color-foreground: var(--foreground);
--color-background: var(--background);
--radius-sm: calc(var(--radius) * 0.6);
--radius-md: calc(var(--radius) * 0.8);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) * 1.4);
--radius-2xl: calc(var(--radius) * 1.8);
}
.beaver-root {
box-sizing: border-box;
height: 100%;
padding-bottom: var(--beaver-inset-bottom, 0px);
font-family: var(--font-interface);
font-size: var(--text-sm);
color: var(--foreground);
background: var(--background);
}
/* Portal layer for menus and dialogs: a zero-sized anchor at body level, above
the sidedocks, carrying the theme aliases so popovers stay on theme. */
.beaver-portal {
position: fixed;
top: 0;
left: 0;
z-index: var(--layer-menu, 65);
width: 0;
height: 0;
background: transparent;
}
.beaver-root.beaver-root *,
.beaver-root.beaver-root *::before,
.beaver-root.beaver-root *::after {
box-sizing: border-box;
border: 0 solid var(--border);
}
.beaver-root.beaver-root
:is(h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd) {
margin: 0;
font-size: inherit;
font-weight: inherit;
line-height: inherit;
}
.beaver-root.beaver-root :is(ul, ol) {
padding: 0;
margin: 0;
list-style: none;
}
.beaver-root.beaver-root :is(button, input, select, textarea) {
height: auto;
min-height: 0;
padding: 0;
margin: 0;
font: inherit;
color: inherit;
letter-spacing: inherit;
-webkit-appearance: none;
appearance: none;
outline: none;
background: transparent;
border: 0 solid var(--border);
border-radius: 0;
box-shadow: none;
}
.beaver-root.beaver-root :is(button, input, select, textarea):hover,
.beaver-root.beaver-root :is(button, input, select, textarea):focus,
.beaver-root.beaver-root :is(button, input, select, textarea):active {
box-shadow: none;
}
.beaver-root.beaver-root button {
justify-content: flex-start;
width: auto;
text-align: left;
cursor: pointer;
}
/* A grid button centres by `place-items`, which the rule above would override
for its inline axis: an icon-only button ends up pinned to its left edge. */
.beaver-root.beaver-root button:is(.grid, .inline-grid) {
justify-content: initial;
}
.beaver-root.beaver-root button:hover {
background: transparent;
}
.beaver-root.beaver-root button:disabled {
cursor: default;
}
.beaver-root.beaver-root input::placeholder,
.beaver-root.beaver-root textarea::placeholder {
color: var(--muted-foreground);
}
.beaver-root.beaver-root :is(input, textarea) {
caret-color: var(--primary);
}
.beaver-root.beaver-root :focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
.beaver-root.beaver-root svg {
display: block;
flex-shrink: 0;
}
.beaver-root.beaver-root a,
.beaver-root.beaver-root a:hover {
color: inherit;
text-decoration: inherit;
}
.beaver-root.beaver-root img {
display: block;
max-width: 100%;
height: auto;
}
.beaver-root.beaver-root :is(code, pre, kbd) {
font-family: var(--font-monospace);
font-size: 0.8125rem;
}
/* Chat text rendered by Obsidian itself, kept compact for a sidedock. */
.beaver-root.beaver-root .beaver-md {
font-size: var(--text-sm);
line-height: 1.5;
}
.beaver-root.beaver-root .beaver-md :is(p, ul, ol, pre, blockquote, table) {
margin-block: 0.4em;
}
.beaver-root.beaver-root .beaver-md :is(h1, h2, h3, h4, h5, h6) {
margin-block: 0.8em 0.4em;
font-size: 1em;
font-weight: 600;
}
.beaver-root.beaver-root .beaver-md :is(ul, ol) {
padding-left: 1.25em;
list-style: disc;
}
.beaver-root.beaver-root .beaver-md ol {
list-style: decimal;
}
.beaver-root.beaver-root .beaver-md li + li {
margin-top: 0.15em;
}
.beaver-root.beaver-root .beaver-md a {
color: var(--link);
text-decoration: none;
}
.beaver-root.beaver-root .beaver-md a:hover {
text-decoration: underline;
}
.beaver-root.beaver-root .beaver-md a.is-unresolved {
color: var(--link-unresolved-color, var(--muted-foreground));
opacity: 0.75;
}
.beaver-root.beaver-root .beaver-md code {
padding: 0.1em 0.3em;
font-size: 0.9em;
font-weight: 500;
background: color-mix(in oklch, var(--muted) 70%, transparent);
border-radius: var(--radius-sm);
}
.beaver-root.beaver-root .beaver-md pre {
padding: 0.6em 0.8em;
overflow: auto;
background: var(--muted);
border-radius: var(--radius-md);
}
.beaver-root.beaver-root .beaver-md pre code {
padding: 0;
font-weight: 400;
background: transparent;
}
.beaver-root.beaver-root .beaver-md blockquote {
padding-left: 0.75em;
color: var(--muted-foreground);
border-left: 1px solid var(--border);
}
.beaver-root.beaver-root .beaver-md > :first-child {
margin-top: 0;
}
.beaver-root.beaver-root .beaver-md > :last-child {
margin-bottom: 0;
}
/* The luma primitives are pill-shaped for the browser; inside Obsidian every
control takes the app's own corner language, like beaver-calendar's. */
@layer utilities {
/* Utilities are !important here, so the hidden attribute needs its own weight. */
.beaver-root [hidden] {
display: none !important;
}
.beaver-root [data-slot="button"],
.beaver-root [data-slot="select-trigger"] {
border-radius: var(--button-radius, var(--radius-s)) !important;
}
.beaver-root [data-slot="input"],
.beaver-root [data-slot="tabs-trigger"],
.beaver-root [data-slot$="-item"] {
border-radius: var(--input-radius, var(--radius-s)) !important;
}
.beaver-root [data-slot="tabs-list"],
.beaver-root [data-slot="skeleton"] {
border-radius: var(--radius-m, 8px) !important;
}
/* The luma tabs mark the active trigger with the page colour, which on a
dark Obsidian theme is the same as the surface behind the list. */
.beaver-root [data-slot="tabs-list"] {
background: color-mix(
in oklab,
var(--text-normal) 6%,
transparent
) !important;
}
.beaver-root [data-slot="tabs-trigger"][data-state="active"] {
color: var(--text-normal) !important;
background: color-mix(
in oklab,
var(--text-normal) 14%,
transparent
) !important;
}
.beaver-root [data-slot="dialog-content"],
.beaver-root [data-slot="popover-content"],
.beaver-root [data-slot="dropdown-menu-content"],
.beaver-root [data-slot="context-menu-content"],
.beaver-root [data-slot="select-content"] {
border: 1px solid var(--border) !important;
border-radius: var(--radius-m, 8px) !important;
box-shadow: var(--shadow-s) !important;
}
.beaver-root [data-slot="dropdown-menu-content"],
.beaver-root [data-slot="context-menu-content"],
.beaver-root [data-slot="select-content"] {
background: var(--popover) !important;
}
.beaver-root [data-slot="dropdown-menu-content"]::before,
.beaver-root [data-slot="context-menu-content"]::before,
.beaver-root [data-slot="select-content"]::before {
display: none !important;
}
/* Obsidian's own toggle: border-hover track, accent when on, a white thumb.
Tripled class: luma's group/data variants carry three classes' worth of
specificity, and the utilities are all !important. */
.beaver-root.beaver-root.beaver-root [data-slot="switch"] {
justify-content: flex-start !important;
width: 40px !important;
height: 20px !important;
padding: 0 !important;
background: var(--background-modifier-border-hover) !important;
border: 0 !important;
border-radius: var(--toggle-radius, 18px) !important;
}
.beaver-root.beaver-root.beaver-root
[data-slot="switch"][data-state="checked"] {
background: var(--interactive-accent) !important;
}
.beaver-root.beaver-root.beaver-root [data-slot="switch-thumb"] {
display: block !important;
width: 16px !important;
height: 16px !important;
margin-left: 2px !important;
background: var(--toggle-thumb-color, white) !important;
border-radius: 50% !important;
box-shadow: var(--shadow-s) !important;
}
.beaver-root.beaver-root.beaver-root [data-slot="switch-thumb"] {
translate: 0 !important;
}
.beaver-root.beaver-root.beaver-root
[data-slot="switch-thumb"][data-state="checked"] {
translate: 20px 0 !important;
}
.beaver-root [data-slot="button"][data-variant="default"],
.beaver-root [data-slot="button"]:not([class*="bg-"]) {
font-weight: var(--font-medium, 500) !important;
}
}
/* Strips and the island are buttons here; the reset above flattens buttons,
so the vocabulary is restated at the reset's own specificity. */
.beaver-root.beaver-root .strip {
display: grid;
grid-template-columns: 1.5rem minmax(0, 1fr) auto;
align-items: center;
justify-content: stretch;
justify-items: stretch;
width: 100%;
padding: 0.375rem 0.875rem 0.375rem 0.625rem;
text-align: left;
background: var(--strip);
border-bottom: 1px solid var(--border);
border-radius: 0;
}
.beaver-root.beaver-root .strip:hover,
.beaver-root.beaver-root .strip:focus-visible {
background: var(--strip);
box-shadow: var(--shadow-lift);
}
.beaver-root.beaver-root .strip:first-child {
border-top-left-radius: var(--radius-md);
border-top-right-radius: var(--radius-md);
}
.beaver-root.beaver-root .strip:last-child {
border-bottom: 0;
border-bottom-right-radius: var(--radius-md);
border-bottom-left-radius: var(--radius-md);
}
.beaver-root.beaver-root .strip[aria-current="true"] {
background: color-mix(in oklab, var(--strip) 85%, var(--primary) 15%);
}
.beaver-root.beaver-root .strip[data-state="waiting"] {
box-shadow: var(--shadow-lift);
transform: translateX(0.5rem);
}
.beaver-root.beaver-root .strip.strip-child {
padding-left: 1.75rem;
}
.beaver-root.beaver-root button.island {
display: inline-flex;
gap: 0.625rem;
align-items: center;
height: 2.125rem;
padding: 0 0.875rem 0 0.75rem;
white-space: nowrap;
background: var(--strip);
border: 1px solid var(--border);
border-radius: 999px;
}
.beaver-root.beaver-root button.island:hover {
background: var(--strip);
}
.beaver-root.beaver-root button.island:disabled {
opacity: 1;
}
.beaver-root.beaver-root .bay-rack {
border: 1px solid var(--border);
border-radius: calc(var(--radius-md) + 1px);
}
.beaver-root.beaver-root .strip-child::before {
left: 1.125rem;
}