mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-21 17:26:29 -05:00
fix: replace dark mode hack with bootstrap's own dark mode
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
3f42798965
commit
0993372290
77 changed files with 244 additions and 365 deletions
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
|
||||
body.dark {
|
||||
@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 "colors-only-bootstrap/bootstrap";
|
||||
|
||||
.btn-close {
|
||||
filter: invert(1);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,6 @@
|
|||
|
||||
@import '~highlight.js/styles/github';
|
||||
|
||||
body.dark {
|
||||
[data-bs-theme="dark"] {
|
||||
@import '~highlight.js/styles/github-dark';
|
||||
}
|
||||
|
|
|
@ -26,10 +26,6 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: $dark;
|
||||
}
|
||||
|
||||
*:focus {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
$white: #fff;
|
||||
$gray-100: #f8f9fa;
|
||||
$gray-200: #ebebeb;
|
||||
$gray-300: #dee2e6;
|
||||
$gray-400: #ced4da;
|
||||
$gray-500: #adb5bd;
|
||||
$gray-600: #888;
|
||||
$gray-700: #444;
|
||||
$gray-800: #303030;
|
||||
$gray-900: #222;
|
||||
$black: #000;
|
||||
|
||||
$blue: #337ab7;
|
||||
$indigo: #6610f2;
|
||||
$purple: #6f42c1;
|
||||
$pink: #e83e8c;
|
||||
$red: #e74c3c;
|
||||
$orange: #fd7e14;
|
||||
$yellow: #f39c12;
|
||||
$green: #00bc8c;
|
||||
$teal: #20c997;
|
||||
$cyan: #5EB7E0;
|
||||
|
||||
$primary: $blue;
|
||||
$secondary: $white;
|
||||
$success: $green;
|
||||
$info: $cyan;
|
||||
$warning: $yellow;
|
||||
$danger: $red;
|
||||
$light: $gray-900;
|
||||
$dark: $white;
|
||||
|
||||
$yiq-contrasted-threshold: 175;
|
||||
|
||||
// Body
|
||||
$body-bg: $light;
|
||||
$body-color: $dark;
|
||||
|
||||
// Links
|
||||
$link-color: $cyan;
|
||||
|
||||
// Fonts
|
||||
$text-muted: $gray-400;
|
||||
|
||||
// Tables
|
||||
$table-accent-bg: $gray-800;
|
||||
$table-border-color: $gray-700;
|
||||
|
||||
// Forms
|
||||
$input-border-color: $body-bg;
|
||||
$input-group-addon-color: $gray-500;
|
||||
$input-group-addon-bg: $gray-700;
|
||||
$input-bg: $gray-700;
|
||||
$input-placeholder-color: $gray-500;
|
||||
$input-color: $white;
|
||||
$input-disabled-bg: $gray-900;
|
||||
|
||||
$custom-file-color: $gray-500;
|
||||
$custom-file-border-color: $body-bg;
|
||||
|
||||
// Dropdowns
|
||||
$dropdown-bg: $gray-900;
|
||||
$dropdown-border-color: $gray-700;
|
||||
$dropdown-divider-bg: $gray-700;
|
||||
$dropdown-link-color: $white;
|
||||
$dropdown-link-hover-color: $white;
|
||||
$dropdown-link-hover-bg: $primary;
|
||||
|
||||
// Navs
|
||||
$nav-link-disabled-color: $gray-500;
|
||||
$nav-tabs-border-color: $gray-700;
|
||||
$nav-tabs-link-hover-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent;
|
||||
$nav-tabs-link-active-color: $white;
|
||||
$nav-tabs-link-active-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent;
|
||||
|
||||
// Navbar
|
||||
$navbar-dark-color: rgba($white, .6);
|
||||
$navbar-dark-hover-color: $white;
|
||||
$navbar-light-color: rgba($gray-900, .7);
|
||||
$navbar-light-hover-color: $gray-900;
|
||||
$navbar-light-active-color: $gray-900;
|
||||
$navbar-light-toggler-border-color: rgba($gray-900, .1);
|
||||
|
||||
// Jumbotron
|
||||
$jumbotron-bg: $gray-800;
|
||||
|
||||
// Cards
|
||||
$card-cap-bg: $gray-700;
|
||||
$card-bg: $gray-800;
|
||||
|
||||
// Popovers
|
||||
$popover-bg: $gray-800;
|
||||
$popover-header-bg: $gray-700;
|
||||
|
||||
// Toasts
|
||||
$toast-background-color: $gray-700;
|
||||
$toast-header-background-color: $gray-800;
|
||||
|
||||
// Modals
|
||||
$modal-content-color: $dark;
|
||||
$modal-content-bg: $gray-800;
|
||||
$modal-content-border-color: $gray-700;
|
||||
$modal-header-border-color: $gray-700;
|
||||
|
||||
// Progress bars
|
||||
$progress-bg: $gray-700;
|
||||
|
||||
// List group
|
||||
$list-group-bg: $gray-800;
|
||||
$list-group-border-color: $gray-700;
|
||||
$list-group-hover-bg: $gray-700;
|
||||
$list-group-action-hover-color: $white;
|
||||
|
||||
// Breadcrumbs
|
||||
$breadcrumb-bg: $gray-700;
|
||||
|
||||
// Close
|
||||
$close-color: $white;
|
||||
$close-text-shadow: none;
|
||||
|
||||
// Code
|
||||
$pre-color: $dark;
|
||||
|
||||
$list-group-color: $dark;
|
||||
|
||||
@import "~bootstrap/scss/functions";
|
||||
@import "~bootstrap/scss/mixins";
|
||||
@import "~bootstrap/scss/variables";
|
|
@ -7,10 +7,3 @@
|
|||
$blue: #337ab7 !default;
|
||||
$cyan: #5EB7E0 !default;
|
||||
$dark: #222222 !default;
|
||||
|
||||
@import "~bootstrap/scss/functions";
|
||||
@import "~bootstrap/scss/mixins";
|
||||
@import "~bootstrap/scss/variables";
|
||||
|
||||
$toast-background-color: $white;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ export interface LoadingScreenProps {
|
|||
*/
|
||||
export const LoadingScreen: React.FC<LoadingScreenProps> = ({ errorMessage }) => {
|
||||
return (
|
||||
<div className={`${styles.loader} text-light`}>
|
||||
<div className={`${styles.loader} text-light bg-dark`}>
|
||||
<div className='mb-3 text-light'>
|
||||
<span className={`d-block`}>
|
||||
<LoadingAnimation error={!!errorMessage} />
|
||||
|
|
|
@ -38,7 +38,6 @@ export const DisplayNameField: React.FC<DisplayNameFieldProps> = ({ onChange, va
|
|||
isValid={isValid}
|
||||
onChange={onChange}
|
||||
placeholder={t('profile.displayName') ?? undefined}
|
||||
className='bg-dark text-light'
|
||||
autoComplete='name'
|
||||
required
|
||||
/>
|
||||
|
|
|
@ -33,7 +33,6 @@ export const NewPasswordField: React.FC<CommonFieldProps> = ({ onChange, value,
|
|||
isInvalid={hasError}
|
||||
onChange={onChange}
|
||||
placeholder={t('login.auth.password') ?? undefined}
|
||||
className='bg-dark text-light'
|
||||
autoComplete='new-password'
|
||||
required
|
||||
/>
|
||||
|
|
|
@ -47,7 +47,6 @@ export const PasswordAgainField: React.FC<PasswordAgainFieldProps> = ({
|
|||
isValid={isValid}
|
||||
onChange={onChange}
|
||||
placeholder={t('login.register.passwordAgain') ?? undefined}
|
||||
className='bg-dark text-light'
|
||||
autoComplete='new-password'
|
||||
required
|
||||
/>
|
||||
|
|
|
@ -33,7 +33,6 @@ export const UsernameField: React.FC<CommonFieldProps> = ({ onChange, value }) =
|
|||
isValid={isValid}
|
||||
onChange={onChange}
|
||||
placeholder={t('login.auth.username') ?? undefined}
|
||||
className='bg-dark text-light'
|
||||
autoComplete='username'
|
||||
autoFocus={true}
|
||||
required
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { AsyncLoadingBoundary } from '../../../components/common/async-loading-boundary/async-loading-boundary'
|
||||
import { CopyToClipboardButton } from '../../../components/common/copyable/copy-to-clipboard-button/copy-to-clipboard-button'
|
||||
import { concatCssClasses } from '../../../utils/concat-css-classes'
|
||||
import { cypressAttribute, cypressId } from '../../../utils/cypress-attribute'
|
||||
import { testId } from '../../../utils/test-id'
|
||||
import { AsyncLoadingBoundary } from '../async-loading-boundary/async-loading-boundary'
|
||||
import { CopyToClipboardButton } from '../copyable/copy-to-clipboard-button/copy-to-clipboard-button'
|
||||
import styles from './highlighted-code.module.scss'
|
||||
import { useAsyncHighlightJsImport } from './hooks/use-async-highlight-js-import'
|
||||
import { useAttachLineNumbers } from './hooks/use-attach-line-numbers'
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
exports[`ExternalLink renders an external link correctly 1`] = `
|
||||
<div>
|
||||
<a
|
||||
class="text-light"
|
||||
class=""
|
||||
dir="auto"
|
||||
href="https://example.com"
|
||||
rel="noopener noreferrer"
|
||||
|
@ -17,7 +17,7 @@ exports[`ExternalLink renders an external link correctly 1`] = `
|
|||
exports[`ExternalLink renders an external link with a title 1`] = `
|
||||
<div>
|
||||
<a
|
||||
class="text-light"
|
||||
class=""
|
||||
dir="auto"
|
||||
href="https://example.com"
|
||||
rel="noopener noreferrer"
|
||||
|
@ -46,7 +46,7 @@ exports[`ExternalLink renders an external link with additional className 1`] = `
|
|||
exports[`ExternalLink renders an external link with an icon 1`] = `
|
||||
<div>
|
||||
<a
|
||||
class="text-light"
|
||||
class=""
|
||||
dir="auto"
|
||||
href="https://example.com"
|
||||
rel="noopener noreferrer"
|
||||
|
@ -62,7 +62,7 @@ exports[`ExternalLink renders an external link with an icon 1`] = `
|
|||
exports[`ExternalLink renders an external link with an id 1`] = `
|
||||
<div>
|
||||
<a
|
||||
class="text-light"
|
||||
class=""
|
||||
dir="auto"
|
||||
href="https://example.com"
|
||||
id="testId"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
exports[`InternalLink renders an internal link correctly 1`] = `
|
||||
<div>
|
||||
<a
|
||||
class="text-light"
|
||||
class=""
|
||||
href="/test"
|
||||
>
|
||||
testText
|
||||
|
@ -14,7 +14,7 @@ exports[`InternalLink renders an internal link correctly 1`] = `
|
|||
exports[`InternalLink renders an internal link with a title 1`] = `
|
||||
<div>
|
||||
<a
|
||||
class="text-light"
|
||||
class=""
|
||||
href="/test"
|
||||
title="testTitle"
|
||||
>
|
||||
|
@ -37,7 +37,7 @@ exports[`InternalLink renders an internal link with additional className 1`] = `
|
|||
exports[`InternalLink renders an internal link with an icon 1`] = `
|
||||
<div>
|
||||
<a
|
||||
class="text-light"
|
||||
class=""
|
||||
href="/test"
|
||||
>
|
||||
BootstrapIconMock_Heart
|
||||
|
@ -50,7 +50,7 @@ exports[`InternalLink renders an internal link with an icon 1`] = `
|
|||
exports[`InternalLink renders an internal link with an id 1`] = `
|
||||
<div>
|
||||
<a
|
||||
class="text-light"
|
||||
class=""
|
||||
href="/test"
|
||||
id="testId"
|
||||
>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
exports[`TranslatedExternalLink renders with i18nKey 1`] = `
|
||||
<div>
|
||||
<a
|
||||
class="text-light"
|
||||
class=""
|
||||
dir="auto"
|
||||
href="https://example.com"
|
||||
rel="noopener noreferrer"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
exports[`TranslatedInternalLink renders with i18nKey 1`] = `
|
||||
<div>
|
||||
<a
|
||||
class="text-light"
|
||||
class=""
|
||||
href="/test"
|
||||
>
|
||||
testi18nKey
|
||||
|
|
|
@ -19,14 +19,7 @@ import React from 'react'
|
|||
* @param className Additional class names added to the link object
|
||||
* @param title The title of the link
|
||||
*/
|
||||
export const ExternalLink: React.FC<LinkWithTextProps> = ({
|
||||
href,
|
||||
text,
|
||||
icon,
|
||||
id,
|
||||
className = 'text-light',
|
||||
title
|
||||
}) => {
|
||||
export const ExternalLink: React.FC<LinkWithTextProps> = ({ href, text, icon, id, className = '', title }) => {
|
||||
return (
|
||||
<a href={href} target='_blank' rel='noopener noreferrer' id={id} className={className} title={title} dir='auto'>
|
||||
<UiIcon icon={icon} nbsp={true} />
|
||||
|
|
|
@ -19,14 +19,7 @@ import React from 'react'
|
|||
* @param className Additional class names added to the link object
|
||||
* @param title The title of the link
|
||||
*/
|
||||
export const InternalLink: React.FC<LinkWithTextProps> = ({
|
||||
href,
|
||||
text,
|
||||
icon,
|
||||
id,
|
||||
className = 'text-light',
|
||||
title
|
||||
}) => {
|
||||
export const InternalLink: React.FC<LinkWithTextProps> = ({ href, text, icon, id, className = '', title }) => {
|
||||
return (
|
||||
<Link href={href} className={className} id={id} title={title}>
|
||||
<UiIcon icon={icon} nbsp={true} />
|
||||
|
|
|
@ -4,7 +4,7 @@ exports[`CommonModal does not render if show is false 1`] = `<div />`;
|
|||
|
||||
exports[`CommonModal render correctly in size lg 1`] = `
|
||||
<div
|
||||
class="modal-dialog text-dark modal-lg"
|
||||
class="modal-dialog modal-lg"
|
||||
data-testid="commonModal"
|
||||
>
|
||||
<div
|
||||
|
@ -26,7 +26,7 @@ exports[`CommonModal render correctly in size lg 1`] = `
|
|||
|
||||
exports[`CommonModal render correctly in size sm 1`] = `
|
||||
<div
|
||||
class="modal-dialog text-dark modal-sm"
|
||||
class="modal-dialog modal-sm"
|
||||
data-testid="commonModal"
|
||||
>
|
||||
<div
|
||||
|
@ -48,7 +48,7 @@ exports[`CommonModal render correctly in size sm 1`] = `
|
|||
|
||||
exports[`CommonModal render correctly in size xl 1`] = `
|
||||
<div
|
||||
class="modal-dialog text-dark modal-xl"
|
||||
class="modal-dialog modal-xl"
|
||||
data-testid="commonModal"
|
||||
>
|
||||
<div
|
||||
|
@ -70,7 +70,7 @@ exports[`CommonModal render correctly in size xl 1`] = `
|
|||
|
||||
exports[`CommonModal render correctly with additionalClasses 1`] = `
|
||||
<div
|
||||
class="modal-dialog text-dark testClass"
|
||||
class="modal-dialog testClass"
|
||||
data-testid="commonModal"
|
||||
>
|
||||
<div
|
||||
|
@ -92,7 +92,7 @@ exports[`CommonModal render correctly with additionalClasses 1`] = `
|
|||
|
||||
exports[`CommonModal render correctly with i18nTitle 1`] = `
|
||||
<div
|
||||
class="modal-dialog text-dark"
|
||||
class="modal-dialog"
|
||||
data-testid="commonModal"
|
||||
>
|
||||
<div
|
||||
|
@ -114,7 +114,7 @@ exports[`CommonModal render correctly with i18nTitle 1`] = `
|
|||
|
||||
exports[`CommonModal render correctly with title 1`] = `
|
||||
<div
|
||||
class="modal-dialog text-dark"
|
||||
class="modal-dialog"
|
||||
data-testid="commonModal"
|
||||
>
|
||||
<div
|
||||
|
@ -136,7 +136,7 @@ exports[`CommonModal render correctly with title 1`] = `
|
|||
|
||||
exports[`CommonModal render correctly with title icon 1`] = `
|
||||
<div
|
||||
class="modal-dialog text-dark"
|
||||
class="modal-dialog"
|
||||
data-testid="commonModal"
|
||||
>
|
||||
<div
|
||||
|
@ -160,7 +160,7 @@ exports[`CommonModal render correctly with title icon 1`] = `
|
|||
|
||||
exports[`CommonModal renders correctly and calls onHide, when close button is clicked 1`] = `
|
||||
<div
|
||||
class="modal-dialog text-dark"
|
||||
class="modal-dialog"
|
||||
data-testid="commonModal"
|
||||
>
|
||||
<div
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`DeletionModal disables deletion when user is not owner 1`] = `
|
||||
<div
|
||||
class="modal-dialog text-dark"
|
||||
class="modal-dialog"
|
||||
data-testid="commonModal"
|
||||
>
|
||||
<div
|
||||
|
@ -23,7 +23,7 @@ exports[`DeletionModal disables deletion when user is not owner 1`] = `
|
|||
/>
|
||||
</div>
|
||||
<div
|
||||
class="text-dark modal-body"
|
||||
class="modal-body"
|
||||
>
|
||||
testText
|
||||
</div>
|
||||
|
@ -44,7 +44,7 @@ exports[`DeletionModal disables deletion when user is not owner 1`] = `
|
|||
|
||||
exports[`DeletionModal renders correctly with deletionButtonI18nKey 1`] = `
|
||||
<div
|
||||
class="modal-dialog text-dark"
|
||||
class="modal-dialog"
|
||||
data-testid="commonModal"
|
||||
>
|
||||
<div
|
||||
|
@ -65,7 +65,7 @@ exports[`DeletionModal renders correctly with deletionButtonI18nKey 1`] = `
|
|||
/>
|
||||
</div>
|
||||
<div
|
||||
class="text-dark modal-body"
|
||||
class="modal-body"
|
||||
>
|
||||
testText
|
||||
</div>
|
||||
|
|
|
@ -74,7 +74,7 @@ export const CommonModal: React.FC<PropsWithChildren<CommonModalProps>> = ({
|
|||
onHide={onHide}
|
||||
animation={true}
|
||||
{...testId('commonModal')}
|
||||
dialogClassName={concatCssClasses('text-dark', additionalClasses)}
|
||||
dialogClassName={concatCssClasses(additionalClasses)}
|
||||
size={modalSize}>
|
||||
<Modal.Header closeButton={!!showCloseButton}>
|
||||
<Modal.Title>
|
||||
|
|
|
@ -51,7 +51,7 @@ export const DeletionModal: React.FC<PropsWithChildren<DeletionModalProps>> = ({
|
|||
titleIcon={titleIcon}
|
||||
showCloseButton={true}
|
||||
{...props}>
|
||||
<Modal.Body className='text-dark'>{children}</Modal.Body>
|
||||
<Modal.Body>{children}</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button {...cypressId('deletionModal.confirmButton')} variant='danger' onClick={onConfirm} disabled={!isOwner}>
|
||||
<Trans i18nKey={deletionButtonI18nKey} />
|
||||
|
|
|
@ -14,7 +14,7 @@ exports[`motd modal renders a modal if a motd was fetched and can dismiss it 1`]
|
|||
This is a mock implementation of a Modal:
|
||||
<dialog>
|
||||
<div
|
||||
class="bg-light modal-body"
|
||||
class="modal-body"
|
||||
>
|
||||
<span
|
||||
data-testid="motd-renderer"
|
||||
|
|
|
@ -53,7 +53,7 @@ export const MotdModal: React.FC = () => {
|
|||
show={!!lines && !loading && !error && !dismissed}
|
||||
titleI18nKey={'motd.title'}
|
||||
{...cypressId('motd-modal')}>
|
||||
<Modal.Body className={'bg-light'}>
|
||||
<Modal.Body>
|
||||
<EditorToRendererCommunicatorContextProvider>
|
||||
<RendererIframe
|
||||
frameClasses={'w-100'}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useApplicationState } from '../../../../hooks/common/use-application-state'
|
||||
import { DarkModePreference } from '../../../../redux/dark-mode/types'
|
||||
import { useSendToRenderer } from '../../../render-page/window-post-message-communicator/hooks/use-send-to-renderer'
|
||||
import { CommunicationMessageType } from '../../../render-page/window-post-message-communicator/rendering-message'
|
||||
import { useMemo } from 'react'
|
||||
|
@ -13,27 +12,19 @@ import { useMemo } from 'react'
|
|||
* Sends additional configuration options (dark mode, line break, etc.) to the renderer.
|
||||
*
|
||||
* @param rendererReady Defines if the target renderer is ready
|
||||
* @param forcedDarkMode Overwrites the value from the global application states if set.
|
||||
*/
|
||||
export const useSendAdditionalConfigurationToRenderer = (
|
||||
rendererReady: boolean,
|
||||
forcedDarkMode: DarkModePreference = DarkModePreference.AUTO
|
||||
): void => {
|
||||
export const useSendAdditionalConfigurationToRenderer = (rendererReady: boolean): void => {
|
||||
const darkModePreference = useApplicationState((state) => state.darkMode.darkModePreference)
|
||||
const newlinesAreBreaks = useApplicationState((state) => state.noteDetails.frontmatter.newlinesAreBreaks)
|
||||
|
||||
const darkMode = useMemo(() => {
|
||||
return forcedDarkMode === DarkModePreference.AUTO ? darkModePreference : forcedDarkMode
|
||||
}, [darkModePreference, forcedDarkMode])
|
||||
|
||||
useSendToRenderer(
|
||||
useMemo(
|
||||
() => ({
|
||||
type: CommunicationMessageType.SET_ADDITIONAL_CONFIGURATION,
|
||||
darkModePreference: darkMode,
|
||||
darkModePreference: darkModePreference,
|
||||
newLinesAreBreaks: newlinesAreBreaks
|
||||
}),
|
||||
[darkMode, newlinesAreBreaks]
|
||||
[darkModePreference, newlinesAreBreaks]
|
||||
),
|
||||
rendererReady
|
||||
)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import type { DarkModePreference } from '../../../redux/dark-mode/types'
|
||||
import { concatCssClasses } from '../../../utils/concat-css-classes'
|
||||
import { cypressAttribute, cypressId } from '../../../utils/cypress-attribute'
|
||||
import { Logger } from '../../../utils/logger'
|
||||
|
@ -27,11 +26,11 @@ import { useForceRenderPageUrlOnIframeLoadCallback } from './hooks/use-force-ren
|
|||
import { useSendAdditionalConfigurationToRenderer } from './hooks/use-send-additional-configuration-to-renderer'
|
||||
import { useSendMarkdownToRenderer } from './hooks/use-send-markdown-to-renderer'
|
||||
import { useSendScrollState } from './hooks/use-send-scroll-state'
|
||||
import styles from './style.module.scss'
|
||||
import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
export interface RendererIframeProps extends Omit<CommonMarkdownRendererProps & ScrollProps, 'baseUrl'> {
|
||||
rendererType: RendererType
|
||||
forcedDarkMode?: DarkModePreference
|
||||
frameClasses?: string
|
||||
onRendererStatusChange?: undefined | ((rendererReady: boolean) => void)
|
||||
adaptFrameHeightToContent?: boolean
|
||||
|
@ -51,7 +50,6 @@ const log = new Logger('RendererIframe')
|
|||
* @param onMakeScrollSource Callback that is fired when the renderer requests to be set as the current scroll source
|
||||
* @param frameClasses CSS classes that should be applied to the iframe
|
||||
* @param rendererType The {@link RendererType type} of the renderer to use.
|
||||
* @param forcedDarkMode If set, the dark mode will be set to the given value. Otherwise, the dark mode won't be changed.
|
||||
* @param adaptFrameHeightToContent If set, the iframe height will be adjusted to the content height
|
||||
* @param onRendererStatusChange Callback that is fired when the renderer in the iframe is ready
|
||||
*/
|
||||
|
@ -62,7 +60,6 @@ export const RendererIframe: React.FC<RendererIframeProps> = ({
|
|||
onMakeScrollSource,
|
||||
frameClasses,
|
||||
rendererType,
|
||||
forcedDarkMode,
|
||||
adaptFrameHeightToContent,
|
||||
onRendererStatusChange
|
||||
}) => {
|
||||
|
@ -142,7 +139,7 @@ export const RendererIframe: React.FC<RendererIframeProps> = ({
|
|||
)
|
||||
|
||||
useEffectOnRenderTypeChange(rendererType, onIframeLoad)
|
||||
useSendAdditionalConfigurationToRenderer(rendererReady, forcedDarkMode)
|
||||
useSendAdditionalConfigurationToRenderer(rendererReady)
|
||||
useSendMarkdownToRenderer(markdownContentLines, rendererReady)
|
||||
|
||||
useSendScrollState(scrollState, rendererReady)
|
||||
|
@ -169,7 +166,7 @@ export const RendererIframe: React.FC<RendererIframeProps> = ({
|
|||
allowFullScreen={true}
|
||||
ref={frameReference}
|
||||
referrerPolicy={'no-referrer'}
|
||||
className={concatCssClasses('border-0', frameClasses)}
|
||||
className={concatCssClasses('border-0', styles.frame, frameClasses)}
|
||||
allow={'clipboard-write'}
|
||||
{...cypressAttribute('renderer-ready', rendererReady ? 'true' : 'false')}
|
||||
{...cypressAttribute('renderer-type', rendererType)}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/*!
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
.frame {
|
||||
color-scheme: initial;
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useApplicationState } from '../../../hooks/common/use-application-state'
|
||||
import { useOutlineButtonVariant } from '../../../hooks/dark-mode/use-outline-button-variant'
|
||||
import { NewNoteButton } from '../../common/new-note-button/new-note-button'
|
||||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import { SignInButton } from '../../landing-layout/navigation/sign-in-button'
|
||||
|
@ -35,9 +36,10 @@ export interface AppBarProps {
|
|||
export const AppBar: React.FC<AppBarProps> = ({ mode }) => {
|
||||
const userExists = useApplicationState((state) => !!state.user)
|
||||
const noteFrontmatter = useApplicationState((state) => state.noteDetails.frontmatter)
|
||||
const buttonVariant = useOutlineButtonVariant()
|
||||
|
||||
return (
|
||||
<Navbar expand={true} className={'bg-light px-3'}>
|
||||
<Navbar expand={true} className={'px-3'}>
|
||||
<Nav className='me-auto d-flex align-items-center'>
|
||||
<NavbarBranding />
|
||||
<ShowIf condition={mode === AppBarMode.EDITOR}>
|
||||
|
@ -52,7 +54,7 @@ export const AppBar: React.FC<AppBarProps> = ({ mode }) => {
|
|||
</ShowIf>
|
||||
</Nav>
|
||||
<Nav className='d-flex gap-2 align-items-center text-secondary justify-content-end'>
|
||||
<SettingsButton variant={'outline-dark'} />
|
||||
<SettingsButton variant={buttonVariant} />
|
||||
<NewNoteButton />
|
||||
<ShowIf condition={!userExists}>
|
||||
<SignInButton size={'sm'} />
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useBooleanState } from '../../../../hooks/common/use-boolean-state'
|
||||
import { useOutlineButtonVariant } from '../../../../hooks/dark-mode/use-outline-button-variant'
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
import { CommonModal } from '../../../common/modals/common-modal'
|
||||
import { CheatsheetContent } from './cheatsheet-content'
|
||||
|
@ -18,6 +19,7 @@ import { Trans, useTranslation } from 'react-i18next'
|
|||
export const CheatsheetButton: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
const buttonVariant = useOutlineButtonVariant()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
@ -25,7 +27,7 @@ export const CheatsheetButton: React.FC = () => {
|
|||
{...cypressId('open.cheatsheet-button')}
|
||||
title={t('cheatsheet.button') ?? undefined}
|
||||
className={'mx-2'}
|
||||
variant='outline-dark'
|
||||
variant={buttonVariant}
|
||||
size={'sm'}
|
||||
onClick={showModal}>
|
||||
<Trans i18nKey={'cheatsheet.button'}></Trans>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useOutlineButtonVariant } from '../../../../hooks/dark-mode/use-outline-button-variant'
|
||||
import { IconButton } from '../../../common/icon-button/icon-button'
|
||||
import type { MouseEvent } from 'react'
|
||||
import React, { useCallback } from 'react'
|
||||
|
@ -28,6 +29,8 @@ export const CheatsheetInNewTabButton: React.FC<CheatsheetInNewTabButtonProps> =
|
|||
|
||||
const { t } = useTranslation()
|
||||
|
||||
const buttonVariant = useOutlineButtonVariant()
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
size={'sm'}
|
||||
|
@ -36,7 +39,7 @@ export const CheatsheetInNewTabButton: React.FC<CheatsheetInNewTabButtonProps> =
|
|||
onClick={openPopUp}
|
||||
icon={BoxArrowUpRight}
|
||||
className={'p-2 border-0'}
|
||||
variant={'outline-dark'}
|
||||
variant={buttonVariant}
|
||||
target={'_blank'}
|
||||
title={t('cheatsheet.modal.popup') ?? ''}
|
||||
/>
|
||||
|
|
|
@ -23,7 +23,7 @@ export const ReadMoreLinkItem: React.FC<ReadMoreLinkGroupProps> = ({ url }) => {
|
|||
<h4>
|
||||
<Trans i18nKey={'cheatsheet.modal.headlines.readMoreLink'} />
|
||||
</h4>
|
||||
<ExternalLink className={'text-dark'} text={url.toString()} href={url.toString()}></ExternalLink>
|
||||
<ExternalLink text={url.toString()} href={url.toString()}></ExternalLink>
|
||||
</ListGroupItem>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useBooleanState } from '../../../../hooks/common/use-boolean-state'
|
||||
import { useOutlineButtonVariant } from '../../../../hooks/dark-mode/use-outline-button-variant'
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
import { IconButton } from '../../../common/icon-button/icon-button'
|
||||
import { HelpModal } from './help-modal'
|
||||
|
@ -17,6 +18,7 @@ import { Trans, useTranslation } from 'react-i18next'
|
|||
export const HelpButton: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const [modalVisibility, showModal, closeModal] = useBooleanState()
|
||||
const buttonVariant = useOutlineButtonVariant()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
@ -26,7 +28,7 @@ export const HelpButton: React.FC = () => {
|
|||
title={t('editor.documentBar.help') ?? undefined}
|
||||
className='ms-2'
|
||||
size='sm'
|
||||
variant='outline-dark'
|
||||
variant={buttonVariant}
|
||||
onClick={showModal}>
|
||||
<Trans i18nKey={'editor.documentBar.help'} />
|
||||
</IconButton>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useApplicationState } from '../../../hooks/common/use-application-state'
|
||||
import { useOutlineButtonVariant } from '../../../hooks/dark-mode/use-outline-button-variant'
|
||||
import { UiIcon } from '../../common/icons/ui-icon'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
|
@ -17,14 +18,11 @@ import { useTranslation } from 'react-i18next'
|
|||
export const ReadOnlyModeButton: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const noteIdentifier = useApplicationState((state) => state.noteDetails.primaryAddress)
|
||||
const buttonVariant = useOutlineButtonVariant()
|
||||
|
||||
return (
|
||||
<Link href={`/s/${noteIdentifier}`} target='_blank'>
|
||||
<Button
|
||||
title={t('editor.documentBar.readOnlyMode') ?? undefined}
|
||||
className='ms-2 text-secondary'
|
||||
size='sm'
|
||||
variant='outline-light'>
|
||||
<Button title={t('editor.documentBar.readOnlyMode') ?? undefined} size='sm' variant={buttonVariant}>
|
||||
<UiIcon icon={IconFileEarmarkTextFill} />
|
||||
</Button>
|
||||
</Link>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useApplicationState } from '../../../hooks/common/use-application-state'
|
||||
import { useOutlineButtonVariant } from '../../../hooks/dark-mode/use-outline-button-variant'
|
||||
import { UiIcon } from '../../common/icons/ui-icon'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
|
@ -17,6 +18,7 @@ import { useTranslation } from 'react-i18next'
|
|||
export const SlideModeButton: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const noteIdentifier = useApplicationState((state) => state.noteDetails.primaryAddress)
|
||||
const buttonVariant = useOutlineButtonVariant()
|
||||
|
||||
return (
|
||||
<Link href={`/p/${noteIdentifier}`} target='_blank'>
|
||||
|
@ -24,7 +26,7 @@ export const SlideModeButton: React.FC = () => {
|
|||
title={t('editor.documentBar.slideMode') ?? undefined}
|
||||
className='ms-2 text-secondary'
|
||||
size='sm'
|
||||
variant='outline-light'>
|
||||
variant={buttonVariant}>
|
||||
<UiIcon icon={IconTv} />
|
||||
</Button>
|
||||
</Link>
|
||||
|
|
|
@ -16,7 +16,7 @@ import React from 'react'
|
|||
*/
|
||||
export const StatusBar: React.FC = () => {
|
||||
return (
|
||||
<div className={`d-flex flex-row border-secondary border-top small bg-light px-2`}>
|
||||
<div className={`d-flex flex-row border-secondary border-top small px-2`}>
|
||||
<div>
|
||||
<CursorPositionInfo />
|
||||
<SelectedCharacters />
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
*/
|
||||
|
||||
.tooltip {
|
||||
&, :global(body.dark) & {
|
||||
--bs-popover-max-width: 100%;
|
||||
--bs-popover-body-padding-y: 0;
|
||||
--bs-popover-body-padding-x: 0;
|
||||
}
|
||||
--bs-popover-max-width: 100%;
|
||||
--bs-popover-body-padding-y: 0;
|
||||
--bs-popover-body-padding-x: 0;
|
||||
}
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
*/
|
||||
|
||||
:global(.btn-toolbar).toolbar {
|
||||
border-bottom: 1px solid #ededed;
|
||||
border-top: 1px solid #ededed;
|
||||
|
||||
:global(.btn) {
|
||||
padding: 0.1875rem 0.5rem;
|
||||
min-width: 30px;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useMayEdit } from '../../../../hooks/common/use-may-edit'
|
||||
import { concatCssClasses } from '../../../../utils/concat-css-classes'
|
||||
import { ShowIf } from '../../../common/show-if/show-if'
|
||||
import { BoldButton } from './buttons/bold-button'
|
||||
import { CheckListButton } from './buttons/check-list-button'
|
||||
|
@ -39,7 +40,7 @@ export const ToolBar: React.FC = () => {
|
|||
|
||||
return (
|
||||
<ShowIf condition={mayEdit}>
|
||||
<ButtonToolbar className={`bg-light ${styles.toolbar}`}>
|
||||
<ButtonToolbar className={concatCssClasses(styles.toolbar, 'mb-2')}>
|
||||
<ButtonGroup className={'mx-1 flex-wrap'}>
|
||||
<BoldButton />
|
||||
<ItalicButton />
|
||||
|
|
|
@ -41,7 +41,8 @@ export const ToolbarButton: React.FC<PropsWithChildren<ToolbarButtonProps>> = ({
|
|||
|
||||
return (
|
||||
<Button
|
||||
variant={'light'}
|
||||
variant={'outline-secondary'}
|
||||
className={'text-body-emphasis'}
|
||||
onClick={onClick}
|
||||
title={title}
|
||||
ref={buttonRef}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
padding: 0;
|
||||
transition: height 0.2s, flex-basis 0.2s;
|
||||
overflow: hidden;
|
||||
color: var(--bs-dark);
|
||||
color: var(--bs-emphasis-color);
|
||||
|
||||
&.hide {
|
||||
flex-basis: 0;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
.slide-sidebar {
|
||||
--sidebar-entry-height: 44px;
|
||||
--sidebar-menu-width: 280px;
|
||||
--sidebar-separator-color: rgba(0, 0, 0, 0.15);
|
||||
--sidebar-separator-color: var(--bs-secondary);
|
||||
|
||||
:global(body.dark) & {
|
||||
--sidebar-separator-color: rgba(255, 255, 255, 0.2);
|
||||
|
@ -35,6 +35,6 @@
|
|||
left: calc(0px - var(--sidebar-menu-width) + var(--sidebar-entry-height));
|
||||
}
|
||||
|
||||
background: var(--bs-light);
|
||||
background: var(--bs-body-bg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@ exports[`Splitter resize can change size with mouse 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="split-divider"
|
||||
class="divider"
|
||||
data-testid="splitter-divider"
|
||||
>
|
||||
<div
|
||||
class="bg-light middle "
|
||||
class="middle"
|
||||
>
|
||||
<div
|
||||
class="buttons"
|
||||
|
@ -75,11 +75,11 @@ exports[`Splitter resize can change size with mouse 2`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="split-divider"
|
||||
class="divider"
|
||||
data-testid="splitter-divider"
|
||||
>
|
||||
<div
|
||||
class="bg-light middle "
|
||||
class="middle"
|
||||
>
|
||||
<div
|
||||
class="buttons"
|
||||
|
@ -134,11 +134,11 @@ exports[`Splitter resize can change size with mouse 3`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="split-divider"
|
||||
class="divider"
|
||||
data-testid="splitter-divider"
|
||||
>
|
||||
<div
|
||||
class="bg-light middle "
|
||||
class="middle"
|
||||
>
|
||||
<div
|
||||
class="buttons"
|
||||
|
@ -193,11 +193,11 @@ exports[`Splitter resize can change size with mouse 4`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="split-divider"
|
||||
class="divider"
|
||||
data-testid="splitter-divider"
|
||||
>
|
||||
<div
|
||||
class="bg-light middle "
|
||||
class="middle"
|
||||
>
|
||||
<div
|
||||
class="buttons"
|
||||
|
@ -252,11 +252,11 @@ exports[`Splitter resize can change size with touch 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="split-divider"
|
||||
class="divider"
|
||||
data-testid="splitter-divider"
|
||||
>
|
||||
<div
|
||||
class="bg-light middle "
|
||||
class="middle"
|
||||
>
|
||||
<div
|
||||
class="buttons"
|
||||
|
@ -311,11 +311,11 @@ exports[`Splitter resize can change size with touch 2`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="split-divider"
|
||||
class="divider"
|
||||
data-testid="splitter-divider"
|
||||
>
|
||||
<div
|
||||
class="bg-light middle "
|
||||
class="middle"
|
||||
>
|
||||
<div
|
||||
class="buttons"
|
||||
|
@ -370,11 +370,11 @@ exports[`Splitter resize can change size with touch 3`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="split-divider"
|
||||
class="divider"
|
||||
data-testid="splitter-divider"
|
||||
>
|
||||
<div
|
||||
class="bg-light middle "
|
||||
class="middle"
|
||||
>
|
||||
<div
|
||||
class="buttons"
|
||||
|
@ -429,11 +429,11 @@ exports[`Splitter resize can change size with touch 4`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="split-divider"
|
||||
class="divider"
|
||||
data-testid="splitter-divider"
|
||||
>
|
||||
<div
|
||||
class="bg-light middle "
|
||||
class="middle"
|
||||
>
|
||||
<div
|
||||
class="buttons"
|
||||
|
@ -488,11 +488,11 @@ exports[`Splitter resize can react to shortcuts 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="split-divider"
|
||||
class="divider"
|
||||
data-testid="splitter-divider"
|
||||
>
|
||||
<div
|
||||
class="bg-light middle shift-right"
|
||||
class="middle shift-right"
|
||||
>
|
||||
<div
|
||||
class="buttons"
|
||||
|
@ -547,11 +547,11 @@ exports[`Splitter resize can react to shortcuts 2`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="split-divider"
|
||||
class="divider"
|
||||
data-testid="splitter-divider"
|
||||
>
|
||||
<div
|
||||
class="bg-light middle shift-left"
|
||||
class="middle shift-left"
|
||||
>
|
||||
<div
|
||||
class="buttons"
|
||||
|
@ -606,11 +606,11 @@ exports[`Splitter resize can react to shortcuts 3`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="split-divider"
|
||||
class="divider"
|
||||
data-testid="splitter-divider"
|
||||
>
|
||||
<div
|
||||
class="bg-light middle "
|
||||
class="middle"
|
||||
>
|
||||
<div
|
||||
class="buttons"
|
||||
|
|
|
@ -4,19 +4,15 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
.split-divider {
|
||||
.divider {
|
||||
width: 15px;
|
||||
background: white;
|
||||
background: var(--bs-body-bg);
|
||||
z-index: 1;
|
||||
box-shadow: 3px 0 6px #e7e7e7;
|
||||
box-shadow: 0 0 6px var(--bs-gray-400);
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
:global(body.dark) & {
|
||||
box-shadow: 3px 0 6px #7b7b7b;
|
||||
}
|
||||
}
|
||||
|
||||
.grabber {
|
||||
|
@ -29,7 +25,8 @@
|
|||
z-index: 100000;
|
||||
position: absolute;
|
||||
border-radius: 90px;
|
||||
border: solid 1px #d5d5d5;
|
||||
border: solid 1px var(--bs-gray-500);
|
||||
background: var(--bs-body-bg);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { concatCssClasses } from '../../../../utils/concat-css-classes'
|
||||
import { testId } from '../../../../utils/test-id'
|
||||
import { UiIcon } from '../../../common/icons/ui-icon'
|
||||
import styles from './split-divider.module.scss'
|
||||
import React from 'react'
|
||||
import React, { useMemo } from 'react'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import { ArrowLeftRight as IconArrowLeftRight } from 'react-bootstrap-icons'
|
||||
import { ArrowLeft as IconArrowLeft } from 'react-bootstrap-icons'
|
||||
|
@ -49,12 +50,17 @@ export const SplitDivider: React.FC<SplitDividerProps> = ({
|
|||
focusRight,
|
||||
forceOpen
|
||||
}) => {
|
||||
const shiftClass = dividerButtonsShift == '' ? '' : styles[dividerButtonsShift]
|
||||
const className = useMemo(() => {
|
||||
return concatCssClasses(styles.middle, {
|
||||
[styles.open]: forceOpen,
|
||||
[styles[dividerButtonsShift]]: dividerButtonsShift !== ''
|
||||
})
|
||||
}, [dividerButtonsShift, forceOpen])
|
||||
|
||||
return (
|
||||
<div className={`${styles['split-divider']}`} {...testId('splitter-divider')}>
|
||||
<div className={`bg-light ${styles['middle']} ${forceOpen ? styles['open'] : ''} ${shiftClass}`}>
|
||||
<div className={styles['buttons']}>
|
||||
<div className={styles.divider} {...testId('splitter-divider')}>
|
||||
<div className={className}>
|
||||
<div className={styles.buttons}>
|
||||
<Button variant={focusLeft ? 'secondary' : 'light'} onClick={onLeftButtonClick}>
|
||||
<UiIcon icon={IconArrowLeft} />
|
||||
</Button>
|
||||
|
|
|
@ -51,7 +51,7 @@ export const EntryMenu: React.FC<EntryMenuProps> = ({
|
|||
return (
|
||||
<Dropdown className={`d-inline-flex ${className || ''}`} {...cypressId('history-entry-menu')}>
|
||||
<Dropdown.Toggle
|
||||
variant={'light'}
|
||||
variant={'secondary'}
|
||||
id={`dropdown-card-${id}`}
|
||||
className={`no-arrow ${styles['history-menu']} d-inline-flex align-items-center`}>
|
||||
<UiIcon icon={IconThreeDots} />
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useDarkModeState } from '../../../hooks/dark-mode/use-dark-mode-state'
|
||||
import { cypressAttribute, cypressId } from '../../../utils/cypress-attribute'
|
||||
import { UiIcon } from '../../common/icons/ui-icon'
|
||||
import { EntryMenu } from '../entry-menu/entry-menu'
|
||||
|
@ -45,16 +46,19 @@ export const HistoryCard: React.FC<HistoryEntryProps & HistoryEventHandlers> = (
|
|||
|
||||
const entryTitle = useHistoryEntryTitle(entry)
|
||||
|
||||
const darkModeState = useDarkModeState()
|
||||
|
||||
const tags = useMemo(
|
||||
() =>
|
||||
entry.tags.map((tag) => (
|
||||
<Badge className={'bg-dark me-1 mb-1'} key={tag}>
|
||||
{tag}
|
||||
</Badge>
|
||||
)),
|
||||
entry.tags.map((tag) => {
|
||||
return (
|
||||
<Badge className={'bg-secondary text-light me-1 mb-1'} key={tag}>
|
||||
{tag}
|
||||
</Badge>
|
||||
)
|
||||
}),
|
||||
[entry.tags]
|
||||
)
|
||||
|
||||
const lastVisited = useMemo(() => formatHistoryDate(entry.lastVisitedAt), [entry.lastVisitedAt])
|
||||
|
||||
return (
|
||||
|
@ -62,18 +66,18 @@ export const HistoryCard: React.FC<HistoryEntryProps & HistoryEventHandlers> = (
|
|||
className='p-2 col-xs-12 col-sm-6 col-md-6 col-lg-4'
|
||||
{...cypressId('history-card')}
|
||||
{...cypressAttribute('card-title', entryTitle)}>
|
||||
<Card className={styles['card-min-height']} text={'dark'} bg={'light'}>
|
||||
<Card className={`${styles['card-min-height']}`} bg={darkModeState ? 'dark' : 'light'}>
|
||||
<Card.Body className='p-2 d-flex flex-row justify-content-between'>
|
||||
<div className={'d-flex flex-column'}>
|
||||
<PinButton isDark={false} isPinned={entry.pinStatus} onPinClick={onPinEntry} />
|
||||
</div>
|
||||
<Link href={`/n/${entry.identifier}`} className='text-decoration-none flex-fill text-dark'>
|
||||
<Link href={`/n/${entry.identifier}`} className='text-decoration-none text-body-emphasis flex-fill'>
|
||||
<div className={'d-flex flex-column justify-content-between'}>
|
||||
<Card.Title className='m-0 mt-1dot5' {...cypressId('history-entry-title')}>
|
||||
{entryTitle}
|
||||
</Card.Title>
|
||||
<div>
|
||||
<div className='text-black-50 mt-2'>
|
||||
<div className='mt-2'>
|
||||
<UiIcon icon={IconClock} /> {DateTime.fromISO(entry.lastVisitedAt).toRelative()}
|
||||
<br />
|
||||
{lastVisited}
|
||||
|
|
|
@ -44,14 +44,14 @@ export const HistoryTableRow: React.FC<HistoryEntryProps & HistoryEventHandlers>
|
|||
return (
|
||||
<tr {...cypressAttribute('entry-title', entryTitle)}>
|
||||
<td>
|
||||
<Link href={`/n/${entry.identifier}`} className='text-light' {...cypressId('history-entry-title')}>
|
||||
<Link href={`/n/${entry.identifier}`} className='text-secondary' {...cypressId('history-entry-title')}>
|
||||
{entryTitle}
|
||||
</Link>
|
||||
</td>
|
||||
<td>{formatHistoryDate(entry.lastVisitedAt)}</td>
|
||||
<td>
|
||||
{entry.tags.map((tag) => (
|
||||
<Badge className={'bg-light me-1 mb-1'} key={tag}>
|
||||
<Badge className={'me-1 mb-1'} key={tag}>
|
||||
{tag}
|
||||
</Badge>
|
||||
))}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useDarkModeState } from '../../../hooks/dark-mode/use-dark-mode-state'
|
||||
import { cypressId } from '../../../utils/cypress-attribute'
|
||||
import { Pager } from '../../common/pagination/pager'
|
||||
import type { HistoryEntriesProps, HistoryEventHandlers } from '../history-content/history-content'
|
||||
|
@ -44,13 +45,15 @@ export const HistoryTable: React.FC<HistoryEntriesProps & HistoryEventHandlers>
|
|||
))
|
||||
}, [entries, onPinClick, onRemoveEntryClick, onDeleteNoteClick])
|
||||
|
||||
const darkModeState = useDarkModeState()
|
||||
|
||||
return (
|
||||
<Table
|
||||
striped
|
||||
bordered
|
||||
hover
|
||||
size='sm'
|
||||
variant='dark'
|
||||
variant={darkModeState ? 'dark' : 'light'}
|
||||
className={styles['history-table']}
|
||||
{...cypressId('history-table')}>
|
||||
<thead>
|
||||
|
|
|
@ -36,7 +36,7 @@ export const ClearHistoryButton: React.FC = () => {
|
|||
return (
|
||||
<Fragment>
|
||||
<Button
|
||||
variant={'light'}
|
||||
variant={'secondary'}
|
||||
title={t('landing.history.toolbar.clear') ?? undefined}
|
||||
onClick={showModal}
|
||||
{...cypressId('history-clear-button')}>
|
||||
|
|
|
@ -17,7 +17,7 @@ export const ExportHistoryButton: React.FC = () => {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<Button variant={'light'} title={t('landing.history.toolbar.export') ?? undefined} onClick={downloadHistory}>
|
||||
<Button variant={'secondary'} title={t('landing.history.toolbar.export') ?? undefined} onClick={downloadHistory}>
|
||||
<UiIcon icon={IconDownload} />
|
||||
</Button>
|
||||
)
|
||||
|
|
|
@ -19,7 +19,7 @@ export const HistoryRefreshButton: React.FC = () => {
|
|||
const refreshHistory = useSafeRefreshHistoryStateCallback()
|
||||
|
||||
return (
|
||||
<Button variant={'light'} title={t('landing.history.toolbar.refresh') ?? undefined} onClick={refreshHistory}>
|
||||
<Button variant={'secondary'} title={t('landing.history.toolbar.refresh') ?? undefined} onClick={refreshHistory}>
|
||||
<UiIcon icon={IconArrowRepeat} />
|
||||
</Button>
|
||||
)
|
||||
|
|
|
@ -90,7 +90,7 @@ export const HistoryToolbar: React.FC = () => {
|
|||
<ShowIf condition={userExists}>
|
||||
<div className={'me-1 mb-1'}>
|
||||
<Button
|
||||
variant={'light'}
|
||||
variant={'secondary'}
|
||||
title={t('landing.history.toolbar.uploadAll') ?? undefined}
|
||||
onClick={onUploadAllToRemote}>
|
||||
<UiIcon icon={IconCloudUpload} />
|
||||
|
|
|
@ -34,13 +34,13 @@ export const HistoryViewModeToggleButton: React.FC = () => {
|
|||
<ToggleButtonGroup type='radio' name='options' dir='auto' className={'button-height'} onChange={onViewStateChange}>
|
||||
<Button
|
||||
title={t('landing.history.toolbar.cards') ?? undefined}
|
||||
variant={historyToolbarState.viewState === ViewStateEnum.CARD ? 'light' : 'outline-light'}
|
||||
variant={historyToolbarState.viewState === ViewStateEnum.CARD ? 'secondary' : 'outline-secondary'}
|
||||
onClick={() => onViewStateChange(ViewStateEnum.CARD)}>
|
||||
<UiIcon icon={IconStickyFill} className={'fa-fix-line-height'} />
|
||||
</Button>
|
||||
<Button
|
||||
{...cypressId('history-mode-table')}
|
||||
variant={historyToolbarState.viewState === ViewStateEnum.TABLE ? 'light' : 'outline-light'}
|
||||
variant={historyToolbarState.viewState === ViewStateEnum.TABLE ? 'secondary' : 'outline-secondary'}
|
||||
title={t('landing.history.toolbar.table') ?? undefined}
|
||||
onClick={() => onViewStateChange(ViewStateEnum.TABLE)}>
|
||||
<UiIcon icon={IconTable} className={'fa-fix-line-height'} />
|
||||
|
|
|
@ -128,7 +128,7 @@ export const ImportHistoryButton: React.FC = () => {
|
|||
{...cypressId('import-history-file-input')}
|
||||
/>
|
||||
<Button
|
||||
variant={'light'}
|
||||
variant={'secondary'}
|
||||
title={t('landing.history.toolbar.import') ?? undefined}
|
||||
onClick={onUploadButtonClick}
|
||||
{...cypressId('import-history-file-button')}>
|
||||
|
|
|
@ -28,7 +28,7 @@ export interface PinButtonProps {
|
|||
export const PinButton: React.FC<PinButtonProps> = ({ isPinned, onPinClick, isDark, className }) => {
|
||||
return (
|
||||
<Button
|
||||
variant={isDark ? 'secondary' : 'light'}
|
||||
variant={isDark ? 'secondary' : 'secondary'}
|
||||
className={`${styles['history-pin']} ${className || ''} ${isPinned ? styles['pinned'] : ''}`}
|
||||
onClick={onPinClick}
|
||||
{...cypressId('history-entry-pin-button')}
|
||||
|
|
|
@ -64,7 +64,7 @@ export const SortButton: React.FC<SortButtonProps> = ({ children, onDirectionCha
|
|||
}, [direction])
|
||||
|
||||
return (
|
||||
<IconButton onClick={toggleSort} variant={'light'} icon={icon} iconSize={1.5} border={true}>
|
||||
<IconButton onClick={toggleSort} variant={'secondary'} icon={icon} iconSize={1.5} border={true}>
|
||||
{children}
|
||||
</IconButton>
|
||||
)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { DarkModePreference } from '../../redux/dark-mode/types'
|
||||
import { Logger } from '../../utils/logger'
|
||||
import { AsyncLoadingBoundary } from '../common/async-loading-boundary/async-loading-boundary'
|
||||
import { RendererIframe } from '../common/renderer-iframe/renderer-iframe'
|
||||
|
@ -32,7 +31,6 @@ export const IntroCustomContent: React.FC = () => {
|
|||
frameClasses={'w-100 overflow-y-hidden'}
|
||||
markdownContentLines={value as string[]}
|
||||
rendererType={RendererType.SIMPLE}
|
||||
forcedDarkMode={DarkModePreference.DARK}
|
||||
adaptFrameHeightToContent={true}
|
||||
/>
|
||||
</AsyncLoadingBoundary>
|
||||
|
|
|
@ -12,7 +12,7 @@ import React from 'react'
|
|||
*/
|
||||
export const Footer: React.FC = () => {
|
||||
return (
|
||||
<footer className='text-light small'>
|
||||
<footer className='small'>
|
||||
<PoweredByLinks />
|
||||
<SocialLink />
|
||||
</footer>
|
||||
|
|
|
@ -18,12 +18,7 @@ export const VersionInfoLink: React.FC = () => {
|
|||
|
||||
return (
|
||||
<Fragment>
|
||||
<Button
|
||||
size={'sm'}
|
||||
variant={'link'}
|
||||
{...cypressId('show-version-modal')}
|
||||
className={'text-light p-0'}
|
||||
onClick={showModal}>
|
||||
<Button size={'sm'} variant={'link'} {...cypressId('show-version-modal')} className={'p-0'} onClick={showModal}>
|
||||
<Trans i18nKey={'landing.versionInfo.versionInfo'} />
|
||||
</Button>
|
||||
<VersionInfoModal onHide={closeModal} show={modalVisibility} />
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useApplyDarkModeStyle } from '../../hooks/dark-mode/use-apply-dark-mode-style'
|
||||
import { useSaveDarkModePreferenceToLocalStorage } from '../../hooks/dark-mode/use-save-dark-mode-preference-to-local-storage'
|
||||
import { MotdModal } from '../common/motd-modal/motd-modal'
|
||||
import { Footer } from './footer/footer'
|
||||
import { HeaderBar } from './navigation/header-bar/header-bar'
|
||||
import type { PropsWithChildren } from 'react'
|
||||
import React, { Fragment } from 'react'
|
||||
import React from 'react'
|
||||
import { Container } from 'react-bootstrap'
|
||||
|
||||
/**
|
||||
|
@ -15,17 +17,20 @@ import { Container } from 'react-bootstrap'
|
|||
*
|
||||
* @param children The children that should be rendered on the page.
|
||||
*/
|
||||
export const LandingLayout: React.FC<PropsWithChildren<unknown>> = ({ children }) => {
|
||||
export const LandingLayout: React.FC<PropsWithChildren> = ({ children }) => {
|
||||
useApplyDarkModeStyle()
|
||||
useSaveDarkModePreferenceToLocalStorage()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div>
|
||||
<MotdModal />
|
||||
<Container className='text-light d-flex flex-column mvh-100'>
|
||||
<Container className='d-flex flex-column mvh-100'>
|
||||
<HeaderBar />
|
||||
<div className={'d-flex flex-column justify-content-between flex-fill text-center'}>
|
||||
<main>{children}</main>
|
||||
<Footer />
|
||||
</div>
|
||||
</Container>
|
||||
</Fragment>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ const HeaderBar: React.FC = () => {
|
|||
</HeaderNavLink>
|
||||
</div>
|
||||
<div className='d-inline-flex gap-2'>
|
||||
<SettingsButton variant={'outline-light'} />
|
||||
<SettingsButton variant={'outline-dark'} />
|
||||
<NewNoteButton />
|
||||
{!userExists ? <SignInButton size='sm' /> : <UserDropdown />}
|
||||
</div>
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
.nav-link {
|
||||
.link {
|
||||
border-bottom: 2px solid transparent
|
||||
}
|
||||
|
||||
.nav-link-active {
|
||||
border-bottom-color: #fff;
|
||||
.active {
|
||||
border-bottom-color: var(--bs-primary);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { concatCssClasses } from '../../../../utils/concat-css-classes'
|
||||
import type { PropsWithDataCypressId } from '../../../../utils/cypress-attribute'
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
import styles from './header-nav-link.module.scss'
|
||||
|
@ -26,17 +27,19 @@ export interface HeaderNavLinkProps extends PropsWithDataCypressId {
|
|||
export const HeaderNavLink: React.FC<PropsWithChildren<HeaderNavLinkProps>> = ({ to, children, ...props }) => {
|
||||
const { route } = useRouter()
|
||||
|
||||
const activeClass = useMemo(() => {
|
||||
return route === to ? styles['nav-link-active'] : ''
|
||||
const className = useMemo(() => {
|
||||
return concatCssClasses(
|
||||
{
|
||||
[styles.active]: route === to
|
||||
},
|
||||
'nav-link',
|
||||
styles.link
|
||||
)
|
||||
}, [route, to])
|
||||
|
||||
return (
|
||||
<Nav.Item>
|
||||
<Link
|
||||
href={to}
|
||||
passHref={true}
|
||||
className={`nav-link text-light ${activeClass} ${styles['nav-link']}`}
|
||||
{...cypressId(props)}>
|
||||
<Link href={to} passHref={true} className={className} {...cypressId(props)}>
|
||||
{children}
|
||||
</Link>
|
||||
</Nav.Item>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useBooleanState } from '../../../hooks/common/use-boolean-state'
|
||||
import { useOutlineButtonVariant } from '../../../hooks/dark-mode/use-outline-button-variant'
|
||||
import { cypressId } from '../../../utils/cypress-attribute'
|
||||
import { IconButton } from '../../common/icon-button/icon-button'
|
||||
import { SettingsModal } from './settings-modal'
|
||||
|
@ -17,9 +18,17 @@ export type SettingsButtonProps = Omit<ButtonProps, 'onClick'>
|
|||
*/
|
||||
export const SettingsButton: React.FC<SettingsButtonProps> = (props) => {
|
||||
const [show, showModal, hideModal] = useBooleanState(false)
|
||||
const buttonVariant = useOutlineButtonVariant()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<IconButton {...props} {...cypressId('settingsButton')} onClick={showModal} icon={IconGear} />
|
||||
<IconButton
|
||||
{...props}
|
||||
{...cypressId('settingsButton')}
|
||||
onClick={showModal}
|
||||
icon={IconGear}
|
||||
variant={buttonVariant}
|
||||
/>
|
||||
<SettingsModal show={show} onHide={hideModal} />
|
||||
</Fragment>
|
||||
)
|
||||
|
|
|
@ -25,7 +25,6 @@ export const PasswordField: React.FC<AuthFieldProps> = ({ onChange, invalid }) =
|
|||
size='sm'
|
||||
placeholder={t('login.auth.password') ?? undefined}
|
||||
onChange={onChange}
|
||||
className='bg-dark text-light'
|
||||
autoComplete='current-password'
|
||||
/>
|
||||
</Form.Group>
|
||||
|
|
|
@ -32,7 +32,6 @@ export const UsernameField: React.FC<UsernameFieldProps> = ({ onChange, invalid,
|
|||
size='sm'
|
||||
placeholder={t('login.auth.username') ?? undefined}
|
||||
onChange={onChange}
|
||||
className='bg-dark text-light'
|
||||
autoComplete='username'
|
||||
/>
|
||||
</Form.Group>
|
||||
|
|
|
@ -49,7 +49,7 @@ export const ViaLocal: React.FC = () => {
|
|||
const onPasswordChange = useOnInputChange(setPassword)
|
||||
|
||||
return (
|
||||
<Card className='bg-dark mb-4'>
|
||||
<Card className='mb-4'>
|
||||
<Card.Body>
|
||||
<Card.Title>
|
||||
<Trans i18nKey='login.signInVia' values={{ service: t('login.auth.username') }} />
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
.image-drop {
|
||||
border: 3px dashed var(--bs-dark);
|
||||
border: 3px dashed var(--bs-primary);
|
||||
|
||||
border-radius: 3px;
|
||||
transition: background-color 50ms, color 50ms;
|
||||
|
|
|
@ -97,7 +97,7 @@ export const ImagePlaceholder: React.FC<PlaceholderImageFrameProps> = ({
|
|||
onChange={onChangeHandler}
|
||||
ref={fileInputReference}
|
||||
/>
|
||||
<div className={'align-items-center flex-column justify-content-center flex-fill d-flex'}>
|
||||
<div className={'align-items-center flex-column justify-content-center flex-fill d-flex text-body-emphasis'}>
|
||||
<div className={'d-flex flex-column'}>
|
||||
<span className='my-2'>
|
||||
<Trans i18nKey={'editor.embeddings.placeholderImage.placeholderText'} />
|
||||
|
|
|
@ -13,11 +13,16 @@ export const useApplyDarkModeStyle = (): void => {
|
|||
const darkMode = useDarkModeState()
|
||||
useEffect(() => {
|
||||
if (darkMode) {
|
||||
window.document.body.classList.add('dark')
|
||||
window.document.body.dataset.bsTheme = 'dark'
|
||||
} else {
|
||||
window.document.body.classList.remove('dark')
|
||||
window.document.body.dataset.bsTheme = 'light'
|
||||
}
|
||||
}, [darkMode])
|
||||
|
||||
useEffect(() => () => window.document.body.classList.remove('dark'), [])
|
||||
useEffect(
|
||||
() => () => {
|
||||
window.document.body.dataset.bsTheme = 'light'
|
||||
},
|
||||
[]
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import * as UseDarkModeStateModule from './use-dark-mode-state'
|
||||
import { useOutlineButtonVariant } from './use-outline-button-variant'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import React from 'react'
|
||||
|
||||
jest.mock('./use-dark-mode-state')
|
||||
|
||||
describe('useOutlineButtonVariant', () => {
|
||||
const TestComponent: React.FC = () => {
|
||||
return useOutlineButtonVariant()
|
||||
}
|
||||
|
||||
it('returns the correct variant for dark mode', async () => {
|
||||
jest.spyOn(UseDarkModeStateModule, 'useDarkModeState').mockReturnValue(true)
|
||||
render(<TestComponent />)
|
||||
await screen.findByText('outline-light')
|
||||
})
|
||||
|
||||
it('returns the correct variant for light mode', async () => {
|
||||
jest.spyOn(UseDarkModeStateModule, 'useDarkModeState').mockReturnValue(false)
|
||||
render(<TestComponent />)
|
||||
await screen.findByText('outline-dark')
|
||||
})
|
||||
})
|
10
frontend/src/hooks/dark-mode/use-outline-button-variant.ts
Normal file
10
frontend/src/hooks/dark-mode/use-outline-button-variant.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useDarkModeState } from './use-dark-mode-state'
|
||||
|
||||
export const useOutlineButtonVariant = (): 'outline-light' | 'outline-dark' => {
|
||||
return useDarkModeState() ? 'outline-light' : 'outline-dark'
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import '../../global-styles/dark.scss'
|
||||
import '../../global-styles/index.scss'
|
||||
import type { FrontendConfig } from '../api/config/types'
|
||||
import { ApplicationLoader } from '../components/application-loader/application-loader'
|
||||
|
|
|
@ -72,7 +72,7 @@ export const LoginPage: React.FC = () => {
|
|||
</ShowIf>
|
||||
<ShowIf condition={oneClickProviders.length > 0}>
|
||||
<Col xs={12} sm={10} lg={4}>
|
||||
<Card className='bg-dark mb-4'>
|
||||
<Card className='mb-4'>
|
||||
<Card.Body>
|
||||
<Card.Title>
|
||||
<Trans i18nKey='login.signInVia' values={{ service: '' }} />
|
||||
|
|
|
@ -7,6 +7,7 @@ import { NoteLoadingBoundary } from '../../components/common/note-loading-bounda
|
|||
import { EditorPageContent } from '../../components/editor-page/editor-page-content'
|
||||
import { EditorToRendererCommunicatorContextProvider } from '../../components/editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
||||
import { ResetRealtimeStateBoundary } from '../../components/editor-page/reset-realtime-state-boundary'
|
||||
import { useApplyDarkModeStyle } from '../../hooks/dark-mode/use-apply-dark-mode-style'
|
||||
import type { NextPage } from 'next'
|
||||
import React from 'react'
|
||||
|
||||
|
@ -14,6 +15,8 @@ import React from 'react'
|
|||
* Renders a page that is used by the user to edit markdown notes. It contains the editor and a renderer.
|
||||
*/
|
||||
export const EditorPage: NextPage = () => {
|
||||
useApplyDarkModeStyle()
|
||||
|
||||
return (
|
||||
<ResetRealtimeStateBoundary>
|
||||
<NoteLoadingBoundary>
|
||||
|
|
|
@ -84,7 +84,7 @@ export const RegisterPage: NextPage = () => {
|
|||
</h1>
|
||||
<Row className='h-100 d-flex justify-content-center'>
|
||||
<Col lg={6}>
|
||||
<Card className='bg-dark mb-4 text-start'>
|
||||
<Card className='mb-4 text-start'>
|
||||
<Card.Body>
|
||||
<Form onSubmit={doRegisterSubmit} className={'d-flex flex-column gap-3'}>
|
||||
<UsernameField onChange={onUsernameChange} value={username} />
|
||||
|
|
|
@ -7,12 +7,17 @@ import { RendererToEditorCommunicatorContextProvider } from '../components/edito
|
|||
import { RenderPageContent } from '../components/render-page/render-page-content'
|
||||
import { useApplyDarkModeStyle } from '../hooks/dark-mode/use-apply-dark-mode-style'
|
||||
import type { NextPage } from 'next'
|
||||
import React from 'react'
|
||||
import React, { useEffect } from 'react'
|
||||
|
||||
/**
|
||||
* Renders the actual markdown renderer that receives the content and metadata via iframe communication.
|
||||
*/
|
||||
export const RenderPage: NextPage = () => {
|
||||
useEffect(() => {
|
||||
document.body.classList.add('bg-transparent')
|
||||
return () => document.body.classList.remove('bg-transparent')
|
||||
}, [])
|
||||
|
||||
useApplyDarkModeStyle()
|
||||
|
||||
return (
|
||||
|
|
|
@ -25,7 +25,7 @@ export const DocumentReadOnlyPage: React.FC = () => {
|
|||
<NoteLoadingBoundary>
|
||||
<HeadMetaProperties />
|
||||
<MotdModal />
|
||||
<div className={'d-flex flex-column mvh-100 bg-light'}>
|
||||
<div className={'d-flex flex-column mvh-100'}>
|
||||
<AppBar mode={AppBarMode.BASIC} />
|
||||
<DocumentReadOnlyPageContent />
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue