How we build design systems at if

Alexander Vassbotn Røyne-Helgesen

Manager, Front-end Developer @ Bekk
 

github@phun-ky
twitter@phun_ky

Hvordan vi leverer

Hva vi leverer

Hvordan vi lager det

dokumenterer

implementerer

STYLEGUIDE

/

DESIGNSYSTEM

/

KOMPONENTBIBLIOTEK

Hvordan vi leverer

Hva vi leverer

Hvordan vi lager det

dokumenterer

implementerer

Monorepo

Dev ops

pakkehåndtering

Hvordan vi leverer

Hva vi leverer

Hvordan vi lager det

dokumenterer

implementerer

Kode

Dokumentasjon

design

Patterns

arkitektur

et tankesett

Design tokens

... er et sentralt område for å lagre designrelatert informasjon som farger, skrifter, bredder, animasjoner osv. Disse råverdiene kan deretter transformeres og formateres for å imøtekomme behovene til enhver plattform.

props:
  - minLarge:
    name: minLarge
    value: '90rem'
    type: unit
    comment: 1440px
  - minExtraLarge:
    name: minExtraLarge
    value: '120rem'
    type: unit
    comment: 1920px
  - onePixel:
    name: onePixel
    value: '0.0625rem'
    comment: 1px
    type: unit
global:
  category: misc
$ npm i theo
@import 'primary.less' /* Aliased with build system*/

a {
  color: @color-darkestBlue-primary; /* #0F2A6E */
}
import React from 'react';
import primaryColors from '@relax/colors/src/primary.js'

const Button = ({...props}) => (
  <button
    type="button"
    onClick={...}
    onKeyPress={...}
    style={{
      backgroundColor: primaryColors.darkestBlue.rgb
    }}
  >
    {title}
  </button>
)
import React from 'react';
import { colorDarkerSlatePrimary, colorLightestBrownSecondary } from '@relax/colors/src/color-variables.module.js'

const Tile = ({...props}) => (
  <div
    style={{
      backgroundColor: colorDarkerSlatePrimary,
      color: colorLightestBrownSecondary
    }}
  >
    {children}
  </div>
)
import React from 'react';
import styled from 'styled-components';
import { colorDarkerSlatePrimary, colorLightestBrownSecondary } from '@relax/colors/src/color-variables.module.js'

const TileContainer = styled.div`
  backgroundColor: ${colorDarkerSlatePrimary},
  color: ${colorLightestBrownSecondary}
`;

const Tile = ({...props}) => (
  <TileContainer>
    {children}
  </div>
)

Boilerplate

$ npx @relax/rlx-react-app folderName

Dokumentasjon

Design &

Patterns

$ npm i html-sketchapp-cli

Arkitektur

Et tankesett

Hvordan vi leverer

Hva vi leverer

Hvordan vi lager det

dokumenterer

implementerer

@require 'core.styl'

/**
 * @package {package} buttons - Buttons
 * @doc ../docs/buttons.md
 * @section
 * @sectionof Guidelines.Components
 */

/**
 * @doc ../docs/usage.md
 * @section
 * @sectionof Guidelines.Components.Buttons
 */
# Buttons

Buttons express what action will occur when the user clicks or touches it. Buttons are used to initialize an action, either in the background or foreground of an experience.

<figure class="sg figure sample">
  <sg-example>
    <div class="relax-card">
      <div class="relax-card-header">
        Edit customer
      </div>
      <div class="relax-card-content">
        Do you want to save?
        <div>
          <button type="button" class="relax-button">Cancel</button>
          <button type="button" class="relax-button relax-button--primary">Save</button>
        </div>
      </div>
    </div>
  </sg-example>
</figure>
$ npm i livingcss

Hvordan vi leverer

Hva vi leverer

Hvordan vi lager det

dokumenterer

implementerer

Eksempler

TYPER

States

Tydelighet

ANNotering av komponenter

$ npm i speccer

BRUKEREN

Tastatursnarveier

TILGJENGELIGHET

$ratio = 7

getCorrectContrastColor($bgcolor)
  if(contrast($bgcolor, $white).ratio > $ratio){
    color $white
  } else if(contrast($bgcolor, $darkerGrey).ratio > $ratio){
    color $darkerGrey
  } else {
    color $darkerSlate
  }

TEMAER

.theme--light
  background-color tint($color-lightGrey-secondary, 30%)
  color $color-darkerGrey-secondary

.theme--dark
  background-color $color-darkSlate-primary
  color $color-white-secondary

.theme--contrast
  filter invert(1)
componentDidMount() {
  const { preferences } = this.props;

  const watchDarkThemeMQ = window.matchMedia('(prefers-color-scheme: dark)');

  const darkThemeMQChange = mq => {
    if (mq.matches) {
      this.changeTheme('dark');
    } else {
      this.changeTheme('light');
    }
  };

  watchDarkThemeMQ.addListener(darkThemeMQChange);

  if (preferences.theme) {
    this.changeTheme(preferences.theme);
  } else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
    this.changeTheme('dark');
  } else if (window.matchMedia('(prefers-color-scheme: light)').matches) {
    this.changeTheme('light');
  }
}

Animasjoner

:root {
  --animation-duration: 250ms; 
  --transition-duration: 250ms; 
}

/* Contextually shorten duration length */
@media screen and (prefers-reduced-motion: reduce), (update: slow) {
  :root {
    --animation-duration: 0.001ms !important; 
    --transition-duration: 0.001ms !important;
  }
}

@media screen and (prefers-reduced-motion: reduce), (update: slow) {
  /* Remove duration for all unknown animation when a user requests a reduced animation experience */
  * {
    animation-duration: var(--animation-duration);
    animation-iteration-count: 1 !important;
    transition-duration: var(--animation-duration);
  }
}

"Blålysfilter"

:root
  --filterBlueColor rgba(204,20,0,0.2)

.theme--filter-blue
  background-color var(--filterBlueColor)
  display none
  top 0
  left 0
  right 0
  bottom 0
  pointer-events none
  position fixed
  z-index 9999
  opacity 0
  transition all 0.5s cubic-bezier(0.4, 0, 0.2, 1)

.theme--filter-blue.is-active
  opacity 1
  display block
<input
  type="range"
  onChange={filterChange}
  onInput={filterInput}
  defaultValue={preferences.blueLightFilter || 200}
  min="100"
  max="499"
/>
const filterInput = e => {
  const blueFilter = document.querySelector('.relax-filter-blue');
  if (!blueFilter) return;
  // Use the value from the input[type=range] to increase or decrease the alphachannel
  blueFilter.style.setProperty(
    '--filterBlueColor',
    `rgba(204,20,0,0.${(e.target.value + '').padStart(3, '0')})`
  );
};

const delayedSave = debounce(e => {
  saveBlueLightFiltering(parseInt(e.target.value, 10));
}, 500);

const filterChange = e => {
  e.persist();
  delayedSave(e);
};

Hvordan vi leverer

Hva vi leverer

Hvordan vi lager det

dokumenterer

POC SITE

Veien videre

Oppsummering

Hvordan vi leverer

Hva vi leverer

Hvordan vi lager det

dokumenterer

implementerer

Organisk

Not a project

tett på UX & Design

Alle skal med

tankesett

Release first, QUESTIONS LATER

brukeren først

SPØRSMÅL?

Manager, Front-end Developer @ Bekk
 

github@phun-ky
twitter@phun_ky

 

bekk.no/jobb

Alexander Vassbotn Røyne-Helgesen