Styling

Primer Design System

PrimerLive components are based on the styling described in the Primer Design System. Primer Design System is created by GitHub and includes 2 implementations: one for React and one for Ruby on Rails. The third implementation, using plain HTML and CSS, has been deprecated by GitHub.

The CSS that comes with PrimerLive includes component styles and utility classes.

Customizing components

Style attributes

Some components contain attributes to create visual variations. For example, Box rows can be styled using attributes is_yellow, is_blue, and so on:

<.box>
  <:row is_yellow>Row</:row>
</.box>

Adding classes

All PrimerLive components accept the class attribute:

<.box class="my-box">
  <:row>Row</:row>
</.box>

To address inner elements, use the component classes attribute, is a key-classname map. The map keys are described in the component documentation.

We can define the styles in 2 ways:

  1. Writing custom CSS
  2. Using predefined classes

In the next two sections we're creating a custom styled Box. It will have a thicker border, a header row with larger heading and white background, and data rows with gray background.

Writing custom CSS

The component with the classes attribute map:

<.box classes={%{
  box: "my-box",
  header: "my-box__header",
  row: "my-box__row"
}}>
  <:header>Header</:header>
  <:row>Row</:row>
</.box>
.Box.my-box {
  border-width: 2px;
}

Adding the "root" component class to the custom class in CSS may be needed to create a higher specificity, needed to override the default styles.

.Box.my-box .my-box__header {
  color: rgb(89, 99, 110);
  background-color: #fff;
  font-weight: 500;
  font-size: 16px;
}

.Box.my-box .my-box__row {
  background-color: #f6f6f5;
}

Instead of using "hardcoded" color values, a better approach would be to use the Primer's Custom Properties (Variables), which are designed to work with theme settings. For example, in dark mode, a white background automatically changes to a darker shade, preserving the intent of the color rather than applying a fixed hex value. This benefit becomes even more apparent if you are offering additional options for color blindness, such as "high contrast".

Primer's Custom Properties can be found at Primer Design System: Primitives. Use the Theme dropdowns to compare the color variants for each theme.

The same styles, now with Custom Properties:

.Box.my-box .my-box__header {
  color: var(--fgColor-muted);
  background-color: var(--bgColor-default);
  font-weight: var(--base-text-weight-medium);
  font-size: var(--h4-size);
}

.Box.my-box .my-box__row {
  background-color: var(--bgColor-muted);
}

Using predefined classes

One step up is to use CSS utility classes. These are documented in Primer Design System's CSS utilities, and using them won't require the creation of a separate CSS file.

<.box classes={%{
  box: "pl-border-thick",
  header: "bgColor-default f4 fgColor-muted text-semibold",
  row: "bgColor-muted"
}}>
  <:header>Header</:header>
  <:row>Row</:row>
</.box>

Note that the box class "pl-border-thick" is defined by PrimerLive as one of the "custom" utility classes. You can find these below.

Reusing styled components

Style changes can be encapsulated using a wrapper component:

slot :header
slot :row

def styled_box(assigns) do
 ~H"""
 <.box classes={%{
   box: "pl-border-thick",
   header: "bgColor-default f4 fgColor-muted text-semibold",
   row: "bgColor-muted"
 }} {assigns} />
 """
end

Then use the wrapper as a regular component:

<.styled_box>
  <:header>Header</:header>
  <:row>Row</:row>
  <:row>Row</:row>
  <:row>Row</:row>
</.styled_box>

Supporting right-to-left (RTL) languages

To display components in right-to-left (RTL) languages, set the dir attribute of the html element to "rtl".

<html dir="rtl">
  ...
</html>

PrimerLive util classes

Flex and grid gap

Gap (or gutter) between rows and columns.

Integer values are translated to px values using the Primer Design System's base-8 scale.

ClassGap size in px
pl-gap-00
pl-gap-14
pl-gap-28
pl-gap-2_512
pl-gap-316
pl-gap-424
pl-gap-532
pl-gap-640
pl-gap-748
pl-gap-864
pl-gap-980
pl-gap-1096
pl-gap-11112
pl-gap-12128

Alignment

ClassDescription
pl-aligned-start(default) Aligns the element at the start (at the left in left-to-right languages and at the right in right-to-left languages).
pl-aligned-endAligns the element at the end (at the right in left-to-right languages and at the left in right-to-left languages).

Offset

The absolute offset for the element on the horizontal axis. This can be used together with the alignment classes: class pl-offset-x-2 pl-aligned-end will place the element 16px from the right in a left-to-right language.

Integer values are translated to px values using the Primer Design System's base-8 scale.

ClassOffset in px
pl-offset-x-00
pl-offset-x-14
pl-offset-x-28
pl-offset-x-2_512
pl-offset-x-316
pl-offset-x-424
pl-offset-x-532
pl-offset-x-640
pl-offset-x-748
pl-offset-x-864
pl-offset-x-980
pl-offset-x-1096
pl-offset-x-11112
pl-offset-x-12128

Border width

ClassWidth in px
pl-border-thin1
pl-border-thick2
pl-border-thicker4

Text

ClassDescription
pl-text-underline-hoverUnderline text on hover
pl-text-monospaceUse monospace font family