Herman 3.0.0

Exporting Styles to JSON

While many UX patterns will be rendered as HTML components, there are several abstract style patterns – like color-palettes and font-specimens – that never appear as components in the application.

Herman provides several annotations to help visualize these abstract patterns, but they require access to the raw Sass data. We do that using Sass maps (key:value object variables) and the herman-export mixin to generate JSON out of Sass variables.

See the sass.jsonfile configuration to ensure that Herman has access to your exported Sass data.

Example

scss
$herman: (
  'colors': (
    'brand-colors': (
      'brand-orange': #c75000,
      'brand-blue': #0d7fa5,
    ),
  ),
);

@include herman-export($herman);
css compiled
/*! json-encode: {"colors": {"brand-colors": {"brand-orange": "#c75000", "brand-blue": "#0d7fa5"}}} */

Related

$herman

scss
$herman: () !default;

Use the $herman map variable to collect and organize color, font, size, and ratio values for export.

The $herman map should be structured with top-level keys for each type of data, and nested maps of the individual items to preview. Use the herman-add mixin to automatically populate fonts, colors, sizes, and ratios from existing maps – or construct your $herman map by hand, following these guidelines…

Map structure

Each type of preview value should be nested under a key that describes what type of data is being stored:

$herman: (
  'colors': (
    /* color maps */
  );
  'sizes': (
    /* size maps */
  );
  'ratios': (
    /* ratio maps */
  );
  'fonts': (
    /* font maps */
  );
);

Colors

Each color has an access name and value. The key will be used to identify the correct data for a given color-palette, and the data includes color name:value pairs, both in string format.

'brand-colors': (
  'brand-orange': #c75000,
  'brand-blue': #0d7fa5,
)

Color values can be in any valid web-color format – hex, hsl/a, rgba/a, etc.

Sizes & Ratios

Size and ratio data is similar to colors, organized into top-level groups that may contain one or more name:value pairs:

'font-ratios': (
  'line-height': 1.4,
  'minor-seventh': 16/9,
),
'text-sizes': (
  'root': 18px,
  'large': calc(1rem + 1.5vw),
)

Ratio values can be in any valid number, and size values should be valid CSS lengths.

Fonts

Each font should have a top-level key of its own, since font-previews display a single font at a time. The data map accepts:

  • name: how the font should be referenced in CSS (if omitted, defaults to top-level key)
  • stack: optional string or list of font-stack fallbacks
  • source: link to more information on the font, or typekit/googlefonts as useful
  • formats: font format (or space-separated list of font formats) for locally-hosted fonts – valid format options are ttf, otf, woff, woff2, svg, svgz, and eot
  • <variant>: describe any number of relative paths to locally-hosted font-files, or embedded data:... font strings per variant (e.g. normal, bold italic, etc.) – optionally, the value can also be a nested object with the following variant-specific keys:
    • path: variant-specific relative path to locally-hosted font-files
    • local: font name (or space-separated list of font names) used to look for local user fonts
    • svgid: optional suffix value for local SVG font src, e.g. font-file.svg#svgid (if omitted, defaults to name)
    • <format>: describe any number of relative paths to locally-hosted font-files, or embedded data:... font strings per format (e.g. ttf, otf, woff2, etc.)
'body-font': (
  'name': 'Source Sans Pro',
  'stack': ('Helvetica Neue', 'Helvetica', 'Arial', 'sans-serif'),
  'formats': 'woff' 'woff2' 'ttf',
  'normal': 'sans/sourcesanspro-regular-webfont',
  'italic': 'sans/sourcesanspro-italic-webfont',
  'bold': (
    'path': 'sans/sourcesanspro-bold-webfont',
    'local': 'source-sans-pro-bold',
    'ttf': 'sans-ttf/sourcesanspro-bold-webfont',
    'woff': 'data:application/x-font-woff;charset=utf-8;base64...'
  ),
)

Example

scss sample map structure
$herman: (
  'colors': (
    'brand-colors': (
      'brand-orange': '#c75000',
      'brand-blue': '#0d7fa5',
    ),
    'status-colors': (
      'go': '#657e1b',
      'yield': '#c75000',
    ),
  ),
  'fonts': (
    'body-font': (
      'name': 'Source Sans Pro',
      'stack': ('Helvetica Neue', 'Helvetica', 'Arial', 'sans-serif'),
      'formats': 'woff' 'woff2' 'ttf',
      'normal': 'sans/sourcesanspro-regular-webfont',
      'italic': 'sans/sourcesanspro-italic-webfont',
      'bold': (
        'path': 'sans/sourcesanspro-bold-webfont',
        'local': 'source-sans-pro-bold',
        'ttf': 'sans-ttf/sourcesanspro-bold-webfont',
        'woff': 'data:application/x-font-woff;charset=utf-8;base64...'
      ),
    ),
  ),
  'sizes': (
    'text-sizes': (
      'root': '18px',
      'large': 'calc(1rem + 1.5vw)',
    ),
  ),
);

Used By

@mixin herman-add()

@mixin herman-export()

Encode a Sass map as a JSON-ready string, and print to CSS output as a persistent comment.

Parameters

$map: $herman (map)

Map to be encoded for JSON exporting

Example

scss
// Export to JSON
@include herman-export;
css compiled
/*! json-encode: {"colors": {"brand-colors": {"brand-orange": "#c75000", "brand-blue": "#0d7fa5", "brand-pink": "#aa0e5c"}, "neutral-colors": {"light-gray": "#dedede", "gray": "#555b5e", "black": "#3b4042"}, "theme-colors": {"theme-dark": "#0d7fa5", "theme-light": "#cfe5ed", "background": "#fff", "text": "#3b4042", "text-light": "#555b5e", "action": "#aa0e5c", "focus": "#0d7fa5", "underline": "#eac3d6", "border": "#555b5e", "border-light": "#dedede", "shadow": "rgba(85, 91, 94, 0.5)", "callout": "#cfe5ed", "slight": "#fafcfd", "code": "#0d7fa5", "code-shadow": "rgba(13, 127, 165, 0.2)"}, "system-colors": {"contrast-light": "#fff", "contrast-dark": "#3b4042"}}, "ratios": {"text-ratios": {"line-height": 1.4}}, "sizes": {"root-sizes": {"root": "18px", "responsive": "calc(1em + 0.125vw)", "large": "calc(1rem + 0.5vw)", "small": "0.9rem"}, "text-sizes": {"reset": "1rem", "h1": "calc(1rem + 2vw)", "h2": "calc(1rem + 1vw)", "h3": "calc(1rem + 0.5vw)", "quote": "calc(1rem + 0.5vw)", "code": "0.9rem", "footer": "0.9rem", "search": "0.9rem"}, "spacing-sizes": {"rhythm": "1.4rem", "gutter": "1.4rem", "gutter-plus": "2.1rem", "double-gutter": "2.8rem", "flex-gutter": "calc(0.7rem + 2.5vw)", "spacer": "calc(4.2rem + 2.5vw)", "gutter-minus": "1.05rem", "shim": "0.7rem", "half-shim": "0.35rem", "quarter-shim": "0.175rem"}, "pattern-sizes": {"nav-underline": "4px", "nav-icon": "28px", "arrow-border": "8px", "arrow-depth": "0.7rem", "arrow-side": "1.4rem", "font-preview": "24em", "specimen-aa": "4.2rem", "color-preview": "16em", "color-swatch": "5.6rem", "footer-logo": "2.8rem"}, "layout-sizes": {"page": "50rem", "item-break": "40em", "page-break": "50em", "nav-break": "65em"}}, "fonts": {"sans": {"name": "Source Sans Pro", "source": "https://fonts.google.com/specimen/Source+Sans+Pro", "stack": ["Helvetica Neue", "Helvetica", "Arial", "sans-serif"]}, "code": {"name": "Source Code Pro", "source": "https://fonts.google.com/specimen/Source+Code+Pro", "stack": ["Consolas", "Menlo", "Monaco", "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", "monospace", "sans-serif"]}}} */

Requires

@function _herman-encode() [private]

@mixin herman-add()

Add a map of colors, fonts, sizes, ratios, etc to the $herman map for JSON-export, converting values to JSON-ready strings, with optional functions/args for compiling raw values.

Parameters & Output

$type: (String)

The type of map being added, e.g. colors, fonts, sizes, or ratios.

$key: (String)

A key name for accessing this data in JSON – should match the variable name, unless key is otherwise set in the @font/@colors/@ratios/@sizes annotation

$map: (Map)

A map of name/value pairs

$args…: (Arglist)

A function to use for compiling values before export, and any additional arguments for the function

{CSS output} (code block)

Updated $herman map, ready for JSON export

Example

scss
$brand-colors: (
  'brand-blue': hsl(195, 85%, 35%),
  'light-gray': 'brand-blue' ('tint': 80%, 'desaturate': 80%),
);
@include herman-add('colors', 'brand-colors', $brand-colors, get-function('color'));
/* #{$herman} */
css compiled
/* ("colors": ("brand-colors": ("brand-blue": #0d7fa5, "light-gray": #dedede), "neutral-colors": ("light-gray": #dedede, "gray": #555b5e, "black": #3b4042), "theme-colors": ("theme-dark": #0d7fa5, "theme-light": #cfe5ed, "background": #fff, "text": #3b4042, "text-light": #555b5e, "action": #aa0e5c, "focus": #0d7fa5, "underline": #eac3d6, "border": #555b5e, "border-light": #dedede, "shadow": rgba(85, 91, 94, 0.5), "callout": #cfe5ed, "slight": #fafcfd, "code": #0d7fa5, "code-shadow": rgba(13, 127, 165, 0.2)), "system-colors": ("contrast-light": #fff, "contrast-dark": #3b4042)), "ratios": ("text-ratios": ("line-height": 1.4)), "sizes": ("root-sizes": ("root": 18px, "responsive": calc(1em + 0.125vw), "large": calc(1rem + 0.5vw), "small": 0.9rem), "text-sizes": ("reset": 1rem, "h1": calc(1rem + 2vw), "h2": calc(1rem + 1vw), "h3": calc(1rem + 0.5vw), "quote": calc(1rem + 0.5vw), "code": 0.9rem, "footer": 0.9rem, "search": 0.9rem), "spacing-sizes": ("rhythm": 1.4rem, "gutter": 1.4rem, "gutter-plus": 2.1rem, "double-gutter": 2.8rem, "flex-gutter": calc(0.7rem + 2.5vw), "spacer": calc(4.2rem + 2.5vw), "gutter-minus": 1.05rem, "shim": 0.7rem, "half-shim": 0.35rem, "quarter-shim": 0.175rem), "pattern-sizes": ("nav-underline": 4px, "nav-icon": 28px, "arrow-border": 8px, "arrow-depth": 0.7rem, "arrow-side": 1.4rem, "font-preview": 24em, "specimen-aa": 4.2rem, "color-preview": 16em, "color-swatch": 5.6rem, "footer-logo": 2.8rem), "layout-sizes": ("page": 50rem, "item-break": 40em, "page-break": 50em, "nav-break": 65em)), "fonts": ("sans": ("name": "Source Sans Pro", "source": "https://fonts.google.com/specimen/Source+Sans+Pro", "stack": "Helvetica Neue", "Helvetica", "Arial", sans-serif), "code": ("name": "Source Code Pro", "source": "https://fonts.google.com/specimen/Source+Code+Pro", "stack": "Consolas", "Menlo", "Monaco", "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif))) */

Requires

$_herman-plural-types (map) [private]

Used By

@mixin config()

@function herman-map-compile()

Pass the values of any map through a given function (with optional arguments) and return the compiled map. This is used by herman-add and accoutrement-add, but can also be accessed directly.

Parameters & Return

$map: (Map)

A sass map with values that need to be compiled, such as Accoutrement Colors or Sizes with adjustments

$function: (String | Function)

The function (or function name) to use in compiling values, such as Accoutrement color and size functions

$args…: (Arglist)

Pass in any additional arguments for the function

@return (String | Any)

An updated map, with values compiled by a third-party function, and converted to json-ready strings

Example

scss
$brand-colors: (
  'brand-orange': hsl(24, 100%, 39%),
  'brand-blue': hsl(195, 85%, 35%),
  'light-gray': 'brand-blue' ('tint': 80%, 'desaturate': 80%),
);
/* #{herman-map-compile($brand-colors, get-function('color'))} */
css compiled
/* ("brand-orange": #c75000, "brand-blue": #0d7fa5, "light-gray": #dedede) */

Used By

@mixin herman-add()