Skip to content

Commit

Permalink
Better header
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuszmigas committed Mar 7, 2024
1 parent 8f311ae commit deee9d7
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 57 deletions.
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-tabs": "^1.0.4",
"@tauri-apps/api": "^1",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
Expand Down
61 changes: 22 additions & 39 deletions apps/web/src/components/main/appHeaderBar.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,40 @@
import { ModeToggle } from "../themeToggle";
import { MenuBar } from "../menu-bar/menuBar";
import { ScrollArea, ScrollBar } from "../ui/scroll-area";
import { Button } from "../ui/button";
import { cn } from "@/utils/css";
import { useWorkspacesStore } from "@/store";
import { memo } from "react";

const WorkspaceTab = (props: {
index: number;
name: string;
isSelected: boolean;
}) => {
const { index, name, isSelected } = props;
const selectWorkspace = useWorkspacesStore((state) => state.selectWorkspace);

return (
<Button
className={cn(
"border-b-4 h-8 text-sm hover:text-primary pt-1 rounded-none",
isSelected ? "border-primary" : "border-transparent"
)}
variant="ghost"
size="sm"
onClick={() => selectWorkspace(index)}
>
{name}
</Button>
);
};
import { Tabs, TabsList, TabsTrigger } from "../ui/tabs";
import { IconButton } from "../iconButton";

export const AppHeaderBar = memo(() => {
const { workspaces, selectedWorkspaceIndex } = useWorkspacesStore(
(state) => state
);
const {
workspaces,
selectedWorkspaceId,
selectWorkspace,
addNewActiveWorkspace,
} = useWorkspacesStore((state) => state);

return (
<div className="border-b flex flex-row justify-between items-center px-small gap-big">
<MenuBar />
<div className="flex-1 flex flex-row justify-center overflow-auto items-center">
<ScrollArea className="whitespace-nowrap">
<div className="h-full flex-row flex items-center">
{workspaces.map((tab, index) => (
<WorkspaceTab
key={tab.id}
index={index}
name={tab.name}
isSelected={index === selectedWorkspaceIndex}
/>
))}
</div>
<Tabs value={selectedWorkspaceId} onValueChange={selectWorkspace}>
<TabsList className="bg-transparent p-0">
{workspaces.map((tab) => (
<TabsTrigger
key={tab.id}
value={tab.id}
className="rounded-none border-b-4 border-b-transparent px-big pb-1 pt-2 font-semibold text-muted-foreground shadow-none transition-none data-[state=active]:border-b-primary data-[state=active]:text-foreground data-[state=active]:shadow-none"
>
{tab.name}
</TabsTrigger>
))}
</TabsList>
</Tabs>
<ScrollBar orientation="horizontal" />
</ScrollArea>
{/* <IconButton type="plus" size="medium" onClick={addWorkspace} /> */}
<IconButton type="plus" size="medium" onClick={addNewActiveWorkspace} />
</div>
<ModeToggle />
</div>
Expand Down
53 changes: 53 additions & 0 deletions apps/web/src/components/ui/tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as React from "react"
import * as TabsPrimitive from "@radix-ui/react-tabs"

import { cn } from "@/utils/css"

const Tabs = TabsPrimitive.Root

const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
"inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
className
)}
{...props}
/>
))
TabsList.displayName = TabsPrimitive.List.displayName

const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger
ref={ref}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
className
)}
{...props}
/>
))
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName

const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Content
ref={ref}
className={cn(
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
className
)}
{...props}
/>
))
TabsContent.displayName = TabsPrimitive.Content.displayName

export { Tabs, TabsList, TabsTrigger, TabsContent }
38 changes: 20 additions & 18 deletions apps/web/src/store/workspacesStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,47 @@ type Workspace = {

type AppWorkspacesState = {
workspaces: Workspace[];
selectedWorkspaceIndex: number | null;
selectedWorkspaceId: string;
};

const defaultWorkspace = {
id: uuid(),
name: "Untitled",
filePath: null,
isSaved: false,
};
const defaultState: AppWorkspacesState = {
workspaces: [
{
id: uuid(),
name: "Untitled",
filePath: null,
isSaved: false,
},
],
selectedWorkspaceIndex: 0,
workspaces: [defaultWorkspace],
selectedWorkspaceId: defaultWorkspace.id,
};

type AppWorkspacesSlice = AppWorkspacesState & {
selectWorkspace: (index: number) => void;
addWorkspace: () => void;
selectWorkspace: (id: string) => void;
addNewActiveWorkspace: () => void;
};

export const settingsStoreCreator: StateCreator<AppWorkspacesSlice> = (
set,
get
) => ({
...defaultState,
selectWorkspace: (index) => set({ selectedWorkspaceIndex: index }),
addWorkspace: () =>
set((state) => ({
selectWorkspace: (id) => set({ selectedWorkspaceId: id }),
addNewActiveWorkspace: () => {
const newId = uuid();
return set((state) => ({
...state,
workspaces: [
...state.workspaces,
{
id: uuid(),
id: newId,
name: `Workspace ${get().workspaces.length + 1}`,
filePath: null,
isSaved: false,
},
],
selectedWorkspaceIndex: state.workspaces.length,
})),
selectedWorkspaceId: newId,
}));
},
});

export const useWorkspacesStore =
Expand Down
31 changes: 31 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit deee9d7

Please sign in to comment.