Skip to content

Commit

Permalink
Extend Component Documentation (#176)
Browse files Browse the repository at this point in the history
* feat: compound components

* docs: link to compound component example

* docs: kick off compound components page

* fix: prettier and syncpack failures

* docs: update example to include boolean variants

* chore(vue): include boolean variant

* chore(astro-with-tailwindcss): include boolean variant

* chore(react-with-tailwindcss): include boolean variant

* chore(react-with-css-modules): include boolean variant

* chore(svelte): include boolean variant

* docs: polymorphism

* chore(react-with-tailwindcss-compound): tidy

* feat: compound docs

* fix: sync versions

* Update packages/cva/package.json

* chore: kick off beta examples

* chore: create latest examples dir

* chore: add beta examples

* chore: add stackblitz embeds to beta pages

* chore: revert manual branch override

* docs: compound components

* chore: tidy up
  • Loading branch information
joe-bell authored Dec 13, 2024
1 parent c58c1a1 commit 5579f51
Show file tree
Hide file tree
Showing 182 changed files with 2,790 additions and 327 deletions.
17 changes: 15 additions & 2 deletions .config/.syncpackrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
{
"label": "Use `workspace:*` protocol for local packages",
"packages": [
"root",
"docs-*",
"cva",
"class-variance-authority",
Expand All @@ -21,19 +22,31 @@
"pinVersion": "workspace:*"
},
{
"label": "Use `latest` for examples",
"label": "Use `latest` for `latest` examples",
"packages": [
"example-*"
],
"dependencies": [
"cva",
"class-variance-authority"
],
"dependencyTypes": [
"!local"
],
"pinVersion": "latest"
},
{
"label": "Use `beta` for `beta` examples",
"packages": [
"example-*"
],
"dependencies": [
"cva"
],
"dependencyTypes": [
"!local"
],
"pinVersion": "beta"
},
{
"label": "Keep all other dependencies in sync",
"packages": [
Expand Down
46 changes: 43 additions & 3 deletions docs/beta/astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const config = {
export default defineConfig({
site,
output: "static",
adapter: vercel({ analytics: false }),
adapter: vercel(),
integrations: [
starlight({
...config,
Expand All @@ -41,6 +41,10 @@ export default defineConfig({
{ label: "What's New?", link: "/getting-started/whats-new" },
{ label: "Installation", link: "/getting-started/installation" },
{ label: "Variants", link: "/getting-started/variants" },
{
label: "Compound Components",
link: "/getting-started/compound-components",
},
{
label: "Extending Components",
link: "/getting-started/extending-components",
Expand All @@ -49,12 +53,48 @@ export default defineConfig({
label: "Composing Components",
link: "/getting-started/composing-components",
},
{
label: "Polymorphism",
link: "/getting-started/polymorphism",
},
{ label: "TypeScript", link: "/getting-started/typescript" },
],
},
{
label: "Examples ↗",
link: "https://cva.style/docs/examples/astro",
label: "Examples",
items: [
{
label: "11ty",
link: "/examples/11ty",
},
{
label: "Astro",
link: "/examples/astro",
},
{
label: "BEM",
link: "/examples/bem",
},
{
label: "React",
items: [
{ label: "CSS Modules", link: "/examples/react/css-modules" },
{ label: "Tailwind CSS", link: "/examples/react/tailwindcss" },
],
},
{
label: "Svelte",
link: "/examples/svelte",
},
{
label: "Vue",
link: "/examples/vue",
},
{
label: "Other Use Cases",
link: "/examples/other-use-cases",
},
],
},
{
label: "API Reference",
Expand Down
1 change: 1 addition & 0 deletions docs/beta/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"date-fns": "3.6.0",
"sharp": "^0.33.2",
"tailwindcss": "^3.4.3",
"tiny-invariant": "1.3.1",
"typescript": "5.4.5"
}
}
25 changes: 25 additions & 0 deletions docs/beta/src/components/stackblitz.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
import invariant from "tiny-invariant";
export interface Props {
dir?: string;
file?: string;
}
const branch = "main";
const { dir, file } = Astro.props;
invariant(dir, "No directory specified");
invariant(file, "No file specified");
---

<div class="mt-4 block [&>*+*]:mt-4">
<a href={`https://github.com/joe-bell/cva/tree/${branch}/${dir}/${file}`}>
View on GitHub <span aria-label="External">↗</span>
</a>
<iframe
style={{ aspectRatio: 1 / 1, width: "100%" }}
src={`https://stackblitz.com/github/cva/tree/${branch}/${dir}?embed=1&file=${file}&hideNavigation=1&view=preview`}
></iframe>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import React from "react";
import { cva, type VariantProps } from "class-variance-authority";
---
title: 11ty
---

## Tailwind CSS

```js
// button.11ty.js
const { cva } = require("class-variance-authority");

// ⚠️ Disclaimer: Use of Tailwind CSS is optional
const button = cva("button", {
variants: {
intent: {
Expand Down Expand Up @@ -29,13 +37,7 @@ const button = cva("button", {
},
});

export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof button> {}

export const Button: React.FC<ButtonProps> = ({
className,
intent,
size,
...props
}) => <button className={button({ intent, size, className })} {...props} />;
module.exports = function ({ label, intent, size }) {
return `<button class="${button({ intent, size })}">${label}</button>`;
};
```
12 changes: 12 additions & 0 deletions docs/beta/src/content/docs/examples/astro.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: Astro
---

import StackBlitz from "../../../components/stackblitz.astro";

## Tailwind CSS

<StackBlitz
dir="examples/latest/astro-with-tailwindcss"
file="src/components/button.astro"
/>
58 changes: 58 additions & 0 deletions docs/beta/src/content/docs/examples/bem.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: BEM
---

```css
/* styles.css */
.button {
/* */
}

.button--primary {
/* */
}
.button--secondary {
/* */
}

.button--small {
/* */
}
.button--medium {
/* */
}

.button--primary-small {
/* */
}
```

```ts
import { cva } from "class-variance-authority";

const button = cva("button", {
variants: {
intent: {
primary: "button--primary",
secondary: "button--secondary",
},
size: {
small: "button--small",
medium: "button--medium",
},
},
compoundVariants: [
{ intent: "primary", size: "medium", class: "button--primary-small" },
],
defaultVariants: {
intent: "primary",
size: "medium",
},
});

button();
// => "button button--primary button--medium"

button({ intent: "secondary", size: "small" });
// => "button button--secondary button--small"
```
27 changes: 27 additions & 0 deletions docs/beta/src/content/docs/examples/other-use-cases.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: Other Use Cases
---

Although primarily designed for handling class names, at its core, `cva` is really just a fancy way of managing a string…

## Dynamic Text Content

```ts
const greeter = cva("Good morning!", {
variants: {
isLoggedIn: {
true: "Here's a secret only logged in users can see",
false: "Log in to find out more…",
},
},
defaultVariants: {
isLoggedIn: "false",
},
});

greeter();
// => "Good morning! Log in to find out more…"

greeter({ isLoggedIn: "true" });
// => "Good morning! Here's a secret only logged in users can see"
```
10 changes: 10 additions & 0 deletions docs/beta/src/content/docs/examples/react/css-modules.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: React with CSS Modules
---

import StackBlitz from "../../../../components/stackblitz.astro";

<StackBlitz
dir="examples/beta/react-with-css-modules"
file="src/components/button/button.tsx"
/>
19 changes: 19 additions & 0 deletions docs/beta/src/content/docs/examples/react/tailwindcss.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
title: React with Tailwind CSS
---

import StackBlitz from "../../../../components/stackblitz.astro";

## Basic Component

<StackBlitz
dir="examples/beta/react-with-tailwindcss"
file="src/components/button/button.tsx"
/>

## Compound Components

<StackBlitz
dir="examples/beta/react-with-tailwindcss-compound"
file="src/components/nav/nav.tsx"
/>
7 changes: 7 additions & 0 deletions docs/beta/src/content/docs/examples/svelte.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: Svelte
---

import StackBlitz from "../../../components/stackblitz.astro";

<StackBlitz dir="examples/latest/svelte" file="src/components/button.svelte" />
7 changes: 7 additions & 0 deletions docs/beta/src/content/docs/examples/vue.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: Vue
---

import StackBlitz from "../../../components/stackblitz.astro";

<StackBlitz dir="examples/latest/vue" file="src/components/Button.vue" />
31 changes: 31 additions & 0 deletions docs/beta/src/content/docs/getting-started/compound-components.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
title: Compound Components
---

For larger, more complex components, you may end up wanting to create a set of composable components that work together: "Compound Components"

<details>
<summary>e.g. <code>&lt;Accordion.Subcomponent /&gt;</code> instead of <code>&lt;Accordion /&gt;</code></summary>

```tsx
import * as Accordion from "./Accordion";

function Example() {
return (
<Accordion.Root>
<Accordion.Item>
<Accordion.Header>Section 1</Accordion.Header>
<Accordion.Content>Content 1</Accordion.Content>
</Accordion.Item>
</Accordion.Root>
);
}
```

</details>

`cva` encourages you to build these compound components **with the power of CSS**; leverage the cascade, custom properties, `:has()` selectors, and more…

## Examples

- [React with Tailwind CSS (Compound Components)](../examples/react/tailwindcss#compound-components)
6 changes: 1 addition & 5 deletions docs/beta/src/content/docs/getting-started/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,7 @@ You can enable autocompletion inside `cva` using the steps below:

### Handling Style Conflicts

Although `cva`'s API is designed to help you avoid styling conflicts, there's still a small margin of error.

If you're keen to lift that burden altogether, check out the wonderful [`tailwind-merge`](https://github.com/dcastil/tailwind-merge) package.

For bulletproof components, extend `cva` with `twMerge`.
If you want to merge Tailwind CSS classes without conflicts, you may wish to [roll-your-own `cva`](../api-reference#defineconfig) with the [`tailwind-merge`](https://github.com/dcastil/tailwind-merge) package:

<details>

Expand Down
Loading

0 comments on commit 5579f51

Please sign in to comment.