schultek / jaspr

Modern web framework for building websites in Dart. Supports SPAs, SSR and SSG.
https://jasprpad.schultek.de
MIT License
1.18k stars 69 forks source link

Global variables #279

Closed mjablecnik closed 3 days ago

mjablecnik commented 3 weeks ago

Hello, is somehow possible to define css variables for whole html document?

For example this for theming?:

/* Dark theme */
.dark-theme {
    --header-bg: #222;
    --header-text: #ddd;
    --nav-bg: #444;
    --nav-text: #ddd;
    --nav-hover-bg: #666;
    --section-bg: #333;
    --footer-bg: #222;
    --footer-text: #ddd;

    --btn-primary-bg: #555;
    --btn-primary-text: #ddd;
    --btn-primary-hover-bg: #666;
    --btn-primary-active-bg: #444;

    --btn-secondary-bg: #007B9E;
    --btn-secondary-text: #ddd;
    --btn-secondary-hover-bg: #008CBA;
    --btn-secondary-active-bg: #005F7A;

    --border-radius: 5px;
}

Or should I define my theme into dart variables and change theme by changing some global theme variable? What is better approach?

mjablecnik commented 3 weeks ago

Hello, so I created very simple InheritedComponent in my project for change themes (light and dark modes):

Screenshot 2024-08-22 at 17 17 37

But I discovered that when I want to use it in my project so I need the context but in styles of every component, is context missing because it is static variable:

Screenshot 2024-08-22 at 17 26 17

So now I don't know how to change my theme other than by css variables.

schultek commented 3 weeks ago

I suggest using 'data-theme' attribute on the html tag and then using it in a css attribute selector to have separate styles for light and dark.

I will write a more detailed answer when I'm back at the laptop, writing this from the phone rn.

mjablecnik commented 3 weeks ago

@schultek Ok, I will wait for some simple example.

schultek commented 1 week ago

So I recommend doing light/dark theming like this:

In main.dart (or somewhere else) add the top-level styles using the @css annotation:


@css
final styles = [
  css('body')
      .box(minHeight: 100.vh)
      // Use the background theme value
      .raw({'background-color': 'var(--background-color)'}),
];

// Define the theme values
@css
final List<StyleRule> theme = [
  css('html', [
    css('&[data-theme=\'light\']').raw({
      '--background-color': '#fff',
      '--text-color': '#121416d8',
      // other values...
    }),
    css('&[data-theme=\'dark\']').raw({
      '--background-color': '#212a2e',
      '--text-color': '#F7F8F8',
      // other values ...
    }),
  ]),
];

and then you can create a theme toggle component like this:

import 'package:jaspr/jaspr';

@client
class ThemeToggle extends StatefulComponent {
  const ThemeToggle({super.key});

  @override
  State createState() => ThemeToggleState();
}

class ThemeToggleState extends State<ThemeToggle> {
  bool isDark = false;

  @override
  Iterable<Component> build(BuildContext context) sync* {
    yield Document.html(attributes: {
      'data-theme': isDark ? 'dark' : 'light',
    });

    yield button(onClick: () {
      setState(() {
        isDark = !isDark;
      });
    }, [text('Toggle Theme')]);
  }
}
mjablecnik commented 1 week ago

Ok, thank you very much. It is very useful for me.

My another question is: Is possible for variable usage write it by this way?:

@css
final styles = [
  css('body')
      .box(minHeight: 100.vh)
      .background(color: Unit.var('--background-color')),
];

Or something similar instead of raw function usage?

schultek commented 1 week ago

Right now no, because of how the types are setup.

mjablecnik commented 3 days ago

When https://github.com/schultek/jaspr/pull/288 is merged, I can close this.