Here you are grouping semantic usage for a set of fixed props, this could be: “paragraph”, “heading”, “body”, “label”. You end up with a set of base classNames in which you define fixed font-family, font-size, letter-spacing and line-height PER semantic-name + semantic-size.
Then we have the last leaf of each semantic token, you need at least a default config which will define defaults for stuff like font-weight, font-style. But you can also create modifiers, which will define new values for these properties, like: /semibold or /semibold-italic as you need.
/*
FIGMA TOKEN NAMING CONVENTION:
typography/[semantic-name]-[semantic-size]/default
typography/[semantic-name]-[semantic-size]/[modifier]
EXAMPLES:
typography/title-lg/default
typography/title-lg/semibold
typography/title-lg/semibold-italic
typography/title-lg/bold
typography/title-lg/bold-italic
typography/body-18/bold
typography/body-18/semibold
typography/body-18-tight/bold
typography/body-18-tight/semibold
WRONG EXAMPLES:
typography/title/lg-tighter-semibold
typography/title/lg-wide-bold
What does the [semantic-name] define?
- Font Family (sans, serif, mono)
- Font Letter Spacing
What does the [semantic-size] define?
- Font Size
- Font Line Height in ratio form (example: 1.2)
- Font Letter Spacing
What does the [modifier] define?
- Weight (normal, medium, semibold, bold)
- Font Style (normal, italic)
*/
Then, in the code you will just create classes for the default modifier, you have utility classes like:
@utility text-title-1 {
@apply text-3xl font-semibold leading-tighter tracking-tighter;
}
@utility text-title-2 {
@apply text-2xl font-semibold leading-tighter tracking-tight;
}
@utility text-title-3 {
@apply text-xl font-semibold leading-tighter tracking-normal;
}
@utility text-title-4 {
@apply text-lg font-semibold leading-tight tracking-wide;
}
@utility text-title-5 {
@apply text-base font-semibold leading-tight tracking-wider;
}
@utility text-title-6 {
@apply text-sm font-semibold leading-tight tracking-widest;
}
And then, you can overwrite them with tailwind css classes by reading the [modifier] semantic names to identify the modification. For example, the token name typography/title-sm/italic maps to className="text-title-sm italic", but you can also do <em> inside the element. Same thing with typography/paragraph-sm/bold, you could do <strong>. And you could even set a diff weight for strong tags inside text-paragraph-sm like:
@utility text-paragraph-6 {
@apply text-sm font-normal leading-tight tracking-widest [&>strong]:font-semibold;
}
Consider using font-size token based for sizing to prevent future updates to shift the whole scale.
@utility text-paragraph-14 {
@apply text-sm font-normal leading-tight tracking-widest [&>strong]:font-semibold;
}
The first component of this approach is the font-family + font-size let’s call this fixture font-profile. This “font-profile” has the letter-spacing and line-height fixed. The second component of this approach is the font-weight + font-style. We can call this “font-flavor” this allows you to have a set of flavors per each set of profiles, where you can assume that each profile has the same consistent letter-spacing and line-height across all flavors.