dark-theme-feature

This commit is contained in:
Untone 2024-10-06 20:02:24 +03:00
parent c789124ff7
commit 47dd3b21f4
16 changed files with 229 additions and 218 deletions

View File

@ -671,3 +671,7 @@ a[data-toggle='tooltip'] {
}
}
}
.figureAlignColumn {
clear: both;
}

View File

@ -4,6 +4,7 @@ import { A, useSearchParams } from '@solidjs/router'
import { clsx } from 'clsx'
import { For, Show, createEffect, createMemo, createSignal, on, onCleanup, onMount } from 'solid-js'
import { isServer } from 'solid-js/web'
import { useFeed } from '~/context/feed'
import { useLocalize } from '~/context/localize'
import { useReactions } from '~/context/reactions'
@ -19,7 +20,6 @@ import { capitalize } from '~/utils/capitalize'
import { AuthorBadge } from '../Author/AuthorBadge'
import { CardTopic } from '../Feed/CardTopic'
import { FeedArticlePopup } from '../Feed/FeedArticlePopup'
import stylesHeader from '../HeaderNav/Header.module.scss'
import { Icon } from '../_shared/Icon'
import { Image } from '../_shared/Image'
import { InviteMembers } from '../_shared/InviteMembers'
@ -30,13 +30,15 @@ import { ShareModal } from '../_shared/ShareModal'
import { ImageSwiper } from '../_shared/SolidSwiper'
import { TableOfContents } from '../_shared/TableOfContents'
import { VideoPlayer } from '../_shared/VideoPlayer'
import styles from './Article.module.scss'
import { AudioHeader } from './AudioHeader'
import { AudioPlayer } from './AudioPlayer'
import { CommentsTree } from './CommentsTree'
import { SharePopup, getShareUrl } from './SharePopup'
import { ShoutRatingControl } from './ShoutRatingControl'
import stylesHeader from '../HeaderNav/Header.module.scss'
import styles from './Article.module.scss'
type Props = {
article: Shout
}
@ -366,7 +368,7 @@ export const FullArticle = (props: Props) => {
props.article.layout !== 'image'
}
>
<figure class="img-align-column">
<figure class={styles.figureAlignColumn}>
<Image
width={800}
alt={props.article.cover_caption || ''}

View File

@ -133,7 +133,7 @@
}
.authControl {
color: $link-color;
color: $color-primary;
margin-top: 1em;
text-align: center;
}

View File

@ -10,10 +10,10 @@
a:visited {
background: transparent;
border: none;
color: $link-color;
color: $color-primary;
&:hover {
background: $link-color;
background: $color-primary;
color: #fff !important;
}
}

View File

@ -1,16 +1,16 @@
import type { Shout } from '~/graphql/schema/core.gen'
import { For } from 'solid-js'
import type { Shout } from '~/graphql/schema/core.gen'
import { ArticleCard } from './ArticleCard'
import styles from '~/styles/views/Feed.module.scss'
export default (props: { articles: Shout[] }) => (
<div class="floor floor--7">
<div class="wide-container">
<div class="short-cards">
<div class={styles['short-cards']}>
<For each={props.articles}>
{(a) => (
<div class="short-card">
<div class={styles['short-card']}>
<ArticleCard
article={a}
settings={{

View File

@ -86,7 +86,7 @@
vertical-align: middle;
width: 100px;
[data-editor-dark-mode='true'] & {
[data-theme='dark'] & {
filter: invert(1);
}
}

View File

@ -199,9 +199,9 @@ export const TopicView = (props: Props) => {
</ul>
</div>
<div class="col-md-8">
<div class="mode-switcher">
<div class={styles.modeSwitcher}>
{`${t('Show')} `}
<span class="mode-switcher__control">{t('All posts')}</span>
<span class={styles.modeSwitcherControl}>{t('All posts')}</span>
</div>
</div>
</div>

View File

@ -12,45 +12,38 @@ type Props = {
export const DarkModeToggle = (props: Props) => {
const { t } = useLocalize()
const [editorDarkMode, setEditorDarkMode] = createSignal(false)
const [isDark, setIsDark] = createSignal(false)
onMount(() => {
const editorDarkModeSelected = localStorage?.getItem('editorDarkMode')
const editorDarkModeAttr = document.documentElement.getAttribute('editorDarkMode')
if (editorDarkModeSelected === 'true') {
setEditorDarkMode(true)
document.documentElement.dataset.editorDarkMode = 'true'
} else if (editorDarkModeSelected === 'false') {
setEditorDarkMode(false)
document.documentElement.dataset.editorDarkMode = 'false'
const theme = localStorage?.getItem('theme') || document.documentElement.getAttribute('theme')
if (theme === 'dark') {
setIsDark(true)
document.documentElement.dataset.theme = 'dark'
} else if (theme !== 'dark') {
setIsDark(false)
document.documentElement.dataset.theme = 'light'
}
if (!(editorDarkModeAttr || editorDarkModeSelected)) {
localStorage?.setItem('editorDarkMode', 'false')
document.documentElement.dataset.editorDarkMode = 'false'
if (!theme) {
localStorage?.setItem('theme', 'light')
document.documentElement.dataset.theme = 'light'
}
onCleanup(() => {
setEditorDarkMode(false)
document.documentElement.dataset.editorDarkMode = undefined
setIsDark(false)
document.documentElement.dataset.theme = undefined
})
})
const handleSwitchTheme = () => {
setEditorDarkMode(!editorDarkMode())
localStorage?.setItem('editorDarkMode', editorDarkMode() ? 'true' : 'false')
document.documentElement.dataset.editorDarkMode = editorDarkMode() ? 'true' : 'false'
setIsDark(!isDark())
localStorage?.setItem('theme', isDark() ? 'dark' : 'light')
document.documentElement.dataset.theme = isDark() ? 'dark' : 'light'
}
return (
<div class={clsx(styles.DarkModeToggle, props.class)}>
<input
type="checkbox"
id="theme-switcher"
value="1"
checked={editorDarkMode()}
onClick={handleSwitchTheme}
/>
<input type="checkbox" id="theme-switcher" value="1" checked={isDark()} onClick={handleSwitchTheme} />
<label for="theme-switcher">
{t('Night mode')}
<div class={styles.switcher}>

View File

@ -5,6 +5,7 @@ import { Show, createSignal, onMount } from 'solid-js'
import { useLocalize } from '~/context/localize'
import { Button } from '../Button'
import './cropper.css'
import styles from './ImageCropper.module.scss'
interface CropperProps {

View File

@ -0,0 +1,28 @@
.cropper-modal {
background-color: #000 !important;
opacity: 0.4 !important;
}
.cropper-canvas {
filter: blur(2px);
}
.cropper-view-box,
.cropper-crop-box,
.cropper-line,
.cropper-point {
box-shadow: none !important;
outline: none !important;
border: none !important;
background-color: transparent !important;
}
.cropper-crop-box {
border: 2px solid #000 !important;
border-radius: 8px;
}
.cropper-view-box,
.cropper-face {
border-radius: 50%;
}

View File

@ -1,3 +1,5 @@
@import 'vars';
// Миксин для media-breakpoint-up
@mixin media-breakpoint-up($breakpoint, $breakpoints: $grid-breakpoints) {
$min-width: map-get($breakpoints, $breakpoint);

56
src/styles/_theme.scss Normal file
View File

@ -0,0 +1,56 @@
@import 'vars';
:root {
--background-color: #fff;
--default-color: #{$default-color};
--background-color-invert: #000;
--default-color-invert: #fff;
--link-color: #000;
--link-hover-color: #fff;
--link-hover-background: #000;
--secondary-color: #85878a;
--placeholder-color: #9fa1a7;
--placeholder-color-semi: rgb(159 169 167 / 20%);
--danger-color: $color-danger;
--lightgray-color: rgb(84 16 17 / 6%);
--selection-background: #000;
--selection-color: #fff;
--icon-filter: invert(0);
--icon-filter-hover: invert(1);
--editor-bubble-menu-background: #fff;
--blue-link: $link-color;
// names from figma
--black-50: #f7f7f8;
--black-100: #e9e9ee;
--black-300: #9fa1a7;
--black-400: #696969;
--black-500: #141414;
--white-500: #fff;
--blue-500: #2638d9;
--yellow-50: #fffbeb;
--gray-100: #f3f4f6;
}
[data-theme='dark'] {
--background-color: #121416;
--default-color: #fff;
--background-color-invert: #fff;
--default-color-invert: #121416;
--link-color: #fff;
--link-hover-color: #000;
--link-hover-background: #fff;
--selection-background: #eee;
--selection-color: #000;
--icon-filter: invert(1);
--icon-filter-hover: invert(0);
--editor-bubble-menu-background: #444;
// names from figma
--black-50: #080807;
--black-100: #161611;
--black-300: #696969;
--black-400: #969696;
--black-500: #ebebeb;
--white-500: #000;
}

View File

@ -12,11 +12,7 @@ $grid-breakpoints: (
xl: 1200px,
xxl: 1400px,
) !default;
$default-color: #141414;
$link-color: #2638d9;
$container-padding-x: $grid-gutter-width * 0.5 !default;
// Additional variables needed
$container-max-widths: $grid-breakpoints;
$gutters: (
0: 0,
@ -28,3 +24,18 @@ $gutters: (
) !default;
$grid-row-columns: 6 !default;
$prefix: '' !default;
// Шрифты
$font-family: muller, arial, helvetica, sans-serif;
$font-size-base: 2rem;
$line-height-base: 1.6;
// Базовые цвета (не зависящие от темы)
$color-primary: #2638d9;
$color-danger: #d00820;
$default-color: #141414;
// Другие переменные
$border-radius: 2px;
$transition-base: all 0.2s ease-in-out;
$container-padding-x: $grid-gutter-width * 0.5;

View File

@ -1,60 +1,7 @@
@import 'fonts';
:root {
--background-color: #fff;
--default-color: #121416;
--background-color-invert: #000;
--default-color-invert: #fff;
--link-color: #000;
--link-hover-color: #fff;
--link-hover-background: #000;
--secondary-color: #85878a;
--placeholder-color: #9fa1a7;
--placeholder-color-semi: rgb(159 169 167 / 20%);
--danger-color: #d00820;
--lightgray-color: rgb(84 16 17 / 6%);
--font: -apple-system, blinkmacsystemfont, 'Segoe UI', roboto, oxygen, ubuntu, cantarell, 'Open Sans',
'Helvetica Neue', sans-serif;
--selection-background: #000;
--selection-color: #fff;
--icon-filter: invert(0);
--icon-filter-hover: invert(1);
--editor-bubble-menu-background: #fff;
--blue-link: #2638d9;
// names from figma
--black-50: #f7f7f8;
--black-100: #e9e9ee;
--black-300: #9fa1a7;
--black-500: #141414;
--black-400: #696969;
--white-500: #fff;
--blue-500: #2638d9;
--yellow-50: #fffbeb;
--gray-100: #f3f4f6;
}
[data-editor-dark-mode='true'] {
--background-color: #121416;
--default-color: #fff;
--background-color-invert: #fff;
--default-color-invert: #121416;
--link-color: #fff;
--link-hover-color: #000;
--link-hover-background: #fff;
--selection-background: #eee;
--selection-color: #000;
--icon-filter: invert(1);
--icon-filter-hover: invert(0);
--editor-bubble-menu-background: #444;
// names from figma
--black-50: #080807;
--black-100: #161611;
--black-500: #ebebeb;
--black-400: #969696;
--white-500: #000;
}
@import 'vars';
@import 'theme';
@import 'grid';
* {
box-sizing: border-box;
@ -66,7 +13,7 @@
}
html {
color: $default-color;
color: var(--default-color);
font-size: 62.5%;
height: 100%;
-webkit-font-smoothing: antialiased;
@ -125,16 +72,16 @@ h2 {
line-height: 1.3;
.wrapped {
background: #000;
color: #fff;
background: var(--background-color-invert);
color: var(--default-color-invert);
margin-left: -0.15em;
padding: 0 0.15em;
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
&::selection {
background: #fff;
color: #000;
background: var(--selection-background);
color: var(--selection-color);
}
}
}
@ -240,27 +187,28 @@ button {
}
.button {
background: #000;
color: var(--default-color-invert);
background: var(--background-color-invert);
box-sizing: border-box;
color: #fff;
font-size: 100%;
font-weight: 500;
padding: 0.6rem 1.2rem;
text-align: center;
&:hover {
color: #ccc;
color: var(--black-300);
opacity: 1;
}
&:active {
color: #9fa1a7;
color: var(--black-300);
}
}
.button--subscribe {
background: #fff;
border: 2px solid #f6f6f6;
background: var(--background-color);
color: var(--default-color);
border: 2px solid var(--black-100);
font-size: 1.5rem;
justify-content: center;
padding: 0.6rem 1.2rem;
@ -272,7 +220,8 @@ button {
}
&:hover {
background: #000;
background: var(--background-color-invert);
color: var(--default-color-invert);
img {
filter: invert(1);
@ -282,31 +231,31 @@ button {
.button--light {
font-size:1.5rem;
background-color: #f6f6f6;
background-color: var(--black-100);
border-radius: 0.8rem;
color: #000;
color: var(--default-color);
font-weight: 500;
height: auto;
padding: 0.6rem 1.2rem 0.6rem 1rem;
&:hover {
background: #e9e9ee;
background: var(--black-300);
}
}
.button--subscribe-topic {
background: #fff;
border: 2px solid #000;
background: var(--background-color);
color: var(--default-color);
border: 2px solid var(--default-color);
border-radius: 0.8rem;
color: #000;
font-size: 1.4rem;
line-height: 2.8rem;
height: 3.2rem;
padding: 0 1rem;
&:hover {
background: #000;
color: #fff;
background: var(--background-color-invert);
color: var(--default-color-invert);
opacity: 1;
.icon {
@ -315,8 +264,8 @@ button {
}
&[disabled]:hover {
background: #fff;
color: #000;
background: var(--background-color);
color: var(--default-color);
}
.icon {
@ -339,7 +288,7 @@ button {
}
background: none;
border: 2px solid #fff;
border: 2px solid var(--white-500);
height: 3.2rem;
float: right;
padding: 0;
@ -390,7 +339,7 @@ button {
color: #000;
&:hover {
box-shadow: inset 0 0 0 2px #ccc;
box-shadow: inset 0 0 0 2px var(--black-300);
}
}
@ -403,7 +352,7 @@ form {
input[type='date'],
textarea,
select {
border: 2px solid #e8e8e8;
border: 2px solid var(--black-100);
border-radius: 2px;
display: block;
font-family: inherit;
@ -421,7 +370,7 @@ form {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-touch-callout: none;
color: #a4acb1;
color: var(--black-400);
position: absolute;
left: 1.2rem;
display: block;
@ -498,7 +447,7 @@ form {
.pretty-form__item--error {
input {
border-color: #d00820;
border-color: var(--danger-color);
}
}
@ -575,13 +524,10 @@ figure {
margin: auto;
width: 100%;
}
}
.ta-video-container,
figure {
figcaption {
font-size:1.2rem;
color: rgb(0 0 0 / 60%);
color: var(--black-400);
line-height: 1.5;
}
}
@ -627,12 +573,6 @@ figure {
padding: 0 !important;
}
a {
&:hover {
color: #fff;
}
}
a,
.link,
.linkReplacement,
@ -655,8 +595,8 @@ figure {
.link,
.linkReplacement,
button {
border-bottom: 2px solid #000;
color: #000;
border-bottom: 2px solid var(--default-color);
color: var(--default-color);
cursor: default;
&:hover {
@ -682,8 +622,8 @@ figure {
text-align: center;
.view-switcher__item--selected & {
background: #000;
color: #fff;
background: var(--background-color-invert);
color: var(--default-color-invert);
}
}
@ -753,15 +693,15 @@ figure {
margin-bottom: 5rem;
}
background: #000;
color: #fff;
background: var(--background-color-invert);
color: var(--default-color-invert);
padding: $grid-gutter-width 0;
padding-bottom: $container-padding-x;
padding-top: $container-padding-x;
::selection {
background: #fff;
color: #000;
background: var(--background-color);
color: var(--default-color) !important;
}
h2 {
@ -771,38 +711,16 @@ figure {
.all-materials {
a {
color: #fff;
color: var(--default-color-invert) !important;
}
}
a:hover {
background: #fff;
color: #000 !important;
color: var(--default-color) !important;
background: var(--background-color);
}
}
.short-cards {
@include media-breakpoint-up(md) {
display: flex;
flex-wrap: wrap;
}
margin: 0 -5px;
}
.short-card {
@include media-breakpoint-up(md) {
flex: 1 0 50%;
}
@include media-breakpoint-up(lg) {
flex: 1 0 25%;
}
margin-bottom: 10px;
padding: 0 5px;
}
.row {
@include media-breakpoint-down(md) {
> * {
@ -896,20 +814,6 @@ figure {
height: 420px;
}
.mode-switcher {
@include media-breakpoint-up(md) {
text-align: right;
}
font-size:1.5rem;
}
.mode-switcher__control {
border-bottom: 1px dotted;
cursor: pointer;
font-weight: bold;
}
.content-index {
@include media-breakpoint-up(md) {
position: sticky;
@ -998,7 +902,7 @@ details {
.description {
font-size:1.4rem;
color: rgba(0 0 0 / 40%);
color: var(--black-400);
.pretty-form__item + & {
margin-top: -2rem;
@ -1011,20 +915,23 @@ details {
/* total width */
&::-webkit-scrollbar {
background-color: #fff;
color: var(--default-color);
background: var(--background-color);
width: 16px;
}
/* background of the scrollbar except button or resizer */
&::-webkit-scrollbar-track {
background-color: #fff;
color: var(--default-color);
background: var(--background-color);
}
/* scrollbar itself */
&::-webkit-scrollbar-thumb {
background-color: #babac0;
color: var(--default-color);
background: var(--background-color);
border-radius: 16px;
border: 4px solid #fff;
border: 4px solid var(--white-500);
}
/* set button(top and bottom of the scrollbar) */
@ -1035,7 +942,7 @@ details {
iframe {
border: none;
color: rgb(255 255 255 / 0%);
color: var(--default-color);
max-width: 100%;
}
@ -1051,38 +958,9 @@ iframe {
.blackModeIntersection {
color: var(--default-color);
background: #fef2f2;
background: var(--background-color);
}
.img-align-column {
clear: both;
}
.cropper-modal {
background-color: #000 !important;
opacity: 0.4 !important;
}
.cropper-canvas {
filter: blur(2px);
}
.cropper-view-box,
.cropper-crop-box,
.cropper-line,
.cropper-point {
box-shadow: none !important;
outline: none !important;
border: none !important;
background-color: transparent !important;
}
.cropper-crop-box {
border: 2px solid #000 !important;
border-radius: 8px;
}
.cropper-view-box,
.cropper-face {
border-radius: 50%;
}

View File

@ -224,3 +224,25 @@
font-weight: 700;
line-height: 18px;
}
.short-cards {
@include media-breakpoint-up(md) {
display: flex;
flex-wrap: wrap;
}
margin: 0 -5px;
}
.short-card {
@include media-breakpoint-up(md) {
flex: 1 0 50%;
}
@include media-breakpoint-up(lg) {
flex: 1 0 25%;
}
margin-bottom: 10px;
padding: 0 5px;
}

View File

@ -20,4 +20,18 @@
padding-left: 0;
padding-right: 0;
}
.modeSwitcher {
@include media-breakpoint-up(md) {
text-align: right;
}
font-size:1.5rem;
}
.modeSwitcherControl {
border-bottom: 1px dotted;
cursor: pointer;
font-weight: bold;
}
}