Compare commits

...

17 Commits

Author SHA1 Message Date
Lucien Cartier-Tilet b6e9ebf100
[Dart] Bump localStorage timestamp 2021-03-30 20:41:46 +02:00
Lucien Cartier-Tilet d645e29ce5
[SCSS, some dart] Theme rework, dark dropped, nord replaces dark
The old dark mode is dropped and replaced with nord. Light and black
themes were also rebased on the Nord theme.

Code blocks now appear the same way my terminal windows appear in my
Linux configuration, emulating a side titlebar.
2021-03-30 19:26:30 +02:00
Lucien Cartier-Tilet 291fc9111b
[dart] Upgrade to Dart 2.12 and its null-safety features 2021-03-30 18:54:31 +02:00
Lucien Cartier-Tilet 0e8e894056
[Style] add twitter card styling 2021-02-12 11:39:54 +01:00
Lucien Cartier-Tilet add728eb6d
[Style] Better titles display 2021-01-28 19:49:46 +01:00
Lucien Cartier-Tilet 6e30e3f361
Add before content for fish and rust source blocks 2021-01-02 14:18:45 +01:00
Lucien Cartier-Tilet f9e0ffa0eb
Add explicit size to header image, bump last update date 2020-12-21 20:38:24 +01:00
Lucien Cartier-Tilet 9632b008ac
Replace header image extension with webp 2020-12-21 20:29:25 +01:00
Lucien Cartier-Tilet 4cd74fd9b4
[Style] Make both SVGs and images centered 2020-12-21 16:05:28 +01:00
Lucien Cartier-Tilet 5355576443
Handle SVGs like images 2020-12-07 16:03:33 +01:00
Lucien Cartier-Tilet 975b5d3fb3
Make build dependencies not fixed to a specific version 2020-12-07 16:03:15 +01:00
Lucien Cartier-Tilet f0847a622f
Fix theme for pre tags with example class 2020-12-06 01:20:42 +01:00
Lucien Cartier-Tilet e69b9fb9c8
Image in header now round 2020-12-06 01:17:29 +01:00
Lucien Cartier-Tilet 16f23c08c6
[Dart] Cleaner code, force the web page to reload on modifier code
The code in `navbar.dart' is now more declarative and cleaner.

If the `lastUpdate' variable’s content change, then it will force the
user to reload the page, bypassing their cache. This can be useful in
case of an update with which the cache could break the website.
2020-08-28 22:23:35 +02:00
Lucien Cartier-Tilet e710c594f1
[Style] Add Nord theme, break up SCSS code
This commit adds the Nord theme into the list of available themes. The
Nord theme is now the default theme for dark-based systems.

Theme buttons now have their own class to make it easier to change
them without too much work.

The `style.scss' file has been split up in three different files:
- main.scss, the new file to load from the HTML page, imports the two
    other files
- themes.scss, containing all the theming of the websites
- style.scss, containing the rest

All websites loading the theme will now need to load it from
`main.scss' instead of `style.scss', likewise with the `.css'
extension
2020-08-28 22:19:42 +02:00
Lucien Cartier-Tilet e4dc101346
fix for dropdown pages 2020-08-28 17:13:31 +02:00
Lucien Cartier-Tilet f99d45e8ab
Simplify code, remove html dependency
This commit removes the `html' package dependency, speeding up the
compile time of the Dart code.

It also simplifies the code and removes some unused code. For instance
the sun, moon, and lightbulb icons is removed, the `Theme' class is
removed, and the `switchTheme' function is now merged into the
`setTheme' function. The `makeThemeItem' function has also had its
second argument removed.
2020-08-25 03:34:55 +02:00
10 changed files with 416 additions and 396 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@
/.sass-cache/
/build/
*.scssc
/Book.html

View File

@ -5,12 +5,11 @@ homepage: https://labs.phundrak.com/phundrak/org-website-backend
author: Lucien Cartier-Tilet <lucien@phundrak.com>
environment:
sdk: '>=2.7.0 <3.0.0'
sdk: '>=2.12.0 <3.0.0'
dependencies:
html: '^0.14.0+3'
dev_dependencies:
build_runner: ^1.8.0
build_web_compilers: ^2.9.0
pedantic: ^1.9.0
build_runner: ">=1.10.1 <2.0.0"
build_web_compilers: ">=2.9.0 <3.0.0"
pedantic: ">=1.9.0 <2.0.0"

View File

@ -4,7 +4,8 @@ import './theme.dart' show enableThemeChanger, setTheme;
Future<void> main() async {
await setTheme();
await reorganizeHtml()
.then((_) => enableThemeChanger())
.then((_) => createSitemap());
await reorganizeHtml().then((_) {
enableThemeChanger();
createSitemap();
});
}

View File

@ -1,5 +1,5 @@
import 'dart:html';
import 'dart:svg';
import 'dart:html' show querySelector, Element, window;
import 'dart:svg' show SvgElement;
// You will see here and there some 'tabindex' attributes added to various HTML
// elements, and Im sure you will ask "Why? They dont serve any purpose, do
@ -32,16 +32,10 @@ final icons = {
'<svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2.04C6.5 2.04 2 6.53 2 12.06C2 17.06 5.66 21.21 10.44 21.96V14.96H7.9V12.06H10.44V9.85C10.44 7.34 11.93 5.96 14.22 5.96C15.31 5.96 16.45 6.15 16.45 6.15V8.62H15.19C13.95 8.62 13.56 9.39 13.56 10.18V12.06H16.34L15.89 14.96H13.56V21.96A10 10 0 0 0 22 12.06C22 6.53 17.5 2.04 12 2.04Z" /></svg>'),
'theme': SvgElement.svg(
'<svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="currentColor" d="M12,18V6A6,6 0 0,1 18,12A6,6 0 0,1 12,18M20,15.31L23.31,12L20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31Z" /></svg>'),
'sun': SvgElement.svg(
'<svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="currentColor" d="M3.55,18.54L4.96,19.95L6.76,18.16L5.34,16.74M11,22.45C11.32,22.45 13,22.45 13,22.45V19.5H11M12,5.5A6,6 0 0,0 6,11.5A6,6 0 0,0 12,17.5A6,6 0 0,0 18,11.5C18,8.18 15.31,5.5 12,5.5M20,12.5H23V10.5H20M17.24,18.16L19.04,19.95L20.45,18.54L18.66,16.74M20.45,4.46L19.04,3.05L17.24,4.84L18.66,6.26M13,0.55H11V3.5H13M4,10.5H1V12.5H4M6.76,4.84L4.96,3.05L3.55,4.46L5.34,6.26L6.76,4.84Z" /></svg>'),
'lightbulb': SvgElement.svg(
'<svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="currentColor" d="M12,6A6,6 0 0,1 18,12C18,14.22 16.79,16.16 15,17.2V19A1,1 0 0,1 14,20H10A1,1 0 0,1 9,19V17.2C7.21,16.16 6,14.22 6,12A6,6 0 0,1 12,6M14,21V22A1,1 0 0,1 13,23H11A1,1 0 0,1 10,22V21H14M20,11H23V13H20V11M1,11H4V13H1V11M13,1V4H11V1H13M4.92,3.5L7.05,5.64L5.63,7.05L3.5,4.93L4.92,3.5M16.95,5.63L19.07,3.5L20.5,4.93L18.37,7.05L16.95,5.63Z" /></svg>'),
'moon': SvgElement.svg(
'<svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="currentColor" d="M17.75,4.09L15.22,6.03L16.13,9.09L13.5,7.28L10.87,9.09L11.78,6.03L9.25,4.09L12.44,4L13.5,1L14.56,4L17.75,4.09M21.25,11L19.61,12.25L20.2,14.23L18.5,13.06L16.8,14.23L17.39,12.25L15.75,11L17.81,10.95L18.5,9L19.19,10.95L21.25,11M18.97,15.95C19.8,15.87 20.69,17.05 20.16,17.8C19.84,18.25 19.5,18.67 19.08,19.07C15.17,23 8.84,23 4.94,19.07C1.03,15.17 1.03,8.83 4.94,4.93C5.34,4.53 5.76,4.17 6.21,3.85C6.96,3.32 8.14,4.21 8.06,5.04C7.79,7.9 8.75,10.87 10.95,13.06C13.14,15.26 16.1,16.22 18.97,15.95M17.33,17.97C14.5,17.81 11.7,16.64 9.53,14.5C7.36,12.31 6.2,9.5 6.04,6.68C3.23,9.82 3.34,14.64 6.35,17.66C9.37,20.67 14.19,20.78 17.33,17.97Z" /></svg>'),
};
// Get the current pages title
String getPageTitle() => querySelector('title').text;
String getPageTitle() => querySelector('title')!.text!;
// Create the home button
Future<Element> makeHome() async {
@ -51,29 +45,27 @@ Future<Element> makeHome() async {
'afterBegin',
Element.a()
..attributes['href'] = '/'
..append(makeIcon(icons['home'])));
..append(makeIcon(icons['home']!)));
}
// Create a clickable icon
// `t_elem` must be an SVG declared in the above `icons` variable.
Element makeIcon(SvgElement t_elem) {
final icon = t_elem..classes.add('nav-icon');
return icon;
return t_elem..classes.add('nav-icon');
}
// Create the dropdown sitemap
Future<Element> makePages() async {
var pages = Element.ul()
..attributes['id'] = 'drop-page'
..classes.add('dropdown');
return Element.li()
..attributes['tabindex'] = '0'
..append(Element.a()
..attributes['tabindex'] = '-1'
..attributes['href'] = 'javascript:void(0)'
..append(makeIcon(icons['pages'])))
..append(makeIcon(icons['pages']!)))
..classes.addAll(['nav-item', 'has-dropdown'])
..append(pages);
..append(Element.ul()
..attributes['id'] = 'drop-page'
..classes.add('dropdown'));
}
// Create the array of share icons
@ -95,32 +87,34 @@ Future<Element> makeShare() async {
..append(Element.a()
..attributes['href'] = 'javascript:void(0)'
..attributes['tabindex'] = '-1'
..append(makeIcon(icons['share'])))
..append(makeIcon(icons['share']!)))
..append(Element.ul()
..classes.add('dropdown')
..attributes['id'] = 'drop-share'
..append(makeShareLink(
makeIcon(icons['twitter']),
makeIcon(icons['twitter']!),
'https://twitter.com/share?text=${getPageTitle()}'
'&url=${window.location.href}'))
..append(makeShareLink(makeIcon(icons['reddit']),
..append(makeShareLink(makeIcon(icons['reddit']!),
'https://www.reddit.com/submit?title=${getPageTitle()}s&url=${window.location.href}'))
..append(makeShareLink(makeIcon(icons['email']),
'mailto:?subject=${getPageTitle}&body=${window.location.href}'))
..append(makeShareLink(makeIcon(icons['email']!),
'mailto:?subject=$getPageTitle&body=${window.location.href}'))
..append(makeShareLink(
makeIcon(icons['linkedin']),
makeIcon(icons['linkedin']!),
'https://www.linkedin.com/shareArticle?mini=true&url=${window.location.href}'
'&title=${getPageTitle()}'))
..append(makeShareLink(makeIcon(icons['facebook']),
..append(makeShareLink(makeIcon(icons['facebook']!),
'https://www.facebook.com/sharer/sharer.php?u=${window.location.href}')));
}
// Create the theme changer
Future<Element> makeThemeChanger() async {
Element makeThemeItem(String t_btnId, [Element t_icon]) {
Element makeThemeItem(String t_btnId) {
return Element.li()
..classes.add('dropdown-item')
..append(Element.span()..attributes['id'] = t_btnId);
..append(Element.span()
..attributes['id'] = t_btnId
..classes.add('themeBtn'));
}
return Element.li()
@ -131,13 +125,13 @@ Future<Element> makeThemeChanger() async {
..attributes['tabindex'] = '-1'
..append(Element.span()
..style.verticalAlign = 'top'
..append(makeIcon(icons['theme']))))
..append(makeIcon(icons['theme']!))))
..append(Element.ul()
..classes.add('dropdown')
..attributes['id'] = 'theme-dropdown'
..append(makeThemeItem('lightBtn', makeIcon(icons['sun'])))
..append(makeThemeItem('darkBtn', makeIcon(icons['lightbulb'])))
..append(makeThemeItem('blackBtn', makeIcon(icons['moon']))));
..append(makeThemeItem('lightBtn'))
..append(makeThemeItem('darkBtn'))
..append(makeThemeItem('blackBtn')));
}
// Create the dropdown table of contents
@ -149,7 +143,7 @@ Future<Element> makeToc() async {
..append(Element.a()
..attributes['tabindex'] = '-1'
..attributes['href'] = 'javascript:void(0)'
..append(makeIcon(icons['toc'])));
..append(makeIcon(icons['toc']!)));
}
// Add a navbar atop of the HTML body, containing:

View File

@ -1,7 +1,4 @@
import 'dart:html' as html show HttpRequest, Element, querySelector;
import 'package:html/parser.dart' show parse;
import 'package:html/dom.dart' as dom show Element;
import 'dart:html' show HttpRequest, Element, querySelector;
final excluded_keywords = {'index', 'CONTRIBUTING', 'LICENSE', 'README'};
@ -9,7 +6,7 @@ final excluded_keywords = {'index', 'CONTRIBUTING', 'LICENSE', 'README'};
Future<String> fetchRemoteSitemap() async {
const path = '/sitemap.html';
try {
return await html.HttpRequest.getString(path);
return await HttpRequest.getString(path);
} catch (e) {
print('Couldnt open $path');
}
@ -17,47 +14,48 @@ Future<String> fetchRemoteSitemap() async {
}
// Parse the list of elements and detect pages from this list
Map<String, String> detectPages(List<dom.Element> t_sitemap,
[String t_prefix, Map<String, String> t_links]) {
Map<String, String> detectPages(List<Element> t_sitemap,
[String? t_prefix, Map<String, String>? t_links]) {
t_links ??= <String, String>{};
// parse each element in sitemap
for (var elem in t_sitemap) {
// if its a link
if (elem.innerHtml.startsWith('<a')) {
elem = elem.firstChild;
final url = elem.attributes['href'];
final text = elem.firstChild.text;
if (elem.innerHtml!.startsWith('<a')) {
elem = elem.children[0];
final url = elem.attributes['href']!;
final text = elem.children[0].text;
if (excluded_keywords.contains(text) ||
excluded_keywords.contains(url.substring(0, url.length - 5))) {
continue;
}
t_links['/$url'] = (t_prefix == null) ? text : '$text ($t_prefix)';
t_links!['/$url'] = ((t_prefix == null) ? text : '$text ($t_prefix)')!;
} else {
final prefix = (t_prefix == null)
? elem.firstChild.text.replaceAll('\n', '')
: '$t_prefix / ${elem.firstChild.text}'.replaceAll('\n', '');
? elem.firstChild!.text!.replaceAll('\n', '')
: '$t_prefix / ${elem.firstChild!.text}'.replaceAll('\n', '');
t_links = detectPages(elem.children[0].children, prefix, t_links);
}
}
return t_links;
return t_links!;
}
// This function returns a Map which contains all links to languages detected
// from the sitemap.
Future<Map<String, String>> parseSitemap() async {
final content = await fetchRemoteSitemap();
final sitemap = parse(content).getElementsByClassName('org-ul')[0].children;
return detectPages(sitemap);
final sitemap = Element.ul()..innerHtml = content;
final sitemapNodes = sitemap.querySelector('ul')!.children;
return detectPages(sitemapNodes);
}
Future<void> createSitemap() async {
final sitemap = await parseSitemap();
final pages = html.querySelector('#drop-page');
final pages = querySelector('#drop-page')!;
sitemap.forEach((url, name) {
final link = html.Element.li()
final link = Element.li()
..classes.add('dropdown-item')
..append(html.Element.a()
..append(Element.a()
..attributes['href'] = url
..innerText = name);
pages.append(link);

View File

@ -1,8 +1,19 @@
import 'dart:html';
import 'dart:html'
show DivElement, Element, querySelector, querySelectorAll, window;
import './navbar.dart' show makeNavbar;
const image_header = '/img/icon.png';
const image_header = '/img/icon.webp';
Future<void> makeDecorativeButtonsOrgSrc() async {
for (var pre in querySelectorAll('.org-src-container')) {
pre
..append(Element.div()..attributes['class'] = 'closeButton')
..append(Element.div()..attributes['class'] = 'minButton')
..append(Element.div()..attributes['class'] = 'maxButton')
..append(Element.div()..attributes['class'] = 'floatButton');
}
}
Future<Element> makeHeader() async {
var header = Element.tag('header');
@ -10,9 +21,9 @@ Future<Element> makeHeader() async {
..append(Element.img()
..attributes['src'] = image_header
..attributes['alt'] = 'Logo'
..attributes['heigh'] = '150px'
..attributes['height'] = '150px'
..attributes['width'] = '150px')
..append(querySelector('h1'));
..append(querySelector('h1')!);
final subt = header.querySelector('.subtitle');
if (subt != null) {
header.append(subt);
@ -31,8 +42,8 @@ Future<void> wrapTables() async {
// All images that are not nested inside a link will be linkified to themselves.
Future<void> linkifyImg() async {
querySelectorAll('img').forEach((img) {
if (img.parent.tagName == 'P') {
final link = Element.a()..attributes['href'] = img.attributes['src'];
if (img.parent!.tagName == 'P') {
final link = Element.a()..attributes['href'] = img.attributes['src']!;
img.insertAdjacentElement('beforeBegin', link);
link.append(img);
}
@ -40,12 +51,22 @@ Future<void> linkifyImg() async {
}
Future<void> reorganizeHtml() async {
final ls = window.localStorage;
final lastUpdate = '20210330';
if (ls['last-update'] != lastUpdate) {
ls['last-update'] = lastUpdate;
window.location.reload();
}
// Make navbar
final navbar = await makeNavbar();
// Make header
final header = await makeHeader();
// Add decorative divs to source block wrappers
await makeDecorativeButtonsOrgSrc();
// wrap tables in container for better SCSS display
await wrapTables();
@ -53,10 +74,10 @@ Future<void> reorganizeHtml() async {
await linkifyImg();
// Add navbar to page
querySelector('body').insertAdjacentElement('afterBegin', navbar);
querySelector('body')!.insertAdjacentElement('afterBegin', navbar);
// Add headet to page
querySelector('#content').insertAdjacentElement('beforeBegin', header);
querySelector('#content')!.insertAdjacentElement('beforeBegin', header);
// Add correct class to TOC
final toc = (querySelector('#table-of-contents') ??
@ -64,7 +85,7 @@ Future<void> reorganizeHtml() async {
..attributes['id'] = 'table-of-contents'
..innerText = 'Table of Contents Unavailable'))
..classes.add('dropdown');
navbar.querySelector('#toc-drop').append(toc);
navbar.querySelector('#toc-drop')!.append(toc);
// Remove all <br> tags from HTML
querySelectorAll('br').forEach((br) => br.remove());

View File

@ -1,53 +1,20 @@
import 'dart:html';
class Theme {
String _name;
String _icon;
Theme(String t_name, String t_icon) {
_name = t_name;
_icon = t_icon;
}
String getIcon() => _icon;
String getName() => _name;
}
final themes = {
'light': Theme('light', 'fa-sun'),
'dark': Theme('dark', 'fa-lightbulb'),
'black': Theme('black', 'fa-moon')
};
import 'dart:html' show window, querySelector;
final localStorage = window.localStorage;
Future<void> setTheme([String? theme]) async {
theme ??= localStorage['theme'] ??
(window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light');
localStorage['theme'] = theme;
querySelector('body')!
..classes.clear()
..classes.add(theme);
}
void enableThemeChanger() {
final darkBtn = querySelector('#darkBtn');
final lightBtn = querySelector('#lightBtn');
final blackBtn = querySelector('#blackBtn');
lightBtn.onClick.listen((_) => switchTheme(themes['light']));
darkBtn.onClick.listen((_) => switchTheme(themes['dark']));
blackBtn.onClick.listen((_) => switchTheme(themes['black']));
}
Future<void> setTheme() async {
final currentTheme = themes[localStorage['theme']] ??
() {
final devicePrefersDark =
window.matchMedia('(prefers-color-scheme: dark)').matches;
return themes[devicePrefersDark ? 'dark' : 'light'];
}();
querySelector('body')
..classes.clear()
..classes.add(currentTheme.getName());
}
void switchTheme(Theme currentTheme) {
// Set HTML theme
querySelector('body')
..classes.clear()
..classes.add(currentTheme.getName());
// Set storage theme
localStorage['theme'] = currentTheme.getName();
final themes = <String>['light', 'dark', 'black'];
themes.forEach((theme) =>
querySelector('#${theme}Btn')!.onClick.listen((_) => setTheme(theme)));
}

2
web/style/main.scss Normal file
View File

@ -0,0 +1,2 @@
@import "themes.scss";
@import "style.scss";

View File

@ -1,4 +1,4 @@
/* Variables *****************************************************************/
// Variables //////////////////////////////////////////////////////////////////
$switch-small-screen: "only screen and (max-width: 600px)";
$switch-smaller-screen: "only screen and (max-width: 400px)";
@ -6,262 +6,7 @@ $switch-smaller-screen: "only screen and (max-width: 400px)";
$navbar-height: 70px;
$postamble-height: 55px;
$tooltip-underline-size: 3px;
// Themes /////////////////////////////////////////////////////////////////////
$dark: rgba( 52, 73, 94, 1);
$black: rgba( 0, 0, 0, 1);
$accent1: rgba( 93, 115, 126, 1);
$accent2: rgba( 92, 172, 126, 1);
$accent3: rgba(197, 193, 155, 1);
$light: #eee;
$grey1: #f8f8f8;
$grey2: #dbe1e8;
$grey3: #b2becd;
$grey4: #6c7983;
$grey5: #454e56;
$grey6: #12181b;
// Accent 1
// Black
$gradient-accent1-black-left: linear-gradient(to left, $black, $accent1, $accent1);
$gradient-accent1-black-right: linear-gradient(to right, $black, $accent1, $accent1);
// Dark
$gradient-accent1-dark-left: linear-gradient(to left, $dark, $accent1);
$gradient-accent1-dark-right: linear-gradient(to right, $dark, $accent1);
// Light
$gradient-accent1-light-left: linear-gradient(to left, $light, $accent1);
$gradient-accent1-light-right: linear-gradient(to right, $light, $accent1);
// Accent 2
// Black
$gradient-accent2-black-left: linear-gradient(to left, $black, $accent2, $accent2);
$gradient-accent2-black-right: linear-gradient(to right, $black, $accent2, $accent2);
// Dark
$gradient-accent2-dark-left: linear-gradient(to left, $dark, $accent2);
$gradient-accent2-dark-right: linear-gradient(to right, $dark, $accent2);
// Light
$gradient-accent2-light-left: linear-gradient(to left, $light, $accent2);
$gradient-accent2-light-right: linear-gradient(to right, $light, $accent2);
// Accent 3
// Black
$gradient-accent3-black-left: linear-gradient(to left, $black, $accent3, $accent3);
$gradient-accent3-black-right: linear-gradient(to right, $black, $accent3, $accent3);
// Dark
$gradient-accent3-dark-left: linear-gradient(to left, $dark, $accent3);
$gradient-accent3-dark-right: linear-gradient(to right, $dark, $accent3);
// Light
$gradient-accent3-light-left: linear-gradient(to left, $light, $accent3);
$gradient-accent3-light-right: linear-gradient(to right, $light, $accent3);
.light {
$bg-nav: $gradient-accent3-light-right;
$border-color: $accent1;
color: $dark;
background: $light;
transition: background 500ms ease-in-out, color 1s ease-in-out;
pre {
box-shadow: 3px 5px $dark;
border-color: $light;
}
pre.src {
&::before {
background-color: $light;
color: $dark;
}
}
.navbar, header {
background: $bg-nav;
}
.navbar svg {
fill: $dark;
}
.status {
background: $gradient-accent3-light-left;
color: $dark;
}
.tooltip {
border-bottom: $tooltip-underline-size dotted $accent3;
.tooltiptext {
background-color: $accent3;
color: $dark;
&::after {
border-color: $accent3 transparent transparent transparent;
}
}
}
.dropdown {
background: $accent3;
color: $dark;
}
#content {
a {
box-shadow: inset 0 -3px 0 $accent3;
transition: box-shadow 300ms ease-in-out;
&:hover {
box-shadow: inset 0 -23px 0 $accent3;
transition: box-shadow 300ms ease-in-out;
}
}
}
table, th, td {
border: 1px solid $dark;
}
th {
background: darken($light, 5%);
}
.gentree {
filter: invert(0%);
transition: filter 1s ease-in-out;
}
}
.dark, .black {
$bg-nav: $gradient-accent2-dark-right;
$border-color: $dark;
color: $light;
background: $dark;
transition: background 500ms ease-in-out, color 1s ease-in-out;
pre {
box-shadow: 3px 3px $dark;
border: none;
}
pre.src {
&::before {
background-color: $dark;
color: $light;
}
}
.navbar, header {
background: $bg-nav;
}
.navbar svg {
fill: $light;
}
.status {
background: $gradient-accent2-dark-left;
color: $light;
}
.tooltip {
border-bottom: $tooltip-underline-size dotted $accent1;
.tooltiptext {
background-color: $accent1;
color: $light;
&::after {
border-color: $accent1 transparent transparent transparent;
}
}
}
.dropdown {
background: $dark;
color: $light;
}
#content {
a {
box-shadow: inset 0 -3px 0 $accent2;
transition: box-shadow 300ms ease-in-out;
&:hover {
box-shadow: inset 0 -23px 0 $accent2;
transition: box-shadow 300ms ease-in-out;
}
}
}
table, th, td {
border: 1px solid $accent1;
}
th {
background: darken($dark, 2.5%);
}
.gentree {
filter: invert(100%);
transition: filter 1s ease-in-out;
}
}
.black {
$bg-nav: $gradient-accent1-black-right;
background: $black;
pre {
box-shadow: 3px 3px $light;
border: none;
}
pre.src {
&::before {
background-color: $black;
color: $light;
}
}
.navbar, header {
background: $bg-nav;
}
.status {
background: $gradient-accent1-black-left;
}
.dropdown {
background: $dark;
color: $light;
}
#content {
a {
box-shadow: inset 0 -3px 0 $accent1;
transition: box-shadow 300ms ease-in-out;
&:hover {
box-shadow: inset 0 -23px 0 $accent1;
transition: box-shadow 300ms ease-in-out;
}
}
}
table, th, td {
border: 1px solid $light;
}
th {
background: lighten($black, 15%);
}
}
/* Style *********************************************************************/
// Style //////////////////////////////////////////////////////////////////////
* {
outline: none;
@ -343,7 +88,6 @@ header {
align-items: center;
justify-content: space-around;
min-height: 3rem;
margin-top: 1rem;
padding: 0.5rem;
top: 0;
@ -363,22 +107,22 @@ header {
}
#table-of-contents, #drop-page {
top: $navbar-height / 1.3;
top: $navbar-height;
opacity: 1;
z-index: 5;
height: 500%;
height: 80vh;
pointer-events: auto;
}
}
}
#theme-dropdown {
width: 150px;
width: 250px;
flex-direction: row;
transform: translateX(-75%);
}
#lightBtn, #darkBtn, #blackBtn {
.themeBtn {
content: ' ';
border: 2px solid white;
border-radius: 50%;
@ -389,18 +133,6 @@ header {
margin-right: 10px;
}
#lightBtn {
background: $light;
}
#darkBtn {
background: $dark;
}
#blackBtn {
background: $black;
}
#drop-page, #table-of-contents {
flex-direction: column;
@ -420,7 +152,7 @@ header {
}
}
#drop-share, #drop-page {
#drop-share {
li {
padding: 10px;
}
@ -507,7 +239,10 @@ header {
}
h1, h2, h3, h4, h5, h6 {
text-align: center;
font-family: serif;
font-style: italic;
margin-left: 2em;
margin-right: 60px;
}
h2 {
@ -597,9 +332,17 @@ th, td {
padding: 10px;
}
img {
img, svg {
max-height: 600px;
max-width: 100%;
display: block;
margin: 0 auto;
}
header > img {
width: 150px;
height: 150px;
border-radius: 75px;
}
.nav-icon {
@ -615,8 +358,72 @@ ul {
padding-inline-start: 20px;
}
pre.src {
background: $dark;
color: $light;
.org-src-container,
pre {
border-radius: .5em;
}
.org-src-container {
position: relative;
padding-left: 1em;
box-shadow: 3px 3px 10px rgba(0,0,0,.3);
min-height: 5.5em;
margin: 0 auto;
width: -moz-fit-content;
width: fit-content;
}
pre {
width: -moz-fit-content;
width: fit-content;
border: none;
box-shadow: none !important;
margin: .5em;
padding: 2.75em 1.5em !important;
overflow-y: auto;
}
pre.src::before {
top: -10px;
}
pre.src-fish::before {
content: 'fish';
}
pre.src-rust::before {
content: 'Rust';
}
.closeButton,
.minButton,
.maxButton,
.floatButton {
position: absolute;
position: absolute;
width: .8em;
height: .8em;
border-radius: .4em;
z-index: 2;
left: .3em;
}
.closeButton {
top: .3em;
}
.minButton {
top: 1.4em;
}
.maxButton {
top: 2.5em;
}
.floatButton {
bottom: .3em;
}
.twitter-tweet {
margin: 10px auto;
}

230
web/style/themes.scss Normal file
View File

@ -0,0 +1,230 @@
// Variables //////////////////////////////////////////////////////////////////
$tooltip-underline-size: 3px;
// Themes /////////////////////////////////////////////////////////////////////
$nord0: #2e3440;
$nord1: #3b4252;
$nord2: #434c5e;
$nord3: #4c566a;
$nord4: #d8dee9;
$nord5: #e5e9f0;
$nord6: #eceff4;
$nord7: #8fbcbb;
$nord8: #88c0d0;
$nord9: #81a1c1;
$nord10: #5e81ac;
$nord11: #bf616a;
$nord12: #d08770;
$nord13: #ebcb8b;
$nord14: #a3be8c;
$nord15: #b48ead;
$dark: $nord1;
$light: $nord5;
$accent1: $nord7;
$accent2: $nord9;
$accent3: $nord8;
.light {
$border-color: $accent1;
color: $dark;
background: $light;
$bg-nav: linear-gradient(to right, $nord6, $nord4);
.navbar, header, .dropdown {
background: $bg-nav;
color: $dark;
}
.navbar svg {
fill: $dark;
}
transition: background 500ms ease-in-out, color 1s ease-in-out;
pre {
border-color: $light;
}
pre.src, pre.example {
&::before {
background-color: $nord6;
color: $dark;
}
}
pre.src, pre.example, .org-src-container {
background: $light;
color: $dark;
}
.status {
background: $bg-nav;
color: $dark;
}
.tooltip {
border-bottom: $tooltip-underline-size dotted $accent3;
.tooltiptext {
background-color: $accent3;
color: $dark;
&::after {
border-color: $accent3 transparent transparent transparent;
}
}
}
#content {
a {
box-shadow: inset 0 -3px 0 $accent3;
transition: box-shadow 300ms ease-in-out;
&:hover {
box-shadow: inset 0 -23px 0 $accent3;
transition: box-shadow 300ms ease-in-out;
}
}
}
table, th, td {
border: 1px solid $dark;
}
th {
background: darken($light, 5%);
}
.gentree {
filter: invert(0%);
transition: filter 1s ease-in-out;
}
}
.black, .dark {
$border-color: $nord1;
color: $nord6;
background: $nord0;
$bg-nav: linear-gradient(to right, $nord3, $nord1);
.navbar, header, .dropdown {
background: $bg-nav;
color: $light;
}
.navbar svg {
fill: $light;
}
transition: background 500ms ease-in-out, color 1s ease-in-out;
pre {
border: none;
}
pre.src, pre.example {
&::before {
background-color: $nord0;
color: $nord6;
}
}
.status {
background: $bg-nav;
color: $nord6;
}
.tooltip {
border-bottom: $tooltip-underline-size dotted $nord7;
.tooltiptext {
background-color: $nord7;
color: $nord6;
&::after {
border-color: $nord7 transparent transparent transparent;
}
}
}
#content {
a {
box-shadow: inset 0 -3px 0 $nord7;
transition: box-shadow 300ms ease-in-out;
&:hover {
box-shadow: inset 0 -23px 0 $nord7;
transition: box-shadow 300ms ease-in-out;
}
}
}
table, th, td {
border: 1px solid $nord7;
}
th {
background: darken($nord0, 2.5%);
}
.gentree {
filter: invert(100%);
transition: filter 1s ease-in-out;
}
pre.src, pre.example, .org-src-container {
background: $nord1;
color: $nord5;
}
}
.black {
background: black;
color: $nord4;
$bg-nav: linear-gradient(to right, $nord2, $nord0);
.navbar, header, .dropdown {
background: $bg-nav;
}
pre.src, pre.example, .org-src-container {
background: $nord0;
color: $nord4;
}
}
#lightBtn {
background: $light;
}
#darkBtn {
background: $nord0;
}
#blackBtn {
background: black;
}
pre {
box-shadow: none;
}
.closeButton {
background-color: $nord11;
}
.minButton {
background-color: $nord12;
}
.maxButton {
background-color: $nord14;
}
.floatButton {
background-color: $nord15;
}