bu-styleguide

2.0.0 • Public • Published

bu-styleguide

Core styles, components, macros and fields for BetterUp's website.

Contents

  1. About
  2. Organization
  3. Getting started
  4. Workflow
  5. Taking changes live
  6. Usage guidelines

About

As BetterUp's website grows, the best way to scale our branding is to centralize styles and components. This NPM package is that centralization. Whenever a new project is spun up, this package should be included, which allows field presets, macros, styles, and scripts to be easily ported over.

If changes are needed to the global BetterUp branding, they can be made here, and propagated out to all projects.

Organization

  • /fields
    • JS files for field partials. Each preset partial is designed to work fluidly with a macro.
    • presets are all used with hubspot-fields-js package
    • some presets may accept a variable, depending on their usage.
  • /js
    • JS scripts that may be used repeatedly. See each file for usage notes (coming soon)
  • /scss
    • All core styles.
    • /base
      • main variable values. This is the lowest level of SCSS breakdown, and should not be modified without review.
      • None of the variables used here should be accessed directly in other scss files. Use theme.scss variables and utility classes instead.
    • /partials
      • utility classes used in macros. All partials are imported into utility-classes.scss
    • components.scss
      • base mixins. Mixins are used in partials, but may also be used directly in module.scss files
    • theme.scss
      • base theme variables. Use these variables to build components.
    • utility-classes.scss
      • combined file of all partials. Import this into a new global scss file for the project
        • This allows the code to only be loaded once for performance.
    • macros.html

Getting started

To install this package, run:

npm i bu-styleguide

To install this package and save it to your project, run:

npm i bu-styleguide --save-dev

After downloading the package, you can include fields, js, styles, and macros as needed.

Including fields

In your fields.js file, you can import a field partial at the top of your file with:

let background = require('bu-styleguide/src/fields/background');

The imported field partial can then be used in your module.exports as a function, i.e. background().

For more on field partials, see the hubspot-fields-js documentation here.

Including JavaScript

To import js from bu-styleguide, import the file in a module.js or a js file. For example:

import 'bu-styleguide/src/js/countup.js';

Would import countup.js into your file, and be compiled on build.

Including styles

Important: Include utility classes and font declarations at the top of your project stylesheet with:

@import 'bu-styleguide/src/scss/utility-classes.scss';
@import "bu-styleguide/src/scss/base/icons.scss";

@include loadIvarFonts;
@include loadSohneFonts;

It's recommended you include icons.scss as well (our font awesome icons).

If you have a need for a single style partial to be included in a module.css or other css file, import it with:

@import 'bu-styleguide/src/scss/utility-classes.scss'

Including macros

In most BetterUp projects, macros.html is copied when webpack starts from the npm package to your dist folder, and then uploaded to HubSpot.

Workflow

If you're developing improvements to bu-styleguide locally, you can point your project to the local version of the package using npm link.

In /bu-styleguide, run:

npm link

In your project, run:

npm link {{local path to bu-styleguide}}

If bu-styleguide is on my desktop, and my project is also on my desktop, I would run:

npm link ../bu-styleguide

From the root of my project.

When your save a file in bu-styleguide, it will then automatically be updated in your project.

Important: The hubspot-fields-js CLI (command npm run generate-fields in most projects) must be exited and restarted after making changes to a field partial.

Taking changes live

To update the npm package:

  1. Confirm you're on the main branch and up-to-date. All code changes should be committed and pushed. Note that changes to the NPM package should be reviewed by Michele.

  2. Run npm version {{newVersion}}. This will tag the package with a new version number. Use semantic versioning and replace {{newVersion}} with the appropriate update.

    • For example, if I'm on version 1.0.0 and just added a patch, I'll run npm version 1.0.1.
    • For more on semantic versioning, see here.
  3. Run npm publish. This will publish the new npm package.

  4. Run git push to push your changes to github.

Usage Guidelines

Field partials, macros, and styles are designed to work fluidly together. See /examples for mock modules that pull together a macro and it's associated field preset. For use of many macros and field presets at once, see the module library (/betterup theme).

Modals

  • macro: generateModal(options)
  • fields: modal.js
  • styles: modal.scss. Included in utility-classes.scss
  • output: a button that triggers a form, video, or video with copy ('mixed') modal.
  • input: object. see below

generateModal() and the modal.js field preset both intake values. Note that this macro and fields are not currently used directly on production - instead, the modal macro and field preset are used by the CTA, video CTA, and link presets to keep modal options consistent.

For fields:

  • First parameter: index. Should be a string. This allows you to input multiple modal options in a module without creating conflicting visibility settings (multiple fields with the same id).
  • Second parameter: visibility field name, usually a choice field. When this field is equal to modal, the rest of the modal options will appear.

For the macro:

  • Easiest to just pass in the field group.
  • if not passing in the field group, can pass in an options object like below.

Example options, annotated:

{% set options = {
    "index": 1,
    "form": false, // set to true if a form modal
    "video_embed": false, // set to true if a video modal
    "vwo_goal_id": false, // set to a VWO goal id if necessary. Consult with CRO if needed
    "headline": false, // pass in to add a headline to a  "mixed" modal, with copy, a CTA, and a video
    "description": false, // pass in to create a  "mixed" modal, with copy, a CTA, and a video. This value will be checked to determine which kind of modal
    "button_link": false, //pass in to add a CTA to your mixed modal. Destination of the CTA. Should be an object based on a link field.
    "button_label": false, // pass in to add a CTA to your mixed modal. Destination of the button label
    "tracking_class": false // pass in to add a tracking class to the mixed modal CTA
  }
%}

Because this isn't used directly, there's no example provided for this snippet. Instead, refer to examples/cta-module.module for usage.

Style Warning

  • macro: generateStyleWarning(string)
  • fields: none
  • styles: Not used for production. Included in utility-classes.scss.
  • output: Block of HTML that is only visible in the page editor.
  • input: no fields

This macro is used to create a "style warning" within a module. This warning will only appear in the editor, and is only designed to work with a module library module.

The macro accepts one parameter - the text to be displayed as a warning. There is then a link to the module library documentation.

Because this doesn't have any fields, it's only used in an html file, such as:

{% if fieldA == 'value' && fieldB == 'value' %}
  {{generateStyleWarning('FieldA and FieldB cannot have the same value.)}}
{% endif %}

For a full example, see the generateCTA macro.

CTAs

  • macro: generateCTA(group)
  • fields: cta.js or ctaVisibility.js or ctaArray.js
  • styles: cta.scss. Included in utility-classes.scss
  • output: 1 or 2 CTAs that can link to another page or a modal.
  • input: varies based on fields. For most basic option, module.set_ctas.

generateCTA intakes the entire field preset generated by cta.js. It should be added wherever a CTA is needed in the DOM.

There are several field presets for a CTA based on a variety of uses.

  • cta.js - is the most basic option. The field preset does not take in any options. Limited to 1 per module because of visibility.
  • ctaVisibility.js - more complex option. Takes in an object with an index, dependency field name, and value for that dependency. Used with the same CTA macro. However, this field preset can be used to generate CTA options that aren't always visible, and more than one per module.

Example object:

let CTAOptions = {
  dependency: 'content_type', // name of field to base visibility on. Usually a choice field
  value: 'text|stats|bullets', // field value to base visibility on
  index: '1' // index, to allow more than 1 instance of CTAs per module
}

  • ctaArray.js - deconstructed CTA option. Used with the same CTA macro. This is an array of the same field preset, which allows the CTA field preset to be nested further within a module group. I didn't realize this was possible the first time I built this - it might be better for the user experience.
    • An object of CTA options must be passed into the macro for this to work.

Example object:

 {% set ctaOptions = {
  include_cta_1: module.include_cta_1,
  cta_1: module.cta_1,
  include_cta_2: module.include_cta_2,
  cta_2: module.cta_2,
 }
 %}

Outputs 1 or 2 CTAs based on options. Note than an editor error is thrown if a primary CTA & secondary CTA are used next to eachother.

For an example of all three field groups, see examples/section-width-module.module.

Background

  • macro: generateBackground(group)
  • fields: background.js, backgroundSimple.js
  • styles: background.scss. Included in utility-classes.scss
  • output: classes & parameters to render a background image
  • input: module.background___{index} (default) & class array variable for macro, {index} for field

generateBackground intakes the field group generated by background.js or backgroundSimple.js. It should be added to the outermost wrapper of a module, so that a user can adjust the overall width of the section.

background.js is the full set of background options, including an image, bespoke mobile image, and lazy loading. backgroundSimple.js is a simplified version of this set, only supporting our core background colors (black, white, and gray). This should be used in modules where the foreground could get difficult to read on a background image, such as a form.

Whem adding the background.js field preset, an index should be passed into the function so that multiple backgrounds can be used per module. This index can be a string or a number, and is then accessed with module.background___{index}.

backgroundSimple.js does not take an index.

example:

let background = require('bu-styleguide/src/fields/background');

module.exports = [
  background('1'),
  ]

vs.

let backgroundSimple = require('bu-styleguide/src/fields/backgroundSimple');

module.exports = [
  backgroundSimple(),
  ]

This macro outputs a string of classes and several parameters for the wrapper element. It must be used with a class variable, and this class variable should be an array. The class array should be passed into the macro, and then used in the element's class paramater with HubL's |join.

Example:

{% set wrapperClasses = [] %}

{% set background = generateBackground(module.background__main, wrapperClasses) %}

<section {{background}} class="{{wrapperClasses|join(' ')}}">
  
</section>

For an example, see examples/background.module.

Section Width Class

  • macro: generateSectionWidthClass(field)
  • fields: sectionWidth.js
  • styles: sectionWidth.scss. Included in utility-classes.scss
  • output: string of classes
  • input: module.section_width (default) for macro, array of choices for field

generateSectionWidthClass intakes the field generated by sectionWidth.js. It should be added to the outermost wrapper of a module, so that a user can adjust the overall width of the section.

When adding the sectionWidth field preset, you'll need to specify which width options are available. This should be an array of arrays, so that it can be used in a choice field. If an unsupported width option is added, the new option will need to be custom styled from the module.

Supported width options:

let widthOptions = [
  ['full-bleed', 'Full bleed'],
  ['full-width', 'Full width'],
  ['narrow', 'Narrow']
]

This macro outputs a string of classes. It can be used with a class variable and .append to make your module more readable, or directly in the class list of an element.

For an example, see examples/section-width-module.module.

Content Width Classes

  • macro: generateContentWidthClass(field)
  • fields: contentWidth.js
  • styles: contentWidth.scss. Included in utility-classes.scss
  • output: string of classes
  • input: module.content_width (default)

generateContentWidthClass intakes the field generated by contentWidth.js. It should be added to the content wrapper of a module, so that a user can adjust the overall content width. Note that the content wrapper is not the outermost element of the module, but usually the direct child of that outermost element.

This macro outputs a string of classes. It can be used with a class variable and .append to make your module more readable, or directly in the class list of an element.

For an example, see examples/content-width-module.module.

Spacing Classes

  • macro: generateSpacingClasses(group)
  • fields: spacing.js
  • styles: spacing.scss. Included in utility-classes.scss
  • output: string of classes
  • input: module.spacing (default)

generateSpacingClasses intakes the entire field group generated by spacing.js. It should be added to the outermost wrapper of a module, so that a user can adjust margins and padding within a flexible column.

This macro outputs a string of classes. It can be used with a class variable and .append to make your module more readable, or directly in the class list of an element.

For an example, see examples/spacing-module.module.

Heading

  • macro: generateHeading(group)
  • fields: heading.js
  • styles: heading.scss. Included in utility-classes.scss
  • output: an heading tag (H1 through H6) styled based on style selection (H1 through H7)
  • input: module.heading (default)

generateHeading intakes the entire field group generated by heading.js. This allows a user to select the correct semantic Heading tag (for SEO & accessibility) but also style it as needed.

The default field group name is module.heading. If this field preset is nested within a group, pass in module.groupName.heading.

Note that BetterUp has an additional heading style - H7 - that is a smaller version of the H1.

If no heading label is input, nothing will appear.

For an example, see example.heading-module.module.

Video CTA

  • macro: generateVideoCTA(group)
  • fields: videoCTA.js
  • styles: videoCTA.scss. Included in utility-classes.scss
  • output: an heading tag (H1 through H6) styled based on style selection (H1 through H7)
  • input: module.video_cta (default) for macro, dependent field name for videoCta.js

generateVideoCTA(group) intakes the entire field group created by videoCTA.js. It will render a light or dark video CTA that links to a modal.

The preset field group from videoCTA.js intakes the name of a boolean field that this field group's visibility will be dependent on.

Example:

const { Group, Field } = require("@igomoon/hubspot-fields-js");
let videoCTA = require('bu-styleguide/src/fields/videoCTA');

module.exports = [
  Field.boolean()
    .name('add_video_cta', 'Add a video CTA?')
    .id('add_video_cta')
    .visibleIf('content_type', 'video', 'EQUAL')
    .inlineHelpText('Check this box to add a video play button to your section.'),
  videoCTA('add_video_cta')
]

For an example, see examples/video-cta-module.module.

Simple Link

  • macro: generateLink(object)
  • fields: linkSimple.js
  • styles: N/A, functionality only
  • output: a link or a button that can go to another page or open a modal.
  • input: object for macro, index for field preset

generateLink creates an element wrapped in an a element linking to another page or wrapped in a button element linking to a modal. It intakes an object, and is commonly used with a repeating field group. An example use case for generateLink is creating a linked card.

Because generateLink can intake an element, it's recommended the inner HTML of that element is abstracted to a macro.

Example:


// extracted macro
{% macro innerContent(field) %}
  {{field}}
{% endmacro %}

<div>
  {% set elementWrapperClasses = [] %}

  {% set innerContent = innerContent(module.field) %}

  {% set params = {
    'group': module.link__1 // linkSimple.js field group
    'classList': elementWrapperClasses,
    'innerContent': innerContent,
    'index': loop.index,
    'additionalParams': false // can be background, or any other param needed in the button or a element
    } %}

    {{ macros.generateLink(params)}}
  {% else %}
</div>

The generateLink macro uses the generateModal macro to generate modals.

When adding the linkSimple.js field preset, an index should be passed into the function so that multiple linked items can be used per module. This index can be a string or a number, and is then accessed with module.link__{index}.

For an example, see examples/simple-link-module.module.

Anchor

  • macro: generateAnchor()
  • fields: anchor
  • styles: N/A, functionality only
  • output: id, which can then be linked to elsewhere on the page
  • input: none

The anchor module does not require any options, as it uses the module context. It should be added the the outermost wrapper of a module, so that it can be appropriately linked with an anchor.

This macro outputs an id.

For an example, see examples/anchor-module.module.

Phone Slider

Not in use.

Device Slider

Not in use.

Readme

Keywords

none

Package Sidebar

Install

npm i bu-styleguide

Weekly Downloads

1

Version

2.0.0

License

ISC

Unpacked Size

345 kB

Total Files

57

Last publish

Collaborators

  • dillonclift