Skip to content

Commit

Permalink
Adding workspaces
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuszmigas committed Mar 3, 2024
1 parent c56c526 commit fb65540
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 6 deletions.
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-menubar": "^1.0.4",
"@radix-ui/react-scroll-area": "^1.0.5",
"@radix-ui/react-slot": "^1.0.2",
"@tauri-apps/api": "^1",
"class-variance-authority": "^0.7.0",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useSyncTheme } from "./hooks/useSyncTheme";
export const App = () => {
useSyncTheme();
return (
<div className="w-full h-full flex flex-col">
<div className="w-full h-full flex flex-col select-none">
<AppHeaderBar></AppHeaderBar>
<AppContent></AppContent>
<AppStatusBar></AppStatusBar>
Expand Down
49 changes: 48 additions & 1 deletion apps/web/src/components/appHeaderBar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,57 @@
import { ModeToggle } from "./themeToggle";
import { MenuBar } from "./menu-bar/menuBar";
import { ScrollArea, ScrollBar } from "./ui/scroll-area";
import { IconButton } from "./iconButton";
import { Button } from "./ui/button";
import { cn } from "@/utils/css";
import { useWorkspacesStore } from "@/store";

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-full text-sm hover:text-primary py-[6px] rounded-none",
isSelected ? "border-primary" : "border-transparent"
)}
variant="ghost"
size="sm"
onClick={() => selectWorkspace(index)}
>
{name}
</Button>
);
};

export const AppHeaderBar = () => {
const { workspaces, selectedWorkspaceIndex, addWorkspace } =
useWorkspacesStore((state) => state);

return (
<div className="border-b flex flex-row justify-between items-center px-2">
<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">
<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>
<ScrollBar orientation="horizontal" />
</ScrollArea>
<IconButton type="plus" size="medium" onClick={addWorkspace} />
</div>
<ModeToggle />
</div>
);
Expand Down
6 changes: 4 additions & 2 deletions apps/web/src/components/icon.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* This is an icon aggregator where all icons from various libraries are imported. */
import { Pen, Pencil, Moon, Sun } from "lucide-react";
import { Pen, Pencil, Moon, Sun, Plus } from "lucide-react";

export type IconType = "pen" | "pencil" | "moon" | "sun";
export type IconType = "pen" | "pencil" | "moon" | "sun" | "plus";
export type IconSize = "small" | "medium";

const renderLucideIcon = (
Expand All @@ -19,6 +19,8 @@ const renderLucideIcon = (
return <Moon className={className} size={fontSize} />;
case "sun":
return <Sun className={className} size={fontSize} />;
case "plus":
return <Plus className={className} size={fontSize} />;
default:
return null;
}
Expand Down
46 changes: 46 additions & 0 deletions apps/web/src/components/ui/scroll-area.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as React from "react"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"

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

const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<ScrollAreaPrimitive.Root
ref={ref}
className={cn("relative overflow-hidden", className)}
{...props}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
))
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName

const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
>(({ className, orientation = "vertical", ...props }, ref) => (
<ScrollAreaPrimitive.ScrollAreaScrollbar
ref={ref}
orientation={orientation}
className={cn(
"flex touch-none select-none transition-colors",
orientation === "vertical" &&
"h-full w-2.5 border-l border-l-transparent p-[1px]",
orientation === "horizontal" &&
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
className
)}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
</ScrollAreaPrimitive.ScrollAreaScrollbar>
))
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName

export { ScrollArea, ScrollBar }
20 changes: 19 additions & 1 deletion apps/web/src/store/workspacesStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { uuid } from "@/utils/uuid";
import { create, type StateCreator } from "zustand";

type Workspace = {
id: string;
name: string;
filePath: string | null;
isSaved: boolean;
Expand All @@ -14,6 +16,7 @@ type AppWorkspacesState = {
const defaultState: AppWorkspacesState = {
workspaces: [
{
id: uuid(),
name: "Untitled",
filePath: null,
isSaved: false,
Expand All @@ -24,13 +27,28 @@ const defaultState: AppWorkspacesState = {

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

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

export const useWorkspacesStore =
Expand Down
2 changes: 2 additions & 0 deletions apps/web/src/utils/uuid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const uuid = () => crypto.randomUUID();

2 changes: 1 addition & 1 deletion apps/web/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const space = {
["very-small"]: "0.125rem",
small: "0.25rem",
medium: "0.5rem",
huge: "1rem",
big: "1rem",
};


Expand Down
38 changes: 38 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 fb65540

Please sign in to comment.