Skip to content

Commit

Permalink
v1 (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
typicode authored Nov 1, 2024
1 parent 7777055 commit 1c6074b
Show file tree
Hide file tree
Showing 52 changed files with 1,578 additions and 10,644 deletions.
39 changes: 0 additions & 39 deletions .github/workflows/deploy.yml

This file was deleted.

2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
node_modules
lib
docs/.vitepress/cache
docs/.vitepress/dist
.DS_Store
.idea
276 changes: 233 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,262 @@
# 💧 MistCSS
# MistCSS

[![Node.js CI](https://github.com/typicode/mistcss/actions/workflows/node.js.yml/badge.svg)](https://github.com/typicode/mistcss/actions/workflows/node.js.yml)
> Simplicity is the ultimate sophistication
> Create components with 50% less code
MistCSS lets you create reusable visual components without JavaScript or TypeScript (_think about it for a second... no JS/TS needed_).

MistCSS is a new, better and faster way to write visual components. ~~CSS-in-JS~~? Nope! JS-from-CSS 👍
Leverage native HTML and CSS, get type safety and auto completion. Just clean and efficient styling.

All major frameworks are supported.
<img width="1116" alt="Screenshot 2024-11-01 at 03 47 44" src="https://github.com/user-attachments/assets/74aea071-be00-4d03-b43a-e46d6282e4b5">

## 1. Write your component in CSS only
_What you see above is standard HTML ([data-attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*)) and CSS ([nested CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting)). MistCSS simply creates a `d.ts` file based on your CSS._

`./src/Button.mist.css`
## Features

- 🥶 Below zero-runtime, it's zero JavaScript. Smaller bundles and faster code.
- 💎 What you write is what you get. No transformations, easy debugging.
- 🎒 Standards-based, reusable styles across frameworks, compatible with Tailwind or any CSS framework
- ⚡️ Instantly productive, no learning curve, simple onboarding.
- 💖 Back to basics with a modern twist: access the full power of HTML and CSS, enhanced with type safety and code completion (without the complexity).

## Usage

Traditional approaches require wrapping your markup/styles in JavaScript functions (`Button.tsx``<button/>`, `Input.tsx``<input/>`, ...), defining props with TypeScript types, and writing logic to manage class names.

With MistCSS, styling is straightforward and minimal. Here’s how it looks:

`mist.css`

```css
@scope (button.custom-button) {
:scope {
background: black;
button {
border-radius: 1rem;
padding: 1rem;
background: lightgray;

&[data-variant='primary'] {
background-color: black;
color: white;
}

&[data-variant='secondary'] {
background-color: grey;
color: white;
}
}
```

/* 👇 Define component's props directly in your CSS */
&[data-variant='primary'] {
background: blue;
}
`Page.tsx`

&[data-variant='secondary'] {
background: gray;
}
```jsx
<>
<button data-variant="primary">Save</button>
<button data-variant="tertiary">Save</button> {/* TS error, tertiary isn't valid */}
</>
```

Output

```jsx
<button data-variant="primary">Save</button> {/* Same as in Page.tsx */}
```

_This example demonstrates enums, but MistCSS also supports boolean and string props. For more details, see the FAQ._

## How does it work?

MistCSS parses your `mist.css` file and generates `mist.d.ts` for type safety.

For instance, here’s the generated `mist.d.ts` for our button component:

```typescript
interface Mist_button extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
'data-variant'?: 'primary' | 'secondary'
}

declare namespace JSX {
interface IntrinsicElements {
button: Mist_button // ← <button/> is extended at JSX level to allow 'primary' and 'secondary' values
}
}
```

## 2. Run MistCSS codegen
That’s it! Simple yet powerful, built entirely on browser standards and TypeScript/JSX.

## Install

```sh
npm install mistcss --save-dev
```

`postcss.config.js`

```js
module.exports = {
plugins: {
mistcss: {},
},
}
```

`layout.tsx`

```shell
mistcss ./src --target=react --watch
# It will create ./src/Button.mist.tsx
```ts
import './mist.css'
```

## 3. Get a type-safe component without writing TypeScript
## FAQ

### Can I use CSS frameworks like Tailwind or Open Props?

Absolutely, MistCSS is pure HTML and CSS, generating only `mist.d.ts`, so there are no limitations. You can integrate any CSS framework seamlessly. Here are a few examples to get you started:

#### Tailwind v3 ([@apply](https://tailwindcss.com/docs/functions-and-directives#apply))

```css
button {
@apply bg-blue-500 text-white;
/* ... */
}
```

#### Tailwind v3 ([theme](https://tailwindcss.com/docs/functions-and-directives#theme))

```css
button {
background: theme(colors.blue.500);
/* ... */
}
```

#### Tailwind v4

Tailwind v4 will support CSS variables natively (see [blog post](https://tailwindcss.com/blog/tailwindcss-v4-alpha
)).

`./src/App.tsx`
#### Tailwind (inline style)

To override some styles, you can use `className`

```jsx
<button data-variant="primary" className="p-12">
Save
</button>
```

#### Open Props

```css
button {
background-color: var(--blue-6);
/* ... */
}
```

### Can I do X without JavaScript?

CSS is more powerful than ever, before reaching for JS, explore if native CSS features can accomplish what you need.

### How to write enum, boolean, string props and conditions?

```css
div[data-component='section']
/* CSS variables */
--color: ...;

/* Default styles */
background: var(--color, green);
margin: ...;
padding: ...;

/* Enum props */
&[data-size="sm"] { ... }
&[data-size="lg"] { ... }

/* Boolean props */
&[data-is-active] { ... }

/* Condition: size="lg" && is-active */
&[data-size="lg"]&[data-is-active] { ... }

/* Condition: size="lg" && !is-active */
&[data-size="lg"]:not([data-is-active]) { ... }
}
```

```jsx
<div
data-component="section"
data-size="foo"
data-is-active
style={{ '--color': 'red' }}
/>
```

### How to re-use the same tag

If you want both basic links and button-styled links, here’s how you can do:

```css
a { /* ... */ }

a[data-component='button'] { /* ... */
&[data-variant='primary'] { /* ... */ }
}
```

```jsx
import { CustomButton } from './Button.mist'
<>
<a href="/home">Home</a>
<a href="/home" data-component="button">Home</a>
<a href="/home" data-component="button" data-variant="primary">Home</a>
<a href="/home" data-variant="primary">Home</a> {/* TS error, `data-variant` is only valid with `data-component="button"` */}
</>
```

> [!NOTE]
> `data-component` is just a naming convention. Feel free to use any attribute, like `data-style='button'` or `data-button`. It’s simply a way to differentiate between components using the same tag.

### How to build complex components?

export const App = () => (
<>
<CustomButton variant="primary">Save</CustomButton>
`mist.css`

{/* TypeScript will catch the error */}
<CustomButton variant="tertiary">Cancel</CustomButton>
</>
)
```css
article[data-component='card'] { /* ... */ }
div[data-component='card-title'] { /* ... */ }
div[data-component='card-content'] { /* ... */ }
```

`Card.jsx`

```jsx
export function Card({ title, children }) {
return (
<article data-component="card">
<div data-component="card-title">{title}</div>
<div data-component="card-content">{children}</div>
</article>
)
}
```

MistCSS can generate ⚛️ **React**, 💚 **Vue**, 🚀 **Astro**, 🧠**Svelte** and 🔥 **Hono** components. You can use 🍃 **Tailwind CSS** to style them.
> [!TIP]
> To indicate that these styles aren't meant to be used outside of `Card`, you can name them `data-p-component` (`p` for `private`) or use another naming convention.
## Documentation
### How to define CSS variables

```css
:root {
--primary-color: #007bff;
--secondary-color: #6c757d;
}

button {
background: var(--primary-color)
/* ... */
```

https://typicode.github.io/mistcss
See also your CSS framework/tooling documentation for ways to define them in JS if you prefer.

## Supports
### Origin of the project name?

- [Next.js](https://nextjs.org/)
- [Remix](https://remix.run/)
- [React](https://react.dev/)
- [Vue](https://vuejs.org)
- [Svelte](https://svelte.dev/)
- [Astro](https://astro.build/)
- [Hono](https://hono.dev/)
- [Tailwind CSS](https://tailwindcss.com/)
Mist is inspired by atomized water 💧 often seen near waterfalls. A nod to the _Cascading_ in CSS 🌊.
21 changes: 0 additions & 21 deletions docs/.gitignore

This file was deleted.

4 changes: 0 additions & 4 deletions docs/.vscode/extensions.json

This file was deleted.

11 changes: 0 additions & 11 deletions docs/.vscode/launch.json

This file was deleted.

Loading

0 comments on commit 1c6074b

Please sign in to comment.