add initial accessibility panel
This commit is contained in:
1 parent
605ff872e8
commit
85c0d8c4ab
15 files changed
+764
-56
No files matched your search
Generated
+51
-7
@@ -24,7 +24,8 @@
|
||||
"sharp": "^0.32.6",
|
||||
"sitemap": "^1.5.0",
|
||||
"typograf": "^6.11.1",
|
||||
"use-media": "^1.4.0"
|
||||
"use-media": "^1.4.0",
|
||||
"valtio": "^2.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
@@ -1268,13 +1269,13 @@
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.18.tgz",
|
||||
"integrity": "sha512-6hI08umYs6NaiHFEEGioXnxJ+oEhY3eRz8VCUaudZmGdtvPviCJB8mgaMxaDWAdPSYd4eFavrPk2QIolwbLYrg==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
@@ -1285,7 +1286,7 @@
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/@types/sharp": {
|
||||
"version": "0.29.2",
|
||||
@@ -4735,6 +4736,12 @@
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-compare": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-3.0.1.tgz",
|
||||
"integrity": "sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
@@ -5911,6 +5918,30 @@
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"node_modules/valtio": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/valtio/-/valtio-2.1.7.tgz",
|
||||
"integrity": "sha512-DwJhCDpujuQuKdJ2H84VbTjEJJteaSmqsuUltsfbfdbotVfNeTE4K/qc/Wi57I9x8/2ed4JNdjEna7O6PfavRg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"proxy-compare": "^3.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": ">=18.0.0",
|
||||
"react": ">=18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
@@ -6778,13 +6809,13 @@
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "18.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.18.tgz",
|
||||
"integrity": "sha512-6hI08umYs6NaiHFEEGioXnxJ+oEhY3eRz8VCUaudZmGdtvPviCJB8mgaMxaDWAdPSYd4eFavrPk2QIolwbLYrg==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
@@ -6795,7 +6826,7 @@
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"@types/sharp": {
|
||||
"version": "0.29.2",
|
||||
@@ -9131,6 +9162,11 @@
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"proxy-compare": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-3.0.1.tgz",
|
||||
"integrity": "sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q=="
|
||||
},
|
||||
"pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
@@ -9951,6 +9987,14 @@
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"valtio": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/valtio/-/valtio-2.1.7.tgz",
|
||||
"integrity": "sha512-DwJhCDpujuQuKdJ2H84VbTjEJJteaSmqsuUltsfbfdbotVfNeTE4K/qc/Wi57I9x8/2ed4JNdjEna7O6PfavRg==",
|
||||
"requires": {
|
||||
"proxy-compare": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
||||
+2
-1
@@ -34,7 +34,8 @@
|
||||
"sharp": "^0.32.6",
|
||||
"sitemap": "^1.5.0",
|
||||
"typograf": "^6.11.1",
|
||||
"use-media": "^1.4.0"
|
||||
"use-media": "^1.4.0",
|
||||
"valtio": "^2.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
|
||||
+1
-4
@@ -8,7 +8,6 @@ import App from "next/app"
|
||||
import Head from "next/head"
|
||||
import Script from "next/script"
|
||||
import { YMetrika } from "src/components/YMetrika"
|
||||
import { Theme } from "@/ui/theme/Theme"
|
||||
import { ThemeColor } from "@/ui/ThemeColor"
|
||||
|
||||
export default class MyApp extends App {
|
||||
@@ -51,9 +50,7 @@ export default class MyApp extends App {
|
||||
</Head>
|
||||
<Script src="https://culturaltracking.ru/static/js/spxl.js?pixelId=27154" data-pixel-id="27154"></Script>
|
||||
|
||||
<Theme>
|
||||
<Component {...pageProps} />
|
||||
</Theme>
|
||||
<Component {...pageProps} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { theme, toggleTheme } from "@/store/theme"
|
||||
import { Button } from "@/ui/Button"
|
||||
import { HiOutlineEye, HiOutlineEyeOff } from "react-icons/hi"
|
||||
import { useTheme } from "@/ui/theme/useTheme"
|
||||
import { useSnapshot } from "valtio"
|
||||
|
||||
export function AccessibilityButton() {
|
||||
const { theme, setTheme } = useTheme()
|
||||
const t = useSnapshot(theme)
|
||||
|
||||
return (
|
||||
<Button
|
||||
theme="icon"
|
||||
size="default"
|
||||
onClick={() => {
|
||||
setTheme(theme === "default" ? "contrast" : "default")
|
||||
}}
|
||||
onClick={toggleTheme}
|
||||
>
|
||||
{theme === "default" ? (
|
||||
{t.theme === "default" ? (
|
||||
<HiOutlineEyeOff size={24} />
|
||||
) : (
|
||||
<HiOutlineEye size={24} />
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { decreaseFontSize, hideImages, increaseFontSize, reset, setBlackOnWhite, setBlueOnBlue, setBrownOnYellow, setDefaultTheme, setGreenOnBrown, setLetterSpacingOne, setLetterSpacingTwo, setLetterSpacingFour, setLineHeightOneAndHalf, setLineHeightTwo, setLineHeightTwoAndHalf, setSansFont, setSerifFont, setWhiteOnBlack, showImages } from "@/store/theme"
|
||||
import s from "./panel.module.css"
|
||||
|
||||
function AccessibilityPanel() {
|
||||
return ( <div className={s.viewsettings}>
|
||||
<div className={s.row}>
|
||||
<div className={s.block}>
|
||||
<p>Размер шрифта:</p>
|
||||
<a onClick={decreaseFontSize} title="уменьшить размер шрифта">A-</a>
|
||||
<a onClick={increaseFontSize} title="увеличить размер шрифта"><strong>A+</strong></a>
|
||||
</div>
|
||||
|
||||
<div className={s.block}>
|
||||
<p>Изображения:</p>
|
||||
<a onClick={showImages}>Включить</a>
|
||||
<a onClick={hideImages}>Выключить</a>
|
||||
</div>
|
||||
|
||||
<div className={s.block}>
|
||||
<p>Цвет сайта:</p>
|
||||
<a onClick={setBlackOnWhite} title="черные буквы на белом фоне" style={{color: "black", backgroundColor: "white"}}>Ц</a>
|
||||
<a onClick={setWhiteOnBlack} title="белые буквы на черном фоне" style={{color: "white", backgroundColor: "black"}}>Ц</a>
|
||||
<a onClick={setBlueOnBlue} title="синии буквы на голубом фоне" style={{color: "oklch(32% 24% 253deg)", backgroundColor: "oklch(84% 21% 245deg)"}}>Ц</a>
|
||||
<a onClick={setBrownOnYellow} title="коричневые буквы на желтом фоне" style={{color: "oklch(41% 3% 92deg)", backgroundColor: "oklch(96% 9% 101deg)"}}>Ц</a>
|
||||
<a onClick={setGreenOnBrown} title="зеленые буквы на коричневом фоне" style={{color: "oklch(85% 47% 128deg)", backgroundColor: "oklch(29% 10% 61deg)"}}>Ц</a>
|
||||
</div>
|
||||
|
||||
<div className={s.block}>
|
||||
<p>Шрифт:</p>
|
||||
<a onClick={setSansFont}>С засечками</a>
|
||||
<a onClick={setSerifFont}>Без засечек</a>
|
||||
{/*<a id="btn-on-braille" href="javascript:void(0)" onClick="smSetting('fontBraille', 'brailleOn')" title="только для печати">Брайля</a>*/}
|
||||
{/*<a id="btn-off-braille" href="javascript:void(0)" onClick="smSetting('fontBraille', 'brailleOff')">Обычный</a>*/}
|
||||
</div>
|
||||
|
||||
<div className={s.block}>
|
||||
<p>Высота строк:</p>
|
||||
<a onClick={setLineHeightOneAndHalf}>1.5</a>
|
||||
<a onClick={setLineHeightTwo}>2.0</a>
|
||||
<a onClick={setLineHeightTwoAndHalf}>2.5</a>
|
||||
</div>
|
||||
|
||||
<div className={s.block}>
|
||||
<p>Межбуквенный интервал:</p>
|
||||
<a onClick={setLetterSpacingOne}>1</a>
|
||||
<a onClick={setLetterSpacingTwo}>2</a>
|
||||
<a onClick={setLetterSpacingFour}>4</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={s.row}>
|
||||
<a onClick={reset}><i className="fa fa-cog fa-fw"></i>Сброс настроек</a>
|
||||
{/*<a id="mobile-version" href="?mobile=1"><i className="fa fa-mobile fa-fw"></i> Мобильная версия</a>*/}
|
||||
<a onClick={setDefaultTheme}><i className="fa fa-eye-slash fa-fw"></i>Обычная версия</a>
|
||||
{/*<a id="_playlist" href="javascript:void(0)" onClick="playSound('all', this);"><i className="fa fa-play fa-fw"></i>Прослушать всё</a>*/}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AccessibilityPanel
|
||||
@@ -0,0 +1,433 @@
|
||||
/*body {
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
width: 96%;
|
||||
padding-top: 90px;
|
||||
}*/
|
||||
|
||||
.viewsettings {
|
||||
background: white;
|
||||
z-index: 10;
|
||||
display: block;
|
||||
/*width: 96%;*/
|
||||
font-size: 20px !important;
|
||||
line-height: 30px;
|
||||
font-family: sans-serif, arial;
|
||||
letter-spacing: normal !important;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
||||
margin: 10px;
|
||||
|
||||
text-align: center;
|
||||
border: 2px solid;
|
||||
/*border-right: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
border-bottom-right-radius: 25px;
|
||||
border-bottom-left-radius: 25px;*/
|
||||
}
|
||||
|
||||
.viewsettings .row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
|
||||
margin: 8px 0;
|
||||
}
|
||||
.viewsettings p {
|
||||
margin: 0;
|
||||
}
|
||||
.viewsettings a {
|
||||
border: 1px solid;
|
||||
text-decoration: none;
|
||||
padding: 4px 10px;
|
||||
cursor: pointer;
|
||||
|
||||
color: black;
|
||||
}
|
||||
.viewsettings a:hover {
|
||||
background-color: #cfcfcf !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.viewsettings a:focus {
|
||||
outline: 1px solid !important;
|
||||
}
|
||||
|
||||
.viewsettings .block {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
line-height: 30px;
|
||||
border: 2px solid;
|
||||
padding: 6px 10px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.viewsettings .block a {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
#mainContent {
|
||||
padding-top: 60px;
|
||||
}
|
||||
|
||||
.feedback label {
|
||||
display: block;
|
||||
margin: 16px 0 0 0;
|
||||
}
|
||||
.feedback input {
|
||||
width: 50%;
|
||||
}
|
||||
.feedback textarea {
|
||||
width: 50%;
|
||||
height: 100px;
|
||||
}
|
||||
.feedback input[name="agree"] {
|
||||
display: block;
|
||||
width: 100px;
|
||||
}
|
||||
#captcha {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.line_1_5 {
|
||||
line-height: 1.5;
|
||||
}
|
||||
body.line_2_0 {
|
||||
line-height: 2;
|
||||
}
|
||||
body.line_2_5 {
|
||||
line-height: 2.5;
|
||||
}
|
||||
|
||||
.letter_spacing1 {
|
||||
letter-spacing: normal;
|
||||
}
|
||||
.letter_spacing2 {
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
.letter_spacing4 {
|
||||
letter-spacing: 4px;
|
||||
}
|
||||
|
||||
#btn-black-text {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
#btn-white-text {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
#btn-blue-text {
|
||||
background-color: #9dd1ff;
|
||||
color: #063462;
|
||||
}
|
||||
#btn-sand-text {
|
||||
background-color: #f7f3d6;
|
||||
color: #4d4b43;
|
||||
}
|
||||
#btn-brown-text {
|
||||
background-color: #3b2716;
|
||||
color: #a9e44d;
|
||||
}
|
||||
|
||||
body.imageOff #btn-hide-images,
|
||||
body.imageOff img {
|
||||
display: none;
|
||||
}
|
||||
body.imageOn #btn-show-images {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.brailleOff #btn-off-braille {
|
||||
display: none;
|
||||
}
|
||||
body.brailleOn #btn-on-braille {
|
||||
display: none;
|
||||
}
|
||||
body.brailleOn {
|
||||
font-family: "Kanischev_Braille" !important;
|
||||
}
|
||||
|
||||
body.noSerif #btn-font-sans {
|
||||
display: none;
|
||||
}
|
||||
body.noSerif {
|
||||
font-family: sans-serif, Arial;
|
||||
}
|
||||
|
||||
body.sans #btn-font-serif {
|
||||
display: none;
|
||||
}
|
||||
body.sans {
|
||||
font-family: serif, "Times New Roman";
|
||||
}
|
||||
|
||||
body.BlackOnWhite {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
body.BlackOnWhite a:link,
|
||||
body.BlackOnWhite a:visited,
|
||||
body.BlackOnWhite .viewsettings .block,
|
||||
body.BlackOnWhite .viewsettings,
|
||||
body.BlackOnWhite .additional_text,
|
||||
body.BlackOnWhite .img-wrp::after,
|
||||
body.BlackOnWhite .date {
|
||||
color: black;
|
||||
}
|
||||
body.BlackOnWhite a#active {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
body.BlackOnWhite .image_placeholder {
|
||||
border: 1px solid black;
|
||||
}
|
||||
body.BlackOnWhite a:focus,
|
||||
body.BlackOnWhite input:focus,
|
||||
body.BlackOnWhite textarea:focus,
|
||||
body.BlackOnWhite #attach_cont:focus,
|
||||
body.BlackOnWhite button:focus {
|
||||
outline: #000 solid 5px;
|
||||
}
|
||||
body.BlackOnWhite button,
|
||||
body.BlackOnWhite input,
|
||||
body.BlackOnWhite textarea {
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
body.WhiteOnBlack {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
body.WhiteOnBlack a:link,
|
||||
body.WhiteOnBlack a:visited,
|
||||
body.WhiteOnBlack .viewsettings .block,
|
||||
body.WhiteOnBlack .viewsettings,
|
||||
body.WhiteOnBlack .additional_text,
|
||||
body.WhiteOnBlack .img-wrp::after,
|
||||
body.WhiteOnBlack .date {
|
||||
color: white;
|
||||
}
|
||||
body.WhiteOnBlack a#active {
|
||||
color: black;
|
||||
background-color: white;
|
||||
}
|
||||
body.WhiteOnBlack .image_placeholder {
|
||||
border: 1px solid white;
|
||||
}
|
||||
body.WhiteOnBlack a:focus,
|
||||
body.WhiteOnBlack input:focus,
|
||||
body.WhiteOnBlack textarea:focus,
|
||||
body.WhiteOnBlack #attach_cont:focus,
|
||||
body.WhiteOnBlack button:focus {
|
||||
outline: #fff solid 5px;
|
||||
}
|
||||
body.WhiteOnBlack button,
|
||||
body.BlackOnWhite input,
|
||||
body.BlackOnWhite textarea {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
body.BlueOnBlue {
|
||||
background-color: #9dd1ff;
|
||||
color: #063462;
|
||||
}
|
||||
body.BlueOnBlue a:link,
|
||||
body.BlueOnBlue a:visited,
|
||||
body.BlueOnBlue .viewsettings .block,
|
||||
body.BlueOnBlue .viewsettings,
|
||||
body.BlueOnBlue .additional_text,
|
||||
body.BlueOnBlue .img-wrp::after,
|
||||
body.BlueOnBlue .date {
|
||||
color: #063462;
|
||||
}
|
||||
body.BlueOnBlue a#active {
|
||||
color: #9dd1ff;
|
||||
background-color: #063462;
|
||||
}
|
||||
body.BlueOnBlue .image_placeholder {
|
||||
border: 1px solid #063462;
|
||||
}
|
||||
body.BlueOnBlue a:focus,
|
||||
body.BlueOnBlue input:focus,
|
||||
body.BlueOnBlue textarea:focus,
|
||||
body.BlueOnBlue #attach_cont:focus,
|
||||
body.BlueOnBlue button:focus {
|
||||
outline: #063462 solid 5px;
|
||||
}
|
||||
body.BlueOnBlue button,
|
||||
body.BlueOnBlue input,
|
||||
body.BlueOnBlue textarea {
|
||||
background-color: #9dd1ff;
|
||||
color: #063462;
|
||||
border: 1px solid #063462;
|
||||
}
|
||||
|
||||
body.SandTheme {
|
||||
background-color: #f7f3d6;
|
||||
color: #4d4b43;
|
||||
}
|
||||
body.SandTheme a:link,
|
||||
body.SandTheme a:visited,
|
||||
body.SandTheme .viewsettings .block,
|
||||
body.SandTheme .viewsettings,
|
||||
body.SandTheme .additional_text,
|
||||
body.SandTheme .img-wrp::after,
|
||||
body.SandTheme .date {
|
||||
color: #4d4b43;
|
||||
}
|
||||
body.SandTheme a#active {
|
||||
color: #f7f3d6;
|
||||
background-color: #4d4b43;
|
||||
}
|
||||
body.SandTheme .image_placeholder {
|
||||
border: 1px solid #4d4b43;
|
||||
}
|
||||
body.SandTheme a:focus,
|
||||
body.SandTheme input:focus,
|
||||
body.SandTheme textarea:focus,
|
||||
body.SandTheme #attach_cont:focus,
|
||||
body.SandTheme button:focus {
|
||||
outline: #4d4b43 solid 5px;
|
||||
}
|
||||
body.SandTheme button,
|
||||
body.SandTheme input,
|
||||
body.SandTheme textarea {
|
||||
background-color: #f7f3d6;
|
||||
color: #4d4b43;
|
||||
border: 1px solid #4d4b43;
|
||||
}
|
||||
|
||||
body.BrownTheme {
|
||||
background-color: #3b2716;
|
||||
color: #a9e44d;
|
||||
}
|
||||
body.BrownTheme a:link,
|
||||
body.BrownTheme a:visited,
|
||||
body.BrownTheme .viewsettings .block,
|
||||
body.BrownTheme .viewsettings,
|
||||
body.BrownTheme .additional_text,
|
||||
body.BrownTheme .img-wrp::after,
|
||||
body.BrownTheme .date {
|
||||
color: #a9e44d;
|
||||
}
|
||||
body.BrownTheme a#active {
|
||||
color: #3b2716;
|
||||
background-color: #a9e44d;
|
||||
}
|
||||
body.BrownTheme .image_placeholder {
|
||||
border: 1px solid #a9e44d;
|
||||
}
|
||||
body.BrownTheme a:focus,
|
||||
body.BrownTheme input:focus,
|
||||
body.BrownTheme textarea:focus,
|
||||
body.BrownTheme #attach_cont:focus,
|
||||
body.BrownTheme button:focus {
|
||||
outline: #a9e44d solid 5px;
|
||||
}
|
||||
body.BrownTheme button,
|
||||
body.BrownTheme input,
|
||||
body.BrownTheme textarea {
|
||||
background-color: #3b2716;
|
||||
color: #a9e44d;
|
||||
border: 1px solid #a9e44d;
|
||||
}
|
||||
|
||||
ul#navmenu-h li a {
|
||||
padding: 0 6px 0 6px;
|
||||
}
|
||||
|
||||
.news_list_item strong {
|
||||
padding-bottom: 4px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.date {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.s-on {
|
||||
background-position: 0 0;
|
||||
}
|
||||
.s-of {
|
||||
background-position: 0 30px;
|
||||
}
|
||||
.image_alt {
|
||||
width: 144px;
|
||||
height: 144px;
|
||||
border: 1px solid black;
|
||||
font-size: 18px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gallery_album_thumbail {
|
||||
display: block;
|
||||
max-width: 150px;
|
||||
max-height: 150px;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
ul#navmenu-h li a {
|
||||
text-decoration: none;
|
||||
}
|
||||
ul#navmenu-h li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.additional_text {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 70%;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.image_placeholder {
|
||||
font-size: 70%;
|
||||
font-weight: normal;
|
||||
margin: 5px;
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
min-width: 100px;
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.play-button {
|
||||
display: block;
|
||||
min-width: 30px;
|
||||
min-height: 30px;
|
||||
cursor: pointer;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#playlist {
|
||||
float: right;
|
||||
display: block;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
._afisha_table_content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.img-wrp {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.img-wrp::after {
|
||||
content: attr(data-alt);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
font-size: 70%;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import { useMobile } from "src/hooks/useMobile"
|
||||
import { Navigation } from "@/components/Navigation"
|
||||
import { Box } from "@/ui/Box"
|
||||
import { AccessibilityButton } from "../AccessibilityButton"
|
||||
import { useTheme } from "@/ui/theme/useTheme"
|
||||
import { Copyright } from "../Copyright"
|
||||
import { Spacer } from "../Spacer"
|
||||
import { Author } from "../Author"
|
||||
@@ -22,6 +21,7 @@ import dynamic from "next/dynamic"
|
||||
import qr0 from "src/assets/qr00.png"
|
||||
import qr1 from "src/assets/qr01.png"
|
||||
import Image from "next/image"
|
||||
import AccessibilityPanel from "../AccessibilityPanel"
|
||||
|
||||
const Gosuslugi = dynamic(import("../Gosuslugi").then(module => module.Gosuslugi), {
|
||||
ssr: false,
|
||||
@@ -41,7 +41,6 @@ export const App: React.FC<AppProps> = ({ showAuthor = false, menu, ...props })
|
||||
const blockStyle = {
|
||||
justifyContent: "center",
|
||||
}
|
||||
const { theme, setTheme } = useTheme()
|
||||
|
||||
return (
|
||||
<ConfigContext.Provider value={{
|
||||
@@ -146,6 +145,8 @@ export const App: React.FC<AppProps> = ({ showAuthor = false, menu, ...props })
|
||||
</Footer>
|
||||
)}
|
||||
>
|
||||
<AccessibilityPanel/>
|
||||
|
||||
<Box style={blockStyle}>
|
||||
<Content style={props.contentStyle}>
|
||||
{props.children}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import s from "./wrapper.module.css"
|
||||
|
||||
import cx from "classnames"
|
||||
import { useTheme } from "@/ui/theme/useTheme"
|
||||
import { useSnapshot } from "valtio"
|
||||
import { theme } from "@/store/theme"
|
||||
|
||||
export type WrapperProps = {
|
||||
header: React.ReactNode
|
||||
@@ -12,10 +13,10 @@ export type WrapperProps = {
|
||||
}
|
||||
|
||||
export const Wrapper: React.FC<WrapperProps> = props => {
|
||||
const { theme } = useTheme()
|
||||
const t = useSnapshot(theme)
|
||||
|
||||
return (
|
||||
<div className={cx(s.container, `theme-${theme}`)} style={props.style}>
|
||||
<div className={cx(s.container, `theme-${t.theme}`, !t.showImages ? "no-images" : null)} style={props.style}>
|
||||
{props.header}
|
||||
|
||||
<main className={s.main} style={props.mainStyle}>
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
import { proxy, subscribe, useSnapshot } from "valtio"
|
||||
|
||||
export type ThemeName = "default" | "contrast"
|
||||
export type ColorSchemeVariant = "black-on-white" | "white-on-black" | "blue-on-blue" | "brown-on-yellow" | "green-on-brown"
|
||||
|
||||
const MIN_FONT_SIZE = 8
|
||||
const MAX_FONT_SIZE = 48
|
||||
const CHANGE_FONT_SIZE_DELTA = 0.2
|
||||
|
||||
function clamp(val: number, min: number, max: number): number {
|
||||
if (val < min) {
|
||||
return min
|
||||
}
|
||||
if (val > max) {
|
||||
return max
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
export type ThemeOptions = {
|
||||
theme: ThemeName
|
||||
fontType: string
|
||||
fontSize: number
|
||||
lineHeight: number
|
||||
letterSpacing: number
|
||||
showImages: boolean
|
||||
colorScheme: ColorSchemeVariant
|
||||
}
|
||||
|
||||
export const theme = proxy<ThemeOptions>({
|
||||
theme: "default",
|
||||
fontSize: 14,
|
||||
lineHeight: 1.5,
|
||||
letterSpacing: 1,
|
||||
fontType: "Times New Roman",
|
||||
showImages: true,
|
||||
colorScheme: "black-on-white",
|
||||
})
|
||||
|
||||
export function reset() {
|
||||
theme.fontSize = 14
|
||||
theme.lineHeight = 1.5
|
||||
theme.letterSpacing = 1
|
||||
theme.fontType = "Times New Roman"
|
||||
theme.showImages = true
|
||||
theme.colorScheme = "black-on-white"
|
||||
}
|
||||
|
||||
export function setDefaultTheme() {
|
||||
theme.theme = "default"
|
||||
reset()
|
||||
}
|
||||
|
||||
export function toggleTheme() {
|
||||
theme.theme = theme.theme === "default" ? "contrast" : "default"
|
||||
}
|
||||
|
||||
export function increaseFontSize() {
|
||||
theme.fontSize = clamp(theme.fontSize + CHANGE_FONT_SIZE_DELTA, MIN_FONT_SIZE, MAX_FONT_SIZE)
|
||||
}
|
||||
|
||||
export function decreaseFontSize() {
|
||||
theme.fontSize = clamp(theme.fontSize - CHANGE_FONT_SIZE_DELTA, MIN_FONT_SIZE, MAX_FONT_SIZE)
|
||||
}
|
||||
|
||||
export function setSerifFont() {
|
||||
theme.fontType = "sans-serif"
|
||||
}
|
||||
|
||||
export function setSansFont() {
|
||||
theme.fontType = "Times New Roman"
|
||||
}
|
||||
|
||||
export function showImages() {
|
||||
theme.showImages = true
|
||||
}
|
||||
|
||||
export function hideImages() {
|
||||
theme.showImages = false
|
||||
}
|
||||
|
||||
export function setBlackOnWhite() {
|
||||
theme.colorScheme = "black-on-white"
|
||||
}
|
||||
|
||||
export function setWhiteOnBlack() {
|
||||
theme.colorScheme = "white-on-black"
|
||||
}
|
||||
|
||||
export function setBlueOnBlue() {
|
||||
theme.colorScheme = "blue-on-blue"
|
||||
}
|
||||
|
||||
export function setBrownOnYellow() {
|
||||
theme.colorScheme = "brown-on-yellow"
|
||||
}
|
||||
|
||||
export function setGreenOnBrown() {
|
||||
theme.colorScheme = "green-on-brown"
|
||||
}
|
||||
|
||||
export function setLineHeightOneAndHalf() {
|
||||
theme.lineHeight = 1.5
|
||||
}
|
||||
|
||||
export function setLineHeightTwo() {
|
||||
theme.lineHeight = 2
|
||||
}
|
||||
|
||||
export function setLineHeightTwoAndHalf() {
|
||||
theme.lineHeight = 2.5
|
||||
}
|
||||
|
||||
export function setLetterSpacingOne() {
|
||||
theme.letterSpacing = 1
|
||||
}
|
||||
|
||||
export function setLetterSpacingTwo() {
|
||||
theme.letterSpacing = 2
|
||||
}
|
||||
|
||||
export function setLetterSpacingFour() {
|
||||
theme.letterSpacing = 4
|
||||
}
|
||||
|
||||
function getColor(scheme: ColorSchemeVariant): [string, string] {
|
||||
switch (theme.colorScheme) {
|
||||
case "black-on-white":
|
||||
return ["black", "white"]
|
||||
case "white-on-black":
|
||||
return ["white", "black"]
|
||||
case "blue-on-blue":
|
||||
return ["oklch(32% 24% 253deg)", "oklch(84% 21% 245deg)"]
|
||||
case "brown-on-yellow":
|
||||
return ["oklch(41% 3% 92deg)", "oklch(96% 9% 101deg)"]
|
||||
case "green-on-brown":
|
||||
return ["oklch(85% 47% 128deg)", "oklch(29% 10% 61deg)"]
|
||||
default:
|
||||
return ["black", "white"]
|
||||
}
|
||||
}
|
||||
|
||||
const unsubscribe = subscribe(theme, () => {
|
||||
document.documentElement.style.setProperty("--font-size-default", `${theme.fontSize}pt`)
|
||||
|
||||
document.documentElement.style.setProperty("--title-font", theme.fontType)
|
||||
document.documentElement.style.setProperty("--text-font", theme.fontType)
|
||||
|
||||
document.documentElement.style.setProperty("--article-line-height", `${theme.lineHeight}em`)
|
||||
if (theme.letterSpacing === 1) {
|
||||
document.documentElement.style.setProperty("--letter-spacing", "normal")
|
||||
} else {
|
||||
document.documentElement.style.setProperty("--letter-spacing", `${theme.letterSpacing}px`)
|
||||
}
|
||||
|
||||
const [t, b] = getColor(theme.colorScheme)
|
||||
document.documentElement.style.setProperty("--color-text", t)
|
||||
document.documentElement.style.setProperty("--color-text-second", t)
|
||||
document.documentElement.style.setProperty("--color-text-opposite", b)
|
||||
document.documentElement.style.setProperty("--color-back-main", b)
|
||||
document.documentElement.style.setProperty("--color-back", b)
|
||||
})
|
||||
+23
-9
@@ -21,6 +21,8 @@
|
||||
--font-size-h2: 3rem;
|
||||
--font-size-h3: 1.5rem;
|
||||
|
||||
--letter-spacing: normal;
|
||||
|
||||
/* COLOR */
|
||||
--color-text: hsl(0, 0%, 15%);
|
||||
--color-text-second: hsl(240, 10%, 60%);
|
||||
@@ -89,6 +91,7 @@ body {
|
||||
background-color: var(--color-back-main);
|
||||
|
||||
font-family: var(--text-font);
|
||||
letter-spacing: var(--letter-spacing);
|
||||
}
|
||||
|
||||
/* TITLE */
|
||||
@@ -168,21 +171,19 @@ h3 {
|
||||
/* CONTRAST THEME */
|
||||
.theme-contrast {
|
||||
/* FONTS */
|
||||
--title-font: 'Roboto', Helvetica, sans-serif;
|
||||
--text-font: 'Roboto', Helvetica, sans-serif;
|
||||
/*--title-font: "Roboto", Helvetica, sans-serif;*/
|
||||
/*--text-font: "Roboto", Helvetica, sans-serif;*/
|
||||
|
||||
/* TEXT COLOR */
|
||||
--color-text: black;
|
||||
/*--color-text: black;
|
||||
--color-text-second: black;
|
||||
--color-text-opposite: white;
|
||||
|
||||
--color-back-main: white;
|
||||
--color-back: white;
|
||||
--color-back-active: hsl(240, 10%, 20%);
|
||||
/* --color-back-opposite: hsl(240, 10%, 80%); */
|
||||
--color-back-opposite: black;
|
||||
--color-link: hsl(240, 10%, 40%);
|
||||
--color-link-opposite: hsl(240, 10%, 60%);
|
||||
--color-link-opposite: hsl(240, 10%, 60%);*/
|
||||
|
||||
--color-hover: white;
|
||||
--color-hover-back: black;
|
||||
@@ -193,9 +194,9 @@ h3 {
|
||||
--shadow-active: none;
|
||||
|
||||
/* FONTS */
|
||||
--font-size-default: 16pt;
|
||||
--font-size-accent: 24pt;
|
||||
--font-size-second: 14pt;
|
||||
/*--font-size-default: 16pt;*/
|
||||
/*--font-size-accent: 24pt;*/
|
||||
/*--font-size-second: 14pt;*/
|
||||
|
||||
--font-size-h1: 5rem;
|
||||
--font-size-h2: 3rem;
|
||||
@@ -207,6 +208,19 @@ h3 {
|
||||
--border: 5px solid var(--color-back-opposite);
|
||||
}
|
||||
|
||||
.theme-contrast.no-images img {
|
||||
display: none;
|
||||
/*opacity: 0.5;*/
|
||||
/*position: relative;*/
|
||||
}
|
||||
|
||||
/*.theme-contrast.no-images img:after {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid black;
|
||||
}*/
|
||||
|
||||
/* CONTRAST + DARK THEME */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.theme-contrast {
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { useLocalStorage } from "react-use"
|
||||
import { ThemeContext } from "./ThemeContext"
|
||||
import { ThemeType } from "./types"
|
||||
|
||||
export type ThemeProps = {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const Theme: React.FC<ThemeProps> = ({ children }) => {
|
||||
const [theme, setTheme] = useLocalStorage<ThemeType>("hudozka-theme", "default")
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={[theme ?? "default", setTheme]}>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createContext } from "react"
|
||||
import { SetTheme, ThemeType } from "./types"
|
||||
import { DEFAULT } from "./const"
|
||||
import { SetTheme, ThemeOptions } from "./types"
|
||||
|
||||
export const ThemeContext = createContext<[ThemeType, SetTheme]>(["default", () => {}])
|
||||
export const ThemeContext = createContext<[ThemeOptions, SetTheme]>([DEFAULT, () => {}])
|
||||
@@ -0,0 +1,5 @@
|
||||
import { ThemeOptions } from "./types"
|
||||
|
||||
export const DEFAULT: ThemeOptions = {
|
||||
theme: "default",
|
||||
}
|
||||
@@ -1,2 +1,5 @@
|
||||
export type ThemeType = "default" | "contrast"
|
||||
export type SetTheme = (theme: ThemeType) => void
|
||||
export type ThemeOptions = {
|
||||
theme: "default" | "contrast"
|
||||
fontSize?: number
|
||||
}
|
||||
export type SetTheme = (theme: ThemeOptions["theme"]) => void
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useContext } from "react"
|
||||
import { ThemeContext } from "./ThemeContext"
|
||||
import { SetTheme, ThemeType } from "./types"
|
||||
import { SetTheme, ThemeOptions } from "./types"
|
||||
|
||||
export type UseThemeResult = {
|
||||
theme: ThemeType
|
||||
theme: ThemeOptions["theme"]
|
||||
setTheme: SetTheme
|
||||
// toggleTheme:
|
||||
}
|
||||
@@ -11,5 +11,8 @@ export type UseThemeResult = {
|
||||
export function useTheme(): UseThemeResult {
|
||||
const [theme, setTheme] = useContext(ThemeContext)
|
||||
|
||||
return { theme, setTheme }
|
||||
return {
|
||||
setTheme,
|
||||
theme: theme.theme ?? "default",
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user