Skip to content

Philosophies

We believe in leveraging the native capabilities of the web platform as much as possible. This means using semantic HTML, built-in browser features, and progressive enhancement to ensure our design system is accessible, performant, and future-proof. By relying on the platform, we reduce dependencies, improve maintainability, and ensure our components work well across a wide range of devices and environments. We avoid reinventing the wheel and instead build upon the solid foundation provided by modern browsers.

Our design system is built on the principles of Cube CSS, a CSS methodology that emphasizes simplicity, composition, and scalability. Cube stands for Composition, Utility, Block, and Exception. We use these principles to create a CSS architecture that is easy to understand, maintain, and extend. By focusing on composition and utility classes, we keep our styles modular and avoid unnecessary specificity. This approach helps us deliver consistent, predictable results across all our products.

We embrace the concept of composition, as described in Every Layout’s Composition. Rather than creating rigid, monolithic components, we design our system to be flexible and composable. Layouts and components are built from smaller, reusable pieces that can be combined in different ways to meet a variety of needs. This encourages creativity, adaptability, and scalability, allowing teams to build complex interfaces without duplicating code or styles.

We maintain a clear separation between layout and design. Layout concerns (such as spacing, positioning, and structure) are handled independently from design concerns (such as color, typography, and visual style). This separation makes our codebase easier to reason about and maintain. It also allows for greater flexibility, as layouts can be adjusted without affecting the underlying design, and vice versa. By keeping these concerns separate, we empower teams to iterate quickly and confidently.

Anything that should grow when a user raises their browser font size is sized in rem: type, spacing, icons, control heights and the width caps on text. Details that should stay crisp at every size stay in px: borders, hairlines, focus-ring offsets, shadows, breakpoints and decorative artwork.

The root is the legacy html { font-size: 62.5% }, so 1rem is 10px. Nobody types that rem by hand, because a typed 2rem hard-codes the 10px root into the value. Instead, px stays the source of truth and the build divides it by the root size in one place. The design tokens already work this way: the token tree holds px, and only the CSS output is rem (--tng-radius-4: 0.4rem is 4px).

Hand-written CSS follows the same rule. Reach for a token first, since --tng-spacing-20 is already rem. When no token fits, write remOf():

.tng-example {
inline-size: remOf(36px); /* compiles to 3.6rem */
min-block-size: max(44px, var(--tng-spacing-44)); /* a physical floor */
}

remOf() compiles away at build time against --tng-rem, the root size @tmedxp/figma-tokens publishes. When the 62.5% root goes away, that one value changes and every token and every remOf() follows. Stylelint rejects a typed rem.

Touch targets keep a px floor with max(). The WCAG minimum is a physical size, so it has to hold even on a host whose root is smaller than 10px.