Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SidebarBottom to toggle sidebar filtering based on story status #45

Merged
merged 8 commits into from
Aug 26, 2023
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
34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"typecheck": "tsc --noemit"
},
"dependencies": {
"@storybook/csf-tools": "^7.3.0",
"@storybook/csf-tools": "7.4.0-alpha.2",
"@storybook/design-system": "^7.15.15",
"chromatic": "6.23.0",
"date-fns": "^2.30.0",
Expand All @@ -69,23 +69,23 @@
"@graphql-codegen/cli": "^4.0.1",
"@graphql-codegen/client-preset": "^4.0.1",
"@graphql-typed-document-node/core": "^3.2.0",
"@storybook/addon-actions": "^7.3.0",
"@storybook/addon-essentials": "^7.3.0",
"@storybook/addon-interactions": "^7.3.0",
"@storybook/addon-mdx-gfm": "^7.3.0",
"@storybook/channels": "^7.3.0",
"@storybook/client-logger": "^7.3.0",
"@storybook/addon-actions": "7.4.0-alpha.2",
"@storybook/addon-essentials": "7.4.0-alpha.2",
"@storybook/addon-interactions": "7.4.0-alpha.2",
"@storybook/addon-mdx-gfm": "7.4.0-alpha.2",
"@storybook/channels": "7.4.0-alpha.2",
"@storybook/client-logger": "7.4.0-alpha.2",
"@storybook/eslint-config-storybook": "^3.1.2",
"@storybook/jest": "^0.2.1",
"@storybook/manager-api": "^7.3.0",
"@storybook/react": "^7.3.0",
"@storybook/react-vite": "^7.3.0",
"@storybook/manager-api": "7.4.0-alpha.2",
"@storybook/react": "7.4.0-alpha.2",
"@storybook/react-vite": "7.4.0-alpha.2",
"@storybook/testing-library": "^0.2.1-next.0",
"@storybook/theming": "^7.3.0",
"@storybook/theming": "7.4.0-alpha.2",
"@types/jest": "^29.5.3",
"@types/node": "^18.15.0",
"@types/pluralize": "^0.0.29",
"@types/react": "^18.0.34",
"@types/react": "^16.14.0",
"@typescript-eslint/eslint-plugin": "^5.59.11",
"@typescript-eslint/parser": "^5.59.11",
"@vitejs/plugin-react": "^3.1.0",
Expand All @@ -104,10 +104,10 @@
"prettier": "^2.8.8",
"prompts": "^2.4.2",
"prop-types": "^15.8.1",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react": "^16.14.0",
"react-dom": "^16.14.0",
ghengeveld marked this conversation as resolved.
Show resolved Hide resolved
"rimraf": "^3.0.2",
"storybook": "^7.3.0",
"storybook": "7.4.0-alpha.2",
"storybook-addon-designs": "^7.0.0-beta.2",
"ts-jest": "^29.1.1",
"tsup": "^6.6.3",
Expand Down Expand Up @@ -143,8 +143,8 @@
"workerDirectory": "public"
},
"resolutions": {
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"jackspeak": "2.1.1"
},
"storybook": {
Expand Down
7 changes: 4 additions & 3 deletions src/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { logger } from "@storybook/client-logger";
import { useChannel, useStorybookApi, useStorybookState } from "@storybook/manager-api";
import type { API } from "@storybook/manager-api";
import { useChannel, useStorybookState } from "@storybook/manager-api";
// eslint-disable-next-line import/no-unresolved
import { GitInfo } from "chromatic/node";
import React, { useCallback, useState } from "react";
Expand All @@ -23,6 +24,7 @@ import { useProjectId } from "./utils/useProjectId";

interface PanelProps {
active: boolean;
api: API;
}

const {
Expand All @@ -46,8 +48,7 @@ logger.debug("Initial Git info:", initialGitInfo);

const storedBuildId = localStorage.getItem(DEV_BUILD_ID_KEY);

export const Panel = ({ active }: PanelProps) => {
const api = useStorybookApi();
export const Panel = ({ active, api }: PanelProps) => {
const [accessToken, setAccessToken] = useAccessToken();
const { storyId } = useStorybookState();

Expand Down
24 changes: 24 additions & 0 deletions src/SidebarBottom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { type API, useStorybookState } from "@storybook/manager-api";
import type { API_FilterFunction } from "@storybook/types";
import React, { useCallback } from "react";

import { SidebarToggleButton } from "./components/SidebarToggleButton";
import { ADDON_ID } from "./constants";

const filterNone: API_FilterFunction = () => true;
const filterWarn: API_FilterFunction = ({ status }) => status?.[ADDON_ID]?.status === "warn";
ghengeveld marked this conversation as resolved.
Show resolved Hide resolved

interface SidebarBottomProps {
api: API;
}

export const SidebarBottom = ({ api }: SidebarBottomProps) => {
const onEnable = useCallback(() => api.experimental_setFilter(ADDON_ID, filterWarn), [api]);
const onDisable = useCallback(() => api.experimental_setFilter(ADDON_ID, filterNone), [api]);

const { status } = useStorybookState();
const warnings = Object.values(status).filter((value) => value[ADDON_ID]?.status === "warn");
if (!warnings.length) return null;

return <SidebarToggleButton count={warnings.length} onEnable={onEnable} onDisable={onDisable} />;
};
24 changes: 24 additions & 0 deletions src/components/SidebarToggleButton.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { action } from "@storybook/addon-actions";
import { type StoryObj } from "@storybook/react";
import { findByRole, userEvent } from "@storybook/testing-library";

import { playAll } from "../utils/playAll";
import { SidebarToggleButton } from "./SidebarToggleButton";

export default {
component: SidebarToggleButton,
args: {
count: 12,
onEnable: action("onEnable"),
onDisable: action("onDisable"),
},
};

export const Default = {};

export const Enabled: StoryObj = {
play: playAll(async ({ canvasElement }) => {
const button = await findByRole(canvasElement, "button");
await userEvent.click(button);
}),
};
57 changes: 57 additions & 0 deletions src/components/SidebarToggleButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Badge as BaseBadge } from "@storybook/components";
import { css, styled } from "@storybook/theming";
import pluralize from "pluralize";
import React, { useState } from "react";

import { IconButton } from "./IconButton";

const Badge = styled(BaseBadge)(({ theme }) => ({
padding: "4px 8px",
fontSize: theme.typography.size.s1,
}));

const Button = styled(IconButton)(
{
"&:hover [data-badge], [data-badge=true]": {
background: "#E3F3FF",
borderColor: "rgba(2, 113, 182, 0.1)",
color: "#0271B6",
},
},
({ active, theme }) =>
!active &&
css({
"&:hover": {
color: theme.color.defaultText,
},
})
);

interface SidebarToggleButtonProps {
count: number;
onEnable: () => void;
onDisable: () => void;
}

export const SidebarToggleButton = React.memo(function SidebarToggleButton({
count,
onEnable,
onDisable,
}: SidebarToggleButtonProps) {
const [filter, setFilter] = useState(false);

const toggleFilter = () => {
setFilter(!filter);
if (filter) onDisable();
else onEnable();
};

return (
<Button active={filter} onClick={toggleFilter}>
<Badge status="warning" data-badge={filter}>
{count}
</Badge>
<span>{pluralize("Change", count)}</span>
</Button>
);
});
14 changes: 12 additions & 2 deletions src/components/SuffixInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,24 @@ const SuffixOverlay = ({
</SuffixWrapper>
);

interface SuffixInputProps extends Omit<ComponentProps<typeof Input>, "label"> {
interface SuffixInputProps
extends Omit<ComponentProps<typeof Input>, "label" | "crossOrigin" | "enterKeyHint"> {
suffix: string;
}

export const SuffixInput = ({ id, value, placeholder, suffix, ...props }: SuffixInputProps) => {
return (
<InputWrapper>
<Input id={id} hideLabel label="" value={value} placeholder={placeholder} {...props} />
<Input
id={id}
hideLabel
label=""
value={value}
placeholder={placeholder}
crossOrigin={undefined}
weeksling marked this conversation as resolved.
Show resolved Hide resolved
enterKeyHint={undefined}
{...props}
/>
<SuffixOverlay value={value} placeholder={placeholder} suffix={suffix} />
</InputWrapper>
);
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const {
export const ADDON_ID = "chromaui/addon-visual-tests";
export const TOOL_ID = `${ADDON_ID}/tool`;
export const PANEL_ID = `${ADDON_ID}/panel`;
export const SIDEBAR_BOTTOM_ID = `${ADDON_ID}/sidebarBottom`;
export const ACCESS_TOKEN_KEY = `${ADDON_ID}/access-token/${CHROMATIC_BASE_URL}`;
export const DEV_BUILD_ID_KEY = `${ADDON_ID}/dev-build-id`;

Expand Down
2 changes: 0 additions & 2 deletions src/gql/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -761,13 +761,11 @@ export type ProjectBranchNamesArgs = {

export type ProjectLastBuildArgs = {
branches?: InputMaybe<Array<Scalars['String']['input']>>;
commit?: InputMaybe<Scalars['String']['input']>;
defaultBranch?: InputMaybe<Scalars['Boolean']['input']>;
localBuilds?: InputMaybe<LocalBuildsSpecifierInput>;
results?: InputMaybe<Array<BuildResult>>;
slug?: InputMaybe<Scalars['String']['input']>;
statuses?: InputMaybe<Array<BuildStatus>>;
uncommittedHash?: InputMaybe<Scalars['String']['input']>;
};

export type PublicAccountInfo = {
Expand Down
28 changes: 0 additions & 28 deletions src/manager.ts

This file was deleted.

27 changes: 27 additions & 0 deletions src/manager.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { addons, types } from "@storybook/manager-api";
import React from "react";

import { ADDON_ID, PANEL_ID, SIDEBAR_BOTTOM_ID, TOOL_ID } from "./constants";
import { Panel } from "./Panel";
import { SidebarBottom } from "./SidebarBottom";
import { Tool } from "./Tool";

addons.register(ADDON_ID, (api) => {
addons.add(TOOL_ID, {
type: types.TOOL,
title: "Run visual tests",
render: Tool,
});

addons.add(PANEL_ID, {
type: types.PANEL,
title: "Visual Tests",
match: ({ viewMode }) => viewMode === "story",
render: ({ active }) => <Panel active={active} api={api} />,
});

addons.add(SIDEBAR_BOTTOM_ID, {
type: types.experimental_SIDEBAR_BOTTOM,
render: () => <SidebarBottom api={api} />,
});
});
1 change: 0 additions & 1 deletion src/utils/testsToStatusUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export type StatusUpdate = Parameters<API["experimental_updateStatus"]>[1];
type StoryStatus = StatusUpdate[any]["status"];

export const statusMap: Partial<Record<TestStatus, StoryStatus>> = {
[TestStatus.InProgress]: "pending",
ghengeveld marked this conversation as resolved.
Show resolved Hide resolved
[TestStatus.Pending]: "warn",
[TestStatus.Failed]: "error",
[TestStatus.Denied]: "error",
Expand Down
2 changes: 1 addition & 1 deletion tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default defineConfig((options) => [
},
},
{
entry: ["src/manager.ts"],
entry: ["src/manager.tsx"],
splitting: false,
minify: !options.watch,
format: ["esm"],
Expand Down
Loading