Morfeo

website·Indexed 30 days ago

https://morfeo.dev/

A build-time CSS-in-TS solution for creating design systems and styling applications with minimal shipped CSS. It provides tools for theming, responsive design, dark mode, and pseudo-classes, allowing developers and designers to share a common design language.

Tokens
5.2K
Snippets
30
Records
34
Agent score
58%

What's inside Morfeo

  1. Overview of Morfeo's architecture

    Morfeo is a toolset for building design systems and styling applications with nearly zero runtime. It consists of three core components:

    1. Theming System: Allows developers to create a custom Design Language or use a default theme.
    2. CSS-in-TS Library: Provides a type-safe way to style applications based on the defined theme.
    3. Ahead-of-Time (AOT) CSS Extraction: Analyzes the code to collect css-in-ts definitions and extracts only the necessary CSS at build time.
  2. Overview of Morfeo CSS-in-TS

    Morfeo is a build-time CSS-in-TS solution designed for advanced theming with a minimal CSS footprint. It provides the developer experience (DX) of CSS-in-JS but avoids runtime style injection by extracting CSS at build time. It is framework-agnostic (supporting Next.js, Remix, React, Svelte) and compatible with various bundlers including Webpack, Vite, and Esbuild. The compiler optimizes styles by splitting them into reusable atomic CSS classes to reduce the final bundle size.
  3. Understand Morfeo's core architectural approach

    Morfeo is designed to bridge the communication gap between developers and designers by implementing three core technical concepts:

    1. Design Language: A single source of truth (typically a theme object) containing the primitive blocks used to construct all layouts.
    2. Parser: A mechanism that converts the design language/theme into valid HTML and CSS.
    3. TypeScript: Used to enforce the use of the theme when describing UIs, ensuring the design language is spoken correctly and consistently across the project.
  4. Apply pseudo-classes in Morfeo styles

    Use the & selector followed by a single colon and the pseudo-class name (e.g., &:hover, &:disabled) within a morfeo.css style object to apply styles based on the element's state. This follows standard CSS pseudo-class logic and is fully type-safe.
    const classes = morfeo.css({
      button: {
        bg: 'primary',
        radius: 'm',
        px: 'm',
        py: 's',
        transition: 'fast',
        '&:hover': {
          bg: 'primary.light',
        },
        '&:disabled': {
          opacity: 'light',
          cursor: 'not-allowed',
        },
      },
    });
  5. Implement responsive styles using ResponsiveValue

    In Morfeo, responsiveness is handled by passing a ResponsiveValue object instead of a plain value to a CSS property. A ResponsiveValue allows you to define a default value and specific overrides for different screen breakpoints (e.g., xs, sm, md, lg). Only the breakpoints that differ from the default need to be specified.
    import { morfeo } from '../morfeo';
     
    const classes = morfeo.css({
      container: {
        padding: {
          default: 'm', // Base padding
          sm: 's',      // Padding for small screens
        },
        bg: 'white',
        color: 'text',
      },
    });
     
    export function Card() {
      return (
        <div className={classes('container')}>
          This card will have different padding based on the screen size!
        </div>
      );
    }
  6. Install Morfeo using the CLI

    The recommended way to install Morfeo is via the CLI initialization command. This process will prompt you for the location of your source code, the desired output path for the extracted CSS, and the location for the Morfeo instance configuration file. The CLI then automatically updates your package.json and .gitignore and creates the necessary configuration files.
    npx morfeo init
  7. Combine pseudo-classes and pseudo-elements in Morfeo

    You can nest pseudo-elements inside pseudo-classes to trigger specific element styles based on a state change. For example, you can define a style for a pseudo-element that only appears when the parent element is hovered.
    const classes = morfeo.css({
      tag: {
        position: 'relative',
        '&:hover': {
          '&::after': {
            content: "'Show more ->'",
            position: 'absolute',
          },
        },
      },
    });
  8. Understand the Morfeo build-time workflow

    Morfeo operates in three primary steps to ensure high performance and a small CSS footprint:

    1. Define your theme: Create a custom theme or use a preset.
    2. Style components: Write CSS-in-JS styles that reference the defined theme.
    3. Build-time extraction: The Morfeo compiler automatically extracts the necessary styles into atomic CSS classes during the build process, eliminating runtime injection.
  9. Apply pseudo-elements in Morfeo styles

    Use the & selector followed by double colons :: and the pseudo-element name (e.g., &::first-line, &::after) within a morfeo.css style object. Double colons are required for pseudo-elements, consistent with standard CSS syntax.
    const classes = morfeo.css({
      paragraph: {
        color: 'text',
        '&::first-line': {
          textTransform: 'uppercase',
        },
      },
    });
  10. Complete Morfeo setup by importing the generated CSS

    After running the CLI installation and generating the morfeo.css file, you must manually import this CSS file into the main entry point of your application (e.g., index.tsx or main.js) to apply the styles.
    import './styles/morfeo.css';
     
    export function App() {
      return <></>;
    }
  11. Customize media query generation logic

    To change how media queries are constructed (e.g., to move away from mobile-first or add max-width constraints), use the mediaQueries slice in your theme. Use the {{key}} syntax as placeholders; these will be replaced by the corresponding values from the breakpoints slice during CSS generation.
    const theme = {
      breakpoints: {
        xs: '375px',
        sm: '768px',
        md: '1366px',
        lg: '1920px',
      },
      mediaQueries: {
        xs: '@media screen and (min-width: {{xs}})',
        sm: '@media screen and (min-width: {{xs}}) and (max-width: {{md}})',
        md: '@media screen and (min-width: {{md}}) and (max-width: {{lg}})',
        lg: '@media screen (min-width: {{lg}})',
      },
    };
  12. Manage Morfeo dependencies and scripts in package.json

    Morfeo adds specific dependencies and scripts to your package.json.

    • @morfeo/compiler is added as a devDependency.
    • @morfeo/web (or @morfeo/react if React is detected) is added as a dependency.
    • dev:morfeo script runs the extractor in watch mode.
    • build:morfeo script runs a one-time extraction.
    {
      "scripts": {
        "dev:morfeo": "morfeo extract --watch",
        "build:morfeo": "morfeo extract"
      },
      "dependencies": {
        "@morfeo/web": "<latest-version>"
      },
      "devDependencies": {
        "@morfeo/compiler": "<latest-version>"
      }
    }