Skip to content

Commit 7c23583

Browse files
authored
refactor: decouple features from sidebar (#4304)
Here removed reliance on sidebar from all its panels so we can store them as features and not just panels. This will greatly reduce folder nesting and simplify navigation from command line.
1 parent 02551fa commit 7c23583

File tree

12 files changed

+292
-258
lines changed

12 files changed

+292
-258
lines changed

apps/builder/app/builder/features/sidebar-left/panels/assets/assets.tsx

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,31 @@
1-
import { ImageIcon } from "@webstudio-is/icons";
1+
import {
2+
Button,
3+
PanelTitle,
4+
Separator,
5+
Tooltip,
6+
} from "@webstudio-is/design-system";
7+
import { CrossIcon } from "@webstudio-is/icons";
28
import { ImageManager } from "~/builder/shared/image-manager";
3-
import type { TabContentProps } from "../../types";
4-
import { Header, CloseButton, Root } from "../../shared/panel";
59

6-
export const TabContent = ({ onSetActiveTab }: TabContentProps) => {
10+
export const AssetsPanel = ({ onClose }: { onClose: () => void }) => {
711
return (
8-
<Root>
9-
<Header
10-
title="Assets"
11-
suffix={<CloseButton onClick={() => onSetActiveTab("none")} />}
12-
/>
12+
<>
13+
<PanelTitle
14+
suffix={
15+
<Tooltip content="Close panel" side="bottom">
16+
<Button
17+
color="ghost"
18+
prefix={<CrossIcon />}
19+
aria-label="Close panel"
20+
onClick={onClose}
21+
/>
22+
</Tooltip>
23+
}
24+
>
25+
Assets
26+
</PanelTitle>
27+
<Separator />
1328
<ImageManager />
14-
</Root>
29+
</>
1530
);
1631
};
17-
18-
export const Icon = ImageIcon;
19-
20-
export const label = "Assets";

apps/builder/app/builder/features/sidebar-left/panels/components/components.tsx

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useMemo, useState } from "react";
22
import { useStore } from "@nanostores/react";
3+
import { CrossIcon } from "@webstudio-is/icons";
34
import {
45
type WsComponentMeta,
56
componentCategories,
@@ -17,13 +18,12 @@ import {
1718
findNextListItemIndex,
1819
Text,
1920
Box,
20-
Kbd,
2121
Grid,
22+
PanelTitle,
23+
Tooltip,
24+
Button,
2225
} from "@webstudio-is/design-system";
23-
import { PlusIcon } from "@webstudio-is/icons";
2426
import { CollapsibleSection } from "~/builder/shared/collapsible-section";
25-
import type { TabContentProps } from "../../types";
26-
import { Header, CloseButton, Root } from "../../shared/panel";
2727
import { dragItemAttribute, useDraggable } from "./use-draggable";
2828
import { MetaIcon } from "~/builder/shared/meta-icon";
2929
import { $registeredComponentMetas, $selectedPage } from "~/shared/nano-states";
@@ -37,6 +37,7 @@ import { isFeatureEnabled } from "@webstudio-is/feature-flags";
3737
import { insert } from "./insert";
3838
import { matchSorter } from "match-sorter";
3939
import { parseComponentName } from "@webstudio-is/sdk";
40+
import type { Publish } from "~/shared/pubsub";
4041

4142
const matchComponents = (
4243
metas: Array<WsComponentMeta>,
@@ -159,13 +160,19 @@ const findComponentIndex = (
159160
return { index: -1, metas: [] };
160161
};
161162

162-
export const TabContent = ({ publish, onSetActiveTab }: TabContentProps) => {
163+
export const ComponentsPanel = ({
164+
publish,
165+
onClose,
166+
}: {
167+
publish: Publish;
168+
onClose: () => void;
169+
}) => {
163170
const metaByComponentName = useStore($registeredComponentMetas);
164171
const selectedPage = useStore($selectedPage);
165172
const [selectedComponent, setSelectedComponent] = useState<string>();
166173

167174
const handleInsert = (component: string) => {
168-
onSetActiveTab("none");
175+
onClose();
169176
insert(component);
170177
};
171178

@@ -227,22 +234,33 @@ export const TabContent = ({ publish, onSetActiveTab }: TabContentProps) => {
227234
});
228235

229236
return (
230-
<Root ref={draggableContainerRef}>
231-
<Header
232-
title="Components"
233-
suffix={<CloseButton onClick={() => onSetActiveTab("none")} />}
234-
/>
237+
<>
238+
<PanelTitle
239+
suffix={
240+
<Tooltip content="Close panel" side="bottom">
241+
<Button
242+
color="ghost"
243+
prefix={<CrossIcon />}
244+
aria-label="Close panel"
245+
onClick={onClose}
246+
/>
247+
</Tooltip>
248+
}
249+
>
250+
Components
251+
</PanelTitle>
252+
<Separator />
253+
235254
<Box css={{ padding: theme.panel.padding }}>
236255
<SearchField
237256
{...searchFieldProps}
238257
autoFocus
239258
placeholder="Find components"
240259
/>
241260
</Box>
242-
243261
<Separator />
244262

245-
<ScrollArea>
263+
<ScrollArea ref={draggableContainerRef}>
246264
{groups.map((group) => (
247265
<CollapsibleSection
248266
label={group.category}
@@ -302,15 +320,6 @@ export const TabContent = ({ publish, onSetActiveTab }: TabContentProps) => {
302320
</CollapsibleSection>
303321
))}
304322
</ScrollArea>
305-
</Root>
323+
</>
306324
);
307325
};
308-
309-
export const Icon = PlusIcon;
310-
311-
export const label = (
312-
<Text>
313-
Components&nbsp;&nbsp;
314-
<Kbd value={["A"]} color="moreSubtle" />
315-
</Text>
316-
);

apps/builder/app/builder/features/sidebar-left/panels/index.ts

Lines changed: 0 additions & 23 deletions
This file was deleted.

apps/builder/app/builder/features/sidebar-left/panels/marketplace/about.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
Button,
33
Flex,
44
Link,
5+
PanelTitle,
56
Separator,
67
Text,
78
Tooltip,
@@ -10,7 +11,6 @@ import {
1011
truncate,
1112
} from "@webstudio-is/design-system";
1213
import type { MarketplaceOverviewItem } from "~/shared/marketplace/types";
13-
import { Header } from "../../shared/panel";
1414
import { ChevronDoubleLeftIcon, ExternalLinkIcon } from "@webstudio-is/icons";
1515
import { builderUrl } from "~/shared/router-utils";
1616

@@ -29,8 +29,7 @@ export const About = ({
2929

3030
return (
3131
<>
32-
<Header
33-
title={item.name}
32+
<PanelTitle
3433
suffix={
3534
<Tooltip content="Close" side="bottom">
3635
<Button
@@ -44,7 +43,11 @@ export const About = ({
4443
/>
4544
</Tooltip>
4645
}
47-
/>
46+
>
47+
{item.name}
48+
</PanelTitle>
49+
<Separator />
50+
4851
<Flex
4952
direction="column"
5053
css={{ my: theme.spacing[5], mx: theme.spacing[8] }}

apps/builder/app/builder/features/sidebar-left/panels/marketplace/marketplace.tsx

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
import { ExtensionIcon, SpinnerIcon } from "@webstudio-is/icons";
2-
import { Flex, rawTheme } from "@webstudio-is/design-system";
3-
import type { TabContentProps } from "../../types";
4-
import { Header, CloseButton, Root } from "../../shared/panel";
1+
import { CrossIcon, SpinnerIcon } from "@webstudio-is/icons";
2+
import {
3+
Button,
4+
Flex,
5+
PanelTitle,
6+
rawTheme,
7+
Separator,
8+
Tooltip,
9+
} from "@webstudio-is/design-system";
510
import { Overview } from "./overview";
611
import { Templates } from "./templates";
712
import { useEffect, useState } from "react";
@@ -12,7 +17,7 @@ import { ExtendedPanel } from "../../shared/extended-panel";
1217
import { About } from "./about";
1318
import { trpcClient } from "~/shared/trpc/trpc-client";
1419

15-
export const TabContent = ({ onSetActiveTab }: TabContentProps) => {
20+
export const MarketplacePanel = ({ onClose }: { onClose: () => void }) => {
1621
const [activeOverviewItem, setAciveOverviewItem] =
1722
useState<MarketplaceOverviewItem>();
1823
const [openAbout, setOpenAbout] = useState<Project["id"]>();
@@ -36,43 +41,52 @@ export const TabContent = ({ onSetActiveTab }: TabContentProps) => {
3641

3742
return (
3843
<>
39-
<Root>
40-
<Header
41-
title="Marketplace"
42-
suffix={<CloseButton onClick={() => onSetActiveTab("none")} />}
43-
/>
44-
<Overview
45-
items={items}
46-
activeProjectId={activeOverviewItem?.projectId}
47-
onSelect={(activeOverviewItem) => {
48-
setAciveOverviewItem(activeOverviewItem);
49-
getBuildData({ projectId: activeOverviewItem.projectId });
44+
<PanelTitle
45+
suffix={
46+
<Tooltip content="Close panel" side="bottom">
47+
<Button
48+
color="ghost"
49+
prefix={<CrossIcon />}
50+
aria-label="Close panel"
51+
onClick={onClose}
52+
/>
53+
</Tooltip>
54+
}
55+
>
56+
Marketplace
57+
</PanelTitle>
58+
<Separator />
59+
<Overview
60+
items={items}
61+
activeProjectId={activeOverviewItem?.projectId}
62+
onSelect={(activeOverviewItem) => {
63+
setAciveOverviewItem(activeOverviewItem);
64+
getBuildData({ projectId: activeOverviewItem.projectId });
65+
}}
66+
openAbout={openAbout}
67+
onOpenAbout={setOpenAbout}
68+
hidden={showTemplates}
69+
/>
70+
71+
{showTemplates && (
72+
<Templates
73+
projectId={activeOverviewItem.projectId}
74+
name={activeOverviewItem.name}
75+
authorizationToken={activeOverviewItem.authorizationToken}
76+
productCategory={activeOverviewItem.category}
77+
data={toWebstudioData(buildData)}
78+
onOpenChange={(isOpen: boolean) => {
79+
if (isOpen === false) {
80+
setAciveOverviewItem(undefined);
81+
}
5082
}}
51-
openAbout={openAbout}
52-
onOpenAbout={setOpenAbout}
53-
hidden={showTemplates}
5483
/>
55-
56-
{showTemplates && (
57-
<Templates
58-
projectId={activeOverviewItem.projectId}
59-
name={activeOverviewItem.name}
60-
authorizationToken={activeOverviewItem.authorizationToken}
61-
productCategory={activeOverviewItem.category}
62-
data={toWebstudioData(buildData)}
63-
onOpenChange={(isOpen: boolean) => {
64-
if (isOpen === false) {
65-
setAciveOverviewItem(undefined);
66-
}
67-
}}
68-
/>
69-
)}
70-
{itemsLoadingState !== "idle" && (
71-
<Flex justify="center" css={{ mt: "20%" }}>
72-
<SpinnerIcon size={rawTheme.spacing[15]} />
73-
</Flex>
74-
)}
75-
</Root>
84+
)}
85+
{itemsLoadingState !== "idle" && (
86+
<Flex justify="center" css={{ mt: "20%" }}>
87+
<SpinnerIcon size={rawTheme.spacing[15]} />
88+
</Flex>
89+
)}
7690
<ExtendedPanel isOpen={openAboutItem !== undefined}>
7791
<About
7892
item={openAboutItem}
@@ -84,7 +98,3 @@ export const TabContent = ({ onSetActiveTab }: TabContentProps) => {
8498
</>
8599
);
86100
};
87-
88-
export const Icon = ExtensionIcon;
89-
90-
export const label = "Marketplace";

0 commit comments

Comments
 (0)