Add Dracula theme

This commit is contained in:
mkpaz 2023-02-16 10:27:36 +04:00
parent 80734327dc
commit 19f78bfe66
15 changed files with 374 additions and 21 deletions

BIN
.screenshots/dracula.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

@ -5,14 +5,16 @@
### Features
- (CSS) 🚀 New MacOS-like Cupertino theme in light and dark variants.
- (CSS) 🚀 New [Dracula](https://ui.draculatheme.com/) theme.
### Improvements
- (CSS) `Button` shadow support (`-color-button-shadow`). Only for themes compiled with the `button.$use-shadow` flag enabled.
- (CSS) Looked-up color variables support: `Separator`.
### Bugfixes
- (CSS) Added border radius/shadow to `ComboBox` popup menu to match other controls.
- (CSS) Added border radius/shadow to popup menu for `ComboBox` (and `ComboBox`-based) controls.
- (CSS) Fixed `Popover` arrow background color.
## [1.2.0] - 2023-02-11

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: MIT */
package atlantafx.base.theme;
import atlantafx.base.Preview;
/**
* A theme based on <a href="https://draculatheme.com">Dracula</a> color palette.
*/
@Preview
public class Dracula implements Theme {
public Dracula() {
// Default constructor
}
@Override
public String getName() {
return "Dracula";
}
@Override
public String getUserAgentStylesheet() {
return "/atlantafx/base/theme/dracula.css";
}
@Override
public boolean isDarkMode() {
return true;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

@ -62,3 +62,8 @@ Or download the latest build on the [releases page](https://github.com/mkpaz/atl
![Cupertino Dark](assets/images/cupertino-dark.png){ width="800" }
<figcaption>Cupertino Dark</figcaption>
</figure>
<figure markdown>
![Dracula](assets/images/dracula.png){ width="800" }
<figcaption>Dracula</figcaption>
</figure>

@ -183,6 +183,12 @@ Color variables:
* `-color-progress-indicator-track`
* `-color-progress-indicator-fill`
## Separator
Color variables:
* `-color-separator`
## Slider
CSS classes

@ -59,4 +59,12 @@ public class HighlightJSTheme {
var fg = "#ECEFF4";
return new HighlightJSTheme(css, bg, fg);
}
public static HighlightJSTheme dracula() {
var css =
"pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#e9e9f4;background:#282936}.hljs ::selection,.hljs::selection{background-color:#4d4f68;color:#e9e9f4}.hljs-comment{color:#626483}.hljs-tag{color:#62d6e8}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#e9e9f4}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#ea51b2}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#b45bcf}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#00f769}.hljs-strong{font-weight:700;color:#00f769}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#ebff87}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#a1efe4}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#62d6e8}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#b45bcf}.hljs-emphasis{color:#b45bcf;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#00f769}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}";
var bg = "#282a36";
var fg = "#f8f8f2";
return new HighlightJSTheme(css, bg, fg);
}
}

@ -7,6 +7,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import atlantafx.base.theme.CupertinoDark;
import atlantafx.base.theme.CupertinoLight;
import atlantafx.base.theme.Dracula;
import atlantafx.base.theme.NordDark;
import atlantafx.base.theme.NordLight;
import atlantafx.base.theme.PrimerDark;
@ -42,7 +43,8 @@ public final class ThemeManager {
static final Set<Class<? extends Theme>> PROJECT_THEMES = Set.of(
PrimerLight.class, PrimerDark.class,
NordLight.class, NordDark.class,
CupertinoLight.class, CupertinoDark.class
CupertinoLight.class, CupertinoDark.class,
Dracula.class
);
private static final PseudoClass DARK = PseudoClass.getPseudoClass("dark");
@ -227,6 +229,9 @@ public final class ThemeManager {
if ("Nord Dark".equals(theme.getName())) {
return HighlightJSTheme.nordDark();
}
if ("Dracula".equals(theme.getName())) {
return HighlightJSTheme.dracula();
}
return theme.isDarkMode() ? HighlightJSTheme.githubDark() : HighlightJSTheme.githubLight();
}

@ -6,6 +6,7 @@ import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
import atlantafx.base.theme.CupertinoDark;
import atlantafx.base.theme.CupertinoLight;
import atlantafx.base.theme.Dracula;
import atlantafx.base.theme.NordDark;
import atlantafx.base.theme.NordLight;
import atlantafx.base.theme.PrimerDark;
@ -38,7 +39,8 @@ public final class ThemeRepository {
new SamplerTheme(new NordLight()),
new SamplerTheme(new NordDark()),
new SamplerTheme(new CupertinoLight()),
new SamplerTheme(new CupertinoDark())
new SamplerTheme(new CupertinoDark()),
new SamplerTheme(new Dracula())
);
private final List<SamplerTheme> externalThemes = new ArrayList<>();

@ -37,6 +37,7 @@
<arg>${scss.inputDir}/nord-dark.scss:${css.outputDir}/nord-dark.css</arg>
<arg>${scss.inputDir}/cupertino-light.scss:${css.outputDir}/cupertino-light.css</arg>
<arg>${scss.inputDir}/cupertino-dark.scss:${css.outputDir}/cupertino-dark.css</arg>
<arg>${scss.inputDir}/dracula.scss:${css.outputDir}/dracula.css</arg>
<arg>--no-source-map</arg>
</args>
</configuration>

@ -2,7 +2,16 @@
@use "../settings/config" as cfg;
$color-border: -color-border-default !default;
$color-bg: -color-bg-default !default;
$color-bg-selected: -color-accent-emphasis !default;
$color-border: -color-border-default !default;
$color-border-selected: -color-accent-emphasis !default;
$color-dot: transparent !default;
$color-dot-selected: -color-fg-emphasis !default;
$color-dot-border: transparent !default;
$color-dot-border-selected: -color-accent-emphasis !default;
$border-width: 1.5px !default;
$dot-width: 1px !default;
$dot-width-selected: 1px !default;
@ -15,14 +24,14 @@ $dot-width-selected: 1px !default;
-fx-label-padding: cfg.$checkbox-label-padding cfg.$checkbox-label-padding 0 cfg.$graphic-gap;
>.radio {
-fx-background-color: $color-border, -color-bg-default;
-fx-background-color: $color-border, $color-bg;
-fx-background-insets: 0, $border-width;
-fx-background-radius: 1em; // large value to make sure this remains circular
-fx-padding: cfg.$checkbox-mark-padding-y;
-fx-alignment: CENTER;
>.dot {
-fx-background-color: transparent, transparent;
-fx-background-color: $color-dot-border, $color-dot;
-fx-background-insets: 0, $dot-width;
-fx-background-radius: 1em; // large value to make sure this remains circular
-fx-min-height: cfg.$checkbox-mark-size;
@ -46,10 +55,10 @@ $dot-width-selected: 1px !default;
&:selected {
>.radio {
-fx-background-color: -color-accent-emphasis;
-fx-background-color: $color-border-selected, $color-bg-selected;
>.dot {
-fx-background-color: -color-accent-emphasis, -color-fg-emphasis;
-fx-background-color: $color-dot-border-selected, $color-dot-selected;
-fx-background-insets: 0, $dot-width-selected;
}
}

@ -8,12 +8,14 @@ $line-width: cfg.$border-width !default;
.separator {
-color-separator: $line-color;
&:horizontal {
-fx-padding: $padding 0 $padding 0;
// using border instead of insets to get thinner line
>.line {
-fx-border-color: $line-color transparent transparent transparent;
-fx-border-color: -color-separator transparent transparent transparent;
-fx-border-insets: $line-width 0 0 0;
}
}
@ -22,7 +24,7 @@ $line-width: cfg.$border-width !default;
-fx-padding: 0 $padding 0 $padding;
>.line {
-fx-border-color: transparent transparent transparent $line-color;
-fx-border-color: transparent transparent transparent -color-separator;
-fx-border-insets: 0 0 0 $line-width;
}
}

@ -2,13 +2,26 @@
@use "../settings/config" as cfg;
$color-label: -color-fg-default !default;
$color-thumb: -color-fg-emphasis !default;
$color-thumb-border: -color-border-default !default;
$color-thumb-selected: -color-fg-emphasis !default;
$color-thumb-border-selected: -color-accent-emphasis !default;
$color-thumb-area: -color-bg-subtle !default;
$color-thumb-area-border: -color-border-default !default;
$color-thumb-area-border-selected: -color-accent-emphasis !default;
$color-thumb-area-selected: -color-accent-emphasis !default;
$thumb-radius: 10em !default;
$thumb-padding: 0.85em !default;
$thumb-border-width: 2px !default;
$thumb-opacity: 0.8 !default;
$thumb-area-radius: 1em !default;
$thumb-area-padding: 0.85em 1.4em 0.85em 1.4em !default;
$thumb-area-border-width: cfg.$border-width !default;
$thumb-area-radius: 1em !default;
$thumb-area-padding: 0.85em 1.4em 0.85em 1.4em !default;
.toggle-switch {
-fx-thumb-move-animation-time: 200;
@ -16,13 +29,13 @@ $thumb-area-padding: 0.85em 1.4em 0.85em 1.4em !default;
>.label-container {
>.label {
-fx-font-size: 1em;
-fx-text-fill: -color-fg-default;
-fx-text-fill: $color-label;
-fx-padding: cfg.$checkbox-label-padding cfg.$graphic-gap cfg.$checkbox-label-padding 0;
}
}
>.thumb {
-fx-background-color:-color-border-default, -color-fg-emphasis;
-fx-background-color: $color-thumb-border, $color-thumb;
-fx-background-insets: 0, $thumb-border-width;
-fx-background-radius: $thumb-radius;
-fx-padding: $thumb-padding;
@ -33,20 +46,19 @@ $thumb-area-padding: 0.85em 1.4em 0.85em 1.4em !default;
>.thumb-area {
-fx-background-radius: $thumb-area-radius;
-fx-background-color: -color-border-default, -color-bg-subtle;
-fx-background-insets: 0, cfg.$border-width;
-fx-background-color: $color-thumb-area-border, $color-thumb-area;
-fx-background-insets: 0, $thumb-area-border-width;
-fx-padding: $thumb-area-padding;
}
&:selected {
>.thumb {
-fx-background-color: -color-accent-emphasis, -color-fg-emphasis;
-fx-background-color: $color-thumb-border-selected, $color-thumb-selected;
-fx-opacity: 1;
}
>.thumb-area {
-fx-background-color: -color-accent-emphasis;
-fx-background-insets: 0;
-fx-background-color: $color-thumb-area-border-selected, $color-thumb-area-selected;
}
}

@ -4,8 +4,9 @@
@use "../settings/icons";
@use "../settings/utils";
$color-bg: -color-bg-subtle !default;
$color-bg: -color-bg-subtle !default;
$color-bg-selected: if(cfg.$darkMode, -color-base-6, -color-base-2) !default;
$color-separator: -color-border-muted !default;
$padding-x: 0.3em !default;
$padding-y: 4px !default;
@ -38,7 +39,8 @@ $border-width: cfg.$border-width !default;
}
>.separator {
-fx-orientation: vertical;
-fx-orientation: vertical;
-color-separator: $color-separator;
}
}

268
styles/src/dracula.scss Executable file

@ -0,0 +1,268 @@
// SPDX-License-Identifier: MIT)
@use "sass:color";
@use "settings/utils" as utils;
// Dracula color palette
// https://spec.draculatheme.com
$background: #282a36;
$currentLine: #44475a;
$foreground: #f8f8f2;
$comment: #6272a4;
$cyan: #8be9fd;
$green: #50fa7b;
$orange: #ffb86c;
$pink: #ff79c6;
$purple: #bd93f9;
$red: #ff5555;
$yellow: #f1fa8c;
// Dracula UI color palette
// https: //ui.draculatheme.com/
$ui-black: hsl(230, 15%, 15%);
$ui-blackSecondary: hsl(230, 15%, 30%);
$ui-blackTernary: hsl(230, 15%, 70%);
$ui-blackLight: hsla(230, 15%, 15%, 5%);
$ui-grey: hsl(230, 15%, 30%);
$ui-greySecondary: hsl(230, 15%, 45%);
$ui-greyTernary: hsl(230, 15%, 75%);
$ui-greyLight: hsla(230, 15%, 30%, 5%);
$ui-white: hsl(60, 30%, 96%);
$ui-whiteSecondary: hsl(60, 30%, 100%);
$ui-whiteLight: hsla(60, 30%, 96%, 5%);
$ui-cyan: hsl(170, 100%, 75%);
$ui-cyanSecondary: hsl(170, 100%, 90%);
$ui-cyanLight: hsla(170, 100%, 75%, 5%);
$ui-green: hsl(115, 100%, 75%);
$ui-greenSecondary: hsl(115, 100%, 90%);
$ui-greenLight: hsla(115, 100%, 75%, 5%);
$ui-orange: hsl(35, 100%, 75%);
$ui-orangeSecondary: hsl(35, 100%, 90%);
$ui-orangeLight: hsla(35, 100%, 75%, 5%);
$ui-pink: hsl(330, 100%, 75%);
$ui-pinkSecondary: hsl(330, 100%, 90%);
$ui-pinkLight: hsla(330, 100%, 75%, 5%);
$ui-purple: hsl(250, 100%, 75%);
$ui-purpleSecondary: hsl(250, 100%, 90%);
$ui-purpleLight: hsl(250, 100%, 75%, 5%);
$ui-red: hsl(10, 100%, 75%);
$ui-redSecondary: hsl(10, 100%, 90%);
$ui-redLight: hsla(10, 100%, 75%, 5%);
$ui-yellow: hsl(60, 100%, 75%);
$ui-yellowSecondary: hsl(60, 100%, 90%);
$ui-yellowLight: hsla(60, 100%, 75%, 5%);
@forward "settings/color-scale" with (
$dark: #0d0e12,
$light: $foreground, // $ui-white
$base-0: #d4d4d7,
$base-1: #bfbfc3,
$base-2: #94959b,
$base-3: #7e7f86,
$base-4: #696a72,
$base-5: #53555e,
$base-6: #3d3f4a,
$base-7: $background,
$base-8: #181920,
$base-9: #0d0e12,
$accent-0: #e5dfff,
$accent-1: #d5ccff,
$accent-2: #c5b9ff,
$accent-3: #b5a6ff,
$accent-4: #a593ff,
$accent-5: #9580ff, // $ui-purple
$accent-6: #7f6dd9,
$accent-7: #685ab3,
$accent-8: #52468c,
$accent-9: #3c3366,
$success-0: #e2ffdf,
$success-1: #d0ffcc,
$success-2: #bfffb9,
$success-3: #adffa6,
$success-4: #9cff93,
$success-5: #8AFF80, // $ui-green
$success-6: #75d96d,
$success-7: #61b35a,
$success-8: #4c8c46,
$success-9: #376633,
$warning-0: #fff2df,
$warning-1: #ffeacc,
$warning-2: #ffe2b9,
$warning-3: #ffdaa6,
$warning-4: #ffd293,
$warning-5: #FFCA80, // $ui-orange
$warning-6: #d9ac6d,
$warning-7: #b38d5a,
$warning-8: #8c6f46,
$warning-9: #665133,
$danger-0: #ffe5df,
$danger-1: #ffd5cc,
$danger-2: #ffc5b9,
$danger-3: #ffb5a6,
$danger-4: #ffa593,
$danger-5: #FF9580, // $ui-red
$danger-6: #d97f6d,
$danger-7: #b3685a,
$danger-8: #8c5246,
$danger-9: #663c33
);
@use "settings/color-scale" as scale;
@forward "settings/color-vars" with (
$fg-default: $foreground,
$fg-muted: scale.$base-1,
$fg-subtle: scale.$base-3,
$fg-onEmphasis: scale.$dark,
$canvas-default: $background,
$canvas-overlay: $background,
$canvas-inset: scale.$base-8,
$canvas-subtle: scale.$base-6,
$border-default: scale.$accent-7,
$border-muted: scale.$accent-8,
$border-subtle: scale.$accent-9,
$shadow-default: scale.$dark,
$neutral-emphasisPlus: scale.$base-2,
$neutral-emphasis: scale.$base-3,
$neutral-muted: color.change(scale.$base-3, $alpha: 0.4),
$neutral-subtle: color.change(scale.$base-2, $alpha: 0.1),
$accent-fg: scale.$accent-5,
$accent-emphasis: scale.$accent-5,
$accent-muted: color.change(scale.$accent-5, $alpha: 0.4),
$accent-subtle: color.change(scale.$accent-5, $alpha: 0.1),
$success-fg: scale.$success-5,
$success-emphasis: scale.$success-5,
$success-muted: color.change(scale.$success-5, $alpha: 0.4),
$success-subtle: color.change(scale.$success-5, $alpha: 0.1),
$warning-fg: scale.$warning-5,
$warning-emphasis: scale.$warning-5,
$warning-muted: color.change(scale.$warning-5, $alpha: 0.4),
$warning-subtle: color.change(scale.$warning-5, $alpha: 0.1),
$danger-fg: scale.$danger-5,
$danger-emphasis: scale.$danger-5,
$danger-muted: color.change(scale.$danger-5, $alpha: 0.4),
$danger-subtle: color.change(scale.$danger-5, $alpha: 0.1)
);
@forward "settings/config" with (
$darkMode: true,
$border-radius: 6px,
$checkbox-mark-size: 0.85em,
$scrollbar-color-thumb: -color-accent-4
);
@use "general";
@forward "components/button" as button-* with (
$color-bg-hover: -color-base-5
);
@forward "components/checkbox" as checkbox-* with (
$color-box-indeterminate: -color-accent-emphasis,
$color-border-indeterminate: -color-accent-emphasis,
$color-mark-indeterminate: -color-fg-emphasis
);
@forward "components/combo-box" as combo-box-* with (
$use-alt-icon: true,
$color-arrow-button-fg: -color-accent-fg,
$color-list-bg-hover: -color-accent-emphasis,
$color-list-bg-selected: -color-accent-emphasis,
$color-list-fg-hover: -color-fg-emphasis,
$color-list-fg-selected: -color-fg-emphasis
);
@forward "components/data" as data-* with (
$color-header-bg: -color-bg-default,
$color-header-fg: -color-fg-muted,
$color-cell-bg-selected: -color-accent-subtle
);
@forward "components/date-picker" as date-picker-* with (
$cell-padding-x: 2px,
$cell-padding-y: 2px,
$cell-size: 2.5em,
$color-icon: -color-accent-fg,
$day-cell-font-size: 0.85em,
$day-name-font-size: 0.9em,
$month-year-font-size: 1em
);
@forward "components/menu" as menu-* with (
$color-menuitem-bg-hover: -color-accent-emphasis,
$color-menuitem-fg-hover: -color-fg-emphasis,
$color-menubar-bg-hover: -color-base-5
);
@forward "components/menu-button" as menu-button-* with (
$color-split-arrow-bg: -color-accent-emphasis,
$color-split-arrow-fg: -color-fg-emphasis
);
@forward "components/radio" as radio-* with (
$dot-width-selected: 3px,
$color-dot-selected: -color-accent-emphasis,
$color-dot-border-selected: -color-bg-default
);
@forward "components/slider" as slider-* with (
$color-track: scale.$accent-8
);
@forward "components/spinner" as spinner-* with (
$color-button-hover: -color-accent-muted
);
@forward "components/split-pane" as split-pane-* with (
$divider-thickness: 1px,
$grabber-length: 15px
);
@forward "components/tab-pane" as tab-pane-* with (
$color-lr-bg-selected: -color-base-6
);
@forward "components/text-input" as text-input-* with (
$color-bg-highlight: $currentLine
);
@forward "components/toggle-button" as toggle-button-* with (
$color-bg-selected: -color-accent-emphasis,
$color-fg-selected: -color-fg-emphasis,
$color-border-selected: scale.$accent-6
);
@forward "components/toggle-switch" as toggle-switch-* with (
$thumb-padding: 0.75em,
$thumb-area-border-width: 2px,
$thumb-opacity: 1,
$thumb-border-width: 4px,
$color-thumb: -color-fg-default,
$color-thumb-border: transparent,
$color-thumb-selected: -color-accent-emphasis,
$color-thumb-border-selected: transparent,
$color-thumb-area: -color-bg-default,
$color-thumb-area-border: -color-accent-emphasis,
$color-thumb-area-selected: -color-bg-default
);
@forward "components/toolbar" as toolbar-* with (
$color-bg-selected: -color-base-4,
$color-separator: -color-accent-8
);
@use "components";