Skip to content

Commit

Permalink
feat: 优化搜索交互 (#76)
Browse files Browse the repository at this point in the history
  • Loading branch information
crazyair committed Mar 18, 2024
1 parent c678c21 commit 909a82c
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 38 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@monaco-editor/react": "^4.4.2",
"@types/react-dom": "18.2.5",
"@vercel/node": "^2.15.5",
"antd": "^5.6.4",
"antd": "^5.15.3",
"antd-style": "^3.4.4",
"chart.js": "^4.4.1",
"dayjs": "^1.11.9",
Expand Down
16 changes: 9 additions & 7 deletions src/components/LandingSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
'use client';

import React, { useLayoutEffect, useState } from 'react';
import { Input, Typography, AutoComplete, Space } from 'antd';
import { Input, Typography, AutoComplete } from 'antd';
import { useCachedSearch } from '@/hooks/useSearch';
import { useRouter } from 'next/router';
import Link from 'next/link';
import { PackageTag } from './PackageCard';
import { useRecent } from '@/hooks/useRecent';

Expand All @@ -29,13 +28,13 @@ export default function LandingSearch() {

return searchResult.objects.map((object) => ({
label: (
<Link href={`/package/${object.package.name}`}>
<>
<Typography.Text>
{object.package.name}@{object.package.version}
</Typography.Text>
<br />
<Typography.Text type="secondary">{object.package.description}</Typography.Text>
</Link>
</>
),
value: object.package.name,
}));
Expand All @@ -49,15 +48,18 @@ export default function LandingSearch() {
options={options}
autoFocus
onChange={setSearch}
onSelect={(search) => router.push(`/package/${search}`)}
onSelect={(search) => router.push(`/package/${search}`, undefined, { shallow: true })}
>
<Input.Search
size="large"
placeholder="输入 NPM 包名、作者、关键字等信息即可搜索..."
enterButton
onSearch={(_, e) => {
e?.stopPropagation();
router.push(`/packages?q=${search}`);
// 点击搜索按钮才进搜索页面
if (e?.type === 'click') {
e?.stopPropagation();
router.push(`/packages?q=${search}`);
}
}}
loading={!!(search && isLoading)}
/>
Expand Down
58 changes: 44 additions & 14 deletions src/components/PackageCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@ dayjs.locale('zh-cn');

dayjs.extend(relativeTime);

export function PackageTag({ tags, closeIcon, onClose }: { tags: {label: string, href: string}[], closeIcon?: boolean, onClose?: (tag: string) => void }) {
export function PackageTag({
tags,
closeIcon,
onClose,
}: {
tags: { label: string; href: string }[];
closeIcon?: boolean;
onClose?: (tag: string) => void;
}) {
if (!tags) {
return null;
}
Expand All @@ -26,14 +34,21 @@ export function PackageTag({ tags, closeIcon, onClose }: { tags: {label: string,
className={styles.tagCon}
maxCount="responsive"
data={tags}
renderItem={tag => (
<Tag key={tag.label} color="cyan" closeIcon={closeIcon} onClose={() => onClose?.(tag.label)}>
<Link href={tag.href}>
{tag.label}
</Link>
renderItem={(tag) => (
<Tag
key={tag.label}
color="cyan"
closeIcon={closeIcon}
onClose={() => onClose?.(tag.label)}
>
<Link href={tag.href}>{tag.label}</Link>
</Tag>
)}
renderRest={() => (
<Tag key={'_others'} color="cyan">
...
</Tag>
)}
renderRest={() => <Tag key={'_others'} color="cyan">...</Tag>}
/>
);
}
Expand All @@ -45,11 +60,15 @@ export const PackageCard = ({
}: {
package: SearchPackageResult;
loading?: boolean;
themeMode: ThemeMode,
themeMode: ThemeMode;
}) => {
return (
<Link href={`/package/${pkg.name}`} target="_blank">
<Card hoverable className={styles.packageCard} bodyStyle={{ padding: 0, height: '100%' }}>
<Card
hoverable
className={styles.packageCard}
styles={{ body: { padding: 0, height: '100%' } }}
>
<div className={styles.packageCon} style={{ paddingLeft: 80, paddingBottom: 16 }}>
{/* Logo */}
<div className={styles.logo} style={{ top: 20 }}>
Expand All @@ -60,7 +79,12 @@ export const PackageCard = ({
<div className={styles.content}>
<Row style={{ flexWrap: 'nowrap' }}>
<Col flex="auto" style={{ minWidth: 0 }}>
<SkeletonText className={themeMode === 'dark' ? styles.darkTitle :styles.title} loading={loading} title={pkg.name} ellipsis>
<SkeletonText
className={themeMode === 'dark' ? styles.darkTitle : styles.title}
loading={loading}
title={pkg.name}
ellipsis
>
{pkg.name}@{pkg.version}
</SkeletonText>
</Col>
Expand Down Expand Up @@ -94,10 +118,16 @@ export const PackageCard = ({
>
<Row gutter={8} align="middle" wrap={false}>
<Col flex="auto">
<PackageTag tags={pkg.keywords? pkg.keywords.map(item => ({
label: item,
href: `/packages?q=${item}`,
})): []} />
<PackageTag
tags={
pkg.keywords
? pkg.keywords.map((item) => ({
label: item,
href: `/packages?q=${item}`,
}))
: []
}
/>
</Col>
<Col flex="none">
<Space size="small" style={{ opacity: '.65' }}>
Expand Down
43 changes: 27 additions & 16 deletions src/components/SearchBox.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { SearchOutlined } from '@ant-design/icons';
import { Col, Input, Row, Space, Tabs } from 'antd';
import React from 'react';
import React, { useEffect, useState } from 'react';
import styles from './SearchBox.module.css';
import { SearchResult } from '@/hooks/useSearch';
import { useRouter } from 'next/router';

export interface SearchBoxProps {
defaultSearch: string;
Expand All @@ -12,6 +11,11 @@ export interface SearchBoxProps {
}

export default function SearchBox({ defaultSearch, onSearch, searchResult }: SearchBoxProps) {
const [value, setValue] = useState(defaultSearch);
useEffect(() => {
setValue(defaultSearch);
}, [defaultSearch]);

return (
<div style={{ overflow: 'hidden' }}>
<div style={{ padding: '32px 0' }}>
Expand All @@ -28,26 +32,33 @@ export default function SearchBox({ defaultSearch, onSearch, searchResult }: Sea
</Space>
}
size="large"
defaultValue={defaultSearch}
value={value}
onChange={(e) => setValue(e.target.value)}
onSearch={onSearch}
/>
</Col>
</Row>
</div>
<div>
<Tabs size="large" className={styles.tab} activeKey={'npm'}>
<Tabs.TabPane
key="npm"
tab={
<Space size="small">
搜索结果
<span className={styles.count}>
{((searchResult?.total as number) > 9999 ? '9999+' : searchResult?.total) ?? '-'}
</span>
</Space>
}
/>
</Tabs>
<Tabs
size="large"
className={styles.tab}
activeKey={'npm'}
items={[
{
key: 'npm',
label: (
<Space size="small">
搜索结果
<span className={styles.count}>
{((searchResult?.total as number) > 9999 ? '9999+' : searchResult?.total) ??
'-'}
</span>
</Space>
),
},
]}
/>
</div>
</div>
);
Expand Down

0 comments on commit 909a82c

Please sign in to comment.