Skip to content
This repository has been archived by the owner on Oct 30, 2022. It is now read-only.

Latest commit

 

History

History
521 lines (388 loc) · 13.7 KB

style-variables.md

File metadata and controls

521 lines (388 loc) · 13.7 KB

Back to Theme main page

Styling with variables

Introduction

Polythene components are styled with variables that specify the sizes and colors for that component. The variables are used to create a component style, to be written by JavaScript or to a CSS file.

Component style variables are located in each component's CSS vars.js file (see the complete list of all variables below).

For example, the variables file for Icon contains:

// polythene-css-icon/src/vars.js
import { vars } from "polythene-theme"

export default {
  size_small:   vars.unit_icon_size_small,  // 16
  size_regular: vars.unit_icon_size,        // 24
  size_medium:  vars.unit_icon_size_medium, // 32
  size_large:   vars.unit_icon_size_large,  // 40
  color_light:  "currentcolor",
  color_dark:   "currentcolor"
}

"Global" variables such as unit_icon_size_small are imported from polythene-theme (which gets them from package polythene-style). To override these base variables, see Global theme file.

Styling components with variables

Using addStyle

Each component's CSS functions can be accessed with the naming pattern {ComponentName}CSS:

import { IconCSS } from "polythene-css"

Call addStyle to create a style:

IconCSS.addStyle(selector, {
  // CSS style key value pairs
})

The selector is usually a class name.

For example, to set the size and color of an icon:

IconCSS.addStyle(
  ".purple-icon",
  {
    // Note that we only need to list the variables that differ
    size_regular: 44,
    color_light:  "purple"
  }
)

Then use that style for a specific component instance by using the same selector.

With Mithril:

m(Icon, { className: "purple-icon" })

With React JSX:

<Icon className="purple-icon" />

Performance

The above method is the easiest way to create a new style, but any import from polythene-css will trigger each component to add its styles to the page head.

This is not a problem if you are using CSS-in-JS anyway, but when you are using CSS files instead, this is unnecessary overhead.

Two options to keep the impact small:

  1. Keep all CSS in files: write custom CSS to a file
  2. Import from the component's CSS package:
import { addStyle } from "polythene-css-icon"

addStyle(
  ".purple-icon",
  {
    color_light:  "purple"
  }
)

Only the minimum of CSS

When using addStyle (or getStyle when writing CSS to a file) only a minimal subset of CSS is created based on the passed variables.

Tip 1: When using a custom style for a component that will be displayed on a dark tone, be sure to also add dark tone color variables:

ButtonCSS.addStyle(".my-button", {
  color_light_text: "#333",
  color_dark_text:  "#fff",
});

Tip 2: To use all default variables, pass general_styles: true. This will read the default variables, plus the ones added with addStyle/getStyle. The resulting CSS will be bigger of course.

Themed behaviors

A number of components allows to change its behavior using style variables. Some examples:

Create a Contained Button with a drop shadow:

import { ButtonCSS } from "polythene-css"

ButtonCSS.addStyle(
  ".contained-button",
  {
    contained:              true,
    color_light_background: "#673ab7",
    color_light_text:       "#fff",
    shadow_depth:           1,
  }
)

Create a cover Drawer:

import { DrawerCSS } from "polythene-css"

DrawerCSS.addStyle(
  ".cover-drawer",
  {
    cover: true
  }
)

Create a modal Dialog (disabling clicking the background) with a backdrop:

import { DialogCSS } from "polythene-css"

DialogCSS.addStyle(
  ".modal-dialog",
  {
    modal:    true,
    backdrop: true
  }
)

Create a Menu with a backdrop:

import { MenuCSS } from "polythene-css"

MenuCSS.addStyle(
  ".menu-backdrop",
  {
    backdrop: true
  }
)

Using scope

To restrict a theme style to a CSS scope, add parameter scope as attribute of the "additional options":

import { ListTileCSS } from "polythene-css"

ListTileCSS.addStyle(
  ".navigation-list-tile",
  {
    // Style variables:
    font_size_title: 21
  },
  {
    // Additional options:
    scope: ".main-navigation"
  }
)

Using media queries

To restrict a theme style to certain screen conditions, you can pass an additional media query parameter.

Conceptually, this is very close to writing CSS with media queries, but it has the benefit that you don't need to know the internal component structure - you still work with style variables.

Pass the media query string as attribute of the "additional options":

import { IconCSS } from "polythene-css"

IconCSS.addStyle(
  ".small-screen-icon",
  {
    // Style variables:
    size_regular: 16
  },
  {
    // Additional options:
    mediaQuery: "@media all and (max-width: 420px)"
  }
)

It is possible to combine styles. This card has a colored background, and at small screen sizes the image is displayed smaller:

CardCSS.addStyle(
  ".themed-card",
  {
    color_dark_main_background: "#B89E58",
    color_dark_title_text:      "#fff",
    color_dark_subtitle_text:   "#fff"
  }
),
CardCSS.addStyle(
  ".small-image-card",
  {
    image_size_medium: 90
  },
  {
    mediaQuery: "@media all and (max-width: 420px)"
  }
)

Then apply the styles by setting the class name:

m(Card, { className: "themed-card small-image-card" })

Function addStyle

addStyle(selector, vars, options)
Option Required Type Description
selector required String CSS selector; using a class selector is the most convenient because of the reuse in component option className
vars required Object The component's theme variables, or a subset thereof
options.mediaQuery optional String Media query that wraps the selector

Under the hood

Component variables are passed on to CSS creation modules (usually "layout" and "colors") that take variables and return a style object. The style object is converted to a style sheet by j2c.

Only a minimal stylesheet is created, based on the set of passed variables. To recreate all styles, pass general_styles: true.

Choosing CSS-in-JS or CSS files

See Polythene CSS for guidelines and instructions.

Examples

Mithril example

If we want to create large icons:

import { Icon } from "polythene-mithril"
import { IconCSS } from "polythene-css"

const unitSize = 20

IconCSS.addStyle(
  ".app-icon",
  {
    size_large: 4 * unitSize
  }
)

// Show the large icon
m(Icon, {
  className: "app-icon",
  size: "large" // results in 4 * unitSize
})

To create a blue button on a dark background:

import { Button } from "polythene-mithril"
import { ButtonCSS } from "polythene-css"

ButtonCSS.addStyle(
  ".blue-on-dark-button",
  {
    color_dark_text: "#1976D2"
  }
)

// Show the blue button on a dark background
m(".pe-dark-tone", 
  m(Button, {
    className: "blue-on-dark-button",
    label: "Blue Button"
  })
)

To make a Menu appear full width on a small screen:

import { Menu } from "polythene-mithril"
import { MenuCSS } from "polythene-css"

MenuCSS.addStyle(
  ".small-screen-menu",
  {
    top_menu: true,
    backdrop: true,                                           // add a backdrop
    animation_hide_origin_effect_css: "transform: scale(1);", // prevent the menu fron scaling
    height: "50vh !important",                                // use !important to override the component height option (if set)
  },
  {
    mediaQuery: "@media all and (max-width: 480px)"
  }
)

// Show the menu
m(Menu, {
  className: "small-screen-menu",
  height: 150,
  // ...
})

React JSX example

If we want to create large icons:

import { Icon } from "polythene-react"
import { IconCSS } from "polythene-css"

const unitSize = 20

IconCSS.addStyle(
  ".app-icon",
  {
    size_large: 4 * unitSize
  }
)

// Show the large icon
<Icon className="app-icon" size="large" />

To create a blue button on a dark background:

import { Button } from "polythene-react"
import { ButtonCSS } from "polythene-css"

ButtonCSS.addStyle(
  ".blue-on-dark-button",
  {
    color_dark_text: "#1976D2"
  }
)

// Show the blue button on a dark background
<div className="pe-dark-tone">
  <Button
    className="blue-on-dark-button"
    label="Blue Button"
  />
</div>

To make a Menu appear full width on a small screen:

import { Menu } from "polythene-react"
import { MenuCSS } from "polythene-css"

MenuCSS.addStyle(
  ".small-screen-menu",
  {
    top_menu: true,
    backdrop: true,                                           // add a backdrop
    animation_hide_origin_effect_css: "transform: scale(1);", // prevent the menu fron scaling
    height: "50vh !important",                                // use !important to override the component height option
  },
  {
    mediaQuery: "@media all and (max-width: 480px)"
  }
)

// Show the menu
<Menu
  className="small-screen-menu"
  height={150}
  {/* ... */}
/>

Global styling by overriding Polythene defaults

Using the same method it is possible to override the default styling, just by using Polythene classnames:

IconCSS.addStyle(".pe-icon", {
  color_light:  "purple"
})

To override global variables such as the app's primary action color, see Global theme file.

List of all variables

Global variables

Component variables

Variables are defined in each module's vars.js file.