Theme improvements (#822)

* start converting

* small fixes

* reorganize theme files

* cleanup search bar

* increase spacing

* small tweaks

* fix select styles in Chrome

* cleanup menus

* improve button icons

* restore badges

* remove unused classes

* restore some overrides

* restore bookmark form

* add summary outline

* avoid layout shifts

* restore bookmark details

* increase border radius for modals

* improve details modal

* restore reader mode

* restore settings

* cleanup variables

* start with dark theme

* more dark theme...

* more light theme...

* more dark theme...

* add postcss build

* remove sass processor

* update docker build

* fix alt color

* remove endless symbol

* fix tests

* update assets

* remove sass files

* fix docker build

* cleanup spacing

* improve theme

* update test scripts

* update CI workflow

* fix test
This commit is contained in:
Sascha Ißbrücker
2024-09-13 23:19:47 +02:00
committed by GitHub
parent b736464f3f
commit 3ae9cf0420
84 changed files with 5366 additions and 1344 deletions

View File

@@ -1,136 +0,0 @@
/* Main layout */
body {
margin: 20px 10px;
@media (min-width: $size-sm) {
// Horizontal padding accounts for checkboxes that show up in bulk edit mode
margin: 20px 32px;
}
}
header {
margin-bottom: $unit-9;
.logo {
width: 28px;
height: 28px;
}
a:hover {
text-decoration: none;
}
h1 {
margin: 0 0 0 $unit-3;
font-size: $font-size-lg;
}
}
header .toasts {
margin-bottom: 20px;
.toast {
margin-bottom: 0.4rem;
}
.toast a.btn-clear:visited {
color: currentColor;
}
}
/* Shared components */
// Content area component
section.content-area {
h2 {
font-size: $font-size-lg;
}
.content-area-header {
border-bottom: solid 1px $border-color;
display: flex;
flex-wrap: wrap;
column-gap: $unit-5;
padding-bottom: $unit-1;
margin-bottom: $unit-3;
h2 {
flex: 0 0 auto;
line-height: $unit-9;
margin: 0;
}
.header-controls {
flex: 1 1 0;
display: flex;
}
}
}
// Confirm button component
span.confirmation {
display: flex;
align-items: baseline;
gap: $unit-1;
color: $error-color !important;
svg {
align-self: center;
}
.btn.btn-link {
color: $error-color !important;
&:hover {
text-decoration: underline;
}
}
}
/* Additional utilities */
.truncate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.text-gray-dark {
color: $gray-color-dark;
}
.align-baseline {
align-items: baseline;
}
.align-center {
align-items: center;
}
.justify-between {
justify-content: space-between;
}
.mb-4 {
margin-bottom: $unit-4;
}
.mx-auto {
margin-left: auto;
margin-right: auto;
}
.btn.btn-wide {
padding-left: $unit-6;
padding-right: $unit-6;
}
.btn.btn-sm.btn-icon {
display: inline-flex;
align-items: baseline;
gap: $unit-h;
svg {
align-self: center;
}
}

View File

@@ -0,0 +1,150 @@
/* Common styles */
.bookmark-details {
& h2 {
flex: 1 1 0;
align-items: flex-start;
font-size: 1rem;
margin: 0;
}
& .weblinks {
display: flex;
flex-direction: column;
gap: var(--unit-2);
}
& a.weblink {
display: flex;
align-items: center;
gap: var(--unit-2);
}
& a.weblink img, & a.weblink svg {
flex: 0 0 auto;
width: 16px;
height: 16px;
color: var(--text-color);
}
& a.weblink span {
flex: 1 1 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
& .preview-image {
margin: var(--unit-4 0);
img {
max-width: 100%;
max-height: 200px;
}
}
& dl {
margin-bottom: 0;
}
& .assets {
margin-top: var(--unit-2);
& .asset {
display: flex;
align-items: center;
gap: var(--unit-2);
padding: var(--unit-2) 0;
border-top: var(--unit-o) solid var(--secondary-border-color);
}
& .asset:last-child {
border-bottom: var(--unit-o) solid var(--secondary-border-color);
}
& .asset-icon {
display: flex;
align-items: center;
justify-content: center;
}
& .asset-text {
flex: 1 1 0;
gap: var(--unit-2);
min-width: 0;
display: flex;
}
& .asset-text .truncate {
flex-shrink: 1;
}
& .asset-text .filesize {
color: var(--tertiary-text-color);
}
& .asset-actions {
display: flex;
gap: var(--unit-4);
align-items: center;
& .btn.btn-link {
height: unset;
padding: 0;
border: none;
}
}
}
& .assets-actions {
display: flex;
gap: var(--unit-4);
align-items: center;
margin-top: var(--unit-2);
& .btn.btn-link {
height: unset;
padding: 0;
border: none;
}
}
& .tags a {
color: var(--alternative-color);
}
& .status form {
display: flex;
gap: var(--unit-2);
}
& .status .form-group, .status .form-switch {
margin: 0;
}
& .actions {
display: flex;
justify-content: space-between;
align-items: center;
}
}
/* Bookmark details view specific */
.bookmark-details.page {
display: flex;
flex-direction: column;
gap: var(--unit-6);
}
/* Bookmark details modal specific */
.bookmark-details.modal {
& .modal-header {
display: flex;
align-items: flex-start;
gap: var(--unit-2);
}
& .modal-body {
padding-top: 0;
padding-bottom: 0;
}
}

View File

@@ -1,141 +0,0 @@
/* Common styles */
.bookmark-details {
h2 {
flex: 1 1 0;
align-items: flex-start;
font-size: 1rem;
margin: 0;
}
.weblinks {
display: flex;
flex-direction: column;
gap: $unit-2;
}
a.weblink {
display: flex;
align-items: center;
gap: $unit-2;
}
a.weblink img, a.weblink svg {
flex: 0 0 auto;
width: 16px;
height: 16px;
color: $body-font-color;
}
a.weblink span {
flex: 1 1 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.preview-image {
margin: $unit-4 0;
img {
max-width: 100%;
max-height: 200px;
}
}
dl {
margin-bottom: 0;
}
.assets {
margin-top: $unit-2;
}
.assets .asset {
display: flex;
align-items: center;
gap: $unit-3;
padding: $unit-2 0;
border-top: $unit-o solid $border-color-light;
}
.assets .asset:last-child {
border-bottom: $unit-o solid $border-color-light;
}
.assets .asset-icon {
display: flex;
align-items: center;
justify-content: center;
}
.assets .asset-text {
flex: 1 1 0;
gap: $unit-2;
min-width: 0;
display: flex;
}
.assets .asset-text .truncate {
flex-shrink: 1;
}
.assets .asset-text .filesize {
color: $gray-color;
}
.assets .asset-actions, .assets-actions {
display: flex;
gap: $unit-4;
align-items: center;
}
.assets .asset-actions .btn, .assets-actions .btn {
height: unset;
padding: 0;
border: none;
}
.assets-actions {
margin-top: $unit-2;
}
.tags a {
color: $alternative-color;
}
.status form {
display: flex;
gap: $unit-2;
}
.status .form-group, .status .form-switch {
margin: 0;
}
.actions {
display: flex;
justify-content: space-between;
align-items: center;
}
}
/* Bookmark details view specific */
.bookmark-details.page {
display: flex;
flex-direction: column;
gap: $unit-6;
}
/* Bookmark details modal specific */
.bookmark-details.modal {
.modal-header {
display: flex;
align-items: flex-start;
gap: $unit-2;
}
.modal-body {
padding-top: 0;
padding-bottom: 0;
}
}

View File

@@ -0,0 +1,48 @@
.bookmarks-form-page {
section {
max-width: 550px;
margin: 0 auto;
}
}
.bookmarks-form {
& .btn.btn-link.form-icon {
padding: 0;
width: 20px;
height: 20px;
visibility: hidden;
--btn-icon-color: var(--tertiary-text-color);
& > svg {
width: 20px;
height: 20px;
}
}
& .has-icon-right > input, & .has-icon-right > textarea {
padding-right: 30px;
}
& .has-icon-right > input:placeholder-shown ~ .btn.form-icon,
& .has-icon-right > textarea:placeholder-shown ~ .btn.form-icon {
visibility: visible;
}
& .form-icon.loading {
visibility: hidden;
}
& .form-input-hint.bookmark-exists {
display: none;
color: var(--warning-color);
}
& .form-input-hint.auto-tags {
display: none;
color: var(--success-color);
}
& details.notes textarea {
box-sizing: border-box;
}
}

View File

@@ -1,49 +0,0 @@
.bookmarks-form {
.btn.form-icon {
padding: 0;
width: 20px;
height: 20px;
visibility: hidden;
color: $gray-color;
&:focus,
&:hover,
&:active,
&.active {
color: $gray-color-dark;
}
> svg {
width: 20px;
height: 20px;
}
}
.has-icon-right > input, .has-icon-right > textarea {
padding-right: 30px;
}
.has-icon-right > input:placeholder-shown ~ .btn.form-icon,
.has-icon-right > textarea:placeholder-shown ~ .btn.form-icon {
visibility: visible;
}
.form-icon.loading {
visibility: hidden;
}
.form-input-hint.bookmark-exists {
display: none;
color: $warning-color;
}
.form-input-hint.auto-tags {
display: none;
color: $success-color;
}
details.notes textarea {
box-sizing: border-box;
}
}

View File

@@ -0,0 +1,457 @@
:root {
--bookmark-title-color: var(--primary-text-color);
--bookmark-title-weight: 500;
--bookmark-description-color: var(--text-color);
--bookmark-description-weight: 400;
--bookmark-actions-color: var(--secondary-text-color);
--bookmark-actions-hover-color: var(--text-color);
--bookmark-actions-weight: 400;
--bulk-actions-bg-color: var(--gray-50);
}
/* Bookmark page grid */
.bookmarks-page.grid {
grid-gap: var(--unit-9);
}
/* Bookmark area header controls */
.bookmarks-page .search-container {
flex: 1 1 0;
display: flex;
max-width: 300px;
margin-left: auto;
& form {
width: 100%;
}
@media (max-width: 600px) {
max-width: initial;
margin-left: 0;
}
/* Regular input */
& input[type='search'] {
height: var(--control-size);
-webkit-appearance: none;
}
/* Enhanced auto-complete input */
/* This needs a bit more wrangling to make the CSS component align with the attached button */
& .form-autocomplete {
height: var(--control-size);
& .form-autocomplete-input {
width: 100%;
height: var(--control-size);
& input[type='search'] {
width: 100%;
height: 100%;
margin: 0;
border: none;
}
}
}
/* Group search options button with search button */
height: var(--control-size);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow-xs);
& input, & .form-autocomplete-input {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
box-shadow: none;
}
& .dropdown-toggle {
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
box-shadow: none;
outline-offset: calc(var(--focus-outline-offset) * -1);
}
/* Search option menu styles */
& .dropdown {
& .menu {
padding: var(--unit-4);
min-width: 250px;
font-size: var(--font-size-sm);
}
& .menu .actions {
margin-top: var(--unit-4);
display: flex;
justify-content: space-between;
}
& .form-group:first-of-type {
margin-top: 0;
}
& .form-group {
margin-bottom: var(--unit-3);
}
& .radio-group {
& .form-label {
margin-bottom: var(--unit-1);
}
& .form-radio.form-inline {
margin: 0 var(--unit-2) 0 0;
padding: 0;
display: inline-flex;
align-items: center;
column-gap: var(--unit-1);
}
& .form-icon {
top: 0;
position: relative;
}
}
}
}
/* Bookmark list */
ul.bookmark-list {
list-style: none;
margin: 0;
padding: 0;
/* Increase line-height for better separation within / between items */
line-height: 1.1rem;
}
@keyframes appear {
0% {
opacity: 0;
}
90% {
opacity: 0;
}
100% {
opacity: 1;
}
}
/* Bookmarks */
li[ld-bookmark-item] {
position: relative;
display: flex;
gap: var(--unit-2);
margin-top: 0;
margin-bottom: var(--unit-3);
& .content {
flex: 1 1 0;
min-width: 0;
}
& img.preview-image {
flex: 0 0 auto;
width: 100px;
height: 60px;
margin-top: var(--unit-h);
object-fit: cover;
border-radius: var(--border-radius);
border: solid 1px var(--border-color);
}
& .form-checkbox.bulk-edit-checkbox {
display: none;
}
& .title {
position: relative;
}
& .title img {
position: absolute;
width: 16px;
height: 16px;
left: 0;
top: 50%;
transform: translateY(-50%);
pointer-events: none;
}
& .title img + a {
padding-left: 22px;
}
& .title a {
color: var(--bookmark-title-color);
font-weight: var(--bookmark-title-weight);
display: block;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
& .title a[data-tooltip]:hover::after, & .title a[data-tooltip]:focus::after {
content: attr(data-tooltip);
position: absolute;
z-index: 10;
top: 100%;
left: 50%;
transform: translateX(-50%);
width: max-content;
max-width: 90%;
height: fit-content;
background-color: #292f62;
color: #fff;
padding: var(--unit-1);
border-radius: var(--border-radius);
border: 1px solid #424a8c;
font-size: var(--font-size-sm);
font-style: normal;
white-space: normal;
pointer-events: none;
animation: 0.3s ease 0s appear;
}
@media (pointer: coarse) {
& .title a[data-tooltip]::after {
display: none;
}
}
&.unread .title a {
font-style: italic;
}
& .url-path, & .url-display {
font-size: var(--font-size-sm);
color: var(--secondary-link-color);
}
& .description {
color: var(--bookmark-description-color);
font-weight: var(--bookmark-description-weight);
}
& .description.separate {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: var(--ld-bookmark-description-max-lines, 1);
overflow: hidden;
}
& .tags {
& a, & a:visited:hover {
color: var(--alternative-color);
}
}
& .actions, & .extra-actions {
display: flex;
align-items: baseline;
flex-wrap: wrap;
column-gap: var(--unit-2);
}
@media (max-width: 600px) {
& .extra-actions {
width: 100%;
margin-top: var(--unit-1);
}
}
& .actions {
color: var(--bookmark-actions-color);
font-size: var(--font-size-sm);
& a, & button.btn-link {
color: var(--bookmark-actions-color);
--btn-icon-color: var(--bookmark-actions-color);
font-weight: var(--bookmark-actions-weight);
padding: 0;
height: auto;
vertical-align: unset;
border: none;
box-sizing: border-box;
transition: none;
text-decoration: none;
&:focus,
&:hover,
&:active,
&.active {
color: var(--bookmark-actions-hover-color);
--btn-icon-color: var(--bookmark-actions-hover-color);
}
}
}
}
.bookmark-pagination {
margin-top: var(--unit-4);
/* Remove left padding from first pagination link */
& .page-item:first-child a {
padding-left: 0;
}
}
.tag-cloud {
/* Increase line-height for better separation within / between items */
line-height: 1.1rem;
& .selected-tags {
margin-bottom: var(--unit-4);
& a,
& a:visited:hover {
color: var(--error-color);
}
}
& .unselected-tags {
& a,
& a:visited:hover {
color: var(--alternative-color);
}
}
& .group {
margin-bottom: var(--unit-3);
}
& .highlight-char {
font-weight: bold;
text-transform: uppercase;
color: var(--alternative-color-dark);
}
}
/* Bookmark notes */
ul.bookmark-list {
& .notes {
display: none;
max-height: 300px;
margin: var(--unit-1) 0;
overflow-y: auto;
background: var(--body-color-contrast);
border-radius: var(--border-radius);
}
& .notes .markdown {
padding: var(--unit-2) var(--unit-3);
}
&.show-notes .notes,
& li.show-notes .notes {
display: block;
}
}
/* Bookmark bulk edit */
:root {
--bulk-edit-toggle-width: 16px;
--bulk-edit-toggle-offset: 8px;
--bulk-edit-bar-offset: calc(var(--bulk-edit-toggle-width) + (2 * var(--bulk-edit-toggle-offset)));
--bulk-edit-transition-duration: 400ms;
}
[ld-bulk-edit] {
& .bulk-edit-bar {
margin-top: -1px;
margin-left: calc(-1 * var(--bulk-edit-bar-offset));
margin-bottom: var(--unit-4);
max-height: 0;
overflow: hidden;
transition: max-height var(--bulk-edit-transition-duration);
background: var(--bulk-actions-bg-color);
}
&.active .bulk-edit-bar {
max-height: 37px;
border-bottom: solid 1px var(--secondary-border-color);
}
/* Hide section border when bulk edit bar is opened, otherwise borders overlap in dark mode due to using contrast colors */
&.active section:first-of-type .content-area-header {
border-bottom-color: transparent;
}
/* remove overflow after opening animation, otherwise tag autocomplete overlay gets cut off */
&.active:not(.activating) .bulk-edit-bar {
overflow: visible;
}
/* All checkbox */
& .form-checkbox.bulk-edit-checkbox.all {
display: block;
width: var(--bulk-edit-toggle-width);
margin: 0 0 0 var(--bulk-edit-toggle-offset);
padding: 0;
}
/* Bookmark checkboxes */
& li[ld-bookmark-item] .form-checkbox.bulk-edit-checkbox {
display: block;
position: absolute;
width: var(--bulk-edit-toggle-width);
min-height: var(--bulk-edit-toggle-width);
left: calc(-1 * var(--bulk-edit-toggle-width) - var(--bulk-edit-toggle-offset));
top: 50%;
transform: translateY(-50%);
padding: 0;
margin: 0;
visibility: hidden;
opacity: 0;
transition: all var(--bulk-edit-transition-duration);
.form-icon {
top: 0;
}
}
&.active li[ld-bookmark-item] .form-checkbox.bulk-edit-checkbox {
visibility: visible;
opacity: 1;
}
/* Actions */
& .bulk-edit-actions {
display: flex;
align-items: center;
padding: var(--unit-1) 0;
border-top: solid 1px var(--secondary-border-color);
gap: var(--unit-2);
& button {
--control-padding-x-sm: 0;
}
& button:hover {
text-decoration: underline;
}
& > input,
& .form-autocomplete,
& select {
width: auto;
max-width: 140px;
-webkit-appearance: none;
}
& .select-across {
margin: 0 0 0 auto;
font-size: var(--font-size-sm);
}
}
}

View File

@@ -1,408 +0,0 @@
.bookmarks-page.grid {
grid-gap: $unit-9;
}
/* Bookmark area header controls */
.bookmarks-page .content-area-header {
--searchbox-max-width: 350px;
@media (max-width: $size-sm) {
--searchbox-max-width: initial;
flex-direction: column;
}
}
.bookmarks-page .search-container {
flex: 1 1 0;
display: flex;
justify-content: flex-end;
// Regular input
input[type='search'] {
height: $control-size;
-webkit-appearance: none;
}
// Enhanced auto-complete input
// This needs a bit more wrangling to make the CSS component align with the attached button
.form-autocomplete {
height: $control-size;
.form-autocomplete-input {
width: 100%;
height: $control-size;
input[type='search'] {
width: 100%;
height: 100%;
margin: 0;
border: none;
}
}
}
.input-group {
flex: 1 1 0;
min-width: var(--searchbox-min-width);
max-width: var(--searchbox-max-width);
}
.input-group > :first-child {
flex: 1 1 0;
}
// Group search options button with search button
.input-group input[type='submit'] {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.dropdown-toggle {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.dropdown {
margin-left: -1px;
}
// Search option menu styles
.dropdown {
.menu {
padding: $unit-4;
min-width: 250px;
font-size: $font-size-sm;
}
.menu .actions {
margin-top: $unit-4;
display: flex;
justify-content: space-between;
}
.radio-group {
margin-bottom: $unit-1;
.form-label {
padding-bottom: 0;
}
.form-radio.form-inline {
margin: 0 $unit-2 0 0;
padding: 0;
display: inline-flex;
align-items: center;
column-gap: $unit-1;
}
.form-icon {
top: 0;
position: relative;
}
}
}
}
/* Bookmark list */
ul.bookmark-list {
list-style: none;
margin: 0;
padding: 0;
/* Increase line-height for better separation within / between items */
line-height: 1.1rem;
}
@keyframes appear {
0% {
opacity: 0;
}
90% {
opacity: 0;
}
100% {
opacity: 1;
}
}
/* Bookmarks */
li[ld-bookmark-item] {
position: relative;
display: flex;
gap: $unit-2;
margin-top: $unit-2;
.content {
flex: 1 1 0;
min-width: 0;
}
img.preview-image {
flex: 0 0 auto;
width: 100px;
height: 60px;
margin-top: $unit-h;
object-fit: cover;
border-radius: $border-radius;
border: solid 1px $border-color-dark;
}
.form-checkbox.bulk-edit-checkbox {
display: none;
}
.title {
position: relative;
}
.title img {
position: absolute;
width: 16px;
height: 16px;
left: 0;
top: 50%;
transform: translateY(-50%);
pointer-events: none;
}
.title img + a {
padding-left: 22px;
}
.title a {
display: block;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.title a[data-tooltip]:hover::after, .title a[data-tooltip]:focus::after {
content: attr(data-tooltip);
position: absolute;
z-index: 10;
top: 100%;
left: 50%;
transform: translateX(-50%);
width: max-content;
max-width: 90%;
height: fit-content;
background-color: #292f62;
color: #fff;
padding: $unit-1;
border-radius: $border-radius;
border: 1px solid #424a8c;
font-size: $font-size-sm;
font-style: normal;
white-space: normal;
pointer-events: none;
animation: 0.3s ease 0s appear;
}
@media (pointer:coarse) {
.title a[data-tooltip]::after {
display: none;
}
}
&.unread .title a {
font-style: italic;
}
.url-path, .url-display {
font-size: $font-size-sm;
color: $secondary-link-color;
}
.description {
color: $gray-color-dark;
}
.description.separate {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: var(--ld-bookmark-description-max-lines, 1);
overflow: hidden;
}
.tags {
a, a:visited:hover {
color: $alternative-color;
}
}
.actions, .extra-actions {
display: flex;
align-items: baseline;
flex-wrap: wrap;
column-gap: $unit-2;
}
@media (max-width: $size-sm) {
.extra-actions {
width: 100%;
margin-top: $unit-1;
}
}
.actions {
font-size: $font-size-sm;
a, button.btn-link {
color: $gray-color;
padding: 0;
height: auto;
vertical-align: unset;
border: none;
transition: none;
text-decoration: none;
&:focus,
&:hover,
&:active,
&.active {
color: $gray-color-dark;
}
}
}
}
.bookmark-pagination {
margin-top: $unit-4;
}
.tag-cloud {
/* Increase line-height for better separation within / between items */
line-height: 1.1rem;
.selected-tags {
margin-bottom: $unit-4;
a, a:visited:hover {
color: $error-color;
}
}
.unselected-tags {
a, a:visited:hover {
color: $alternative-color;
}
}
.group {
margin-bottom: $unit-2;
}
.highlight-char {
font-weight: bold;
text-transform: uppercase;
color: $alternative-color-dark;
}
}
/* Bookmark notes */
ul.bookmark-list {
.notes {
display: none;
max-height: 300px;
margin: $unit-1 0;
overflow-y: auto;
}
.notes .markdown {
padding: $unit-2 $unit-3;
}
&.show-notes .notes,
li.show-notes .notes {
display: block;
}
}
/* Bookmark bulk edit */
$bulk-edit-toggle-width: 16px;
$bulk-edit-toggle-offset: 8px;
$bulk-edit-bar-offset: $bulk-edit-toggle-width + (2 * $bulk-edit-toggle-offset);
$bulk-edit-transition-duration: 400ms;
[ld-bulk-edit] {
.bulk-edit-bar {
margin-top: -1px;
margin-left: -$bulk-edit-bar-offset;
margin-bottom: $unit-3;
max-height: 0;
overflow: hidden;
transition: max-height $bulk-edit-transition-duration;
}
&.active .bulk-edit-bar {
max-height: 37px;
border-bottom: solid 1px $border-color;
}
/* remove overflow after opening animation, otherwise tag autocomplete overlay gets cut off */
&.active:not(.activating) .bulk-edit-bar {
overflow: visible;
}
/* All checkbox */
.form-checkbox.bulk-edit-checkbox.all {
display: block;
width: $bulk-edit-toggle-width;
margin: 0 0 0 $bulk-edit-toggle-offset;
padding: 0;
}
/* Bookmark checkboxes */
li[ld-bookmark-item] .form-checkbox.bulk-edit-checkbox {
display: block;
position: absolute;
width: $bulk-edit-toggle-width;
min-height: $bulk-edit-toggle-width;
left: -$bulk-edit-toggle-width - $bulk-edit-toggle-offset;
top: 50%;
transform: translateY(-50%);
padding: 0;
margin: 0;
visibility: hidden;
opacity: 0;
transition: all $bulk-edit-transition-duration;
.form-icon {
top: 0;
}
}
&.active li[ld-bookmark-item] .form-checkbox.bulk-edit-checkbox {
visibility: visible;
opacity: 1;
}
/* Actions */
.bulk-edit-actions {
display: flex;
align-items: center;
padding: $unit-1 0;
border-top: solid 1px $border-color;
gap: $unit-2;
button {
padding: 0 !important;
}
button:hover {
text-decoration: underline;
}
> input, .form-autocomplete, select {
width: auto;
max-width: 140px;
-webkit-appearance: none;
}
.select-across {
margin: 0 0 0 auto;
font-size: $font-size-sm;
}
}
}

View File

@@ -0,0 +1,60 @@
/* Shared components */
/* Content area component */
section.content-area {
h2 {
font-size: var(--font-size-lg);
}
.content-area-header {
border-bottom: solid 1px var(--secondary-border-color);
display: flex;
flex-wrap: wrap;
column-gap: var(--unit-5);
padding-bottom: var(--unit-2);
margin-bottom: var(--unit-4);
h2 {
flex: 0 0 auto;
line-height: var(--unit-9);
margin: 0;
}
.header-controls {
flex: 1 1 0;
display: flex;
}
}
}
@media (max-width: 600px) {
section.content-area .content-area-header {
flex-direction: column;
}
}
/* Confirm button component */
span.confirmation {
display: flex;
align-items: baseline;
gap: var(--unit-1);
color: var(--error-color) !important;
svg {
align-self: center;
}
.btn.btn-link {
color: var(--error-color) !important;
&:hover {
text-decoration: underline;
}
}
}
/* Divider */
.divider {
border-bottom: solid 1px var(--secondary-border-color);
margin: var(--unit-5) 0;
}

View File

@@ -0,0 +1,39 @@
/* Main layout */
body {
margin: 20px 10px;
@media (min-width: 600px) {
/* Horizontal offset accounts for checkboxes that show up in bulk edit mode */
margin: 20px 32px;
}
}
header {
margin-bottom: var(--unit-9);
.logo {
width: 28px;
height: 28px;
}
a:hover {
text-decoration: none;
}
h1 {
margin: 0 0 0 var(--unit-3);
font-size: var(--font-size-lg);
}
}
header .toasts {
margin-bottom: 20px;
.toast {
margin-bottom: 0.4rem;
}
.toast a.btn-clear:visited {
color: currentColor;
}
}

View File

@@ -0,0 +1,40 @@
.markdown {
& p, & ul, & ol, & pre, & blockquote {
margin: 0 0 var(--unit-2) 0;
}
& > *:first-child {
margin-top: 0;
}
& > *:last-child {
margin-bottom: 0;
}
& ul, & ol {
margin-left: var(--unit-4);
}
& ul li, & ol li {
margin-top: var(--unit-1);
}
& pre {
padding: var(--unit-1) var(--unit-2);
background-color: var(--code-bg-color);
border-radius: var(--unit-1);
overflow-x: auto;
}
& pre code {
background: none;
box-shadow: none;
padding: 0;
}
& > pre:first-child:last-child {
padding: 0;
background: none;
border-radius: 0;
}
}

View File

@@ -1,40 +0,0 @@
.markdown {
p, ul, ol, pre, blockquote {
margin: 0 0 $unit-2 0;
}
> *:first-child {
margin-top: 0;
}
> *:last-child {
margin-bottom: 0;
}
ul, ol {
margin-left: $unit-4;
}
ul li, ol li {
margin-top: $unit-1;
}
pre {
padding: $unit-1 $unit-2;
background-color: $code-bg-color;
border-radius: $unit-1;
overflow-x: auto;
}
pre code {
background: none;
box-shadow: none;
padding: 0;
}
> pre:first-child:last-child {
padding: 0;
background: none;
border-radius: 0;
}
}

View File

@@ -1,10 +1,3 @@
.container {
margin-left: auto;
margin-right: auto;
width: 100%;
max-width: $size-lg;
}
.show-sm,
.show-md {
display: none !important;
@@ -26,11 +19,18 @@
width: 100%;
}
.container {
margin-left: auto;
margin-right: auto;
width: 100%;
max-width: var(--size-lg);
}
.grid {
--grid-columns: 3;
display: grid;
grid-template-columns: repeat(var(--grid-columns), 1fr);
grid-gap: $unit-4;
grid-gap: var(--unit-4);
}
.grid > * {
@@ -46,18 +46,18 @@
}
.col-1 {
grid-column: unquote("span min(1, var(--grid-columns))");
grid-column: span min(1, var(--grid-columns));
}
.col-2 {
grid-column: unquote("span min(2, var(--grid-columns))");
grid-column: span min(2, var(--grid-columns));
}
.col-3 {
grid-column: unquote("span min(3, var(--grid-columns))");
grid-column: span min(3, var(--grid-columns));
}
@media (max-width: $size-md) {
@media (max-width: 840px) {
.hide-md {
display: none !important;
}
@@ -86,7 +86,7 @@
}
}
@media (max-width: $size-sm) {
@media (max-width: 600px) {
.hide-sm {
display: none !important;
}

View File

@@ -1,9 +1,9 @@
.settings-page {
section.content-area {
margin-bottom: $unit-10;
margin-bottom: var(--unit-10);
h2 {
margin-bottom: $unit-3;
margin-bottom: var(--unit-3);
}
}
@@ -17,6 +17,10 @@
}
section.about table {
max-width: 500px;
max-width: 400px;
}
& .form-group {
margin-bottom: var(--unit-4);
}
}

View File

@@ -1,204 +0,0 @@
// Customized Spectre CSS imports, removing modules that are not used
// See node_modules/spectre.css/src/spectre.scss for the original version
// Variables and mixins
@import "../../node_modules/spectre.css/src/variables";
// Customize variables to reduce font and control sizes
// Can use CSS variables for font sizes, as they are not used in SCSS calculations
$font-size: var(--font-size);
$font-size-sm: var(--font-size-sm);
$font-size-lg: var(--font-size-lg);
// Can't use CSS variables for these, used in SCSS calculations
$line-height: 1rem;
$control-size: $unit-8;
$control-size-sm: $unit-6;
$control-size-lg: $unit-9;
// Declare defaults for CSS variables, expose SCSS variables as CSS variables
html {
--font-size: 0.7rem;
--font-size-sm: 0.65rem;
--font-size-lg: 0.8rem;
--control-size: #{$control-size};
--control-size-sm: #{$control-size-sm};
--control-size-lg: #{$control-size-lg};
}
// Mixins
@import "../../node_modules/spectre.css/src/mixins";
/*! Spectre.css v#{$version} | MIT License | github.com/picturepan2/spectre */
// Reset and dependencies
@import "../../node_modules/spectre.css/src/normalize";
@import "../../node_modules/spectre.css/src/base";
// Elements
@import "../../node_modules/spectre.css/src/typography";
@import "../../node_modules/spectre.css/src/asian";
@import "../../node_modules/spectre.css/src/tables";
@import "../../node_modules/spectre.css/src/buttons";
@import "../../node_modules/spectre.css/src/forms";
@import "../../node_modules/spectre.css/src/labels";
@import "../../node_modules/spectre.css/src/codes";
@import "../../node_modules/spectre.css/src/media";
// Components
@import "../../node_modules/spectre.css/src/badges";
@import "../../node_modules/spectre.css/src/dropdowns";
@import "../../node_modules/spectre.css/src/empty";
@import "../../node_modules/spectre.css/src/menus";
@import "../../node_modules/spectre.css/src/modals";
@import "../../node_modules/spectre.css/src/pagination";
@import "../../node_modules/spectre.css/src/tabs";
@import "../../node_modules/spectre.css/src/toasts";
@import "../../node_modules/spectre.css/src/tooltips";
// Utility classes
@import "../../node_modules/spectre.css/src/animations";
@import "../../node_modules/spectre.css/src/utilities";
// Auto-complete component
@import "../../node_modules/spectre.css/src/autocomplete";
/* Spectre overrides / fixes */
// Fix up visited styles
a:visited {
color: $link-color;
}
a:visited:hover {
color: $link-color-dark;
}
.btn-link:visited:not(.btn-primary) {
color: $link-color;
}
.btn-link:visited:not(.btn-primary):hover {
color: $link-color-dark;
}
// Disable transitions on buttons, which can otherwise flicker while loading CSS file
// something to do with .btn applying a transition for background, and then .btn-link setting a different background
.btn {
transition: none !important;
}
// Make code work with light and dark theme
code {
color: $gray-color-dark;
background-color: $code-bg-color;
box-shadow: 1px 1px 0 $code-shadow-color;
}
// Remove left padding from first pagination link
.pagination .page-item:first-child a {
padding-left: 0;
}
// Override border color for tab block
.tab-block {
border-bottom: solid 1px $border-color;
}
// Fix padding for first menu item
ul.menu li:first-child {
margin-top: 0;
}
// Form auto-complete menu
.form-autocomplete .menu {
.menu-item.selected > a, .menu-item > a:hover {
background: $secondary-color;
color: $primary-color;
}
.group-item, .group-item:hover {
color: $gray-color;
text-transform: uppercase;
background: none;
font-size: 0.6rem;
font-weight: bold;
}
}
.modal {
// Add border to separate from background in dark mode
.modal-container {
border: solid 1px $border-color;
}
// Fix modal header to use default color
.modal-header {
color: inherit;
}
}
// Customize modal animation
@keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
.modal.active .modal-container, .modal.active .modal-overlay {
animation: fade-in .15s ease 1;
}
.modal.active.closing .modal-container, .modal.active.closing .modal-overlay {
animation: fade-out .15s ease 1;
}
// Customize menu animation
.dropdown .menu {
animation: fade-in .15s ease 1;
}
// Modal close button
.modal .modal-header button.close {
background: none;
border: none;
padding: 0;
line-height: 0;
cursor: pointer;
opacity: .85;
color: $gray-color-dark;
&:hover {
opacity: 1;
}
}
// Increase input font size on small viewports to prevent zooming on focus the input
// on mobile devices. 430px relates to the "normalized" iPhone 14 Pro Max
// viewport size
@media screen and (max-width: 430px) {
.form-input {
font-size: 16px;
}
}
// Hide tooltips on mobile
@media (pointer:coarse) {
.tooltip::after {
display: none;
}
}

View File

@@ -0,0 +1,143 @@
@import "theme-light.css";
:root {
/* Color palette */
--contrast-5: hsla(241, 65%, 85%, 0.06);
--contrast-10: hsla(241, 60%, 80%, 0.14);
--contrast-20: hsla(241, 64%, 82%, 0.23);
--contrast-30: hsla(241, 69%, 84%, 0.32);
--contrast-40: hsla(241, 73%, 86%, 0.41);
--contrast-50: hsla(241, 78%, 88%, 0.5);
--contrast-60: hsla(241, 82%, 90%, 0.58);
--contrast-70: hsla(241, 87%, 92%, 0.69);
--contrast-80: hsla(241, 91%, 94%, 0.8);
--contrast-90: hsla(241, 96%, 96%, 0.9);
--primary-color: hsl(241, 75%, 64%);
--primary-color-highlight: hsl(241, 75%, 68%);
--primary-color-shade: hsl(241, 75%, 64%, 0.42);
--alternative-color: hsl(179, 50%, 58%);
--alternative-color-dark: hsl(179, 80%, 75%);
--success-color: hsl(142, 76%, 36%);
--success-color-highlight: hsl(142, 76%, 40%);
--success-color-shade: hsla(142, 76%, 36%, 0.1);
--warning-color: hsl(38, 92%, 50%);
--warning-color-highlight: hsl(38, 92%, 55%);
--warning-color-shade: hsla(38, 92%, 50%, 0.1);
--error-color: hsl(0, 80%, 60%);
--error-color-highlight: hsl(0, 72%, 60%);
--error-color-shade: hsla(0, 72%, 51%, 0.1);
/* Core colors */
--text-color: var(--gray-300);
--secondary-text-color: var(--gray-400);
--tertiary-text-color: var(--gray-500);
--contrast-text-color: #fff;
--primary-text-color: hsl(241, 82%, 82%);
--link-color: var(--primary-text-color);
--secondary-link-color: hsla(241, 82%, 82%, 0.8);
--icon-color: var(--text-color);
--border-color: var(--contrast-30);
--secondary-border-color: var(--contrast-20);
--body-color: hsl(241, 15%, 14%);
--body-color-contrast: var(--contrast-10);
/* Focus */
--focus-outline: 2px solid hsl(241, 100%, 78%);
--focus-outline-offset: 2px;
/* Shadows */
--box-shadow-xs: none;
--box-shadow: none;
--box-shadow-lg: none;
}
:root {
--input-bg-color: var(--contrast-5);
--input-disabled-bg-color: var(--contrast-30);
--input-text-color: var(--text-color);
--input-hint-color: var(--secondary-text-color);
--input-border-color: var(--border-color);
--input-placeholder-color: var(--tertiary-text-color);
--input-box-shadow: var(--box-shadow-xs);
--checkbox-bg-color: var(--contrast-10);
--checkbox-checked-bg-color: var(--primary-color);
--checkbox-disabled-bg-color: var(--contrast-30);
--checkbox-border-color: var(--border-color);
--checkbox-icon-color: #fff;
--switch-bg-color: var(--contrast-10);
--switch-border-color: var(--border-color);
--switch-toggle-color: var(--text-color);
}
:root {
--btn-bg-color: var(--contrast-5);
--btn-hover-bg-color: var(--contrast-20);
--btn-border-color: var(--border-color);
--btn-text-color: var(--text-color);
--btn-icon-color: var(--icon-color);
--btn-font-weight: 400;
--btn-box-shadow: var(--box-shadow-xs);
--btn-primary-bg-color: var(--primary-color);
--btn-primary-hover-bg-color: var(--primary-color-highlight);
--btn-primary-text-color: var(--contrast-text-color);
--btn-success-bg-color: var(--success-color);
--btn-success-hover-bg-color: var(--success-color-highlight);
--btn-success-text-color: var(--contrast-text-color);
--btn-error-bg-color: var(--error-color);
--btn-error-hover-bg-color: var(--error-color-highlight);
--btn-error-text-color: var(--contrast-text-color);
--btn-link-text-color: var(--link-color);
--btn-link-hover-text-color: var(--link-color);
}
:root {
--modal-overlay-bg-color: hsla(229, 21%, 16%, 0.55);
--modal-container-bg-color: hsl(241, 20%, 20%);
--modal-container-border-color: var(--contrast-30);
--modal-border-radius: var(--border-radius-lg);
--modal-box-shadow: none;
}
:root {
--menu-bg-color: hsl(241, 20%, 20%);
--menu-border-color: var(--contrast-30);
--menu-border-radius: var(--border-radius);
--menu-box-shadow: none;
--menu-item-color: var(--text-color);
--menu-item-hover-color: var(--text-color);
--menu-item-bg-color: transparent;
--menu-item-hover-bg-color: var(--contrast-20);
}
:root {
--tab-color: var(--text-color);
--tab-hover-color: var(--primary-text-color);
--tab-active-color: var(--primary-text-color);
--tab-highlight-color: var(--primary-text-color);
}
:root {
--bookmark-title-color: var(--primary-text-color);
--bookmark-title-weight: 500;
--bookmark-description-color: var(--text-color);
--bookmark-description-weight: 400;
--bookmark-actions-color: var(--secondary-text-color);
--bookmark-actions-hover-color: var(--text-color);
--bookmark-actions-weight: 400;
--bulk-actions-bg-color: var(--contrast-5);
}

View File

@@ -1,66 +0,0 @@
// Import custom variables
@import "variables-dark";
// Import Spectre CSS lib
@import "spectre";
// Import style modules
@import "base";
@import "responsive";
@import "bookmark-details";
@import "bookmark-page";
@import "bookmark-form";
@import "settings";
@import "markdown";
@import "reader-mode";
/* Dark theme overrides */
// Buttons
.btn.btn-primary {
background: $dt-primary-button-color;
border-color: darken($dt-primary-button-color, 5%);
&:hover, &:active, &:focus {
background: darken($dt-primary-button-color, 5%);
border-color: darken($dt-primary-button-color, 10%);
}
}
// Focus ring
a:focus, .btn:focus {
box-shadow: 0 0 0 .1rem rgba($primary-color, .5);
}
// Forms
.form-input:not(:placeholder-shown):invalid,
.form-input:not(:placeholder-shown):invalid:focus,
.has-error .form-input,
.form-input.is-error,
.has-error .form-select,
.form-select.is-error {
background: darken($error-color, 40%);
}
.form-checkbox input:checked + .form-icon, .form-radio input:checked + .form-icon, .form-switch input:checked + .form-icon {
background: $dt-primary-input-color;
border-color: $dt-primary-input-color;
}
.form-switch .form-icon::before, .form-switch input:active + .form-icon::before {
background: $light-color;
}
.form-switch input:checked + .form-icon {
background: $dt-primary-input-color;
border-color: $dt-primary-input-color;
}
.form-radio input:checked + .form-icon::before {
background: $light-color;
}
// Pagination
.pagination .page-item.active a {
background: $dt-primary-button-color;
}

View File

@@ -0,0 +1,30 @@
@import "theme/variables.css";
@import "theme/_normalize.css";
@import "theme/base.css";
@import "theme/typography.css";
@import "theme/asian.css";
@import "theme/tables.css";
@import "theme/buttons.css";
@import "theme/forms.css";
@import "theme/code.css";
@import "theme/dropdowns.css";
@import "theme/menus.css";
@import "theme/badges.css";
@import "theme/empty.css";
@import "theme/modals.css";
@import "theme/pagination.css";
@import "theme/tabs.css";
@import "theme/toasts.css";
@import "theme/autocomplete.css";
@import "theme/animations.css";
@import "theme/utilities.css";
@import "responsive.css";
@import "layout.css";
@import "components.css";
@import "bookmark-details.css";
@import "bookmark-form.css";
@import "bookmark-page.css";
@import "markdown.css";
@import "reader-mode.css";
@import "settings.css";

View File

@@ -1,15 +0,0 @@
// Import custom variables
@import "variables-light";
// Import Spectre CSS lib
@import "spectre";
// Import style modules
@import "base";
@import "responsive";
@import "bookmark-details";
@import "bookmark-page";
@import "bookmark-form";
@import "settings";
@import "markdown";
@import "reader-mode";

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 - 2020 Yan Zhu
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,446 @@
/* Manually forked from Normalize.css */
/* normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
/**
* 1. Change the default font family in all browsers (opinionated).
* 2. Correct the line height in all browsers.
* 3. Prevent adjustments of font size after orientation changes in
* IE on Windows Phone and in iOS.
*/
/* Document
========================================================================== */
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 3 */
-webkit-text-size-adjust: 100%; /* 3 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers (opinionated).
*/
body {
margin: 0;
}
/**
* Add the correct display in IE 9-.
*/
article,
aside,
footer,
header,
nav,
section {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in IE.
*/
figcaption,
figure,
main { /* 1 */
display: block;
}
/**
* Add the correct margin in IE 8 (removed).
*/
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers. (removed)
* 2. Correct the odd `em` font sizing in all browsers.
*/
/* Text-level semantics
========================================================================== */
/**
* 1. Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/
a {
background-color: transparent; /* 1 */
-webkit-text-decoration-skip: objects; /* 2 */
}
/**
* Remove the outline on focused links when they are also active or hovered
* in all browsers (opinionated).
*/
a:active,
a:hover {
outline-width: 0;
}
/**
* Modify default styling of address.
*/
address {
font-style: normal;
}
/**
* 1. Remove the bottom border in Firefox 39-.
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. (removed)
*/
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
pre,
samp {
font-family: var(--mono-font-family); /* 1 (changed) */
font-size: 1em; /* 2 */
}
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Add the correct background and color in IE 9-. (Removed)
*/
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
font-weight: 400; /* (added) */
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* 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 images inside links in IE 10-.
*/
img {
border-style: none;
}
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers (opinionated).
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 (changed) */
font-size: inherit; /* 1 (changed) */
line-height: inherit; /* 1 (changed) */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/
button,
html [type="button"], /* 1 */
[type="reset"],
[type="submit"] {
-webkit-appearance: button; /* 2 */
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule (removed).
*/
/**
* Change the border, margin, and padding in all browsers (opinionated) (changed).
*/
fieldset {
border: 0;
margin: 0;
padding: 0;
}
/**
* 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 {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* 1. Add the correct display in IE 9-.
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Remove the default vertical scrollbar in IE.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10-.
* 2. Remove the padding in IE 10-.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-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 and cancel buttons in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-cancel-button,
[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 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in IE 9-.
* 1. Add the correct display in Edge, IE, and Firefox.
*/
details, /* 1 */
menu {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
outline: none;
}
/* Scripting
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
canvas {
display: inline-block;
}
/**
* Add the correct display in IE.
*/
template {
display: none;
}
/* Hidden
========================================================================== */
/**
* Add the correct display in IE 10-.
*/
[hidden] {
display: none;
}

View File

@@ -0,0 +1,38 @@
/* Animations */
@keyframes loading {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes slide-down {
0% {
opacity: 0;
transform: translateY(calc(-1 * var(--unit-8)));
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}

View File

@@ -0,0 +1,43 @@
/* Optimized for East Asian CJK */
html:lang(zh),
html:lang(zh-Hans),
.lang-zh,
.lang-zh-hans {
font-family: var(--cjk-zh-hans-font-family);
}
html:lang(zh-Hant),
.lang-zh-hant {
font-family: var(--cjk-zh-hant-font-family);
}
html:lang(ja),
.lang-ja {
font-family: var(--cjk-jp-font-family);
}
html:lang(ko),
.lang-ko {
font-family: var(--cjk-ko-font-family);
}
:lang(zh),
:lang(ja),
.lang-cjk {
& ins,
& u {
border-bottom: var(--border-width) solid;
text-decoration: none;
}
& del + del,
& del + s,
& ins + ins,
& ins + u,
& s + del,
& s + s,
& u + ins,
& u + u {
margin-left: .125em;
}
}

View File

@@ -0,0 +1,55 @@
/* Autocomplete */
.form-autocomplete {
position: relative;
& .form-autocomplete-input {
align-content: flex-start;
display: flex;
flex-wrap: wrap;
height: auto;
min-height: var(--unit-8);
padding: var(--unit-h);
background: var(--input-bg-color);
&.is-focused {
outline: var(--focus-outline);
outline-offset: calc(var(--focus-outline-offset) * -1);
}
& .form-input {
background: transparent;
border-color: transparent;
box-shadow: none;
display: inline-block;
flex: 1 0 auto;
height: var(--unit-6);
line-height: var(--unit-4);
margin: var(--unit-h);
width: auto;
&:focus {
outline: none;
}
}
}
& .menu {
left: 0;
position: absolute;
top: 100%;
width: 100%;
& .menu-item.selected > a, & .menu-item > a:hover {
background: var(--menu-item-hover-bg-color);
color: var(--menu-item-hover-color);
}
& .group-item, & .group-item:hover {
color: var(--tertiary-text-color);
text-transform: uppercase;
background: none;
font-size: 0.6rem;
font-weight: bold;
}
}
}

View File

@@ -0,0 +1,64 @@
/* Badges */
.badge {
position: relative;
white-space: nowrap;
&[data-badge],
&:not([data-badge]) {
&::after {
background: var(--primary-color);
background-clip: padding-box;
border-radius: .5rem;
box-shadow: 0 0 0 1px var(--body-color);
color: var(--contrast-text-color);
content: attr(data-badge);
display: inline-block;
transform: translate(-.05rem, -.5rem);
}
}
&[data-badge] {
&::after {
font-size: var(--font-size-sm);
height: .9rem;
line-height: 1;
min-width: .9rem;
padding: .1rem .2rem;
text-align: center;
white-space: nowrap;
}
}
&:not([data-badge]),
&[data-badge=""] {
&::after {
height: 6px;
min-width: 6px;
padding: 0;
width: 6px;
}
}
/* Badges for Buttons */
&.btn {
&::after {
position: absolute;
top: 0;
right: 0;
transform: translate(50%, -50%);
}
}
/* Badges for Avatars */
&.avatar {
&::after {
position: absolute;
top: 14.64%;
right: 14.64%;
transform: translate(50%, -50%);
z-index: var(--zindex-1);
}
}
}

View File

@@ -0,0 +1,61 @@
/* Base */
*,
*::before,
*::after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
font-size: var(--html-font-size);
line-height: var(--html-line-height);
-webkit-tap-highlight-color: transparent;
scrollbar-gutter: stable;
}
/* Reserve space for vert. scrollbar to avoid layout shifting when scrollbars are added */
html {
scrollbar-gutter: stable;
}
@media (pointer: coarse) {
html {
scrollbar-gutter: initial;
}
}
body {
background: var(--body-color);
color: var(--text-color);
font-family: var(--body-font-family);
font-size: var(--font-size);
overflow-x: hidden;
text-rendering: optimizeLegibility;
}
a {
color: var(--link-color);
outline: none;
text-decoration: none;
}
a:focus-visible {
outline: var(--focus-outline);
outline-offset: var(--focus-outline-offset);
}
a:focus,
a:hover,
a:active,
a.active {
text-decoration: underline;
}
summary {
cursor: pointer;
}
summary:focus-visible {
outline: var(--focus-outline);
outline-offset: var(--focus-outline-offset);
}

View File

@@ -0,0 +1,257 @@
/* Buttons */
:root {
--btn-bg-color: var(--body-color);
--btn-hover-bg-color: var(--gray-50);
--btn-border-color: var(--border-color);
--btn-text-color: var(--text-color);
--btn-icon-color: var(--icon-color);
--btn-font-weight: 400;
--btn-box-shadow: var(--box-shadow-xs);
--btn-primary-bg-color: var(--primary-color);
--btn-primary-hover-bg-color: var(--primary-color-highlight);
--btn-primary-text-color: var(--contrast-text-color);
--btn-success-bg-color: var(--success-color);
--btn-success-hover-bg-color: var(--success-color-highlight);
--btn-success-text-color: var(--contrast-text-color);
--btn-error-bg-color: var(--error-color);
--btn-error-hover-bg-color: var(--error-color-highlight);
--btn-error-text-color: var(--contrast-text-color);
--btn-link-text-color: var(--link-color);
--btn-link-hover-text-color: var(--link-color);
}
.btn {
appearance: none;
background: var(--btn-bg-color);
border: var(--border-width) solid var(--btn-border-color);
border-radius: var(--border-radius);
color: var(--btn-text-color);
font-weight: var(--btn-font-weight);
cursor: pointer;
display: inline-flex;
align-items: baseline;
justify-content: center;
font-size: var(--font-size);
height: var(--control-size);
line-height: var(--line-height);
outline: none;
padding: var(--control-padding-y) var(--control-padding-x);
box-shadow: var(--btn-box-shadow);
text-align: center;
text-decoration: none;
transition: background 0.2s, border 0.2s, box-shadow 0.2s, color 0.2s;
user-select: none;
vertical-align: middle;
white-space: nowrap;
&:focus-visible {
outline: var(--focus-outline);
outline-offset: var(--focus-outline-offset);
}
&:hover {
background: var(--btn-hover-bg-color);
text-decoration: none;
}
&[disabled],
&:disabled,
&.disabled {
cursor: default;
opacity: 0.5;
pointer-events: none;
}
&:focus,
&:hover,
&:active,
&.active {
text-decoration: none;
}
/* Button Primary */
&.btn-primary {
background: var(--btn-primary-bg-color);
border-color: transparent;
color: var(--btn-primary-text-color);
--btn-icon-color: var(--btn-primary-text-color);
&:hover {
background: var(--btn-primary-hover-bg-color);
}
}
/* Button Colors */
&.btn-success {
background: var(--btn-success-bg-color);
border-color: transparent;
color: var(--btn-success-text-color);
--btn-icon-color: var(--btn-success-text-color);
&:hover {
background: var(--btn-success-hover-bg-color);
}
}
&.btn-error {
--btn-border-color: var(--error-color);
--btn-text-color: var(--error-color);
&:hover {
--btn-hover-bg-color: var(--error-color-shade);
}
}
/* Button Link */
&.btn-link {
background: transparent;
border-color: transparent;
box-shadow: none;
color: var(--btn-link-text-color);
--btn-icon-color: var(--btn-link-text-color);
&:hover {
color: var(--btn-link-hover-text-color);
--btn-icon-color: var(--btn-link-hover-text-color);
}
&:focus,
&:hover,
&:active,
&.active {
text-decoration: none;
}
}
/* Button Sizes */
&.btn-sm {
font-size: var(--font-size-sm);
height: var(--control-size-sm);
padding: var(--control-padding-y-sm) var(--control-padding-x-sm);
}
&.btn-lg {
font-size: var(--font-size-lg);
height: var(--control-size-lg);
padding: var(--control-padding-y-lg) var(--control-padding-x-lg);
}
/* Button Block */
&.btn-block {
display: block;
width: 100%;
}
/* Button Action */
&.btn-action {
width: var(--control-size);
padding-left: 0;
padding-right: 0;
&.btn-sm {
width: var(--control-size-sm);
}
&.btn-lg {
width: var(--control-size-lg);
}
}
/* Button Clear */
&.btn-clear {
background: transparent;
border: 0;
color: currentColor;
box-shadow: none;
height: var(--unit-5);
line-height: var(--unit-4);
margin-left: var(--unit-1);
margin-right: -2px;
opacity: 1;
padding: var(--unit-h);
text-decoration: none;
width: var(--unit-5);
&::before {
content: "\2715";
}
}
/* Wider button */
&.btn-wide {
padding-left: var(--unit-6);
padding-right: var(--unit-6);
}
/* Small icon button */
&.btn-sm.btn-icon {
display: inline-flex;
align-items: baseline;
gap: var(--unit-h);
svg {
align-self: center;
}
}
/* Button icons */
& svg {
color: var(--btn-icon-color);
align-self: center;
}
}
/* Button groups */
.btn-group {
display: inline-flex;
flex-wrap: wrap;
.btn {
flex: 1 0 auto;
&:first-child:not(:last-child) {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
&:not(:first-child):not(:last-child) {
border-radius: 0;
margin-left: calc(-1 * var(--border-width));
}
&:last-child:not(:first-child) {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
margin-left: calc(-1 * var(--border-width));
}
&:focus,
&:hover,
&:active,
&.active {
z-index: var(--zindex-0);
}
}
&.btn-group-block {
display: flex;
.btn {
flex: 1 0 0;
}
}
}

View File

@@ -0,0 +1,30 @@
/* Code */
:root {
--code-bg-color: var(--body-color-contrast);
--code-color: var(--text-color);
}
code {
border-radius: var(--border-radius);
line-height: 1.25;
padding: .1rem .2rem;
background: var(--code-bg-color);
color: var(--code-color);
font-size: 85%;
}
.code {
border-radius: var(--border-radius);
background: var(--code-bg-color);
color: var(--text-color);
position: relative;
& code {
color: inherit;
display: block;
line-height: 1.5;
overflow-x: auto;
padding: var(--unit-2);
width: 100%;
}
}

View File

@@ -0,0 +1,36 @@
/* Dropdown */
.dropdown {
display: inline-block;
position: relative;
.menu {
animation: fade-in .15s ease 1;
display: none;
left: 0;
max-height: 50vh;
overflow-y: auto;
position: absolute;
top: 100%;
}
&.dropdown-right {
.menu {
left: auto;
right: 0;
}
}
&.active .menu,
.dropdown-toggle:focus + .menu,
.menu:hover {
display: block;
}
/* Fix dropdown-toggle border radius in button groups */
.btn-group {
.dropdown-toggle:nth-last-child(2) {
border-bottom-right-radius: var(--border-radius);
border-top-right-radius: var(--border-radius);
}
}
}

View File

@@ -0,0 +1,21 @@
/* Empty states (or Blank slates) */
.empty {
background: var(--body-color-contrast);
border-radius: var(--border-radius);
color: var(--secondary-text-color);
text-align: center;
padding: var(--unit-16) var(--unit-8);
.empty-icon {
margin-bottom: var(--layout-spacing-lg);
}
.empty-title,
.empty-subtitle {
margin: var(--layout-spacing) auto;
}
.empty-action {
margin-top: var(--layout-spacing-lg);
}
}

View File

@@ -0,0 +1,515 @@
/* Forms */
:root {
--input-bg-color: var(--body-color);
--input-disabled-bg-color: var(--gray-100);
--input-text-color: var(--text-color);
--input-hint-color: var(--secondary-text-color);
--input-border-color: var(--border-color);
--input-placeholder-color: var(--tertiary-text-color);
--input-box-shadow: var(--box-shadow-xs);
--checkbox-bg-color: var(--body-color);
--checkbox-checked-bg-color: var(--primary-color);
--checkbox-disabled-bg-color: var(--gray-100);
--checkbox-border-color: var(--border-color);
--checkbox-icon-color: #fff;
--switch-bg-color: var(--gray-300);
--switch-border-color: var(--gray-400);
--switch-toggle-color: #fff;
}
.form-group {
&:first-of-type {
margin-top: var(--unit-4);
}
&:not(:last-child) {
margin-bottom: var(--unit-4);
}
}
fieldset {
margin-bottom: var(--layout-spacing-lg);
}
legend {
font-size: var(--font-size-lg);
font-weight: 500;
margin-bottom: var(--layout-spacing-lg);
}
/* Form element: Label */
.form-label {
display: block;
line-height: var(--line-height);
margin-bottom: var(--unit-2);
font-weight: 500;
}
details summary .form-label {
margin-bottom: 0;
}
details[open] summary .form-label {
margin-bottom: var(--unit-2);
}
/* Form element: Input */
.form-input {
appearance: none;
background: var(--input-bg-color);
background-image: none;
border: var(--border-width) solid var(--input-border-color);
border-radius: var(--border-radius);
box-shadow: var(--input-box-shadow);
color: var(--input-text-color);
display: block;
font-size: var(--font-size);
height: var(--control-size);
line-height: var(--line-height);
max-width: 100%;
outline: none;
padding: var(--control-padding-y) var(--control-padding-x);
position: relative;
transition: background 0.2s, border 0.2s, color 0.2s;
width: 100%;
&:focus {
outline: var(--focus-outline);
outline-offset: calc(var(--focus-outline-offset) * -1);
}
&::placeholder {
color: var(--input-placeholder-color);
opacity: 1;
}
/* Input sizes */
&.input-sm {
font-size: var(--font-size-sm);
height: var(--control-size-sm);
padding: var(--control-padding-y-sm) var(--control-padding-x-sm);
}
&.input-lg {
font-size: var(--font-size-lg);
height: var(--control-size-lg);
padding: var(--control-padding-y-lg) var(--control-padding-x-lg);
}
&.input-inline {
display: inline-block;
vertical-align: middle;
width: auto;
}
/* Input types */
&[type="file"] {
height: auto;
}
}
/* Form element: Textarea */
textarea.form-input {
&,
&.input-lg,
&.input-sm {
height: auto;
}
}
/* Form element: Input hint */
.form-input-hint {
color: var(--input-hint-color);
font-size: var(--font-size-sm);
margin-top: var(--unit-1);
.has-success &,
.is-success + & {
color: var(--success-color);
}
.has-error &,
.is-error + & {
color: var(--error-color);
}
}
/* Form element: Select */
.form-select {
appearance: none;
background: var(--input-bg-color);
border: var(--border-width) solid var(--input-border-color);
border-radius: var(--border-radius);
box-shadow: var(--input-box-shadow);
color: var(--input-text-color);
font-size: var(--font-size);
height: var(--control-size);
line-height: var(--line-height);
outline: none;
padding: var(--control-padding-y) var(--control-padding-x);
vertical-align: middle;
width: 100%;
&:focus {
outline: var(--focus-outline);
outline-offset: calc(var(--focus-outline-offset) * -1);
}
/* Select sizes */
&.select-sm {
font-size: var(--font-size-sm);
height: var(--control-size-sm);
padding: var(--control-padding-y-sm) calc(var(--control-icon-size) + var(--control-padding-x-sm)) var(--control-padding-y-sm) var(--control-padding-x-sm);
}
&.select-lg {
font-size: var(--font-size-lg);
height: var(--control-size-lg);
padding: var(--control-padding-y-lg) calc(var(--control-icon-size) + var(--control-padding-x-lg)) var(--control-padding-y-lg) var(--control-padding-x-lg);
}
/* Multiple select */
&[size],
&[multiple] {
height: auto;
padding: var(--control-padding-y) var(--control-padding-x);
& option {
padding: var(--unit-h) var(--unit-1);
}
}
&:not([multiple]):not([size]) {
background: var(--input-bg-color) url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%204%205'%3E%3Cpath%20fill='%23667189'%20d='M2%200L0%202h4zm0%205L0%203h4z'/%3E%3C/svg%3E") no-repeat right .35rem center / .4rem .5rem;
padding-right: calc(var(--control-icon-size) + var(--control-padding-x));
}
}
/* Form element: Checkbox and Radio */
.form-checkbox,
.form-radio,
.form-switch {
display: block;
line-height: var(--line-height);
margin: calc((var(--control-size) - var(--control-size-sm)) / 2) 0;
min-height: var(--control-size-sm);
padding: calc((var(--control-size-sm) - var(--line-height)) / 2) var(--control-padding-x) calc((var(--control-size-sm) - var(--line-height)) / 2) calc(var(--control-icon-size) + var(--control-padding-x));
position: relative;
input {
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
position: absolute;
width: 1px;
&:focus-visible + .form-icon {
outline: var(--focus-outline);
outline-offset: var(--focus-outline-offset);
}
&:checked + .form-icon {
background: var(--checkbox-checked-bg-color);
border-color: var(--checkbox-checked-bg-color);
}
}
.form-icon {
border: var(--border-width) solid var(--checkbox-border-color);
box-shadow: var(--input-box-shadow);
cursor: pointer;
display: inline-block;
position: absolute;
transition: background .2s, border .2s, color .2s;
}
/* Input checkbox, radio, and switch sizes */
&.input-sm {
font-size: var(--font-size-sm);
margin: 0;
}
&.input-lg {
font-size: var(--font-size-lg);
margin: calc((var(--control-size-lg) - var(--control-size-sm)) / 2) 0;
}
}
.form-checkbox,
.form-radio {
.form-icon {
background: var(--checkbox-bg-color);
height: var(--control-icon-size);
left: 0;
top: calc((var(--control-size-sm) - var(--control-icon-size)) / 2);
width: var(--control-icon-size);
}
}
.form-checkbox {
font-weight: 500;
.form-icon {
border-radius: var(--border-radius);
}
input {
&:checked + .form-icon {
&::before {
background-clip: padding-box;
border: var(--border-width-lg) solid var(--checkbox-icon-color);
border-left-width: 0;
border-top-width: 0;
content: "";
height: 9px;
left: 50%;
margin-left: -3px;
margin-top: -6px;
position: absolute;
top: 50%;
transform: rotate(45deg);
width: 6px;
}
}
&:indeterminate + .form-icon {
background: var(--checkbox-checked-bg-color);
border-color: var(--checkbox-checked-bg-color);
&::before {
background: var(--checkbox-icon-color);
content: "";
height: 2px;
left: 50%;
margin-left: -5px;
margin-top: -1px;
position: absolute;
top: 50%;
width: 10px;
}
}
}
}
.form-radio {
.form-icon {
border-radius: 50%;
}
input {
&:checked + .form-icon {
&::before {
background: var(--checkbox-icon-color);
border-radius: 50%;
content: "";
height: 6px;
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 6px;
}
}
}
}
/* Form element: Switch */
.form-switch {
padding-left: calc(var(--unit-8) + var(--control-padding-x));
.form-icon {
background: var(--switch-bg-color);
background-clip: padding-box;
border-color: var(--switch-border-color);
border-radius: calc(var(--unit-2) + var(--border-width));
height: calc(var(--unit-4) + var(--border-width) * 2);
left: 0;
top: calc((var(--control-size-sm) - var(--unit-4)) / 2 - var(--border-width));
width: var(--unit-8);
&::before {
background: var(--switch-toggle-color);
border-radius: 50%;
content: "";
display: block;
height: var(--unit-4);
left: 0;
position: absolute;
top: 0;
transition: background .2s, border .2s, color .2s, left .2s;
width: var(--unit-4);
}
}
input {
&:checked + .form-icon {
&::before {
left: 14px;
}
}
}
}
/* Form Icons */
.has-icon-left,
.has-icon-right {
position: relative;
.form-icon {
height: var(--control-icon-size);
margin: 0 var(--control-padding-y);
position: absolute;
top: 50%;
transform: translateY(-50%);
width: var(--control-icon-size);
z-index: calc(var(--zindex-0) + 1);
}
}
.has-icon-left {
& .form-icon {
left: var(--border-width);
}
& .form-input {
padding-left: calc(var(--control-icon-size) + var(--control-padding-y) * 2);
}
}
.has-icon-right {
& .form-icon {
right: var(--border-width);
}
& .form-input {
padding-right: calc(var(--control-icon-size) + var(--control-padding-y) * 2);
}
}
/* Form element: Input groups */
.input-group {
display: flex;
.input-group-addon {
background: var(--body-color);
border: var(--border-width) solid var(--input-border-color);
border-radius: var(--border-radius);
line-height: var(--line-height);
padding: var(--control-padding-y) var(--control-padding-x);
white-space: nowrap;
&.addon-sm {
font-size: var(--font-size-sm);
padding: var(--control-padding-y-sm) var(--control-padding-x-sm);
}
&.addon-lg {
font-size: var(--font-size-lg);
padding: var(--control-padding-y-lg) var(--control-padding-x-lg);
}
}
.form-input,
.form-select {
flex: 1 1 auto;
width: 1%;
}
.input-group-btn {
z-index: var(--zindex-0);
}
.form-input,
.form-select,
.input-group-addon,
.input-group-btn {
&:first-child:not(:last-child) {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
&:not(:first-child):not(:last-child) {
border-radius: 0;
margin-left: calc(-1 * var(--border-width));
}
&:last-child:not(:first-child) {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
margin-left: calc(-1 * var(--border-width));
}
&:focus {
z-index: calc(var(--zindex-0) + 1);
}
}
.form-select {
width: auto;
}
&.input-inline {
display: inline-flex;
}
}
/* Form validation states */
.form-input,
.form-select {
.has-success &,
&.is-success {
background: var(--success-color-shade);
border-color: var(--success-color);
&:focus {
outline-color: var(--success-color);
}
}
.has-error &,
&.is-error {
background: var(--error-color-shade);
border-color: var(--error-color);
&:focus {
outline-color: var(--error-color);
}
}
}
/* Form disabled and readonly */
.form-input,
.form-select {
&:disabled,
&.disabled {
background-color: var(--input-disabled-bg-color);
cursor: not-allowed;
}
}
input {
&:disabled,
&.disabled {
& + .form-icon {
background: var(--checkbox-disabled-bg-color);
cursor: not-allowed;
}
}
}
/* Increase input font size on small viewports to prevent zooming on focus the input */
/* on mobile devices. 430px relates to the "normalized" iPhone 14 Pro Max */
/* viewport size */
@media screen and (max-width: 430px) {
.form-input {
font-size: 16px;
}
}

View File

@@ -0,0 +1,89 @@
:root {
--menu-bg-color: var(--body-color);
--menu-border-color: var(--gray-200);
--menu-border-radius: var(--border-radius);
--menu-box-shadow: var(--box-shadow);
--menu-item-color: var(--text-color);
--menu-item-hover-color: var(--primary-text-color);
--menu-item-bg-color: transparent;
--menu-item-hover-bg-color: var(--primary-color-shade);
}
/* Menus */
.menu {
background: var(--menu-bg-color);
border: solid 1px var(--menu-border-color);
border-radius: var(--menu-border-radius);
box-shadow: var(--menu-box-shadow);
list-style: none;
margin: 0;
min-width: var(--control-width-xs);
transform: translateY(var(--layout-spacing-sm));
z-index: var(--zindex-3);
&.menu-nav {
background: transparent;
box-shadow: none;
}
.menu-item {
margin-top: 0;
padding: 0 var(--unit-4);
position: relative;
text-decoration: none;
&:first-of-type {
padding-top: var(--unit-2);
}
&:last-of-type {
padding-bottom: var(--unit-2);
}
& > a, .btn.btn-link {
border-radius: var(--menu-border-radius);
color: var(--menu-item-color);
background: var(--menu-item-bg-color);
display: block;
margin: 0 calc(-1 * var(--unit-2));
padding: var(--unit-1) var(--unit-2);
text-decoration: none;
&:focus,
&:hover,
&:active,
&.active {
background: var(--menu-item-hover-bg-color);
color: var(--menu-item-hover-color);
}
}
.form-checkbox,
.form-radio,
.form-switch {
margin: var(--unit-h) 0;
}
& + .menu-item {
margin-top: var(--unit-1);
}
}
& .menu-badge {
align-items: center;
display: flex;
height: 100%;
position: absolute;
right: 0;
top: 0;
.label {
margin-right: var(--unit-2);
}
}
& .divider {
border-bottom: solid 1px var(--secondary-border-color);
margin: var(--unit-2) 0;
}
}

View File

@@ -0,0 +1,93 @@
/* Modals */
:root {
--modal-overlay-bg-color: rgba(243, 244, 246, 0.6);
--modal-container-bg-color: var(--body-color);
--modal-container-border-color: var(--gray-200);
--modal-border-radius: var(--border-radius-lg);
--modal-box-shadow: var(--box-shadow-lg);
}
.modal {
align-items: center;
bottom: 0;
display: none;
justify-content: center;
left: 0;
opacity: 0;
overflow: hidden;
padding: var(--layout-spacing);
position: fixed;
right: 0;
top: 0;
&:target,
&.active {
display: flex;
opacity: 1;
z-index: var(--zindex-4);
& .modal-overlay {
animation: fade-in .15s ease 1;
background: var(--modal-overlay-bg-color);
bottom: 0;
cursor: default;
display: block;
left: 0;
position: absolute;
right: 0;
top: 0;
}
& .modal-container {
animation: fade-in .15s ease 1;
z-index: var(--zindex-0);
}
}
&.active.closing {
& .modal-overlay, & .modal-container {
animation: fade-out .15s ease 1;
}
}
}
.modal-container {
background: var(--modal-container-bg-color);
border: solid 1px var(--modal-container-border-color);
border-radius: var(--modal-border-radius);
box-shadow: var(--modal-box-shadow);
display: flex;
flex-direction: column;
gap: var(--unit-4);
max-height: 75vh;
max-width: var(--control-width-md);
padding: var(--unit-6);
width: 100%;
& .modal-header {
color: var(--text-color);
& button.close {
background: none;
border: none;
padding: 0;
line-height: 0;
cursor: pointer;
opacity: .85;
color: var(--secondary-text-color);
&:hover {
opacity: 1;
}
}
}
& .modal-body {
overflow-y: auto;
position: relative;
}
& .modal-footer {
text-align: right;
}
}

View File

@@ -0,0 +1,61 @@
/* Pagination */
.pagination {
display: flex;
list-style: none;
margin: var(--unit-1) 0;
padding: var(--unit-1) 0;
& .page-item {
margin: var(--unit-1) var(--unit-o);
& span {
display: inline-block;
padding: var(--unit-1) var(--unit-1);
}
& a {
border-radius: var(--border-radius);
display: inline-block;
padding: var(--unit-1) var(--unit-2);
text-decoration: none;
&:focus,
&:hover {
color: var(--primary-text-color);
}
}
&.disabled {
& a {
cursor: default;
opacity: .5;
pointer-events: none;
}
}
&.active {
& a {
background: var(--primary-color);
color: var(--contrast-text-color);
}
}
&.page-prev,
&.page-next {
flex: 1 0 50%;
}
&.page-next {
text-align: right;
}
& .page-item-title {
margin: 0;
}
& .page-item-subtitle {
margin: 0;
opacity: .5;
}
}
}

View File

@@ -0,0 +1,26 @@
/* Tables */
.table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
text-align: left;
/* Scrollable tables */
&.table-scroll {
display: block;
overflow-x: auto;
padding-bottom: 0.75rem;
white-space: nowrap;
}
& td,
& th {
border-bottom: var(--border-width) solid var(--border-color);
padding: var(--unit-3) var(--unit-2);
}
& th {
border-bottom-width: var(--border-width-lg);
}
}

View File

@@ -0,0 +1,75 @@
/* Tabs */
:root {
--tab-color: var(--text-color);
--tab-hover-color: var(--primary-text-color);
--tab-active-color: var(--primary-text-color);
--tab-highlight-color: var(--primary-color);
}
.tab {
align-items: center;
border-bottom: var(--border-width) solid var(--border-color);
display: flex;
flex-wrap: wrap;
list-style: none;
margin: var(--unit-1) 0 calc(var(--unit-1) - var(--border-width)) 0;
& .tab-item {
margin-top: 0;
& a {
border-bottom: var(--border-width-lg) solid transparent;
color: var(--tab-color);
display: block;
margin: 0 var(--unit-2) 0 0;
padding: var(--unit-2) var(--unit-1) calc(var(--unit-2) - var(--border-width-lg)) var(--unit-1);
text-decoration: none;
&:focus,
&:hover {
color: var(--tab-hover-color);
}
}
&.active a,
& a.active {
border-bottom-color: var(--tab-highlight-color);
color: var(--tab-active-color);
}
&.tab-action {
flex: 1 0 auto;
text-align: right;
}
& .btn-clear {
margin-top: calc(-1 * var(--unit-1));
}
}
&.tab-block {
& .tab-item {
flex: 1 0 0;
text-align: center;
& a {
margin: 0;
}
& .badge {
&[data-badge]::after {
position: absolute;
right: var(--unit-h);
top: var(--unit-h);
transform: translate(0, 0);
}
}
}
}
&:not(.tab-block) {
& .badge {
padding-right: 0;
}
}
}

View File

@@ -0,0 +1,35 @@
/* Toasts */
.toast {
background: var(--gray-600);
border-radius: var(--border-radius);
color: var(--contrast-text-color);
display: block;
padding: var(--layout-spacing);
width: 100%;
&.toast-primary {
background: var(--primary-color);
}
&.toast-success {
background: var(--success-color);
}
&.toast-warning {
background: var(--warning-color);
}
&.toast-error {
background: var(--error-color);
}
.btn-clear {
margin: var(--unit-h);
}
p {
&:last-child {
margin-bottom: 0;
}
}
}

View File

@@ -0,0 +1,117 @@
/* Typography */
/* Headings */
h1,
h2,
h3,
h4,
h5,
h6 {
color: inherit;
font-weight: 500;
line-height: 1.2;
margin-bottom: 0.5em;
margin-top: 0;
}
.h1,
.h2,
.h3,
.h4,
.h5,
.h6 {
font-weight: 500;
}
h1,
.h1 {
font-size: 2rem;
}
h2,
.h2 {
font-size: 1.6rem;
}
h3,
.h3 {
font-size: 1.4rem;
}
h4,
.h4 {
font-size: 1.2rem;
}
h5,
.h5 {
font-size: 1rem;
}
h6,
.h6 {
font-size: 0.8rem;
}
/* Paragraphs */
p {
margin: 0 0 var(--line-height);
}
/* Semantic text elements */
a,
ins,
u {
text-decoration-skip-ink: auto;
}
abbr[title] {
border-bottom: var(--border-width) dotted;
cursor: help;
text-decoration: none;
}
/* Blockquote */
blockquote {
border-left: var(--border-width-lg) solid var(--border-color);
margin-left: 0;
padding: var(--unit-2) var(--unit-4);
& p:last-child {
margin-bottom: 0;
}
}
/* Lists */
ul,
ol {
margin: var(--unit-4) 0 var(--unit-4) var(--unit-4);
padding: 0;
& ul,
& ol {
margin: var(--unit-4) 0 var(--unit-4) var(--unit-4);
}
& li {
margin-top: var(--unit-2);
}
}
ul {
list-style: disc inside;
& ul {
list-style-type: circle;
}
}
ol {
list-style: decimal inside;
& ol {
list-style-type: lower-alpha;
}
}
dl {
& dt {
font-weight: bold;
}
& dd {
margin: var(--unit-1) 0 var(--unit-4) 0;
}
}

View File

@@ -0,0 +1,296 @@
/* Colors */
.text-primary {
color: var(--primary-text-color);
}
.text-secondary {
color: var(--secondary-text-color);
}
.text-tertiary {
color: var(--tertiary-text-color);
}
.text-success {
color: var(--success-color);
}
.text-warning {
color: var(--warning-color);
}
.text-error {
color: var(--error-color);
}
.icon-color {
color: var(--icon-color);
}
/* Display */
.d-block {
display: block;
}
.d-inline {
display: inline;
}
.d-inline-block {
display: inline-block;
}
.d-flex {
display: flex;
}
.d-inline-flex {
display: inline-flex;
}
.d-none,
.d-hide {
display: none !important;
}
.d-visible {
visibility: visible;
}
.d-invisible {
visibility: hidden;
}
.text-hide {
background: transparent;
border: 0;
color: transparent;
font-size: 0;
line-height: 0;
text-shadow: none;
}
.text-assistive {
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
/* Loading */
.loading {
color: transparent !important;
min-height: var(--unit-4);
pointer-events: none;
position: relative;
&::after {
animation: loading 500ms infinite linear;
background: transparent;
border: var(--border-width-lg) solid var(--primary-color);
border-radius: 50%;
border-right-color: transparent;
border-top-color: transparent;
content: "";
display: block;
height: var(--unit-4);
left: 50%;
margin-left: calc(-1 * var(--unit-2));
margin-top: calc(-1 * var(--unit-2));
opacity: 1;
padding: 0;
position: absolute;
top: 50%;
width: var(--unit-4);
z-index: var(--zindex-0);
}
&.loading-lg {
min-height: var(--unit-10);
&::after {
height: var(--unit-8);
margin-left: calc(-1 * var(--unit-4));
margin-top: calc(-1 * var(--unit-4));
width: var(--unit-8);
}
}
}
/* Position */
.m-0 {
margin: 0 !important;
}
.mb-0 {
margin-bottom: 0 !important;
}
.ml-0 {
margin-left: 0 !important;
}
.mr-0 {
margin-right: 0 !important;
}
.mt-0 {
margin-top: 0 !important;
}
.mx-0 {
margin-left: 0 !important;
margin-right: 0 !important;
}
.my-0 {
margin-bottom: 0 !important;
margin-top: 0 !important;
}
.m-1 {
margin: var(--unit-1) !important;
}
.mb-1 {
margin-bottom: var(--unit-1) !important;
}
.ml-1 {
margin-left: var(--unit-1) !important;
}
.mr-1 {
margin-right: var(--unit-1) !important;
}
.mt-1 {
margin-top: var(--unit-1) !important;
}
.mx-1 {
margin-left: var(--unit-1) !important;
margin-right: var(--unit-1) !important;
}
.my-1 {
margin-bottom: var(--unit-1) !important;
margin-top: var(--unit-1) !important;
}
.m-2 {
margin: var(--unit-2) !important;
}
.mb-2 {
margin-bottom: var(--unit-2) !important;
}
.ml-2 {
margin-left: var(--unit-2) !important;
}
.mr-2 {
margin-right: var(--unit-2) !important;
}
.mt-2 {
margin-top: var(--unit-2) !important;
}
.mx-2 {
margin-left: var(--unit-2) !important;
margin-right: var(--unit-2) !important;
}
.my-2 {
margin-bottom: var(--unit-2) !important;
margin-top: var(--unit-2) !important;
}
.m-4 {
margin: var(--unit-4) !important;
}
.mb-4 {
margin-bottom: var(--unit-4) !important;
}
.ml-4 {
margin-left: var(--unit-4) !important;
}
.mr-4 {
margin-right: var(--unit-4) !important;
}
.mt-4 {
margin-top: var(--unit-4) !important;
}
.mx-4 {
margin-left: var(--unit-4) !important;
margin-right: var(--unit-4) !important;
}
.my-4 {
margin-bottom: var(--unit-4) !important;
margin-top: var(--unit-4) !important;
}
.mx-auto {
margin-left: auto;
margin-right: auto;
}
/* Text */
.text-normal {
font-weight: normal;
}
.text-bold {
font-weight: bold;
}
.text-italic {
font-style: italic;
}
.text-large {
font-size: 1.2em;
}
.text-small {
font-size: .9em;
}
.text-tiny {
font-size: .8em;
}
.text-muted {
opacity: .8;
}
.truncate {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Flex */
.align-baseline {
align-items: baseline;
}
.align-center {
align-items: center;
}
.justify-between {
justify-content: space-between;
}

View File

@@ -0,0 +1,135 @@
:root {
/* Color palette */
--gray-50: rgb(249, 250, 251);
--gray-100: rgb(243, 244, 246);
--gray-200: rgb(229, 231, 235);
--gray-300: rgb(209, 213, 219);
--gray-400: rgb(156, 163, 175);
--gray-500: rgb(107, 114, 128);
--gray-600: rgb(75, 85, 99);
--gray-700: rgb(55, 65, 81);
--gray-800: rgb(31, 41, 55);
--gray-900: rgb(17, 24, 39);
--primary-color: hsl(241, 63%, 59%);
--primary-color-highlight: hsl(241, 63%, 64%);
--primary-color-shade: hsl(241, 63%, 59%, 0.075);
--alternative-color: hsl(179, 94%, 29%);
--alternative-color-dark: hsl(179, 94%, 22%);
--success-color: hsl(142, 76%, 36%);
--success-color-highlight: hsl(142, 76%, 40%);
--success-color-shade: hsla(142, 76%, 36%, 0.1);
--warning-color: hsl(38, 92%, 50%);
--warning-color-highlight: hsl(38, 92%, 55%);
--warning-color-shade: hsla(38, 92%, 50%, 0.1);
--error-color: hsl(0, 72%, 51%);
--error-color-highlight: hsl(0, 72%, 60%);
--error-color-shade: hsla(0, 72%, 51%, 0.1);
/* Core colors */
--text-color: var(--gray-700);
--secondary-text-color: var(--gray-500);
--tertiary-text-color: var(--gray-500);
--contrast-text-color: #fff;
--primary-text-color: hsl(241, 63%, 55%);
--link-color: var(--primary-text-color);
--secondary-link-color: hsla(241, 63%, 54%, 0.8);
--icon-color: var(--gray-500);
--border-color: var(--gray-300);
--secondary-border-color: var(--gray-200);
--body-color: #fff;
--body-color-contrast: var(--gray-100);
/* Fonts */
--base-font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto;
--mono-font-family: "SF Mono", "Segoe UI Mono", "Roboto Mono", Menlo, Courier, monospace;
--fallback-font-family: "Helvetica Neue", sans-serif;
--cjk-zh-hans-font-family: var(--base-font-family), "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", var(--fallback-font-family);
--cjk-zh-hant-font-family: var(--base-font-family), "PingFang TC", "Hiragino Sans CNS", "Microsoft JhengHei", var(--fallback-font-family);
--cjk-jp-font-family: var(--base-font-family), "Hiragino Sans", "Hiragino Kaku Gothic Pro", "Yu Gothic", YuGothic, Meiryo, var(--fallback-font-family);
--cjk-ko-font-family: var(--base-font-family), "Malgun Gothic", var(--fallback-font-family);
--body-font-family: var(--base-font-family), var(--fallback-font-family);
/* Unit sizes */
--unit-o: 0.05rem;
--unit-h: 0.1rem;
--unit-1: 0.2rem;
--unit-2: 0.4rem;
--unit-3: 0.6rem;
--unit-4: 0.8rem;
--unit-5: 1rem;
--unit-6: 1.2rem;
--unit-7: 1.4rem;
--unit-8: 1.6rem;
--unit-9: 1.8rem;
--unit-10: 2rem;
--unit-12: 2.4rem;
--unit-16: 3.2rem;
/* Font sizes */
--html-font-size: 20px;
--html-line-height: 1.5;
--font-size: 0.7rem;
--font-size-sm: 0.65rem;
--font-size-lg: 0.8rem;
--line-height: 1rem;
/* Sizes */
--layout-spacing: var(--unit-2);
--layout-spacing-sm: var(--unit-1);
--layout-spacing-lg: var(--unit-4);
--border-radius: var(--unit-1);
--border-radius-lg: var(--unit-2);
--border-width: var(--unit-o);
--border-width-lg: var(--unit-h);
--control-size: var(--unit-8);
--control-size-sm: var(--unit-6);
--control-size-lg: var(--unit-9);
--control-padding-x: var(--unit-2);
--control-padding-x-sm: calc(var(--unit-2) * 0.75);
--control-padding-x-lg: calc(var(--unit-2) * 1.5);
--control-padding-y: calc((var(--control-size) - var(--line-height)) / 2 - var(--border-width));
--control-padding-y-sm: calc((var(--control-size-sm) - var(--line-height)) / 2 - var(--border-width));
--control-padding-y-lg: calc((var(--control-size-lg) - var(--line-height)) / 2 - var(--border-width));
--control-icon-size: 0.8rem;
--control-width-xs: 180px;
--control-width-sm: 320px;
--control-width-md: 640px;
--control-width-lg: 960px;
--control-width-xl: 1280px;
/* Responsive breakpoints */
--size-xs: 480px;
--size-sm: 600px;
--size-md: 840px;
--size-lg: 960px;
--size-xl: 1280px;
--size-2x: 1440px;
--responsive-breakpoint: var(--size-xs);
/* Z-index */
--zindex-0: 1;
--zindex-1: 100;
--zindex-2: 200;
--zindex-3: 300;
--zindex-4: 400;
/* Focus */
--focus-outline: 2px solid var(--primary-color);
--focus-outline-offset: 2px;
/* Shadows */
--box-shadow-xs: rgba(0, 0, 0, 0.05) 0px 1px 2px 0px;
--box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--box-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
}

View File

@@ -1,32 +0,0 @@
$body-bg: #161822 !default;
$bg-color: lighten($body-bg, 5%) !default;
$bg-color-light: lighten($body-bg, 5%) !default;
$border-color: #4C4E53 !default;
$border-color-dark: $border-color !default;
$body-font-color: #b5bec8 !default;
$light-color: #fafafa !default;
$gray-color: #7f879b !default;
$gray-color-dark: lighten($gray-color, 20%) !default;
$primary-color: #a8b1ff !default;
$primary-color-dark: saturate($primary-color, 5%) !default;
$secondary-color: lighten($body-bg, 10%) !default;
$link-color: $primary-color !default;
$link-color-dark: darken($link-color, 5%) !default;
$link-color-light: $link-color !default;
$secondary-link-color: rgba(168, 177, 255, 0.73);
$alternative-color: #59bdb9;
$alternative-color-dark: #73f1eb;
$code-bg-color: rgba(255, 255, 255, 0.1);
$code-shadow-color: rgba(255, 255, 255, 0.2);
/* Dark theme specific */
$dt-primary-input-color: #5C68E7 !default;
$dt-primary-button-color: #5761cb !default;

View File

@@ -1,7 +0,0 @@
$alternative-color: #05a6a3;
$alternative-color-dark: darken($alternative-color, 5%);
$secondary-link-color: rgba(87, 85, 217, 0.64);
$code-bg-color: rgba(0, 0, 0, 0.05);
$code-shadow-color: rgba(0, 0, 0, 0.15);