Switch the base framework from Create React App to Next.JS

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Renovate Bot 2021-12-25 15:44:24 +00:00 committed by Tilman Vatteroth
parent a979b6ffdd
commit 77a60c6c48
361 changed files with 5130 additions and 9605 deletions

View file

@ -1,37 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React from 'react'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import type { IconName } from '../../common/fork-awesome/types'
import { ShowIf } from '../../common/show-if/show-if'
import type { SidebarEntryProps } from './types'
export type SidebarEntryVariant = 'primary'
export const SidebarButton: React.FC<SidebarEntryProps> = ({
children,
icon,
className,
variant,
buttonRef,
hide,
...props
}) => {
return (
<button
ref={buttonRef}
className={`sidebar-entry ${hide ? 'hide' : ''} ${variant ? `sidebar-entry-${variant}` : ''} ${className ?? ''}`}
{...props}>
<ShowIf condition={!!icon}>
<span className={'sidebar-icon'}>
<ForkAwesomeIcon icon={icon as IconName} />
</span>
</ShowIf>
<span className={'sidebar-text'}>{children}</span>
</button>
)
}

View file

@ -0,0 +1,91 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.sidebar-button {
@import '../style/variables.scss';
height: $height;
flex: 0 0 $height;
width: 100%;
display: flex;
align-items: center;
border: solid 1px rgba(0, 0, 0, 0.15);
user-select: none;
cursor: pointer;
background: transparent;
padding: 0;
transition: height 0.2s, flex-basis 0.2s;
overflow: hidden;
&.hide {
flex-basis: 0;
height: 0px;
border-width: 0px;
.sidebar-icon {
opacity: 0;
}
.sidebar-text {
opacity: 0;
}
}
.sidebar-icon {
transition: opacity 0.2s;
opacity: 1;
height: $height;
width: $height;
display: inline-flex;
align-items: center;
justify-content: center;
position: relative;
flex: 0 0 40px;
}
.sidebar-text {
height: 100%;
display: flex;
align-items: center;
opacity: 1;
transition: opacity 0.2s;
text-align: left;
flex: 1 1 0;
width: 0;
}
@mixin colors {
color: $dark;
&.sidebar-button-primary {
background: $primary;
color: $white;
&:hover {
color: $primary;
background: $entry-hover-bg;
}
}
&:hover {
background: $entry-hover-bg;
color: $dark;
}
}
@import "../../../../../global-styles/variables.light";
$entry-hover-bg: darken($body-bg, 10%);
@include colors;
:global(body.dark) & {
@import "../../../../../global-styles/variables.dark";
$entry-hover-bg: darken($body-bg, 10%);
@include colors;
}
}

View file

@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React, { useMemo } from 'react'
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
import type { IconName } from '../../../common/fork-awesome/types'
import { ShowIf } from '../../../common/show-if/show-if'
import type { SidebarEntryProps } from '../types'
import styles from './sidebar-button.module.scss'
export interface SidebarButton extends SidebarEntryProps {
variant?: 'primary'
}
/**
* A button that should be rendered in the sidebar.
*
* @param children The react elements in the button
* @param icon The icon at the left side of the button
* @param className Additional css class names
* @param buttonRef A reference to the button
* @param hide Should be {@code true} if the button should be invisible
* @param variant An alternative theme for the button
* @param props Other button props
*/
export const SidebarButton: React.FC<SidebarButton> = ({
children,
icon,
className,
buttonRef,
hide,
variant,
...props
}) => {
const variantClass = useMemo(() => {
return variant !== undefined ? styles['sidebar-button-' + variant] : ''
}, [variant])
return (
<button
ref={buttonRef}
className={`${styles['sidebar-button']} ${variantClass} ${hide ? styles['hide'] : ''} ${className ?? ''}`}
{...props}>
<ShowIf condition={!!icon}>
<span className={`sidebar-button-icon ${styles['sidebar-icon']}`}>
<ForkAwesomeIcon icon={icon as IconName} />
</span>
</ShowIf>
<span className={styles['sidebar-text']}>{children}</span>
</button>
)
}

View file

@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.sidebar-menu {
transition: height 0.2s, flex-basis 0.2s;
display: flex;
flex-direction: column;
overflow: hidden;
flex: 0 1 0;
height: 0;
&.show {
height: 100%;
flex-basis: 100%;
overflow-y: auto;
}
@import "../../../../../global-styles/variables.light";
& > div {
background: $body-bg;
box-shadow: inset 0 7px 7px -6px #bbbbbb;
}
:global(body.dark) & {
@import "../../../../../global-styles/variables.dark";
& > div {
background: $body-bg;
box-shadow: inset 0 7px 7px -6px #1d1d1d;
}
}
}

View file

@ -5,11 +5,12 @@
*/
import React from 'react'
import type { SidebarMenuProps } from './types'
import type { SidebarMenuProps } from '../types'
import styles from './sidebar-menu.module.scss'
export const SidebarMenu: React.FC<SidebarMenuProps> = ({ children, expand }) => {
return (
<div className={`sidebar-menu ${expand ? 'show' : ''}`}>
<div className={`${styles['sidebar-menu']} ${expand ? styles['show'] : ''}`}>
<div className={`d-flex flex-column`}>{children}</div>
</div>
)

View file

@ -6,15 +6,15 @@
import React, { useCallback, useRef, useState } from 'react'
import { useClickAway } from 'react-use'
import { DeleteNoteSidebarEntry } from './delete-note-sidebar-entry'
import { DocumentInfoSidebarEntry } from './document-info-sidebar-entry'
import { ExportMenuSidebarMenu } from './export-menu-sidebar-menu'
import { ImportMenuSidebarMenu } from './import-menu-sidebar-menu'
import { PermissionsSidebarEntry } from './permissions-sidebar-entry'
import { PinNoteSidebarEntry } from './pin-note-sidebar-entry'
import { RevisionSidebarEntry } from './revision-sidebar-entry'
import { ShareSidebarEntry } from './share-sidebar-entry'
import './style/theme.scss'
import { DeleteNoteSidebarEntry } from './specific-sidebar-entries/delete-note-sidebar-entry'
import { DocumentInfoSidebarEntry } from './specific-sidebar-entries/document-info-sidebar-entry'
import { ExportMenuSidebarMenu } from './specific-sidebar-entries/export-menu-sidebar-menu'
import { ImportMenuSidebarMenu } from './specific-sidebar-entries/import-menu-sidebar-menu'
import { PermissionsSidebarEntry } from './specific-sidebar-entries/permissions-sidebar-entry'
import { PinNoteSidebarEntry } from './specific-sidebar-entries/pin-note-sidebar-entry'
import { RevisionSidebarEntry } from './specific-sidebar-entries/revision-sidebar-entry'
import { ShareSidebarEntry } from './specific-sidebar-entries/share-sidebar-entry'
import styles from './style/sidebar.module.scss'
import { DocumentSidebarMenuSelection } from './types'
import { UsersOnlineSidebarMenu } from './users-online-sidebar-menu/users-online-sidebar-menu'
@ -37,8 +37,8 @@ export const Sidebar: React.FC = () => {
const selectionIsNotNone = selectedMenu !== DocumentSidebarMenuSelection.NONE
return (
<div className='slide-sidebar'>
<div ref={sideBarRef} className={`sidebar-inner ${selectionIsNotNone ? 'show' : ''}`}>
<div className={styles['slide-sidebar']}>
<div ref={sideBarRef} className={`${styles['sidebar-inner']} ${selectionIsNotNone ? styles['show'] : ''}`}>
<UsersOnlineSidebarMenu
menuId={DocumentSidebarMenuSelection.USERS_ONLINE}
selectedMenuId={selectedMenu}

View file

@ -6,9 +6,9 @@
import React, { Fragment, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { DeletionModal } from '../../common/modals/deletion-modal'
import { SidebarButton } from './sidebar-button'
import type { SpecificSidebarEntryProps } from './types'
import { DeletionModal } from '../../../common/modals/deletion-modal'
import { SidebarButton } from '../sidebar-button/sidebar-button'
import type { SpecificSidebarEntryProps } from '../types'
export const DeleteNoteSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ hide, className }) => {
useTranslation()

View file

@ -6,10 +6,10 @@
import React, { Fragment, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { DocumentInfoModal } from '../document-bar/document-info/document-info-modal'
import { SidebarButton } from './sidebar-button'
import type { SpecificSidebarEntryProps } from './types'
import { cypressId } from '../../../utils/cypress-attribute'
import { DocumentInfoModal } from '../../document-bar/document-info/document-info-modal'
import { SidebarButton } from '../sidebar-button/sidebar-button'
import type { SpecificSidebarEntryProps } from '../types'
import { cypressId } from '../../../../utils/cypress-attribute'
export const DocumentInfoSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
const [showModal, setShowModal] = useState(false)

View file

@ -6,12 +6,12 @@
import React, { useCallback } from 'react'
import sanitize from 'sanitize-filename'
import { store } from '../../../redux'
import { store } from '../../../../redux'
import { Trans, useTranslation } from 'react-i18next'
import { download } from '../../common/download/download'
import { SidebarButton } from './sidebar-button'
import { useNoteMarkdownContent } from '../../../hooks/common/use-note-markdown-content'
import { cypressId } from '../../../utils/cypress-attribute'
import { download } from '../../../common/download/download'
import { SidebarButton } from '../sidebar-button/sidebar-button'
import { useNoteMarkdownContent } from '../../../../hooks/common/use-note-markdown-content'
import { cypressId } from '../../../../utils/cypress-attribute'
export const ExportMarkdownSidebarEntry: React.FC = () => {
const { t } = useTranslation()

View file

@ -6,13 +6,13 @@
import React, { Fragment, useCallback } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import links from '../../../links.json'
import links from '../../../../links.json'
import { ExportMarkdownSidebarEntry } from './export-markdown-sidebar-entry'
import { SidebarButton } from './sidebar-button'
import { SidebarMenu } from './sidebar-menu'
import type { SpecificSidebarMenuProps } from './types'
import { DocumentSidebarMenuSelection } from './types'
import { cypressId } from '../../../utils/cypress-attribute'
import { SidebarButton } from '../sidebar-button/sidebar-button'
import { SidebarMenu } from '../sidebar-menu/sidebar-menu'
import type { SpecificSidebarMenuProps } from '../types'
import { DocumentSidebarMenuSelection } from '../types'
import { cypressId } from '../../../../utils/cypress-attribute'
export const ExportMenuSidebarMenu: React.FC<SpecificSidebarMenuProps> = ({
className,

View file

@ -6,11 +6,11 @@
import React, { Fragment, useCallback, useRef } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { useNoteMarkdownContent } from '../../../hooks/common/use-note-markdown-content'
import { setNoteContent } from '../../../redux/note-details/methods'
import { SidebarButton } from './sidebar-button'
import { UploadInput } from './upload-input'
import { cypressId } from '../../../utils/cypress-attribute'
import { useNoteMarkdownContent } from '../../../../hooks/common/use-note-markdown-content'
import { setNoteContent } from '../../../../redux/note-details/methods'
import { SidebarButton } from '../sidebar-button/sidebar-button'
import { UploadInput } from '../upload-input'
import { cypressId } from '../../../../utils/cypress-attribute'
export const ImportMarkdownSidebarEntry: React.FC = () => {
const markdownContent = useNoteMarkdownContent()

View file

@ -7,11 +7,11 @@
import React, { Fragment, useCallback } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { ImportMarkdownSidebarEntry } from './import-markdown-sidebar-entry'
import { SidebarButton } from './sidebar-button'
import { SidebarMenu } from './sidebar-menu'
import type { SpecificSidebarMenuProps } from './types'
import { DocumentSidebarMenuSelection } from './types'
import { cypressId } from '../../../utils/cypress-attribute'
import { SidebarButton } from '../sidebar-button/sidebar-button'
import { SidebarMenu } from '../sidebar-menu/sidebar-menu'
import type { SpecificSidebarMenuProps } from '../types'
import { DocumentSidebarMenuSelection } from '../types'
import { cypressId } from '../../../../utils/cypress-attribute'
export const ImportMenuSidebarMenu: React.FC<SpecificSidebarMenuProps> = ({
className,

View file

@ -6,9 +6,9 @@
import React, { Fragment, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { PermissionModal } from '../document-bar/permissions/permission-modal'
import { SidebarButton } from './sidebar-button'
import type { SpecificSidebarEntryProps } from './types'
import { PermissionModal } from '../../document-bar/permissions/permission-modal'
import { SidebarButton } from '../sidebar-button/sidebar-button'
import type { SpecificSidebarEntryProps } from '../types'
export const PermissionsSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
const [showModal, setShowModal] = useState(false)

View file

@ -6,17 +6,15 @@
import React, { useCallback, useMemo } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { SidebarButton } from './sidebar-button'
import type { SpecificSidebarEntryProps } from './types'
import { useParams } from 'react-router-dom'
import type { EditorPagePathParams } from '../editor-page'
import { toggleHistoryEntryPinning } from '../../../redux/history/methods'
import { showErrorNotification } from '../../../redux/ui-notifications/methods'
import { useApplicationState } from '../../../hooks/common/use-application-state'
import { SidebarButton } from '../sidebar-button/sidebar-button'
import type { SpecificSidebarEntryProps } from '../types'
import { toggleHistoryEntryPinning } from '../../../../redux/history/methods'
import { showErrorNotification } from '../../../../redux/ui-notifications/methods'
import { useApplicationState } from '../../../../hooks/common/use-application-state'
export const PinNoteSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
useTranslation()
const { id } = useParams<EditorPagePathParams>()
const id = useApplicationState((state) => state.noteDetails.id)
const history = useApplicationState((state) => state.history)
const isPinned = useMemo(() => {

View file

@ -4,21 +4,27 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React, { Fragment, useState } from 'react'
import React, { Fragment, useCallback, useState } from 'react'
import { Trans } from 'react-i18next'
import { RevisionModal } from '../document-bar/revisions/revision-modal'
import { SidebarButton } from './sidebar-button'
import type { SpecificSidebarEntryProps } from './types'
import { RevisionModal } from '../../document-bar/revisions/revision-modal'
import { SidebarButton } from '../sidebar-button/sidebar-button'
import type { SpecificSidebarEntryProps } from '../types'
export const RevisionSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
const [showModal, setShowModal] = useState(false)
const onHide = useCallback(() => {
setShowModal(false)
}, [])
const onShow = useCallback(() => {
setShowModal(true)
}, [])
return (
<Fragment>
<SidebarButton hide={hide} className={className} icon={'history'} onClick={() => setShowModal(true)}>
<SidebarButton hide={hide} className={className} icon={'history'} onClick={onShow}>
<Trans i18nKey={'editor.modal.revision.title'} />
</SidebarButton>
<RevisionModal show={showModal} onHide={() => setShowModal(false)} />
<RevisionModal show={showModal} onHide={onHide} />
</Fragment>
)
}

View file

@ -6,9 +6,9 @@
import React, { Fragment, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { ShareModal } from '../document-bar/share/share-modal'
import { SidebarButton } from './sidebar-button'
import type { SpecificSidebarEntryProps } from './types'
import { ShareModal } from '../../document-bar/share/share-modal'
import { SidebarButton } from '../sidebar-button/sidebar-button'
import type { SpecificSidebarEntryProps } from '../types'
export const ShareSidebarEntry: React.FC<SpecificSidebarEntryProps> = ({ className, hide }) => {
const [showModal, setShowModal] = useState(false)

View file

@ -1,53 +0,0 @@
/*!
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.slide-sidebar {
background: $body-bg;
.sidebar-menu > div {
background: $sidebar-menu-bg;
box-shadow: inset 0 7px 7px -6px $sidebar-menu-shadow;
}
.sidebar-inner {
background: $body-bg;
}
.sidebar-entry {
color: $dark;
&:hover {
background: $entry-hover-bg;
color: $dark;
}
&.sidebar-entry-primary {
background: $primary;
color: $white;
&:hover {
color: $primary;
background: $entry-hover-bg;
}
}
&.icon-highlighted > .sidebar-icon {
color: $orange
}
}
}
@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;
}

View file

@ -1,100 +0,0 @@
/*!
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
$height: 40px;
$menu-width: 175px;
.slide-sidebar {
flex: 0 0 $height;
position: relative;
.sidebar-inner {
height: 100%;
display: flex;
overflow-y: auto;
flex-direction: column;
position: absolute;
z-index: 999;
width: $menu-width;
top: 0;
left: 0;
transition: left 0.3s;
box-shadow: 0 0 0px rgba(0, 0, 0, 0.15);
&:hover, &.show {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
left: (-$menu-width + $height);
}
}
.sidebar-menu {
transition: height 0.2s, flex-basis 0.2s;
display: flex;
flex-direction: column;
overflow: hidden;
flex: 0 1 0;
height: 0;
&.show {
height: 100%;
flex-basis: 100%;
overflow-y: auto;
}
}
.sidebar-entry {
height: $height;
flex: 0 0 $height;
width: 100%;
display: flex;
align-items: center;
border: solid 1px rgba(0, 0, 0, 0.15);
user-select: none;
cursor: pointer;
background: transparent;
padding: 0;
transition: height 0.2s, flex-basis 0.2s;
overflow: hidden;
&.hide {
flex-basis: 0;
height: 0px;
border-width: 0px;
.sidebar-icon {
opacity: 0;
}
.sidebar-text {
opacity: 0;
}
}
.sidebar-icon {
transition: opacity 0.2s;
opacity: 1;
height: $height;
width: $height;
display: inline-flex;
align-items: center;
justify-content: center;
position: relative;
flex: 0 0 40px;
}
.sidebar-text {
height: 100%;
display: flex;
align-items: center;
opacity: 1;
transition: opacity 0.2s;
text-align: left;
flex: 1 1 0;
width: 0;
}
}
}

View file

@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
.slide-sidebar {
@import "./variables.scss";
flex: 0 0 $height;
position: relative;
.sidebar-inner {
height: 100%;
display: flex;
overflow-y: auto;
flex-direction: column;
position: absolute;
z-index: 999;
width: $menu-width;
top: 0;
left: 0;
transition: left 0.3s;
box-shadow: 0 0 0px rgba(0, 0, 0, 0.15);
&:hover, &.show {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
left: (-$menu-width + $height);
}
:global(body.dark) & {
@import "../../../../../global-styles/variables.dark";
background: $body-bg;
}
@import "../../../../../global-styles/variables.light";
background: $body-bg;
}
}

View file

@ -1,21 +0,0 @@
/*!
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
body.dark {
@import "../../../../style/variables.dark";
$entry-hover-bg: lighten($body-bg, 10%);
$sidebar-menu-bg: $body-bg;
$sidebar-menu-shadow: #1d1d1d;
@import "colors";
}
@import "../../../../style/variables.light";
$entry-hover-bg: darken($body-bg, 10%);
$sidebar-menu-bg: $body-bg;
$sidebar-menu-shadow: #bbbbbb;
@import "colors";
@import "layout";

View file

@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
$height: 40px;
$menu-width: 175px;

View file

@ -6,7 +6,6 @@
import type { RefObject } from 'react'
import type { IconName } from '../../common/fork-awesome/types'
import type { SidebarEntryVariant } from './sidebar-button'
import type { PropsWithDataCypressId } from '../../../utils/cypress-attribute'
export interface SpecificSidebarEntryProps {
@ -17,7 +16,6 @@ export interface SpecificSidebarEntryProps {
export interface SidebarEntryProps extends PropsWithDataCypressId {
icon?: IconName
variant?: SidebarEntryVariant
buttonRef?: RefObject<HTMLButtonElement>
hide?: boolean
className?: string

View file

@ -1,4 +1,4 @@
/*!
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only

View file

@ -6,9 +6,9 @@
import React from 'react'
import { UserAvatar } from '../../../common/user-avatar/user-avatar'
import type { ActiveIndicatorStatus } from './active-indicator'
import { ActiveIndicator } from './active-indicator'
import './user-line.scss'
import type { ActiveIndicatorStatus } from '../users-online-sidebar-menu/active-indicator'
import { ActiveIndicator } from '../users-online-sidebar-menu/active-indicator'
import styles from './user-line.module.scss'
export interface UserLineProps {
name: string
@ -20,9 +20,12 @@ export interface UserLineProps {
export const UserLine: React.FC<UserLineProps> = ({ name, photo, color, status }) => {
return (
<div className={'d-flex align-items-center h-100 w-100'}>
<div className='d-inline-flex align-items-bottom user-line-color-indicator' style={{ borderLeftColor: color }} />
<div
className={`d-inline-flex align-items-bottom ${styles['user-line-color-indicator']}`}
style={{ borderLeftColor: color }}
/>
<UserAvatar photo={photo} name={name} additionalClasses={'flex-fill overflow-hidden px-2 text-nowrap w-100'} />
<div className={'active-indicator-container'}>
<div className={styles['active-indicator-container']}>
<ActiveIndicator status={status} />
</div>
</div>

View file

@ -1,4 +1,4 @@
/*!
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only

View file

@ -5,7 +5,7 @@
*/
import React from 'react'
import './active-indicator.scss'
import styles from './active-indicator.module.scss'
export enum ActiveIndicatorStatus {
ACTIVE = 'active',
@ -17,5 +17,5 @@ export interface ActiveIndicatorProps {
}
export const ActiveIndicator: React.FC<ActiveIndicatorProps> = ({ status }) => {
return <span className={`activeIndicator ${status}`} />
return <span className={`${styles['activeIndicator']} ${status}`} />
}

View file

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

View file

@ -1,42 +0,0 @@
/*!
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
body.dark {
@import "../../../../style/variables.dark";
$entry-hover-bg: lighten($body-bg, 10%);
$sidebar-menu-bg: $body-bg;
$sidebar-menu-shadow: #1d1d1d;
@import "../style/colors";
}
@import "../../../../style/variables.light";
$entry-hover-bg: darken($body-bg, 10%);
$sidebar-menu-bg: $body-bg;
$sidebar-menu-shadow: #bbbbbb;
@import "../style/colors";
.slide-sidebar .sidebar-entry.online-entry {
&:hover {
.sidebar-icon:after {
color: $primary;
$shadow-color: #ffffff;
@include text-stroke(#ffffff);
}
}
--users-online: '0';
.sidebar-icon:after {
@include text-stroke($primary);
content: var(--users-online);
position: absolute;
right: 5px;
bottom: 3px;
font-size: 0.9rem;
color: #ffffff;
line-height: 1;
}
}

View file

@ -6,13 +6,14 @@
import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { SidebarButton } from '../sidebar-button'
import { SidebarMenu } from '../sidebar-menu'
import { SidebarButton } from '../sidebar-button/sidebar-button'
import { SidebarMenu } from '../sidebar-menu/sidebar-menu'
import type { SpecificSidebarMenuProps } from '../types'
import { DocumentSidebarMenuSelection } from '../types'
import { ActiveIndicatorStatus } from './active-indicator'
import './online-counter.scss'
import { UserLine } from './user-line'
import styles from './online-counter.module.scss'
import { UserLine } from '../user-line/user-line'
import { useCustomizeAssetsUrl } from '../../../../hooks/common/use-customize-assets-url'
export const UsersOnlineSidebarMenu: React.FC<SpecificSidebarMenuProps> = ({
className,
@ -35,6 +36,8 @@ export const UsersOnlineSidebarMenu: React.FC<SpecificSidebarMenuProps> = ({
onClick(menuId)
}, [menuId, onClick])
const avatarUrl = useCustomizeAssetsUrl() + 'img/avatar.png'
return (
<Fragment>
<SidebarButton
@ -42,21 +45,16 @@ export const UsersOnlineSidebarMenu: React.FC<SpecificSidebarMenuProps> = ({
buttonRef={buttonRef}
onClick={onClickHandler}
icon={expand ? 'arrow-left' : 'users'}
variant={'primary'}
className={`online-entry ${className ?? ''}`}>
className={`${styles['online-entry']} ${className ?? ''}`}
variant={'primary'}>
<Trans i18nKey={'editor.onlineStatus.online'} />
</SidebarButton>
<SidebarMenu expand={expand}>
<SidebarButton>
<UserLine name='Philip Molares' photo='/img/avatar.png' color='red' status={ActiveIndicatorStatus.INACTIVE} />
<UserLine name='Philip Molares' photo={avatarUrl} color='red' status={ActiveIndicatorStatus.INACTIVE} />
</SidebarButton>
<SidebarButton>
<UserLine
name='Tilman Vatteroth'
photo='/img/avatar.png'
color='blue'
status={ActiveIndicatorStatus.ACTIVE}
/>
<UserLine name='Tilman Vatteroth' photo={avatarUrl} color='blue' status={ActiveIndicatorStatus.ACTIVE} />
</SidebarButton>
</SidebarMenu>
</Fragment>