diff --git a/.screenshots/dracula.png b/.screenshots/dracula.png new file mode 100644 index 0000000..692d126 Binary files /dev/null and b/.screenshots/dracula.png differ diff --git a/CHANGELOG.md b/CHANGELOG.md index f701c43..a888ad3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/base/src/main/java/atlantafx/base/theme/Dracula.java b/base/src/main/java/atlantafx/base/theme/Dracula.java new file mode 100644 index 0000000..6ea6c6c --- /dev/null +++ b/base/src/main/java/atlantafx/base/theme/Dracula.java @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: MIT */ + +package atlantafx.base.theme; + +import atlantafx.base.Preview; + +/** + * A theme based on Dracula 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; + } +} diff --git a/docs/docs/assets/images/dracula.png b/docs/docs/assets/images/dracula.png new file mode 100644 index 0000000..692d126 Binary files /dev/null and b/docs/docs/assets/images/dracula.png differ diff --git a/docs/docs/index.md b/docs/docs/index.md index 4fb3d5f..086a2c9 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -61,4 +61,9 @@ Or download the latest build on the [releases page](https://github.com/mkpaz/atl
![Cupertino Dark](assets/images/cupertino-dark.png){ width="800" }
Cupertino Dark
+
+ +
+ ![Dracula](assets/images/dracula.png){ width="800" } +
Dracula
\ No newline at end of file diff --git a/docs/docs/reference/controls.md b/docs/docs/reference/controls.md index 82cb529..2ba6bf8 100644 --- a/docs/docs/reference/controls.md +++ b/docs/docs/reference/controls.md @@ -183,6 +183,12 @@ Color variables: * `-color-progress-indicator-track` * `-color-progress-indicator-fill` +## Separator + +Color variables: + +* `-color-separator` + ## Slider CSS classes diff --git a/sampler/src/main/java/atlantafx/sampler/theme/HighlightJSTheme.java b/sampler/src/main/java/atlantafx/sampler/theme/HighlightJSTheme.java index 6df4ea5..80d9a51 100644 --- a/sampler/src/main/java/atlantafx/sampler/theme/HighlightJSTheme.java +++ b/sampler/src/main/java/atlantafx/sampler/theme/HighlightJSTheme.java @@ -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); + } } diff --git a/sampler/src/main/java/atlantafx/sampler/theme/ThemeManager.java b/sampler/src/main/java/atlantafx/sampler/theme/ThemeManager.java index a18263f..adb991c 100644 --- a/sampler/src/main/java/atlantafx/sampler/theme/ThemeManager.java +++ b/sampler/src/main/java/atlantafx/sampler/theme/ThemeManager.java @@ -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> 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(); } diff --git a/sampler/src/main/java/atlantafx/sampler/theme/ThemeRepository.java b/sampler/src/main/java/atlantafx/sampler/theme/ThemeRepository.java index ba604e6..9b47741 100644 --- a/sampler/src/main/java/atlantafx/sampler/theme/ThemeRepository.java +++ b/sampler/src/main/java/atlantafx/sampler/theme/ThemeRepository.java @@ -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 externalThemes = new ArrayList<>(); diff --git a/styles/pom.xml b/styles/pom.xml index b6ac2f4..170a8c8 100755 --- a/styles/pom.xml +++ b/styles/pom.xml @@ -37,6 +37,7 @@ ${scss.inputDir}/nord-dark.scss:${css.outputDir}/nord-dark.css ${scss.inputDir}/cupertino-light.scss:${css.outputDir}/cupertino-light.css ${scss.inputDir}/cupertino-dark.scss:${css.outputDir}/cupertino-dark.css + ${scss.inputDir}/dracula.scss:${css.outputDir}/dracula.css --no-source-map diff --git a/styles/src/components/_radio.scss b/styles/src/components/_radio.scss index 6c95a5c..3b09aeb 100755 --- a/styles/src/components/_radio.scss +++ b/styles/src/components/_radio.scss @@ -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; } } diff --git a/styles/src/components/_separator.scss b/styles/src/components/_separator.scss index 4f4c4d4..d2a4cb3 100755 --- a/styles/src/components/_separator.scss +++ b/styles/src/components/_separator.scss @@ -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; } } diff --git a/styles/src/components/_toggle-switch.scss b/styles/src/components/_toggle-switch.scss index 05e6a4a..5aa2089 100644 --- a/styles/src/components/_toggle-switch.scss +++ b/styles/src/components/_toggle-switch.scss @@ -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; } } diff --git a/styles/src/components/_toolbar.scss b/styles/src/components/_toolbar.scss index c215525..d86c834 100755 --- a/styles/src/components/_toolbar.scss +++ b/styles/src/components/_toolbar.scss @@ -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; } } diff --git a/styles/src/dracula.scss b/styles/src/dracula.scss new file mode 100755 index 0000000..c427bf4 --- /dev/null +++ b/styles/src/dracula.scss @@ -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";