Skip to content

Commit

Permalink
Tags filter: Use built in menu components
Browse files Browse the repository at this point in the history
  • Loading branch information
shilman committed Oct 12, 2024
1 parent 5529530 commit e8a505c
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 88 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ code/bench-results/

/packs
code/.nx/cache
code/.vite-inspect
.nx/cache
!**/fixtures/**/yarn.lock
code/core/report

*storybook.log
21 changes: 17 additions & 4 deletions code/core/src/manager/components/sidebar/TagsFilter.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ import { TagsFilter } from './TagsFilter';
const meta = {
component: TagsFilter,
tags: ['haha'],
args: {
api: {
experimental_setFilter: fn(),
getDocsUrl: () => 'https://storybook.js.org/docs/',
} as any,
updateQueryParams: fn(),
},
} satisfies Meta<typeof TagsFilter>;

export default meta;
Expand All @@ -14,16 +21,12 @@ type Story = StoryObj<typeof meta>;

export const Closed: Story = {
args: {
api: {
experimental_setFilter: fn(),
} as any,
indexJson: {
v: 6,
entries: {
'c1-s1': { tags: ['A', 'B', 'C', 'dev'] } as any,
},
},
updateQueryParams: fn(),
},
};

Expand All @@ -46,3 +49,13 @@ export const OpenWithSelection: Story = {
...ClosedWithSelection,
play: Open.play,
};

export const OpenEmpty: Story = {
args: {
indexJson: {
v: 6,
entries: {},
},
},
play: Open.play,
};
2 changes: 2 additions & 0 deletions code/core/src/manager/components/sidebar/TagsFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,13 @@ export const TagsFilter = ({
onVisibleChange={setExpanded}
tooltip={() => (
<TagsFilterPanel
api={api}
allTags={Array.from(allTags)}
selectedTags={selectedTags}
toggleTag={toggleTag}
/>
)}
closeOnOutsideClick
>
<Wrapper>
<IconButton key="tags" title="Tag filters" active={tagsActive} onClick={handleToggleExpand}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const meta = {
component: TagsFilterPanel,
args: {
toggleTag: fn(),
api: {
getDocsUrl: () => 'https://storybook.js.org/docs/',
} as any,
},
tags: ['hoho'],
} satisfies Meta<typeof TagsFilterPanel>;
Expand Down
131 changes: 47 additions & 84 deletions code/core/src/manager/components/sidebar/TagsFilterPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { ChangeEvent } from 'react';
import React from 'react';

import { styled } from '@storybook/core/theming';
import { TooltipLinkList } from '@storybook/core/components';
import { styled, useTheme } from '@storybook/core/theming';
import { ShareAltIcon } from '@storybook/icons';
import type { Tag } from '@storybook/types';

import { transparentize } from 'polished';
import type { API } from '@storybook/core/manager-api';

const BUILT_IN_TAGS = new Set([
'dev',
Expand All @@ -15,97 +16,59 @@ const BUILT_IN_TAGS = new Set([
'play-fn',
]);

const CollapseButton = styled.button(({ theme }) => ({
all: 'unset',
display: 'flex',
padding: '0px 8px',
borderRadius: 4,
transition: 'color 150ms, box-shadow 150ms',
gap: 6,
alignItems: 'center',
cursor: 'pointer',
height: 28,

'&:hover, &:focus': {
outline: 'none',
background: transparentize(0.93, theme.color.secondary),
},
}));

const Text = styled.span({
'[aria-readonly=true] &': {
opacity: 0.5,
},
});

const Label = styled.label({
lineHeight: '20px',
alignItems: 'center',
marginBottom: 8,

'&:last-child': {
marginBottom: 0,
},

input: {
margin: 0,
marginRight: 6,
},
const Wrapper = styled.div({
minWidth: 180,
maxWidth: 220,
});

interface TagsFilterPanelProps {
api: API;
allTags: Tag[];
selectedTags: Tag[];
toggleTag: (tag: Tag) => void;
}

interface TagsListProps {
tags: Tag[];
selectedTags: Tag[];
toggleTag: (tag: Tag) => void;
}

const TagsList = ({ tags, selectedTags, toggleTag }: TagsListProps) => {
return tags.map((tag) => {
const checked = selectedTags.includes(tag);
const id = `tag-${tag}`;
return (
<Label key={id} htmlFor={id}>
<input
type="checkbox"
id={id}
name={id}
value={tag}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
toggleTag(e.target.value);
}}
checked={checked}
/>
<Text>{tag}</Text>
</Label>
);
});
};

const Wrapper = styled.div({
padding: 10,
label: {
display: 'flex',
},
});

export const TagsFilterPanel = ({ allTags, selectedTags, toggleTag }: TagsFilterPanelProps) => {
export const TagsFilterPanel = ({
api,
allTags,
selectedTags,
toggleTag,
}: TagsFilterPanelProps) => {
const theme = useTheme();
const userTags = allTags.filter((tag) => tag === 'play-fn' || !BUILT_IN_TAGS.has(tag)).toSorted();
const docsUrl = api.getDocsUrl({ subpath: 'writing-stories/tags' });
const items =
userTags.length === 0
? [
{
id: 'no-tags',
title: 'There are no tags. Use tags to organize and filter your Storybook.',
isIndented: false,
style: {
borderBottom: `4px solid ${theme.appBorderColor}`,
},
},
{
id: 'tags-docs',
title: 'Learn how to add tags',
icon: <ShareAltIcon />,
href: docsUrl,
},
]
: userTags.map((tag) => {
const checked = selectedTags.includes(tag);
const id = `tag-${tag}`;
return {
id,
title: tag,
right: <input type="checkbox" id={id} name={id} value={tag} checked={checked} />,
onClick: () => toggleTag(tag),
};
});

return (
<div>
{userTags.length === 0 ? (
<>There are no tags. Use tags to organize and filter your Storybook.</>
) : (
<Wrapper>
<TagsList tags={userTags} selectedTags={selectedTags} toggleTag={toggleTag} />
</Wrapper>
)}
</div>
<Wrapper>
<TooltipLinkList links={items} />
</Wrapper>
);
};

0 comments on commit e8a505c

Please sign in to comment.