Make Site Adaptive and Introduce Hamburger Menu for Mobile #14

Merged
june merged 3 commits from feature/adaptivity into main 2024-01-27 23:14:42 +01:00
42 changed files with 3929 additions and 16 deletions

View file

@ -0,0 +1,33 @@
"use strict";
function setScrolling(enable = true) {
const body = document.body;
if (enable) {
body.style.overflow = "unset";
}
else {
body.style.overflow = "hidden";
}
};
document.addEventListener("DOMContentLoaded", () => {
const hamburgerMenuCheckbox = document.querySelector(".menu-button");
// When the hamburger menu is open, disable scrolling.
hamburgerMenuCheckbox.addEventListener("change", () => {
if (hamburgerMenuCheckbox.checked) {
setScrolling(false);
}
else {
setScrolling(true);
}
});
window.addEventListener("resize", () => {
if (window.innerWidth > 768 && hamburgerMenuCheckbox.checked) {
// Uncheck the checkbox to disable scrolling and to get to the original state.
hamburgerMenuCheckbox.checked = false;
hamburgerMenuCheckbox.dispatchEvent(new Event("change"));
}
});
});

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019-2023 Pico
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,4 @@
// Output color in RGB format
@function to-rgb($color) {
@return unquote("rgb(#{red($color)}, #{green($color)}, #{blue($color)})");
}

View file

@ -0,0 +1,69 @@
// Config
//
// Set the root element for $enable-semantic-container and $enable-responsive-spacings
$semantic-root-element: "body" !default;
// Enable <header>, <main>, <footer> inside $semantic-root-element as containers
$enable-semantic-container: false !default;
// Enable .container and .container-fluid
$enable-class-container: true !default;
// Enable a centered viewport for <header>, <main>, <footer> inside $enable-semantic-container
// Fluid layout if disabled
$enable-viewport: true !default;
// Enable responsive spacings for <header>, <main>, <footer>, <section>, <article>
// Fixed spacings if disabled
$enable-responsive-spacings: true !default;
// Enable responsive typography
// Fixed root element size if disabled
$enable-responsive-typography: true !default;
// Enable .classes
// .classless version if disabled
$enable-classes: true !default;
// Enable .grid class
$enable-grid: true !default;
// Enable transitions
$enable-transitions: true !default;
// Enable overriding with !important
$enable-important: true !default;
// Responsive
//
// xs: Extra small (portrait phones)
// sm: Small(landscape phones)
// md: Medium(tablets)
// lg: Large(desktops)
// xl: Extra large (large desktops)
// NOTE:
// To provide an easy and fine styling on each breakpoint
// we didn't use @each, @mixin or @include.
// That means you need to edit each CSS selector file to add a breakpoint
// Breakpoints
// 'null' disable the breakpoint
$breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
) !default;
// Viewports
$viewports: (
// 'null' disable the viewport on a breakpoint
sm: 510px,
md: 700px,
lg: 920px,
xl: 1130px
) !default;

View file

@ -0,0 +1,116 @@
/**
* Accordion (<details>)
*/
details {
display: block;
margin-bottom: var(--spacing);
padding-bottom: var(--spacing);
border-bottom: var(--border-width) solid var(--accordion-border-color);
summary {
line-height: 1rem;
list-style-type: none;
cursor: pointer;
&:not([role]) {
color: var(--accordion-close-summary-color);
}
@if $enable-transitions {
transition: color var(--transition);
}
// Reset marker
&::-webkit-details-marker {
display: none;
}
&::marker {
display: none;
}
&::-moz-list-bullet {
list-style-type: none;
}
// Marker
&::after {
display: block;
width: 1rem;
height: 1rem;
margin-inline-start: calc(var(--spacing, 1rem) * 0.5);
float: right;
transform: rotate(-90deg);
background-image: var(--icon-chevron);
background-position: right center;
background-size: 1rem auto;
background-repeat: no-repeat;
content: "";
@if $enable-transitions {
transition: transform var(--transition);
}
}
&:focus {
outline: none;
&:not([role="button"]) {
color: var(--accordion-active-summary-color);
}
}
// Type button
&[role="button"] {
width: 100%;
text-align: left;
// Marker
&::after {
height: calc(1rem * var(--line-height, 1.5));
background-image: var(--icon-chevron-button);
}
@if $enable-classes {
// .contrast
&:not(.outline).contrast {
// Marker
&::after {
background-image: var(--icon-chevron-button-inverse);
}
}
}
}
}
// Open
&[open] {
> summary {
margin-bottom: calc(var(--spacing));
&:not([role]) {
&:not(:focus) {
color: var(--accordion-open-summary-color);
}
}
&::after {
transform: rotate(0);
}
}
}
}
[dir="rtl"] {
details {
summary {
text-align: right;
&::after {
float: left;
background-position: left center;
}
}
}
}

View file

@ -0,0 +1,36 @@
/**
* Card (<article>)
*/
article {
margin: var(--block-spacing-vertical) 0;
padding: var(--block-spacing-vertical) var(--block-spacing-horizontal);
border-radius: var(--border-radius);
background: var(--card-background-color);
box-shadow: var(--card-box-shadow);
> header,
> footer {
margin-right: calc(var(--block-spacing-horizontal) * -1);
margin-left: calc(var(--block-spacing-horizontal) * -1);
padding: calc(var(--block-spacing-vertical) * 0.66)
var(--block-spacing-horizontal);
background-color: var(--card-sectionning-background-color);
}
> header {
margin-top: calc(var(--block-spacing-vertical) * -1);
margin-bottom: var(--block-spacing-vertical);
border-bottom: var(--border-width) solid var(--card-border-color);
border-top-right-radius: var(--border-radius);
border-top-left-radius: var(--border-radius);
}
> footer {
margin-top: var(--block-spacing-vertical);
margin-bottom: calc(var(--block-spacing-vertical) * -1);
border-top: var(--border-width) solid var(--card-border-color);
border-bottom-right-radius: var(--border-radius);
border-bottom-left-radius: var(--border-radius);
}
}

View file

@ -0,0 +1,214 @@
/**
* Dropdown ([role="list"])
*/
// Menu
details[role="list"],
li[role="list"] {
position: relative;
}
details[role="list"] summary + ul,
li[role="list"] > ul {
display: flex;
z-index: 99;
position: absolute;
top: auto;
right: 0;
left: 0;
flex-direction: column;
margin: 0;
padding: 0;
border: var(--border-width) solid var(--dropdown-border-color);
border-radius: var(--border-radius);
border-top-right-radius: 0;
border-top-left-radius: 0;
background-color: var(--dropdown-background-color);
box-shadow: var(--card-box-shadow);
color: var(--dropdown-color);
white-space: nowrap;
li {
width: 100%;
margin-bottom: 0;
padding: calc(var(--form-element-spacing-vertical) * 0.5)
var(--form-element-spacing-horizontal);
list-style: none;
&:first-of-type {
margin-top: calc(var(--form-element-spacing-vertical) * 0.5);
}
&:last-of-type {
margin-bottom: calc(var(--form-element-spacing-vertical) * 0.5);
}
a {
display: block;
margin: calc(var(--form-element-spacing-vertical) * -0.5)
calc(var(--form-element-spacing-horizontal) * -1);
padding: calc(var(--form-element-spacing-vertical) * 0.5)
var(--form-element-spacing-horizontal);
overflow: hidden;
color: var(--dropdown-color);
text-decoration: none;
text-overflow: ellipsis;
&:hover {
background-color: var(--dropdown-hover-background-color);
}
}
}
}
// Marker
details[role="list"] summary,
li[role="list"] > a {
&::after {
display: block;
width: 1rem;
height: calc(1rem * var(--line-height, 1.5));
margin-inline-start: 0.5rem;
float: right;
transform: rotate(0deg);
background-image: var(--icon-chevron);
background-position: right center;
background-size: 1rem auto;
background-repeat: no-repeat;
content: "";
}
}
// Global dropdown only
details[role="list"] {
padding: 0;
border-bottom: none;
// Style <summary> as <select>
summary {
margin-bottom: 0;
&:not([role]) {
height: calc(
1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 +
var(--border-width) * 2
);
padding: var(--form-element-spacing-vertical)
var(--form-element-spacing-horizontal);
border: var(--border-width) solid var(--form-element-border-color);
border-radius: var(--border-radius);
background-color: var(--form-element-background-color);
color: var(--form-element-placeholder-color);
line-height: inherit;
cursor: pointer;
@if $enable-transitions {
transition: background-color var(--transition),
border-color var(--transition), color var(--transition),
box-shadow var(--transition);
}
&:active,
&:focus {
border-color: var(--form-element-active-border-color);
background-color: var(--form-element-active-background-color);
}
&:focus {
box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color);
}
}
}
// Close for details[role="list"]
&[open] summary {
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
&::before {
display: block;
z-index: 1;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: none;
content: "";
cursor: default;
}
}
}
// All Dropdowns inside <nav>
nav details[role="list"] summary,
nav li[role="list"] a {
display: flex;
direction: ltr;
}
nav details[role="list"] summary + ul,
nav li[role="list"] > ul {
min-width: fit-content;
border-radius: var(--border-radius);
li a {
border-radius: 0;
}
}
// Dropdowns inside <nav> as nested <details>
nav details[role="list"] {
summary,
summary:not([role]) {
height: auto;
padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal);
}
&[open] summary {
border-radius: var(--border-radius);
}
summary + ul {
margin-top: var(--outline-width);
margin-inline-start: 0;
}
summary[role="link"] {
margin-bottom: calc(var(--nav-link-spacing-vertical) * -1);
line-height: var(--line-height);
+ ul {
margin-top: calc(var(--nav-link-spacing-vertical) + var(--outline-width));
margin-inline-start: calc(var(--nav-link-spacing-horizontal) * -1);
}
}
}
// Dropdowns inside a <nav> without using <details>
li[role="list"] {
// Open on hover (for mobile)
// or on active/focus (for keyboard navigation)
&:hover > ul,
a:active ~ ul,
a:focus ~ ul {
display: flex;
}
> ul {
display: none;
margin-top: calc(var(--nav-link-spacing-vertical) + var(--outline-width));
margin-inline-start: calc(
var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal)
);
}
> a::after {
background-image: var(--icon-chevron);
}
}
label > details[role="list"] {
margin-top: calc(var(--spacing) * .25);
margin-bottom: var(--spacing);
}

View file

@ -0,0 +1,168 @@
/**
* Modal (<dialog>)
*/
:root {
--scrollbar-width: 0px;
}
dialog {
display: flex;
z-index: 999;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
align-items: center;
justify-content: center;
width: inherit;
min-width: 100%;
height: inherit;
min-height: 100%;
padding: var(--spacing);
border: 0;
backdrop-filter: var(--modal-overlay-backdrop-filter);
background-color: var(--modal-overlay-background-color);
color: var(--color);
// Content
article {
$close-selector: if($enable-classes, ".close", "a[rel='prev']");
max-height: calc(100vh - var(--spacing) * 2);
overflow: auto;
@if map-get($breakpoints, "sm") {
@media (min-width: map-get($breakpoints, "sm")) {
max-width: map-get($viewports, "sm");
}
}
@if map-get($breakpoints, "md") {
@media (min-width: map-get($breakpoints, "md")) {
max-width: map-get($viewports, "md");
}
}
> header,
> footer {
padding: calc(var(--block-spacing-vertical) * 0.5)
var(--block-spacing-horizontal);
}
> header {
#{$close-selector} {
margin: 0;
margin-left: var(--spacing);
float: right;
}
}
> footer {
text-align: right;
[role="button"] {
margin-bottom: 0;
&:not(:first-of-type) {
margin-left: calc(var(--spacing) * 0.5);
}
}
}
p {
&:last-of-type {
margin: 0;
}
}
// Close icon
#{$close-selector} {
display: block;
width: 1rem;
height: 1rem;
margin-top: calc(var(--block-spacing-vertical) * -0.5);
margin-bottom: var(--typography-spacing-vertical);
margin-left: auto;
background-image: var(--icon-close);
background-position: center;
background-size: auto 1rem;
background-repeat: no-repeat;
opacity: 0.5;
@if $enable-transitions {
transition: opacity var(--transition);
}
&:is([aria-current], :hover, :active, :focus) {
opacity: 1;
}
}
}
// Closed state
&:not([open]),
&[open="false"] {
display: none;
}
}
// Utilities
@if $enable-classes {
.modal-is-open {
padding-right: var(--scrollbar-width, 0px);
overflow: hidden;
pointer-events: none;
touch-action: none;
dialog {
pointer-events: auto;
}
}
}
// Animations
@if ($enable-classes and $enable-transitions) {
$animation-duration: 0.2s;
:where(.modal-is-opening, .modal-is-closing) {
dialog,
dialog > article {
animation-duration: $animation-duration;
animation-timing-function: ease-in-out;
animation-fill-mode: both;
}
dialog {
animation-duration: ($animation-duration * 4);
animation-name: modal-overlay ;
> article {
animation-delay: $animation-duration;
animation-name: modal;
}
}
}
.modal-is-closing {
dialog,
dialog > article {
animation-delay: 0s;
animation-direction: reverse;
}
}
@keyframes modal-overlay {
from {
backdrop-filter: none;
background-color: transparent;
}
}
@keyframes modal {
from {
transform: translateY(-100%);
opacity: 0;
}
}
}

View file

@ -0,0 +1,141 @@
/**
* Nav
*/
// Reboot based on :
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
// Prevent VoiceOver from ignoring list semantics in Safari (opinionated)
:where(nav li)::before {
float: left;
content: "\200B";
}
// Pico
//
// Horizontal Nav
nav,
nav ul {
display: flex;
}
nav {
justify-content: space-between;
ol,
ul {
align-items: center;
margin-bottom: 0;
padding: 0;
list-style: none;
&:first-of-type {
margin-left: calc(var(--nav-element-spacing-horizontal) * -1);
}
&:last-of-type {
margin-right: calc(var(--nav-element-spacing-horizontal) * -1);
}
}
li {
display: inline-block;
margin: 0;
padding: var(--nav-element-spacing-vertical)
var(--nav-element-spacing-horizontal);
// Minimal support for buttons and forms elements
> * {
--spacing: 0;
}
}
:where(a, [role="link"]) {
display: inline-block;
margin: calc(var(--nav-link-spacing-vertical) * -1)
calc(var(--nav-link-spacing-horizontal) * -1);
padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal);
border-radius: var(--border-radius);
text-decoration: none;
&:is([aria-current], :hover, :active, :focus) {
text-decoration: none;
}
}
// Breadcrumb
&[aria-label="breadcrumb"] {
align-items: center;
justify-content: start;
& ul li {
&:not(:first-child) {
margin-inline-start: var(--nav-link-spacing-horizontal);
}
&:not(:last-child) {
::after {
position: absolute;
width: calc(var(--nav-link-spacing-horizontal) * 2);
margin-inline-start: calc(var(--nav-link-spacing-horizontal) / 2);
content: "/";
color: var(--muted-color);
text-align: center;
}
}
}
& a[aria-current] {
background-color: transparent;
color: inherit;
text-decoration: none;
pointer-events: none;
}
}
// Minimal support for role="button"
[role="button"] {
margin-right: inherit;
margin-left: inherit;
padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal);
}
}
// Vertical Nav
aside {
nav,
ol,
ul,
li {
display: block;
}
li {
padding: calc(var(--nav-element-spacing-vertical) * 0.5)
var(--nav-element-spacing-horizontal);
a {
display: block;
}
// Minimal support for links as buttons
[role="button"] {
margin: inherit;
}
}
}
// Breadcrumb RTL
[dir="rtl"] {
nav {
&[aria-label="breadcrumb"] {
& ul li {
&:not(:last-child) {
::after {
content: "\\";
}
}
}
}
}
}

View file

@ -0,0 +1,89 @@
/**
* Progress
*/
// Reboot based on :
// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// 1. Add the correct display in Edge 18- and IE
// 2. Add the correct vertical alignment in Chrome, Edge, and Firefox
progress {
display: inline-block; // 1
vertical-align: baseline; // 2
}
// Pico
//
progress {
// Reset the default appearance
-webkit-appearance: none;
-moz-appearance: none;
// Styles
display: inline-block;
appearance: none;
width: 100%;
height: 0.5rem;
margin-bottom: calc(var(--spacing) * 0.5);
overflow: hidden;
// Remove Firefox and Opera border
border: 0;
border-radius: var(--border-radius);
background-color: var(--progress-background-color);
// IE10 uses `color` to set the bar background-color
color: var(--progress-color);
&::-webkit-progress-bar {
border-radius: var(--border-radius);
background: none;
}
&[value]::-webkit-progress-value {
background-color: var(--progress-color);
}
&::-moz-progress-bar {
background-color: var(--progress-color);
}
// Indeterminate state
@media (prefers-reduced-motion: no-preference) {
&:indeterminate {
background: var(--progress-background-color)
linear-gradient(
to right,
var(--progress-color) 30%,
var(--progress-background-color) 30%
)
top left / 150% 150% no-repeat;
animation: progress-indeterminate 1s linear infinite;
&[value]::-webkit-progress-value {
background-color: transparent;
}
&::-moz-progress-bar {
background-color: transparent;
}
}
}
}
[dir="rtl"] {
@media (prefers-reduced-motion: no-preference) {
progress:indeterminate {
animation-direction: reverse;
}
}
}
@keyframes progress-indeterminate {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}

View file

@ -0,0 +1,183 @@
/**
* Button
*/
// Reboot based on :
// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// 1. Change the font styles in all browsers
// 2. Remove the margin on controls in Safari
// 3. Show the overflow in Edge
button {
margin: 0; // 2
overflow: visible; // 3
font-family: inherit; // 1
text-transform: none; // 1
}
// Correct the inability to style buttons in iOS and Safari
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
// Pico
//
button {
display: block;
width: 100%;
margin-bottom: var(--spacing);
}
[role="button"] {
display: inline-block;
text-decoration: none;
}
button,
input[type="submit"],
input[type="button"],
input[type="reset"],
[role="button"] {
--background-color: var(--primary);
--border-color: var(--primary);
--color: var(--primary-inverse);
--box-shadow: var(--button-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
padding: var(--form-element-spacing-vertical)
var(--form-element-spacing-horizontal);
border: var(--border-width) solid var(--border-color);
border-radius: var(--border-radius);
outline: none;
background-color: var(--background-color);
box-shadow: var(--box-shadow);
color: var(--color);
font-weight: var(--font-weight);
font-size: 1rem;
line-height: var(--line-height);
text-align: center;
cursor: pointer;
@if $enable-transitions {
transition: background-color var(--transition),
border-color var(--transition), color var(--transition),
box-shadow var(--transition);
}
&:is([aria-current], :hover, :active, :focus) {
--background-color: var(--primary-hover);
--border-color: var(--primary-hover);
--box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
--color: var(--primary-inverse);
}
&:focus {
--box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),
0 0 0 var(--outline-width) var(--primary-focus);
}
}
// .secondary, .contrast & .outline
@if $enable-classes {
// Secondary
:is(button, input[type="submit"], input[type="button"], [role="button"]).secondary,
input[type="reset"] {
--background-color: var(--secondary);
--border-color: var(--secondary);
--color: var(--secondary-inverse);
cursor: pointer;
&:is([aria-current], :hover, :active, :focus) {
--background-color: var(--secondary-hover);
--border-color: var(--secondary-hover);
--color: var(--secondary-inverse);
}
&:focus {
--box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),
0 0 0 var(--outline-width) var(--secondary-focus);
}
}
// Contrast
:is(button, input[type="submit"], input[type="button"], [role="button"]).contrast {
--background-color: var(--contrast);
--border-color: var(--contrast);
--color: var(--contrast-inverse);
&:is([aria-current], :hover, :active, :focus) {
--background-color: var(--contrast-hover);
--border-color: var(--contrast-hover);
--color: var(--contrast-inverse);
}
&:focus {
--box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),
0 0 0 var(--outline-width) var(--contrast-focus);
}
}
// Outline (primary)
:is(button, input[type="submit"], input[type="button"], [role="button"]).outline,
input[type="reset"].outline {
--background-color: transparent;
--color: var(--primary);
&:is([aria-current], :hover, :active, :focus) {
--background-color: transparent;
--color: var(--primary-hover);
}
}
// Outline (secondary)
:is(button, input[type="submit"], input[type="button"], [role="button"]).outline.secondary,
input[type="reset"].outline {
--color: var(--secondary);
&:is([aria-current], :hover, :active, :focus) {
--color: var(--secondary-hover);
}
}
// Outline (contrast)
:is(button, input[type="submit"], input[type="button"], [role="button"]).outline.contrast {
--color: var(--contrast);
&:is([aria-current], :hover, :active, :focus) {
--color: var(--contrast-hover);
}
}
}
@else {
// Secondary button without .class
input[type="reset"] {
--background-color: var(--secondary);
--border-color: var(--secondary);
--color: var(--secondary-inverse);
cursor: pointer;
&:is([aria-current], :hover, :active, :focus) {
--background-color: var(--secondary-hover);
--border-color: var(--secondary-hover);
}
&:focus {
--box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),
0 0 0 var(--outline-width) var(--secondary-focus);
}
}
}
// Button [disabled]
// Links without href are disabled by default
:where(button, [type="submit"], [type="button"], [type="reset"], [role="button"])[disabled],
:where(fieldset[disabled]) :is(button, [type="submit"], [type="button"], [type="reset"], [role="button"]),
a[role="button"]:not([href]) {
opacity: 0.5;
pointer-events: none;
}

View file

@ -0,0 +1,91 @@
/**
* Code
*/
// Reboot based on :
// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// 1. Correct the inheritance and scaling of font size in all browsers
// 2. Correct the odd `em` font sizing in all browsers
pre,
code,
kbd,
samp {
font-size: 0.875em; // 2
font-family: var(--font-family); // 1
}
// Prevent overflow of the container in all browsers (opinionated)
pre {
-ms-overflow-style: scrollbar;
overflow: auto;
}
// Pico
//
pre,
code,
kbd {
border-radius: var(--border-radius);
background: var(--code-background-color);
color: var(--code-color);
font-weight: var(--font-weight);
line-height: initial;
}
code,
kbd {
display: inline-block;
padding: 0.375rem 0.5rem;
}
pre {
display: block;
margin-bottom: var(--spacing);
overflow-x: auto;
> code {
display: block;
padding: var(--spacing);
background: none;
font-size: 14px;
line-height: var(--line-height);
}
}
// Code Syntax
code {
// Tags
b {
color: var(--code-tag-color);
font-weight: var(--font-weight);
}
// Properties
i {
color: var(--code-property-color);
font-style: normal;
}
// Values
u {
color: var(--code-value-color);
text-decoration: none;
}
// Comments
em {
color: var(--code-comment-color);
font-style: normal;
}
}
// kbd
kbd {
background-color: var(--code-kbd-background-color);
color: var(--code-kbd-color);
vertical-align: baseline;
}

View file

@ -0,0 +1,48 @@
/**
* Embedded content
*/
// Reboot based on :
// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// Change the alignment on media elements in all browsers (opinionated)
:where(audio, canvas, iframe, img, svg, video) {
vertical-align: middle;
}
// Add the correct display in IE 9-
audio,
video {
display: inline-block;
}
// Add the correct display in iOS 4-7
audio:not([controls]) {
display: none;
height: 0;
}
// Remove the border on iframes in all browsers (opinionated)
:where(iframe) {
border-style: none;
}
// 1. Remove the border on images inside links in IE 10.
// 2. Responsive by default
img {
max-width: 100%; // 2
height: auto; // 2
border-style: none; // 1
}
// Change the fill color to match the text color in all browsers (opinionated)
:where(svg:not([fill])) {
fill: currentColor;
}
// Hide the overflow in IE
svg:not(:root) {
overflow: hidden;
}

View file

@ -0,0 +1,286 @@
/**
* Form elements
* Alternatives input types (Not Checkboxes & Radios)
*/
// Color
[type="color"] {
// Wrapper
@mixin color-wrapper {
padding: 0;
}
&::-webkit-color-swatch-wrapper {
@include color-wrapper;
}
&::-moz-focus-inner {
@include color-wrapper;
}
// Swatch
@mixin color-swatch {
border: 0;
border-radius: calc(var(--border-radius) * 0.5);
}
&::-webkit-color-swatch {
@include color-swatch;
}
&::-moz-color-swatch {
@include color-swatch;
}
}
// Date & Time
// :not() are needed to add Specificity and avoid !important on padding
input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]) {
&:is([type="date"], [type="datetime-local"], [type="month"], [type="time"], [type="week"]) {
--icon-position: 0.75rem;
--icon-width: 1rem;
padding-right: calc(var(--icon-width) + var(--icon-position));
background-image: var(--icon-date);
background-position: center right var(--icon-position);
background-size: var(--icon-width) auto;
background-repeat: no-repeat;
}
// Time
&[type="time"] {
background-image: var(--icon-time);
}
}
// Calendar picker
[type="date"],
[type="datetime-local"],
[type="month"],
[type="time"],
[type="week"] {
&::-webkit-calendar-picker-indicator {
width: var(--icon-width);
margin-right: calc(var(--icon-width) * -1);
margin-left: var(--icon-position);
opacity: 0;
}
}
[dir="rtl"]
:is([type="date"], [type="datetime-local"], [type="month"], [type="time"], [type="week"]) {
text-align: right;
}
// Calendar icons are hidden in Firefox
@if $enable-important {
@-moz-document url-prefix() {
[type="date"],
[type="datetime-local"],
[type="month"],
[type="time"],
[type="week"] {
padding-right: var(--form-element-spacing-horizontal) !important;
background-image: none !important;
}
}
}
// File
[type="file"] {
--color: var(--muted-color);
padding: calc(var(--form-element-spacing-vertical) * 0.5) 0;
border: 0;
border-radius: 0;
background: none;
@mixin file-selector-button {
--background-color: var(--secondary);
--border-color: var(--secondary);
--color: var(--secondary-inverse);
margin-right: calc(var(--spacing) / 2);
margin-left: 0;
margin-inline-start: 0;
margin-inline-end: calc(var(--spacing) / 2);
padding: calc(var(--form-element-spacing-vertical) * 0.5)
calc(var(--form-element-spacing-horizontal) * 0.5);
border: var(--border-width) solid var(--border-color);
border-radius: var(--border-radius);
outline: none;
background-color: var(--background-color);
box-shadow: var(--box-shadow);
color: var(--color);
font-weight: var(--font-weight);
font-size: 1rem;
line-height: var(--line-height);
text-align: center;
cursor: pointer;
@if $enable-transitions {
transition: background-color var(--transition),
border-color var(--transition), color var(--transition),
box-shadow var(--transition);
}
&:is(:hover, :active, :focus) {
--background-color: var(--secondary-hover);
--border-color: var(--secondary-hover);
}
}
&::file-selector-button {
@include file-selector-button;
}
&::-webkit-file-upload-button {
@include file-selector-button;
}
&::-ms-browse {
@include file-selector-button;
}
}
// Range
[type="range"] {
// Config
$height-track: 0.25rem;
$height-thumb: 1.25rem;
$border-thumb: 2px;
// Styles
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
width: 100%;
height: $height-thumb;
background: none;
// Slider Track
@mixin slider-track {
width: 100%;
height: $height-track;
border-radius: var(--border-radius);
background-color: var(--range-border-color);
@if $enable-transitions {
transition: background-color var(--transition),
box-shadow var(--transition);
}
}
&::-webkit-slider-runnable-track {
@include slider-track;
}
&::-moz-range-track {
@include slider-track;
}
&::-ms-track {
@include slider-track;
}
// Slider Thumb
@mixin slider-thumb {
-webkit-appearance: none;
width: $height-thumb;
height: $height-thumb;
margin-top: #{(-($height-thumb * 0.5) + ($height-track * 0.5))};
border: $border-thumb solid var(--range-thumb-border-color);
border-radius: 50%;
background-color: var(--range-thumb-color);
cursor: pointer;
@if $enable-transitions {
transition: background-color var(--transition),
transform var(--transition);
}
}
&::-webkit-slider-thumb {
@include slider-thumb;
}
&::-moz-range-thumb {
@include slider-thumb;
}
&::-ms-thumb {
@include slider-thumb;
}
&:hover,
&:focus {
--range-border-color: var(--range-active-border-color);
--range-thumb-color: var(--range-thumb-hover-color);
}
&:active {
--range-thumb-color: var(--range-thumb-active-color);
// Slider Thumb
&::-webkit-slider-thumb {
transform: scale(1.25);
}
&::-moz-range-thumb {
transform: scale(1.25);
}
&::-ms-thumb {
transform: scale(1.25);
}
}
}
// Search
// :not() are needed to add Specificity and avoid !important on padding
input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]) {
&[type="search"] {
padding-inline-start: calc(var(--form-element-spacing-horizontal) + 1.75rem);
border-radius: 5rem;
background-image: var(--icon-search);
background-position: center left 1.125rem;
background-size: 1rem auto;
background-repeat: no-repeat;
&[aria-invalid] {
@if $enable-important {
padding-inline-start: calc(var(--form-element-spacing-horizontal) + 1.75rem) !important;
}
@else {
padding-inline-start: calc(var(--form-element-spacing-horizontal) + 1.75rem);
}
background-position: center left 1.125rem, center right 0.75rem;
}
&[aria-invalid="false"] {
background-image: var(--icon-search), var(--icon-valid);
}
&[aria-invalid="true"] {
background-image: var(--icon-search), var(--icon-invalid);
}
}
}
// Cancel button
[type="search"] {
&::-webkit-search-cancel-button {
-webkit-appearance: none;
display: none;
}
}
[dir="rtl"] {
:where(input) {
&:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]) {
&[type="search"] {
background-position: center right 1.125rem;
&[aria-invalid] {
background-position: center right 1.125rem, center left 0.75rem;
}
}
}
}
}

View file

@ -0,0 +1,138 @@
/**
* Form elements
* Checkboxes & Radios
*/
[type="checkbox"],
[type="radio"] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
width: 1.25em;
height: 1.25em;
margin-top: -0.125em;
margin-right: 0.375em;
margin-left: 0;
margin-inline-start: 0;
margin-inline-end: 0.375em;
border-width: var(--border-width);
font-size: inherit;
vertical-align: middle;
cursor: pointer;
&::-ms-check {
display: none; // unstyle IE checkboxes
}
&:checked,
&:checked:active,
&:checked:focus {
--background-color: var(--primary);
--border-color: var(--primary);
background-image: var(--icon-checkbox);
background-position: center;
background-size: 0.75em auto;
background-repeat: no-repeat;
}
& ~ label {
display: inline-block;
margin-right: 0.375em;
margin-bottom: 0;
cursor: pointer;
}
}
// Checkboxes
[type="checkbox"] {
&:indeterminate {
--background-color: var(--primary);
--border-color: var(--primary);
background-image: var(--icon-minus);
background-position: center;
background-size: 0.75em auto;
background-repeat: no-repeat;
}
}
// Radios
[type="radio"] {
border-radius: 50%;
&:checked,
&:checked:active,
&:checked:focus {
--background-color: var(--primary-inverse);
border-width: 0.35em;
background-image: none;
}
}
// Switchs
[type="checkbox"][role="switch"] {
--background-color: var(--switch-background-color);
--border-color: var(--switch-background-color);
--color: var(--switch-color);
// Config
$switch-height: 1.25em;
$switch-width: 2.25em;
$switch-transition: 0.1s ease-in-out;
// Styles
width: $switch-width;
height: $switch-height;
border: var(--border-width) solid var(--border-color);
border-radius: $switch-height;
background-color: var(--background-color);
line-height: $switch-height;
&:focus {
--background-color: var(--switch-background-color);
--border-color: var(--switch-background-color);
}
&:checked {
--background-color: var(--switch-checked-background-color);
--border-color: var(--switch-checked-background-color);
}
&:before {
display: block;
width: calc(#{$switch-height} - (var(--border-width) * 2));
height: 100%;
border-radius: 50%;
background-color: var(--color);
content: "";
@if $enable-transitions {
transition: margin $switch-transition;
}
}
&:checked {
background-image: none;
&::before {
margin-left: calc(#{$switch-width * 0.5} - var(--border-width));
margin-inline-start: calc(#{$switch-width * 0.5} - var(--border-width));
}
}
}
// Aria-invalid
[type="checkbox"],
[type="checkbox"]:checked,
[type="radio"],
[type="radio"]:checked,
[type="checkbox"][role="switch"],
[type="checkbox"][role="switch"]:checked {
&[aria-invalid="false"] {
--border-color: var(--form-element-valid-border-color);
}
&[aria-invalid="true"] {
--border-color: var(--form-element-invalid-border-color);
}
}

View file

@ -0,0 +1,352 @@
/**
* Form elements
*/
// Reboot based on :
// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// 1. Change the font styles in all browsers
// 2. Remove the margin in Firefox and Safari
input,
optgroup,
select,
textarea {
margin: 0; // 2
font-size: 1rem; // 1
line-height: var(--line-height); // 1
font-family: inherit; // 1
letter-spacing: inherit; // 2
}
// Show the overflow in IE.
input {
overflow: visible;
}
// Remove the inheritance of text transform in Edge, Firefox, and IE
select {
text-transform: none;
}
// 1. Correct the text wrapping in Edge and IE
// 2. Correct the color inheritance from `fieldset` elements in IE
// 3. Remove the padding so developers are not caught out when they zero out
// `fieldset` elements in all browsers
legend {
max-width: 100%; // 1
padding: 0; // 3
color: inherit; // 2
white-space: normal; // 1
}
// 1. Remove the default vertical scrollbar in IE
textarea {
overflow: auto; // 1
}
// Remove the padding in IE 10
[type="checkbox"],
[type="radio"] {
padding: 0;
}
// Correct the cursor style of increment and decrement buttons in Safari
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
// 1. Correct the odd appearance in Chrome and Safari
// 2. Correct the outline style in Safari
[type="search"] {
-webkit-appearance: textfield; // 1
outline-offset: -2px; // 2
}
// Remove the inner padding in Chrome and Safari on macOS
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
// 1. Correct the inability to style clickable types in iOS and Safari
// 2. Change font properties to `inherit` in Safari
::-webkit-file-upload-button {
-webkit-appearance: button; // 1
font: inherit; // 2
}
// Remove the inner border and padding of focus outlines in Firefox
::-moz-focus-inner {
padding: 0;
border-style: none;
}
// Remove the focus outline in Firefox
:-moz-focusring {
outline: none;
}
// Remove the additional :invalid styles in Firefox
:-moz-ui-invalid {
box-shadow: none;
}
// Change the inconsistent appearance in IE (opinionated)
::-ms-expand {
display: none;
}
// Remove the border and padding in all browsers (opinionated)
[type="file"],
[type="range"] {
padding: 0;
border-width: 0;
}
// Pico
//
// Force height for alternatives input types
input:not([type="checkbox"], [type="radio"], [type="range"]) {
height: calc(
(1rem * var(--line-height)) + (var(--form-element-spacing-vertical) * 2) +
(var(--border-width) * 2)
);
}
// Fieldset
fieldset {
margin: 0;
margin-bottom: var(--spacing);
padding: 0;
border: 0;
}
// Label & legend
label,
fieldset legend {
display: block;
margin-bottom: calc(var(--spacing) * 0.25);
font-weight: var(--form-label-font-weight, var(--font-weight));
}
// Blocks, 100%
input:not([type="checkbox"], [type="radio"]),
select,
textarea {
width: 100%;
}
// Reset appearance (Not Checkboxes, Radios, Range and File)
input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]),
select,
textarea {
appearance: none;
padding: var(--form-element-spacing-vertical)
var(--form-element-spacing-horizontal);
}
// Commons styles
input,
select,
textarea {
--background-color: var(--form-element-background-color);
--border-color: var(--form-element-border-color);
--color: var(--form-element-color);
--box-shadow: none;
border: var(--border-width) solid var(--border-color);
border-radius: var(--border-radius);
outline: none;
background-color: var(--background-color);
box-shadow: var(--box-shadow);
color: var(--color);
font-weight: var(--font-weight);
@if $enable-transitions {
transition: background-color var(--transition),
border-color var(--transition), color var(--transition),
box-shadow var(--transition);
}
}
// Active & Focus
input:not([type="submit"], [type="button"], [type="reset"], [type="checkbox"], [type="radio"], [readonly]),
:where(select, textarea) {
&:is(:active, :focus) {
--background-color: var(--form-element-active-background-color);
}
}
// Active & Focus
input:not([type="submit"], [type="button"], [type="reset"], [role="switch"], [readonly]),
:where(select, textarea) {
&:is(:active, :focus) {
--border-color: var(--form-element-active-border-color);
}
}
// Focus
input:not([type="submit"], [type="button"], [type="reset"], [type="range"], [type="file"], [readonly]),
select,
textarea {
&:focus {
--box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color);
}
}
// Disabled
input:not([type="submit"], [type="button"], [type="reset"])[disabled],
select[disabled],
textarea[disabled],
:where(fieldset[disabled]) :is(input:not([type="submit"], [type="button"], [type="reset"]), select, textarea) {
--background-color: var(--form-element-disabled-background-color);
--border-color: var(--form-element-disabled-border-color);
opacity: var(--form-element-disabled-opacity);
pointer-events: none;
}
// Aria-invalid
:where(input, select, textarea) {
&:not([type="checkbox"], [type="radio"], [type="date"], [type="datetime-local"], [type="month"], [type="time"], [type="week"]) {
&[aria-invalid] {
@if $enable-important {
padding-right: calc(
var(--form-element-spacing-horizontal) + 1.5rem
) !important;
padding-left: var(--form-element-spacing-horizontal);
padding-inline-start: var(--form-element-spacing-horizontal) !important;
padding-inline-end: calc(
var(--form-element-spacing-horizontal) + 1.5rem
) !important;
}
@else {
padding-right: calc(var(--form-element-spacing-horizontal) + 1.5rem);
padding-left: var(--form-element-spacing-horizontal);
padding-inline-start: var(--form-element-spacing-horizontal);
padding-inline-end: calc(var(--form-element-spacing-horizontal) + 1.5rem);
}
background-position: center right 0.75rem;
background-size: 1rem auto;
background-repeat: no-repeat;
}
&[aria-invalid="false"] {
background-image: var(--icon-valid);
}
&[aria-invalid="true"] {
background-image: var(--icon-invalid);
}
}
&[aria-invalid="false"] {
--border-color: var(--form-element-valid-border-color);
&:is(:active, :focus) {
@if $enable-important {
--border-color: var(--form-element-valid-active-border-color) !important;
--box-shadow: 0 0 0 var(--outline-width) var(--form-element-valid-focus-color) !important;
}
@else {
--border-color: var(--form-element-valid-active-border-color);
--box-shadow: 0 0 0 var(--outline-width) var(--form-element-valid-focus-color);
}
}
}
&[aria-invalid="true"] {
--border-color: var(--form-element-invalid-border-color);
&:is(:active, :focus) {
@if $enable-important {
--border-color: var(--form-element-invalid-active-border-color) !important;
--box-shadow: 0 0 0 var(--outline-width) var(--form-element-invalid-focus-color) !important;
}
@else {
--border-color: var(--form-element-invalid-active-border-color);
--box-shadow: 0 0 0 var(--outline-width) var(--form-element-invalid-focus-color);
}
}
}
}
[dir="rtl"] {
:where(input, select, textarea) {
&:not([type="checkbox"], [type="radio"]) {
&:is([aria-invalid], [aria-invalid="true"], [aria-invalid="false"] ){
background-position: center left 0.75rem;
}
}
}
}
// Placeholder
input::placeholder,
input::-webkit-input-placeholder,
textarea::placeholder,
textarea::-webkit-input-placeholder,
select:invalid {
color: var(--form-element-placeholder-color);
opacity: 1;
}
// Margin bottom (Not Checkboxes and Radios)
input:not([type="checkbox"], [type="radio"]),
select,
textarea {
margin-bottom: var(--spacing);
}
// Select
select {
// Unstyle the caret on `<select>`s in IE10+.
&::-ms-expand {
border: 0;
background-color: transparent;
}
&:not([multiple], [size]) {
padding-right: calc(var(--form-element-spacing-horizontal) + 1.5rem);
padding-left: var(--form-element-spacing-horizontal);
padding-inline-start: var(--form-element-spacing-horizontal);
padding-inline-end: calc(var(--form-element-spacing-horizontal) + 1.5rem);
background-image: var(--icon-chevron);
background-position: center right 0.75rem;
background-size: 1rem auto;
background-repeat: no-repeat;
}
}
[dir="rtl"] {
select {
&:not([multiple], [size]) {
background-position: center left 0.75rem;
}
}
}
// Helper
$inputs: "input, select, textarea";
@if ($enable-classes and $enable-grid) {
$inputs: $inputs + ", .grid";
}
:where(#{$inputs}) {
+ small {
display: block;
width: 100%;
margin-top: calc(var(--spacing) * -0.75);
margin-bottom: var(--spacing);
color: var(--muted-color);
}
}
// Styles for Input inside a label
label {
> :where(input, select, textarea) {
margin-top: calc(var(--spacing) * 0.25);
}
}

View file

@ -0,0 +1,33 @@
/**
* Miscs
*/
// Reboot based on :
// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// 1. Correct the inheritance of border color in Firefox
// 2. Add the correct box sizing in Firefox
hr {
height: 0; // 2
border: 0;
border-top: 1px solid var(--muted-border-color);
color: inherit; // 1
}
// Add the correct display in IE 10+
[hidden],
template {
@if $enable-important {
display: none !important;
}
@else {
display: none;
}
}
// Add the correct display in IE 9-
canvas {
display: inline-block;
}

View file

@ -0,0 +1,50 @@
/**
* Table
*/
// Reboot based on :
// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// 1. Collapse border spacing in all browsers (opinionated)
// 2. Remove text indentation from table contents in Chrome, Edge, and Safari
:where(table) {
width: 100%;
border-collapse: collapse; // 1
border-spacing: 0;
text-indent: 0; // 2
}
// Pico
//
// Cells
th,
td {
padding: calc(var(--spacing) / 2) var(--spacing);
border-bottom: var(--border-width) solid var(--table-border-color);
color: var(--color);
font-weight: var(--font-weight);
font-size: var(--font-size);
text-align: left;
text-align: start;
}
// Footer
tfoot {
th,
td {
border-top: var(--border-width) solid var(--table-border-color);
border-bottom: 0;
}
}
// Striped
table {
&[role="grid"] {
tbody tr:nth-child(odd) {
background-color: var(--table-row-stripped-background-color);
}
}
}

View file

@ -0,0 +1,264 @@
/**
* Typography
*/
// Reboot based on :
// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// Add the correct font weight in Chrome, Edge, and Safari
b,
strong {
font-weight: bolder;
}
// Prevent `sub` and `sup` elements from affecting the line height in all browsers
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
// Pico
//
address,
blockquote,
dl,
figure,
form,
ol,
p,
pre,
table,
ul {
margin-top: 0;
margin-bottom: var(--typography-spacing-vertical);
color: var(--color);
font-style: normal;
font-weight: var(--font-weight);
font-size: var(--font-size);
}
// Links
// 1. Remove the gray background on active links in IE 10
a,
[role="link"] {
--color: var(--primary);
--background-color: transparent;
outline: none;
background-color: var(--background-color); // 1
color: var(--color);
text-decoration: var(--text-decoration);
@if $enable-transitions {
transition: background-color var(--transition), color var(--transition),
text-decoration var(--transition), box-shadow var(--transition);
}
&:is([aria-current], :hover, :active, :focus) {
--color: var(--primary-hover);
--text-decoration: underline;
}
&:focus {
--background-color: var(--primary-focus);
}
@if $enable-classes {
// Secondary
&.secondary {
--color: var(--secondary);
&:is([aria-current], :hover, :active, :focus) {
--color: var(--secondary-hover);
}
&:focus {
--background-color: var(--secondary-focus);
}
}
// Contrast
&.contrast {
--color: var(--contrast);
&:is([aria-current], :hover, :active, :focus) {
--color: var(--contrast-hover);
}
&:focus {
--background-color: var(--contrast-focus);
}
}
}
}
// Headings
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 0;
margin-bottom: var(--typography-spacing-vertical);
color: var(--color);
font-weight: var(--font-weight);
font-size: var(--font-size);
font-family: var(--font-family);
}
h1 {
--color: var(--h1-color);
}
h2 {
--color: var(--h2-color);
}
h3 {
--color: var(--h3-color);
}
h4 {
--color: var(--h4-color);
}
h5 {
--color: var(--h5-color);
}
h6 {
--color: var(--h6-color);
}
// Margin-top for headings after a typography block
:where(address, blockquote, dl, figure, form, ol, p, pre, table, ul) {
~ :is(h1, h2, h3, h4, h5, h6) {
margin-top: var(--typography-spacing-vertical);
}
}
// Heading group
@if $enable-classes == false {
hgroup {
margin-bottom: var(--typography-spacing-vertical);
> * {
margin-bottom: 0;
}
> *:last-child {
--color: var(--muted-color);
--font-weight: unset;
font-size: 1rem;
font-family: unset;
}
}
}
@if $enable-classes {
hgroup,
.headings {
margin-bottom: var(--typography-spacing-vertical);
> * {
margin-bottom: 0;
}
> *:last-child {
--color: var(--muted-color);
--font-weight: unset;
font-size: 1rem;
font-family: unset;
}
}
}
// Paragraphs
p {
margin-bottom: var(--typography-spacing-vertical);
}
// Small
small {
font-size: var(--font-size);
}
// Lists
:where(dl, ol, ul) {
padding-right: 0;
padding-left: var(--spacing);
padding-inline-start: var(--spacing);
padding-inline-end: 0;
li {
margin-bottom: calc(var(--typography-spacing-vertical) * 0.25);
}
}
// Margin-top for nested lists
// 1. Remove the margin on nested lists in Chrome, Edge, IE, and Safari
:where(dl, ol, ul) {
:is(dl, ol, ul) {
margin: 0; // 1
margin-top: calc(var(--typography-spacing-vertical) * 0.25);
}
}
ul li {
list-style: square;
}
// Highlighted text
mark {
padding: 0.125rem 0.25rem;
background-color: var(--mark-background-color);
color: var(--mark-color);
vertical-align: baseline;
}
// Blockquote
blockquote {
display: block;
margin: var(--typography-spacing-vertical) 0;
padding: var(--spacing);
border-right: none;
border-left: 0.25rem solid var(--blockquote-border-color);
border-inline-start: 0.25rem solid var(--blockquote-border-color);
border-inline-end: none;
footer {
margin-top: calc(var(--typography-spacing-vertical) * 0.5);
color: var(--blockquote-footer-color);
}
}
// Abbreviations
// 1. Remove underline decoration in Chrome, Edge, IE, Opera, and Safari
abbr[title] {
border-bottom: 1px dotted;
text-decoration: none; // 1
cursor: help;
}
// Ins
ins {
color: var(--ins-color);
text-decoration: none;
}
// del
del {
color: var(--del-color);
}
// selection
::selection {
background-color: var(--primary-focus);
}

View file

@ -0,0 +1,42 @@
@if ($enable-class-container and $enable-classes) {
/**
* Container
*/
.container,
.container-fluid {
width: 100%;
margin-right: auto;
margin-left: auto;
padding-right: var(--spacing);
padding-left: var(--spacing);
}
.container {
@if map-get($breakpoints, "sm") {
@media (min-width: map-get($breakpoints, "sm")) {
max-width: map-get($viewports, "sm");
padding-right: 0;
padding-left: 0;
}
}
@if map-get($breakpoints, "md") {
@media (min-width: map-get($breakpoints, "md")) {
max-width: map-get($viewports, "md");
}
}
@if map-get($breakpoints, "lg") {
@media (min-width: map-get($breakpoints, "lg")) {
max-width: map-get($viewports, "lg");
}
}
@if map-get($breakpoints, "xl") {
@media (min-width: map-get($breakpoints, "xl")) {
max-width: map-get($viewports, "xl");
}
}
}
}

View file

@ -0,0 +1,48 @@
/**
* Document
* Content-box & Responsive typography
*/
// Reboot based on :
// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// 1. Add border box sizing in all browsers (opinionated)
// 2. Backgrounds do not repeat by default (opinionated)
*,
*::before,
*::after {
box-sizing: border-box; // 1
background-repeat: no-repeat; // 2
}
// 1. Add text decoration inheritance in all browsers (opinionated)
// 2. Add vertical alignment inheritance in all browsers (opinionated)
::before,
::after {
text-decoration: inherit; // 1
vertical-align: inherit; // 2
}
// 1. Use the default cursor in all browsers (opinionated)
// 2. Change the line height in all browsers (opinionated)
// 3. Breaks words to prevent overflow in all browsers (opinionated)
// 4. Use a 4-space tab width in all browsers (opinionated)
// 5. Remove the grey highlight on links in iOS (opinionated)
// 6. Prevent adjustments of font size after orientation changes in iOS
:where(:root) {
-webkit-tap-highlight-color: transparent; // 5
-webkit-text-size-adjust: 100%; // 6
text-size-adjust: 100%; // 6
background-color: var(--background-color);
color: var(--color);
font-weight: var(--font-weight);
font-size: var(--font-size);
line-height: var(--line-height); // 2
font-family: var(--font-family);
text-rendering: optimizeLegibility;
overflow-wrap: break-word; // 3
cursor: default; // 1
tab-size: 4; // 4
}

View file

@ -0,0 +1,24 @@
@if ($enable-classes and $enable-grid) {
/**
* Grid
* Minimal grid system with auto-layout columns
*/
.grid {
grid-column-gap: var(--grid-spacing-horizontal);
grid-row-gap: var(--grid-spacing-vertical);
display: grid;
grid-template-columns: 1fr;
margin: 0;
@if map-get($breakpoints, "lg") {
@media (min-width: map-get($breakpoints, "lg")) {
grid-template-columns: repeat(auto-fit, minmax(0%, 1fr));
}
}
& > * {
min-width: 0; // HACK for childs in overflow
}
}
}

View file

@ -0,0 +1,16 @@
/**
* Horizontal scroller (<figure>)
*/
// Wrapper to make any content responsive across all viewports
figure {
display: block;
margin: 0;
padding: 0;
overflow-x: auto;
figcaption {
padding: calc(var(--spacing) * 0.5) 0;
color: var(--muted-color);
}
}

View file

@ -0,0 +1,8 @@
/**
* Section
* Responsive spacings for section
*/
section {
margin-bottom: var(--block-spacing-vertical);
}

View file

@ -0,0 +1,70 @@
/**
* Sectioning
* Container and responsive spacings for header, main, footer
*/
// Reboot based on :
// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// Render the `main` element consistently in IE
main {
display: block;
}
// Pico
//
// 1. Remove the margin in all browsers (opinionated)
#{$semantic-root-element} {
width: 100%;
margin: 0; // 1
> header,
> main,
> footer {
width: 100%;
margin-right: auto;
margin-left: auto;
// Semantic container
@if $enable-semantic-container {
padding: var(--block-spacing-vertical) var(--block-spacing-horizontal);
// Centered viewport
@if $enable-viewport {
@if map-get($breakpoints, "sm") and $enable-viewport {
@media (min-width: map-get($breakpoints, "sm")) {
max-width: map-get($viewports, "sm");
padding-right: 0;
padding-left: 0;
}
}
@if map-get($breakpoints, "md") and $enable-viewport {
@media (min-width: map-get($breakpoints, "md")) {
max-width: map-get($viewports, "md");
}
}
@if map-get($breakpoints, "lg") and $enable-viewport {
@media (min-width: map-get($breakpoints, "lg")) {
max-width: map-get($viewports, "lg");
}
}
@if map-get($breakpoints, "xl") and $enable-viewport {
@media (min-width: map-get($breakpoints, "xl")) {
max-width: map-get($viewports, "xl");
}
}
}
}
// Semantic container
@else {
padding: var(--block-spacing-vertical) 0;
}
}
}

View file

@ -0,0 +1,13 @@
// Config
// --------------------
// Enable <header>, <main>, <footer> inside $semantic-root-element as containers
$enable-semantic-container: true;
// Enable .classes
$enable-classes: false;
// Pico Lib
// --------------------
@import "pico";

View file

@ -0,0 +1,16 @@
// Config
// --------------------
// Enable <header>, <main>, <footer> inside $semantic-root-element as containers
$enable-semantic-container: true;
// Enable a centered viewport for <header>, <main>, <footer> inside $enable-semantic-container
$enable-viewport: false;
// Enable .classes
$enable-classes: false;
// Pico Lib
// --------------------
@import "pico";

View file

@ -0,0 +1,43 @@
/*!
* Pico CSS v1.5.11 (https://picocss.com)
* Copyright 2019-2023 - Licensed under MIT
*/
// Config
@import "variables";
// Theming
@import "themes/default";
// Layout
@import "layout/document"; // html
@import "layout/sectioning"; // body, header, main, footer
@import "layout/container"; // .container, .container-fluid
@import "layout/section"; // section
@import "layout/grid"; // .grid
@import "layout/scroller"; // figure
// Content
@import "content/typography"; // a, headings, p, ul, blockquote, ...
@import "content/embedded"; // audio, canvas, iframe, img, svg, video
@import "content/button"; // button, a[role=button], type=button, type=submit ...
@import "content/form"; // input, select, textarea, label, fieldset, legend
@import "content/form-checkbox-radio"; // type=checkbox, type=radio, role=switch
@import "content/form-alt-input-types"; // type=color, type=date, type=file, type=search, ...
@import "content/table"; // table, tr, td, ...
@import "content/code"; // pre, code, ...
@import "content/miscs"; // hr, template, [hidden], dialog, canvas
// Components
@import "components/accordion"; // details, summary
@import "components/card"; // article
@import "components/modal"; // dialog
@import "components/nav"; // nav
@import "components/progress"; // progress
@import "components/dropdown"; // dropdown
// Utilities
@import "utilities/loading"; // aria-busy=true
@import "utilities/tooltip"; // data-tooltip
@import "utilities/accessibility"; // -ms-touch-action, aria-*
@import "utilities/reduce-motion"; // prefers-reduced-motion

View file

@ -0,0 +1,47 @@
/*!
* Pico CSS v1.5.11 (https://picocss.com)
* Copyright 2019-2023 - Licensed under MIT
*
* Slim version example
* You can export only the modules you need
*/
// Config
// --------------------
// Enable responsive spacings for <header>, <main>, <footer>, <section>, <article>
$enable-responsive-spacings: false;
// Enable transitions
$enable-transitions: false;
// Enable overriding with !important
$enable-important: false;
// Pico Lib
// --------------------
// Config
@import "variables";
// Theming
@import "themes/default";
// Layout
@import "layout/document"; // html
@import "layout/sectioning"; // body, header, main, footer
@import "layout/container"; // .container, .container-fluid
@import "layout/section"; // section
@import "layout/grid"; // .grid
@import "layout/scroller"; // figure
// Content
@import "content/typography"; // a, headings, p, ul, blockquote, ...
@import "content/embedded"; // audio, canvas, iframe, img, svg, video
@import "content/button"; // button, a[role=button], type=button, type=submit ...
@import "content/form"; // input, select, textarea, label, fieldset, legend
@import "content/table"; // table, tr, td, ...
// Utilities
@import "utilities/accessibility"; // -ms-touch-action, aria-*
@import "utilities/reduce-motion"; // prefers-reduced-motion

View file

@ -0,0 +1,37 @@
/**
* Theme: default
*/
// Variables
@import "../variables";
@import "default/colors";
// Commons styles
@import "default/styles";
// Light theme (Default)
// Can be forced with data-theme="light"
@import "default/light";
// Dark theme (Auto)
// Automatically enabled if user has Dark mode enabled
@import "default/dark";
@media only screen and (prefers-color-scheme: dark) {
:root:not([data-theme]) {
@include dark;
}
}
// Dark theme (Forced)
// Enabled if forced with data-theme="dark"
[data-theme="dark"] {
@include dark;
}
// Accent-color
progress,
[type="checkbox"],
[type="radio"],
[type="range"] {
accent-color: var(--primary);
}

View file

@ -0,0 +1,65 @@
// Navy-Grey
$grey-hue: 205 !default;
$grey-50: hsl($grey-hue, 20%, 94%) !default;
$grey-100: hsl($grey-hue, 18%, 86%) !default;
$grey-200: hsl($grey-hue, 16%, 77%) !default;
$grey-300: hsl($grey-hue, 14%, 68%) !default;
$grey-400: hsl($grey-hue, 12%, 59%) !default;
$grey-500: hsl($grey-hue, 10%, 50%) !default;
$grey-600: hsl($grey-hue, 15%, 41%) !default;
$grey-700: hsl($grey-hue, 20%, 32%) !default;
$grey-800: hsl($grey-hue, 25%, 23%) !default;
$grey-900: hsl($grey-hue, 30%, 15%) !default;
// Light Blue
$primary-hue: 195 !default;
$primary-50: hsl($primary-hue, 90%, 94%) !default;
$primary-100: hsl($primary-hue, 88%, 86%) !default;
$primary-200: hsl($primary-hue, 86%, 77%) !default;
$primary-300: hsl($primary-hue, 84%, 68%) !default;
$primary-400: hsl($primary-hue, 82%, 59%) !default;
$primary-500: hsl($primary-hue, 80%, 50%) !default;
$primary-600: hsl($primary-hue, 85%, 41%) !default;
$primary-700: hsl($primary-hue, 90%, 32%) !default;
$primary-800: hsl($primary-hue, 95%, 23%) !default;
$primary-900: hsl($primary-hue, 100%, 15%) !default;
// Black & White
$black: #000 !default;
$white: #fff !default;
// Amber
$amber-50: #fff8e1 !default;
$amber-100: #ffecb3 !default;
$amber-200: #ffe082 !default;
$amber-300: #ffd54f !default;
$amber-400: #ffca28 !default;
$amber-500: #ffc107 !default;
$amber-600: #ffb300 !default;
$amber-700: #ffa000 !default;
$amber-800: #ff8f00 !default;
$amber-900: #ff6f00 !default;
// Green
$green-50: #e8f5e9 !default;
$green-100: #c8e6c9 !default;
$green-200: #a5d6a7 !default;
$green-300: #81c784 !default;
$green-400: #66bb6a !default;
$green-500: #4caf50 !default;
$green-600: #43a047 !default;
$green-700: #388e3c !default;
$green-800: #2e7d32 !default;
$green-900: #1b5e20 !default;
// Red
$red-50: #ffebee !default;
$red-100: #ffcdd2 !default;
$red-200: #ef9a9a !default;
$red-300: #e57373 !default;
$red-400: #ef5350 !default;
$red-500: #f44336 !default;
$red-600: #e53935 !default;
$red-700: #d32f2f !default;
$red-800: #c62828 !default;
$red-900: #b71c1c !default;

View file

@ -0,0 +1,159 @@
@import "../../functions";
// Default: Dark theme
@mixin dark {
--background-color: #{mix($black, $grey-900, 37.5%)};
// Texts colors
--color: #{$grey-200};
--h1-color: #{$grey-50};
--h2-color: #{mix($grey-100, $grey-50)};
--h3-color: #{$grey-100};
--h4-color: #{mix($grey-200, $grey-100)};
--h5-color: #{$grey-200};
--h6-color: #{mix($grey-300, $grey-200)};
// Muted colors
--muted-color: #{$grey-500};
--muted-border-color: #{mix($grey-900, $grey-800, 75%)};
// Primary colors
--primary: #{$primary-600};
--primary-hover: #{$primary-500};
--primary-focus: #{rgba($primary-600, 0.25)};
--primary-inverse: #{$white};
// Secondary colors
--secondary: #{$grey-600};
--secondary-hover: #{$grey-500};
--secondary-focus: #{rgba($grey-500, 0.25)};
--secondary-inverse: #{$white};
// Contrast colors
--contrast: #{$grey-50};
--contrast-hover: #{$white};
--contrast-focus: #{rgba($grey-500, 0.25)};
--contrast-inverse: #{$black};
// Highlighted text (<mark>)
--mark-background-color: #{mix($grey-300, $amber-300)};
--mark-color: #{mix($black, $grey-900, 37.5%)};
// Inserted (<ins>) & Deleted (<ins>)
--ins-color: #{$green-700};
--del-color: #{$red-800};
// Blockquote
--blockquote-border-color: var(--muted-border-color);
--blockquote-footer-color: var(--muted-color);
// Button
// To disable box-shadow, remove the var or set to '0 0 0 rgba(0, 0, 0, 0)'
// Don't use, 'none, 'false, 'null', '0', etc.
--button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
--button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
// Form elements
--form-element-background-color: #{mix($black, $grey-900, 37.5%)};
--form-element-border-color: #{mix($grey-800, $grey-700)};
--form-element-color: var(--color);
--form-element-placeholder-color: var(--muted-color);
--form-element-active-background-color: var(--form-element-background-color);
--form-element-active-border-color: var(--primary);
--form-element-focus-color: var(--primary-focus);
--form-element-disabled-background-color: #{$grey-800};
--form-element-disabled-border-color: #{$grey-700};
--form-element-disabled-opacity: 0.5;
--form-element-invalid-border-color: #{$red-900};
--form-element-invalid-active-border-color: #{$red-800};
--form-element-invalid-focus-color: #{rgba($red-800, 0.25)};
--form-element-valid-border-color: #{$green-800};
--form-element-valid-active-border-color: #{$green-700};
--form-element-valid-focus-color: #{rgba($green-700, 0.25)};
// Switch (input[type="checkbox"][role="switch"])
--switch-background-color: #{mix($grey-800, $grey-700)};
--switch-color: var(--primary-inverse);
--switch-checked-background-color: var(--primary);
// Range (input[type="range"])
--range-border-color: #{mix($grey-900, $grey-800)};
--range-active-border-color: #{$grey-800};
--range-thumb-border-color: var(--background-color);
--range-thumb-color: var(--secondary);
--range-thumb-hover-color: var(--secondary-hover);
--range-thumb-active-color: var(--primary);
// Table
--table-border-color: var(--muted-border-color);
--table-row-stripped-background-color: #{rgba($grey-500, 0.05)};
// Code
--code-background-color: #{mix($black, $grey-900, 12.5%)};
--code-color: var(--muted-color);
--code-kbd-background-color: var(--contrast);
--code-kbd-color: var(--contrast-inverse);
--code-tag-color: #{hsl(330, 30%, 50%)};
--code-property-color: #{hsl(185, 30%, 50%)};
--code-value-color: #{hsl(40, 10%, 50%)};
--code-comment-color: #{mix($grey-700, $grey-600)};
// Accordion (<details>)
--accordion-border-color: var(--muted-border-color);
--accordion-active-summary-color: var(--primary);
--accordion-close-summary-color: var(--color);
--accordion-open-summary-color: var(--muted-color);
// Card (<article>)
$box-shadow-elevation: 1rem;
$box-shadow-blur-strengh: 6rem;
$box-shadow-opacity: 0.06;
--card-background-color: #{mix($black, $grey-900, 25%)};
--card-border-color: var(--card-background-color);
--card-box-shadow:
#{($box-shadow-elevation * 0.5 * 0.029)} #{($box-shadow-elevation * 0.029)} #{($box-shadow-blur-strengh * 0.029)} #{rgba($black, ($box-shadow-opacity * 0.283))},
#{($box-shadow-elevation * 0.5 * 0.067)} #{($box-shadow-elevation * 0.067)} #{($box-shadow-blur-strengh * 0.067)} #{rgba($black, ($box-shadow-opacity * 0.4))},
#{($box-shadow-elevation * 0.5 * 0.125)} #{($box-shadow-elevation * 0.125)} #{($box-shadow-blur-strengh * 0.125)} #{rgba($black, ($box-shadow-opacity * 0.5))},
#{($box-shadow-elevation * 0.5 * 0.225)} #{($box-shadow-elevation * 0.225)} #{($box-shadow-blur-strengh * 0.225)} #{rgba($black, ($box-shadow-opacity * 0.6))},
#{($box-shadow-elevation * 0.5 * 0.417)} #{($box-shadow-elevation * 0.417)} #{($box-shadow-blur-strengh * 0.417)} #{rgba($black, ($box-shadow-opacity * 0.717))},
#{($box-shadow-elevation * 0.5)} #{$box-shadow-elevation} #{$box-shadow-blur-strengh} #{rgba($black, $box-shadow-opacity)},
0 0 0 0.0625rem #{rgba($black, ($box-shadow-opacity * 0.25) )};
--card-sectionning-background-color: #{mix($black, $grey-900, 12.5%)};
// Dropdown (<details role="list">)
--dropdown-background-color: #{$grey-900};
--dropdown-border-color: #{mix($grey-900, $grey-800)};
--dropdown-box-shadow: var(--card-box-shadow);
--dropdown-color: var(--color);
--dropdown-hover-background-color: #{rgba(mix($grey-900, $grey-800), 0.75)};
// Modal (<dialog>)
--modal-overlay-background-color: #{rgba(mix($grey-900, $grey-800), 0.8)};
// Progress
--progress-background-color: #{mix($grey-900, $grey-800)};
--progress-color: var(--primary);
// Loading ([aria-busy=true])
--loading-spinner-opacity: 0.5;
// Tooltip ([data-tooltip])
--tooltip-background-color: var(--contrast);
--tooltip-color: var(--contrast-inverse);
// Icons
--icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($white)}' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
--icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-300)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
--icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($white)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
--icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($black)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
--icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-500)}' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
--icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-300)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
--icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($red-900)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
--icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($white)}' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");
--icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-300)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
--icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-300)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
--icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($green-800)}' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
// Document
color-scheme: dark;
}

View file

@ -0,0 +1,159 @@
@import "../../functions";
// Default: Light theme
[data-theme="light"],
:root:not([data-theme="dark"]) {
--background-color: #{$white};
// Texts colors
--color: #{$grey-700};
--h1-color: #{$grey-900};
--h2-color: #{mix($grey-900, $grey-800)};
--h3-color: #{$grey-800};
--h4-color: #{mix($grey-800, $grey-700)};
--h5-color: #{$grey-700};
--h6-color: #{mix($grey-700, $grey-600)};
// Muted colors
--muted-color: #{$grey-500};
--muted-border-color: #{$grey-50};
// Primary colors
--primary: #{$primary-600};
--primary-hover: #{$primary-700};
--primary-focus: #{rgba($primary-600, 0.125)};
--primary-inverse: #{$white};
// Secondary colors
--secondary: #{$grey-600};
--secondary-hover: #{$grey-700};
--secondary-focus: #{rgba($grey-600, 0.125)};
--secondary-inverse: #{$white};
// Contrast colors
--contrast: #{$grey-900};
--contrast-hover: #{$black};
--contrast-focus: #{rgba($grey-600, 0.125)};
--contrast-inverse: #{$white};
// Highlighted text (<mark>)
--mark-background-color: #{mix($amber-100, $amber-50)};
--mark-color: #{mix($grey-900, $amber-900, 75%)};
// Inserted (<ins>) & Deleted (<ins>)
--ins-color: #{$green-700};
--del-color: #{$red-800};
// Blockquote
--blockquote-border-color: var(--muted-border-color);
--blockquote-footer-color: var(--muted-color);
// Button
// To disable box-shadow, remove the var or set to '0 0 0 rgba(0, 0, 0, 0)'
// Don't use, 'none, 'false, 'null', '0', etc.
--button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
--button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
// Form elements
--form-element-background-color: transparent;
--form-element-border-color: #{$grey-300};
--form-element-color: var(--color);
--form-element-placeholder-color: var(--muted-color);
--form-element-active-background-color: transparent;
--form-element-active-border-color: var(--primary);
--form-element-focus-color: var(--primary-focus);
--form-element-disabled-background-color: #{$grey-100};
--form-element-disabled-border-color: #{$grey-300};
--form-element-disabled-opacity: 0.5;
--form-element-invalid-border-color: #{$red-800};
--form-element-invalid-active-border-color: #{$red-700};
--form-element-invalid-focus-color: #{rgba($red-700, 0.125)};
--form-element-valid-border-color: #{$green-700};
--form-element-valid-active-border-color: #{$green-600};
--form-element-valid-focus-color: #{rgba($green-600, 0.125)};
// Switch (input[type="checkbox"][role="switch"])
--switch-background-color: #{$grey-200};
--switch-color: var(--primary-inverse);
--switch-checked-background-color: var(--primary);
// Range (input[type="range"])
--range-border-color: #{$grey-100};
--range-active-border-color: #{$grey-200};
--range-thumb-border-color: var(--background-color);
--range-thumb-color: var(--secondary);
--range-thumb-hover-color: var(--secondary-hover);
--range-thumb-active-color: var(--primary);
// Table
--table-border-color: var(--muted-border-color);
--table-row-stripped-background-color: #{mix($grey-50, $white)};
// Code
--code-background-color: #{$grey-50};
--code-color: var(--muted-color);
--code-kbd-background-color: var(--contrast);
--code-kbd-color: var(--contrast-inverse);
--code-tag-color: #{hsl(330, 40%, 50%)};
--code-property-color: #{hsl(185, 40%, 40%)};
--code-value-color: #{hsl(40, 20%, 50%)};
--code-comment-color: #{$grey-300};
// Accordion (<details>)
--accordion-border-color: var(--muted-border-color);
--accordion-close-summary-color: var(--color);
--accordion-open-summary-color: var(--muted-color);
// Card (<article>)
$box-shadow-elevation: 1rem;
$box-shadow-blur-strengh: 6rem;
$box-shadow-opacity: 0.06;
--card-background-color: var(--background-color);
--card-border-color: var(--muted-border-color);
--card-box-shadow:
#{($box-shadow-elevation * 0.5 * 0.029)} #{($box-shadow-elevation * 0.029)} #{($box-shadow-blur-strengh * 0.029)} #{rgba($grey-900, ($box-shadow-opacity * 0.283))},
#{($box-shadow-elevation * 0.5 * 0.067)} #{($box-shadow-elevation * 0.067)} #{($box-shadow-blur-strengh * 0.067)} #{rgba($grey-900, ($box-shadow-opacity * 0.4))},
#{($box-shadow-elevation * 0.5 * 0.125)} #{($box-shadow-elevation * 0.125)} #{($box-shadow-blur-strengh * 0.125)} #{rgba($grey-900, ($box-shadow-opacity * 0.5))},
#{($box-shadow-elevation * 0.5 * 0.225)} #{($box-shadow-elevation * 0.225)} #{($box-shadow-blur-strengh * 0.225)} #{rgba($grey-900, ($box-shadow-opacity * 0.6))},
#{($box-shadow-elevation * 0.5 * 0.417)} #{($box-shadow-elevation * 0.417)} #{($box-shadow-blur-strengh * 0.417)} #{rgba($grey-900, ($box-shadow-opacity * 0.717))},
#{($box-shadow-elevation * 0.5)} #{$box-shadow-elevation} #{$box-shadow-blur-strengh} #{rgba($grey-900, $box-shadow-opacity)},
0 0 0 0.0625rem #{rgba($grey-900, ($box-shadow-opacity * 0.25) )};
--card-sectionning-background-color: #{mix($grey-50, $white, 25%)};
// Dropdown (<details role="list">)
--dropdown-background-color: #{mix($grey-50, $white, 25%)};
--dropdown-border-color: #{mix($grey-100, $grey-50)};
--dropdown-box-shadow: var(--card-box-shadow);
--dropdown-color: var(--color);
--dropdown-hover-background-color: #{$grey-50};
// Modal (<dialog>)
--modal-overlay-background-color: #{rgba($grey-100, 0.7)};
// Progress
--progress-background-color: #{$grey-100};
--progress-color: var(--primary);
// Loading ([aria-busy=true])
--loading-spinner-opacity: 0.5;
// Tooltip ([data-tooltip])
--tooltip-background-color: var(--contrast);
--tooltip-color: var(--contrast-inverse);
// Icons
--icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($white)}' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
--icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-700)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
--icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($white)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
--icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($white)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
--icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-500)}' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
--icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-700)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
--icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($red-800)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
--icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($white)}' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");
--icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-700)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
--icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($grey-700)}' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
--icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='#{to-rgb($green-700)}' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
// Document
color-scheme: light;
}

View file

@ -0,0 +1,247 @@
// Commons Styles
:root {
// Typography
--font-family: system-ui, -apple-system, "Segoe UI", "Roboto", "Ubuntu",
"Cantarell", "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol", "Noto Color Emoji";
--line-height: 1.5;
--font-weight: 400;
--font-size: 16px;
// Responsive typography
@if $enable-responsive-typography {
@if map-get($breakpoints, "sm") {
@media (min-width: map-get($breakpoints, "sm")) {
--font-size: 17px;
}
}
@if map-get($breakpoints, "md") {
@media (min-width: map-get($breakpoints, "md")) {
--font-size: 18px;
}
}
@if map-get($breakpoints, "lg") {
@media (min-width: map-get($breakpoints, "lg")) {
--font-size: 19px;
}
}
@if map-get($breakpoints, "xl") {
@media (min-width: map-get($breakpoints, "xl")) {
--font-size: 20px;
}
}
}
// Borders
--border-radius: 0.25rem;
--border-width: 1px;
--outline-width: 3px;
// Spacings
--spacing: 1rem;
// Spacings for typography elements
--typography-spacing-vertical: 1.5rem;
// Spacings for body > header, body > main, body > footer, section, article
--block-spacing-vertical: calc(var(--spacing) * 2);
--block-spacing-horizontal: var(--spacing);
@if ($enable-classes and $enable-grid) {
--grid-spacing-vertical: 0;
--grid-spacing-horizontal: var(--spacing);
}
// Spacings for form elements and button
--form-element-spacing-vertical: 0.75rem;
--form-element-spacing-horizontal: 1rem;
// Spacings for nav component
--nav-element-spacing-vertical: 1rem;
--nav-element-spacing-horizontal: 0.5rem;
--nav-link-spacing-vertical: 0.5rem;
--nav-link-spacing-horizontal: 0.5rem;
// Font weight for form labels & fieldsets legend
--form-label-font-weight: var(--font-weight);
// Transitions
--transition: 0.2s ease-in-out;
// Modal (<dialog>)
--modal-overlay-backdrop-filter: blur(0.25rem);
}
// Responsives spacings
@if $enable-responsive-spacings {
// Sectioning
#{$semantic-root-element} > header,
#{$semantic-root-element} > main,
#{$semantic-root-element} > footer,
section {
@if map-get($breakpoints, "sm") {
@media (min-width: map-get($breakpoints, "sm")) {
--block-spacing-vertical: calc(var(--spacing) * 2.5);
}
}
@if map-get($breakpoints, "md") {
@media (min-width: map-get($breakpoints, "md")) {
--block-spacing-vertical: calc(var(--spacing) * 3);
}
}
@if map-get($breakpoints, "lg") {
@media (min-width: map-get($breakpoints, "lg")) {
--block-spacing-vertical: calc(var(--spacing) * 3.5);
}
}
@if map-get($breakpoints, "xl") {
@media (min-width: map-get($breakpoints, "xl")) {
--block-spacing-vertical: calc(var(--spacing) * 4);
}
}
}
// Card (<article>)
article {
@if map-get($breakpoints, "sm") {
@media (min-width: map-get($breakpoints, "sm")) {
--block-spacing-horizontal: calc(var(--spacing) * 1.25);
}
}
@if map-get($breakpoints, "md") {
@media (min-width: map-get($breakpoints, "md")) {
--block-spacing-horizontal: calc(var(--spacing) * 1.5);
}
}
@if map-get($breakpoints, "lg") {
@media (min-width: map-get($breakpoints, "lg")) {
--block-spacing-horizontal: calc(var(--spacing) * 1.75);
}
}
@if map-get($breakpoints, "xl") {
@media (min-width: map-get($breakpoints, "xl")) {
--block-spacing-horizontal: calc(var(--spacing) * 2);
}
}
}
// Modal
dialog > article {
--block-spacing-vertical: calc(var(--spacing) * 2);
--block-spacing-horizontal: var(--spacing);
@if map-get($breakpoints, "sm") {
@media (min-width: map-get($breakpoints, "sm")) {
--block-spacing-vertical: calc(var(--spacing) * 2.5);
--block-spacing-horizontal: calc(var(--spacing) * 1.25);
}
}
@if map-get($breakpoints, "md") {
@media (min-width: map-get($breakpoints, "md")) {
--block-spacing-vertical: calc(var(--spacing) * 3);
--block-spacing-horizontal: calc(var(--spacing) * 1.5);
}
}
}
}
// Link
a {
--text-decoration: none;
// Secondary & Contrast
@if $enable-classes {
&.secondary,
&.contrast {
--text-decoration: underline;
}
}
}
// Small
small {
--font-size: 0.875em;
}
// Headings
h1,
h2,
h3,
h4,
h5,
h6 {
--font-weight: 700;
}
h1 {
--font-size: 2rem;
--typography-spacing-vertical: 3rem;
}
h2 {
--font-size: 1.75rem;
--typography-spacing-vertical: 2.625rem;
}
h3 {
--font-size: 1.5rem;
--typography-spacing-vertical: 2.25rem;
}
h4 {
--font-size: 1.25rem;
--typography-spacing-vertical: 1.874rem;
}
h5 {
--font-size: 1.125rem;
--typography-spacing-vertical: 1.6875rem;
}
// Forms elements
[type="checkbox"],
[type="radio"] {
--border-width: 2px;
}
[type="checkbox"][role="switch"] {
--border-width: 3px;
}
// Table
thead,
tfoot {
th,
td {
--border-width: 3px;
}
}
:not(thead, tfoot) > * > td {
--font-size: 0.875em;
}
// Code
pre,
code,
kbd,
samp {
--font-family: "Menlo", "Consolas", "Roboto Mono", "Ubuntu Monospace",
"Noto Mono", "Oxygen Mono", "Liberation Mono", monospace,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
kbd {
--font-weight: bolder;
}

View file

@ -0,0 +1,52 @@
/**
* Accessibility & User interaction
*/
// Based on :
// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// Accessibility
// Change the cursor on control elements in all browsers (opinionated)
[aria-controls] {
cursor: pointer;
}
// Change the cursor on disabled, not-editable, or otherwise inoperable elements in all browsers (opinionated)
[aria-disabled="true"],
[disabled] {
cursor: not-allowed;
}
// Change the display on visually hidden accessible elements in all browsers (opinionated)
[aria-hidden="false"][hidden] {
display: initial;
}
[aria-hidden="false"][hidden]:not(:focus) {
clip: rect(0, 0, 0, 0);
position: absolute;
}
// User interaction
// Remove the tapping delay in IE 10
a,
area,
button,
input,
label,
select,
summary,
textarea,
[tabindex] {
-ms-touch-action: manipulation;
}
// Pico
//
[dir="rtl"] {
direction: rtl;
}

View file

@ -0,0 +1,58 @@
/**
* Loading ([aria-busy=true])
*/
// Cursor
[aria-busy="true"] {
cursor: progress;
}
// Everyting except form elements
[aria-busy="true"]:not(input, select, textarea, html) {
&::before {
display: inline-block;
width: 1em;
height: 1em;
border: 0.1875em solid currentColor;
border-radius: 1em;
border-right-color: transparent;
content: "";
vertical-align: text-bottom;
vertical-align: -.125em; // Visual alignment
animation: spinner 0.75s linear infinite;
opacity: var(--loading-spinner-opacity);
}
&:not(:empty) {
&::before {
margin-right: calc(var(--spacing) * 0.5);
margin-left: 0;
margin-inline-start: 0;
margin-inline-end: calc(var(--spacing) * 0.5);
}
}
&:empty {
text-align: center;
}
}
// Buttons and links
button,
input[type="submit"],
input[type="button"],
input[type="reset"],
a {
&[aria-busy="true"] {
pointer-events: none;
}
}
// Animation: rotate
@keyframes spinner {
to {
transform: rotate(360deg);
}
}

View file

@ -0,0 +1,27 @@
@if $enable-transitions and $enable-important {
/**
* Reduce Motion Features
*/
// Based on :
// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
//
// 1. Remove animations when motion is reduced (opinionated)
// 2. Remove fixed background attachments when motion is reduced (opinionated)
// 3. Remove timed scrolling behaviors when motion is reduced (opinionated)
// 4. Remove transitions when motion is reduced (opinionated)
@media (prefers-reduced-motion: reduce) {
*:not([aria-busy="true"]),
:not([aria-busy="true"])::before,
:not([aria-busy="true"])::after {
background-attachment: initial !important; // 2
animation-duration: 1ms !important; // 1
animation-delay: -1ms !important; // 1
animation-iteration-count: 1 !important; // 1
scroll-behavior: auto !important; // 3
transition-delay: 0s !important; // 4
transition-duration: 0s !important; // 4
}
}
}

View file

@ -0,0 +1,278 @@
/**
* Tooltip ([data-tooltip])
*/
[data-tooltip] {
position: relative;
&:not(a, button, input) {
border-bottom: 1px dotted;
text-decoration: none;
cursor: help;
}
&[data-placement="top"]::before,
&[data-placement="top"]::after,
&::before,
&::after {
display: block;
z-index: 99;
position: absolute;
bottom: 100%;
left: 50%;
padding: .25rem .5rem;
overflow: hidden;
transform: translate(-50%, -.25rem);
border-radius: var(--border-radius);
background: var(--tooltip-background-color);
content: attr(data-tooltip);
color: var(--tooltip-color);
font-style: normal;
font-weight: var(--font-weight);
font-size: .875rem;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
opacity: 0;
pointer-events: none;
}
// Caret
&[data-placement="top"]::after,
&::after {
padding: 0;
transform: translate(-50%, 0rem);
border-top: .3rem solid;
border-right: .3rem solid transparent;
border-left: .3rem solid transparent;
border-radius: 0;
background-color: transparent;
content: "";
color: var(--tooltip-background-color);
}
&[data-placement="bottom"] {
&::before,
&::after {
top: 100%;
bottom: auto;
transform: translate(-50%, .25rem);
}
&:after{
transform: translate(-50%, -.3rem);
border: .3rem solid transparent;
border-bottom: .3rem solid;
}
}
&[data-placement="left"] {
&::before,
&::after {
top: 50%;
right: 100%;
bottom: auto;
left: auto;
transform: translate(-.25rem, -50%);
}
&:after{
transform: translate(.3rem, -50%);
border: .3rem solid transparent;
border-left: .3rem solid;
}
}
&[data-placement="right"] {
&::before,
&::after {
top: 50%;
right: auto;
bottom: auto;
left: 100%;
transform: translate(.25rem, -50%);
}
&:after{
transform: translate(-.3rem, -50%);
border: .3rem solid transparent;
border-right: .3rem solid;
}
}
// Display
&:focus,
&:hover {
&::before,
&::after {
opacity: 1;
}
}
@if $enable-transitions {
// Animations, excluding touch devices
@media (hover: hover) and (pointer: fine) {
&[data-placement="bottom"]:focus,
&[data-placement="bottom"]:hover
&:focus,
&:hover {
&::before,
&::after {
animation-duration: .2s;
animation-name: tooltip-slide-top;
}
&::after {
animation-name: tooltip-caret-slide-top;
}
}
&[data-placement="bottom"] {
&:focus,
&:hover {
&::before,
&::after {
animation-duration: .2s;
animation-name: tooltip-slide-bottom;
}
&::after {
animation-name: tooltip-caret-slide-bottom;
}
}
}
&[data-placement="left"] {
&:focus,
&:hover {
&::before,
&::after {
animation-duration: .2s;
animation-name: tooltip-slide-left;
}
&::after {
animation-name: tooltip-caret-slide-left;
}
}
}
&[data-placement="right"] {
&:focus,
&:hover {
&::before,
&::after {
animation-duration: .2s;
animation-name: tooltip-slide-right;
}
&::after {
animation-name: tooltip-caret-slide-right;
}
}
}
}
@keyframes tooltip-slide-top {
from {
transform: translate(-50%, .75rem);
opacity: 0;
}
to {
transform: translate(-50%, -.25rem);
opacity: 1;
}
}
@keyframes tooltip-caret-slide-top {
from {
opacity: 0;
}
50% {
transform: translate(-50%, -.25rem);
opacity: 0;
}
to {
transform: translate(-50%, 0rem);
opacity: 1;
}
}
@keyframes tooltip-slide-bottom {
from {
transform: translate(-50%, -.75rem);
opacity: 0;
}
to {
transform: translate(-50%, .25rem);
opacity: 1;
}
}
@keyframes tooltip-caret-slide-bottom {
from {
opacity: 0;
}
50% {
transform: translate(-50%, -.5rem);
opacity: 0;
}
to {
transform: translate(-50%, -.3rem);
opacity: 1;
}
}
@keyframes tooltip-slide-left {
from {
transform: translate(.75rem, -50%);
opacity: 0;
}
to {
transform: translate(-.25rem, -50%);
opacity: 1;
}
}
@keyframes tooltip-caret-slide-left {
from {
opacity: 0;
}
50% {
transform: translate(.05rem, -50%);
opacity: 0;
}
to {
transform: translate(.3rem, -50%);
opacity: 1;
}
}
@keyframes tooltip-slide-right {
from {
transform: translate(-.75rem, -50%);
opacity: 0;
}
to {
transform: translate(.25rem, -50%);
opacity: 1;
}
}
@keyframes tooltip-caret-slide-right {
from {
opacity: 0;
}
50% {
transform: translate(-.05rem, -50%);
opacity: 0;
}
to {
transform: translate(-.3rem, -50%);
opacity: 1;
}
}
}
}

View file

@ -128,6 +128,7 @@ body>main {
line-height: 1.0em; line-height: 1.0em;
max-width: 8em; max-width: 8em;
padding: 5px; padding: 5px;
white-space: nowrap;
color: $roomstate_color_unknown; color: $roomstate_color_unknown;
@ -144,7 +145,7 @@ body>main {
} }
} }
// CCCHH Icon in Menu // CCCHH icon & hamburger menu in header
@media only screen and (prefers-color-scheme: light) { @media only screen and (prefers-color-scheme: light) {
.invert-on-light { .invert-on-light {
filter: invert(1); filter: invert(1);
@ -253,6 +254,167 @@ body>main {
box-shadow: var(--card-box-shadow); box-shadow: var(--card-box-shadow);
padding: 0; padding: 0;
margin: 0; margin: 0;
--main-header-content-height: calc(var(--font-size) * var(--line-height));
.container {
display: block flex;
position: relative;
flex-direction: row;
justify-content: start;
align-items: center;
column-gap: var(--spacing);
}
.menu-button,
.hamburger,
.in-nav-home {
// Don't display, when not in mobile mode.
display: none;
}
.menu {
// Set this to 100% to force the roomstate to "right-align".
width: 100%;
}
.ccchh-logo {
padding-top: var(--nav-element-spacing-vertical);
padding-bottom: var(--nav-element-spacing-vertical);
img {
height: var(--main-header-content-height);
}
}
// When the header content doesn't display nicely anymore, switch to mobile mode.
@import "../pico-1.5.11/scss/variables";
@media (max-width: map-get($breakpoints, md)) {
.hamburger-button {
display: unset;
position: absolute;
top: calc(var(--nav-element-spacing-vertical));
right: var(--spacing);
height: var(--main-header-content-height);
// To have an attempt at a good-looking cross, when converting the burger
// stack to one, set the width to the height / sin(45).
width: calc(var(--main-header-content-height) / 0.707106781);
}
.menu-button {
z-index: 3;
opacity: 0%;
border: 0;
margin: 0;
}
.hamburger {
display: flex;
flex-direction: column;
justify-content: space-between;
.hamburger-line {
height: 4px;
width: 100%;
background-color: white;
}
}
.in-nav-home {
display: unset;
}
// Don't display the menu per default in mobile mode.
.menu {
display: none;
}
.menu-button:checked~.menu {
display: unset;
position: fixed;
width: 100%;
height: 100%;
top: calc(var(--main-header-content-height) + (var(--nav-element-spacing-vertical) * 2) + 3px);
left: 0;
background-color: var(--background-color);
ul,
li {
display: block;
padding-top: calc(var(--nav-element-spacing-vertical) * 0.5);
padding-bottom: calc(var(--nav-element-spacing-vertical) * 0.5);
}
ul {
padding-left: var(--spacing);
padding-right: var(--spacing);
}
li {
padding-left: 0;
padding-right: 0;
border-bottom: 0.2em solid var(--muted-border-color);
display: flex;
// borrowed form pico css for li
margin-bottom: calc(var(--typography-spacing-vertical) * .25);
}
a {
flex-grow: 1;
}
.main-nav {
margin: auto;
}
// Use the media queries, which we need, from here:
@if map-get($breakpoints, "sm") {
@media (min-width: map-get($breakpoints, "sm")) {
ul {
padding-left: 0;
padding-right: 0;
}
.main-nav {
max-width: map-get($viewports, "sm");
}
}
}
}
.hamburger-line-top {
transform-origin: top right;
transition: all 0.4s ease-in-out;
}
.hamburger-line-middle {
transition: all 0.2s ease-in-out;
}
.hamburger-line-bottom {
transform-origin: bottom right;
transition: all 0.4s ease-in-out;
}
.menu-button:checked~.hamburger {
.hamburger-line-top {
// After some adjustments to make the cross look decent, rotate -45deg.
transform: translateX(-1.5px) translateY(-1.5px) rotate(-45deg);
}
.hamburger-line-middle {
transform: scaleY(0);
}
.hamburger-line-bottom {
// After some adjustments to make the cross look decent, rotate 45deg.
transform: translateX(-1.5px) translateY(1.5px) rotate(45deg);
}
}
}
} }

View file

@ -1,13 +1,14 @@
{{- $options := dict "transpiler" "libsass" "targetPath" "css/style.css" -}} {{- $cssOptionsMain := dict "transpiler" "libsass" "targetPath" "css/style.css" -}}
{{- $cssOptionsPico := dict "transpiler" "libsass" "targetPath" "css/pico.css" -}}
{{- $jsResources := resources.Match "js/*.js" }} {{- $jsResources := resources.Match "js/*.js" }}
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8"> <meta charset="utf-8">
{{- partial "robots.html" . -}} {{- partial "robots.html" . -}}
{{- with resources.GetRemote "https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css" }} {{ with resources.Get "pico-1.5.11/scss/pico.scss" | toCSS $cssOptionsPico | minify | fingerprint -}}
<link rel="stylesheet" href="{{ .RelPermalink }}" crossorigin="anonymous"> <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
{{ end }} {{- end }}
{{ with resources.Get "sass/main.scss" | toCSS $options | minify | fingerprint -}} {{ with resources.Get "sass/main.scss" | toCSS $cssOptionsMain | minify | fingerprint -}}
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
{{- end }} {{- end }}
<link rel="stylesheet" href="{{ .Site.BaseURL }}thirdparty/fontawesome6/css/all.min.css" crossorigin="anonymous"> <link rel="stylesheet" href="{{ .Site.BaseURL }}thirdparty/fontawesome6/css/all.min.css" crossorigin="anonymous">

View file

@ -1,8 +1,21 @@
<header class="main-header header"> <header class="main-header header">
<div class="container"> <div class="container">
{{ $image := resources.Get "images/logo.svg" }}
<a href="{{ .Site.Home.RelPermalink }}" class="ccchh-logo">
<img src="{{ $image.RelPermalink }}" class="invert-on-light" alt="CCCHH Icon">
</a>
<input class="menu-button hamburger-button" type="checkbox">
<div class="hamburger hamburger-button invert-on-light">
<div class="hamburger-line hamburger-line-top"></div>
<div class="hamburger-line hamburger-line-middle"></div>
<div class="hamburger-line hamburger-line-bottom"></div>
</div>
<nav class="menu"> <nav class="menu">
{{- partial "menu.html" (dict "menuID" "main" "page" . ) -}} {{- partial "menu.html" (dict "menuID" "main" "page" . ) -}}
</nav> </nav>
<div class="roomstate" id="roomstate">
<span class="state">unbekannt</span><br><span class="duration">(seit&nbsp;)</span>
</div>
</div> </div>
</header> </header>

View file

@ -2,10 +2,9 @@
{{- $menuID := .menuID -}} {{- $menuID := .menuID -}}
{{- $menuContent := index site.Menus .menuID -}} {{- $menuContent := index site.Menus .menuID -}}
<ul> <ul class="main-nav">
{{- if compare.Eq $menuID "main" -}} {{- if compare.Eq $menuID "main" -}}
{{- $image := resources.Get "images/logo.svg" }} <li><a href="/{{ .Site.Home.RelPermalink }}" class="in-nav-home">Home</a></li>
<li><a href="/{{ .Site.Home.URL }}"><img src="{{ $image.RelPermalink }}" class="invert-on-light" width="150px" alt="CCCHH Icon"></a></li>
{{- end }} {{- end }}
{{- range $menuContent }} {{- range $menuContent }}
<li> <li>
@ -22,10 +21,3 @@
>{{ or (T .Identifier) .Name | safeHTML }}</a></li> >{{ or (T .Identifier) .Name | safeHTML }}</a></li>
{{- end }} {{- end }}
</ul> </ul>
{{ if compare.Eq $menuID "main" -}}
<ul>
<li class="roomstate" id="roomstate">
<span class="state">unbekannt</span><br><span class="duration">(seit&nbsp;)</span>
</li>
</ul>
{{- end -}}