From c76ab965d5fc50759d441124a04e824ba25e1bf4 Mon Sep 17 00:00:00 2001 From: chroxify Date: Sat, 9 Mar 2024 19:24:35 +0100 Subject: [PATCH 01/66] refractor(dash): add new header & sidebar and update ui components --- apps/web/app/dash/[slug]/layout.tsx | 99 +++++++++---------- apps/web/components/layout/header.tsx | 35 +++++++ apps/web/components/layout/inbox-popover.tsx | 8 +- apps/web/components/layout/nav-bar-mobile.tsx | 17 ++-- apps/web/components/layout/nav-tabs.tsx | 80 ++++++++------- .../components/layout/project-dropdown.tsx | 10 +- apps/web/components/layout/sidebar.tsx | 26 +++-- apps/web/components/layout/theme-button.tsx | 2 +- apps/web/components/layout/title-provider.tsx | 12 +-- .../components/shared/icons/icons-static.tsx | 13 +++ apps/web/components/shared/user-dropdown.tsx | 2 +- apps/web/lib/types.ts | 10 +- packages/ui/components/ui/button.tsx | 10 +- packages/ui/components/ui/dropdown-menu.tsx | 2 +- packages/ui/components/ui/input.tsx | 2 +- packages/ui/components/ui/label.tsx | 2 +- packages/ui/components/ui/tabs.tsx | 4 +- 17 files changed, 190 insertions(+), 144 deletions(-) create mode 100644 apps/web/components/layout/header.tsx diff --git a/apps/web/app/dash/[slug]/layout.tsx b/apps/web/app/dash/[slug]/layout.tsx index aa90d86..2ff5af2 100644 --- a/apps/web/app/dash/[slug]/layout.tsx +++ b/apps/web/app/dash/[slug]/layout.tsx @@ -2,7 +2,8 @@ import { headers } from 'next/headers'; import { redirect } from 'next/navigation'; import { getCurrentUser, getUserProjects } from '@/lib/api/user'; import { DASH_DOMAIN } from '@/lib/constants'; -import InboxPopover from '@/components/layout/inbox-popover'; +import { SidebarTabsProps } from '@/lib/types'; +import DashboardHeader from '@/components/layout/header'; import NavbarMobile from '@/components/layout/nav-bar-mobile'; import Sidebar from '@/components/layout/sidebar'; import TitleProvider from '@/components/layout/title-provider'; @@ -13,36 +14,40 @@ import { SettingsIcon, TagLabelIcon, } from '@/components/shared/icons/icons-animated'; -import { Icons } from '@/components/shared/icons/icons-static'; -import UserDropdown from '@/components/shared/user-dropdown'; -const tabs = [ - { - name: 'Changelog', - icon: TagLabelIcon, - slug: 'changelog', - }, - { - name: 'Feedback', - icon: FeedbackIcon, - slug: 'feedback', - }, - { - name: 'Roadmap (Soon)', - icon: CalendarIcon, - slug: 'roadmap', - }, - { - name: 'Analytics', - icon: AnalyticsIcon, - slug: 'analytics', - }, - { - name: 'Settings', - icon: SettingsIcon, - slug: 'settings', - }, -]; +const tabs: SidebarTabsProps = { + Modules: [ + { + name: 'Changelog', + icon: TagLabelIcon, + slug: 'changelog', + }, + { + name: 'Feedback', + icon: FeedbackIcon, + slug: 'feedback', + }, + { + name: 'Roadmap (Soon)', + icon: CalendarIcon, + slug: 'roadmap', + }, + ], + Insights: [ + { + name: 'Analytics', + icon: AnalyticsIcon, + slug: 'analytics', + }, + ], + Project: [ + { + name: 'Settings', + icon: SettingsIcon, + slug: 'settings', + }, + ], +}; export default async function DashboardLayout({ children }: { children: React.ReactNode }) { // Headers @@ -74,41 +79,27 @@ export default async function DashboardLayout({ children }: { children: React.Re } // Retrieve the currently active tab - const activeTabIndex = tabs.findIndex((tab) => pathname?.includes(tab.slug)); + const activeTab = Object.values(tabs) + .flatMap((tabArray) => tabArray) + .find((tab) => pathname?.includes(tab.slug)); return (
-
+
{/* Header with logo and hub button */} {/* BUG: Find a way to solve issue of scroll bar getting removed on avatar dialog open */} {/* https://github.com/radix-ui/primitives/discussions/1100 */} -
- {/* Logo */} - - -
- - -
-
-
+ + +
{/* Sidebar */} - + {/* Main content */}
{children} @@ -116,7 +107,7 @@ export default async function DashboardLayout({ children }: { children: React.Re
{/* Navbar (mobile) */} - +
); diff --git a/apps/web/components/layout/header.tsx b/apps/web/components/layout/header.tsx new file mode 100644 index 0000000..2a8ba11 --- /dev/null +++ b/apps/web/components/layout/header.tsx @@ -0,0 +1,35 @@ +import { ProfileProps, ProjectProps } from '@/lib/types'; +import InboxPopover from '@/components/layout/inbox-popover'; +import { Icons } from '@/components/shared/icons/icons-static'; +import UserDropdown from '@/components/shared/user-dropdown'; +import ProjectDropdown from './project-dropdown'; + +export default function DashboardHeader({ + user, + projects, + currentProject, +}: { + user: ProfileProps['Row']; + projects: ProjectProps['Row'][]; + currentProject: ProjectProps['Row']; +}) { + return ( +
+
+ {/* Logo */} + + + {/* Seperator */} +
+ + {/* Project */} + +
+ +
+ + +
+
+ ); +} diff --git a/apps/web/components/layout/inbox-popover.tsx b/apps/web/components/layout/inbox-popover.tsx index e3ee6c0..c8f69a8 100644 --- a/apps/web/components/layout/inbox-popover.tsx +++ b/apps/web/components/layout/inbox-popover.tsx @@ -175,9 +175,9 @@ export default function InboxPopover({ user }: { user: ProfileProps['Row'] }) { - + {/* Title */} + {tab.name} + + + ))} +
))} ); diff --git a/apps/web/components/layout/project-dropdown.tsx b/apps/web/components/layout/project-dropdown.tsx index f47e770..b31e344 100644 --- a/apps/web/components/layout/project-dropdown.tsx +++ b/apps/web/components/layout/project-dropdown.tsx @@ -30,7 +30,7 @@ export default function ProjectDropdown({ return ( - - + {projects.map((project) => ( +
- {/* Projects */} - - {/* Main Tabs */} - +
{/* Footer Buttons */} {/*
@@ -35,7 +30,7 @@ export default async function Sidebar({ className='h-5 w-5' /> - +
Feedback @@ -51,8 +46,9 @@ export default async function Sidebar({ Sign out -
*/} - {/* */} + + */} + ); } diff --git a/apps/web/components/layout/theme-button.tsx b/apps/web/components/layout/theme-button.tsx index 51895ce..4abfd94 100644 --- a/apps/web/components/layout/theme-button.tsx +++ b/apps/web/components/layout/theme-button.tsx @@ -13,7 +13,7 @@ export default function ToggleThemeButton() { return ( diff --git a/apps/web/app/dash/[slug]/feedback/page.tsx b/apps/web/app/dash/[slug]/feedback/page.tsx index 700c37d..046ca69 100644 --- a/apps/web/app/dash/[slug]/feedback/page.tsx +++ b/apps/web/app/dash/[slug]/feedback/page.tsx @@ -31,7 +31,7 @@ export default async function Feedback({ No feedback yet - + Once somone submits feedback, it will show up here. Make sure to share it so others can vote on it! diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css index cfce9bc..c98a712 100644 --- a/apps/web/app/globals.css +++ b/apps/web/app/globals.css @@ -2,73 +2,94 @@ @tailwind components; @tailwind utilities; +body { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* + https://github.com/tailwindlabs/tailwindcss/discussions/2394 + https://github.com/tailwindlabs/tailwindcss/pull/5732 +*/ +@layer utilities { + /* Chrome, Safari and Opera */ + .no-scrollbar::-webkit-scrollbar { + display: none; + } + + .no-scrollbar { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + } +} + @layer base { :root { /* App root background */ - --root-background: 230 35% 3%; /* #000000 */ + --root-background: 0 0% 100%; + --background: 210 20% 98%; + --foreground: 224 71% 4%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 224 71% 4%; + --primary-foreground: 0 0% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 215 14% 34%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 218 11% 65%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 224 71% 4%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 100%; + --border: 220 13% 91%; + --input: 220 13% 91%; + --highlight: 231 100% 78%; + --ring: 216 12% 84%; + + --radius: 0.5rem; + } + + .dark { + /* App root background */ + --root-background: 235 7% 5%; /* #000000 240 7% 11% */ /* Utility background (Buttons, inputs, etc) */ - --background: 230 11% 12%; /* #0A0C10 | #060606*/ - --foreground: 210 40% 98%; /* #D6D6D6 */ + --background: 230 7% 16%; /* #0A0C10 | #060606*/ + --foreground: 220 9% 94%; /* #D6D6D6 */ /* Muted background (Skeletons, Avatar, tabs, etc) */ --muted: 230 11% 8%; /* #20242c */ - --muted-foreground: 215 6% 62%; + --muted-foreground: 219 6% 55%; --popover: 230 35% 3%; /* #0A0C10 */ - --popover-foreground: 210 40% 98%; + --popover-foreground: 220 9% 94%; - --card: 230 35% 3%; /* #0A0C10 */ - --card-foreground: 210 40% 98%; + --card: 235 7% 5%; /* #0A0C10 */ + --card-foreground: 220 9% 94%; - --border: 222 9% 22%; /* #20242c */ - --input: 222 9% 22%; /* #20242c */ + --border: 223 7% 19%; /* #20242c */ + --input: 223 7% 19%; /* #20242c */ - --primary: 210 40% 98%; + --primary: 220 9% 94%; --primary-foreground: 230 35% 3%; /* Hover & active backgrounds (Nav buttons, etc) */ - --secondary: 227 11% 12%; /* #20242c */ - --secondary-foreground: 210 40% 98%; + --secondary: 230 7% 16%; /* #20242c */ + --secondary-foreground: 218 7% 80%; /* Button background hovers */ - --accent: 227 11% 15%; /* #20242c */ - --accent-foreground: 210 40% 98%; + --accent: 230 7% 16%; /* #20242c */ + --accent-foreground: 220 9% 94%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 40% 98%; + --destructive: 351 95% 65%; + --destructive-foreground: 220 9% 94%; /* Selection & accent color */ --highlight: 231 100% 78%; --ring: 230 9% 13%; /* #20242c */ - - --radius: 0.5rem; - } - - .light { - /* App root background */ - --root-background: 0 0% 100%; /* #000000 */ - --background: 0 0% 100%; - --foreground: 240 10% 3.9%; - --card: 0 0% 100%; - --card-foreground: 240 10% 3.9%; - --popover: 0 0% 100%; - --popover-foreground: 240 10% 3.9%; - --primary: 240 5.9% 10%; - --primary-foreground: 0 0% 98%; - --secondary: 240 4.8% 95.9%; - --secondary-foreground: 240 5.9% 10%; - --muted: 240 4.8% 95.9%; - --muted-foreground: 240 3.8% 46.1%; - --accent: 240 4.8% 95.9%; - --accent-foreground: 240 5.9% 10%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 0 0% 98%; - --border: 240 5.9% 90%; - --input: 240 5.9% 90%; - --highlight: 231 100% 78%; - --ring: 240 5.9% 10%; } } diff --git a/apps/web/app/home/(pages)/deploy/page.tsx b/apps/web/app/home/(pages)/deploy/page.tsx index b5f2ada..341c6f3 100644 --- a/apps/web/app/home/(pages)/deploy/page.tsx +++ b/apps/web/app/home/(pages)/deploy/page.tsx @@ -9,7 +9,7 @@ export default function Deploy() {

Deploy Feedbase to Vercel

-

+

You can deploy your own hosted instance of Feedbase to Vercel, for free, in just a few clicks.

@@ -27,7 +27,7 @@ export default function Deploy() { Create a Supabase project -

+

Supabase is an open source Firebase alternative. It provides a database, auth, and storage.

@@ -51,7 +51,7 @@ export default function Deploy() { Fork the Supabase database -

+

Once you have your Supabase project, you can fork the Feedbase database schemas to your own project.

@@ -79,7 +79,7 @@ export default function Deploy() { Prepare your environment variables -

+

After setting up your Supabase project, check the example configuration to see where you can find the necessary environment variables.

@@ -107,7 +107,7 @@ export default function Deploy() { Deploy to Vercel -

+

Once you have your environment variables, you can deploy to Vercel.

diff --git a/apps/web/app/home/(pages)/page.tsx b/apps/web/app/home/(pages)/page.tsx index a58c6ad..c07d9d9 100644 --- a/apps/web/app/home/(pages)/page.tsx +++ b/apps/web/app/home/(pages)/page.tsx @@ -27,7 +27,7 @@ export default function Landing() { in One Central Place -

+

Feedbase simplifies feedback collection, feature prioritization, and product update sharing, allowing you to focus on building.

@@ -39,7 +39,7 @@ export default function Landing() { @@ -48,7 +48,7 @@ export default function Landing() { + className='text-foreground/60 hover:text-foreground/90 group relative mt-4 flex w-fit flex-row items-center justify-center p-1 text-center text-sm '>

See it in action

@@ -73,7 +73,7 @@ export default function Landing() { Create your feedback
community today. -

+

Capture feedback, post updates, and engage
with your users in one central place.

diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index 8932134..35f166c 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -6,6 +6,7 @@ import { SpeedInsights } from '@vercel/speed-insights/next'; import { GeistSans } from 'geist/font'; import { Toaster } from 'sonner'; import { formatRootUrl } from '@/lib/utils'; +import { ThemeProvider as NextThemeProvider } from '@/components/theme-provider'; export const metadata: Metadata = { title: 'Feedbase', @@ -49,9 +50,11 @@ export default function RootLayout({ children }: { children: React.ReactNode }) )} -
- {children} -
+ +
+ {children} +
+
); diff --git a/apps/web/components/dashboard/analytics/bar-list.tsx b/apps/web/components/dashboard/analytics/bar-list.tsx index 1b7d956..c6d7b92 100644 --- a/apps/web/components/dashboard/analytics/bar-list.tsx +++ b/apps/web/components/dashboard/analytics/bar-list.tsx @@ -50,7 +50,7 @@ export default function BarList({ data, showData, title, maxItems }: BarListProp )}%`, }} /> - + {d.key} @@ -80,13 +80,13 @@ export default function BarList({ data, showData, title, maxItems }: BarListProp {/* If there are more than maxItems, show a "more" label */} {maxItems && data.length > maxItems ? ( -
+
@@ -95,8 +95,8 @@ export default function BarList({ data, showData, title, maxItems }: BarListProp {title}
- Visitors - Views + Visitors + Views
@@ -109,7 +109,7 @@ export default function BarList({ data, showData, title, maxItems }: BarListProp diff --git a/apps/web/components/dashboard/analytics/chart-cards.tsx b/apps/web/components/dashboard/analytics/chart-cards.tsx index 09b08fc..96c4f19 100644 --- a/apps/web/components/dashboard/analytics/chart-cards.tsx +++ b/apps/web/components/dashboard/analytics/chart-cards.tsx @@ -35,7 +35,7 @@ export default function AnalyticsCards({ Unique Visitors - + {updatedAnalyticsData.reduce((a, b) => a + b.visitors, 0)} @@ -51,7 +51,7 @@ export default function AnalyticsCards({ Page Views - + {updatedAnalyticsData.reduce((a, b) => a + b.clicks, 0)} @@ -71,7 +71,7 @@ export default function AnalyticsCards({ Top Changelogs @@ -219,7 +217,7 @@ export default function FeedbackTable({ })()} {/* Date */} -
+
{formatDate(new Date(feedback.created_at))}
diff --git a/apps/web/components/dashboard/feedback/status-combobox.tsx b/apps/web/components/dashboard/feedback/status-combobox.tsx index f727794..4c79015 100644 --- a/apps/web/components/dashboard/feedback/status-combobox.tsx +++ b/apps/web/components/dashboard/feedback/status-combobox.tsx @@ -70,12 +70,12 @@ export function StatusCombobox({ aria-expanded={open} variant='outline' className={cn( - 'text-foreground/60 group flex h-8 w-fit items-center justify-between gap-2 font-extralight', + 'text-foreground/60 group flex h-8 w-fit items-center justify-between gap-2 font-light', triggerClassName )} size='sm'> {currentItem ? ( -
+
{/* Status icon */} @@ -101,7 +101,7 @@ export function StatusCombobox({ setOpen(false); onSelect?.(currentItem?.label.toLowerCase() === currentValue ? '' : currentValue); }} - className='flex flex-row items-center gap-[6px] font-extralight'> + className='flex flex-row items-center gap-[6px] font-light'> {/* Icon */} diff --git a/apps/web/components/dashboard/feedback/tag-combobox.tsx b/apps/web/components/dashboard/feedback/tag-combobox.tsx index b231e21..bf93fcb 100644 --- a/apps/web/components/dashboard/feedback/tag-combobox.tsx +++ b/apps/web/components/dashboard/feedback/tag-combobox.tsx @@ -44,14 +44,14 @@ export function TagCombobox({ <> { // Close the dropdown setOpenColorDialog(true); }}> - Create tag: "{search}" + Create tag: "{search}" ); @@ -80,14 +80,14 @@ export function TagCombobox({ aria-expanded={open} variant='outline' className={cn( - 'text-foreground/60 flex h-8 w-1/4 items-center justify-between gap-2 font-extralight sm:w-fit', + 'text-foreground/60 flex h-8 w-1/4 items-center justify-between gap-2 font-light sm:w-fit', triggerClassName )} size='sm'> {/* TODO: Do not nest ternary expressions */} {tags && tags.length > 0 ? ( tags.length === 1 ? ( -
+
{/* Tag color */}
item.value.toLowerCase() === tags[0].toLowerCase())?.label}
) : ( -
+
{/* Tag colors */}
{currentTags.map((tag) => ( @@ -115,7 +115,7 @@ export function TagCombobox({ ))}
{/* Tag name */} - {currentTags.length} Tags + {currentTags.length} Tags
) ) : ( @@ -144,7 +144,7 @@ export function TagCombobox({ }}> + className='flex flex-row items-center gap-2 font-light'> {/* Tag color */}
{item.label} @@ -188,7 +188,7 @@ export function TagCombobox({ ))} - + No tags found, start typing to create a new tag diff --git a/apps/web/components/dashboard/modals/add-api-key-modal.tsx b/apps/web/components/dashboard/modals/add-api-key-modal.tsx index a68744e..26d6cd6 100644 --- a/apps/web/components/dashboard/modals/add-api-key-modal.tsx +++ b/apps/web/components/dashboard/modals/add-api-key-modal.tsx @@ -123,7 +123,7 @@ export default function AddApiKeyDialog({ className='col-span-3' /> -
@@ -136,7 +136,7 @@ export default function AddApiKeyDialog({ - @@ -150,7 +150,7 @@ export default function AddApiKeyDialog({ }}>

Public Access

-

+

View and create public available resources.

@@ -170,7 +170,7 @@ export default function AddApiKeyDialog({ }}>

Full Access

-

+

Admin-level access to all project resources.

@@ -185,7 +185,7 @@ export default function AddApiKeyDialog({
-
@@ -193,7 +193,7 @@ export default function AddApiKeyDialog({
-
+
- diff --git a/apps/web/components/dashboard/modals/add-project-modal.tsx b/apps/web/components/dashboard/modals/add-project-modal.tsx index 3aa30b3..0070247 100644 --- a/apps/web/components/dashboard/modals/add-project-modal.tsx +++ b/apps/web/components/dashboard/modals/add-project-modal.tsx @@ -90,7 +90,7 @@ export default function AddProjectDialog({ trigger }: { trigger: React.ReactNode className='col-span-3' /> - +
{/* Project Slug */} @@ -99,7 +99,7 @@ export default function AddProjectDialog({ trigger }: { trigger: React.ReactNode
-
+
- +
+