Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/assets/vitest.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 9 additions & 3 deletions src/components/build-with-friends/build-with-friends.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import openPropsIcon from "../../assets/open-props.svg?type=raw";
import storybookIcon from "../../assets/storybook.svg?type=raw";
import tailwindIcon from "../../assets/tailwind-logo.svg?type=raw";
import typescriptIcon from "../../assets/typescript.svg?type=raw";
import vitestIcon from "../../assets/vitest.svg?type=raw";
import wccIcon from "../../assets/wcc.svg?type=raw";
import wtrIcon from "../../assets/modern-web.svg?type=raw";

Expand Down Expand Up @@ -34,14 +35,19 @@ export default class BuildWithFriends extends HTMLElement {
</span>
<span class="${styles.icon}">
<span>${wtrIcon}</span>
<span>Web Test Runner</span>
<span class="${styles.iconLabel}">Web Test Runner</span>
</span>
<span class="${styles.icon}">
${wccIcon}
<span>${wccIcon}</span>
<span class="${styles.iconLabel}">WC Compiler</span>
</span>
<span class="${styles.icon}">
<span>${openPropsIcon}</span>
<span>Open Props</span>
<span class="${styles.iconLabel}">Open Props</span>
</span>
<span class="${styles.icon}">
<span>${vitestIcon}</span>
<span class="${styles.iconLabel}">Vitest</span>
</span>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
display: inline-block;
}

.iconLabel {
padding-left: var(--size-1);
}

@media (min-width: 600px) {
.icon {
display: inline-block;
Expand Down
143 changes: 2 additions & 141 deletions src/pages/guides/ecosystem/storybook.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ We were not able to detect the right builder for your project. Please select one
Webpack 5
```

> See our Vitest docs for additional configuration examples to support [Import Attributes](/guides/ecosystem/vitest/#import-attributes) and [Greenwood resource plugins](/guides/ecosystem/vitest/#resource-plugins) usage in your components. For that guide, you'll be updating a _vite.config.js_ file instead.

## Usage

You should now be good to start writing your first story! 📚
Expand Down Expand Up @@ -145,147 +147,6 @@ You'll want to create a CommonJS version with the following name, depending on w

<!-- prettier-ignore-end -->

## Import Attributes

As [Vite does not support Import Attributes](https://github.com/vitejs/vite/issues/14674), we will need to create a _vite.config.js_ and write a [custom plugin](https://vitejs.dev/guide/api-plugin) to work around this.

In this example we are handling for CSS Module scripts:

<!-- prettier-ignore-start -->

<app-ctc-block variant="snippet" heading="vite.config.js">

```js
import { defineConfig } from "vite";
import fs from "node:fs/promises";
import path from "node:path";
// 1) import the greenwood plugin and lifecycle helpers
import { greenwoodPluginStandardCss } from "@greenwood/cli/src/plugins/resource/plugin-standard-css.js";
import { readAndMergeConfig } from "@greenwood/cli/src/lifecycles/config.js";
import { initContext } from "@greenwood/cli/src/lifecycles/context.js";

// 2) initialize Greenwood lifecycles
const config = await readAndMergeConfig();
const context = await initContext({ config });
const compilation = { context, config };

// 3) initialize the plugin
const standardCssResource = greenwoodPluginStandardCss.provider(compilation);

// 4) customize Vite
function transformConstructableStylesheetsPlugin() {
return {
name: "transform-constructable-stylesheets",
enforce: "pre",
resolveId: (id, importer) => {
if (
// you'll need to configure this `importer` line to the location of your own components
importer?.indexOf("/src/components/") >= 0 &&
id.endsWith(".css") &&
!id.endsWith(".module.css")
) {
// append .type to the end of Constructable Stylesheet file paths so that they are not automatically precessed by Vite's default pipeline
return path.join(path.dirname(importer), `${id}.type`);
}
},
load: async (id) => {
if (id.endsWith(".css.type")) {
const filename = id.slice(0, -5);
const contents = await fs.readFile(filename, "utf-8");
const url = new URL(`file://${id.replace(".type", "")}`);
// "coerce" native constructable stylesheets into inline JS so Vite / Rollup do not complain
const request = new Request(url, {
headers: {
Accept: "text/javascript",
},
});
const response = await standardCssResource.intercept(url, request, new Response(contents));
const body = await response.text();

return body;
}
},
};
}

export default defineConfig({
// 5) add it the plugins option
plugins: [transformConstructableStylesheetsPlugin()],
});
```

</app-ctc-block>

<!-- prettier-ignore-end -->

Phew, should be all set now.

## Resource Plugins

If you're using one of Greenwood's [resource plugins](/docs/plugins/), you'll need a _vite.config.js_ so we can create a custom transformation plugin that can leverage Greenwood's plugins to automatically handle custom transformations.

For example, if you're using Greenwood's [Raw Plugin](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-import-raw), you'll need to create a wrapping Vite plugin to handle this transformation.

<!-- prettier-ignore-start -->

<app-ctc-block variant="snippet" heading="vite.config.js">

```js
import { defineConfig } from "vite";
import fs from "node:fs/promises";
import path from 'node:path';
// 1) import the greenwood plugin and lifecycle helpers
import { greenwoodPluginImportRaw } from "@greenwood/plugin-import-raw";
import { readAndMergeConfig } from "@greenwood/cli/src/lifecycles/config.js";
import { initContext } from "@greenwood/cli/src/lifecycles/context.js";

// 2) initialize Greenwood lifecycles
const config = await readAndMergeConfig();
const context = await initContext({ config });
const compilation = { context, config };

// 3) initialize the plugin
const rawResource = greenwoodPluginImportRaw()[0].provider(compilation);

// 4) customize Vite
function transformRawImports() {
const hint = "?type=raw";

return {
name: "transform-raw-imports",
enforce: "pre",
resolveId: (id, importer) => {

if (
id.endsWith(hint)
) {
// append .type to the end of .css file paths so they are not automatically precessed by Vite's default CSS pipeline
return path.join(path.dirname(importer), `${id.slice(0, id.indexOf(hint))}.type${hint}`);
}
},
load: async (id) => {
if (id.endsWith(hint)) {
const filename = id.slice(0, id.indexOf(`.type${hint}`));
const contents = await fs.readFile(filename, "utf-8");
const response = await rawResource.intercept(new URL(`file://${filename}`), null, new Response(contents));
const body = await response.text();

return body;
}
},
};
}

export default defineConfig({
// 5) add it the plugins option
plugins: [transformRawImports()],
});
```

</app-ctc-block>

<!-- prettier-ignore-end -->

## Content as Data

If you are using any of Greenwood's Content as Data [Client APIs](/docs/content-as-data/data-client/), you'll want to configure Storybook to mock the HTTP calls Greenwood's data client makes, and provide the desired response needed based on the API being called.
Expand Down
Loading