Working theming, Layout->MainLayout, profiles list bugfix
This commit is contained in:
parent
019fa83353
commit
2e272de59c
20 changed files with 681 additions and 169 deletions
11
public/less.min.js
vendored
Normal file
11
public/less.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/less.min.js.map
Normal file
1
public/less.min.js.map
Normal file
File diff suppressed because one or more lines are too long
1
public/theme.less
Symbolic link
1
public/theme.less
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../src/styles/theme.less
|
5
public/theme_dyn.less
Normal file
5
public/theme_dyn.less
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
@import url(/theme.less);
|
||||||
|
@accent: #6570d6;
|
||||||
|
@bdrs: 2rem;
|
||||||
|
@purebg: false;
|
||||||
|
body { .theme-mixin(@accent, @bdrs, @purebg) !important; }
|
46
src/components/ColorBtn.astro
Normal file
46
src/components/ColorBtn.astro
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
export interface Props {
|
||||||
|
name: string;
|
||||||
|
hex: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { name, hex } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<a href="javascript:void(0)" class="color-button" data-hex={hex}>
|
||||||
|
<span>{name}</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<style lang="less" define:vars={{ hex }}>
|
||||||
|
.color-button {
|
||||||
|
padding: 0.15rem 0.3rem;
|
||||||
|
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
border-radius: var(--bdrs);
|
||||||
|
background: var(--hex);
|
||||||
|
color: #fff;
|
||||||
|
transition: filter 0.2s ease 0s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
filter: brightness(80%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const accentInput = document.getElementById('accent') as HTMLInputElement
|
||||||
|
|
||||||
|
const btns = document.querySelectorAll('.color-button')
|
||||||
|
for (let btn of btns) {
|
||||||
|
btn.addEventListener('click', ev => {
|
||||||
|
const elem = ev.currentTarget as HTMLAnchorElement
|
||||||
|
accentInput.value = elem.dataset.hex
|
||||||
|
accentInput.dispatchEvent(new Event('input'))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
33
src/components/ListItem.astro
Normal file
33
src/components/ListItem.astro
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
import Icon from './Icon.astro';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { icon } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<span class="icon-wrapper">
|
||||||
|
<Icon code={icon} />
|
||||||
|
</span>
|
||||||
|
<span class="content">
|
||||||
|
<slot />
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-wrapper {
|
||||||
|
margin-right: 0.375rem;
|
||||||
|
width: 1.6rem;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
40
src/components/MenuItem.astro
Normal file
40
src/components/MenuItem.astro
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
---
|
||||||
|
import Icon from './Icon.astro';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
name: string;
|
||||||
|
link: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { name, link, icon } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href={link}>
|
||||||
|
<span class="icon-wrapper">
|
||||||
|
<Icon code={icon} />
|
||||||
|
</span>
|
||||||
|
{name}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
li {
|
||||||
|
// 0.6rem = horizontal padding
|
||||||
|
padding: 0 0.6rem;
|
||||||
|
font-size: 1.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-wrapper {
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--fg-sec);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -43,14 +43,18 @@ const { app, url, name, icon, copyName = false } = Astro.props;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import "/src/styles/profile_calc.less";
|
||||||
|
|
||||||
.profile {
|
.profile {
|
||||||
padding: 0.4rem 0.6rem;
|
// vertical horizontal
|
||||||
|
padding: 0.4rem @profile-horiz-padding;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
border-radius: 2rem;
|
width: @profile-width;
|
||||||
|
border-radius: var(--bdrs);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--accent-bg);
|
background: var(--accent-bg);
|
||||||
|
@ -58,8 +62,6 @@ const { app, url, name, icon, copyName = false } = Astro.props;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.profile-main {
|
a.profile-main {
|
||||||
@icon-size: 2.3rem;
|
|
||||||
|
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -70,13 +72,12 @@ const { app, url, name, icon, copyName = false } = Astro.props;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
.icon-wrapper {
|
.icon-wrapper {
|
||||||
font-size: @icon-size;
|
font-size: @profile-icon-app;
|
||||||
margin-right: 0.4rem;
|
margin-right: @profile-icon-margin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a.copy {
|
a.copy {
|
||||||
@icon-size: 1.8rem;
|
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
|
@ -86,8 +87,8 @@ const { app, url, name, icon, copyName = false } = Astro.props;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.icon-wrapper {
|
.icon-wrapper {
|
||||||
font-size: @icon-size;
|
font-size: @profile-icon-copy;
|
||||||
margin-left: 0.4rem;
|
margin-left: @profile-icon-margin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +96,9 @@ const { app, url, name, icon, copyName = false } = Astro.props;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
width: @profile-text-width;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.app {
|
.app {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
82
src/components/Slider.astro
Normal file
82
src/components/Slider.astro
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
---
|
||||||
|
import Input from "../layouts/Input.astro";
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
min: number;
|
||||||
|
max: number;
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id, label, min, max, value } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<Input label="" column>
|
||||||
|
<span slot="label">
|
||||||
|
{label}:
|
||||||
|
<span class="range-value">2</span>
|
||||||
|
rem
|
||||||
|
</span>
|
||||||
|
<span slot="after">
|
||||||
|
<input type="range" name={id} id={id} min={min} max={max} value={value}>
|
||||||
|
</span>
|
||||||
|
</Input>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
input {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
border: none;
|
||||||
|
outline: 0;
|
||||||
|
background: var(--bg);
|
||||||
|
&:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@track-height: 0.4rem;
|
||||||
|
@thumb-size: 1.05rem;
|
||||||
|
@thumb-shadow-blur: @thumb-size * 0.5;
|
||||||
|
|
||||||
|
// line
|
||||||
|
&::-webkit-slider-runnable-track,
|
||||||
|
&::-moz-range-track {
|
||||||
|
height: @track-height;
|
||||||
|
background: var(--bg-sec);
|
||||||
|
border-radius: @track-height * 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// circle
|
||||||
|
&::-webkit-slider-thumb,
|
||||||
|
&::-moz-range-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
|
||||||
|
width: @thumb-size;
|
||||||
|
height: @thumb-size;
|
||||||
|
border-radius: @thumb-size;
|
||||||
|
|
||||||
|
border: none;
|
||||||
|
//background: var(--bg);
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
// x-offset y-offset blur color
|
||||||
|
box-shadow: 0 0 @thumb-shadow-blur var(--fg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const ranges = document.querySelectorAll('input[type="range"]')
|
||||||
|
const handler = (ev: Event) => {
|
||||||
|
const input = ev.currentTarget as HTMLInputElement
|
||||||
|
const container = input.parentElement.parentElement
|
||||||
|
const valueSpan = container.querySelector('.range-value') as HTMLSpanElement
|
||||||
|
valueSpan.innerText = input.value
|
||||||
|
}
|
||||||
|
for (let elem of ranges) {
|
||||||
|
elem.addEventListener('input', handler)
|
||||||
|
elem.addEventListener('updatedByJavascript', handler)
|
||||||
|
elem.dispatchEvent(new Event('updatedByJavascript'))
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -26,9 +26,14 @@ const { id, label, checked = false } = Astro.props;
|
||||||
|
|
||||||
@switch-width: 2.5rem;
|
@switch-width: 2.5rem;
|
||||||
@switch-height: @switch-width * 0.5;
|
@switch-height: @switch-width * 0.5;
|
||||||
|
@switch-padding: @switch-width * 0.08;
|
||||||
@switch-bdrs: @switch-width * 0.4;
|
@switch-bdrs: @switch-width * 0.4;
|
||||||
@circle-size: @switch-width * 0.4;
|
@circle-size: @switch-width * 0.4;
|
||||||
@circle-margin: @switch-width * 0.04;
|
@circle-margin: @switch-width * 0.05;
|
||||||
|
|
||||||
|
.input-wrapper {
|
||||||
|
padding-top: @switch-padding;
|
||||||
|
}
|
||||||
|
|
||||||
.switch {
|
.switch {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|
|
@ -1,22 +1,48 @@
|
||||||
---
|
---
|
||||||
|
import Input from '../layouts/Input.astro';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
value?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
regex?: string | null;
|
regex?: string;
|
||||||
|
size?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id, label, placeholder = "", regex = null } = Astro.props;
|
const { id, label, value = "", placeholder = "", regex = ".*", size = 15 } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<label>
|
<Input label={label}>
|
||||||
<span class="label">{label}</span>
|
<span slot="after">
|
||||||
<input type="text" name={id} id={id} placeholder={placeholder} pattern={regex}>
|
<input type="text" name={id} id={id} value={value} placeholder={placeholder} pattern={regex} size={size}>
|
||||||
</label>
|
</span>
|
||||||
|
</Input>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
input {
|
input {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
padding: 0.2rem;
|
||||||
|
|
||||||
background: var(--sec-bg);
|
background: var(--sec-bg);
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
|
||||||
|
outline: 0;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 0.125rem solid var(--bg-sec);
|
||||||
|
transition: border-bottom-color 0.2s ease 0s;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-bottom-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-bottom-color: var(--accent-hl);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: var(--fg-sec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,21 +1,42 @@
|
||||||
---
|
---
|
||||||
|
import Input from "../layouts/Input.astro";
|
||||||
import Modal from "../layouts/Modal.astro";
|
import Modal from "../layouts/Modal.astro";
|
||||||
|
import ColorBtn from "./ColorBtn.astro";
|
||||||
|
import Slider from "./Slider.astro";
|
||||||
import Switch from "./Switch.astro";
|
import Switch from "./Switch.astro";
|
||||||
import TextBox from "./TextBox.astro";
|
import TextBox from "./TextBox.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Modal id="theme">
|
<Modal id="theme">
|
||||||
<noscript>
|
<noscript class="hint">
|
||||||
These options will <b>not</b> work without JavaScript
|
These options will <b>not</b> work without JavaScript
|
||||||
</noscript>
|
</noscript>
|
||||||
|
<fieldset class="first">
|
||||||
<Switch id="dark" label="Dark theme" checked />
|
<Switch id="dark" label="Dark theme" checked />
|
||||||
<Switch id="custom-theme" label="Set custom colors" />
|
<Switch id="custom-theme" label="Advanced (βeta)" />
|
||||||
|
</fieldset>
|
||||||
<section id="custom-colors">
|
<section id="custom-colors">
|
||||||
<TextBox id="accent" label="Accent color" placeholder="HEX (#fff)" regex="#?(?:[A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})" />
|
<label class="hint">
|
||||||
<label>
|
You may need to reload the page
|
||||||
<span class="label">Accent color</span>
|
after enabling/disabling "Advanced"
|
||||||
<input type="color" name="accent" id="accent">
|
|
||||||
</label>
|
</label>
|
||||||
|
<fieldset>
|
||||||
|
<Switch id="purebg" label="Pure background" />
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<TextBox id="accent" label="Accent color" placeholder="HEX (#fff)" regex="#?(?:[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})" size={7} />
|
||||||
|
<Input label="">
|
||||||
|
<span class="color-btns" slot="after">
|
||||||
|
<ColorBtn name="red" hex="#ba505a" />
|
||||||
|
<ColorBtn name="yellow" hex="#b9aa50" />
|
||||||
|
<ColorBtn name="green" hex="#5bab65" />
|
||||||
|
<ColorBtn name="blue" hex="#6570d6" />
|
||||||
|
</span>
|
||||||
|
</Input>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<Slider id="bdrs" label="Border radius" min={0} max={4} value={2} />
|
||||||
|
</fieldset>
|
||||||
</section>
|
</section>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
@ -28,137 +49,189 @@ import TextBox from "./TextBox.astro";
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.color-btns {
|
||||||
|
margin-top: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint {
|
||||||
|
width: 18rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--fg-sec);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const colorsSection = document.getElementById('custom-colors')
|
var lessLoaded = false
|
||||||
|
|
||||||
class ThemingOption {
|
class ThemingOption {
|
||||||
private cookieKey: string
|
input: HTMLInputElement | undefined
|
||||||
private cookieSwitch: Array<string | RegExp>
|
onchange:
|
||||||
private callback: (input: HTMLInputElement, state: boolean) => any
|
(opt: ThemingOption, upd: boolean) => any =
|
||||||
private getval: (input: HTMLInputElement) => any
|
(_opt, _upd) => {}
|
||||||
private media: string | null
|
|
||||||
|
|
||||||
private _input: HTMLInputElement | null
|
|
||||||
get input() { return this._input }
|
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
cookieKey: string,
|
inputId: string,
|
||||||
cookieSwitch: Array<string | RegExp> | null,
|
onchange: (opt: ThemingOption, upd: boolean) => any
|
||||||
callback: (input: HTMLInputElement, state: boolean) => any,
|
|
||||||
getval: (input: HTMLInputElement) => any,
|
|
||||||
input: HTMLInputElement | null = null,
|
|
||||||
media: string | null = null,
|
|
||||||
) {
|
) {
|
||||||
this.cookieKey = cookieKey
|
this.input = document.getElementById(inputId) as HTMLInputElement
|
||||||
this.cookieSwitch = cookieSwitch
|
this.onchange = onchange
|
||||||
this.callback = callback
|
|
||||||
this.getval = getval
|
|
||||||
this._input = input
|
|
||||||
this.media = media
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
this.onchange(this, false)
|
||||||
function themeCheck() {
|
if (!this.input) return
|
||||||
if (
|
this.input.addEventListener(
|
||||||
document.cookie.includes('dc09_dark=1') || (
|
'input',
|
||||||
matchMedia('(prefers-color-scheme: dark)') &&
|
() => this.onchange(this, true),
|
||||||
!document.cookie.includes('dc09_dark=0')
|
|
||||||
)
|
)
|
||||||
) {
|
|
||||||
document.body.dataset.dark = '1'
|
|
||||||
switchDark.checked = true
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
document.body.dataset.dark = '0'
|
|
||||||
switchDark.checked = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Here is the rewritten themeCheck:
|
/** Converts string to boolean, mainly for localStorage.
|
||||||
|
* Returned `null` means that the key was unset.
|
||||||
*/
|
*/
|
||||||
check() {
|
const toBool = (val: string | null) => {
|
||||||
const match = this.cookieSwitch.map(
|
switch (val) {
|
||||||
value => document.cookie.match(
|
case undefined:
|
||||||
`${this.cookieKey}=${value}`
|
case null:
|
||||||
|
case '':
|
||||||
|
return null
|
||||||
|
case 'false':
|
||||||
|
case '0':
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const colorRegex = /#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/
|
||||||
|
/** Parses color-like string and
|
||||||
|
* returns the color in the general format.
|
||||||
|
* Returned `undefined` means that it's not a color.
|
||||||
|
* If `val` is `null`, returns `null`.
|
||||||
|
*/
|
||||||
|
const toColor = (val: string | null) => {
|
||||||
|
if (!val) return null
|
||||||
|
return (val.match(colorRegex) || [])[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
new ThemingOption(
|
||||||
|
'dark',
|
||||||
|
(opt, upd) => {
|
||||||
|
if (upd) {
|
||||||
|
const state = opt.input.checked
|
||||||
|
localStorage.setItem('dc09_dark', state ? '1' : '0')
|
||||||
|
return opt.onchange(opt, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const stored = toBool(localStorage.getItem('dc09_dark'))
|
||||||
|
const media = matchMedia('(prefers-color-scheme: dark)')
|
||||||
|
|
||||||
|
const state = (
|
||||||
|
stored || (
|
||||||
|
stored === null &&
|
||||||
|
media.matches
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
opt.input.checked = state
|
||||||
|
document.body.dataset.dark = state ? '1' : '0'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
const purebgOpt = new ThemingOption(
|
||||||
match[1] || (
|
'purebg', // pure background
|
||||||
this.media && !match[0] &&
|
(opt, upd) => {
|
||||||
matchMedia(this.media).matches
|
if (upd) {
|
||||||
|
const state = opt.input.checked
|
||||||
|
localStorage.setItem('dc09_purebg', state ? '1' : '0')
|
||||||
|
reloadTheme()
|
||||||
|
return opt.onchange(opt, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
opt.input.checked = toBool(localStorage.getItem('dc09_purebg'))
|
||||||
|
}
|
||||||
)
|
)
|
||||||
) {
|
|
||||||
if (this.callback)
|
const accentOpt = new ThemingOption(
|
||||||
this.callback(this._input, true)
|
'accent',
|
||||||
|
(opt, upd) => {
|
||||||
|
if (upd) {
|
||||||
|
if (!opt.input.validity.valid) return
|
||||||
|
const color = toColor(opt.input.value)
|
||||||
|
if (!color) return
|
||||||
|
localStorage.setItem('dc09_accent', color)
|
||||||
|
reloadTheme()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.callback)
|
const color = localStorage.getItem('dc09_accent') || '6570d6'
|
||||||
this.callback(this._input, false)
|
opt.input.value = color
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
|
||||||
const value = this.getval(this._input)
|
|
||||||
const localhost = window.location.hostname == 'localhost'
|
|
||||||
const domain = localhost ? 'localhost' : 'dc09.ru'
|
|
||||||
const cookie = `${this.cookieKey}=${value};domain=${domain};samesite=lax`
|
|
||||||
document.cookie = cookie
|
|
||||||
this.check()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const opts = {
|
|
||||||
dark: new ThemingOption(
|
|
||||||
'dc09_dark', ['0', '1'],
|
|
||||||
(input: HTMLInputElement, state: boolean) => {
|
|
||||||
input.checked = state
|
|
||||||
document.body.dataset.dark = state ? '1' : '0'
|
|
||||||
},
|
|
||||||
(input: HTMLInputElement) => input.checked ? 1 : 0,
|
|
||||||
document.getElementById('dark') as HTMLInputElement,
|
|
||||||
'(prefers-color-scheme: dark)',
|
|
||||||
),
|
|
||||||
|
|
||||||
custom: new ThemingOption(
|
|
||||||
'dc09_custom', ['0', '1'],
|
|
||||||
(input: HTMLInputElement, state: boolean) => {
|
|
||||||
input.checked = state
|
|
||||||
colorsSection.dataset.show = state ? '1' : '0'
|
|
||||||
if (state)
|
|
||||||
loadCustomTheme()
|
|
||||||
},
|
|
||||||
(input: HTMLInputElement) => input.checked ? 1 : 0,
|
|
||||||
document.getElementById('custom-theme') as HTMLInputElement,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const bdrsOpt = new ThemingOption(
|
||||||
|
'bdrs', // border-radius, as in Emmet
|
||||||
|
(opt, upd) => {
|
||||||
|
if (upd) {
|
||||||
|
const value = opt.input.value
|
||||||
|
localStorage.setItem('dc09_bdrs', value)
|
||||||
|
reloadTheme()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let optObj of Object.values(opts)) {
|
let value = Number(localStorage.getItem('dc09_bdrs'))
|
||||||
((opt) => {
|
value = isNaN(value) ? 2 : value
|
||||||
opt.check()
|
opt.input.value = String(value)
|
||||||
opt.input.addEventListener('input', () => opt.update())
|
opt.input.dispatchEvent(new Event('updatedByJavascript'))
|
||||||
})(optObj)
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const colorsSection = document.getElementById('custom-colors')
|
||||||
|
new ThemingOption(
|
||||||
|
'custom-theme',
|
||||||
|
(opt, upd) => {
|
||||||
|
if (upd) {
|
||||||
|
const state = opt.input.checked
|
||||||
|
localStorage.setItem('dc09_custom', state ? '1' : '0')
|
||||||
|
return opt.onchange(opt, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadCustomTheme() {
|
const state = toBool(localStorage.getItem('dc09_custom'))
|
||||||
// Load `theme.less`
|
opt.input.checked = state
|
||||||
|
colorsSection.dataset.show = state ? '1' : '0'
|
||||||
|
|
||||||
|
if (state)
|
||||||
|
reloadLess()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
function reloadLess() {
|
||||||
|
if (!lessLoaded) {
|
||||||
|
// Load `theme_dyn.less`
|
||||||
const lessStyles = document.createElement('link')
|
const lessStyles = document.createElement('link')
|
||||||
lessStyles.rel = 'stylesheet/less'
|
lessStyles.rel = 'stylesheet/less'
|
||||||
lessStyles.type = 'text/css'
|
lessStyles.type = 'text/css'
|
||||||
lessStyles.href = '/src/styles/theme.less'
|
lessStyles.href = '/theme_dyn.less'
|
||||||
document.head.append(lessStyles)
|
document.head.append(lessStyles)
|
||||||
// Load LessCSS script element
|
// Create LessCSS script element
|
||||||
const lessScript = document.createElement('script')
|
const lessScript = document.createElement('script')
|
||||||
lessScript.src = 'https://cdn.jsdelivr.net/npm/less'
|
lessScript.src = '/less.min.js'
|
||||||
// Replace variables
|
// Modify variables when less is loaded
|
||||||
lessScript.onload = () => {
|
lessScript.addEventListener('load', reloadTheme)
|
||||||
eval('less').modifyVars({
|
// Load LessCSS script
|
||||||
'accent': '#50aa70',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// Load LessCSS
|
|
||||||
document.head.append(lessScript)
|
document.head.append(lessScript)
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
reloadTheme()
|
||||||
|
}
|
||||||
|
|
||||||
|
function reloadTheme() {
|
||||||
|
const accent = '#' + toColor(accentOpt.input.value)
|
||||||
|
const bdrs = Number(bdrsOpt.input.value)
|
||||||
|
const purebg = purebgOpt.input.checked
|
||||||
|
eval('less').modifyVars({
|
||||||
|
accent: accent,
|
||||||
|
bdrs: `${bdrs}rem`,
|
||||||
|
purebg: purebg,
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,26 +1,47 @@
|
||||||
---
|
---
|
||||||
export interface Props {
|
export interface Props {
|
||||||
label: string;
|
label: string;
|
||||||
|
column?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { label } = Astro.props;
|
const { label, column = false } = Astro.props;
|
||||||
|
|
||||||
|
const flexDirection = column ? "column" : "row";
|
||||||
|
const flexAlign = column ? "start" : "center";
|
||||||
|
const cursor = column ? "normal" : "pointer";
|
||||||
---
|
---
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
<slot name="before" />
|
<slot name="before" />
|
||||||
<span class="label">{label}</span>
|
<slot name="label">
|
||||||
|
<span class="label">
|
||||||
|
{label}
|
||||||
|
</span>
|
||||||
|
</slot>
|
||||||
<slot name="after" />
|
<slot name="after" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less" define:vars={{ flexDirection, flexAlign, cursor }}>
|
||||||
label {
|
label {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: var(--flexDirection);
|
||||||
align-items: center;
|
align-items: var(--flexAlign);
|
||||||
cursor: pointer;
|
cursor: var(--cursor);
|
||||||
|
|
||||||
&:not(:first-of-type) {
|
margin-top: 0.5rem;
|
||||||
margin-top: 0.25rem;
|
}
|
||||||
|
|
||||||
|
:global(fieldset) {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&.first > label:first-of-type {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > label:not(:first-of-type) {
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
---
|
---
|
||||||
import Menu from '../components/Menu.astro';
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { title } = Astro.props;
|
const { title, description } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
@ -14,21 +13,22 @@ const { title } = Astro.props;
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
<meta name="generator" content={Astro.generator} />
|
<meta name="generator" content={Astro.generator} />
|
||||||
<meta name="description" content="Hi! I'm Andrew aka DarkCat09, a 13-years-old fullstack developer from Russia" />
|
<meta name="description" content={description} />
|
||||||
|
<slot name="metadata" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<Menu />
|
|
||||||
<slot />
|
<slot />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
<style lang="less" is:global>
|
<style lang="less" is:global>
|
||||||
|
|
||||||
@import "/src/styles/theme.less";
|
@import "/src/styles/theme.less";
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
.theme-mixin();
|
||||||
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
|
@ -46,10 +46,22 @@ const { title } = Astro.props;
|
||||||
max-width: 300rem;
|
max-width: 300rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
article {
|
||||||
|
max-width: 100vw;
|
||||||
|
width: fit-content;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
section {
|
section {
|
||||||
margin: 0.5rem 0;
|
margin: 0.5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border: 0.125rem dashed var(--bg-sec);
|
||||||
|
border-radius: var(--bdrs);
|
||||||
|
padding: 0.625rem;
|
||||||
|
}
|
||||||
|
|
||||||
hgroup > * {
|
hgroup > * {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
|
@ -63,7 +75,7 @@ const { title } = Astro.props;
|
||||||
h1 { font-size: 2.4rem; }
|
h1 { font-size: 2.4rem; }
|
||||||
|
|
||||||
a, .link {
|
a, .link {
|
||||||
color: var(--accent);
|
color: var(--accent-fg);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
24
src/layouts/MainLayout.astro
Normal file
24
src/layouts/MainLayout.astro
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
---
|
||||||
|
import Layout from "./Layout.astro";
|
||||||
|
import Menu from "./Menu.astro";
|
||||||
|
import MenuItem from "../components/MenuItem.astro";
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
page: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { page, description } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout title={"DarkCat09 | " + page} description={description}>
|
||||||
|
<Menu>
|
||||||
|
<MenuItem name="Homepage" icon="" link="/" />
|
||||||
|
<MenuItem name="Projects" icon="" link="/projects" />
|
||||||
|
<MenuItem name="Services" icon="" link="/services" />
|
||||||
|
<MenuItem name="Blog" icon="" link="/blog" />
|
||||||
|
</Menu>
|
||||||
|
<main>
|
||||||
|
<slot />
|
||||||
|
</main>
|
||||||
|
</Layout>
|
32
src/layouts/Menu.astro
Normal file
32
src/layouts/Menu.astro
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
import MenuItem from "../components/MenuItem.astro";
|
||||||
|
import ThemeModal from "../components/ThemeModal.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<ThemeModal />
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
<slot />
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<MenuItem name="Theme" icon="" link="#theme" />
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
nav {
|
||||||
|
margin: 0.4rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -56,7 +56,7 @@ const { id } = Astro.props;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
z-index: 102;
|
z-index: 102;
|
||||||
|
|
||||||
border-radius: 2rem;
|
border-radius: var(--bdrs);
|
||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,36 +1,103 @@
|
||||||
---
|
---
|
||||||
import Layout from '../layouts/Layout.astro';
|
import MainLayout from '../layouts/MainLayout.astro';
|
||||||
import Profile from '../components/Profile.astro';
|
import Profile from '../components/Profile.astro';
|
||||||
|
import ListItem from '../components/ListItem.astro';
|
||||||
|
|
||||||
|
const description =
|
||||||
|
"Hi! I'm Andrew aka DarkCat09, " +
|
||||||
|
"a 13-years-old fullstack developer from Russia";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="DarkCat09 | Homepage">
|
<MainLayout page="Homepage" description={description}>
|
||||||
<main>
|
<article class="centered">
|
||||||
<hgroup>
|
<hgroup>
|
||||||
<h1>Hi! I'm Andrew.</h1>
|
<h1>Hi! I'm Andrew.</h1>
|
||||||
<h2>13-years-old fullstack dev</h2>
|
<h2><span id="age">13</span>-years-old fullstack dev</h2>
|
||||||
</hgroup>
|
</hgroup>
|
||||||
<section id="profiles">
|
<section id="profiles">
|
||||||
<Profile app="Gitea" icon="" name="DarkCat09" url="https://git.dc09.ru/DarkCat09" />
|
<Profile app="Gitea" icon="" name="DarkCat09" url="https://git.dc09.ru/DarkCat09" />
|
||||||
<Profile app="GitHub" icon="" name="DarkCat09" url="https://github.com/DarkCat09" />
|
<Profile app="GitHub" icon="" name="DarkCat09" url="https://github.com/DarkCat09" />
|
||||||
<Profile app="E-mail" icon="" name="darkcat09@vivaldi.net" url="mailto:darkcat09@vivaldi.net" copyName />
|
<Profile app="E-mail" icon="" name="darkcat09@vivaldi.net" url="mailto:darkcat09@vivaldi.net" copyName />
|
||||||
<Profile app="Telegram" icon="" name="@darkcat09" url="https://t.me/darkcat09" />
|
<Profile app="Telegram" icon="" name="@darkcat09" url="https://t.me/darkcat09" />
|
||||||
<Profile app="Matrix" icon="" name="darkcat09@dc09.ru" url="https://matrix.to/#/@darkcat09:dc09.ru" copyName />
|
<Profile app="Matrix" icon="" name="darkcat09:dc09.ru" url="https://matrix.to/#/@darkcat09:dc09.ru" copyName />
|
||||||
<Profile app="Discord" icon="" name="DarkCat09#5587" url="https://discord.com/app" copyName />
|
<Profile app="Discord" icon="" name="DarkCat09#5587" url="https://discord.com/app" copyName />
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</article>
|
||||||
</Layout>
|
<article class="card" id="about">
|
||||||
|
<ul>
|
||||||
|
<ListItem icon="">
|
||||||
|
<a href="https://t.me/dc09about" target="_blank">
|
||||||
|
https://t.me/dc09about
|
||||||
|
</a>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem icon="">
|
||||||
|
Russia, Ulyanovsk
|
||||||
|
</ListItem>
|
||||||
|
<ListItem icon="">
|
||||||
|
Favorite music bands:
|
||||||
|
</ListItem>
|
||||||
|
<ListItem icon="">
|
||||||
|
<ul>
|
||||||
|
<li>Linkin Park</li>
|
||||||
|
<li>One Direction</li>
|
||||||
|
<li>Set It Off</li>
|
||||||
|
<li>Дайте танк (!)</li>
|
||||||
|
<li>Научно-технический рэп</li>
|
||||||
|
<li>Imagine Dragons</li>
|
||||||
|
</ul>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem icon="">
|
||||||
|
Favorite OS: Manjaro Linux
|
||||||
|
</ListItem>
|
||||||
|
<ListItem icon="">
|
||||||
|
<code>
|
||||||
|
<b>CPU:</b> 6-core Intel Core i5-10400 (-MT MCP-) <b>speed/min/max:</b> 2725/800/4300 MHz<br />
|
||||||
|
<b>Kernel:</b> 6.3.4-1-MANJARO x86_64 <b>Up:</b> 3h 32m <b>Mem:</b> 6763.3/30935.8 MiB (21.9%)<br />
|
||||||
|
<b>Storage:</b> 1.36 TiB (15.8% used) <b>Procs:</b> 303 <b>Shell:</b> Zsh <b>inxi:</b> 3.3.27
|
||||||
|
</code>
|
||||||
|
</ListItem>
|
||||||
|
</ul>
|
||||||
|
</article>
|
||||||
|
</MainLayout>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import "/src/styles/profile_calc.less";
|
||||||
|
|
||||||
#profiles {
|
#profiles {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(1, auto);
|
grid-template-columns: repeat(1, auto);
|
||||||
|
|
||||||
@media (min-width: 450px) {
|
@media (min-width: @profile-width * 2) {
|
||||||
grid-template-columns: repeat(2, auto);
|
grid-template-columns: repeat(2, auto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 670px) {
|
@media (min-width: @profile-width * 3) {
|
||||||
grid-template-columns: repeat(3, auto);
|
grid-template-columns: repeat(3, auto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#about > ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: 'Hack', 'Liberation Mono', 'Source Code Pro', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// in milliseconds
|
||||||
|
const ageMs = Date.now() - 1247481000000
|
||||||
|
|
||||||
|
// in years
|
||||||
|
let age = ageMs / (1000 * 60 * 60 * 24 * 365.25)
|
||||||
|
|
||||||
|
// fallback to default value
|
||||||
|
// + rounding
|
||||||
|
age = (age < 13 ? 13 : Math.floor(age))
|
||||||
|
|
||||||
|
document.getElementById('age').innerText = String(age)
|
||||||
|
</script>
|
||||||
|
|
9
src/styles/profile_calc.less
Normal file
9
src/styles/profile_calc.less
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
@profile-icon-app: 2.3rem;
|
||||||
|
@profile-icon-copy: 1.8rem;
|
||||||
|
|
||||||
|
@profile-text-width: 9.5rem;
|
||||||
|
|
||||||
|
@profile-icon-margin: 0.4rem;
|
||||||
|
@profile-horiz-padding: 0.6rem;
|
||||||
|
|
||||||
|
@profile-width: @profile-horiz-padding + @profile-icon-app + @profile-icon-margin + @profile-text-width + @profile-icon-margin + @profile-icon-copy + @profile-horiz-padding;
|
|
@ -1,30 +1,50 @@
|
||||||
@accent: #5070ca;
|
.theme-mixin(@accent: #6570d6, @bdrs: 2rem, @purebg: false) {
|
||||||
|
|
||||||
body {
|
@bg-pure-light: #fff;
|
||||||
@bg-light: #fff;
|
@bg-colored-light: hsl(
|
||||||
@fg-light: #202020;
|
hue(@accent),
|
||||||
|
15%, 95%,
|
||||||
|
);
|
||||||
|
|
||||||
@bg-dark: #222229;
|
@bg-light: if(@purebg, @bg-pure-light, @bg-colored-light); // background
|
||||||
@fg-dark: #eee;
|
@fg-light: #202020; // foreground
|
||||||
|
|
||||||
|
@bg-pure-dark: #222;
|
||||||
|
@bg-colored-dark: hsl(
|
||||||
|
hue(@accent),
|
||||||
|
5%, 15%,
|
||||||
|
);
|
||||||
|
|
||||||
|
@bg-dark: if(@purebg, @bg-pure-dark, @bg-colored-dark); // background
|
||||||
|
@fg-dark: #eee; // foreground
|
||||||
|
|
||||||
--accent: @accent;
|
--accent: @accent;
|
||||||
|
--bdrs: @bdrs;
|
||||||
|
|
||||||
.light-mixin() {
|
.light-mixin() {
|
||||||
--bg: @bg-light;
|
--bg: @bg-light;
|
||||||
--fg: @fg-light;
|
--fg: @fg-light;
|
||||||
|
|
||||||
--bg-sec: darken(@bg-light, 30%);
|
--bg-sec: darken(@bg-light, 30%);
|
||||||
--fg-sec: lighten(@fg-light, 15%);
|
--fg-sec: lighten(@fg-light, 25%);
|
||||||
--accent-bg: darken(@bg-light, 10%);
|
|
||||||
--accent-hl: darken(@accent, 15%);
|
@accent-fg: darken(@accent, 7%);
|
||||||
|
--accent-bg: darken(@bg-light, 8%);
|
||||||
|
--accent-fg: @accent-fg;
|
||||||
|
--accent-hl: darken(@accent-fg, 15%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-mixin() {
|
.dark-mixin() {
|
||||||
--bg: @bg-dark;
|
--bg: @bg-dark;
|
||||||
--fg: @fg-dark;
|
--fg: @fg-dark;
|
||||||
|
|
||||||
--bg-sec: lighten(@bg-dark, 15%);
|
--bg-sec: lighten(@bg-dark, 15%);
|
||||||
--fg-sec: darken(@bg-light, 25%);
|
--fg-sec: darken(@fg-dark, 30%);
|
||||||
|
|
||||||
|
@accent-fg: lighten(@accent, 7%);
|
||||||
--accent-bg: lighten(@bg-dark, 5%);
|
--accent-bg: lighten(@bg-dark, 5%);
|
||||||
--accent-hl: lighten(@accent, 15%);
|
--accent-fg: @accent-fg;
|
||||||
|
--accent-hl: lighten(@accent-fg, 15%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-mixin();
|
.dark-mixin();
|
||||||
|
|
Loading…
Add table
Reference in a new issue