diff --git a/backend/wordmodels/neighbor_network.py b/backend/wordmodels/neighbor_network.py index 7ccbfae19..1f58d4cb3 100644 --- a/backend/wordmodels/neighbor_network.py +++ b/backend/wordmodels/neighbor_network.py @@ -95,7 +95,6 @@ def _graph_vega_doc(timeframes, nodes, links): "height": 500, "padding": 0, "autosize": "none", - "signals": [ { "name": "cx", "update": "width / 2" }, { "name": "cy", "update": "height / 2" }, @@ -154,7 +153,14 @@ def _graph_vega_doc(timeframes, nodes, links): "on": [ {"events": {"signal": "fix"}, "update": "fix && fix.length"} ] - } + }, + { + 'name': 'theme', + 'description': 'Current site theme (light/dark)', + 'bind': { + 'element': '#current-theme', + } + }, ], "data": [ @@ -181,13 +187,13 @@ def _graph_vega_doc(timeframes, nodes, links): ] } ], - "scales": [ { 'name': 'link-color', 'type': 'linear', 'domain': {"data": "link-data", "field": "value"}, 'range': {'scheme': 'greys'}, + 'reverse': { 'signal': 'theme === "dark"' }, }, { 'name': 'text-weight', @@ -196,13 +202,11 @@ def _graph_vega_doc(timeframes, nodes, links): 'range': ['bold', 'normal'], } ], - "marks": [ { "name": "nodes", "type": "text", "zindex": 1, - "from": {"data": "node-data"}, "on": [ { @@ -218,7 +222,6 @@ def _graph_vega_doc(timeframes, nodes, links): "encode": { "enter": { "fontSize": {"value": 15}, - "fill": {"value": "black"}, "text": {"field": "term"}, "baseline": {"value": "middle"}, "align": {"value": "center"}, @@ -227,7 +230,8 @@ def _graph_vega_doc(timeframes, nodes, links): }, }, "update": { - "cursor": {"value": "pointer"} + "cursor": {"value": "pointer"}, + "fill": {'signal': 'theme === "dark" ? "white" : "black"'}, }, }, "transform": [ diff --git a/documentation/Styling.md b/documentation/Styling.md new file mode 100644 index 000000000..50fe4dcea --- /dev/null +++ b/documentation/Styling.md @@ -0,0 +1,67 @@ +# Styling + +This document covers CSS styling for the frontend. + +Textcavator uses the CSS framework [bulma](https://bulma.io/documentation/). + +Initial and derived variables from bulma are customised in [_utilities.css](/frontend/src/_utilities.scss). This file only defines variables and mixins and can be imported in component stylesheets. [styles.csss](/frontend/src/styles.scss) includes site-wide selectors. + +## Dark mode + +Dark mode is managed by the [ThemeService](/frontend/src/app/services/theme.service.ts). + +The service sets `data-theme="dark"` / `data-theme="light"` on the HTML root node, which is used by CSS selectors. If you need to observe the theme in a component, you can also use `ThemeService.theme$`. + +## Other libraries + +Several other libraries are used to provide components, visualisations, etc. These are often customised to fit the site theme and/or adapt to dark mode. + +## PrimeNG components + +We use several components from [primeNG](https://v19.primeng.org/). [primeng-theme.ts](/frontend/src/app/primeng-theme.ts) defines the preset to customise primeNG styles, mostly using bulma CSS variables. + +## Chart.js + +[select-color.ts](/frontend/src/app/utils/select-color.ts) defines the colour palettes for data visualisations and a utility function to select the nth colour. There are several palettes; the default is chosen to fit the site theme. The [palette selector](/frontend/src/app/visualization/visualization-footer/palette-select/palette-select.component.ts) lets users choose a preferred palette; the `VisualizationComponent` and `WordModelsComponent` provide the chosen palette as input to visualisation components. + +Chart.js has no built-in "dark mode". The `ThemeService` adjusts several defaults to get readable charts in dark mode, and updates all chart instances when the theme changes. + +## Vega + +To let a Vega visualisation adapt to dark/light mode, relevant colours should depend on a signal. + +Add the following signal in your vega document: + +```json +{ + "name": "theme", + "description": "Current site theme (light/dark)", + "bind": { "element": "#current-theme" } +} +``` + +The value of the `theme` signal will be `"dark"` or `"light"`. When you define colours in your document, let theme depend on this signal, e.g. with a mark like this: + +```json +{ + "marks": [ + { + "type": "text", + // ... + "encode": { + "update": { + "fill": {"signal": "theme === \"dark\" ? \"white\" : \"black\""} + }, + } + }, + ] +} +``` + +When you display the visualisation, include a [theme indicator](/frontend/src/app/visualization/theme-indicator.directive.ts) on your page like this: + +```html + +``` + +The Vega graph will bind the `theme` signal to the value of this element. The element will not be visible to users. diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 41ae577ef..8c9e97b63 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -51,6 +51,7 @@ import { MatomoConfig, matomoImports } from './routing/matomo'; import { stylePreset } from './primeng-theme'; import { CoreModule } from './core/core.module'; + export const appRoutes: Routes = [ { path: 'search/:corpus', diff --git a/frontend/src/app/core/footer/footer.component.html b/frontend/src/app/core/footer/footer.component.html index eda42927f..ad1c9af2c 100644 --- a/frontend/src/app/core/footer/footer.component.html +++ b/frontend/src/app/core/footer/footer.component.html @@ -6,7 +6,12 @@ Textcavator is developed by

- Centre for Digital Humanities, Utrecht University + Centre for Digital Humanities, Utrecht University
diff --git a/frontend/src/app/core/footer/footer.component.ts b/frontend/src/app/core/footer/footer.component.ts index 6ba02f98a..62a426967 100644 --- a/frontend/src/app/core/footer/footer.component.ts +++ b/frontend/src/app/core/footer/footer.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; import { environment } from '@environments/environment'; +import { ThemeService } from '@services/theme.service'; @Component({ selector: 'ia-footer', @@ -10,7 +11,9 @@ import { environment } from '@environments/environment'; }) export class FooterComponent { environment = environment as any; + theme$ = this.themeService.theme$; - constructor() { } - + constructor( + private themeService: ThemeService + ) { } } diff --git a/frontend/src/app/core/menu/menu.component.html b/frontend/src/app/core/menu/menu.component.html index 6946e2b89..fc17ab6ef 100644 --- a/frontend/src/app/core/menu/menu.component.html +++ b/frontend/src/app/core/menu/menu.component.html @@ -58,6 +58,20 @@