mirror of
https://github.com/formbricks/formbricks.git
synced 2026-01-25 18:48:58 -06:00
feat: responsive settings menu for mobile screens
This commit is contained in:
@@ -4,6 +4,8 @@ import { useProduct } from "@/lib/products/products";
|
||||
import { useTeam } from "@/lib/teams/teams";
|
||||
import { truncate } from "@/lib/utils";
|
||||
import { IS_FORMBRICKS_CLOUD } from "@formbricks/lib/constants";
|
||||
import { Popover, PopoverTrigger, PopoverContent } from "@formbricks/ui";
|
||||
import { ChevronDownIcon } from "@heroicons/react/20/solid";
|
||||
import {
|
||||
AdjustmentsVerticalIcon,
|
||||
BellAlertIcon,
|
||||
@@ -21,12 +23,14 @@ import {
|
||||
import clsx from "clsx";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useMemo } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
|
||||
export default function SettingsNavbar({ environmentId }: { environmentId: string }) {
|
||||
const pathname = usePathname();
|
||||
const { team } = useTeam(environmentId);
|
||||
const { product } = useProduct(environmentId);
|
||||
const [mobileNavMenuOpen, setMobileNavMenuOpen] = useState(false);
|
||||
|
||||
interface NavigationLink {
|
||||
name: string;
|
||||
href: string;
|
||||
@@ -181,42 +185,94 @@ export default function SettingsNavbar({ environmentId }: { environmentId: strin
|
||||
if (!navigation) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed h-full bg-white py-2 pl-4 pr-10">
|
||||
<nav className="flex-1 space-y-1 bg-white px-2">
|
||||
{navigation.map((item) => (
|
||||
<div key={item.title}>
|
||||
<p className="mt-6 pl-3 pr-1 text-xs font-semibold uppercase tracking-wider text-slate-500">
|
||||
{item.title}{" "}
|
||||
{item.title === "Product" && product?.name && (
|
||||
<span className="font-normal capitalize">({truncate(product?.name, 10)})</span>
|
||||
)}
|
||||
{item.title === "Team" && team?.name && (
|
||||
<span className="font-normal capitalize">({truncate(team?.name, 14)})</span>
|
||||
)}
|
||||
</p>
|
||||
<div className="ml-2 mt-1 space-y-1">
|
||||
{item.links
|
||||
.filter((l) => !l.hidden)
|
||||
.map((link) => (
|
||||
<Link
|
||||
key={link.name}
|
||||
href={link.href}
|
||||
target={link.target}
|
||||
className={clsx(
|
||||
link.current ? "bg-slate-100 text-slate-900" : "text-slate-900 hover:bg-slate-50 ",
|
||||
"group flex items-center whitespace-nowrap rounded-md px-1 py-1 pl-2 text-sm font-medium "
|
||||
)}>
|
||||
<link.icon
|
||||
className="mr-3 h-4 w-4 flex-shrink-0 text-slate-400 group-hover:text-slate-500"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{link.name}
|
||||
</Link>
|
||||
))}
|
||||
<>
|
||||
<div className="fixed hidden h-full bg-white py-2 pl-4 pr-10 sm:block ">
|
||||
<nav className="flex-1 space-y-1 bg-white px-2">
|
||||
{navigation.map((item) => (
|
||||
<div key={item.title}>
|
||||
<p className="mt-6 pl-3 pr-1 text-xs font-semibold uppercase tracking-wider text-slate-500">
|
||||
{item.title}{" "}
|
||||
{item.title === "Product" && product?.name && (
|
||||
<span className="font-normal capitalize">({truncate(product?.name, 10)})</span>
|
||||
)}
|
||||
{item.title === "Team" && team?.name && (
|
||||
<span className="font-normal capitalize">({truncate(team?.name, 14)})</span>
|
||||
)}
|
||||
</p>
|
||||
<div className="ml-2 mt-1 space-y-1">
|
||||
{item.links
|
||||
.filter((l) => !l.hidden)
|
||||
.map((link) => (
|
||||
<Link
|
||||
key={link.name}
|
||||
href={link.href}
|
||||
target={link.target}
|
||||
className={clsx(
|
||||
link.current ? "bg-slate-100 text-slate-900" : "text-slate-900 hover:bg-slate-50 ",
|
||||
"group flex items-center whitespace-nowrap rounded-md px-1 py-1 pl-2 text-sm font-medium "
|
||||
)}>
|
||||
<link.icon
|
||||
className="mr-3 h-4 w-4 flex-shrink-0 text-slate-400 group-hover:text-slate-500"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{link.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
<div className="fixed z-10 flex h-14 w-full items-center justify-between bg-white px-4 sm:hidden sm:px-6">
|
||||
<Popover open={mobileNavMenuOpen} onOpenChange={setMobileNavMenuOpen}>
|
||||
<PopoverTrigger onClick={() => setMobileNavMenuOpen(!mobileNavMenuOpen)}>
|
||||
<span className="flex items-center">
|
||||
<span className="mr-1">Settings</span>
|
||||
<ChevronDownIcon className="h-5 w-5 text-slate-500" aria-hidden="true" />
|
||||
</span>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="shadow">
|
||||
<div className="flex flex-col">
|
||||
{navigation.map((item) => (
|
||||
<div key={item.title}>
|
||||
<p className="mt-6 pl-3 pr-1 text-xs font-semibold uppercase tracking-wider text-slate-500">
|
||||
{item.title}{" "}
|
||||
{item.title === "Product" && product?.name && (
|
||||
<span className="font-normal capitalize">({truncate(product?.name, 10)})</span>
|
||||
)}
|
||||
{item.title === "Team" && team?.name && (
|
||||
<span className="font-normal capitalize">({truncate(team?.name, 14)})</span>
|
||||
)}
|
||||
</p>
|
||||
<div className="ml-2 mt-1 space-y-1">
|
||||
{item.links
|
||||
.filter((l) => !l.hidden)
|
||||
.map((link) => (
|
||||
<Link
|
||||
key={link.name}
|
||||
href={link.href}
|
||||
target={link.target}
|
||||
onClick={() => setMobileNavMenuOpen(false)}
|
||||
className={clsx(
|
||||
link.current
|
||||
? "bg-slate-100 text-slate-900"
|
||||
: "text-slate-900 hover:bg-slate-50 ",
|
||||
"group flex items-center whitespace-nowrap rounded-md px-1 py-1 pl-2 text-sm font-medium "
|
||||
)}>
|
||||
<link.icon
|
||||
className="mr-3 h-4 w-4 flex-shrink-0 text-slate-400 group-hover:text-slate-500"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{link.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ export const metadata: Metadata = {
|
||||
export default function SettingsLayout({ children, params }) {
|
||||
return (
|
||||
<>
|
||||
<div className="flex">
|
||||
<div className="sm:flex">
|
||||
<SettingsNavbar environmentId={params.environmentId} />
|
||||
<div className="ml-64 w-full">
|
||||
<div className="max-w-4xl p-6">
|
||||
<div className="w-full sm:ml-64">
|
||||
<div className="max-w-4xl px-6 pb-6 pt-14 sm:pt-6">
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user