chores: Migrate react-bootstrap changes

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2022-10-16 11:20:34 +02:00
parent 172b278c78
commit c508a7a2b3
80 changed files with 234 additions and 1502 deletions

View file

@ -53,7 +53,7 @@ describe('Intro page', () => {
cy.getByCypressId('version-modal').should('not.exist')
cy.getByCypressId('show-version-modal').click()
cy.getByCypressId('version-modal').should('be.visible')
cy.getByCypressId('version-modal').find('.modal-header .close').click()
cy.getByCypressId('version-modal').find('.modal-header .btn-close').click()
cy.getByCypressId('version-modal').should('not.exist')
})
})

View file

@ -13,7 +13,7 @@ describe('Link gets replaced with embedding: ', () => {
it('GitHub Gist', () => {
cy.setCodemirrorContent('https://gist.github.com/schacon/1')
cy.getMarkdownBody().findByCypressId('click-shield-gist').find('.preview-background').parent().click()
cy.getMarkdownBody().findByCypressId('click-shield-gist').findByCypressId('preview-background').parent().click()
cy.getMarkdownBody().findByCypressId('gh-gist').should('be.visible')
})
})

View file

@ -1,15 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
// Alternate styles
//
// Generate contextual modifier classes for colorizing the alert.
@each $color, $value in $theme-colors {
.alert-#{$color} {
@include alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level));
}
}

View file

@ -1,15 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
// Colors
//
// Contextual variations (linked badges get darker on :hover).
@each $color, $value in $theme-colors {
.badge-#{$color} {
@include badge-variant($value);
}
}

View file

@ -1,21 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.breadcrumb {
background-color: $breadcrumb-bg;
}
.breadcrumb-item {
+ .breadcrumb-item {
&::before {
color: $breadcrumb-divider-color;
}
}
&.active {
color: $breadcrumb-active-color;
}
}

View file

@ -1,72 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
// stylelint-disable selector-no-qualifying-type
//
// Base styles
//
.btn {
color: $body-color;
@include hover() {
color: $body-color;
}
&:focus,
&.focus {
box-shadow: $btn-focus-box-shadow;
}
&:not(:disabled):not(.disabled) {
&:active,
&.active {
@include box-shadow($btn-active-box-shadow);
&:focus {
@include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow);
}
}
}
}
//
// Alternate buttons
//
@each $color, $value in $theme-colors {
.btn-#{$color} {
@include button-variant($value, $value);
}
}
@each $color, $value in $theme-colors {
.btn-outline-#{$color} {
@include button-outline-variant($value);
}
}
//
// Link buttons
//
// Make a button look and behave like a link
.btn-link {
color: $link-color;
@include hover() {
color: $link-hover-color;
}
&:disabled,
&.disabled {
color: $btn-link-disabled-color;
}
// No need for an active state here
}

View file

@ -1,35 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
//
// Base styles
//
.card {
background-color: $card-bg;
border-color: $card-border-color;
}
.card-body {
color: $card-color;
}
//
// Optional textual caps
//
.card-header {
color: $card-cap-color;
background-color: $card-cap-bg;
border-bottom-color: $card-border-color;
}
.card-footer {
color: $card-cap-color;
background-color: $card-cap-bg;
border-top-color: $card-border-color;
}

View file

@ -1,30 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.carousel-control-prev,
.carousel-control-next {
color: $carousel-control-color;
// Hover/focus state
@include hover-focus() {
color: $carousel-control-color;
}
}
.carousel-indicators {
li {
background-color: $carousel-indicator-active-bg;
}
}
// Optional captions
//
//
.carousel-caption {
color: $carousel-caption-color;
}

View file

@ -1,18 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.close {
color: $close-color;
text-shadow: $close-text-shadow;
@include hover() {
color: $close-color;
}
}
button.close {
background-color: transparent;
}

View file

@ -1,25 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
// Inline code
code {
color: $code-color;
}
kbd {
color: $kbd-color;
background-color: $kbd-bg;
@include box-shadow($kbd-box-shadow);
}
// Blocks of code
pre {
color: $pre-color;
code {
color: inherit;
}
}

View file

@ -1,49 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.dropdown-menu {
color: $dropdown-color;
background-color: $dropdown-bg;
border-color: $dropdown-border-color;
@include box-shadow($dropdown-box-shadow);
}
// Dividers (basically an `<hr>`) within the dropdown
.dropdown-divider {
@include nav-divider($dropdown-divider-bg, $dropdown-divider-margin-y, true);
}
.dropdown-item {
color: $dropdown-link-color;
@include hover-focus() {
color: $dropdown-link-hover-color;
@include gradient-bg($dropdown-link-hover-bg);
}
&.active,
&:active {
color: $dropdown-link-active-color;
@include gradient-bg($dropdown-link-active-bg);
}
&.disabled,
&:disabled {
color: $dropdown-link-disabled-color;
background-color: transparent;
}
}
// Dropdown section headers
.dropdown-header {
color: $dropdown-header-color;
}
// Dropdown text
.dropdown-item-text {
color: $dropdown-link-color;
}

View file

@ -1,65 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
// stylelint-disable selector-no-qualifying-type
//
// Textual form controls
//
.form-control {
color: $input-color;
background-color: $input-bg;
border-color: $input-border-color;
@include box-shadow($input-box-shadow);
&:-moz-focusring {
text-shadow: 0 0 0 $input-color;
}
// Customize the `:focus` state to imitate native WebKit styles.
@include form-control-focus($ignore-warning: true);
// Placeholder
&::placeholder {
color: $input-placeholder-color;
}
&:disabled,
&[readonly] {
background-color: $input-disabled-bg;
}
}
select.form-control {
&:focus::-ms-value {
// Suppress the nested default white text on blue background highlight given to
// the selected option text when the (still closed) <select> receives focus
// in IE and (under certain conditions) Edge, as it looks bad and cannot be made to
// match the appearance of the native widget.
// See https://github.com/twbs/bootstrap/issues/19398.
color: $input-color;
background-color: $input-bg;
}
}
.form-control-plaintext {
color: $input-plaintext-color;
background-color: transparent;
}
.form-check-input {
&[disabled] ~ .form-check-label,
&:disabled ~ .form-check-label {
color: $text-muted;
}
}
@each $state, $data in $form-validation-states {
@include form-validation-state($state, map-get($data, color), map-get($data, icon));
}

View file

@ -1,16 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
// Image thumbnails
.img-thumbnail {
background-color: $thumbnail-bg;
border-color: $thumbnail-border-color;
@include box-shadow($thumbnail-box-shadow);
}
.figure-caption {
color: $figure-caption-color;
}

View file

@ -1,11 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.input-group-text {
color: $input-group-addon-color;
background-color: $input-group-addon-bg;
border-color: $input-group-addon-border-color;
}

View file

@ -1,10 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.jumbotron {
color: $jumbotron-color;
background-color: $jumbotron-bg;
}

View file

@ -1,47 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.list-group-item-action {
color: $list-group-action-color;
@include hover-focus() {
color: $list-group-action-hover-color;
background-color: $list-group-hover-bg;
}
&:active {
color: $list-group-action-active-color;
background-color: $list-group-action-active-bg;
}
}
.list-group-item {
color: $list-group-color;
background-color: $list-group-bg;
border-color: $list-group-border-color;
&.disabled,
&:disabled {
color: $list-group-disabled-color;
background-color: $list-group-disabled-bg;
}
// Include both here for `<a>`s and `<button>`s
&.active {
color: $list-group-active-color;
background-color: $list-group-active-bg;
border-color: $list-group-active-border-color;
}
}
// Contextual variants
//
// Add modifier classes to change text and background color on individual items.
// Organizationally, this must come after the `:hover` states.
@each $color, $value in $theme-colors {
@include list-group-item-variant($color, theme-color-level($color, -9), theme-color-level($color, 6));
}

View file

@ -1,41 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
&.modal-open .modal {
overflow-x: hidden;
overflow-y: auto;
}
// Actual modal
.modal-content {
background-color: $modal-content-bg;
border-color: $modal-content-border-color;
@include box-shadow($modal-content-box-shadow-xs);
}
// Modal background
.modal-backdrop {
background-color: $modal-backdrop-bg;
}
// Modal header
// Top section of the modal w/ title and dismiss
.modal-header {
border-bottom: $modal-header-border-width solid $modal-header-border-color;
}
// Footer (for actions)
.modal-footer {
border-top: $modal-footer-border-width solid $modal-footer-border-color;
}
// Scale up the modal
@include media-breakpoint-up(sm) {
.modal-content {
@include box-shadow($modal-content-box-shadow-sm-up);
}
}

View file

@ -1,42 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.nav-link {
&.disabled {
color: $nav-link-disabled-color;
}
}
.nav-tabs {
border-bottom-color: $nav-tabs-border-color;
.nav-link {
@include hover-focus() {
border-color: $nav-tabs-link-hover-border-color;
}
&.disabled {
color: $nav-link-disabled-color;
background-color: transparent;
border-color: transparent;
}
}
.nav-link.active,
.nav-item.show .nav-link {
color: $nav-tabs-link-active-color;
background-color: $nav-tabs-link-active-bg;
border-color: $nav-tabs-link-active-border-color;
}
}
.nav-pills {
.nav-link.active,
.show > .nav-link {
color: $nav-pills-link-active-color;
background-color: $nav-pills-link-active-bg;
}
}

View file

@ -1,112 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
// Button for toggling the navbar when in its collapsed state
.navbar-toggler {
background-color: transparent; // remove default button style
}
// Navbar themes
//
// Styles for switching between navbars with light or dark background.
// Dark links against a light background
.navbar-light {
.navbar-brand {
color: $navbar-light-brand-color;
@include hover-focus() {
color: $navbar-light-brand-hover-color;
}
}
.navbar-nav {
.nav-link {
color: $navbar-light-color;
@include hover-focus() {
color: $navbar-light-hover-color;
}
&.disabled {
color: $navbar-light-disabled-color;
}
}
.show > .nav-link,
.active > .nav-link,
.nav-link.show,
.nav-link.active {
color: $navbar-light-active-color;
}
}
.navbar-toggler {
color: $navbar-light-color;
border-color: $navbar-light-toggler-border-color;
}
.navbar-text {
color: $navbar-light-color;
a {
color: $navbar-light-active-color;
@include hover-focus() {
color: $navbar-light-active-color;
}
}
}
}
// White links against a dark background
.navbar-dark {
.navbar-brand {
color: $navbar-dark-brand-color;
@include hover-focus() {
color: $navbar-dark-brand-hover-color;
}
}
.navbar-nav {
.nav-link {
color: $navbar-dark-color;
@include hover-focus() {
color: $navbar-dark-hover-color;
}
&.disabled {
color: $navbar-dark-disabled-color;
}
}
.show > .nav-link,
.active > .nav-link,
.nav-link.show,
.nav-link.active {
color: $navbar-dark-active-color;
}
}
.navbar-toggler {
color: $navbar-dark-color;
border-color: $navbar-dark-toggler-border-color;
}
.navbar-text {
color: $navbar-dark-color;
a {
color: $navbar-dark-active-color;
@include hover-focus() {
color: $navbar-dark-active-color;
}
}
}
}

View file

@ -1,36 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.page-link {
color: $pagination-color;
background-color: $pagination-bg;
border-color: $pagination-border-color;
&:hover {
color: $pagination-hover-color;
background-color: $pagination-hover-bg;
border-color: $pagination-hover-border-color;
}
&:focus {
outline: $pagination-focus-outline;
box-shadow: $pagination-focus-box-shadow;
}
}
.page-item {
&.active .page-link {
color: $pagination-active-color;
background-color: $pagination-active-bg;
border-color: $pagination-active-border-color;
}
&.disabled .page-link {
color: $pagination-disabled-color;
background-color: $pagination-disabled-bg;
border-color: $pagination-disabled-border-color;
}
}

View file

@ -1,89 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.popover {
background-color: $popover-bg;
border: $popover-border-width solid $popover-border-color;
@include box-shadow($popover-box-shadow);
}
.bs-popover-top {
> .arrow {
&::before {
border-top-color: $popover-arrow-outer-color;
}
&::after {
border-top-color: $popover-arrow-color;
}
}
}
.bs-popover-right {
> .arrow {
&::before {
border-right-color: $popover-arrow-outer-color;
}
&::after {
border-right-color: $popover-arrow-color;
}
}
}
.bs-popover-bottom {
> .arrow {
&::before {
border-bottom-color: $popover-arrow-outer-color;
}
&::after {
border-bottom-color: $popover-arrow-color;
}
}
}
.bs-popover-left {
> .arrow {
&::before {
border-left-color: $popover-arrow-outer-color;
}
&::after {
border-left-color: $popover-arrow-color;
}
}
}
.bs-popover-auto {
&[x-placement^="top"] {
@extend .bs-popover-top;
}
&[x-placement^="right"] {
@extend .bs-popover-right;
}
&[x-placement^="bottom"] {
@extend .bs-popover-bottom;
}
&[x-placement^="left"] {
@extend .bs-popover-left;
}
}
// Offset the popover to account for the popover arrow
.popover-header {
color: $popover-header-color;
background-color: $popover-header-bg;
border-bottom-color: darken($popover-header-bg, 5%);
}
.popover-body {
color: $popover-body-color;
}

View file

@ -1,15 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.progress {
background-color: $progress-bg;
@include box-shadow($progress-box-shadow);
}
.progress-bar {
color: $progress-bar-color;
background-color: $progress-bar-bg;
}

View file

@ -1,28 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
& {
color: $body-color;
background-color: $body-bg; // 2
}
a {
color: $link-color;
background-color: transparent; // Remove the gray background on active links in IE 10.
@include hover() {
color: $link-hover-color;
}
}
caption {
color: $table-caption-color;
}
button:focus {
outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color;
}

View file

@ -1,14 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.spinner-border {
border-color: currentColor;
border-right-color: transparent;
}
.spinner-grow {
background-color: currentColor;
}

View file

@ -1,128 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
//
// Basic Bootstrap table
//
.table {
color: $table-color;
background-color: $table-bg; // Reset for nesting within parents with `background-color`.
th,
td {
border-top-color: $table-border-color;
}
thead th {
border-bottom-color: $table-border-color;
}
tbody + tbody {
border-top-color: $table-border-color;
}
}
// Border versions
//
// Add or remove borders all around the table and between all the columns.
.table-bordered {
border-color: $table-border-color;
th,
td {
border-color: $table-border-color;
}
}
// Zebra-striping
//
// Default zebra-stripe styles (alternating gray and transparent backgrounds)
.table-striped {
tbody tr:nth-of-type(#{$table-striped-order}) {
background-color: $table-accent-bg;
}
}
// Hover effect
//
// Placed here since it has to come after the potential zebra striping
.table-hover {
tbody tr {
@include hover() {
color: $table-hover-color;
background-color: $table-hover-bg;
}
}
}
// Table backgrounds
//
// Exact selectors below required to override `.table-striped` and prevent
// inheritance to nested tables.
@each $color, $value in $theme-colors {
@include table-row-variant($color, theme-color-level($color, $table-bg-level), theme-color-level($color, $table-border-level));
}
@include table-row-variant(active, $table-active-bg);
// Dark styles
//
// Same table markup, but inverted color scheme: dark background and light text.
// stylelint-disable-next-line no-duplicate-selectors
.table {
.thead-dark {
th {
color: $table-dark-color;
background-color: $table-dark-bg;
border-color: $table-dark-border-color;
}
}
.thead-light {
th {
color: $table-head-color;
background-color: $table-head-bg;
border-color: $table-border-color;
}
}
}
.table-dark {
color: $table-dark-color;
background-color: $table-dark-bg;
th,
td,
thead th {
border-color: $table-dark-border-color;
}
&.table-striped {
tbody tr:nth-of-type(#{$table-striped-order}) {
background-color: $table-dark-accent-bg;
}
}
&.table-hover {
tbody tr {
@include hover() {
color: $table-dark-hover-color;
background-color: $table-dark-hover-bg;
}
}
}
}

View file

@ -1,17 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.toast {
color: $toast-color;
background-color: $toast-background-color;
border-color: $toast-border-color;
}
.toast-header {
color: $toast-header-color;
background-color: $toast-header-background-color;
border-bottom-color: $toast-header-border-color;
}

View file

@ -1,61 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.bs-tooltip-top {
.arrow {
&::before {
border-top-color: $tooltip-arrow-color;
}
}
}
.bs-tooltip-right {
.arrow {
&::before {
border-right-color: $tooltip-arrow-color;
}
}
}
.bs-tooltip-bottom {
.arrow {
&::before {
border-bottom-color: $tooltip-arrow-color;
}
}
}
.bs-tooltip-left {
.arrow {
&::before {
border-left-color: $tooltip-arrow-color;
}
}
}
.bs-tooltip-auto {
&[x-placement^="top"] {
@extend .bs-tooltip-top;
}
&[x-placement^="right"] {
@extend .bs-tooltip-right;
}
&[x-placement^="bottom"] {
@extend .bs-tooltip-bottom;
}
&[x-placement^="left"] {
@extend .bs-tooltip-left;
}
}
// Wrapper for the tooltip content
.tooltip-inner {
color: $tooltip-color;
background-color: $tooltip-bg;
}

View file

@ -1,34 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
// stylelint-disable declaration-no-important, selector-list-comma-newline-after
//
// Headings
//
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
color: $headings-color;
}
//
// Horizontal rules
//
hr {
border-top-color: $hr-border-color;
}
mark,
.mark {
background-color: $mark-bg;
}
.blockquote-footer {
color: $blockquote-small-color;
}

View file

@ -1,38 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/mixins";
@import "reboot";
@import "type";
@import "images";
@import "code";
@import "tables";
@import "forms";
@import "buttons";
@import "dropdown";
@import "input-group";
@import "nav";
@import "navbar";
@import "card";
@import "breadcrumb";
@import "pagination";
@import "badge";
@import "jumbotron";
@import "alert";
@import "progress";
@import "list-group";
@import "close";
@import "toasts";
@import "modal";
@import "tooltip";
@import "popover";
@import "carousel";
@import "spinners";
@import "utilities/background";
@import "utilities/borders";
@import "utilities/text";

View file

@ -1,21 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
// stylelint-disable declaration-no-important
@each $color, $value in $theme-colors {
@include bg-variant(".bg-#{$color}", $value, true);
}
@if $enable-gradients {
@each $color, $value in $theme-colors {
@include bg-gradient-variant(".bg-gradient-#{$color}", $value, true);
}
}
.bg-white {
background-color: $white !important;
}

View file

@ -1,41 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
// stylelint-disable property-blacklist, declaration-no-important
//
// Border
//
.border {
border-color: $border-color !important;
}
.border-top {
border-top-color: $border-color !important;
}
.border-right {
border-right-color: $border-color !important;
}
.border-bottom {
border-bottom-color: $border-color !important;
}
.border-left {
border-left-color: $border-color !important;
}
@each $color, $value in $theme-colors {
.border-#{$color} {
border-color: $value !important;
}
}
.border-white {
border-color: $white !important;
}

View file

@ -1,31 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
// Contextual colors
.text-white {
color: $white !important;
}
@each $color, $value in $theme-colors {
@include text-emphasis-variant(".text-#{$color}", $value, true);
}
.text-body {
color: $body-color !important;
}
.text-muted {
color: $text-muted !important;
}
.text-black-50 {
color: rgba($black, .5) !important;
}
.text-white-50 {
color: rgba($white, .5) !important;
}

View file

@ -4,8 +4,23 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
@import "variables.dark";
body.dark {
@import "bootstrap-color-theme/include";
@import "variables.dark";
/* redefine theme color variables */
@each $color, $value in $theme-colors {
--#{$prefix}#{$color}: #{$value};
}
$theme-colors-rgb: map-loop($theme-colors, to-rgb, "$value");
@each $color, $value in $theme-colors-rgb {
--#{$prefix}#{$color}-rgb: #{$value};
}
--#{$prefix}body-color: #{$body-color};
--#{$prefix}body-bg: #{$body-bg};
@import "~bootstrap";
}

View file

@ -6,7 +6,7 @@
@import "variables.module";
@import "variables.light";
@import "bootstrap-vendor/bootstrap";
@import "~bootstrap/scss/bootstrap";
@import '~react-bootstrap-typeahead/css/Typeahead';
@import "~@fontsource/source-sans-pro/index.css";
@import "~twemoji-colr-font/twemoji";

View file

@ -52,15 +52,15 @@ export const CopyableField: React.FC<CopyableFieldProps> = ({ content, shareOrig
return (
<InputGroup className='my-3'>
<FormControl readOnly={true} className={'text-center'} value={content} />
<InputGroup.Append>
<InputGroup.Text>
<CopyToClipboardButton variant={'outline-secondary'} content={content} />
</InputGroup.Append>
</InputGroup.Text>
<ShowIf condition={sharingSupported}>
<InputGroup.Append>
<Button variant='outline-secondary' title={'Share'} onClick={doShareAction}>
<InputGroup.Text>
<Button variant='secondary' title={'Share'} onClick={doShareAction}>
<ForkAwesomeIcon icon='share-alt' />
</Button>
</InputGroup.Append>
</InputGroup.Text>
</ShowIf>
</InputGroup>
)

View file

@ -8,7 +8,7 @@ exports[`create non existing note hint shows success message when the note has b
role="alert"
>
<i
class="fa fa-check-circle mr-2 "
class="fa fa-check-circle me-2 "
/>
noteLoadingBoundary.createNote.success
</div>
@ -23,7 +23,7 @@ exports[`create non existing note hint renders a waiting message when button is
role="alert"
>
<i
class="fa fa-spinner fa-spin mr-2 "
class="fa fa-spinner fa-spin me-2 "
/>
noteLoadingBoundary.createNote.creating
</div>
@ -63,7 +63,7 @@ exports[`create non existing note hint shows an error message if note couldn't b
role="alert"
>
<i
class="fa fa-exclamation-triangle mr-1 "
class="fa fa-exclamation-triangle me-1 "
/>
noteLoadingBoundary.createNote.error
</div>

View file

@ -48,21 +48,21 @@ export const CreateNonExistingNoteHint: React.FC<CreateNonExistingNoteHintProps>
} else if (returnState.value) {
return (
<Alert variant={'info'} {...testId('noteCreated')} className={'mt-5'}>
<ForkAwesomeIcon icon={'check-circle'} className={'mr-2'} />
<ForkAwesomeIcon icon={'check-circle'} className={'me-2'} />
<Trans i18nKey={'noteLoadingBoundary.createNote.success'} />
</Alert>
)
} else if (returnState.loading) {
return (
<Alert variant={'info'} {...testId('loadingMessage')} className={'mt-5'}>
<ForkAwesomeIcon icon={'spinner'} className={'fa-spin mr-2'} />
<ForkAwesomeIcon icon={'spinner'} className={'fa-spin me-2'} />
<Trans i18nKey={'noteLoadingBoundary.createNote.creating'} />
</Alert>
)
} else if (returnState.error !== undefined) {
return (
<Alert variant={'danger'} {...testId('failedMessage')} className={'mt-5'}>
<ForkAwesomeIcon icon={'exclamation-triangle'} className={'mr-1'} />
<ForkAwesomeIcon icon={'exclamation-triangle'} className={'me-1'} />
<Trans i18nKey={'noteLoadingBoundary.createNote.error'} />
</Alert>
)
@ -81,7 +81,7 @@ export const CreateNonExistingNoteHint: React.FC<CreateNonExistingNoteHintProps>
onClick={onClickHandler}
{...testId('createNoteButton')}>
<ShowIf condition={returnState.loading}>
<ForkAwesomeIcon icon={'spinner'} className={'fa-spin mr-2'} />
<ForkAwesomeIcon icon={'spinner'} className={'fa-spin me-2'} />
</ShowIf>
<Trans i18nKey={'noteLoadingBoundary.createNote.create'} />
</Button>

View file

@ -14,7 +14,7 @@ exports[`UserAvatar adds additionalClasses props to wrapping span 1`] = `
width="20"
/>
<span
class="ml-2 mr-1 user-line-name"
class="ms-2 me-1 user-line-name"
>
Boaty McBoatFace
</span>
@ -53,7 +53,7 @@ exports[`UserAvatar renders the user avatar correctly 1`] = `
width="20"
/>
<span
class="ml-2 mr-1 user-line-name"
class="ms-2 me-1 user-line-name"
>
Boaty McBoatFace
</span>
@ -75,7 +75,7 @@ exports[`UserAvatar renders the user avatar in size lg 1`] = `
width="30"
/>
<span
class="ml-2 mr-1 user-line-name"
class="ms-2 me-1 user-line-name"
>
Boaty McBoatFace
</span>
@ -97,7 +97,7 @@ exports[`UserAvatar renders the user avatar in size sm 1`] = `
width="16"
/>
<span
class="ml-2 mr-1 user-line-name"
class="ms-2 me-1 user-line-name"
>
Boaty McBoatFace
</span>

View file

@ -70,7 +70,7 @@ export const UserAvatar: React.FC<UserAvatarProps> = ({ user, size, additionalCl
/>
<ShowIf condition={showName}>
<OverlayTrigger overlay={tooltip}>
<span className={`ml-2 mr-1 ${styles['user-line-name']}`}>{user.displayName}</span>
<span className={`ms-2 me-1 ${styles['user-line-name']}`}>{user.displayName}</span>
</OverlayTrigger>
</ShowIf>
</span>

View file

@ -29,7 +29,7 @@ export const DocumentInfobar: React.FC = () => {
<NoteInfoLineUpdated />
<hr />
</div>
<span className={'ml-auto'}>
<span className={'ms-auto'}>
{noteDetails.viewCount} <Trans i18nKey={'views.readOnly.viewCount'} />
<ShowIf condition={true}>
<InternalLink

View file

@ -39,8 +39,8 @@ export const AppBar: React.FC<AppBarProps> = ({ mode }) => {
const noteFrontmatter = useApplicationState((state) => state.noteDetails.frontmatter)
return (
<Navbar bg={'light'}>
<Nav className='mr-auto d-flex align-items-center'>
<Navbar expand={true} className={'bg-light px-3'}>
<Nav className='me-auto d-flex align-items-center'>
<NavbarBranding />
<ShowIf condition={mode === AppBarMode.EDITOR}>
<EditorViewMode />
@ -57,7 +57,7 @@ export const AppBar: React.FC<AppBarProps> = ({ mode }) => {
<HelpButton />
</ShowIf>
</Nav>
<Nav className='d-flex align-items-center text-secondary'>
<Nav className='d-flex align-items-center text-secondary justify-content-end'>
<NewNoteButton />
<ShowIf condition={!userExists}>
<SignInButton size={'sm'} />

View file

@ -4,42 +4,38 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React from 'react'
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
import React, { useCallback } from 'react'
import { Button, ButtonGroup } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { useIsDarkModeActivated } from '../../../hooks/common/use-is-dark-mode-activated'
import { setDarkMode } from '../../../redux/dark-mode/methods'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
enum DarkModeState {
DARK,
LIGHT
}
/**
* Renders a button group to activate / deactivate the dark mode.
*/
const DarkModeButton: React.FC = () => {
const { t } = useTranslation()
const darkModeEnabled = useIsDarkModeActivated() ? DarkModeState.DARK : DarkModeState.LIGHT
const darkModeEnabled = useIsDarkModeActivated()
const enable = useCallback(() => setDarkMode(true), [])
const disable = useCallback(() => setDarkMode(false), [])
return (
<ToggleButtonGroup type='radio' name='dark-mode' value={darkModeEnabled} className='ml-2'>
<ToggleButton
value={DarkModeState.DARK}
variant='outline-secondary'
title={t('editor.darkMode.switchToDark')}
onChange={() => setDarkMode(true)}>
<ButtonGroup className='ms-2'>
<Button
onClick={enable}
variant={darkModeEnabled ? 'secondary' : 'outline-secondary'}
title={t('editor.darkMode.switchToDark')}>
<ForkAwesomeIcon icon='moon' />
</ToggleButton>
<ToggleButton
value={DarkModeState.LIGHT}
variant='outline-secondary'
title={t('editor.darkMode.switchToLight')}
onChange={() => setDarkMode(false)}>
</Button>
<Button
onClick={disable}
variant={darkModeEnabled ? 'outline-secondary' : 'secondary'}
title={t('editor.darkMode.switchToLight')}>
<ForkAwesomeIcon icon='sun-o' />
</ToggleButton>
</ToggleButtonGroup>
</Button>
</ButtonGroup>
)
}

View file

@ -5,7 +5,7 @@
*/
import React from 'react'
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
import { Button, ButtonGroup } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { setEditorMode } from '../../../redux/editor/methods'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
@ -27,34 +27,28 @@ export const EditorViewMode: React.FC = () => {
const editorMode = useApplicationState((state) => state.editorConfig.editorMode)
return (
<ToggleButtonGroup
type='radio'
name='options'
value={editorMode}
onChange={(value: EditorMode) => {
setEditorMode(value)
}}>
<ToggleButton
<ButtonGroup>
<Button
{...cypressId('view-mode-editor')}
value={EditorMode.EDITOR}
variant='outline-secondary'
onClick={() => setEditorMode(EditorMode.EDITOR)}
variant={editorMode === EditorMode.EDITOR ? 'secondary' : 'outline-secondary'}
title={t('editor.viewMode.edit')}>
<ForkAwesomeIcon icon='pencil' />
</ToggleButton>
<ToggleButton
</Button>
<Button
{...cypressId('view-mode-both')}
value={EditorMode.BOTH}
variant='outline-secondary'
onClick={() => setEditorMode(EditorMode.BOTH)}
variant={editorMode === EditorMode.BOTH ? 'secondary' : 'outline-secondary'}
title={t('editor.viewMode.both')}>
<ForkAwesomeIcon icon='columns' />
</ToggleButton>
<ToggleButton
</Button>
<Button
{...cypressId('view-mode-preview')}
value={EditorMode.PREVIEW}
variant='outline-secondary'
onClick={() => setEditorMode(EditorMode.PREVIEW)}
variant={editorMode === EditorMode.PREVIEW ? 'secondary' : 'outline-secondary'}
title={t('editor.viewMode.view')}>
<ForkAwesomeIcon icon='eye' />
</ToggleButton>
</ToggleButtonGroup>
</Button>
</ButtonGroup>
)
}

View file

@ -24,7 +24,7 @@ export const HelpButton: React.FC = () => {
<Button
{...cypressId('editor-help-button')}
title={t('editor.documentBar.help')}
className='ml-2 text-secondary'
className='ms-2 text-secondary'
size='sm'
variant='outline-light'
onClick={showModal}>

View file

@ -23,7 +23,7 @@ export const ReadOnlyModeButton: React.FC = () => {
<a target='_blank'>
<Button
title={t('editor.documentBar.readOnlyMode')}
className='ml-2 text-secondary'
className='ms-2 text-secondary'
size='sm'
variant='outline-light'>
<ForkAwesomeIcon icon='file-text-o' />

View file

@ -23,7 +23,7 @@ export const SlideModeButton: React.FC = () => {
<a target='_blank'>
<Button
title={t('editor.documentBar.slideMode')}
className='ml-2 text-secondary'
className='ms-2 text-secondary'
size='sm'
variant='outline-light'>
<ForkAwesomeIcon icon='television' />

View file

@ -12,28 +12,12 @@
:global(.btn) {
svg g {
@import "../../../../../global-styles/variables.light";
fill: $secondary;
fill: var(--bs-secondary);
}
:global(&.active), &:hover {
svg g {
@import "../../../../../global-styles/variables.light";
fill: $light;
}
}
:global(body.dark) & {
svg g {
@import "../../../../../global-styles/variables.dark";
fill: $secondary;
}
:global(&.active), &:hover {
svg g {
@import "../../../../../global-styles/variables.dark";
fill: $light;
}
fill: var(--bs-light);
}
}
}

View file

@ -4,8 +4,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React from 'react'
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
import React, { useCallback } from 'react'
import { Button, ButtonGroup } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { setEditorSyncScroll } from '../../../../redux/editor/methods'
import DisabledScroll from './disabledScroll.svg'
@ -13,42 +13,30 @@ import EnabledScroll from './enabledScroll.svg'
import './sync-scroll-buttons.module.scss'
import { useApplicationState } from '../../../../hooks/common/use-application-state'
enum SyncScrollState {
SYNCED,
UNSYNCED
}
/**
* Renders a button group with two states for the sync scroll buttons.
* This makes it possible to activate or deactivate sync scrolling.
*/
export const SyncScrollButtons: React.FC = () => {
const syncScrollEnabled = useApplicationState((state) => state.editorConfig.syncScroll)
? SyncScrollState.SYNCED
: SyncScrollState.UNSYNCED
const { t } = useTranslation()
const enable = useCallback(() => setEditorSyncScroll(true), [])
const disable = useCallback(() => setEditorSyncScroll(false), [])
return (
<ToggleButtonGroup
type='radio'
defaultValue={[]}
name='sync-scroll'
className={'ml-2 sync-scroll-buttons'}
value={syncScrollEnabled}>
<ToggleButton
variant={'outline-secondary'}
title={t('editor.appBar.syncScroll.enable')}
onChange={() => setEditorSyncScroll(true)}
value={SyncScrollState.SYNCED}>
<ButtonGroup className='ms-2 ms-2 sync-scroll-buttons'>
<Button
onClick={enable}
variant={syncScrollEnabled ? 'secondary' : 'outline-secondary'}
title={t('editor.appBar.syncScroll.enable')}>
<EnabledScroll />
</ToggleButton>
<ToggleButton
variant={'outline-secondary'}
title={t('editor.appBar.syncScroll.disable')}
onChange={() => setEditorSyncScroll(false)}
value={SyncScrollState.UNSYNCED}>
</Button>
<Button
onClick={disable}
variant={syncScrollEnabled ? 'outline-secondary' : 'secondary'}
title={t('editor.appBar.syncScroll.disable')}>
<DisabledScroll />
</ToggleButton>
</ToggleButtonGroup>
</Button>
</ButtonGroup>
)
}

View file

@ -4,7 +4,7 @@ exports[`AliasesAddForm renders the input form 1`] = `
<div>
<form>
<div
class="mr-1 mb-1 input-group has-validation"
class="me-1 mb-1 input-group has-validation"
>
<input
class="form-control"
@ -14,7 +14,7 @@ exports[`AliasesAddForm renders the input form 1`] = `
value=""
/>
<button
class="text-secondary ml-2 btn btn-light"
class="text-secondary ms-2 btn btn-light"
data-testid="addAliasButton"
disabled=""
title="editor.modal.aliases.addAlias"

View file

@ -8,7 +8,7 @@ exports[`AliasesListEntry renders an AliasesListEntry that is not primary 1`] =
test-non-primary
<div>
<button
class="mr-2 btn btn-light"
class="me-2 btn btn-light"
data-testid="aliasButtonMakePrimary"
title="editor.modal.aliases.makePrimary"
type="button"
@ -40,7 +40,7 @@ exports[`AliasesListEntry renders an AliasesListEntry that is primary 1`] = `
test-primary
<div>
<button
class="mr-2 text-warning btn btn-light"
class="me-2 text-warning btn btn-light"
data-testid="aliasIsPrimary"
disabled=""
title="editor.modal.aliases.isPrimary"

View file

@ -47,7 +47,7 @@ export const AliasesAddForm: React.FC = () => {
return (
<form onSubmit={onAddAlias}>
<InputGroup className={'mr-1 mb-1'} hasValidation={true}>
<InputGroup className={'me-1 mb-1'} hasValidation={true}>
<Form.Control
value={newAlias}
placeholder={t('editor.modal.aliases.addAlias')}
@ -59,7 +59,7 @@ export const AliasesAddForm: React.FC = () => {
<Button
type={'submit'}
variant='light'
className={'text-secondary ml-2'}
className={'text-secondary ms-2'}
disabled={!newAliasValid || newAlias === ''}
title={t('editor.modal.aliases.addAlias')}
{...testId('addAliasButton')}>

View file

@ -45,7 +45,7 @@ export const AliasesListEntry: React.FC<AliasesListEntryProps> = ({ alias }) =>
<div>
<ShowIf condition={alias.primaryAlias}>
<Button
className={'mr-2 text-warning'}
className={'me-2 text-warning'}
variant='light'
disabled={true}
title={t('editor.modal.aliases.isPrimary')}
@ -55,7 +55,7 @@ export const AliasesListEntry: React.FC<AliasesListEntryProps> = ({ alias }) =>
</ShowIf>
<ShowIf condition={!alias.primaryAlias}>
<Button
className={'mr-2'}
className={'me-2'}
variant='light'
title={t('editor.modal.aliases.makePrimary')}
onClick={onMakePrimaryClick}

View file

@ -26,7 +26,7 @@ export const UnitalicBoldContent: React.FC<PropsWithChildren<UnitalicBoldContent
...props
}) => {
return (
<strong className={'font-style-normal mr-1'} {...cypressId(props)}>
<strong className={'font-style-normal me-1'} {...cypressId(props)}>
{text}
{children}
</strong>

View file

@ -33,9 +33,9 @@ export const PermissionAddEntryField: React.FC<PermissionAddEntryFieldProps> = (
return (
<li className={'list-group-item'}>
<InputGroup className={'mr-1 mb-1'}>
<InputGroup className={'me-1 mb-1'}>
<FormControl value={newEntryIdentifier} placeholder={t(i18nKey)} onChange={onChange} />
<Button variant='light' className={'text-secondary ml-2'} title={t(i18nKey)} onClick={onSubmit}>
<Button variant='light' className={'text-secondary ms-2'} title={t(i18nKey)} onClick={onSubmit}>
<ForkAwesomeIcon icon={'plus'} />
</Button>
</InputGroup>

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React, { useMemo } from 'react'
import { Button, ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
import { Button, ToggleButtonGroup } from 'react-bootstrap'
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
import { AccessLevel } from './types'
import { useTranslation } from 'react-i18next'
@ -68,26 +68,22 @@ export const PermissionEntryButtons: React.FC<PermissionEntryButtonsProps> = ({
return (
<div>
<Button variant='light' className={'text-danger mr-2'} title={t(i18nKeys.remove, { name })} onClick={onRemove}>
<Button variant='light' className={'text-danger me-2'} title={t(i18nKeys.remove, { name })} onClick={onRemove}>
<ForkAwesomeIcon icon={'times'} />
</Button>
<ToggleButtonGroup type='radio' name='edit-mode' value={currentSetting}>
<ToggleButton
<Button
title={t(i18nKeys.setReadOnly, { name })}
variant={'light'}
className={'text-secondary'}
value={AccessLevel.READ_ONLY}
variant={currentSetting === AccessLevel.READ_ONLY ? 'secondary' : 'outline-secondary'}
onClick={onSetReadOnly}>
<ForkAwesomeIcon icon='eye' />
</ToggleButton>
<ToggleButton
</Button>
<Button
title={t(i18nKeys.setWriteable, { name })}
variant={'light'}
className={'text-secondary'}
value={AccessLevel.WRITEABLE}
variant={currentSetting === AccessLevel.WRITEABLE ? 'secondary' : 'outline-secondary'}
onClick={onSetWriteable}>
<ForkAwesomeIcon icon='pencil' />
</ToggleButton>
</Button>
</ToggleButtonGroup>
</div>
)

View file

@ -6,7 +6,7 @@
import React, { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { AccessLevel, SpecialGroup } from './types'
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
import { Button, ToggleButtonGroup } from 'react-bootstrap'
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
import { removeGroupPermission, setGroupPermission } from '../../../../api/permissions'
import { useApplicationState } from '../../../../hooks/common/use-application-state'
@ -66,31 +66,25 @@ export const PermissionEntrySpecialGroup: React.FC<PermissionEntrySpecialGroupPr
<li className={'list-group-item d-flex flex-row justify-content-between align-items-center'}>
<span>{name}</span>
<div>
<ToggleButtonGroup type='radio' name='edit-mode' value={level}>
<ToggleButton
<ToggleButtonGroup type='radio' name='edit-mode'>
<Button
title={t('editor.modal.permissions.denyGroup', { name })}
variant={'light'}
className={'text-secondary'}
value={AccessLevel.NONE}
variant={level === AccessLevel.NONE ? 'secondary' : 'outline-secondary'}
onClick={onSetEntryDenied}>
<ForkAwesomeIcon icon={'ban'} />
</ToggleButton>
<ToggleButton
</Button>
<Button
title={t('editor.modal.permissions.viewOnlyGroup', { name })}
variant={'light'}
className={'text-secondary'}
value={AccessLevel.READ_ONLY}
variant={level === AccessLevel.READ_ONLY ? 'secondary' : 'outline-secondary'}
onClick={onSetEntryReadOnly}>
<ForkAwesomeIcon icon={'eye'} />
</ToggleButton>
<ToggleButton
</Button>
<Button
title={t('editor.modal.permissions.editGroup', { name })}
variant={'light'}
className={'text-secondary'}
value={AccessLevel.WRITEABLE}
onClick={onSetEntryWriteable}>
variant={level === AccessLevel.WRITEABLE ? 'secondary' : 'outline-secondary'}
onClick={() => onSetEntryWriteable}>
<ForkAwesomeIcon icon={'pencil'} />
</ToggleButton>
</Button>
</ToggleButtonGroup>
</div>
</li>

View file

@ -33,7 +33,7 @@ export const PermissionOwnerChange: React.FC<PermissionOwnerChangeProps> = ({ on
}, [ownerFieldValue])
return (
<InputGroup className={'mr-1 mb-1'}>
<InputGroup className={'me-1 mb-1'}>
<FormControl
value={ownerFieldValue}
placeholder={t('editor.modal.permissions.ownerChange.placeholder')}
@ -43,7 +43,7 @@ export const PermissionOwnerChange: React.FC<PermissionOwnerChangeProps> = ({ on
variant='light'
title={t('common.save')}
onClick={onClickConfirm}
className={'ml-2'}
className={'ms-2'}
disabled={confirmButtonDisabled}>
<ForkAwesomeIcon icon={'check'} />
</Button>

View file

@ -24,7 +24,7 @@ export const StatusBar: React.FC = () => {
<SelectedCharacters />
<SelectedLines />
</div>
<div className='ml-auto'>
<div className='ms-auto'>
<NumberOfLinesInDocumentInfo />
<SeparatorDash />
<RemainingCharactersInfo />

View file

@ -6,12 +6,9 @@
.table-picker-container {
@import "../../../../../../global-styles/variables.light";
z-index: 1111;
.table-cell {
border: 1px solid $gray-700;
margin: 1px;
border-radius: 2px;
}

View file

@ -85,10 +85,10 @@ export const TableSizePickerPopover: React.FC<TableSizePickerPopoverProps> = ({
id={'table-picker'}
{...cypressId('table-size-picker-popover')}
className={`${styles['table-picker-container']} bg-light`}>
<Popover.Title>
<Popover.Header>
<TableSizeText tableSize={tableSize} />
</Popover.Title>
<Popover.Content>
</Popover.Header>
<Popover.Body>
<div className={styles['table-container']} role='grid'>
{tableContainer}
</div>
@ -99,7 +99,7 @@ export const TableSizePickerPopover: React.FC<TableSizePickerPopoverProps> = ({
<Trans i18nKey={'editor.editorToolbar.table.customSize'} />
</Button>
</div>
</Popover.Content>
</Popover.Body>
</Popover>
)
}

View file

@ -58,34 +58,27 @@
}
@mixin colors {
color: $dark;
color: black;
&.sidebar-button-primary {
background: $primary;
color: $white;
color: var(--bs-light);
background: var(--bs-primary);
&:hover {
color: $primary;
background: $entry-hover-bg;
color: var(--bs-primary);
background: var(--bs-light);
}
}
&:hover {
background: $entry-hover-bg;
color: $dark;
color: var(--bs-light);
background: var(--bs-primary);
}
}
@import "../../../../../global-styles/variables.light";
$entry-hover-bg: darken($body-bg, 10%);
$entry-hover-bg: darken(black, 10%);
@include colors;
:global(body.dark) & {
@import "../../../../../global-styles/variables.dark";
$entry-hover-bg: darken($body-bg, 10%);
@include colors;
}
}

View file

@ -5,17 +5,13 @@
*/
import type { PropsWithChildren } from 'react'
import React, { useMemo } from 'react'
import React from 'react'
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
import type { IconName } from '../../../common/fork-awesome/types'
import { ShowIf } from '../../../common/show-if/show-if'
import type { SidebarEntryProps } from '../types'
import styles from './sidebar-button.module.scss'
export interface SidebarButton extends SidebarEntryProps {
variant?: 'primary'
}
/**
* A button that should be rendered in the sidebar.
*
@ -28,24 +24,19 @@ export interface SidebarButton extends SidebarEntryProps {
* @param disabled If the button should be disabled
* @param props Other button props
*/
export const SidebarButton: React.FC<PropsWithChildren<SidebarButton>> = ({
export const SidebarButton: React.FC<PropsWithChildren<SidebarEntryProps>> = ({
children,
icon,
className,
buttonRef,
hide,
variant,
disabled,
...props
}) => {
const variantClass = useMemo(() => {
return variant !== undefined ? styles['sidebar-button-' + variant] : ''
}, [variant])
return (
<button
ref={buttonRef}
className={`${styles['sidebar-button']} ${variantClass} ${hide ? styles['hide'] : ''} ${className ?? ''}`}
className={`${styles['sidebar-button']} ${hide ? styles['hide'] : ''} ${className ?? ''}`}
disabled={disabled}
{...props}>
<ShowIf condition={!!icon}>

View file

@ -18,17 +18,8 @@
overflow-y: auto;
}
@import "../../../../../global-styles/variables.light";
& > div {
background: $body-bg;
background: var(--bs-body-bg);
box-shadow: inset 0 7px 7px -6px #bbbbbb;
}
:global(body.dark) & {
@import "../../../../../global-styles/variables.dark";
& > div {
background: $body-bg;
box-shadow: inset 0 7px 7px -6px #1d1d1d;
}
}
}

View file

@ -21,20 +21,13 @@
top: 0;
left: 0;
transition: left 0.3s;
box-shadow: 0 0 0px rgba(0, 0, 0, 0.15);
box-shadow: 0 0 0 rgba(0, 0, 0, 0.15);
&:hover, &.show {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
left: (-$menu-width + $height);
}
:global(body.dark) & {
@import "../../../../../global-styles/variables.dark";
background: $body-bg;
}
@import "../../../../../global-styles/variables.light";
background: $body-bg;
background: var(--bs-light);
}
}

View file

@ -4,38 +4,21 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
.online-entry {
@import "../../../../../global-styles/variables.light";
@mixin text-stroke($shadow-color) {
text-shadow: 0px 0px 1px $shadow-color,
1px 0px 1px $shadow-color,
0px 1px 1px $shadow-color,
-1px 0px 1px $shadow-color,
0px -1px 1px $shadow-color,
1px 1px 1px $shadow-color,
-1px -1px 1px $shadow-color,
-1px 1px 1px $shadow-color,
1px -1px 1px $shadow-color;
}
&:hover {
:global(.sidebar-button-icon):after {
color: $primary;
$shadow-color: #ffffff;
@include text-stroke(#ffffff);
color: inherit;
}
}
--users-online: '0';
:global(.sidebar-button-icon):after {
@include text-stroke($primary);
content: var(--users-online);
position: absolute;
right: 5px;
bottom: 3px;
font-size: 0.9rem;
color: #ffffff;
color: var(--bg-primary);
line-height: 1;
}
}

View file

@ -47,7 +47,7 @@ export const UsersOnlineSidebarMenu: React.FC<SpecificSidebarMenuProps> = ({
if (entries.length === 0) {
return (
<SidebarButton>
<span className={'ml-3'}>
<span className={'ms-3'}>
<Trans i18nKey={'editor.onlineStatus.noUsers'}></Trans>
</span>
</SidebarButton>
@ -70,8 +70,7 @@ export const UsersOnlineSidebarMenu: React.FC<SpecificSidebarMenuProps> = ({
buttonRef={buttonRef}
onClick={onClickHandler}
icon={expand ? 'arrow-left' : 'users'}
className={`${styles['online-entry']} ${className ?? ''}`}
variant={'primary'}>
className={`${styles['online-entry']} ${className ?? ''}`}>
<Trans i18nKey={'editor.onlineStatus.online'} />
</SidebarButton>
<SidebarMenu expand={expand}>{onlineUserElements}</SidebarMenu>

View file

@ -48,7 +48,7 @@ export const HistoryCard: React.FC<HistoryEntryProps & HistoryEventHandlers> = (
const tags = useMemo(
() =>
entry.tags.map((tag) => (
<Badge variant={'dark'} className={'mr-1 mb-1'} key={tag}>
<Badge className={'bg-dark me-1 mb-1'} key={tag}>
{tag}
</Badge>
)),

View file

@ -5,7 +5,7 @@
*/
import React, { Fragment, useCallback, useMemo, useState } from 'react'
import { Alert, Row } from 'react-bootstrap'
import { Alert, Col, Row } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { PagerPagination } from '../../common/pagination/pager-pagination'
import { HistoryCardList } from '../history-card/history-card-list'
@ -116,12 +116,14 @@ export const HistoryContent: React.FC = () => {
return (
<Fragment>
{historyContent}
<Row className='justify-content-center'>
<PagerPagination
numberOfPageButtonsToShowAfterAndBeforeCurrent={2}
lastPageIndex={lastPageIndex}
onPageChange={setPageIndex}
/>
<Row>
<Col className={'justify-content-center d-flex'}>
<PagerPagination
numberOfPageButtonsToShowAfterAndBeforeCurrent={2}
lastPageIndex={lastPageIndex}
onPageChange={setPageIndex}
/>
</Col>
</Row>
</Fragment>
)

View file

@ -54,13 +54,13 @@ export const HistoryTableRow: React.FC<HistoryEntryProps & HistoryEventHandlers>
<td>{formatHistoryDate(entry.lastVisitedAt)}</td>
<td>
{entry.tags.map((tag) => (
<Badge variant={'light'} className={'mr-1 mb-1'} key={tag}>
<Badge className={'bg-light me-1 mb-1'} key={tag}>
{tag}
</Badge>
))}
</td>
<td>
<PinButton isDark={true} isPinned={entry.pinStatus} onPinClick={onPinEntry} className={'mb-1 mr-1'} />
<PinButton isDark={true} isPinned={entry.pinStatus} onPinClick={onPinEntry} className={'mb-1 me-1'} />
<EntryMenu
id={entry.identifier}
title={entryTitle}

View file

@ -5,7 +5,7 @@
*/
import React, { useCallback } from 'react'
import { Button, Form, InputGroup } from 'react-bootstrap'
import { Button, Col } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { ShowIf } from '../../common/show-if/show-if'
@ -62,41 +62,41 @@ export const HistoryToolbar: React.FC = () => {
}, [userExists, historyEntries, showErrorNotification, safeRefreshHistoryState])
return (
<Form inline={true}>
<InputGroup className={'mr-1 mb-1'}>
<Col className={'d-flex flex-row'}>
<div className={'me-1 mb-1'}>
<TagSelectionInput />
</InputGroup>
<InputGroup className={'mr-1 mb-1'}>
</div>
<div className={'me-1 mb-1'}>
<KeywordSearchInput />
</InputGroup>
<InputGroup className={'mr-1 mb-1'}>
</div>
<div className={'me-1 mb-1'}>
<SortByTitleButton />
</InputGroup>
<InputGroup className={'mr-1 mb-1'}>
</div>
<div className={'me-1 mb-1'}>
<SortByLastVisitedButton />
</InputGroup>
<InputGroup className={'mr-1 mb-1'}>
</div>
<div className={'me-1 mb-1'}>
<ExportHistoryButton />
</InputGroup>
<InputGroup className={'mr-1 mb-1'}>
</div>
<div className={'me-1 mb-1'}>
<ImportHistoryButton />
</InputGroup>
<InputGroup className={'mr-1 mb-1'}>
</div>
<div className={'me-1 mb-1'}>
<ClearHistoryButton />
</InputGroup>
<InputGroup className={'mr-1 mb-1'}>
</div>
<div className={'me-1 mb-1'}>
<HistoryRefreshButton />
</InputGroup>
</div>
<ShowIf condition={userExists}>
<InputGroup className={'mr-1 mb-1'}>
<div className={'me-1 mb-1'}>
<Button variant={'light'} title={t('landing.history.toolbar.uploadAll')} onClick={onUploadAllToRemote}>
<ForkAwesomeIcon icon='cloud-upload' />
</Button>
</InputGroup>
</div>
</ShowIf>
<InputGroup className={'mr-1 mb-1'}>
<div className={'me-1 mb-1'}>
<HistoryViewModeToggleButton />
</InputGroup>
</Form>
</div>
</Col>
)
}

View file

@ -5,7 +5,7 @@
*/
import React, { useCallback } from 'react'
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
import { Button, ToggleButtonGroup } from 'react-bootstrap'
import { cypressId } from '../../../utils/cypress-attribute'
import { ViewStateEnum } from './history-toolbar'
import { useTranslation } from 'react-i18next'
@ -30,23 +30,20 @@ export const HistoryViewModeToggleButton: React.FC = () => {
)
return (
<ToggleButtonGroup
type='radio'
name='options'
dir='auto'
value={historyToolbarState.viewState}
className={'button-height'}
onChange={onViewStateChange}>
<ToggleButton className={'btn-light'} value={ViewStateEnum.CARD} title={t('landing.history.toolbar.cards')}>
<ToggleButtonGroup type='radio' name='options' dir='auto' className={'button-height'} onChange={onViewStateChange}>
<Button
title={t('landing.history.toolbar.cards')}
variant={historyToolbarState.viewState === ViewStateEnum.CARD ? 'light' : 'outline-light'}
onClick={() => onViewStateChange(ViewStateEnum.CARD)}>
<ForkAwesomeIcon icon={'sticky-note'} className={'fa-fix-line-height'} />
</ToggleButton>
<ToggleButton
</Button>
<Button
{...cypressId('history-mode-table')}
className={'btn-light'}
value={ViewStateEnum.TABLE}
title={t('landing.history.toolbar.table')}>
variant={historyToolbarState.viewState === ViewStateEnum.TABLE ? 'light' : 'outline-light'}
title={t('landing.history.toolbar.table')}
onClick={() => onViewStateChange(ViewStateEnum.TABLE)}>
<ForkAwesomeIcon icon={'table'} className={'fa-fix-line-height'} />
</ToggleButton>
</Button>
</ToggleButtonGroup>
)
}

View file

@ -14,7 +14,7 @@ import { SocialLink } from './social-links'
*/
export const Footer: React.FC = () => {
return (
<footer className='text-light-50 small'>
<footer className='text-light small'>
<LanguagePicker />
<PoweredByLinks />
<SocialLink />

View file

@ -86,7 +86,7 @@ export const LanguagePicker: React.FC = () => {
)
return (
<Form.Control
<Form.Select
as='select'
size='sm'
className='mb-2 mx-auto w-auto'
@ -94,6 +94,6 @@ export const LanguagePicker: React.FC = () => {
onChange={onChangeLang}
{...cypressId('language-picker')}>
{languageOptions}
</Form.Control>
</Form.Select>
)
}

View file

@ -26,7 +26,7 @@ export const UserDropdown: React.FC = () => {
}
return (
<Dropdown alignRight>
<Dropdown align={'end'}>
<Dropdown.Toggle size='sm' variant='dark' {...cypressId('user-dropdown')} className={'d-flex align-items-center'}>
<UserAvatar user={user} />
</Dropdown.Toggle>

View file

@ -5,13 +5,7 @@
*/
.image-drop {
@import "../../../../../global-styles/variables.light.scss";
border: 3px dashed $dark;
:global(body.dark) & {
@import "../../../../../global-styles/variables.dark.scss";
border-color: $dark;
}
border: 3px dashed var(--bs-dark);
border-radius: 3px;
transition: background-color 50ms, color 50ms;

View file

@ -12,15 +12,15 @@
overflow: hidden;
.preview-hover {
display: inline;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
opacity: 0.5;
transition: opacity 0.2s;
text-shadow: #000000 0 0 5px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.preview-hover-text {
@ -44,12 +44,6 @@
min-height: 300px;
width: 100%;
:global(body.dark) &{
@import "../../../../../global-styles/variables.dark";
box-shadow: inset fade-out($black, 0.5) 0 0 20px;
}
@import "../../../../../global-styles/variables.light";
box-shadow: inset fade-out($black, 0.5) 0 0 20px;
box-shadow: inset rgba(var(--bs-dark), 0.5) 0 0 20px;
}
}

View file

@ -86,10 +86,15 @@ export const ClickShield: React.FC<ClickShieldProps> = ({
const previewBackground = useMemo(() => {
return previewImageUrl === undefined ? (
<span className={'preview-background embed-responsive-item'} style={fallbackBackgroundStyle} />
<span
className={`${styles['preview-background']} embed-responsive-item`}
{...cypressId('preview-background')}
style={fallbackBackgroundStyle}
/>
) : (
<ProxyImageFrame
className={'preview-background embed-responsive-item'}
{...cypressId('preview-background')}
className={`${styles['preview-background']} embed-responsive-item`}
style={fallbackBackgroundStyle}
src={previewImageUrl}
alt={previewHoverText}
@ -104,13 +109,12 @@ export const ClickShield: React.FC<ClickShieldProps> = ({
<span className={containerClassName} {...cypressId(props['data-cypress-id'])}>
<ShowIf condition={showChildren}>{children}</ShowIf>
<ShowIf condition={!showChildren}>
<span className={`${styles['click-shield']} embed-responsive embed-responsive-16by9`} onClick={doShowChildren}>
<span className={`${styles['click-shield']} ratio ratio-16x9`} onClick={doShowChildren}>
{previewBackground}
<span className={`${styles['preview-hover']} text-center`}>
<span className={`${styles['preview-hover']}`}>
<span className={`${styles['preview-hover-text']}`}>
<Trans i18nKey={'renderer.clickShield.previewHoverText'} values={hoverTextTranslationValues} />
</span>
<br />
<ForkAwesomeIcon icon={hoverIcon} size={'5x'} className={'mb-2'} />
</span>
</span>

View file

@ -101,9 +101,9 @@ export const UiNotificationToast: React.FC<UiNotificationProps> = ({ notificatio
onClose={dismissNow}
{...cypressId('notification-toast')}>
<Toast.Header>
<strong className='mr-auto'>
<strong className='me-auto'>
<ShowIf condition={!!notification.icon}>
<ForkAwesomeIcon icon={notification.icon as IconName} fixedWidth={true} className={'mr-1'} />
<ForkAwesomeIcon icon={notification.icon as IconName} fixedWidth={true} className={'me-1'} />
</ShowIf>
<Trans i18nKey={notification.titleI18nKey} tOptions={notification.titleI18nOptions} />
</strong>

View file

@ -5,7 +5,7 @@
*/
import React, { Fragment } from 'react'
import { Button, Card } from 'react-bootstrap'
import { Button, Card, Row } from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { AccountDeletionModal } from './account-deletion-modal'
@ -25,14 +25,18 @@ export const ProfileAccountManagement: React.FC = () => {
<Card.Title>
<Trans i18nKey='profile.accountManagement' />
</Card.Title>
<Button variant='secondary' block href={'me/export'} className='mb-2'>
<ForkAwesomeIcon icon='cloud-download' fixedWidth={true} className='mx-2' />
<Trans i18nKey='profile.exportUserData' />
</Button>
<Button variant='danger' block onClick={showModal}>
<ForkAwesomeIcon icon='trash' fixedWidth={true} className='mx-2' />
<Trans i18nKey='profile.deleteUser' />
</Button>
<Row>
<Button variant='secondary' href={'me/export'} className='mb-2'>
<ForkAwesomeIcon icon='cloud-download' fixedWidth={true} className='mx-2' />
<Trans i18nKey='profile.exportUserData' />
</Button>
</Row>
<Row>
<Button variant='danger' onClick={showModal}>
<ForkAwesomeIcon icon='trash' fixedWidth={true} className='mx-2' />
<Trans i18nKey='profile.deleteUser' />
</Button>
</Row>
</Card.Body>
</Card>
<AccountDeletionModal show={modalVisibility} onHide={closeModal} />

View file

@ -101,7 +101,7 @@ export const RegisterPage: NextPage = () => {
<RegisterInfos />
<Button variant='primary' type='submit' block={true} disabled={!ready}>
<Button variant='primary' type='submit' disabled={!ready}>
<Trans i18nKey='login.register.title' />
</Button>
</Form>