Basics
Getting started
Load two fonts and one stylesheet, then set three attributes on the root element. That is the whole installation.
Install
Copy tomatico-ui.css into your project, or link it from
wherever this guide is published. There is no JavaScript dependency and no build step —
it is one stylesheet driven by custom properties.
<!DOCTYPE html>
<html lang="en" dir="ltr" data-tmt-theme="light">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light dark">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&family=IBM+Plex+Sans+Arabic:wght@300;400;500;600;700&display=swap">
<link rel="stylesheet" href="/assets/css/tomatico-ui.css">
</head>
<body class="tmt">
<a class="tmt-skip-link" href="#main">Skip to content</a>
<!-- masthead, nav, content -->
</body>
</html>
The tmt class on <body>
is what applies the base background, colour, font and line height. The stylesheet
deliberately does not style a bare body, so it can be
dropped into an existing application without fighting the host styles.
The three root attributes
Almost all of the system's behaviour is controlled from
<html>.
| Attribute | Values | What it does |
|---|---|---|
lang |
en, ar |
Selects the typeface. lang="ar" switches to IBM Plex Sans Arabic and relaxes line height. Works on any element, so a single Arabic phrase inside English copy renders correctly. |
dir |
ltr, rtl |
Mirrors the entire layout. No extra stylesheet needed — every rule uses logical properties. |
data-tmt-theme |
light, dark |
Selects the theme. Omit it and the light theme applies. Both themes are brand-approved. |
To respect the operating system's preference rather than forcing a theme, set the attribute from a small inline script before first paint so the page does not flash:
<script>
(function () {
var stored = null;
try { stored = localStorage.getItem("theme"); } catch (e) {}
var dark = window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
document.documentElement.setAttribute(
"data-tmt-theme", stored || (dark ? "dark" : "light")
);
})();
</script>
Class naming
Every class in the system is prefixed tmt-, so it will not
collide with an application's own styles or with a third-party widget. The convention is
block, element, modifier:
.tmt-card— the block..tmt-card__body— an element that only exists inside the block..tmt-card--inverse— a modifier, always applied alongside the block class.
Custom properties are prefixed the same way. Tokens meant for you to set are
--tmt-*; internal ones a component uses to pass values to its
own parts are --_* and are not part of the public contract.
Extending the system
When you need something the system does not have, build it from tokens rather than literal values. A component made of tokens themes itself, mirrors itself and stays consistent when the tokens change.
Do
- Reference semantic tokens:
var(--tmt-surface),var(--tmt-text-muted). - Use
padding-inline,margin-block-start,inset-inline-start. - Size everything from the space scale, so it lands on the 4px grid.
- Add the component here once it is used in more than one place.
Don't
- Write
#363636or13pxinto a component. - Use
padding-leftormargin-right— they break Arabic. - Reference a brand token like
--tmt-grey-500directly for text colour; use--tmt-text-mutedso dark mode keeps working. - Override
.tmt-*classes in application CSS. Wrap or compose instead.
Before you ship a screen
- Tab through it. Every interactive element is reachable and shows the 2px focus ring.
- Flip
dir="rtl". Nothing overlaps, no arrow points the wrong way. - Switch to dark mode. No element disappears into its background.
- Zoom to 200%. Content reflows rather than clipping.
- Check it at 360px wide. Tables scroll, the nav collapses, nothing is cut off.
- Read the copy against Content. Sentence case, no jargon, errors say what to do.