chore: sidebar design update on project page (#272)

This commit is contained in:
kimatata
2025-08-10 12:58:41 +09:00
committed by GitHub
parent 763a3ab832
commit 905eda068f
8 changed files with 69 additions and 32 deletions

View File

@@ -154,6 +154,7 @@
}, },
"Project": { "Project": {
"project": "Project", "project": "Project",
"toggle_sidebar": "Toggle Sidebar",
"home": "Home", "home": "Home",
"test_cases": "Test Cases", "test_cases": "Test Cases",
"test_runs": "Test Runs", "test_runs": "Test Runs",

View File

@@ -155,6 +155,7 @@
}, },
"Project": { "Project": {
"project": "プロジェクト", "project": "プロジェクト",
"toggle_sidebar": "サイドバーの切り替え",
"home": "ホーム", "home": "ホーム",
"test_cases": "テストケース", "test_cases": "テストケース",
"test_runs": "テストラン", "test_runs": "テストラン",

View File

@@ -154,6 +154,7 @@
}, },
"Project": { "Project": {
"project": "Projeto", "project": "Projeto",
"toggle_sidebar": "Alternar barra lateral",
"home": "Início", "home": "Início",
"test_cases": "Casos de Teste", "test_cases": "Casos de Teste",
"test_runs": "Execuções de Teste", "test_runs": "Execuções de Teste",

View File

@@ -23,7 +23,7 @@
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"framer-motion": "^11.18.2", "framer-motion": "^11.18.2",
"intl-messageformat": "^10.7.15", "intl-messageformat": "^10.7.15",
"lucide-react": "^0.475.0", "lucide-react": "^0.539.0",
"next": "^14.2.24", "next": "^14.2.24",
"next-intl": "^3.26.5", "next-intl": "^3.26.5",
"next-themes": "^0.4.4", "next-themes": "^0.4.4",
@@ -10502,9 +10502,10 @@
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
}, },
"node_modules/lucide-react": { "node_modules/lucide-react": {
"version": "0.475.0", "version": "0.539.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.475.0.tgz", "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.539.0.tgz",
"integrity": "sha512-NJzvVu1HwFVeZ+Gwq2q00KygM1aBhy/ZrhY9FsAgJtpB+E4R7uxRk9M2iKvHa6/vNxZydIB59htha4c2vvwvVg==", "integrity": "sha512-VVISr+VF2krO91FeuCrm1rSOLACQUYVy7NQkzrOty52Y8TlTPcXcMdQFj9bYzBgXbWCiywlwSZ3Z8u6a+6bMlg==",
"license": "ISC",
"peerDependencies": { "peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
} }

View File

@@ -24,7 +24,7 @@
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"framer-motion": "^11.18.2", "framer-motion": "^11.18.2",
"intl-messageformat": "^10.7.15", "intl-messageformat": "^10.7.15",
"lucide-react": "^0.475.0", "lucide-react": "^0.539.0",
"next": "^14.2.24", "next": "^14.2.24",
"next-intl": "^3.26.5", "next-intl": "^3.26.5",
"next-themes": "^0.4.4", "next-themes": "^0.4.4",

View File

@@ -1,7 +1,15 @@
'use client'; 'use client';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Listbox, ListboxItem } from '@heroui/react'; import { Button, Tooltip } from '@heroui/react';
import { Home, Files, FlaskConical, Users, Settings } from 'lucide-react'; import {
PanelLeftClose,
PanelLeftOpen,
ChartColumnStacked,
ClipboardList,
FlaskConical,
UserRound,
Settings,
} from 'lucide-react';
import { usePathname, useRouter } from '@/src/i18n/routing'; import { usePathname, useRouter } from '@/src/i18n/routing';
import useGetCurrentIds from '@/utils/useGetCurrentIds'; import useGetCurrentIds from '@/utils/useGetCurrentIds';
import { ProjectMessages } from '@/types/project'; import { ProjectMessages } from '@/types/project';
@@ -16,11 +24,15 @@ export default function Sidebar({ messages, locale }: Props) {
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
const [currentKey, setCurrentTab] = useState('home'); const [currentKey, setCurrentKey] = useState('home');
const baseClass = 'p-3'; const [isSideBarOpen, setIsSideBarOpen] = useState(true);
const selectedClass = `${baseClass} bg-neutral-200 dark:bg-neutral-700`;
const handleTabClick = (key: string) => { const TOGGLE_ICON_STROKE_WIDTH = 1;
const TOGGLE_ICON_SIZE = 18;
const ICON_STROKE_WIDTH = 1;
const ICON_SIZE = 26;
const handleClick = (key: string) => {
if (key === 'home') { if (key === 'home') {
router.push(`/projects/${projectId}/home`, { locale: locale }); router.push(`/projects/${projectId}/home`, { locale: locale });
} else if (key === 'cases') { } else if (key === 'cases') {
@@ -37,15 +49,15 @@ export default function Sidebar({ messages, locale }: Props) {
useEffect(() => { useEffect(() => {
const handleRouteChange = (currentPath: string) => { const handleRouteChange = (currentPath: string) => {
if (currentPath.includes('home')) { if (currentPath.includes('home')) {
setCurrentTab('home'); setCurrentKey('home');
} else if (currentPath.includes('folders')) { } else if (currentPath.includes('folders')) {
setCurrentTab('cases'); setCurrentKey('cases');
} else if (currentPath.includes('runs')) { } else if (currentPath.includes('runs')) {
setCurrentTab('runs'); setCurrentKey('runs');
} else if (currentPath.includes('members')) { } else if (currentPath.includes('members')) {
setCurrentTab('members'); setCurrentKey('members');
} else if (currentPath.includes('settings')) { } else if (currentPath.includes('settings')) {
setCurrentTab('settings'); setCurrentKey('settings');
} }
}; };
@@ -56,44 +68,63 @@ export default function Sidebar({ messages, locale }: Props) {
{ {
key: 'home', key: 'home',
text: messages.home, text: messages.home,
startContent: <Home strokeWidth={1} size={20} />, startContent: <ChartColumnStacked strokeWidth={ICON_STROKE_WIDTH} size={ICON_SIZE} />,
}, },
{ {
key: 'cases', key: 'cases',
text: messages.testCases, text: messages.testCases,
startContent: <Files strokeWidth={1} size={20} />, startContent: <ClipboardList strokeWidth={ICON_STROKE_WIDTH} size={ICON_SIZE} />,
}, },
{ {
key: 'runs', key: 'runs',
text: messages.testRuns, text: messages.testRuns,
startContent: <FlaskConical strokeWidth={1} size={20} />, startContent: <FlaskConical strokeWidth={ICON_STROKE_WIDTH} size={ICON_SIZE} />,
}, },
{ {
key: 'members', key: 'members',
text: messages.members, text: messages.members,
startContent: <Users strokeWidth={1} size={20} />, startContent: <UserRound strokeWidth={ICON_STROKE_WIDTH} size={ICON_SIZE} />,
}, },
{ {
key: 'settings', key: 'settings',
text: messages.settings, text: messages.settings,
startContent: <Settings strokeWidth={1} size={20} />, startContent: <Settings strokeWidth={ICON_STROKE_WIDTH} size={ICON_SIZE} />,
}, },
]; ];
return ( return (
<div className="w-48 border-r-1 dark:border-neutral-700"> <div className="border-r-1 dark:border-neutral-700">
<Listbox aria-label="Listbox Variants" variant="light"> <div className="w-full flex justify-end">
<Tooltip content={messages.toggleSidebar} placement="right">
<Button size="lg" isIconOnly variant="light" onPress={() => setIsSideBarOpen(!isSideBarOpen)}>
{isSideBarOpen ? (
<PanelLeftClose strokeWidth={TOGGLE_ICON_STROKE_WIDTH} size={TOGGLE_ICON_SIZE} />
) : (
<PanelLeftOpen strokeWidth={TOGGLE_ICON_STROKE_WIDTH} size={TOGGLE_ICON_SIZE} />
)}
</Button>
</Tooltip>
</div>
<div className="border-t-1 dark:border-neutral-700">
{tabItems.map((itr) => ( {tabItems.map((itr) => (
<ListboxItem <div key={itr.key}>
key={itr.key} <Tooltip hidden={isSideBarOpen} content={itr.text} placement="right">
<Button
size="lg"
isIconOnly={!isSideBarOpen}
startContent={itr.startContent} startContent={itr.startContent}
onPress={() => handleTabClick(itr.key)} isDisabled={itr.key === currentKey}
className={currentKey === itr.key ? selectedClass : baseClass} variant="light"
className={isSideBarOpen ? 'w-full justify-start' : ''}
onPress={() => handleClick(itr.key)}
> >
{itr.text} {isSideBarOpen ? itr.text : ''}
</ListboxItem> </Button>
</Tooltip>
</div>
))} ))}
</Listbox> </div>
</div> </div>
); );
} }

View File

@@ -11,6 +11,7 @@ export default function SidebarLayout({
}) { }) {
const t = useTranslations('Project'); const t = useTranslations('Project');
const messages: ProjectMessages = { const messages: ProjectMessages = {
toggleSidebar: t('toggle_sidebar'),
home: t('home'), home: t('home'),
testCases: t('test_cases'), testCases: t('test_cases'),
testRuns: t('test_runs'), testRuns: t('test_runs'),

View File

@@ -40,6 +40,7 @@ export type ProjectsMessages = {
}; };
export type ProjectMessages = { export type ProjectMessages = {
toggleSidebar: string;
home: string; home: string;
testCases: string; testCases: string;
testRuns: string; testRuns: string;