rustio-admin 0.24.0

Django Admin, but for Rust. A small, focused admin framework.
Documentation
/* ============================================================
 * rustio-admin / layout / topbar
 *
 * Sticky top chrome — brand mark, identity strip, search trigger,
 * mobile sidebar toggle. Sits above all page content;
 * `position: sticky` keeps it pinned during scroll.
 * ============================================================ */

.rio-topbar {
  display: flex;
  align-items: center;
  gap: var(--rio-s4);
  /* v0.16 — 24px horizontal padding. Topbar stops feeling cramped
   * beside the brand and there's real breathing room between
   * topbar items. */
  padding: 0 var(--rio-s5);
  height: var(--rio-topbar-h);
  /* Light topbar on the light page canvas. `--rio-surface`
   * (now pure `#FFFFFF`) sits one tier above the canvas — GitHub /
   * Vercel / Linear convention. The bottom border carries the seam
   * between chrome and content; the deep-slate weight in the layout
   * comes from the sidebar, not the topbar. */
  background: var(--rio-surface);
  border-bottom: 1px solid var(--rio-border-soft);
  position: sticky;
  top: 0;
  /* Topbar always wins over the sticky sidebar. Before v0.18.6 this
   * was a bare `10`, lower than the sidebar's `20`, so scrolling a
   * long page slid the sidebar up over the identity strip. */
  z-index: var(--rio-z-topbar);
}
.rio-topbar-brand {
  font-weight: var(--rio-fw-bold);
  font-size: var(--rio-fs-lg);                 /* 18px */
  color: var(--rio-text-strong);
  letter-spacing: var(--rio-tracking-heading);
}
.rio-topbar-brand:hover { text-decoration: none; }
.rio-topbar-nav {
  margin-inline-start: auto;
  display: flex;
  align-items: center;
  gap: var(--rio-s4);
  flex-wrap: wrap;
}
.rio-topbar-identity {
  color: var(--rio-text-muted);
  font-size: var(--rio-fs-md);                 /* 16px */
  font-weight: var(--rio-fw-regular);
}
.rio-topbar-link {
  color: var(--rio-text-muted);
  font-size: var(--rio-fs-md);                 /* 16px */
  font-weight: var(--rio-fw-medium);
}
.rio-topbar-link:hover { color: var(--rio-text); }
.rio-topbar-bell {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.rio-topbar-bell__badge {
  position: absolute;
  top: -6px;
  inset-inline-end: -8px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--rio-accent, #b22222);
  color: #fff;
  font-size: 11px;
  font-weight: var(--rio-fw-bold);
  line-height: 16px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.rio-topbar-logout { display: inline; }

/* ── Account dropdown ───────────────────────────────────────
 * Single-button user menu replacing the pre-0.18.5 inline strip
 * of Signed-in / MFA / Sessions / Change-password / Log-out.
 * Reuses .rio-dropdown machinery — JS hook lives in admin.js
 * (`[data-rio-dropdown]`). The avatar is a one-letter
 * monogram derived from the email's first char (no remote
 * fetch, no extra storage). */
.rio-topbar-account__toggle {
  /* Pull padding tighter than the generic dropdown toggle —
   * topbar gravity is less than a content card. */
  padding: 0.35rem 0.55rem 0.35rem 0.4rem;
  gap: 0.5rem;
  font-weight: var(--rio-fw-medium);
}
.rio-topbar-account__avatar {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--rio-brand-tint, var(--rio-accent-soft));
  color: var(--rio-brand-text, var(--rio-accent));
  font-weight: var(--rio-fw-bold);
  font-size: var(--rio-fs-sm);
  display: inline-flex;
  align-items: center; justify-content: center;
  font-variant-numeric: tabular-nums;
}
.rio-topbar-account__email {
  font-size: var(--rio-fs-md);
  color: var(--rio-text);
  /* Cap the email at one ratio of the topbar so very long
   * addresses don't push the toggle into the page title. */
  max-width: 22ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rio-topbar-account__who {
  margin: 0;
  font-size: var(--rio-fs-sm);
  color: var(--rio-text);
  font-weight: var(--rio-fw-semibold);
  word-break: break-all;
}
/* The account panel is narrower than a filter panel — the menu
 * items are short labels and a long panel would float oddly
 * away from the toggle. */
.rio-topbar-account__panel {
  min-width: 240px;
}
/* The logout form lives in the panel footer; the button is the
 * "real" affordance, so let it span the row. */
.rio-topbar-account__panel .rio-topbar-logout { flex: 1; }
.rio-topbar-account__panel .rio-topbar-logout .rio-button { width: 100%; }

.rio-sidebar-toggle {
  display: none;
  background: none;
  border: 1px solid var(--rio-border);
  border-radius: var(--rio-radius-sm);
  padding: var(--rio-s1) var(--rio-s2);
  color: var(--rio-text);
  cursor: pointer;
}