mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-03-25 03:02:54 +00: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",
|
||||
"flowchart.js": "1.14.1",
|
||||
"fork-awesome": "1.1.7",
|
||||
"github-markdown-css": "4.0.0",
|
||||
"highlight.js": "10.2.0",
|
||||
"i18next": "19.7.0",
|
||||
"i18next-browser-languagedetector": "6.0.1",
|
||||
|
|
|
@ -9,8 +9,8 @@ export interface LoadingScreenProps {
|
|||
|
||||
export const LoadingScreen: React.FC<LoadingScreenProps> = ({ failedTitle }) => {
|
||||
return (
|
||||
<div className="loader middle text-white">
|
||||
<div className="mb-3 text-white">
|
||||
<div className="loader middle text-light">
|
||||
<div className="mb-3 text-light">
|
||||
<ForkAwesomeIcon icon="file-text" size="5x"
|
||||
className={failedTitle ? 'animation-shake' : 'animation-pulse'}/>
|
||||
</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 (
|
||||
<ShowIf condition={bannerState.show}>
|
||||
<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}
|
||||
</Link>
|
||||
<Button
|
||||
|
|
|
@ -4,7 +4,7 @@ import { LandingLayout } from '../../landing-layout/landing-layout'
|
|||
export const NotFoundErrorScreen: React.FC = () => {
|
||||
return (
|
||||
<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>
|
||||
</div>
|
||||
</LandingLayout>
|
||||
|
|
|
@ -9,7 +9,7 @@ import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
|
|||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import { SignInButton } from '../../landing-layout/navigation/sign-in-button'
|
||||
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 { DarkModeButton } from './dark-mode-button'
|
||||
import { EditorViewMode } from './editor-view-mode'
|
||||
|
@ -26,7 +26,7 @@ export const AppBar: React.FC = () => {
|
|||
<Nav className="mr-auto d-flex align-items-center">
|
||||
<NavbarBranding/>
|
||||
<EditorViewMode/>
|
||||
<SyncScrollButton/>
|
||||
<SyncScrollButtons/>
|
||||
<DarkModeButton/>
|
||||
<Link to={`/p/${id}`} target='_blank'>
|
||||
<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 { 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'
|
||||
|
||||
const DarkModeButton: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const [buttonState, setButtonState] = useState(false)
|
||||
const buttonToggle = () => {
|
||||
setButtonState(prevState => !prevState)
|
||||
}
|
||||
const darkModeEnabled = useSelector((state: ApplicationState) => state.darkMode.darkMode)
|
||||
|
||||
return (
|
||||
<ToggleButtonGroup type="checkbox" defaultValue={[]} name="dark-mode" className="ml-2" value={buttonState ? ['dark'] : ['']}>
|
||||
<ToggleButton
|
||||
title={ buttonState ? t('editor.darkMode.switchToLight') : t('editor.darkMode.switchToDark')}
|
||||
variant={ buttonState ? 'secondary' : 'light' }
|
||||
className={ buttonState ? 'text-white' : 'text-secondary' }
|
||||
onChange={buttonToggle} value={'dark'}
|
||||
>
|
||||
{buttonState
|
||||
? <ForkAwesomeIcon icon="sun"/>
|
||||
: <ForkAwesomeIcon icon="moon"/>
|
||||
}
|
||||
<ToggleButtonGroup
|
||||
type="radio"
|
||||
name="dark-mode"
|
||||
value={darkModeEnabled}
|
||||
className="ml-2"
|
||||
onChange={(value: boolean) => {
|
||||
setDarkMode(value)
|
||||
}}>
|
||||
<ToggleButton value={true} variant="outline-secondary" title={t('editor.darkMode.switchToDark')}>
|
||||
<ForkAwesomeIcon icon="moon"/>
|
||||
</ToggleButton>
|
||||
<ToggleButton value={false} variant="outline-secondary" title={t('editor.darkMode.switchToLight')}>
|
||||
<ForkAwesomeIcon icon="sun-o"/>
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
)
|
||||
|
|
|
@ -40,30 +40,24 @@ export const HelpButton: React.FC = () => {
|
|||
<ForkAwesomeIcon icon="question-circle"/> <Trans i18nKey={'editor.documentBar.help'}/> – <Trans i18nKey={`editor.help.${tab}`}/>
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body className="text-dark">
|
||||
<ul className='nav nav-tabs'>
|
||||
<li className='nav-item'>
|
||||
<button className={`nav-link ${tab === HelpTabStatus.Cheatsheet ? 'active' : ''}`}
|
||||
onClick={() => setTab(HelpTabStatus.Cheatsheet)}
|
||||
>
|
||||
<Trans i18nKey={'editor.help.cheatsheet.title'}/>
|
||||
</button>
|
||||
</li>
|
||||
<li className='nav-item'>
|
||||
<button className={`nav-link ${tab === HelpTabStatus.Shortcuts ? 'active' : ''}`}
|
||||
onClick={() => setTab(HelpTabStatus.Shortcuts)}
|
||||
>
|
||||
<Trans i18nKey={'editor.help.shortcuts.title'}/>
|
||||
</button>
|
||||
</li>
|
||||
<li className='nav-item'>
|
||||
<button className={`nav-link ${tab === HelpTabStatus.Links ? 'active' : ''}`}
|
||||
onClick={() => setTab(HelpTabStatus.Links)}
|
||||
>
|
||||
<Trans i18nKey={'editor.help.links.title'}/>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<Modal.Body>
|
||||
<nav className='nav nav-tabs'>
|
||||
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Cheatsheet ? 'active' : ''}`}
|
||||
onClick={() => setTab(HelpTabStatus.Cheatsheet)}
|
||||
>
|
||||
<Trans i18nKey={'editor.help.cheatsheet.title'}/>
|
||||
</Button>
|
||||
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Shortcuts ? 'active' : ''}`}
|
||||
onClick={() => setTab(HelpTabStatus.Shortcuts)}
|
||||
>
|
||||
<Trans i18nKey={'editor.help.shortcuts.title'}/>
|
||||
</Button>
|
||||
<Button variant={'light'} className={`nav-link nav-item ${tab === HelpTabStatus.Links ? 'active' : ''}`}
|
||||
onClick={() => setTab(HelpTabStatus.Links)}
|
||||
>
|
||||
<Trans i18nKey={'editor.help.links.title'}/>
|
||||
</Button>
|
||||
</nav>
|
||||
{tabContent()}
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react'
|
||||
import React, { Fragment } from 'react'
|
||||
import { Card, ListGroup, Row } from 'react-bootstrap'
|
||||
import { Trans } from 'react-i18next'
|
||||
import { isMac } from '../../utils'
|
||||
|
@ -25,14 +25,19 @@ export const Shortcut: React.FC = () => {
|
|||
<Row className={'justify-content-center pt-4'}>
|
||||
{Object.keys(shortcutMap).map(category => {
|
||||
return (
|
||||
<Card className={'m-2 w-50'}>
|
||||
<Card key={category} className={'m-2 w-50'}>
|
||||
<Card.Header>{category}</Card.Header>
|
||||
<ListGroup variant="flush">
|
||||
{Object.entries(shortcutMap[category]).map(([functionName, shortcut]) => {
|
||||
{Object.entries(shortcutMap[category]).map(([functionName, shortcuts]) => {
|
||||
return (
|
||||
<ListGroup.Item key={functionName} className={'d-flex justify-content-between'}>
|
||||
<span><Trans i18nKey={functionName}/></span>
|
||||
<span>{shortcut}</span>
|
||||
<span>
|
||||
{
|
||||
shortcuts.map((shortcut, shortcutIndex) =>
|
||||
<Fragment key={shortcutIndex}>{shortcut}</Fragment>)
|
||||
}
|
||||
</span>
|
||||
</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 { ForkAwesomeIcon } from '../../../common/fork-awesome/fork-awesome-icon'
|
||||
import { ActiveIndicatorStatus } from './active-indicator'
|
||||
import './connection-indicator.scss'
|
||||
import { UserLine } from './user-line'
|
||||
|
||||
const ConnectionIndicator: React.FC = () => {
|
||||
const userOnline = 2
|
||||
return (
|
||||
<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
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
|
|
|
@ -2,9 +2,11 @@ import React, { useEffect, useRef, useState } from 'react'
|
|||
import { Alert, Col, ListGroup, Modal, Row, Button } from 'react-bootstrap'
|
||||
import ReactDiffViewer, { DiffMethod } from 'react-diff-viewer'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { useParams } from 'react-router'
|
||||
import { getAllRevisions, getRevision, Revision, RevisionListEntry } from '../../../../api/revisions'
|
||||
import { UserResponse } from '../../../../api/users/types'
|
||||
import { ApplicationState } from '../../../../redux'
|
||||
import { CommonModal, CommonModalProps } from '../../../common/modals/common-modal'
|
||||
import { ShowIf } from '../../../common/show-if/show-if'
|
||||
import { RevisionButtonProps } from './revision-button'
|
||||
|
@ -20,6 +22,7 @@ export const RevisionModal: React.FC<CommonModalProps & RevisionButtonProps> = (
|
|||
const [error, setError] = useState(false)
|
||||
const revisionAuthorListMap = useRef(new Map<number, UserResponse[]>())
|
||||
const revisionCacheMap = useRef(new Map<number, Revision>())
|
||||
const darkModeEnabled = useSelector((state: ApplicationState) => state.darkMode.darkMode)
|
||||
const { id } = useParams<{ id: string }>()
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -81,7 +84,7 @@ export const RevisionModal: React.FC<CommonModalProps & RevisionButtonProps> = (
|
|||
newValue={noteContent}
|
||||
splitView={false}
|
||||
compareMethod={DiffMethod.WORDS}
|
||||
useDarkTheme={false}
|
||||
useDarkTheme={darkModeEnabled}
|
||||
/>
|
||||
</ShowIf>
|
||||
</Col>
|
||||
|
|
|
@ -12,8 +12,3 @@
|
|||
font-size: 18px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.btn-toolbar .btn {
|
||||
padding: 0.1875rem 0.5rem;
|
||||
min-width: 30px;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
.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 {
|
||||
background-color: #e2e6ea;
|
||||
|
|
|
@ -4,6 +4,7 @@ import { useSelector } from 'react-redux'
|
|||
import useMedia from 'use-media'
|
||||
import { ApplicationState } from '../../redux'
|
||||
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 { MotdBanner } from '../common/motd-banner/motd-banner'
|
||||
import { AppBar } from './app-bar/app-bar'
|
||||
|
@ -109,6 +110,7 @@ export const Editor: React.FC = () => {
|
|||
|
||||
return (
|
||||
<Fragment>
|
||||
<ApplyDarkMode/>
|
||||
<MotdBanner/>
|
||||
<DocumentTitle title={documentTitle}/>
|
||||
<div className={'d-flex flex-column vh-100'}>
|
||||
|
|
|
@ -119,8 +119,21 @@ https://asciinema.org/a/117928
|
|||
|
||||
## Code highlighting
|
||||
\`\`\`javascript=
|
||||
|
||||
let a = 1
|
||||
var s = "JavaScript syntax highlighting";
|
||||
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
|
||||
|
|
|
@ -4,4 +4,9 @@
|
|||
z-index: 1;
|
||||
cursor: col-resize;
|
||||
box-shadow: 3px 0 6px #e7e7e7;
|
||||
|
||||
body.dark & {
|
||||
box-shadow: 3px 0 6px #7b7b7b;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,19 +3,22 @@
|
|||
max-width: 200px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
&.sticky {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
>ul>li {
|
||||
>a {
|
||||
> ul > li {
|
||||
> a {
|
||||
padding: 4px 20px;
|
||||
}
|
||||
>ul>li {
|
||||
|
||||
> ul > li {
|
||||
> a {
|
||||
padding: 1px 0 1px 30px;
|
||||
}
|
||||
>ul>li {
|
||||
|
||||
> ul > li {
|
||||
> a {
|
||||
padding: 1px 0 1px 38px;
|
||||
}
|
||||
|
@ -49,14 +52,15 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.markdown-toc-sidebar-button {
|
||||
position: fixed;
|
||||
right: 40px;
|
||||
bottom: 30px;
|
||||
|
||||
&>.dropup {
|
||||
position: sticky;
|
||||
bottom: 20px;
|
||||
right: 0;
|
||||
}
|
||||
.markdown-toc-sidebar-button {
|
||||
position: fixed;
|
||||
right: 40px;
|
||||
bottom: 30px;
|
||||
|
||||
& > .dropup {
|
||||
position: sticky;
|
||||
bottom: 20px;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ export class ErrorBoundary extends Component {
|
|||
render (): ReactElement | undefined | null | string | number | boolean | Record<string, unknown> | ReactNodeArray {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<Container className="text-white d-flex flex-column mvh-100">
|
||||
<div className='text-white d-flex flex-column align-items-center justify-content-center my-5'>
|
||||
<Container className="text-light d-flex flex-column mvh-100">
|
||||
<div className='text-light d-flex flex-column align-items-center justify-content-center my-5'>
|
||||
<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>
|
||||
If you can reproduce this error, then we would be glad if you 
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
}
|
||||
|
||||
.dropup .dropdown-toggle, .dropdown-toggle {
|
||||
&.no-arrow::after {
|
||||
content: initial;
|
||||
}
|
||||
&.no-arrow::after {
|
||||
content: initial;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import { SocialLink } from './social-links'
|
|||
|
||||
export const Footer: React.FC = () => {
|
||||
return (
|
||||
<footer className="text-white-50 small">
|
||||
<footer className="text-light-50 small">
|
||||
<LanguagePicker/>
|
||||
<PoweredByLinks/>
|
||||
<SocialLink/>
|
||||
|
|
|
@ -35,7 +35,9 @@ export const VersionInfo: React.FC = () => {
|
|||
|
||||
return (
|
||||
<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.Body className="text-dark">
|
||||
<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 }) => {
|
||||
return (
|
||||
<Container className="text-white d-flex flex-column mvh-100">
|
||||
<Container className="text-light d-flex flex-column mvh-100">
|
||||
<DocumentTitle/>
|
||||
<MotdBanner/>
|
||||
<HeaderBar/>
|
||||
|
|
|
@ -35,7 +35,7 @@ export const ViaInternal: React.FC = () => {
|
|||
type="text"
|
||||
size="sm"
|
||||
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'
|
||||
/>
|
||||
</Form.Group>
|
||||
|
@ -47,7 +47,7 @@ export const ViaInternal: React.FC = () => {
|
|||
size="sm"
|
||||
placeholder={t('login.auth.password')}
|
||||
onChange={(event) => setPassword(event.currentTarget.value)}
|
||||
className="bg-dark text-white"
|
||||
className="bg-dark text-light"
|
||||
autoComplete='current-password'
|
||||
/>
|
||||
</Form.Group>
|
||||
|
|
|
@ -37,7 +37,7 @@ export const ViaLdap: React.FC = () => {
|
|||
type="text"
|
||||
size="sm"
|
||||
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'
|
||||
/>
|
||||
</Form.Group>
|
||||
|
@ -49,7 +49,7 @@ export const ViaLdap: React.FC = () => {
|
|||
size="sm"
|
||||
placeholder={t('login.auth.password')}
|
||||
onChange={(event) => setPassword(event.currentTarget.value)}
|
||||
className="bg-dark text-white"
|
||||
className="bg-dark text-light"
|
||||
autoComplete='current-password'
|
||||
/>
|
||||
</Form.Group>
|
||||
|
|
|
@ -33,7 +33,7 @@ export const ViaOpenId: React.FC = () => {
|
|||
size="sm"
|
||||
placeholder={'OpenID'}
|
||||
onChange={(event) => setOpenId(event.currentTarget.value)}
|
||||
className="bg-dark text-white"
|
||||
className="bg-dark text-light"
|
||||
/>
|
||||
</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 {
|
||||
position: relative;
|
||||
|
|
|
@ -14,6 +14,6 @@ export const AbcFrame: React.FC<AbcFrameProps> = ({ code }) => {
|
|||
}, [code])
|
||||
|
||||
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 (
|
||||
<table className={'csv-html-table'}>
|
||||
<table className={'csv-html-table table-striped'}>
|
||||
{renderTableHeader(headerRow)}
|
||||
{renderTableBody(rowsWithColumns)}
|
||||
</table>
|
||||
|
|
|
@ -1,42 +1,55 @@
|
|||
.markdown-body {
|
||||
@import '../../../../../../node_modules/highlight.js/styles/github-gist.css';
|
||||
|
||||
}
|
||||
|
||||
.markdown-body code.hljs {
|
||||
.markdown-body {
|
||||
@import '../../../../../../node_modules/highlight.js/styles/github';
|
||||
|
||||
padding: 16px;
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
body.dark & {
|
||||
@import '../../../../../../node_modules/highlight.js/styles/tomorrow-night';
|
||||
}
|
||||
|
||||
&.showGutter {
|
||||
.linenumber {
|
||||
position: relative;
|
||||
cursor: default;
|
||||
z-index: 4;
|
||||
padding: 0 8px 0 0;
|
||||
min-width: 20px;
|
||||
box-sizing: content-box;
|
||||
color: #afafaf;
|
||||
border-right: 3px solid #6ce26c;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
code.hljs {
|
||||
background-color: rgba(27, 31, 35, .05);
|
||||
body.dark & {
|
||||
background-color: rgb(27, 31, 35);
|
||||
}
|
||||
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
body.dark &, & {
|
||||
padding: 16px;
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
|
||||
&:before {
|
||||
content: attr(data-line-number);
|
||||
&.showGutter {
|
||||
.linenumber {
|
||||
position: relative;
|
||||
cursor: default;
|
||||
z-index: 4;
|
||||
padding: 0 8px 0 0;
|
||||
min-width: 20px;
|
||||
box-sizing: content-box;
|
||||
color: #afafaf;
|
||||
border-right: 3px solid #6ce26c;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
|
||||
&:before {
|
||||
content: attr(data-line-number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.showGutter .codeline {
|
||||
margin: 0 0 0 16px;
|
||||
}
|
||||
|
||||
&.wrapLines .codeline {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.showGutter .codeline {
|
||||
margin: 0 0 0 16px;
|
||||
}
|
||||
|
||||
&.wrapLines .codeline {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export const DeprecationWarning: React.FC = () => {
|
|||
<Alert className={'mt-2'} variant={'warning'}>
|
||||
<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>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ export const ProfileChangePassword: React.FC = () => {
|
|||
<Form.Control
|
||||
type="password"
|
||||
size="sm"
|
||||
className="bg-dark text-white"
|
||||
className="bg-dark text-light"
|
||||
required
|
||||
onChange={(event) => setOldPassword(event.target.value)}
|
||||
/>
|
||||
|
@ -49,7 +49,7 @@ export const ProfileChangePassword: React.FC = () => {
|
|||
<Form.Control
|
||||
type="password"
|
||||
size="sm"
|
||||
className="bg-dark text-white"
|
||||
className="bg-dark text-light"
|
||||
required
|
||||
onChange={onChangeNewPassword}
|
||||
isValid={newPasswordValid}
|
||||
|
@ -61,7 +61,7 @@ export const ProfileChangePassword: React.FC = () => {
|
|||
<Form.Control
|
||||
type="password"
|
||||
size="sm"
|
||||
className="bg-dark text-white"
|
||||
className="bg-dark text-light"
|
||||
required
|
||||
onChange={onChangeNewPasswordAgain}
|
||||
isValid={newPasswordAgainValid}
|
||||
|
|
|
@ -53,7 +53,7 @@ export const ProfileDisplayName: React.FC = () => {
|
|||
size="sm"
|
||||
placeholder={t('profile.displayName')}
|
||||
value={displayName}
|
||||
className="bg-dark text-white"
|
||||
className="bg-dark text-light"
|
||||
onChange={changeNameField}
|
||||
isValid={submittable}
|
||||
isInvalid={error}
|
||||
|
|
|
@ -70,7 +70,7 @@ export const RegisterPage: React.FC = () => {
|
|||
isValid={username !== ''}
|
||||
onChange={(event) => setUsername(event.target.value)}
|
||||
placeholder={t('login.auth.username')}
|
||||
className='bg-dark text-white'
|
||||
className='bg-dark text-light'
|
||||
autoComplete='username'
|
||||
autoFocus={true}
|
||||
required
|
||||
|
@ -85,7 +85,7 @@ export const RegisterPage: React.FC = () => {
|
|||
isValid={password !== '' && password.length >= 8}
|
||||
onChange={(event) => setPassword(event.target.value)}
|
||||
placeholder={t('login.auth.password')}
|
||||
className='bg-dark text-white'
|
||||
className='bg-dark text-light'
|
||||
minLength={8}
|
||||
autoComplete='new-password'
|
||||
required
|
||||
|
@ -101,7 +101,7 @@ export const RegisterPage: React.FC = () => {
|
|||
isValid={passwordAgain !== '' && password === passwordAgain}
|
||||
onChange={(event) => setPasswordAgain(event.target.value)}
|
||||
placeholder={t('login.register.passwordAgain')}
|
||||
className='bg-dark text-white'
|
||||
className='bg-dark text-light'
|
||||
autoComplete='new-password'
|
||||
required
|
||||
/>
|
||||
|
|
|
@ -16,6 +16,7 @@ import { RegisterPage } from './components/register-page/register-page'
|
|||
import { store } from './redux'
|
||||
import * as serviceWorker from './service-worker'
|
||||
import './style/index.scss'
|
||||
import './style/dark.scss'
|
||||
|
||||
ReactDOM.render(
|
||||
<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 { BannerState } from './banner/types'
|
||||
import { ConfigReducer } from './config/reducers'
|
||||
import { DarkModeConfigReducer } from './dark-mode/reducers'
|
||||
import { DarkModeConfig } from './dark-mode/types'
|
||||
import { EditorConfigReducer } from './editor/reducers'
|
||||
import { EditorConfig } from './editor/types'
|
||||
import { UserReducer } from './user/reducers'
|
||||
|
@ -16,6 +18,7 @@ export interface ApplicationState {
|
|||
banner: BannerState;
|
||||
apiUrl: ApiUrlObject;
|
||||
editorConfig: EditorConfig;
|
||||
darkMode: DarkModeConfig;
|
||||
}
|
||||
|
||||
export const allReducers: Reducer<ApplicationState> = combineReducers<ApplicationState>({
|
||||
|
@ -23,7 +26,8 @@ export const allReducers: Reducer<ApplicationState> = combineReducers<Applicatio
|
|||
config: ConfigReducer,
|
||||
banner: BannerReducer,
|
||||
apiUrl: ApiUrlReducer,
|
||||
editorConfig: EditorConfigReducer
|
||||
editorConfig: EditorConfigReducer,
|
||||
darkMode: DarkModeConfigReducer
|
||||
})
|
||||
|
||||
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/react-bootstrap-typeahead/css/Typeahead';
|
||||
@import "fonts/source-code-pro/source-code-pro";
|
||||
@import "fonts/twemoji/twemoji";
|
||||
|
||||
.text-black, body.dark .text-black {
|
||||
color: $black;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: darken($dark, 8%);
|
||||
}
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100%;
|
||||
background-color: darken($dark, 8%);
|
||||
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==
|
||||
dependencies:
|
||||
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:
|
||||
version "1.3.7"
|
||||
|
@ -6296,11 +6296,6 @@ getpass@^0.1.1:
|
|||
dependencies:
|
||||
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:
|
||||
version "3.1.0"
|
||||
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"
|
||||
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":
|
||||
version "0.4.2"
|
||||
uid e593ffef81a0350f99448e3ab8111957145ff6b2
|
||||
resolved "https://github.com/paulrosen/MIDI.js.git#e593ffef81a0350f99448e3ab8111957145ff6b2"
|
||||
|
||||
miller-rabin@^4.0.0:
|
||||
|
|
Loading…
Reference in a new issue