mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-15 07:34:42 -04:00
Add dark mode (#554)
This commit is contained in:
parent
be2428f22c
commit
44637c753e
80 changed files with 2474 additions and 178 deletions
|
@ -47,7 +47,6 @@
|
||||||
"fast-deep-equal": "3.1.3",
|
"fast-deep-equal": "3.1.3",
|
||||||
"flowchart.js": "1.14.1",
|
"flowchart.js": "1.14.1",
|
||||||
"fork-awesome": "1.1.7",
|
"fork-awesome": "1.1.7",
|
||||||
"github-markdown-css": "4.0.0",
|
|
||||||
"highlight.js": "10.2.0",
|
"highlight.js": "10.2.0",
|
||||||
"i18next": "19.7.0",
|
"i18next": "19.7.0",
|
||||||
"i18next-browser-languagedetector": "6.0.1",
|
"i18next-browser-languagedetector": "6.0.1",
|
||||||
|
|
|
@ -9,8 +9,8 @@ export interface LoadingScreenProps {
|
||||||
|
|
||||||
export const LoadingScreen: React.FC<LoadingScreenProps> = ({ failedTitle }) => {
|
export const LoadingScreen: React.FC<LoadingScreenProps> = ({ failedTitle }) => {
|
||||||
return (
|
return (
|
||||||
<div className="loader middle text-white">
|
<div className="loader middle text-light">
|
||||||
<div className="mb-3 text-white">
|
<div className="mb-3 text-light">
|
||||||
<ForkAwesomeIcon icon="file-text" size="5x"
|
<ForkAwesomeIcon icon="file-text" size="5x"
|
||||||
className={failedTitle ? 'animation-shake' : 'animation-pulse'}/>
|
className={failedTitle ? 'animation-shake' : 'animation-pulse'}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
20
src/components/common/apply-dark-mode/apply-dark-mode.tsx
Normal file
20
src/components/common/apply-dark-mode/apply-dark-mode.tsx
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import React, { useEffect } from 'react'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
import { ApplicationState } from '../../../redux'
|
||||||
|
|
||||||
|
export const ApplyDarkMode: React.FC = () => {
|
||||||
|
const darkModeActivated = useSelector((state: ApplicationState) => state.darkMode.darkMode)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (darkModeActivated) {
|
||||||
|
window.document.body.classList.add('dark')
|
||||||
|
} else {
|
||||||
|
window.document.body.classList.remove('dark')
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
window.document.body.classList.remove('dark')
|
||||||
|
}
|
||||||
|
}, [darkModeActivated])
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ export const MotdBanner: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<ShowIf condition={bannerState.show}>
|
<ShowIf condition={bannerState.show}>
|
||||||
<Alert variant='primary' dir='auto' className='mb-0 text-center d-flex flex-row justify-content-center'>
|
<Alert variant='primary' dir='auto' className='mb-0 text-center d-flex flex-row justify-content-center'>
|
||||||
<Link to='/s/banner' className='flex-grow-1 align-self-center'>
|
<Link to='/s/banner' className='flex-grow-1 align-self-center text-black'>
|
||||||
{bannerState.text}
|
{bannerState.text}
|
||||||
</Link>
|
</Link>
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { LandingLayout } from '../../landing-layout/landing-layout'
|
||||||
export const NotFoundErrorScreen: React.FC = () => {
|
export const NotFoundErrorScreen: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<LandingLayout>
|
<LandingLayout>
|
||||||
<div className='text-white d-flex align-items-center justify-content-center my-5'>
|
<div className='text-light d-flex align-items-center justify-content-center my-5'>
|
||||||
<h1>404 Not Found <small>oops.</small></h1>
|
<h1>404 Not Found <small>oops.</small></h1>
|
||||||
</div>
|
</div>
|
||||||
</LandingLayout>
|
</LandingLayout>
|
||||||
|
|
|
@ -9,7 +9,7 @@ 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'
|
||||||
import { SignInButton } from '../../landing-layout/navigation/sign-in-button'
|
import { SignInButton } from '../../landing-layout/navigation/sign-in-button'
|
||||||
import { UserDropdown } from '../../landing-layout/navigation/user-dropdown'
|
import { UserDropdown } from '../../landing-layout/navigation/user-dropdown'
|
||||||
import { SyncScrollButton } from './sync-scroll-button/sync-scroll-button'
|
import { SyncScrollButtons } from './sync-scroll-buttons/sync-scroll-buttons'
|
||||||
import { EditorPathParams } from '../editor'
|
import { EditorPathParams } from '../editor'
|
||||||
import { DarkModeButton } from './dark-mode-button'
|
import { DarkModeButton } from './dark-mode-button'
|
||||||
import { EditorViewMode } from './editor-view-mode'
|
import { EditorViewMode } from './editor-view-mode'
|
||||||
|
@ -26,7 +26,7 @@ export const AppBar: React.FC = () => {
|
||||||
<Nav className="mr-auto d-flex align-items-center">
|
<Nav className="mr-auto d-flex align-items-center">
|
||||||
<NavbarBranding/>
|
<NavbarBranding/>
|
||||||
<EditorViewMode/>
|
<EditorViewMode/>
|
||||||
<SyncScrollButton/>
|
<SyncScrollButtons/>
|
||||||
<DarkModeButton/>
|
<DarkModeButton/>
|
||||||
<Link to={`/p/${id}`} target='_blank'>
|
<Link to={`/p/${id}`} target='_blank'>
|
||||||
<Button title={t('editor.documentBar.slideMode')} className="ml-2 text-secondary" size="sm" variant="outline-light">
|
<Button title={t('editor.documentBar.slideMode')} className="ml-2 text-secondary" size="sm" variant="outline-light">
|
||||||
|
|
|
@ -1,27 +1,29 @@
|
||||||
import React, { useState } from 'react'
|
import React from 'react'
|
||||||
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
|
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
import { ApplicationState } from '../../../redux'
|
||||||
|
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'
|
||||||
|
|
||||||
const DarkModeButton: React.FC = () => {
|
const DarkModeButton: React.FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [buttonState, setButtonState] = useState(false)
|
const darkModeEnabled = useSelector((state: ApplicationState) => state.darkMode.darkMode)
|
||||||
const buttonToggle = () => {
|
|
||||||
setButtonState(prevState => !prevState)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToggleButtonGroup type="checkbox" defaultValue={[]} name="dark-mode" className="ml-2" value={buttonState ? ['dark'] : ['']}>
|
<ToggleButtonGroup
|
||||||
<ToggleButton
|
type="radio"
|
||||||
title={ buttonState ? t('editor.darkMode.switchToLight') : t('editor.darkMode.switchToDark')}
|
name="dark-mode"
|
||||||
variant={ buttonState ? 'secondary' : 'light' }
|
value={darkModeEnabled}
|
||||||
className={ buttonState ? 'text-white' : 'text-secondary' }
|
className="ml-2"
|
||||||
onChange={buttonToggle} value={'dark'}
|
onChange={(value: boolean) => {
|
||||||
>
|
setDarkMode(value)
|
||||||
{buttonState
|
}}>
|
||||||
? <ForkAwesomeIcon icon="sun"/>
|
<ToggleButton value={true} variant="outline-secondary" title={t('editor.darkMode.switchToDark')}>
|
||||||
: <ForkAwesomeIcon icon="moon"/>
|
<ForkAwesomeIcon icon="moon"/>
|
||||||
}
|
</ToggleButton>
|
||||||
|
<ToggleButton value={false} variant="outline-secondary" title={t('editor.darkMode.switchToLight')}>
|
||||||
|
<ForkAwesomeIcon icon="sun-o"/>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
</ToggleButtonGroup>
|
</ToggleButtonGroup>
|
||||||
)
|
)
|
||||||
|
|
|
@ -40,30 +40,24 @@ export const HelpButton: React.FC = () => {
|
||||||
<ForkAwesomeIcon icon="question-circle"/> <Trans i18nKey={'editor.documentBar.help'}/> – <Trans i18nKey={`editor.help.${tab}`}/>
|
<ForkAwesomeIcon icon="question-circle"/> <Trans i18nKey={'editor.documentBar.help'}/> – <Trans i18nKey={`editor.help.${tab}`}/>
|
||||||
</Modal.Title>
|
</Modal.Title>
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body className="text-dark">
|
<Modal.Body>
|
||||||
<ul className='nav nav-tabs'>
|
<nav className='nav nav-tabs'>
|
||||||
<li className='nav-item'>
|
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Cheatsheet ? 'active' : ''}`}
|
||||||
<button className={`nav-link ${tab === HelpTabStatus.Cheatsheet ? 'active' : ''}`}
|
|
||||||
onClick={() => setTab(HelpTabStatus.Cheatsheet)}
|
onClick={() => setTab(HelpTabStatus.Cheatsheet)}
|
||||||
>
|
>
|
||||||
<Trans i18nKey={'editor.help.cheatsheet.title'}/>
|
<Trans i18nKey={'editor.help.cheatsheet.title'}/>
|
||||||
</button>
|
</Button>
|
||||||
</li>
|
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Shortcuts ? 'active' : ''}`}
|
||||||
<li className='nav-item'>
|
|
||||||
<button className={`nav-link ${tab === HelpTabStatus.Shortcuts ? 'active' : ''}`}
|
|
||||||
onClick={() => setTab(HelpTabStatus.Shortcuts)}
|
onClick={() => setTab(HelpTabStatus.Shortcuts)}
|
||||||
>
|
>
|
||||||
<Trans i18nKey={'editor.help.shortcuts.title'}/>
|
<Trans i18nKey={'editor.help.shortcuts.title'}/>
|
||||||
</button>
|
</Button>
|
||||||
</li>
|
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Links ? 'active' : ''}`}
|
||||||
<li className='nav-item'>
|
|
||||||
<button className={`nav-link ${tab === HelpTabStatus.Links ? 'active' : ''}`}
|
|
||||||
onClick={() => setTab(HelpTabStatus.Links)}
|
onClick={() => setTab(HelpTabStatus.Links)}
|
||||||
>
|
>
|
||||||
<Trans i18nKey={'editor.help.links.title'}/>
|
<Trans i18nKey={'editor.help.links.title'}/>
|
||||||
</button>
|
</Button>
|
||||||
</li>
|
</nav>
|
||||||
</ul>
|
|
||||||
{tabContent()}
|
{tabContent()}
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react'
|
import React, { Fragment } from 'react'
|
||||||
import { Card, ListGroup, Row } from 'react-bootstrap'
|
import { Card, ListGroup, Row } from 'react-bootstrap'
|
||||||
import { Trans } from 'react-i18next'
|
import { Trans } from 'react-i18next'
|
||||||
import { isMac } from '../../utils'
|
import { isMac } from '../../utils'
|
||||||
|
@ -25,14 +25,19 @@ export const Shortcut: React.FC = () => {
|
||||||
<Row className={'justify-content-center pt-4'}>
|
<Row className={'justify-content-center pt-4'}>
|
||||||
{Object.keys(shortcutMap).map(category => {
|
{Object.keys(shortcutMap).map(category => {
|
||||||
return (
|
return (
|
||||||
<Card className={'m-2 w-50'}>
|
<Card key={category} className={'m-2 w-50'}>
|
||||||
<Card.Header>{category}</Card.Header>
|
<Card.Header>{category}</Card.Header>
|
||||||
<ListGroup variant="flush">
|
<ListGroup variant="flush">
|
||||||
{Object.entries(shortcutMap[category]).map(([functionName, shortcut]) => {
|
{Object.entries(shortcutMap[category]).map(([functionName, shortcuts]) => {
|
||||||
return (
|
return (
|
||||||
<ListGroup.Item key={functionName} className={'d-flex justify-content-between'}>
|
<ListGroup.Item key={functionName} className={'d-flex justify-content-between'}>
|
||||||
<span><Trans i18nKey={functionName}/></span>
|
<span><Trans i18nKey={functionName}/></span>
|
||||||
<span>{shortcut}</span>
|
<span>
|
||||||
|
{
|
||||||
|
shortcuts.map((shortcut, shortcutIndex) =>
|
||||||
|
<Fragment key={shortcutIndex}>{shortcut}</Fragment>)
|
||||||
|
}
|
||||||
|
</span>
|
||||||
</ListGroup.Item>
|
</ListGroup.Item>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
import React, { useCallback } from 'react'
|
|
||||||
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import { useSelector } from 'react-redux'
|
|
||||||
import { ApplicationState } from '../../../../redux'
|
|
||||||
import { setEditorSyncScroll } from '../../../../redux/editor/methods'
|
|
||||||
import disabledScroll from './disabledScroll.svg'
|
|
||||||
import enabledScroll from './enabledScroll.svg'
|
|
||||||
|
|
||||||
export const SyncScrollButton: React.FC = () => {
|
|
||||||
const syncScroll: boolean = useSelector((state: ApplicationState) => state.editorConfig.syncScroll)
|
|
||||||
const translation = syncScroll ? 'editor.appBar.syncScroll.enable' : 'editor.appBar.syncScroll.disable'
|
|
||||||
const onClick = useCallback(() => {
|
|
||||||
setEditorSyncScroll(!syncScroll)
|
|
||||||
}, [syncScroll])
|
|
||||||
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ToggleButtonGroup type="checkbox" defaultValue={[]} name="sync-scroll" className="ml-2" value={[syncScroll]}>
|
|
||||||
<ToggleButton
|
|
||||||
title={ t(translation) }
|
|
||||||
variant={syncScroll ? 'secondary' : 'light'}
|
|
||||||
onChange={onClick} value={true}
|
|
||||||
>
|
|
||||||
<img src={syncScroll ? disabledScroll : enabledScroll} width={'20px'} alt={t(translation)}/>
|
|
||||||
</ToggleButton>
|
|
||||||
</ToggleButtonGroup>
|
|
||||||
)
|
|
||||||
}
|
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
|
@ -0,0 +1,33 @@
|
||||||
|
.sync-scroll-buttons {
|
||||||
|
svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
svg g {
|
||||||
|
@import "../../../../style/light.scss";
|
||||||
|
fill: $secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active, &:hover {
|
||||||
|
svg g {
|
||||||
|
@import "../../../../style/light.scss";
|
||||||
|
fill: $light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark & {
|
||||||
|
svg g {
|
||||||
|
@import "../../../../style/dark.scss";
|
||||||
|
fill: $secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active, &:hover {
|
||||||
|
svg g {
|
||||||
|
@import "../../../../style/dark.scss";
|
||||||
|
fill: $light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
import { ApplicationState } from '../../../../redux'
|
||||||
|
import { setEditorSyncScroll } from '../../../../redux/editor/methods'
|
||||||
|
import { ReactComponent as DisabledScrollIcon } from './disabledScroll.svg'
|
||||||
|
import { ReactComponent as EnabledScrollIcon } from './enabledScroll.svg'
|
||||||
|
import './sync-scroll-buttons.scss'
|
||||||
|
|
||||||
|
export const SyncScrollButtons: React.FC = () => {
|
||||||
|
const syncScroll: boolean = useSelector((state: ApplicationState) => state.editorConfig.syncScroll)
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ToggleButtonGroup type="radio" defaultValue={[]} name="sync-scroll" className={'ml-2 sync-scroll-buttons'}
|
||||||
|
value={[syncScroll]}>
|
||||||
|
<ToggleButton
|
||||||
|
variant={'outline-secondary'}
|
||||||
|
title={t('editor.appBar.syncScroll.enable')}
|
||||||
|
onChange={() => setEditorSyncScroll(true)} value={true}
|
||||||
|
>
|
||||||
|
<EnabledScrollIcon/>
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
variant={'outline-secondary'}
|
||||||
|
title={t('editor.appBar.syncScroll.disable')}
|
||||||
|
onChange={() => setEditorSyncScroll(false)} value={false}
|
||||||
|
>
|
||||||
|
<DisabledScrollIcon/>
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
.upper-case {
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
|
@ -2,14 +2,13 @@ import React from 'react'
|
||||||
import { Dropdown } from 'react-bootstrap'
|
import { Dropdown } from 'react-bootstrap'
|
||||||
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
|
import { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
|
||||||
import { ActiveIndicatorStatus } from './active-indicator'
|
import { ActiveIndicatorStatus } from './active-indicator'
|
||||||
import './connection-indicator.scss'
|
|
||||||
import { UserLine } from './user-line'
|
import { UserLine } from './user-line'
|
||||||
|
|
||||||
const ConnectionIndicator: React.FC = () => {
|
const ConnectionIndicator: React.FC = () => {
|
||||||
const userOnline = 2
|
const userOnline = 2
|
||||||
return (
|
return (
|
||||||
<Dropdown className="small mx-2" alignRight>
|
<Dropdown className="small mx-2" alignRight>
|
||||||
<Dropdown.Toggle id="connection-indicator" size="sm" variant="primary" className="upper-case">
|
<Dropdown.Toggle id="connection-indicator" size="sm" variant="primary" className="text-uppercase">
|
||||||
<ForkAwesomeIcon icon="users" className={'mr-1'}/> {userOnline} Online
|
<ForkAwesomeIcon icon="users" className={'mr-1'}/> {userOnline} Online
|
||||||
</Dropdown.Toggle>
|
</Dropdown.Toggle>
|
||||||
<Dropdown.Menu>
|
<Dropdown.Menu>
|
||||||
|
|
|
@ -2,9 +2,11 @@ import React, { useEffect, useRef, useState } from 'react'
|
||||||
import { Alert, Col, ListGroup, Modal, Row, Button } from 'react-bootstrap'
|
import { Alert, Col, ListGroup, Modal, Row, Button } from 'react-bootstrap'
|
||||||
import ReactDiffViewer, { DiffMethod } from 'react-diff-viewer'
|
import ReactDiffViewer, { DiffMethod } from 'react-diff-viewer'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
import { useParams } from 'react-router'
|
import { useParams } from 'react-router'
|
||||||
import { getAllRevisions, getRevision, Revision, RevisionListEntry } from '../../../../api/revisions'
|
import { getAllRevisions, getRevision, Revision, RevisionListEntry } from '../../../../api/revisions'
|
||||||
import { UserResponse } from '../../../../api/users/types'
|
import { UserResponse } from '../../../../api/users/types'
|
||||||
|
import { ApplicationState } from '../../../../redux'
|
||||||
import { CommonModal, CommonModalProps } from '../../../common/modals/common-modal'
|
import { CommonModal, CommonModalProps } from '../../../common/modals/common-modal'
|
||||||
import { ShowIf } from '../../../common/show-if/show-if'
|
import { ShowIf } from '../../../common/show-if/show-if'
|
||||||
import { RevisionButtonProps } from './revision-button'
|
import { RevisionButtonProps } from './revision-button'
|
||||||
|
@ -20,6 +22,7 @@ export const RevisionModal: React.FC<CommonModalProps & RevisionButtonProps> = (
|
||||||
const [error, setError] = useState(false)
|
const [error, setError] = useState(false)
|
||||||
const revisionAuthorListMap = useRef(new Map<number, UserResponse[]>())
|
const revisionAuthorListMap = useRef(new Map<number, UserResponse[]>())
|
||||||
const revisionCacheMap = useRef(new Map<number, Revision>())
|
const revisionCacheMap = useRef(new Map<number, Revision>())
|
||||||
|
const darkModeEnabled = useSelector((state: ApplicationState) => state.darkMode.darkMode)
|
||||||
const { id } = useParams<{ id: string }>()
|
const { id } = useParams<{ id: string }>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -81,7 +84,7 @@ export const RevisionModal: React.FC<CommonModalProps & RevisionButtonProps> = (
|
||||||
newValue={noteContent}
|
newValue={noteContent}
|
||||||
splitView={false}
|
splitView={false}
|
||||||
compareMethod={DiffMethod.WORDS}
|
compareMethod={DiffMethod.WORDS}
|
||||||
useDarkTheme={false}
|
useDarkTheme={darkModeEnabled}
|
||||||
/>
|
/>
|
||||||
</ShowIf>
|
</ShowIf>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
@ -12,8 +12,3 @@
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-toolbar .btn {
|
|
||||||
padding: 0.1875rem 0.5rem;
|
|
||||||
min-width: 30px;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
.btn-toolbar {
|
.btn-toolbar {
|
||||||
border: 1px solid #ededed;
|
border-bottom: 1px solid #ededed;
|
||||||
|
border-top: 1px solid #ededed;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
padding: 0.1875rem 0.5rem;
|
||||||
|
min-width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-group:not(:last-of-type)::after {
|
.btn-group:not(:last-of-type)::after {
|
||||||
background-color: #e2e6ea;
|
background-color: #e2e6ea;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { useSelector } from 'react-redux'
|
||||||
import useMedia from 'use-media'
|
import useMedia from 'use-media'
|
||||||
import { ApplicationState } from '../../redux'
|
import { ApplicationState } from '../../redux'
|
||||||
import { setEditorMode } from '../../redux/editor/methods'
|
import { setEditorMode } from '../../redux/editor/methods'
|
||||||
|
import { ApplyDarkMode } from '../common/apply-dark-mode/apply-dark-mode'
|
||||||
import { DocumentTitle } from '../common/document-title/document-title'
|
import { DocumentTitle } from '../common/document-title/document-title'
|
||||||
import { MotdBanner } from '../common/motd-banner/motd-banner'
|
import { MotdBanner } from '../common/motd-banner/motd-banner'
|
||||||
import { AppBar } from './app-bar/app-bar'
|
import { AppBar } from './app-bar/app-bar'
|
||||||
|
@ -109,6 +110,7 @@ export const Editor: React.FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
<ApplyDarkMode/>
|
||||||
<MotdBanner/>
|
<MotdBanner/>
|
||||||
<DocumentTitle title={documentTitle}/>
|
<DocumentTitle title={documentTitle}/>
|
||||||
<div className={'d-flex flex-column vh-100'}>
|
<div className={'d-flex flex-column vh-100'}>
|
||||||
|
|
|
@ -119,8 +119,21 @@ https://asciinema.org/a/117928
|
||||||
|
|
||||||
## Code highlighting
|
## Code highlighting
|
||||||
\`\`\`javascript=
|
\`\`\`javascript=
|
||||||
|
var s = "JavaScript syntax highlighting";
|
||||||
let a = 1
|
alert(s);
|
||||||
|
function $initHighlight(block, cls) {
|
||||||
|
try {
|
||||||
|
if (cls.search(/\\bno\\-highlight\\b/) != -1)
|
||||||
|
return process(block, true, 0x0F) +
|
||||||
|
' class=""';
|
||||||
|
} catch (e) {
|
||||||
|
/* handle exception */
|
||||||
|
}
|
||||||
|
for (var i = 0 / 2; i < classes.length; i++) {
|
||||||
|
if (checkCondition(classes[i]) === undefined)
|
||||||
|
return /\\d+[\\s/]/g;
|
||||||
|
}
|
||||||
|
}
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
## PlantUML
|
## PlantUML
|
||||||
|
|
|
@ -4,4 +4,9 @@
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
cursor: col-resize;
|
cursor: col-resize;
|
||||||
box-shadow: 3px 0 6px #e7e7e7;
|
box-shadow: 3px 0 6px #e7e7e7;
|
||||||
|
|
||||||
|
body.dark & {
|
||||||
|
box-shadow: 3px 0 6px #7b7b7b;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|
||||||
&.sticky {
|
&.sticky {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
}
|
}
|
||||||
|
@ -11,10 +12,12 @@
|
||||||
> a {
|
> a {
|
||||||
padding: 4px 20px;
|
padding: 4px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> ul > li {
|
> ul > li {
|
||||||
> a {
|
> a {
|
||||||
padding: 1px 0 1px 30px;
|
padding: 1px 0 1px 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> ul > li {
|
> ul > li {
|
||||||
> a {
|
> a {
|
||||||
padding: 1px 0 1px 38px;
|
padding: 1px 0 1px 38px;
|
||||||
|
@ -49,6 +52,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-toc-sidebar-button {
|
.markdown-toc-sidebar-button {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 40px;
|
right: 40px;
|
||||||
|
|
|
@ -32,8 +32,8 @@ export class ErrorBoundary extends Component {
|
||||||
render (): ReactElement | undefined | null | string | number | boolean | Record<string, unknown> | ReactNodeArray {
|
render (): ReactElement | undefined | null | string | number | boolean | Record<string, unknown> | ReactNodeArray {
|
||||||
if (this.state.hasError) {
|
if (this.state.hasError) {
|
||||||
return (
|
return (
|
||||||
<Container className="text-white d-flex flex-column mvh-100">
|
<Container className="text-light d-flex flex-column mvh-100">
|
||||||
<div className='text-white d-flex flex-column align-items-center justify-content-center my-5'>
|
<div className='text-light d-flex flex-column align-items-center justify-content-center my-5'>
|
||||||
<h1>An unknown error occurred</h1>
|
<h1>An unknown error occurred</h1>
|
||||||
<p>Don't worry, this happens sometimes. If this is the first time you see this page then try reloading the app.</p>
|
<p>Don't worry, this happens sometimes. If this is the first time you see this page then try reloading the app.</p>
|
||||||
If you can reproduce this error, then we would be glad if you 
|
If you can reproduce this error, then we would be glad if you 
|
||||||
|
|
|
@ -18,4 +18,3 @@
|
||||||
content: initial;
|
content: initial;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { SocialLink } from './social-links'
|
||||||
|
|
||||||
export const Footer: React.FC = () => {
|
export const Footer: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<footer className="text-white-50 small">
|
<footer className="text-light-50 small">
|
||||||
<LanguagePicker/>
|
<LanguagePicker/>
|
||||||
<PoweredByLinks/>
|
<PoweredByLinks/>
|
||||||
<SocialLink/>
|
<SocialLink/>
|
||||||
|
|
|
@ -35,7 +35,9 @@ export const VersionInfo: React.FC = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Link id='version' to={'#'} className={'text-light'} onClick={handleShow}><Trans i18nKey={'landing.versionInfo.versionInfo'}/></Link>
|
<Link id='version' to={'#'} className={'text-light'} onClick={handleShow}>
|
||||||
|
<Trans i18nKey={'landing.versionInfo.versionInfo'}/>
|
||||||
|
</Link>
|
||||||
<Modal id='versionModal' show={show} onHide={handleClose} animation={true}>
|
<Modal id='versionModal' show={show} onHide={handleClose} animation={true}>
|
||||||
<Modal.Body className="text-dark">
|
<Modal.Body className="text-dark">
|
||||||
<h3><Trans i18nKey={'landing.versionInfo.title'}/></h3>
|
<h3><Trans i18nKey={'landing.versionInfo.title'}/></h3>
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { HeaderBar } from './navigation/header-bar/header-bar'
|
||||||
|
|
||||||
export const LandingLayout: React.FC = ({ children }) => {
|
export const LandingLayout: React.FC = ({ children }) => {
|
||||||
return (
|
return (
|
||||||
<Container className="text-white d-flex flex-column mvh-100">
|
<Container className="text-light d-flex flex-column mvh-100">
|
||||||
<DocumentTitle/>
|
<DocumentTitle/>
|
||||||
<MotdBanner/>
|
<MotdBanner/>
|
||||||
<HeaderBar/>
|
<HeaderBar/>
|
||||||
|
|
|
@ -35,7 +35,7 @@ export const ViaInternal: React.FC = () => {
|
||||||
type="text"
|
type="text"
|
||||||
size="sm"
|
size="sm"
|
||||||
placeholder={t('login.auth.username')}
|
placeholder={t('login.auth.username')}
|
||||||
onChange={(event) => setUsername(event.currentTarget.value)} className="bg-dark text-white"
|
onChange={(event) => setUsername(event.currentTarget.value)} className="bg-dark text-light"
|
||||||
autoComplete='username'
|
autoComplete='username'
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
@ -47,7 +47,7 @@ export const ViaInternal: React.FC = () => {
|
||||||
size="sm"
|
size="sm"
|
||||||
placeholder={t('login.auth.password')}
|
placeholder={t('login.auth.password')}
|
||||||
onChange={(event) => setPassword(event.currentTarget.value)}
|
onChange={(event) => setPassword(event.currentTarget.value)}
|
||||||
className="bg-dark text-white"
|
className="bg-dark text-light"
|
||||||
autoComplete='current-password'
|
autoComplete='current-password'
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
|
@ -37,7 +37,7 @@ export const ViaLdap: React.FC = () => {
|
||||||
type="text"
|
type="text"
|
||||||
size="sm"
|
size="sm"
|
||||||
placeholder={t('login.auth.username')}
|
placeholder={t('login.auth.username')}
|
||||||
onChange={(event) => setUsername(event.currentTarget.value)} className="bg-dark text-white"
|
onChange={(event) => setUsername(event.currentTarget.value)} className="bg-dark text-light"
|
||||||
autoComplete='username'
|
autoComplete='username'
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
@ -49,7 +49,7 @@ export const ViaLdap: React.FC = () => {
|
||||||
size="sm"
|
size="sm"
|
||||||
placeholder={t('login.auth.password')}
|
placeholder={t('login.auth.password')}
|
||||||
onChange={(event) => setPassword(event.currentTarget.value)}
|
onChange={(event) => setPassword(event.currentTarget.value)}
|
||||||
className="bg-dark text-white"
|
className="bg-dark text-light"
|
||||||
autoComplete='current-password'
|
autoComplete='current-password'
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
|
@ -33,7 +33,7 @@ export const ViaOpenId: React.FC = () => {
|
||||||
size="sm"
|
size="sm"
|
||||||
placeholder={'OpenID'}
|
placeholder={'OpenID'}
|
||||||
onChange={(event) => setOpenId(event.currentTarget.value)}
|
onChange={(event) => setOpenId(event.currentTarget.value)}
|
||||||
className="bg-dark text-white"
|
className="bg-dark text-light"
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
|
|
1013
src/components/markdown-renderer/github-markdown.scss
Normal file
1013
src/components/markdown-renderer/github-markdown.scss
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
@import '../../../node_modules/github-markdown-css/github-markdown.css';
|
@import './github-markdown';
|
||||||
|
|
||||||
.markdown-body {
|
.markdown-body {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -14,6 +14,6 @@ export const AbcFrame: React.FC<AbcFrameProps> = ({ code }) => {
|
||||||
}, [code])
|
}, [code])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={container}/>
|
<div ref={container} className={'bg-white text-center'}/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ export const CsvTable: React.FC<CsvTableProps> = ({ code, delimiter, showHeader,
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<table className={'csv-html-table'}>
|
<table className={'csv-html-table table-striped'}>
|
||||||
{renderTableHeader(headerRow)}
|
{renderTableHeader(headerRow)}
|
||||||
{renderTableBody(rowsWithColumns)}
|
{renderTableBody(rowsWithColumns)}
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -1,9 +1,21 @@
|
||||||
.markdown-body {
|
.markdown-body {
|
||||||
@import '../../../../../../node_modules/highlight.js/styles/github-gist.css';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-body code.hljs {
|
.markdown-body {
|
||||||
|
@import '../../../../../../node_modules/highlight.js/styles/github';
|
||||||
|
|
||||||
|
body.dark & {
|
||||||
|
@import '../../../../../../node_modules/highlight.js/styles/tomorrow-night';
|
||||||
|
}
|
||||||
|
|
||||||
|
code.hljs {
|
||||||
|
background-color: rgba(27, 31, 35, .05);
|
||||||
|
body.dark & {
|
||||||
|
background-color: rgb(27, 31, 35);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark &, & {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto minmax(0, 1fr);
|
grid-template-columns: auto minmax(0, 1fr);
|
||||||
|
@ -38,5 +50,6 @@
|
||||||
&.wrapLines .codeline {
|
&.wrapLines .codeline {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ export const DeprecationWarning: React.FC = () => {
|
||||||
<Alert className={'mt-2'} variant={'warning'}>
|
<Alert className={'mt-2'} variant={'warning'}>
|
||||||
<Trans i18nKey={'renderer.sequence.deprecationWarning'}/>
|
<Trans i18nKey={'renderer.sequence.deprecationWarning'}/>
|
||||||
|
|
||||||
<TranslatedExternalLink i18nKey={'common.why'} className={'text-dark'} href={links.faq}/>
|
<TranslatedExternalLink i18nKey={'common.why'} className={'text-primary'} href={links.faq}/>
|
||||||
</Alert>
|
</Alert>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ export const ProfileChangePassword: React.FC = () => {
|
||||||
<Form.Control
|
<Form.Control
|
||||||
type="password"
|
type="password"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="bg-dark text-white"
|
className="bg-dark text-light"
|
||||||
required
|
required
|
||||||
onChange={(event) => setOldPassword(event.target.value)}
|
onChange={(event) => setOldPassword(event.target.value)}
|
||||||
/>
|
/>
|
||||||
|
@ -49,7 +49,7 @@ export const ProfileChangePassword: React.FC = () => {
|
||||||
<Form.Control
|
<Form.Control
|
||||||
type="password"
|
type="password"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="bg-dark text-white"
|
className="bg-dark text-light"
|
||||||
required
|
required
|
||||||
onChange={onChangeNewPassword}
|
onChange={onChangeNewPassword}
|
||||||
isValid={newPasswordValid}
|
isValid={newPasswordValid}
|
||||||
|
@ -61,7 +61,7 @@ export const ProfileChangePassword: React.FC = () => {
|
||||||
<Form.Control
|
<Form.Control
|
||||||
type="password"
|
type="password"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="bg-dark text-white"
|
className="bg-dark text-light"
|
||||||
required
|
required
|
||||||
onChange={onChangeNewPasswordAgain}
|
onChange={onChangeNewPasswordAgain}
|
||||||
isValid={newPasswordAgainValid}
|
isValid={newPasswordAgainValid}
|
||||||
|
|
|
@ -53,7 +53,7 @@ export const ProfileDisplayName: React.FC = () => {
|
||||||
size="sm"
|
size="sm"
|
||||||
placeholder={t('profile.displayName')}
|
placeholder={t('profile.displayName')}
|
||||||
value={displayName}
|
value={displayName}
|
||||||
className="bg-dark text-white"
|
className="bg-dark text-light"
|
||||||
onChange={changeNameField}
|
onChange={changeNameField}
|
||||||
isValid={submittable}
|
isValid={submittable}
|
||||||
isInvalid={error}
|
isInvalid={error}
|
||||||
|
|
|
@ -70,7 +70,7 @@ export const RegisterPage: React.FC = () => {
|
||||||
isValid={username !== ''}
|
isValid={username !== ''}
|
||||||
onChange={(event) => setUsername(event.target.value)}
|
onChange={(event) => setUsername(event.target.value)}
|
||||||
placeholder={t('login.auth.username')}
|
placeholder={t('login.auth.username')}
|
||||||
className='bg-dark text-white'
|
className='bg-dark text-light'
|
||||||
autoComplete='username'
|
autoComplete='username'
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
required
|
required
|
||||||
|
@ -85,7 +85,7 @@ export const RegisterPage: React.FC = () => {
|
||||||
isValid={password !== '' && password.length >= 8}
|
isValid={password !== '' && password.length >= 8}
|
||||||
onChange={(event) => setPassword(event.target.value)}
|
onChange={(event) => setPassword(event.target.value)}
|
||||||
placeholder={t('login.auth.password')}
|
placeholder={t('login.auth.password')}
|
||||||
className='bg-dark text-white'
|
className='bg-dark text-light'
|
||||||
minLength={8}
|
minLength={8}
|
||||||
autoComplete='new-password'
|
autoComplete='new-password'
|
||||||
required
|
required
|
||||||
|
@ -101,7 +101,7 @@ export const RegisterPage: React.FC = () => {
|
||||||
isValid={passwordAgain !== '' && password === passwordAgain}
|
isValid={passwordAgain !== '' && password === passwordAgain}
|
||||||
onChange={(event) => setPasswordAgain(event.target.value)}
|
onChange={(event) => setPasswordAgain(event.target.value)}
|
||||||
placeholder={t('login.register.passwordAgain')}
|
placeholder={t('login.register.passwordAgain')}
|
||||||
className='bg-dark text-white'
|
className='bg-dark text-light'
|
||||||
autoComplete='new-password'
|
autoComplete='new-password'
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { RegisterPage } from './components/register-page/register-page'
|
||||||
import { store } from './redux'
|
import { store } from './redux'
|
||||||
import * as serviceWorker from './service-worker'
|
import * as serviceWorker from './service-worker'
|
||||||
import './style/index.scss'
|
import './style/index.scss'
|
||||||
|
import './style/dark.scss'
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
|
|
45
src/redux/dark-mode/methods.ts
Normal file
45
src/redux/dark-mode/methods.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import { store } from '..'
|
||||||
|
import { DarkModeConfig, DarkModeConfigActionType, SetDarkModeConfigAction } from './types'
|
||||||
|
|
||||||
|
export const setDarkMode = (darkMode: boolean): void => {
|
||||||
|
const action: SetDarkModeConfigAction = {
|
||||||
|
type: DarkModeConfigActionType.SET_DARK_MODE,
|
||||||
|
darkMode: darkMode
|
||||||
|
}
|
||||||
|
store.dispatch(action)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const saveToLocalStorage = (darkModeConfig: DarkModeConfig): void => {
|
||||||
|
try {
|
||||||
|
window.localStorage.setItem('nightMode', String(darkModeConfig.darkMode))
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Saving dark-mode setting to local storage failed: ', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const loadFromLocalStorage = (): DarkModeConfig | undefined => {
|
||||||
|
try {
|
||||||
|
const storedValue = window.localStorage.getItem('nightMode')
|
||||||
|
if (!storedValue) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
darkMode: storedValue === 'true'
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Loading dark-mode setting from local storage failed: ', e)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const determineDarkModeBrowserSetting = (): DarkModeConfig | undefined => {
|
||||||
|
try {
|
||||||
|
const mediaQueryResult = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||||
|
return {
|
||||||
|
darkMode: mediaQueryResult
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Can not determine dark-mode setting from browser: ', e)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
26
src/redux/dark-mode/reducers.ts
Normal file
26
src/redux/dark-mode/reducers.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { Reducer } from 'redux'
|
||||||
|
import { determineDarkModeBrowserSetting, loadFromLocalStorage, saveToLocalStorage } from './methods'
|
||||||
|
import { DarkModeConfig, DarkModeConfigActions, DarkModeConfigActionType, SetDarkModeConfigAction } from './types'
|
||||||
|
|
||||||
|
export const getInitialState = (): DarkModeConfig => {
|
||||||
|
const initialMode = loadFromLocalStorage() ?? determineDarkModeBrowserSetting() ?? {
|
||||||
|
darkMode: false
|
||||||
|
}
|
||||||
|
saveToLocalStorage(initialMode)
|
||||||
|
return initialMode
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DarkModeConfigReducer: Reducer<DarkModeConfig, DarkModeConfigActions> = (state: DarkModeConfig = getInitialState(), action: DarkModeConfigActions) => {
|
||||||
|
let darkModeConfigState: DarkModeConfig
|
||||||
|
switch (action.type) {
|
||||||
|
case DarkModeConfigActionType.SET_DARK_MODE:
|
||||||
|
darkModeConfigState = {
|
||||||
|
...state,
|
||||||
|
darkMode: (action as SetDarkModeConfigAction).darkMode
|
||||||
|
}
|
||||||
|
saveToLocalStorage(darkModeConfigState)
|
||||||
|
return darkModeConfigState
|
||||||
|
default:
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
}
|
17
src/redux/dark-mode/types.ts
Normal file
17
src/redux/dark-mode/types.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { Action } from 'redux'
|
||||||
|
|
||||||
|
export enum DarkModeConfigActionType {
|
||||||
|
SET_DARK_MODE = 'dark-mode/set',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DarkModeConfig {
|
||||||
|
darkMode: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DarkModeConfigActions extends Action<DarkModeConfigActionType> {
|
||||||
|
type: DarkModeConfigActionType
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SetDarkModeConfigAction extends DarkModeConfigActions {
|
||||||
|
darkMode: boolean
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ import { ApiUrlObject } from './api-url/types'
|
||||||
import { BannerReducer } from './banner/reducers'
|
import { BannerReducer } from './banner/reducers'
|
||||||
import { BannerState } from './banner/types'
|
import { BannerState } from './banner/types'
|
||||||
import { ConfigReducer } from './config/reducers'
|
import { ConfigReducer } from './config/reducers'
|
||||||
|
import { DarkModeConfigReducer } from './dark-mode/reducers'
|
||||||
|
import { DarkModeConfig } from './dark-mode/types'
|
||||||
import { EditorConfigReducer } from './editor/reducers'
|
import { EditorConfigReducer } from './editor/reducers'
|
||||||
import { EditorConfig } from './editor/types'
|
import { EditorConfig } from './editor/types'
|
||||||
import { UserReducer } from './user/reducers'
|
import { UserReducer } from './user/reducers'
|
||||||
|
@ -16,6 +18,7 @@ export interface ApplicationState {
|
||||||
banner: BannerState;
|
banner: BannerState;
|
||||||
apiUrl: ApiUrlObject;
|
apiUrl: ApiUrlObject;
|
||||||
editorConfig: EditorConfig;
|
editorConfig: EditorConfig;
|
||||||
|
darkMode: DarkModeConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const allReducers: Reducer<ApplicationState> = combineReducers<ApplicationState>({
|
export const allReducers: Reducer<ApplicationState> = combineReducers<ApplicationState>({
|
||||||
|
@ -23,7 +26,8 @@ export const allReducers: Reducer<ApplicationState> = combineReducers<Applicatio
|
||||||
config: ConfigReducer,
|
config: ConfigReducer,
|
||||||
banner: BannerReducer,
|
banner: BannerReducer,
|
||||||
apiUrl: ApiUrlReducer,
|
apiUrl: ApiUrlReducer,
|
||||||
editorConfig: EditorConfigReducer
|
editorConfig: EditorConfigReducer,
|
||||||
|
darkMode: DarkModeConfigReducer
|
||||||
})
|
})
|
||||||
|
|
||||||
export const store = createStore(allReducers)
|
export const store = createStore(allReducers)
|
||||||
|
|
9
src/style/bootstrap-color-theme/_alert.scss
Normal file
9
src/style/bootstrap-color-theme/_alert.scss
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
}
|
9
src/style/bootstrap-color-theme/_badge.scss
Normal file
9
src/style/bootstrap-color-theme/_badge.scss
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// Colors
|
||||||
|
//
|
||||||
|
// Contextual variations (linked badges get darker on :hover).
|
||||||
|
|
||||||
|
@each $color, $value in $theme-colors {
|
||||||
|
.badge-#{$color} {
|
||||||
|
@include badge-variant($value);
|
||||||
|
}
|
||||||
|
}
|
15
src/style/bootstrap-color-theme/_breadcrumb.scss
Normal file
15
src/style/bootstrap-color-theme/_breadcrumb.scss
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
.breadcrumb {
|
||||||
|
background-color: $breadcrumb-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-item {
|
||||||
|
+ .breadcrumb-item {
|
||||||
|
&::before {
|
||||||
|
color: $breadcrumb-divider-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: $breadcrumb-active-color;
|
||||||
|
}
|
||||||
|
}
|
65
src/style/bootstrap-color-theme/_buttons.scss
Normal file
65
src/style/bootstrap-color-theme/_buttons.scss
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
// 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
|
||||||
|
}
|
29
src/style/bootstrap-color-theme/_card.scss
Normal file
29
src/style/bootstrap-color-theme/_card.scss
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
24
src/style/bootstrap-color-theme/_carousel.scss
Normal file
24
src/style/bootstrap-color-theme/_carousel.scss
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
.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;
|
||||||
|
}
|
12
src/style/bootstrap-color-theme/_close.scss
Normal file
12
src/style/bootstrap-color-theme/_close.scss
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
.close {
|
||||||
|
color: $close-color;
|
||||||
|
text-shadow: $close-text-shadow;
|
||||||
|
|
||||||
|
@include hover() {
|
||||||
|
color: $close-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button.close {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
18
src/style/bootstrap-color-theme/_code.scss
Normal file
18
src/style/bootstrap-color-theme/_code.scss
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
43
src/style/bootstrap-color-theme/_dropdown.scss
Normal file
43
src/style/bootstrap-color-theme/_dropdown.scss
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
.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;
|
||||||
|
}
|
59
src/style/bootstrap-color-theme/_forms.scss
Normal file
59
src/style/bootstrap-color-theme/_forms.scss
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// 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));
|
||||||
|
}
|
10
src/style/bootstrap-color-theme/_images.scss
Normal file
10
src/style/bootstrap-color-theme/_images.scss
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// 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;
|
||||||
|
}
|
5
src/style/bootstrap-color-theme/_input-group.scss
Normal file
5
src/style/bootstrap-color-theme/_input-group.scss
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.input-group-text {
|
||||||
|
color: $input-group-addon-color;
|
||||||
|
background-color: $input-group-addon-bg;
|
||||||
|
border-color: $input-group-addon-border-color;
|
||||||
|
}
|
4
src/style/bootstrap-color-theme/_jumbotron.scss
Normal file
4
src/style/bootstrap-color-theme/_jumbotron.scss
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.jumbotron {
|
||||||
|
color: $jumbotron-color;
|
||||||
|
background-color: $jumbotron-bg;
|
||||||
|
}
|
41
src/style/bootstrap-color-theme/_list-group.scss
Normal file
41
src/style/bootstrap-color-theme/_list-group.scss
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
.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));
|
||||||
|
}
|
35
src/style/bootstrap-color-theme/_modal.scss
Normal file
35
src/style/bootstrap-color-theme/_modal.scss
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
&.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);
|
||||||
|
}
|
||||||
|
}
|
36
src/style/bootstrap-color-theme/_nav.scss
Normal file
36
src/style/bootstrap-color-theme/_nav.scss
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
104
src/style/bootstrap-color-theme/_navbar.scss
Normal file
104
src/style/bootstrap-color-theme/_navbar.scss
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
src/style/bootstrap-color-theme/_pagination.scss
Normal file
30
src/style/bootstrap-color-theme/_pagination.scss
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
80
src/style/bootstrap-color-theme/_popover.scss
Normal file
80
src/style/bootstrap-color-theme/_popover.scss
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
.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;
|
||||||
|
}
|
9
src/style/bootstrap-color-theme/_progress.scss
Normal file
9
src/style/bootstrap-color-theme/_progress.scss
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
.progress {
|
||||||
|
background-color: $progress-bg;
|
||||||
|
@include box-shadow($progress-box-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
color: $progress-bar-color;
|
||||||
|
background-color: $progress-bar-bg;
|
||||||
|
}
|
22
src/style/bootstrap-color-theme/_reboot.scss
Normal file
22
src/style/bootstrap-color-theme/_reboot.scss
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
& {
|
||||||
|
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;
|
||||||
|
}
|
8
src/style/bootstrap-color-theme/_spinners.scss
Normal file
8
src/style/bootstrap-color-theme/_spinners.scss
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
.spinner-border {
|
||||||
|
border-color: currentColor;
|
||||||
|
border-right-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner-grow {
|
||||||
|
background-color: currentColor;
|
||||||
|
}
|
123
src/style/bootstrap-color-theme/_tables.scss
Normal file
123
src/style/bootstrap-color-theme/_tables.scss
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/style/bootstrap-color-theme/_toasts.scss
Normal file
11
src/style/bootstrap-color-theme/_toasts.scss
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
.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;
|
||||||
|
}
|
52
src/style/bootstrap-color-theme/_tooltip.scss
Normal file
52
src/style/bootstrap-color-theme/_tooltip.scss
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
.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;
|
||||||
|
}
|
28
src/style/bootstrap-color-theme/_type.scss
Normal file
28
src/style/bootstrap-color-theme/_type.scss
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// 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;
|
||||||
|
}
|
33
src/style/bootstrap-color-theme/include.scss
Normal file
33
src/style/bootstrap-color-theme/include.scss
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
@import "../../../node_modules/bootstrap/scss/functions";
|
||||||
|
@import "../../../node_modules/bootstrap/scss/variables";
|
||||||
|
@import "../../../node_modules/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";
|
15
src/style/bootstrap-color-theme/utilities/_background.scss
Normal file
15
src/style/bootstrap-color-theme/utilities/_background.scss
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// 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;
|
||||||
|
}
|
21
src/style/bootstrap-color-theme/utilities/_borders.scss
Normal file
21
src/style/bootstrap-color-theme/utilities/_borders.scss
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// 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;
|
||||||
|
}
|
13
src/style/bootstrap-color-theme/utilities/_text.scss
Normal file
13
src/style/bootstrap-color-theme/utilities/_text.scss
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// 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; }
|
128
src/style/dark.scss
Normal file
128
src/style/dark.scss
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
//
|
||||||
|
// Color system
|
||||||
|
//
|
||||||
|
|
||||||
|
$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-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;
|
||||||
|
|
||||||
|
// Breadcrumbs
|
||||||
|
$breadcrumb-bg: $gray-700;
|
||||||
|
|
||||||
|
// Close
|
||||||
|
$close-color: $white;
|
||||||
|
$close-text-shadow: none;
|
||||||
|
|
||||||
|
// Code
|
||||||
|
$pre-color: $dark;
|
||||||
|
|
||||||
|
body.dark {
|
||||||
|
@import "bootstrap-color-theme/include";
|
||||||
|
}
|
|
@ -1,15 +1,23 @@
|
||||||
|
@import './light';
|
||||||
@import "../../node_modules/bootstrap/scss/bootstrap";
|
@import "../../node_modules/bootstrap/scss/bootstrap";
|
||||||
@import '../../node_modules/react-bootstrap-typeahead/css/Typeahead';
|
@import '../../node_modules/react-bootstrap-typeahead/css/Typeahead';
|
||||||
@import "fonts/source-code-pro/source-code-pro";
|
@import "fonts/source-code-pro/source-code-pro";
|
||||||
@import "fonts/twemoji/twemoji";
|
@import "fonts/twemoji/twemoji";
|
||||||
|
|
||||||
|
.text-black, body.dark .text-black {
|
||||||
|
color: $black;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: darken($dark, 8%);
|
||||||
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
background-color: darken($dark, 8%);
|
|
||||||
font-family: "Source Sans Pro", Helvetica, Arial, twemoji, sans-serif;
|
font-family: "Source Sans Pro", Helvetica, Arial, twemoji, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
src/style/light.scss
Normal file
7
src/style/light.scss
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
$blue: #337ab7 !default;
|
||||||
|
$cyan: #5EB7E0 !default;
|
||||||
|
|
||||||
|
@import "../../node_modules/bootstrap/scss/functions";
|
||||||
|
@import "../../node_modules/bootstrap/scss/variables";
|
||||||
|
@import "../../node_modules/bootstrap/scss/mixins";
|
||||||
|
|
13
yarn.lock
13
yarn.lock
|
@ -2383,7 +2383,7 @@ abcjs@5.12.0:
|
||||||
integrity sha512-pvi7SjOAKT7cRyRtywUSwYB0SNtRHKLxZUZ9Oc4E+nvpBHr8Z2/M9Pfyv3oIaiEpxlWTFK+B/H5t/DckiNFgpg==
|
integrity sha512-pvi7SjOAKT7cRyRtywUSwYB0SNtRHKLxZUZ9Oc4E+nvpBHr8Z2/M9Pfyv3oIaiEpxlWTFK+B/H5t/DckiNFgpg==
|
||||||
dependencies:
|
dependencies:
|
||||||
abcjs "5.11.0"
|
abcjs "5.11.0"
|
||||||
midi "git+https://github.com/paulrosen/MIDI.js.git#abcjs"
|
midi "https://github.com/paulrosen/MIDI.js.git#abcjs"
|
||||||
|
|
||||||
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
|
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
|
||||||
version "1.3.7"
|
version "1.3.7"
|
||||||
|
@ -6296,11 +6296,6 @@ getpass@^0.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
github-markdown-css@4.0.0:
|
|
||||||
version "4.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/github-markdown-css/-/github-markdown-css-4.0.0.tgz#be9f4caf7a389228d4c368336260ffc909061f35"
|
|
||||||
integrity sha512-mH0bcIKv4XAN0mQVokfTdKo2OD5K8WJE9+lbMdM32/q0Ie5tXgVN/2o+zvToRMxSTUuiTRcLg5hzkFfOyBYreg==
|
|
||||||
|
|
||||||
glob-parent@^3.1.0:
|
glob-parent@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
|
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
|
||||||
|
@ -8737,14 +8732,8 @@ micromatch@^4.0.0:
|
||||||
braces "^3.0.1"
|
braces "^3.0.1"
|
||||||
picomatch "^2.0.5"
|
picomatch "^2.0.5"
|
||||||
|
|
||||||
"midi@git+https://github.com/paulrosen/MIDI.js.git#abcjs":
|
|
||||||
version "0.4.2"
|
|
||||||
uid e593ffef81a0350f99448e3ab8111957145ff6b2
|
|
||||||
resolved "git+https://github.com/paulrosen/MIDI.js.git#e593ffef81a0350f99448e3ab8111957145ff6b2"
|
|
||||||
|
|
||||||
"midi@https://github.com/paulrosen/MIDI.js.git#abcjs":
|
"midi@https://github.com/paulrosen/MIDI.js.git#abcjs":
|
||||||
version "0.4.2"
|
version "0.4.2"
|
||||||
uid e593ffef81a0350f99448e3ab8111957145ff6b2
|
|
||||||
resolved "https://github.com/paulrosen/MIDI.js.git#e593ffef81a0350f99448e3ab8111957145ff6b2"
|
resolved "https://github.com/paulrosen/MIDI.js.git#e593ffef81a0350f99448e3ab8111957145ff6b2"
|
||||||
|
|
||||||
miller-rabin@^4.0.0:
|
miller-rabin@^4.0.0:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue