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('version-modal').should('not.exist')
cy.getByCypressId('show-version-modal').click() cy.getByCypressId('show-version-modal').click()
cy.getByCypressId('version-modal').should('be.visible') 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') cy.getByCypressId('version-modal').should('not.exist')
}) })
}) })

View file

@ -13,7 +13,7 @@ describe('Link gets replaced with embedding: ', () => {
it('GitHub Gist', () => { it('GitHub Gist', () => {
cy.setCodemirrorContent('https://gist.github.com/schacon/1') 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') 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 * SPDX-License-Identifier: AGPL-3.0-only
*/ */
@import "variables.dark";
body.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.module";
@import "variables.light"; @import "variables.light";
@import "bootstrap-vendor/bootstrap"; @import "~bootstrap/scss/bootstrap";
@import '~react-bootstrap-typeahead/css/Typeahead'; @import '~react-bootstrap-typeahead/css/Typeahead';
@import "~@fontsource/source-sans-pro/index.css"; @import "~@fontsource/source-sans-pro/index.css";
@import "~twemoji-colr-font/twemoji"; @import "~twemoji-colr-font/twemoji";

View file

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

View file

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

View file

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

View file

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

View file

@ -70,7 +70,7 @@ export const UserAvatar: React.FC<UserAvatarProps> = ({ user, size, additionalCl
/> />
<ShowIf condition={showName}> <ShowIf condition={showName}>
<OverlayTrigger overlay={tooltip}> <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> </OverlayTrigger>
</ShowIf> </ShowIf>
</span> </span>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -12,28 +12,12 @@
:global(.btn) { :global(.btn) {
svg g { svg g {
@import "../../../../../global-styles/variables.light"; fill: var(--bs-secondary);
fill: $secondary;
} }
:global(&.active), &:hover { :global(&.active), &:hover {
svg g { svg g {
@import "../../../../../global-styles/variables.light"; fill: var(--bs-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;
}
} }
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -33,9 +33,9 @@ export const PermissionAddEntryField: React.FC<PermissionAddEntryFieldProps> = (
return ( return (
<li className={'list-group-item'}> <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} /> <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'} /> <ForkAwesomeIcon icon={'plus'} />
</Button> </Button>
</InputGroup> </InputGroup>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -58,34 +58,27 @@
} }
@mixin colors { @mixin colors {
color: $dark; color: black;
&.sidebar-button-primary { &.sidebar-button-primary {
background: $primary; color: var(--bs-light);
color: $white; background: var(--bs-primary);
&:hover { &:hover {
color: $primary; color: var(--bs-primary);
background: $entry-hover-bg; background: var(--bs-light);
} }
} }
&:hover { &:hover {
background: $entry-hover-bg; color: var(--bs-light);
color: $dark; background: var(--bs-primary);
} }
} }
@import "../../../../../global-styles/variables.light"; $entry-hover-bg: darken(black, 10%);
$entry-hover-bg: darken($body-bg, 10%);
@include colors; @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 type { PropsWithChildren } from 'react'
import React, { useMemo } from 'react' import React from 'react'
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon' import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
import type { IconName } from '../../../common/fork-awesome/types' import type { IconName } from '../../../common/fork-awesome/types'
import { ShowIf } from '../../../common/show-if/show-if' import { ShowIf } from '../../../common/show-if/show-if'
import type { SidebarEntryProps } from '../types' import type { SidebarEntryProps } from '../types'
import styles from './sidebar-button.module.scss' import styles from './sidebar-button.module.scss'
export interface SidebarButton extends SidebarEntryProps {
variant?: 'primary'
}
/** /**
* A button that should be rendered in the sidebar. * 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 disabled If the button should be disabled
* @param props Other button props * @param props Other button props
*/ */
export const SidebarButton: React.FC<PropsWithChildren<SidebarButton>> = ({ export const SidebarButton: React.FC<PropsWithChildren<SidebarEntryProps>> = ({
children, children,
icon, icon,
className, className,
buttonRef, buttonRef,
hide, hide,
variant,
disabled, disabled,
...props ...props
}) => { }) => {
const variantClass = useMemo(() => {
return variant !== undefined ? styles['sidebar-button-' + variant] : ''
}, [variant])
return ( return (
<button <button
ref={buttonRef} ref={buttonRef}
className={`${styles['sidebar-button']} ${variantClass} ${hide ? styles['hide'] : ''} ${className ?? ''}`} className={`${styles['sidebar-button']} ${hide ? styles['hide'] : ''} ${className ?? ''}`}
disabled={disabled} disabled={disabled}
{...props}> {...props}>
<ShowIf condition={!!icon}> <ShowIf condition={!!icon}>

View file

@ -18,17 +18,8 @@
overflow-y: auto; overflow-y: auto;
} }
@import "../../../../../global-styles/variables.light";
& > div { & > div {
background: $body-bg; background: var(--bs-body-bg);
box-shadow: inset 0 7px 7px -6px #bbbbbb; 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; top: 0;
left: 0; left: 0;
transition: left 0.3s; 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 { &:hover, &.show {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
left: (-$menu-width + $height); left: (-$menu-width + $height);
} }
:global(body.dark) & { background: var(--bs-light);
@import "../../../../../global-styles/variables.dark";
background: $body-bg;
}
@import "../../../../../global-styles/variables.light";
background: $body-bg;
} }
} }

View file

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

View file

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

View file

@ -48,7 +48,7 @@ export const HistoryCard: React.FC<HistoryEntryProps & HistoryEventHandlers> = (
const tags = useMemo( const tags = useMemo(
() => () =>
entry.tags.map((tag) => ( 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} {tag}
</Badge> </Badge>
)), )),

View file

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

View file

@ -54,13 +54,13 @@ export const HistoryTableRow: React.FC<HistoryEntryProps & HistoryEventHandlers>
<td>{formatHistoryDate(entry.lastVisitedAt)}</td> <td>{formatHistoryDate(entry.lastVisitedAt)}</td>
<td> <td>
{entry.tags.map((tag) => ( {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} {tag}
</Badge> </Badge>
))} ))}
</td> </td>
<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 <EntryMenu
id={entry.identifier} id={entry.identifier}
title={entryTitle} title={entryTitle}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -12,15 +12,15 @@
overflow: hidden; overflow: hidden;
.preview-hover { .preview-hover {
display: inline;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white; color: white;
opacity: 0.5; opacity: 0.5;
transition: opacity 0.2s; transition: opacity 0.2s;
text-shadow: #000000 0 0 5px; text-shadow: #000000 0 0 5px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
} }
.preview-hover-text { .preview-hover-text {
@ -44,12 +44,6 @@
min-height: 300px; min-height: 300px;
width: 100%; width: 100%;
:global(body.dark) &{ box-shadow: inset rgba(var(--bs-dark), 0.5) 0 0 20px;
@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;
} }
} }

View file

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

View file

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

View file

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

View file

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