theme: ./theme
drawings:
persist: false
title: My CSS journey
hideInToc: true
layout: full
layout: image
hideInToc: true
image: '/images/pixel-perfect-studios.webp'
layout: full
hideInToc: true
layout: image
hideInToc: true
image: '/images/stars-bg.webp'
Our story happens in France, specifically in Montreuil 93 RPZ gang brr-brr skidiki-pap-pap.
Brace yourselves, for the epic journey is about to begin, transcending the ordinary and plunging into the extraordinary, where destinies are forged and legends are born.
layout: full
hideInToc: true
hideInToc: true
hideInToc: true
HTML (HyperText Markup Language) is the most basic building block of the Web. It defines the meaning and structure of web content. Other technologies besides HTML are generally used to describe a web page's appearance/presentation (CSS) or functionality/behavior (JavaScript).
Source: developer.mozilla.org: HTML
[...], for example defining paragraphs, headings, and data tables, or embedding images and videos in the page.
Cascading Style Sheets (CSS) is a stylesheet language used to describe the presentation of a document written in HTML or XML (including XML dialects such as SVG, MathML or XHTML). CSS describes how elements should be rendered on screen, on paper, in speech, or on other media.
Source: developer.mozilla.org: CSS
CSS is a language of style rules that we use to apply styling to our HTML content, for example setting background colors and fonts, and laying out our content in multiple columns.
- [...]
- CSS saves a lot of work. It can control the layout of multiple web pages all at once
- External stylesheets are stored in CSS files
Source: w3schools.com
JavaScript is a scripting language that enables you to create dynamically updating content, control multimedia, animate images, and pretty much everything else.
Source: developer.mozilla.org: JavaScript
layout: cover
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>My test page</title>
</head>
<body>
<!-- content aka HTML Elements -->
</body>
</html>
- doctype: It is a required preamble.
- html: wraps all the content (known as root element)
- head: all the stuff you want to include on the HTML page that isn't the content (e.g. CSS, fonts, scripts, etc.)
- body: contains all the content (e.g. text, images, videos, etc.)
Source: developer.mozilla.org: Introduction to HTML, developer.mozilla.org: Getting started with the web
Non-exhaustive list of HTML elements:
- Headings (
<h1>
,<h2>
,...
,<h6>
) - Paragraph (
<p>
) - Links (
<a>
) - Lists (
<ul>
,<ol>
,<li>
) - Images (
<img>
)
- Tables (
<table>
,<tr>
,<td>
,<th>
) - Forms (
<form>
,<input>
,<button>
,<select>
,<textarea>
) - Div (
<div>
) - Span (
<span>
) - [...]
Source: developer.mozilla.org: Introduction to HTML, developer.mozilla.org: Getting started with the web
An attribute should have:
- A space between it and the element name.
- The attribute name, followed by an equal sign.
- An attribute value, wrapped with opening and closing quote marks.
Non-exhaustive list of attributes:
- class, id, name, type, aria-*, data-*
Source: developer.mozilla.org
The DOM (Document Object Model) is an API that represents and interacts with any HTML or XML-based markup language document. The DOM is a document model loaded in the browser and representing the document as a node tree, or DOM tree, where each node represents part of the document (e.g. an element, text string, or comment).
Source: developer.mozilla.org
A real representation
<body>
<h1>This is a red title</h1>
<p>This is a blue text.</p>
</body>
BODY
βββ H1
β βββ "This is a red title"
βββ P
βββ "This is a blue text."
Source: developer.mozilla.org
Non-exhaustive list of properties:
font-size
, color
, background-color
, padding
, margin
, border
, border-radius
, font-family
, [...]
Non-exhaustive list of selectors:
Name | Selector | selects |
---|---|---|
element | p | <p> |
id | #my-id | <element id="my-id"> |
class | .my-class | <element class="my-class"> |
attribute | [data-color-mode=dark] | <element data-color-mode="dark"> |
pseudo-class | a:hover | <a> only when mouse pointer is over the link |
<h1>This is a red title</h1>
<p>This is a blue text.</p>
h1 {
color: red;
font-size: 2.5rem;
line-height: 1;
}
p {
color: blue;
}
<head>
<style>
h1 {
color: red;
font-size: 5rem;
line-height: 1;
}
p {
color: blue;
}
</style>
</head>
/* main.css */
h1 {
color: red;
font-size: 5rem;
line-height: 1;
}
p {
color: blue;
}
<head>
<link href="main.css" rel="stylesheet" />
</head>
title: HTML, CSS & JS framework
level: 1
Bootstrap is the most popular HTML, CSS, and JS framework for developing responsive, mobile first projects on the web.
Source: getbootstrap.com - Bootstrap v3.3 (2014)
- Download Bootstrap
.css
files OR use a CDN (content delivery/distribution network)
<head>
<!-- Local Bootstrap CSS file -->
<link href="/css/bootstrap.css" rel="stylesheet" />
<!-- OR using a CDN -->
<link
crossorigin="anonymous"
href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
rel="stylesheet"
/>
<!-- custom local CSS file -->
<link href="/css/main.css" rel="stylesheet" />
</head>
<button type="button" class="btn btn-default">Default</button>
<button type="button" class="btn btn-primary">Primary</button>
<button type="button" class="btn btn-success">Success</button>
<button type="button" class="btn btn-info">Info</button>
<button type="button" class="btn btn-warning">Warning</button>
<button type="button" class="btn btn-danger">Danger</button>
* using Bootstrap v3.3 back in 2014
- Use LESS (built with) - (π€ what is it?)
- Use Sass (official port) - (π€ what is it?)
- CSS Cascade - default behavior (may not be officially recommended)
Source: getbootstrap.com - Bootstrap v3.3 (2014)
The cascade is the algorithm for solving conflicts where multiple CSS rules apply to an HTML element. The cascade algorithm is split into 5 distinct stages.
Source: web.dev, developer.mozilla.org
- Position and order of appearance
- Specificity: an algorithm which determines which CSS selector has the strongest match
- Cascade layers: layered style < unlayered style <
!important
unlayered style <!important
layered style
- Importance: normal rule (e.g.,
color
) <animation
rule <!important
rule <transition
rule
Source: developer.mozilla.org. Nice blog: 2019.wattenberger.co.
Source: css-tricks.com
- When selectors have an equal specificity value, the latest rule is the one that counts.
- When selectors have an unequal specificity value, the more specific rule is the one that counts.
!important
always win, only way to bypass is another!important
declared later
Source: smashingmagazine.com
/* (0,0,1,1,1) */
#myElement input.myClass {
color: red;
}
/* (0,0,0,2,1) */
[id='myElement'] input.myClass {
color: yellow;
}
/* (0,0,0,2,1) */
input[type='password']:required {
color: blue;
}
/* (0,0,0,0,4) */
html body main input {
color: green;
}
main.css
html {
position: relative;
min-height: 100%;
}
.navbar-default {
background-color: #eee;
border-color: #eee;
}
.btn {
transition: all ease-in-out 0.2s;
}
- Graduation π
- Learn so far: HTML, CSS, JavaScript, Bootstrap, jQuery*
Next π¨π»βπ ?
3 years engineering IT work-study program:
Single Page Application*, Angular*, Angular Material, Material Design, Sass
* will not be addressed, see more at: developer.mozilla.org/SPA, api.jquery.com & v7.angular.io/docs
Material Design [β¦] is a design language developed by Google in 2014. [β¦], Material Design uses more grid-based layouts, responsive animations and transitions, padding, and depth effects such as lighting and shadows.
Source: wikipedia.org/Material_Design
Material Design is a design system built and supported by Google designers and developers. Material.io includes in-depth UX guidance and UI component implementations for Android, Flutter, and the Web.
Source: m3.material.io
A design language or design vocabulary is an overarching scheme or style that guides the design of a complement of products or architectural settings, creating a coherent design system for styling.
Source: wikipedia.org/Design_language
A Design system is a collection of reusable components and clear standards that can be assembled together to build any number of applications.
Source: InVision
Source: m2.material.io - Angular Material v2
Source: wikipedia.org/Material_Design - Angular Material v3
Source: wikipedia.org/Material_Design - M2
Source: wikipedia.org/Material_Design - M3
Angular Material's theming APIs are built with Sass. This document assumes familiarity with CSS and Sass basics, including variables, functions, and mixins.
You can use Angular Material without Sass by using a pre-built theme, described in Using a pre-built theme below. However, using the library's Sass API directly gives you the most control over the styles in your application.
Source: material.angular.io
A CSS preprocessor is a program that lets you generate CSS from the preprocessor's own unique syntax.
Source: developer.mozilla.org
CSS on its own can be fun, but stylesheets are getting larger, more complex, and harder to maintain. This is where a preprocessor can help. Sass has features that donβt exist in CSS yet like nesting, mixins, inheritance, and other nifty goodies that help you write robust, maintainable CSS.
Source: sass-lang.com
π‘ Fun fact: Sass has two syntaxes!
@mixin button-base() {
@include typography(button);
@include ripple-surface;
@include ripple-radius-bounded;
/* [β¦] */
height: $button-height;
/* [β¦] */
&:hover {
cursor: pointer;
}
&:disabled {
color: $mdc-button-disabled-ink-color;
cursor: default;
pointer-events: none;
}
}
The SCSS syntax (
.scss
) is used most commonly. Itβs a superset of CSS [...].
@mixin button-base()
@include typography(button)
@include ripple-surface
@include ripple-radius-bounded
/* [β¦] */
height: $button-height
/* [β¦] */
&:hover
cursor: pointer
&:disabled
color: $mdc-button-disabled-ink-color
cursor: default
pointer-events: none
The indented syntax (
.sass
) is more unusual: it uses indentation rather than curly braces to nest statements, and newlines instead of semicolons to separate them.
Source: sass-lang.com
// _base.scss
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
// styles.scss
@use 'base';
.inverse {
background-color: base.$primary-color;
color: white;
}
body {
font:
100% Helvetica,
sans-serif;
color: #333;
}
.inverse {
background-color: #333;
color: white;
}
Other features: extend/inheritance, operators, functions, at-rules (if, each, for), lists, maps.
// whatever.scss
@import '~@angular/material/theming';
@include mat-core();
$candy-app-primary: mat-palette($mat-indigo);
$candy-app-accent: mat-palette($mat-pink, A200, A100, A400);
$candy-app-warn: mat-palette($mat-red);
$candy-app-theme: mat-light-theme($candy-app-primary, $candy-app-accent, $candy-app-warn);
@include angular-material-theme($candy-app-theme);
Source: v7.material.angular.io
component.html
<button mat-raised-button>Basic</button>
<button mat-raised-button color="primary">Primary</button>
<button mat-raised-button color="accent">Accent</button>
<button mat-raised-button color="warn">Warn</button>
<button mat-raised-button disabled>Disabled</button>
<a mat-raised-button routerLink=".">Link</a>
Source: v7.material.angular.io
- Graduation π
- Angular (Material Design) + me = β€οΈ
* another Material Design implementation for Angular (!== Angular Material)
Example usage:
<aside class="mdc-snackbar">
<div class="mdc-snackbar__surface" role="status" aria-relevant="additions">
<div class="mdc-snackbar__label" aria-atomic="false">Can't send photo. Retry in 5 seconds.</div>
<div class="mdc-snackbar__actions" aria-atomic="true">
<button type="button" class="mdc-button mdc-snackbar__action">
<div class="mdc-button__ripple"></div>
<span class="mdc-button__label">Retry</span>
</button>
</div>
</div>
</aside>
Source: github.com/material-components
The Block, Element, Modifier methodology (commonly referred to as BEM) is a popular naming convention for classes in HTML and CSS. [β¦], its goal is to help developers better understand the relationship between the HTML and CSS in a given project.
Source: css-tricks.com
Syntax:
block__element--modifier
- Block:
header
,container
,menu
,checkbox
,input
,card
,button
, β¦ - Element:
title
,item
,caption
,icon
- Modifier:
disabled
,highlighted
,checked
,size
,color
Source: getbem.com
index.html
<button class="button"><span class="button__label">Normal button</span></button>
<button class="button button--success button--large">
<span class="button__icon"></span><span class="button__label">Success button</span>
</button>
<button class="button button--danger button--outlined">Danger button</button>
main.css
.button {
/* [β¦] */
}
.button__label {
/* [β¦] */
}
.button--success {
/* [β¦] */
}
main.scss
.button {
/* [β¦] */
&__label {
/* [β¦] */
}
&--success {
/* [β¦] */
}
}
- Modularity:
- never dependent on other elements (no cascading problem)
- transfer blocks
- Reusability:
- reduces the amount of CSS code to maintain
- you can build a library of blocks
- Structure:
- simple and easy to understand
Source: getbem.com
- Bundle:
- without minifying/gzipping can bloat CSS files size
So far I know (or I thought I know):
- how to write CSS
- how to write Sass & use BEM
- use a CSS Framework (Bootstrap)
- use a Design System (Material Design)
Next step π ?
How to create a design system ?
Atomic design is methodology for creating design systems. There are five distinct levels in atomic design: atoms, molecules, organisms, templates, pages.
Source: bradfrost.com
Atoms are the basic building blocks of matter. Applied to web interfaces, atoms are our HTML tags, such as a form label, an input or a button.
Source: bradfrost.com
Molecules are groups of atoms bonded together and are the smallest fundamental units of a compound. These molecules take on their own properties and serve as the backbone of our design systems.
Source: bradfrost.com
Organisms are groups of molecules joined together to form a relatively complex, distinct section of an interface.
Source: bradfrost.com
Templates consist mostly of groups of organisms stitched together to form pages. Itβs here where we start to see the design coming together and start seeing things like layout in action.
Source: bradfrost.com
Pages are specific instances of templates. Here, placeholder content is replaced with real representative content to give an accurate depiction of what a user will ultimately see.
Source: bradfrost.com
layout: cover
hideInToc: true
- 09/2014 - 01/2022: CSS, Bootstrap, Material Design, Sass, BEM, Atomic design
- UPCITI: utility-first CSS framework tailwindcss, dark mode, theme configuration, CSS variables, CSS-in-JS, CSS layers
title: Utility-first CSS framework
level: 1
Traditional approach:
<div class="chat-notification">
<div class="chat-notification-logo-wrapper">
<img class="chat-notification-logo" src="/img/logo.svg" alt="ChitChat Logo" />
</div>
<div class="chat-notification-content">
<h4 class="chat-notification-title">ChitChat</h4>
<p class="chat-notification-message">You have a new message!</p>
</div>
</div>
.chat-notification {
/* [β¦] */
}
Source: tailwindcss.com
Utility classes approach:
<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4">
<div class="shrink-0">
<img class="h-12 w-12" src="/img/logo.svg" alt="ChitChat Logo" />
</div>
<div>
<div class="text-xl font-medium text-black">ChitChat</div>
<p class="text-slate-500">You have a new message!</p>
</div>
</div>
Source: tailwindcss.com
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
/* [β¦] */
content: ['./src/**/*.{html,js,ts,vue}'],
/* [β¦] */
};
// index.scss
@tailwind base;
@tailwind components;
@tailwind utilities;
- Build your CSS using CLI / bundler
- Import SCSS / CSS in HTML / TS
Source: tailwindcss.com
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
/* [β¦] */
theme: {
extend: {
colors: {
primary: {
900: 'var(--color-primary-900)',
// 800, 700, 600, 500, 400, 300, 200, 100, 50
},
},
},
},
};
// index.scss
.palette-a {
--color-primary-900: #881337;
/* [β¦] */
}
.palette-b {
--color-primary-900: #0c4a6e;
/* [β¦] */
}
.palette-c {
--color-primary-900: #064e3b;
/* [β¦] */
}
Source: tailwindcss.com
Custom properties (sometimes referred to as CSS variables or cascading variables) are entities defined by CSS authors that represent specific values to be reused throughout a document.
Source: developer.mozilla.org
How to declare?
/* @property at-rule */
@property --logo-color {
syntax: '<color>';
inherits: false;
initial-value: #c0ffee;
}
/* prefix of two dashes (--) */
section {
--logo-color: #c0ffee;
}
How to use?
details {
color: var(--logo-color, #c0ffee);
}
Other features:
:root
pseudo-class- inheritance
- fallback values
<!-- ButtonPrimary.vue -->
<template>
<button
type="button"
:class="[
'relative inline-flex items-center rounded-lg border text-sm font-bold focus:outline-none focus:ring-2 focus:ring-offset-2',
'disabled:cursor-not-allowed disabled:opacity-50',
'border-transparent bg-primary-900 text-base-50 hover:bg-primary-800 focus:ring-primary-800 dark:border-transparent dark:bg-base-600 dark:text-base-200 dark:hover:bg-base-500 dark:focus:ring-base-200 dark:focus:ring-offset-base-700',
'px-4 py-2',
]"
></button>
</template>
- How to share button common classes?
- It's not typed-safe (using TypeScript)
- HTML class size bloat
Use JavaScript object to share classes:
export const colors = {
button: {
common: 'relative inline-flex items-center rounded-lg border text-sm font-bold focus:outline-none [β¦]',
spacing: 'px-4 py-2',
disabled: 'disabled:cursor-not-allowed disabled:opacity-50',
// [β¦]
},
};
But still:
<!-- ButtonPrimary.vue -->
<template>
<button
type="button"
:class="[colors.button.common, colors.button.disabled, colors.button.primary, colors.button.spacing]"
></button>
</template>
- I need to create one Vue component per variant (button example: primary, secondary, outlined, success, warning, info, error)
- How to split set of classes for a component ? (like modifiers?)
- Same issues with headlessui (unstyled, fully accessible UI components)
Until β¦Vue.js Parisπ²π« #24
CSS-in-JS is a styling technique by which JavaScript is used to style components. When this JavaScript is parsed, CSS is generated (usually as a
<style>
element) and attached into the DOM. It enables the abstraction of CSS to the component level itself, using JavaScript to describe styles in a declarative and maintainable way.
Source: en.wikipedia.org
Source: 2023.stateofcss.com
Note: Meta open-sourced its CSS-in-JS tool early in December 2023: stylex.
A CSS Module is a CSS file in which all class names and animation names are scoped locally by default.
Source: github.com/css-modules
Usage with Vite:
/* example.module.css */
.red {
color: red;
}
// index.js
// .apply-color -> applyColor
import { red } from './example.module.css';
document.getElementById('foo').className = red;
Usage in Vue Single-File Component (SFC):
<template>
<p :class="classes.red">red</p>
</template>
<style module="classes">
.red {
color: red;
}
</style>
β Pros:
- no deps, no config, easy to use
β Cons:
- write (S)CSS
- write default theme as global
- Does not work in Functional Components/render functions
Panda is a new CSS-in-JS engine that aims to solve the challenges of CSS-in-JS in the server-first era. It provides styling primitives to create, organize, and manage CSS styles in a type-safe and readable manner.
Source: panda-css.com
How to install?
// panda.config.js
import { defineConfig } from '@pandacss/dev';
export default defineConfig({
preflight: true,
presets: [], // <-- import custom preset
include: ['./src/**/*.{js,jsx,ts,tsx,vue}'],
outdir: 'styled-system',
});
panda codegen
/* src/index.css */
@layer reset, base, tokens, recipes, utilities;
<!-- src/App.vue -->
<script setup lang="ts">
import { css } from '../styled-system/css';
const classes = css({
fontSize: '5xl',
fontWeight: 'bold',
});
</script>
<template>
<div :class="classes">Hello πΌ!</div>
</template>
* c.f. CSS Cascade algorithm
Cascade layers are most relevant when you're working with CSS from multiple sources when there are conflicting CSS selectors and competing specificities, or when you're considering using !important.
Source: developer.mozilla.org
/* unlayered author style: specificity is used */
.overly#powerful .framework.widget {
color: maroon;
}
/* add some IDs to this ??? */
.my-single_class {
/* add !important ??? */
color: rebeccapurple;
}
Source: css-tricks.com
@layer framework {
.overly#powerful .framework.widget {
color: maroon;
}
}
@layer site {
.my-single_class {
color: rebeccapurple;
}
}
Other features: nested layers, anonymous layers, import styles based on conditions (media/feature queries), etc.
Design tokens are a methodology for expressing design decisions in a platform-agnostic way so that they can be shared across different disciplines, tools, and technologies. They help establish a common vocabulary across organisations.
Source: Design Tokens Format Module from W3C
Design tokens are the platform-agnostic way to manage design decisions in your application or website. It is a collection of attributes that describe any fundamental/atomic visual style. Each attribute is a key-value pair.
Source: panda-css.com
/* panda.config.js */
import { defineConfig } from '@pandacss/dev';
export default defineConfig({
theme: {
// ππ» Define your tokens here
tokens: {
colors: {
primary: { value: '#0FEE0F' },
secondary: { value: '#EE0F0F' },
},
fonts: {
body: { value: 'system-ui, sans-serif' },
},
},
},
});
<!-- HelloWorld.vue -->
<template>
<p :class="classes">Hello World</p>
</template>
<script setup lang="ts">
import { css } from '../styled-system/css';
const classes = css({
color: 'primary',
fontFamily: 'body',
});
</script>
Source: panda-css.com
By default, any configuration you add in your own
panda.config.js
file is smartly merged with the default configuration, allowing your override or extend specific parts of the configuration.
Source: panda-css.com
What does it contain?
- Include base preset
- Define colors, breakpoints, tokens (sizes, animations, line-heigths etc.), utilities, fonts, global style, etc.
- Conditions: dark / light mode, multiple themes
import { definePreset } from '@pandacss/dev';
import pandaPreset from '@pandacss/preset-panda';
const basePreset = definePreset({
presets: [pandaPreset],
theme: {
extend: {
breakpoints: {
xs: '475px',
'3xl': '1920px',
},
tokens: {
sizes: {
'8xl': { value: '85rem' },
'9xl': { value: '90rem' },
},
},
},
},
});
import { definePreset } from '@pandacss/dev';
export const orgPreset = definePreset({
presets: [basePreset],
conditions: {
light: '',
dark: '.dark &',
orgTheme: '.org &',
},
theme: {
extend: {
/**
* colors > org > 900 > value
* fonts > inter > value
*/
tokens: {},
semanticTokens: {},
},
},
});
const config = {
conditions: {
light: '[data-color-mode=light] &',
dark: '[data-color-mode=dark] &',
pinkTheme: '[data-theme=pink] &',
blueTheme: '[data-theme=blue] &',
},
};
<template>
<div data-theme="pink" data-color-mode="dark">
<h1 :class="classes">Hello World</h1>
</div>
</template>
<script setup lang="ts">
import { css } from '../styled-system/css';
const classes = css({
color: 'text',
});
</script>
const theme = {
// ...
semanticTokens: {
colors: {
text: {
value: {
_pinkTheme: {
base: '{colors.pink.500}',
_dark: '{colors.pink.300}',
},
_blueTheme: {
base: '{colors.blue.500}',
_dark: '{colors.blue.300}',
},
},
},
},
},
};
Source: panda-css.com
A recipe is a way to write CSS-in-JS with better performance, developer experience, and composability. One of its key features is the ability to create multi-variant styles with a type-safe runtime API.
Source: panda-css.com
Atomic recipes are a way to create multi-variant atomic styles with a type-safe runtime API.
Source: panda-css.com
Config recipes are extracted and generated just in time, this means regardless of the number of recipes in the config, only the recipes and variants you use will exist in the generated CSS.
Source: panda-css.com
Config recipe | Atomic recipe (cva) | |
---|---|---|
Can both use any theme tokens, utilities or conditions | β yes | β yes |
Are generated just in time (JIT) based on usage | β yes, only the recipe variants found in your code will be generated | β no, all variants found in your cva recipes will always be generated |
Can be shared in a preset | β
yes, you can include it in your preset.theme.recipes |
β no |
Can be colocated in your markup code | β no, they must be defined or imported in your panda.config |
β yes, you can place it anywhere in your app |
Generate atomic classes | β no, a specific className will be generated using your recipe.className |
β yes |
Source: panda-css.com
import { cva } from '../styled-system/css';
const button = cva({
base: {
display: 'flex',
},
variants: {
visual: {
solid: { bg: 'red.200', color: 'white' },
outline: {
borderWidth: '1px',
borderColor: 'red.200',
},
},
size: {
sm: { padding: '4', fontSize: '12px' },
lg: { padding: '8', fontSize: '24px' },
},
},
});
Atomic recipe example
<!-- ButtonPrimary.vue -->
<template>
<button :class="classes"></button>
</template>
<script setup lang="ts">
import { button } from '<path>/button.recipe.ts';
const classes = button({
visual: 'solid',
size: 'lg',
});
</script>
Source: panda-css.com
Storybook is a frontend workshop for building UI components and pages in isolation. Thousands of teams use it for UI development, testing, and documentation.
Source: storybook.js.org
A documentation tool is a tool for documenting design tokens usage. For example: Storybook.
<template>
<button :class="classes" title="Save" @click="submit">Save</button>
</template>
<script setup lang="ts">
import { button } from '@scope/design-system';
const classes = button({ variant: 'primary', size: 'md' });
</script>
<template>
<ButtonComponent visual="primary" size="md" title="Save" @click="submit">Save</ButtonComponent>
<ButtonComponent visual="error" rounded="none" title="Delete" @click="delete">Delete</ButtonComponent>
</template>
<template>
<ButtonComponent visual="outline" content="icon" title="Export file to CSV" @click="export">
<IconComponent class="h-5 w-5" :icon="faFileExport" />
</ButtonComponent>
</template>
A monorepo is a single repository containing multiple distinct projects, with well-defined relationships.
Source: monorepo.tools
.
βββ packages/
βββ preset-panda/
βββ design-system/
β βββ public/
β β βββ fonts/
β βββ recipes/
β βββ components/
β βββ stories/
βββ app/
βββ node_modules/
β βββ @scope/styled-system
βββ src/
βββ components/
βββ pages/
- preset-panda: export your base / project / organization specific preset.
- design-system: export the content you need to use your design system (e.g. static files + recipes + components)
-
@scope/styled-system: generated panda CSS Utilities (such as
css
function) & types based on preset & buildinfo from design-system. - app/src: contains your custom application pages/components that are specific to your context
Notions: HTML & CSS basics, CSS Specificity, CSS Frameworks, CSS preprocessor, CSS Variables, CSS-in-JS, CSS Cascade Layers
Glossary: Design system, Design tokens
Methodologies: BEM, Atomic Design
CSS frameworks: Bootstrap, Material Components, tailwindcss, panda
Tools: Storybook
What's next ? : web-components, WASM, Rust
layout: cover
hideInToc: true