Skip to content
Closed
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
48 changes: 48 additions & 0 deletions .github/workflows/chromatic.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Chromatic

on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, ready_for_review]

jobs:
chromatic:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false || github.event_name == 'push'
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0

- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v46
with:
since_last_remote_commit: true
files: |
packages/nimbus/**
packages/tokens/**
packages/nimbus-icons/**
files_ignore: |
packages/nimbus/chromatic.config.json
packages/nimbus/.storybook/main.ts
packages/nimbus/package.json

- name: Installing dependencies and building packages
if: steps.changed-files.outputs.any_changed == 'true'
uses: ./.github/actions/ci

- name: Run Chromatic
if: steps.changed-files.outputs.any_changed == 'true'
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
onlyChanged: true
storybookBaseDir: packages/nimbus
buildScriptName: build-storybook
zip: true
2 changes: 1 addition & 1 deletion apps/docs/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# React + TypeScript + Vite
# YOU BETTER NOT TRIGGER ANYTHING!

This template provides a minimal setup to get React working in Vite with HMR and
some ESLint rules.
Expand Down
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
{
"name": "nimbus",
"private": true,
"workspaces": ["packages/*", "apps/*"],
"workspaces": [
"packages/*",
"apps/*"
],
"preconstruct": {
"packages": ["packages/tokens"]
"packages": [
"packages/tokens"
]
},
"scripts": {
"build": "pnpm build:tokens && pnpm run build:packages && pnpm run build:docs && pnpm run build:mcp",
Expand All @@ -12,6 +17,7 @@
"build:docs-data": "pnpm --filter docs build:docs",
"build:docs": "pnpm --filter './apps/docs' build",
"build:tokens": "pnpm --filter @commercetools/nimbus-tokens run build && preconstruct build",
"build-storybook": "pnpm --filter @commercetools/nimbus build && pnpm --filter @commercetools/nimbus run build-storybook",
"changeset": "changeset",
"openspec": "openspec",
"changeset:version-and-format": "changeset version && prettier --write --parser json '**/package.json' && pnpm install --lockfile-only",
Expand Down Expand Up @@ -51,7 +57,6 @@
"mdast-util-to-hast": "^13.2.1",
"js-yaml": "^3.14.2",
"qs": "^6.14.2",

"minimatch@>=3.0.0 <3.1.4": "3.1.4",
"svgo": ">=3.3.3",
"hono": ">=4.12.4",
Expand All @@ -76,6 +81,7 @@
"@eslint/js": "catalog:tooling",
"@fission-ai/openspec": "catalog:tooling",
"@preconstruct/cli": "catalog:tooling",
"chromatic": "catalog:tooling",
"eslint": "catalog:tooling",
"eslint-config-prettier": "catalog:tooling",
"eslint-plugin-prettier": "catalog:tooling",
Expand Down
4 changes: 4 additions & 0 deletions packages/nimbus/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ const config: StorybookConfig = {
getAbsolutePackagePath("@vueless/storybook-dark-mode"),
getAbsolutePackagePath("@storybook/addon-vitest"),
getAbsolutePackagePath("@storybook/addon-docs"),
{
name: getAbsolutePackagePath("@chromatic-com/storybook"),
options: { projectId: "698e33aebdbff7804c1287d4" },
},
],
framework: {
name: getAbsolutePackagePath("@storybook/react-vite"),
Expand Down
7 changes: 7 additions & 0 deletions packages/nimbus/chromatic.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"onlyChanged": true,
"projectId": "Project:698e33aebdbff7804c1287d4",
"storybookBaseDir": "packages/nimbus",
"buildScriptName": "build-storybook",
"zip": true
}
18 changes: 14 additions & 4 deletions packages/nimbus/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
}
}
},
"files": ["dist", "package.json"],
"files": [
"dist",
"package.json"
],
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
Expand All @@ -35,10 +38,14 @@
"type": "git",
"url": "https://github.com/commercetools/nimbus.git"
},
"sideEffects": ["*.css"],
"sideEffects": [
"*.css"
],
"typesVersions": {
"*": {
"*": ["./dist/index.d.ts"]
"*": [
"./dist/index.d.ts"
]
}
},
"dependencies": {
Expand All @@ -60,6 +67,8 @@
},
"devDependencies": {
"@chakra-ui/react": "catalog:react",
"@chromatic-com/storybook": "catalog:tooling",
"chromatic": "catalog:tooling",
"@commercetools/nimbus-design-token-ts-plugin": "workspace:^",
"@commercetools/nimbus-icons": "workspace:^",
"@commercetools/nimbus-tokens": "workspace:^",
Expand Down Expand Up @@ -121,7 +130,8 @@
"build-theme-typings": "pnpm chakra typegen ./src/theme/index.ts",
"postinstall": "chakra typegen ./dist/index.es.js || true",
"bundles:analyze": "ANALYZE_BUNDLE=true vite build",
"chromatic": "chromatic --exit-zero-on-changes",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
"build-storybook": "storybook build --stats-json"
}
}
1 change: 1 addition & 0 deletions packages/nimbus/src/components/button/button.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// THIS IS A TEST TO SEE IF IT TRIGGERS CHROMATIC BUILD. I SO FANCY!
import { useRef } from "react";
import { useButton, useObjectRef } from "react-aria";
import { ButtonContext, useContextProps } from "react-aria-components";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ const verifyOptionsSelected = async (
const meta: Meta<typeof ComboBox.Root> = {
title: "Components/ComboBox",
component: ComboBox.Root,
parameters: {
chromatic: { disableSnapshot: true },
},
};

export default meta;
Expand Down
32 changes: 32 additions & 0 deletions packages/nimbus/src/components/drawer/drawer.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,27 @@ export const Default: Story = {
*/
export const ButtonAsTrigger: Story = {
args: {},
parameters: {
// Scoped to this story for POC purposes — validates that Chromatic captures
// fixed-position overlay components correctly.
//
// "fullscreen" is required so the drawer's position:fixed overlay fills the
// full iframe viewport. Without it, Chromatic clips the snapshot and the
// open drawer is invisible in the diff.
//
// TODO: If all drawer stories need animation capture, consider moving
// layout + chromatic params to meta level and auditing the impact on other stories.
layout: "fullscreen",
chromatic: {
// The drawer uses CSS animations (slide-from-right-full). We need to wait
// for the animation to finish before Chromatic takes the snapshot.
// pauseAnimationAtEnd:true was tried but freezes the animation at frame 0
// (offscreen), so we use a delay instead.
delay: 500,
// Explicit viewport ensures consistent snapshot width across runs.
viewports: [1200],
},
},
render: (args) => (
<Drawer.Root {...args}>
<Drawer.Trigger asChild>
Expand Down Expand Up @@ -277,6 +298,17 @@ export const ButtonAsTrigger: Story = {
}
);
});

// Leave drawer open for Chromatic to snapshot
await step("Open drawer for Chromatic snapshot", async () => {
const customButton = canvas.getByRole("button", {
name: "Open with Custom Button",
});
await userEvent.click(customButton);
await waitFor(() => {
expect(canvas.getByRole("dialog")).toBeInTheDocument();
});
});
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const meta = {
title: "Components/RichTextInput",
component: RichTextInput,
parameters: {
chromatic: { disableSnapshot: true },
layout: "padded",
docs: {
description: {
Expand Down Expand Up @@ -839,25 +840,15 @@ export const OnChangeCallback: Story = {
const canvas = within(canvasElement);
const editor = canvas.getByRole("textbox");

// Focus the editor and wait for it to be ready before typing.
// Tiptap emits an editor transaction on focus which triggers onChange,
// so we wait for the count to increment before typing.
// Test onChange is called
await userEvent.click(editor);
await waitFor(() => {
expect(canvas.getByText(/Change count: [1-9]/)).toBeInTheDocument();
});

await userEvent.type(editor, "Test");

await waitFor(() => {
// onChange fires at least once per keystroke; assert minimum rather
// than an exact count so the test isn't sensitive to extra editor
// lifecycle events.
// onChange may fire multiple times during typing
const changeCountElement = canvas.getByText(/Change count: \d+/);
const count = Number(changeCountElement.textContent?.match(/\d+/)?.[0]);
expect(count).toBeGreaterThanOrEqual(5);
// Guard against runaway onChange loops (a known ProseMirror failure mode)
expect(count).toBeLessThan(50);
expect(changeCountElement).toBeInTheDocument();
expect(changeCountElement).toHaveTextContent("Change count: 5");
});

// Test HTML output
Expand Down
3 changes: 3 additions & 0 deletions packages/nimbus/src/components/tabs/tabs.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import { SentimentSatisfied } from "@commercetools/nimbus-icons";
const meta: Meta<typeof Tabs.Root> = {
title: "Components/Tabs",
component: Tabs.Root,
parameters: {
chromatic: { disableSnapshot: true },
},
argTypes: {
variant: {
control: "select",
Expand Down
Loading
Loading