Component Directory

Typography

We want valid and semantic HTML so we use utility classes to apply styles to headings. This way we can have markup independent of styles and each page can function independently.

We use a simplified version of the Material Design type scale tokens to limit the number of sizes and enforce consistency.

Display

class='text-display'

As the largest text on the screen, display styles are reserved for short, important text or numerals. They work best on large screens.

Headline

class='text-headline'

Headlines are best-suited for short, high-emphasis text on smaller screens. These styles can be good for marking primary passages of text or important regions of content.

Title

class='text-title'

Titles are smaller than headline styles, and should be used for medium-emphasis text that remains relatively short. For example, consider using title styles to divide secondary passages of text or secondary regions of content.

Body

class='text-body'

Body styles are used for longer passages of text in your app.

Paragraph - lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Label

class='text-label'

Label

class='text-label-sm'

Label styles are smaller, utilitarian styles, used for things like the text inside components or for very small text in the content body, such as captions. Buttons, for example, use the label large style.

Examples

This card has an h1 in a smaller size as the design dictates the h2 is larger

My Content

Today's Content

Paragraph - lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Yesterday's Content

Paragraph - lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.


Color Roles

From the Google Material Design documentation:

  • Surface – A role used for backgrounds and large, low-emphasis areas of the screen.
  • Primary (and Secondary, Tertiary, etc.) – Accent color roles used to emphasize or de-emphasize foreground elements.
  • Container – Roles used as a fill color for foreground elements like buttons. They should not be used for text or icons.
  • On – Roles starting with this term indicate a color for text or icons on top of its paired parent color. For example, "on primary" is used for text and icons against the "primary" fill color.
  • Variant – Roles ending with this term offer a lower emphasis alternative to its non-variant pair. For example, "outline variant" is a less more emphasized version of the "outline" color. Note: this is inverted from MD3 in our system.
Primary: High-emphasis fills, texts, and icons against surface
On primary: Text and icons against primary
Primary container: Standout fill color against surface, for key components like a FAB
On primary container: Text and icons against primary container
Background
Surface: Default color for element backgrounds
Text On Surface: Text and icons against any surface or surface container color
Text On Surface Variant: Lower-emphasis color for text and icons against any surface or surface container color
Outline
Outline Variant

There are also five surface container roles named based on their level of emphasis:

  • Surface container lowest: Lowest-emphasis container color
  • Surface container low: Low-emphasis container color
  • Surface container: Default container color
  • Surface container high: High-emphasis container color
  • Surface container highest: Highest-emphasis container color

Surface container is the default role, but the others are especially helpful for creating hierarchy and nested containers

Here they are shown against the surface as a background:

Lowest
Low
Default
High
Highest

Here they are shown as the background for a default surface:

Surface Container Lowest
Surface
Surface Container Low
Surface
Surface Container (Default)
Surface
Surface Container High
Surface
Surface Container Highest
Surface
Error: Attention-grabbing color against surface for fills, icons, and text, indicating urgency
On error: Text and icons against error
Error container: Attention-grabbing fill color against surface
On error container: Text and icons against error container
success
On success
success Container
On success Container
destructive
On destructive
destructive Container
On destructive Container
warning
On warning
warning Container
On warning Container

Code

We can use the code component to display JSON snippets. This is useful for debug.

Here we have an inline code snippet: { "key": "value" } surrounded by text.

And here we have a block code snippet:

{
"key": "value",
"key2": "someReallyLongValueThatWeCanEitherWrapToTheNextLineOrPresentAScrollbarIfItDoesntFitInThisContainer",
"key3": "xpx1x12x3axp",
}

Buttons

Buttons can be links if the `href` attribute is present

Primary and Secondary buttons get a height of h-12 since they are mostly block level elements. Text and pill buttons are smaller to fit into inline contexts e.g. table rows

Primary

Default

Disabled

Secondary

Default

Disabled

Pill

Default

Active

Text

Default

Disabled

Destructive

Default

Disabled

Icon Buttons

Default

Large

Copy Button


Cards

Consistent card shape and color, with a predefined slot for a title

Card Title

Card content

Cards can be nested

Outer

nested inner

Chips

Little cards that can be used like tags

Test
Test
Test
Test
Test

Toggles

Switch

Uncontrolled

Default

Disabled

Controlled

Default

Disabled

Change listener

Default

Checkbox

Uncontrolled

Default

Disabled

Controlled

Dynamic Checked State

Dynamic Disabled State

Change listener

Default


Select

Pill Select

Value in parent: 30d

Form Select

Value in parent: 60d

Inputs

Text Input

Number Input

kb

Component State

Input Value: 
Parsed Value: 
Satisfies Minimum: false
Satisfies Maximum: false
Satisfies: false
Min: 0
Max: 100

Datetime Input

TODO: Styling needed

Asset Input

FOO

Component State

input (string): ""
input (number): "0"
input (decimals): 0
input (min): 1
input (minUnits): 10000
input (max): 100
input (maxUnits): 1000000
token symbol: 4,FOO
precision: 4
formatted: 0.0000
Asset: 0.0000 FOO
--- 
Valid Input: false
Valid Number: false
Valid Precision: true
Valid Minimum: false
Valid Maximum: true

Page State

Valid Input: false
Asset: 0.0000 FOO

Bytes Input

Component State

Input (string):   ""
Bytes (number):   "0"
Unit: "KB"
Valid: 

PublicKey Input

Component State

input (string):   "PUB_K1_6gqJ7sdPgjHLFLtks9cRPs5qYHa9U3CwK4P2JasTLWKQBdT2GF"
Public Key:        PUB_K1_6gqJ7sdPgjHLFLtks9cRPs5qYHa9U3CwK4P2JasTLWKQBdT2GF
    
---

Valid Input:       true
Valid Public Key:  true

Name Input

Symbol Input

Component State

input (string):   "0,UNKNOWN"
Symbol:            0,UNKNOWN
    
---

Valid Input:       true
Valid Symbol:      true

Loading

Progress Indicator

Skeleton Loader


Formatting Elements

Account/Name

Number

Default

2,000,000

Different Locale

2.000.000

With prefix

+2,000,000

With delta

-2,000 +2,000 0

Asset

Default

$100.00

Value

$100.00

Short

100.00 USD

Full

$100.00 USD

Block

Default

12345

With Icon

12345

Datetime

Default

7/28/26, 10:28:41 PM UTC

Different Locale

26. 7. 28. PM 10시 28분 41초 UTC

Ram

Default

2.05 KB

Expanding Elements

Details Summary

Header (summary)
Content (details)

Accordion

TODO


Tabular Data

Description List

For a two-column key-value type data we can use the description list component. This will collapse the value under the key and right-align it on smaller screens. Note there is no row striping here.

Some items

Some title
0.1178559846646745
Some title
0.5795097498714084
Some title
0.014522139810562384
Some title
0.7095617215543697
Some title
0.462055534290712

For displaying a component in the description, or multiple values under a single key, you can use the components declaratively.

Note: If using the components declaratively you'll need to wrap the child component correctly or you'll get a warning. There are CSS rules that'll visually yell at you to fix it :)

First
teamgreymass
Second
teamgreymass
teamgreymass
Warning
Manual Title
teamgreymass
Missing DT
teamgreymass

Tables

For tabular data with more than two columns and with simple layout requirements (i.e. displays the same on mobile) you can use the Table elements.

For tabular data with more advanced layout requirements (e.g. transitions from card on mobile to table on desktop) a custom component with a grid context should probably be used instead.

Default Table

Test Test Random Number
Test Test 0.1178559846646745
Test Test 0.5795097498714084
Test Test 0.014522139810562384
Test Test 0.7095617215543697
Test Test 0.462055534290712

Add a colgroup snippet for columnar styling.

Column Highlighting

Test Test Random Number
Test Test 0.1178559846646745
Test Test 0.5795097498714084
Test Test 0.014522139810562384
Test Test 0.7095617215543697
Test Test 0.462055534290712

Use the `full` attribute to make the table full width.

Full-width Table

Test Test Random Number
Test Test 0.1178559846646745
Test Test 0.5795097498714084
Test Test 0.014522139810562384
Test Test 0.7095617215543697
Test Test 0.462055534290712

Use the `fixed` attribute to make the table columns fixed, equal width.

Fixed-width Columns

Test Test Random Number
Test Test 0.1178559846646745
Test Test 0.5795097498714084
Test Test 0.014522139810562384
Test Test 0.7095617215543697
Test Test 0.462055534290712

Forms

Section 1

These are some standard fields in section one


Section 2

These are some dynamically created fields in section two



Layout

These layout components are inspired by the elemental layouts defined by Heydon Pickering and Andy Bell in Every Layout.

We're only using a couple here; the others are either easy enough to implement on an ad-hoc basis with tailwind (e.g. Box, Center) without introducing new elements, or they are more situational and a degree of control is required (e.g. Grid, Sidebar)

Stack

Stacks children vertically with a default gap

Note: Stack provides no leading or trailing space

Child 1

Child 2

Child 3

You can push items to the top or bottom of the stack by using mt-auto or mb-auto if the parent has a defined height

Child 1

Child 2 - Then a bigger gap to the bottom of the element

Child 3 with mt-auto

You can customize the gap if needed

Child 1

Child 2

Child 3

Switcher

The Switcher switches a flexbox context between horizontal and a vertical layout at a predefined parent-based breakpoint.

This layout is useful when all elements inside the switcher are considered of equal importance.

For example, if the breakpoint is 30rem the layout will switch to vertical when the parent container itself is less than 30rem wide.

Child 1

Child 2

Child 3

This switcher is set to a 60rem threshold

Child 1

Child 2

Child 3

Cluster

Clusters children horizontally with a default gap. The cluster will re-flow when the screen size changes.

This is essentially just typical flex-wrap behaviour with some default gaps.

Note: no leading or trailing horizontal gap.

Child 1

Child 2 is larger

Child 3 is also large

Child 4

Child 5

Child 6