-
Notifications
You must be signed in to change notification settings - Fork 0
feat: refactor home page #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR refactors the home page to improve the user experience with enhanced animations, optimized card layouts, and new interactive components. The changes focus on making the UI more compact, modern, and engaging.
Changes:
- Added new components: WelcomeSection with animated greeting, QuickStatsSection for activity overview, and AiChatBox for AI assistant interaction
- Refactored PinnedNoteCard to display more content with responsive sizing (basis-full to xl:basis-1/5) and improved hover effects
- Enhanced RecentActivitySection with better styling, empty states, and responsive tab labels
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| src/pages/home/index.tsx | Restructured layout with new sections, fixed duplicate mock data in pinnedNotes array |
| src/pages/home/components/welcome-section.tsx | New component with time-based greeting and waving emoji animation |
| src/pages/home/components/quick-stats.tsx | New statistics overview component with grid layout |
| src/pages/home/components/ai-chat-box.tsx | New AI chat interface with message history and quick actions |
| src/pages/home/components/pinned-note-card.tsx | Refactored with compact design, responsive breakpoints, and improved carousel |
| src/pages/home/components/recent-note-item.tsx | Enhanced with better typography, spacing fixes, and empty state handling |
| src/pages/home/components/home-header.tsx | Improved with functional search input and reorganized dropdown menu |
| package.json | Added baseline-browser-mapping as explicit devDependency |
| pnpm-lock.yaml | Updated lock file with new dependency version |
| .vscode/extensions.json | Added github.copilot-chat to recommended extensions |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)
src/pages/home/index.tsx:52
- The pinnedNotes array contains duplicate entries. Items with id 1, 2, and 3 appear twice (lines 10-30 and lines 32-51). This will cause duplicate keys in the React component rendering and display the same notes twice, which is likely unintentional.
const pinnedNotes = [
{
id: 1,
title: "项目Alpha启动会议纪要",
description: "讨论了Q4目标和资源分配...",
lastEdited: "2小时前",
emoji: "🚀",
},
{
id: 2,
title: "我的2025年旅行计划",
description: "目的地清单:冰岛、新西兰、日本...",
lastEdited: "昨天",
emoji: "✈️",
},
{
id: 3,
title: "React最佳实践",
description: "Hooks, Context, and Performance...",
lastEdited: "3天前",
emoji: "⚛️",
},
{
id: 1,
title: "项目Alpha启动会议纪要",
description: "讨论了Q4目标和资源分配...",
lastEdited: "2小时前",
emoji: "🚀",
},
{
id: 2,
title: "我的2025年旅行计划",
description: "目的地清单:冰岛、新西兰、日本...",
lastEdited: "昨天",
emoji: "✈️",
},
{
id: 3,
title: "React最佳实践",
description: "Hooks, Context, and Performance...",
lastEdited: "3天前",
emoji: "⚛️",
},
];
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -53,20 +55,39 @@ export function HomePage() { | |||
| return ( | |||
| <div className="bg-muted/20 text-foreground min-h-screen"> | |||
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR description mentions removing the min-h-screen style to fix sidebar display issues, but min-h-screen is still present on line 56. This inconsistency between the description and the actual code should be addressed. If min-h-screen needs to be kept, update the PR description accordingly.
| <div className="bg-muted/20 text-foreground min-h-screen"> | |
| <div className="bg-muted/20 text-foreground"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
后续测试证明不需删除 min-h-screen
src/pages/home/index.tsx
Outdated
| @@ -1,9 +1,11 @@ | |||
| import { Star } from "lucide-react"; | |||
| import { Notebook, Star } from "lucide-react"; | |||
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Notebook icon is imported but not used in this file. Consider removing it to keep the imports clean.
| import { Notebook, Star } from "lucide-react"; | |
| import { Star } from "lucide-react"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| <ScrollArea | ||
| className="h-40 rounded-lg border border-border/50 bg-muted/20 p-3" | ||
| ref={scrollRef} |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ScrollArea component is being used with a ref prop, but the ScrollArea component from shadcn/ui doesn't forward refs by default. The ref should be passed to the viewport element inside ScrollArea using ScrollAreaViewport or a custom ref handling mechanism. This will cause the auto-scroll functionality to not work properly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot open a new pull request to apply changes based on this feedback
| <Button | ||
| onClick={handleSend} | ||
| disabled={!input.trim() || isLoading} | ||
| size="icon" | ||
| > | ||
| {isLoading ? ( | ||
| <Loader2 className="h-4 w-4 animate-spin" /> | ||
| ) : ( | ||
| <Send size={16} /> | ||
| )} | ||
| </Button> |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The send button lacks an accessible label. When disabled or in loading state, screen readers won't be able to announce the purpose of this icon-only button. Add an aria-label attribute such as 'Send message' or '发送消息' to improve accessibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
<Button
onClick={handleSend}
disabled={!input.trim() || isLoading}
size="icon"
aria-label="发送消息"
>
{isLoading ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<Send size={16} />
)}
</Button>
package.json
Outdated
| "@types/react": "^19.1.8", | ||
| "@types/react-dom": "^19.1.6", | ||
| "@vitejs/plugin-react": "^4.6.0", | ||
| "baseline-browser-mapping": "^2.9.14", |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The baseline-browser-mapping package is being added as a devDependency. However, this package is typically an internal dependency of browserslist and shouldn't need to be explicitly added to package.json. It will be installed automatically as a transitive dependency when needed. Adding it explicitly may cause version conflicts or confusion about dependency management.
| "baseline-browser-mapping": "^2.9.14", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
|
||
| export function PinnedNoteCard({ notes }: PinnedNoteCardProps) { | ||
| const autoplay = useRef(Autoplay({ delay: 1500, stopOnInteraction: true })); | ||
| const autoplay = useRef(Autoplay({ delay: 4000, stopOnInteraction: true })); |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The autoplay delay has been increased from 1500ms to 4000ms. While this may be intentional for better user experience, such a long delay (4 seconds) might make the carousel feel unresponsive. Consider a middle ground around 2500-3000ms for better balance between allowing users to read content and maintaining engagement.
| const autoplay = useRef(Autoplay({ delay: 4000, stopOnInteraction: true })); | |
| const autoplay = useRef(Autoplay({ delay: 3000, stopOnInteraction: true })); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| id: Date.now().toString(), | ||
| role: "user", | ||
| content: input.trim(), | ||
| timestamp: new Date(), | ||
| }; | ||
|
|
||
| setMessages((prev) => [...prev, userMessage]); | ||
| setInput(""); | ||
| setIsLoading(true); | ||
|
|
||
| // Simulate AI response | ||
| setTimeout(() => { | ||
| const aiMessage: Message = { | ||
| id: (Date.now() + 1).toString(), |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The message ID generation using Date.now().toString() could potentially create duplicate IDs if two messages are created in rapid succession within the same millisecond. Consider using a more robust ID generation method such as crypto.randomUUID() or a counter-based approach to ensure uniqueness.
| "rust-lang.rust-analyzer", | ||
| "github.copilot-chat" |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding github.copilot-chat to the recommended extensions is unrelated to the home page refactoring described in the PR. This change should ideally be in a separate PR or the PR description should mention it. However, this is a minor organizational issue and doesn't affect functionality.
| "rust-lang.rust-analyzer", | |
| "github.copilot-chat" | |
| "rust-lang.rust-analyzer" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
不需要关注
| <style>{` | ||
| @keyframes wave { | ||
| 0%, 100% { transform: rotate(0deg); } | ||
| 25% { transform: rotate(15deg); } | ||
| 50% { transform: rotate(-10deg); } | ||
| 75% { transform: rotate(10deg); } | ||
| } | ||
| `}</style> |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using inline style tags within components creates duplicate style elements when the component re-renders or when multiple instances exist. Consider moving the keyframes animation to a global CSS file or using CSS-in-JS solutions. Additionally, Tailwind CSS already supports keyframe animations which could be configured in tailwind.config.js instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| <Button | ||
| variant="ghost" | ||
| size="icon" | ||
| className="h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity -mr-1 -mt-1" |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dropdown menu trigger button lacks an accessible label. Screen readers won't be able to announce the purpose of this button. Add an aria-label attribute such as 'More options' or '更多操作' to improve accessibility.
| className="h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity -mr-1 -mt-1" | |
| className="h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity -mr-1 -mt-1" | |
| aria-label="更多操作" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 9 out of 10 changed files in this pull request and generated 12 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)
src/pages/home/index.tsx:52
- The pinnedNotes array contains duplicate entries. Items with IDs 1, 2, and 3 are repeated twice (lines 10-30 and 32-51), which appears to be unintentional test data duplication.
const pinnedNotes = [
{
id: 1,
title: "项目Alpha启动会议纪要",
description: "讨论了Q4目标和资源分配...",
lastEdited: "2小时前",
emoji: "🚀",
},
{
id: 2,
title: "我的2025年旅行计划",
description: "目的地清单:冰岛、新西兰、日本...",
lastEdited: "昨天",
emoji: "✈️",
},
{
id: 3,
title: "React最佳实践",
description: "Hooks, Context, and Performance...",
lastEdited: "3天前",
emoji: "⚛️",
},
{
id: 1,
title: "项目Alpha启动会议纪要",
description: "讨论了Q4目标和资源分配...",
lastEdited: "2小时前",
emoji: "🚀",
},
{
id: 2,
title: "我的2025年旅行计划",
description: "目的地清单:冰岛、新西兰、日本...",
lastEdited: "昨天",
emoji: "✈️",
},
{
id: 3,
title: "React最佳实践",
description: "Hooks, Context, and Performance...",
lastEdited: "3天前",
emoji: "⚛️",
},
];
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <DropdownMenuContent align="end"> | ||
| <DropdownMenuItem>移除记录</DropdownMenuItem> | ||
| <DropdownMenuItem>打开</DropdownMenuItem> | ||
| <DropdownMenuItem>添加到收藏</DropdownMenuItem> | ||
| <DropdownMenuItem className="text-red-500">删除笔记</DropdownMenuItem> | ||
| <DropdownMenuItem className="text-red-500">移除</DropdownMenuItem> | ||
| </DropdownMenuContent> |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dropdown menu items in the activity wrapper have no event handlers. The "打开", "添加到收藏", and "移除" options don't perform any actions when clicked.
package.json
Outdated
| "@types/react": "^19.1.8", | ||
| "@types/react-dom": "^19.1.6", | ||
| "@vitejs/plugin-react": "^4.6.0", | ||
| "baseline-browser-mapping": "^2.9.14", |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dependency "baseline-browser-mapping" is added but appears to be unused in the codebase. This package is typically a transitive dependency of browserslist and shouldn't need to be explicitly added to package.json unless there's a specific reason.
| "baseline-browser-mapping": "^2.9.14", |
| <CarouselNext /> | ||
| </Carousel> | ||
| </> | ||
| <Card className="h-full hover:shadow-md hover:border-primary/50 transition-all duration-200 cursor-pointer group border-border/40 bg-card/50 backdrop-blur-sm overflow-hidden"> |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The card has cursor-pointer but no click handler or interactive element. The entire card appears clickable but doesn't perform any action when clicked. Either add an onClick handler or remove the cursor-pointer class to avoid misleading users.
| <Card className="h-full hover:shadow-md hover:border-primary/50 transition-all duration-200 cursor-pointer group border-border/40 bg-card/50 backdrop-blur-sm overflow-hidden"> | |
| <Card className="h-full hover:shadow-md hover:border-primary/50 transition-all duration-200 group border-border/40 bg-card/50 backdrop-blur-sm overflow-hidden"> |
| <style>{` | ||
| @keyframes wave { | ||
| 0%, 100% { transform: rotate(0deg); } | ||
| 25% { transform: rotate(15deg); } | ||
| 50% { transform: rotate(-10deg); } | ||
| 75% { transform: rotate(10deg); } | ||
| } | ||
| `}</style> |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inline style tag should be avoided. The animation keyframes should be defined in a separate CSS file or use Tailwind's animation utilities. Inline style tags can cause issues with Content Security Policy and are harder to maintain.
| {/* Messages Area */} | ||
| <ScrollArea | ||
| className="h-40 rounded-lg border border-border/50 bg-muted/20 p-3" | ||
| ref={scrollRef} |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing accessibility attribute. The scrollable area should have an accessible label or aria-label to improve screen reader support for users navigating the chat messages.
| ref={scrollRef} | |
| ref={scrollRef} | |
| aria-label="AI 聊天消息历史" |
| const stats = [ | ||
| { | ||
| label: "总笔记数", | ||
| value: "24", | ||
| icon: FileText, | ||
| color: "text-blue-500", | ||
| bgColor: "bg-blue-50 dark:bg-blue-950/30", | ||
| }, | ||
| { | ||
| label: "收藏笔记", | ||
| value: "8", | ||
| icon: Star, | ||
| color: "text-yellow-500", | ||
| bgColor: "bg-yellow-50 dark:bg-yellow-950/30", | ||
| }, | ||
| { | ||
| label: "待办项目", | ||
| value: "5", | ||
| icon: AlertCircle, | ||
| color: "text-orange-500", | ||
| bgColor: "bg-orange-50 dark:bg-orange-950/30", | ||
| }, | ||
| { | ||
| label: "已完成项目", | ||
| value: "12", | ||
| icon: CheckCircle2, | ||
| color: "text-green-500", | ||
| bgColor: "bg-green-50 dark:bg-green-950/30", | ||
| }, | ||
| ]; |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The stats data is hardcoded with static values ("24", "8", "5", "12"). These values should be dynamically calculated based on actual user data to provide meaningful information.
| <div className="flex flex-wrap gap-2"> | ||
| <QuickActionButton | ||
| text="总结笔记" | ||
| onClick={() => setInput("帮我总结最近的笔记")} | ||
| /> | ||
| <QuickActionButton | ||
| text="创建待办" | ||
| onClick={() => setInput("帮我创建一个新的待办事项")} | ||
| /> | ||
| <QuickActionButton | ||
| text="搜索内容" | ||
| onClick={() => setInput("帮我搜索相关内容")} | ||
| /> | ||
| </div> |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quick action buttons set input values but don't automatically submit. This may create confusion as users might expect these buttons to immediately execute the action rather than just populating the input field.
| export function HomeHeader() { | ||
| const [searchQuery, setSearchQuery] = useState(""); | ||
|
|
||
| const handleSearch = (e: React.FormEvent) => { | ||
| e.preventDefault(); | ||
| // TODO: 实现搜索逻辑 | ||
| console.log("Search:", searchQuery); |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The search functionality is not implemented (only logs to console). The TODO comment indicates this, but a placeholder that doesn't perform actual search functionality may confuse users if they interact with it.
| export function HomeHeader() { | |
| const [searchQuery, setSearchQuery] = useState(""); | |
| const handleSearch = (e: React.FormEvent) => { | |
| e.preventDefault(); | |
| // TODO: 实现搜索逻辑 | |
| console.log("Search:", searchQuery); | |
| export function HomeHeader({ onSearch }: { onSearch?: (query: string) => void }) { | |
| const [searchQuery, setSearchQuery] = useState(""); | |
| const handleSearch = (e: React.FormEvent) => { | |
| e.preventDefault(); | |
| if (onSearch) { | |
| onSearch(searchQuery); | |
| } |
| // Simulate AI response | ||
| setTimeout(() => { | ||
| const aiMessage: Message = { | ||
| id: (Date.now() + 1).toString(), | ||
| role: "assistant", | ||
| content: `我收到了你的消息:"${userMessage.content}"。这是一个模拟回复。`, | ||
| timestamp: new Date(), | ||
| }; | ||
| setMessages((prev) => [...prev, aiMessage]); | ||
| setIsLoading(false); | ||
| }, 1000); | ||
| }; |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The AI chat response is simulated with a setTimeout and returns a mock message. While acceptable for demonstration, this should be clearly documented or replaced with actual AI integration to avoid confusion.
| <DropdownMenuContent align="end"> | ||
| <DropdownMenuItem>编辑</DropdownMenuItem> | ||
| <DropdownMenuItem>取消收藏</DropdownMenuItem> | ||
| <DropdownMenuItem className="text-destructive"> | ||
| 删除 | ||
| </DropdownMenuItem> | ||
| </DropdownMenuContent> |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dropdown menu items have no event handlers. The "编辑", "取消收藏", and "删除" options are displayed but don't perform any actions when clicked, which may confuse users.
重构首页欢迎区和收藏卡片组件
issue: #1
改动概述
本次 PR 对首页的欢迎区域和收藏笔记卡片进行了重构和优化,提升了用户体验和视觉效果。
主要改动
1. 欢迎区域动效优化 (
welcome-section.tsx)2. 收藏卡片组件重构 (
pinned-note-card.tsx)basis-1/2 lg:basis-1/3改为basis-full sm:basis-1/2 md:basis-1/3 lg:basis-1/4 xl:basis-1/5,在同一屏幕可展示更多内容3. 布局修复 (
index.tsx)min-h-screen样式,修复侧边栏无法显示的问题视觉效果提升