Euma Design
Euma is 1. a color palette 2. a design system 3. a UI-Theme, where 1 and 2 combine to make 3. Euma is something I came up with and I am using across my apps and systems. I'm open to contributions, so if you have any please let me know. You can view the source code on codeberg.org and contact me via email. If you come to like it spread the word about it.
Euma Color Palette
There are nine named colors to choose from, each comes in five different shades. In addition there is a spectrum of twenty-one colors spanning from black to white, to have more subtle differences, where it counts.
Euma Tokens
‘Design Tokens’, to organize the design language. They are like the words and grammar to tell the stroy with.
Definitions
The Design Tokens are stored as a JSON file, which follows a JSON Schema. More on that later in Token Schema.
Token Structure
What defines a token?
- A token (
T
) is an identifier which can refer to a non-unique value (V
). T
encodes how and whereV
should be used.T
consists of sub-tokens (t
).T
must consist of 5t
, joined by colons.T = t1.t2.t3.t4.t5
- Sub-tokens must not repeat within
T
.t1 ≠ t2 ≠ t3 ≠ t4 ≠ t5
- Not every combination of sub-tokens has to map to a value, see rule 1.
t
must be camelCasedt
at position- 1 must be of type
<category>
- 2 must be of type
<property>
- 3 must be of type
<element>
- 4 must be of type
<state>
- 5 must be of type
<variant>
- 1 must be of type
- Types:
- <category> =
color | typo | space | fx - <property> =
background | border | outline | text | textDecorationColor | fontFamily | fontFeatureSettings | fontSize | fontWeight | fontVariantLigatures | fontVariantCaps | fontVariantNumeric | fontVariantEastAsian | fontVariationSettings | fontStyle | letterSpacing | wordSpacing | textAlign | textDecorationLine | textDecorationStyle | textDecorationThickness | textUnderlinePosition | margin | marginTop | marginRight | marginBottom | marginLeft | marginBlock | padding | paddingTop | paddingRight | paddingBottom | paddingLeft | borderRadius | borderTopLeftRadius | borderTopRightRadius | borderBottomRightRadius | borderBottomLeftRadius | maxWidth | maxHeight | borderWidth | animationDuration | transitionDuration | animationTimingFunction | transitionTimingFunction | animationDelay | transitionDelay | boxShadow - <element> =
button | badge | link | label | header | paragraph | small | code | select | input | legend | quote | notification | tab | entry | caption | icon | boxed | side | image | popover | list | indicator | panel | row | column | cell | window - <state> =
hover | focus | active | inactive | normal | load | block | success | error | warn | info | new | visit | alert | click | drag | highlight - <variant> =
default | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
- <category> =
t2
is dependent on it's predecessor.t2(t1)
Compatibility-Table t1
t2
color
background | border | outline | text typo
fontFamily | fontFeatureSettings | fontSize | fontWeight | fontVariantLigatures | fontVariantCaps | fontVariantNumeric | fontVariantEastAsian | fontVariationSettings | fontStyle | letterSpacing | wordSpacing | textAlign | textDecorationLine | textDecorationStyle | textDecorationThickness | textUnderlinePosition space
margin | marginTop | marginRight | marginBottom | marginLeft | marginBlock | padding | paddingTop | paddingRight | paddingBottom | paddingLeft | borderRadius | borderTopLeftRadius | borderTopRightRadius | borderBottomRightRadius | borderBottomLeftRadius | maxWidth | maxHeight | borderWidth fx
animationDuration | transitionDuration | animationTimingFunction | transitionTimingFunction | animationDelay | transitionDelay | boxShadow t3
is dependent on it's predecessor.t3(t2)
Compatibility-Table t2
t3
t2(typo)
button | badge | link | label | header | paragraph | small | code | select | input | legend | quote | notification | tab | entry | caption t2(color) | t2(space) | t2(fx) t3(t2(typo)) | icon | boxed | side | image | popover | list | indicator | panel | row | column | cell | window t4
,t3
andt2
restrict the usage of the token to:- Only to be used on UI-Elements with similar names like
t3
is. - Only to be used on such elements in a state, which names is similar to the name of what
t4
is. - Only to be used on such elements in said state and on properties with a similar name of what
t2
is.
Refer to Sub-Token Usage on what
t
' s usage should be.t5
then leaves room for the designer to define variants. For example differentiation between primary and secondary.- Only to be used on UI-Elements with similar names like
Euma Token Examples
Valid Euma Tokens
color.background.button.hover.default ✓ typo.fontFamily.button.normal.1 ✓ fx.boxShadow.button.normal.default ✓ space.maxWidth.button.focus.1 ✓
Invalid Euma Tokens
See if you can spot all six errors.
category.backgorund.button.hover.default ✗ typo.fontFamily.image.normal.1 ✗ fx.box-shadow.button.normal.default ✗ space.maxwidth.button.focus.1 ✗
Token Value Structure
What defines a token value?
V
is the actual value used in an application, tool, etc…, and not what is written in the file, whereV
is derived from. ThisV
can also be derived differently, depending from application to application and from type to type. So let's call this, what is written in the file - at the storage place - the origin value (O
). So the type ofV
depends on the application and is not acting within the same set of definitions of these rules, unlike the type ofO
. This makes it possible, so thatT
can act as a replacement for - something that is being replaced with - theV
directly in the application.V
is somethingT
points to.V
is non-unique. So it may also be referred to by otherT
.- The type of
O
is inferred fromT
, the usage ofV
can also be inferred fromT
- The type of
O
can be split into normative and non-normative ones. Normative ones are defined by the design token specification . This allows for easy interoperability and support between software application. Everything which is not standardized yet falls in the non-normative section. Those are heavily influenced by CSS types.- <normative> =
<color> | <cubicBezier> | <dimension> | <duration> | <fontWight> | <number> - <non-normative> =
<boxShadow> | <fontFamily> | <fontFeatureSettings> | <fontStyle> | <fontVariantCaps> | <fontVariantEastAsian> | <fontVariantLigatures> | <fontVariantNumeric> | <textAlign> | <textDecorationLine> | <textDecorationStyle> | <textUnderlinePosition>
- <normative> =
- The type of
O
depends on the second sub-token (t2
).Compatibility-Table t2
type of the O
t2(color)
<color>
animationDuration | transitionDuration | animationDelay | transitionDelay <duration>
animationTimingFunction | transitionTimingFunction <cubicBezier>
t2(space) | fontSize | wordSpacing | letterSpacing | textDecorationThickness <dimension>
every property not included above type with the same name as the property
Schema & Types
This section covers the details in what sort of schema the tokens are stored and what how the type dependent values are validated.
Token Schema
The Tokens are defined in JSON file. To save a token is simple, just start with t1
as the first key and create a new object under that key. Continue in the new object and repeat with t2
until all you reach t5
. So now we have no more sub-tokens to continue the chain with. Just an empty and dangling object.
So for T = color.background.button.hover.default
we get this:
{ "color": { | "background": { | | "button": { | | | "hover": { | | | | "default": {} | | | } | | } | } } }
This is where we want our O
to be. Looking at the design token spec and using the correct type we want, we should arrive at something like this:
{ "$type": "color", "$value": "#cdadf0", "$description": "use this for primary buttons" }
Inserting this and adding a JSON Schema Path, to get autocompletion and error detection for our IDE, the final result looks like this:
{ "$schema": "https://codeberg.org/39zde/euma/raw/branch/main/src/schema/tokens.schema.json", "color": { | "background": { | | "button": { | | | "hover": { | | | | "default": { | | | | | "$type": "color", | | | | | "$value": "#cdadf0", | | | | | "$description": "use this for primary buttons" | | | | } | | | } | | } | } } }
Type Definitions
We already got a quick look at the <color>
type. Let's take this as an example to take a deeper dive.
Like most types, value with the <color>
type are valid, if they pass the test of a Regular Expression (regex) (Read up on what these are here or here ). So if "$type"
is "color"
, then $value
must get a positive evaluation from this regex:
^(#([0-9a-f]{2}){3,4})$
Translated, so that a human can understand, this means a $value
passes, if it
- begins with
#
- followed by 2 characters in a row, part of either
a-f
or0-9
- repeat this pattern, so there are in total
3 (min.)
or4 (max.)
such duos in a row
If we check this with our example above, this #cdadf0
is indeed a valid color.
Values of some types are compared against a lookup table, but those are the minority. In the end the steps above happen automatically thanks to the the IDE in combination with the JSON Schema.
Sub-Token Usage
To allow the usage of a token to be inferred it's important to have some guides in place. These guides come in form of a short description for every subtoken.
Category
sub-token | usage |
---|---|
color | everything related to color |
typo | everything related to typography |
space | everything related to spacings, margins, and predefined shapes and dimensions |
fx | everything related to animation/motion and effects (fx), shadows, filters and sound |
Property
sub-token | usage |
---|---|
background | the background property for background-colors |
border | the border property |
outline | the outline property |
text | the text property contains the text colors, to be more precise, the coloring/fill of the glyphs |
textDecorationColor | the text property contains the text-decoration colors, behaves just like the CSS property |
fontFamily | the font family |
fontFeatureSettings | set flags to change the appearance of the font |
fontSize | the font size |
fontWeight | he font weight |
fontVariantLigatures | the ligature (joining of two characters into one shape) settings |
fontVariantCaps | the caps (alternate glyphs used for small or petite capitals or for titling) settings |
fontVariantNumeric | the numeric (usage of alternate glyphs for numbers, fractions, and ordinal markers) settings |
fontVariantEastAsian | the asian (the use of alternate glyphs for East Asian scripts, like Japanese and Chinese) settings |
fontVariationSettings | font settings for variable fonts |
fontStyle | whether a font should be styled with a normal, italic, or oblique face from its font-family |
letterSpacing | the spacing between letters |
wordSpacing | sets the length of space between words and between tags. |
textAlign | the text alignment |
textDecorationLine | the kind of line that is used on text in an element, such as an underline or overline |
textDecorationStyle | the kind of style for the textDecorationLine that is used on text in an element |
textDecorationThickness | sets the stroke thickness of the decoration line |
textUnderlinePosition | where the underline is positioned relative to the letters |
margin | even margin all around |
marginTop | the top margin |
marginRight | the right margin |
marginBottom | the bottom margin |
marginLeft | the left margin |
marginBlock | the top and bottom margin |
padding | even padding all around |
paddingTop | the top padding |
paddingRight | the right padding |
paddingBottom | the bottom padding |
paddingLeft | the left padding |
borderRadius | the border/corner radius of all corners |
borderTopLeftRadius | the top left border/corner radius |
borderTopRightRadius | the the top right border/corner radius |
borderBottomRightRadius | the bottom right border/corner radius |
borderBottomLeftRadius | he bottom left border/corner radius |
maxWidth | redefined max widths |
maxHeight | predefined max heights |
borderWidth | the thickens of a border |
animationDuration | the duration a an animation |
transitionDuration | the duration of a transition |
animationTimingFunction | animation easing functions |
transitionTimingFunction | transition easing functions |
animationDelay | the delay before the start of an animation |
transitionDelay | the delay before the start of a transition |
boxShadow | box/drop shadow |
Element
sub-token | usage |
---|---|
button | a button element |
badge | a badge element |
link | a link element |
label | a label element |
header | a header text element |
paragraph | the body text element, which is used the most |
small | a small text element |
code | a code-text/preformatted-text element |
select | a 'select one from many' element. Different from 'tab', which when pressed changes the content of the much of screen space |
input | a text input element |
legend | a legend element |
quote | a quoted text element |
notification | a notification element |
tab | element in a set of similar items, ordered horizontally; horizontal version of entry |
entry | element in a set of similar items, ordered vertically; vertical version of tab |
caption | description for another element |
icon | a icon element |
boxed | a box element, which is used the most. Think of the HTML 'div' element |
side | a side element, think of a sidebar, HTML 'aside', Androids 'Drawer'. A vertical element to the left or right of the main content |
image | an image element |
popover | a popover/popup element, temporary visible |
list | the list element, containing list items |
indicator | a indicator element, can be something like a dot besides text, a colored border,… |
panel | a panel element. more distinct than the box element |
row | a row element |
column | the column element |
cell | the cell in a table. less distinct than the box element |
window | the window of an application |
State
sub-token | usage |
---|---|
hover | the state when the cursor hovers over the element |
focus | the state when the element is in focus |
active | the state when the element is active, regarding plain text: it means it's selected |
inactive | the state when the element is inactive, but more distinct than normal |
normal | the state when the element is loading |
load | the state when the element is loading |
block | the state when the element is being blocked or can not proceed |
success | the state when the element was successful in doing something |
error | the state when something is wrong with the element |
warn | the state when something is wrong with the element |
info | the state when the element wants to warn about something |
new | the state when the element holds additional information |
visit | the state when the element is was newly added |
alert | the state when the elements needs immediate attention and want to alert about something, more distinct than warn |
click | the state when the element is being clicked |
drag | the state when the element is being dragged |
highlight | volatile, looses it's highlight after a short while, if unattended |
Variant
sub-token | usage |
---|---|
default | the default value variant for the state |
1 | Variant 1 (Primary) |
2 | Variant 2 (Secondary) |
3 | Variant 3 (Tertiary) |
4 | Variant 4 (Quaternary) |
5 | Variant 5 (Quintary) |
6 | Variant 6 (Senary) |
7 | Variant 7 (Septenary) |
8 | Variant 8 (Octonary) |
9 | Variant 9 (Nonary) |
Default Values
Everything on this page is actually styled be in line with the default values, so what are they exactly?
Armed with the knowledge from above we can now create our own UI-Theme.
Typography
Let's start with how we want to display texts.
Font Families
- Source Serif 4 Display: display font
for very large headers, extra crisp and nuanced
- Source Serif Variable: serif font
default header font
- Source Sans Variable: sans-serif font
default body font
The font feature settings are slightly adjusted, to improve readability. The Lexend font was used as reference on what font feature settings to modify. In short: no ligatures, alt-character for 'a' and 'g' plus added serifs to the capital 'I' to better differentiate between 'l', slightly increased letter- and word-spacing, dotted zero '0' to better differentiate between 'O'.
aglI0O - this is default
aglI0O - this is EumaAs to how much this improves readability remains to be seen. With that said, this all might be undone with with the text alignment set to 'justify'. I guess this is a tradeoff I'm willing to put up with… for now.
- SourceCodeVF: monospace font
default code font for data & numbers
Font Sizes
Viewport dependent font sizes. Try adjusting the viewport width somewhere between 420px
and 1440px
and observe the changes. The dynamic scaling is fully implemented in CSS, no JS required.
Normally the font-sizes adjust them self with the viewport width. But since this is a very new feature your browser does not support it yet. Try checking it out later or on another device. Currently on display is either nothing or the default font sizes. The numbers in the table are the would-be values, were your browser to support it.
Font Size | Sample Text |
---|---|
Hello, World! | |
Hello, World! | |
Hello, World! | |
Hello, World! | |
Hello, World! | |
Hello, World! | |
Hello, World! | |
Hello, World! | |
Hello, World! |
Coloring
coming soon
Spacing
coming soon
Effects
coming soon
Acknowledgements
- Thank you Jina Anne, Kaelig Deloumeau-Prigent, Val Head and all the other 461 participants, who have contributed to the W3C Design Tokens Community Group, to create the design token standard.
- Thank you Paul D. Hunt, Frank Grießhammer, Robert Slimbach, Irene Vlachou, Emilios Theofanous, Reymund Schroeder and Thomas Thiemich for creating and maintaining the 'Adobe Source' family of fonts.
- Thank you to the Codeberg Team for hosting this website, providing a platform to develop this project on and providing CI-Runners to distribute releases.