pagetop/extensions/pagetop-bootsier/assets/_bootsier-custom.scss
Manuel Cillero c0a5a8c3ab (bootsier): Añade componentes esenciales
- Añade Dialog como modal de Bootstrap, con el JS de soporte para
  `htmx:confirm` y el saneado de su posición fija.
- Adapta Nav, Navbar y Dropdown al reuso de los tipos movidos al core, y
  traduce BootsierColors/Intent en Button y Badge, con soporte para
  Light/Dark vía with_color().
- Reexporta en el tema los componentes de PageTop que faltaban: Block,
  Breadcrumb, Messages, Pager, Table y form::Number.
2026-08-28 19:46:56 +02:00

244 lines
6.6 KiB
SCSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Bootsier CSS rules: self-hosted fonts, form elements, regions and components.
// Self-hosted Source Sans 3 (SIL OFL 1.1), served from /bootsier/fonts.
// Required by AdminLTE 4, which declares it as the primary font family in $font-family-sans-serif.
// Font URLs must match the Preload declarations in src/lib.rs; a mismatch causes double downloads.
@font-face {
font-family: "Source Sans 3";
src: url("/bootsier/fonts/bootsier.font.woff2") format("woff2");
font-weight: 200 900;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Source Sans 3";
src: url("/bootsier/fonts/bootsier.font.italic.woff2") format("woff2");
font-weight: 200 900;
font-style: italic;
font-display: swap;
}
// Font-relative top offset to keep the skip-link hidden at any font size.
.skip-link {
top: -3em;
}
// Required field indicator in forms.
.form-required {
color: var(--bs-danger);
margin: 0 0.25rem;
}
// Form field with consistent bottom margin.
.form-field {
margin-bottom: 1rem;
&:last-child {
margin-bottom: 0;
}
}
// Button set (button::ButtonSet): spaces its buttons with a gap instead of relying on Bootstrap's
// .btn-group, which merges adjacent buttons into a single joined control.
.button-set {
display: flex;
flex-wrap: wrap;
gap: $spacer * .5;
margin: 1rem 0;
}
// Fieldset with border and floating legend.
fieldset {
position: relative;
background-color: var(--bs-body-bg);
border: var(--bs-border-width) solid var(--bs-border-color);
border-radius: var(--bs-border-radius);
padding: 2rem 1rem 1rem;
margin: 2rem 0 1rem;
}
fieldset > legend {
position: absolute;
top: 0;
left: 1rem;
transform: translateY(-50%);
color: var(--bs-secondary-color);
background-color: var(--bs-body-bg);
border: var(--bs-border-width) solid var(--bs-border-color);
border-radius: var(--bs-border-radius);
padding: 0.125rem 0.75rem;
font-size: ($font-size-sm + $font-size-base) / 2;
font-weight: var(--bs-font-weight-normal);
line-height: 1.25;
width: fit-content;
max-width: 75%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.fieldset-description {
margin-bottom: 1rem;
}
// Gap between group label and first inline check.
.form-label + .form-check-inline {
margin-left: 1rem;
}
// Footer region.
.region-footer {
padding: 0.75rem 0 3rem;
text-align: center;
}
// Messages component. Classes are fixed by pagetop core (`.message`, `.message-info`,
// `.message-warning`, `.message-error`); reusing Bootstrap's own `.alert`/`.alert-*` styles keeps
// the palette in sync with the active Bootstrap theme instead of duplicating it here.
.message {
@extend .alert;
}
.message-info {
@extend .alert-info;
}
.message-warning {
@extend .alert-warning;
}
.message-error {
@extend .alert-danger;
}
// Sort indicator on sortable table headers (`table::SortLink`), using Bootstrap Icons'
// sort-up/sort-down glyphs instead of the plain triangle from basic.css.
.table-sort::after {
font-family: $bootstrap-icons-font;
content: "\f575"; // sort-down
margin-left: 0.25rem;
font-size: 0.8em;
opacity: 0.35;
}
.table-sort-asc::after {
content: "\f57b"; // sort-up
opacity: 1;
}
.table-sort-desc::after {
content: "\f575"; // sort-down
opacity: 1;
}
// Pager component.
// `.pagination`, `.page-item`, `.page-link`, `.active` and `.disabled` already come styled by
// Bootstrap, since Pager reuses that same markup (the ellipsis is a disabled `.page-link` span,
// same as any other cell). Only what Pager adds on top needs rules here: the <nav> wrapper and
// the jump-to-page form.
// <nav> wrapper: flex row that also holds the jump-to-page form.
.pager {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0 $spacer; // row-gap column-gap: no vertical gap when the summary drops to its own line.
margin-block: $spacer;
}
// Horizontal alignment set via PagerAlign.
.pager-align-start {
justify-content: flex-start;
}
.pager-align-center {
justify-content: center;
}
.pager-align-end {
justify-content: flex-end;
}
// Pushes the rest of .pager (pagination, jump form) to the opposite side. With
// PagerAlign::Start the summary swaps to the other end instead, since otherwise it would sit
// right next to a pagination that's already at the start. With PagerAlign::Center an auto margin
// wouldn't work -it always claims all the free space, so the pagination could never be genuinely
// centered- so instead the summary drops to its own line below, centered too.
.pager-summary {
color: var(--bs-secondary-color);
font-size: $font-size-sm;
align-self: flex-start;
margin-inline-end: auto;
}
.pager-align-start .pager-summary {
order: 1;
margin-inline-end: 0;
margin-inline-start: auto;
}
.pager-align-center .pager-summary {
order: 1;
flex-basis: 100%;
text-align: center;
margin-inline-end: 0;
}
// By default, .page-link-icon shows the text of pager_previous_label/pager_next_label
// ("Previous"/"Next"). The full accessible text lives separately, in the link's aria-label, so
// replacing the visible text here with a symbol does not affect accessibility. To use ""/""
// instead, uncomment:
/*
.page-link-icon {
display: inline-block;
font-size: 0;
}
.page-previous .page-link-icon::before {
content: "";
font-size: var(--bs-pagination-font-size);
display: inline-block;
transform: translateY(-0.1em) scale(1.5);
}
.page-next .page-link-icon::before {
content: "";
font-size: var(--bs-pagination-font-size);
display: inline-block;
transform: translateY(-0.1em) scale(1.5);
}
*/
// Jump-to-page field and submit button, presented as a single joined control. Same block margins
// as `ol`/`ul`/`dl` in Bootstrap's reboot (literal values there too, not variables).
.pager-jump {
display: flex;
align-items: center;
margin-top: 0;
margin-bottom: 1rem;
}
// One focus ring for the whole control instead of one per element.
.pager-jump:focus-within {
border-radius: $input-border-radius;
box-shadow: $input-focus-box-shadow;
}
.pager-jump-input > .form-control:focus,
.pager-jump-button:focus {
box-shadow: none;
}
.pager-jump-input > .form-control {
// Extra width equals twice the field's own horizontal padding.
width: calc(var(--pager-jump-width, 1ch) + #{$input-padding-x * 4});
text-align: center;
appearance: textfield;
-moz-appearance: textfield;
// Logical (not physical) corners, so the shape flips correctly under RTL.
border-start-end-radius: 0;
border-end-end-radius: 0;
&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
}
.pager-jump-input {
margin: 0;
}
.pager-jump-button {
@extend .btn-primary;
border-start-start-radius: 0;
border-end-start-radius: 0;
}