优化排序控件
This commit is contained in:
+41
-12
@@ -268,11 +268,16 @@ function Showcase() {
|
||||
}
|
||||
|
||||
function selectRange(minKey: "minCoin" | "minPrice", maxKey: "maxCoin" | "maxPrice", min: string, max: string) {
|
||||
setFilters((current) => ({ ...current, [minKey]: min, [maxKey]: max }));
|
||||
setFilters((current) => {
|
||||
if (current[minKey] === min && current[maxKey] === max) {
|
||||
return { ...current, [minKey]: "", [maxKey]: "" };
|
||||
}
|
||||
return { ...current, [minKey]: min, [maxKey]: max };
|
||||
});
|
||||
}
|
||||
|
||||
function setSort(sortKey: string) {
|
||||
setActiveSort((current) => (current === sortKey && sortKey !== "recommended" ? "recommended" : sortKey));
|
||||
setActiveSort(sortKey);
|
||||
setPage(1);
|
||||
}
|
||||
|
||||
@@ -351,7 +356,10 @@ function Showcase() {
|
||||
) : null}
|
||||
|
||||
<section className="filter-board">
|
||||
<div className="section-title">筛选条件</div>
|
||||
<div className="section-title">
|
||||
<i />
|
||||
筛选条件
|
||||
</div>
|
||||
<div className="filter-grid">
|
||||
<FilterRow
|
||||
active={(item) => filters.minCoin === item.min && filters.maxCoin === item.max}
|
||||
@@ -430,33 +438,39 @@ function Showcase() {
|
||||
<div className="range-fields">
|
||||
<label>
|
||||
<span>哈夫币范围</span>
|
||||
<div className="range-inputs">
|
||||
<Input
|
||||
inputMode="numeric"
|
||||
placeholder="最小"
|
||||
value={filters.minCoin}
|
||||
onChange={(event) => updateFilter("minCoin", event.target.value)}
|
||||
/>
|
||||
<em>至</em>
|
||||
<Input
|
||||
inputMode="numeric"
|
||||
placeholder="最大"
|
||||
value={filters.maxCoin}
|
||||
onChange={(event) => updateFilter("maxCoin", event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
<label>
|
||||
<span>KD范围</span>
|
||||
<div className="range-inputs">
|
||||
<Input
|
||||
inputMode="decimal"
|
||||
placeholder="最小"
|
||||
value={filters.minKd}
|
||||
onChange={(event) => updateFilter("minKd", event.target.value)}
|
||||
/>
|
||||
<em>至</em>
|
||||
<Input
|
||||
inputMode="decimal"
|
||||
placeholder="最大"
|
||||
value={filters.maxKd}
|
||||
onChange={(event) => updateFilter("maxKd", event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
{skinSections.map((section) => (
|
||||
@@ -472,19 +486,27 @@ function Showcase() {
|
||||
</div>
|
||||
|
||||
<div className="filter-footer">
|
||||
<Button type="link" onClick={() => setAdvancedOpen((open) => !open)}>
|
||||
{advancedOpen ? "收起高级筛选" : "展开高级筛选"} <DownOutlined rotate={advancedOpen ? 180 : 0} />
|
||||
</Button>
|
||||
<button className="advanced-toggle" type="button" onClick={() => setAdvancedOpen((open) => !open)}>
|
||||
{advancedOpen ? "收起高级筛选" : "展开高级筛选"}
|
||||
<DownOutlined rotate={advancedOpen ? 180 : 0} />
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="result-area">
|
||||
<div className="sort-toolbar">
|
||||
<div className="sort-buttons">
|
||||
<div className="sort-segment" role="tablist" aria-label="排序方式">
|
||||
{sortOptions.map((option) => (
|
||||
<Button key={option.key} className={activeSort === option.key ? "active" : ""} onClick={() => setSort(option.key)}>
|
||||
{option.label} <DownOutlined />
|
||||
</Button>
|
||||
<button
|
||||
key={option.key}
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={activeSort === option.key}
|
||||
className={activeSort === option.key ? "active" : ""}
|
||||
onClick={() => setSort(option.key)}
|
||||
>
|
||||
{option.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="toolbar-actions">
|
||||
@@ -560,12 +582,19 @@ interface FilterRowProps<T> {
|
||||
function FilterRow<T>({ active, label, onSelect, options, render }: FilterRowProps<T>) {
|
||||
return (
|
||||
<div className="filter-row">
|
||||
<span>{label}</span>
|
||||
<span className="filter-label">{label}</span>
|
||||
<div className="chip-list">
|
||||
{options.map((item) => {
|
||||
const text = render(item);
|
||||
const selected = active(item);
|
||||
return (
|
||||
<button key={text} className={active(item) ? "selected" : ""} type="button" onClick={() => onSelect(item)}>
|
||||
<button
|
||||
key={text}
|
||||
className={selected ? "selected" : ""}
|
||||
type="button"
|
||||
aria-pressed={selected}
|
||||
onClick={() => onSelect(item)}
|
||||
>
|
||||
{text}
|
||||
</button>
|
||||
);
|
||||
|
||||
+169
-47
@@ -271,38 +271,49 @@ input {
|
||||
}
|
||||
|
||||
.filter-board {
|
||||
padding: 18px 22px 10px;
|
||||
padding: 18px 22px 12px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 14px;
|
||||
color: var(--text-main);
|
||||
font-size: 14px;
|
||||
font-size: 15px;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
.section-title i {
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
border-radius: 99px;
|
||||
background: linear-gradient(180deg, #ff8b2f, var(--brand));
|
||||
}
|
||||
|
||||
.filter-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(360px, 0.74fr);
|
||||
gap: 12px 64px;
|
||||
gap: 14px 56px;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
grid-template-columns: 76px minmax(0, 1fr);
|
||||
grid-template-columns: 72px minmax(0, 1fr);
|
||||
align-items: start;
|
||||
gap: 10px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.filter-row > span,
|
||||
.range-fields span {
|
||||
min-height: 26px;
|
||||
.filter-label,
|
||||
.range-fields > label > span {
|
||||
min-height: 30px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: #344054;
|
||||
color: #667085;
|
||||
font-size: 13px;
|
||||
font-weight: 900;
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -310,37 +321,72 @@ input {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 7px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.chip-list button {
|
||||
min-width: 42px;
|
||||
height: 26px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #e6ebf2;
|
||||
border-radius: 4px;
|
||||
background: #f7f9fc;
|
||||
color: #647179;
|
||||
min-width: 44px;
|
||||
height: 30px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 999px;
|
||||
background: #f4f6f9;
|
||||
color: #5b6572;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
color 0.15s ease,
|
||||
background 0.15s ease,
|
||||
border-color 0.15s ease,
|
||||
box-shadow 0.15s ease,
|
||||
transform 0.15s ease;
|
||||
}
|
||||
|
||||
.chip-list button:hover {
|
||||
color: var(--brand-dark);
|
||||
background: #fff4ea;
|
||||
border-color: #ffd7b5;
|
||||
}
|
||||
|
||||
.chip-list button.selected {
|
||||
border-color: var(--brand);
|
||||
color: var(--brand-dark);
|
||||
background: var(--brand-soft);
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, #ff8b2f, var(--brand));
|
||||
border-color: transparent;
|
||||
box-shadow: 0 6px 14px rgba(255, 107, 0, 0.22);
|
||||
}
|
||||
|
||||
.chip-list button.selected:hover {
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, #ff9a45, var(--brand-dark));
|
||||
}
|
||||
|
||||
.chip-list button:active {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
.compact-select .ant-select {
|
||||
width: min(270px, 100%);
|
||||
width: min(280px, 100%);
|
||||
}
|
||||
|
||||
.compact-select .ant-select-selector {
|
||||
min-height: 34px !important;
|
||||
border-radius: 10px !important;
|
||||
border-color: #e6ebf2 !important;
|
||||
background: #f8fafc !important;
|
||||
}
|
||||
|
||||
.compact-select .ant-select-focused .ant-select-selector {
|
||||
border-color: var(--brand) !important;
|
||||
box-shadow: 0 0 0 2px rgba(255, 107, 0, 0.12) !important;
|
||||
}
|
||||
|
||||
.advanced-panel {
|
||||
display: none;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #eef2f3;
|
||||
margin-top: 14px;
|
||||
border-top: 1px dashed #e8edf3;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.advanced-panel.open {
|
||||
@@ -354,52 +400,114 @@ input {
|
||||
gap: 16px 38px;
|
||||
}
|
||||
|
||||
.range-fields label {
|
||||
.range-fields > label {
|
||||
display: grid;
|
||||
grid-template-columns: 76px minmax(0, 1fr) minmax(0, 1fr);
|
||||
grid-template-columns: 72px minmax(0, 1fr);
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.range-inputs {
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.range-inputs em {
|
||||
color: #98a2b3;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.range-inputs .ant-input {
|
||||
border-radius: 10px;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.filter-footer {
|
||||
justify-content: flex-end;
|
||||
justify-content: center;
|
||||
min-height: 44px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.filter-footer .ant-btn {
|
||||
color: #394a4f;
|
||||
font-weight: 800;
|
||||
.advanced-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 14px;
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
background: transparent;
|
||||
color: #667085;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: color 0.15s ease, background 0.15s ease;
|
||||
}
|
||||
|
||||
.advanced-toggle:hover {
|
||||
color: var(--brand-dark);
|
||||
background: var(--brand-soft);
|
||||
}
|
||||
|
||||
.advanced-toggle .anticon {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.result-area {
|
||||
margin-top: 14px;
|
||||
padding: 18px 16px 28px;
|
||||
padding: 16px 16px 28px;
|
||||
}
|
||||
|
||||
.sort-toolbar {
|
||||
justify-content: space-between;
|
||||
gap: 18px;
|
||||
margin-bottom: 14px;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 14px;
|
||||
border-bottom: 1px solid #eef2f6;
|
||||
}
|
||||
|
||||
.sort-buttons {
|
||||
.sort-segment {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
gap: 4px;
|
||||
padding: 4px;
|
||||
border-radius: 12px;
|
||||
background: #f3f5f8;
|
||||
border: 1px solid #e8edf3;
|
||||
}
|
||||
|
||||
.sort-buttons .ant-btn {
|
||||
color: #596872;
|
||||
background: #f6f8fb;
|
||||
border-color: #dfe7ec;
|
||||
font-weight: 800;
|
||||
.sort-segment button {
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
border: none;
|
||||
border-radius: 9px;
|
||||
background: transparent;
|
||||
color: #667085;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
color 0.15s ease,
|
||||
background 0.15s ease,
|
||||
box-shadow 0.15s ease;
|
||||
}
|
||||
|
||||
.sort-buttons .ant-btn.active {
|
||||
.sort-segment button:hover {
|
||||
color: var(--text-main);
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.sort-segment button.active {
|
||||
color: var(--brand-dark);
|
||||
background: var(--brand-soft);
|
||||
border-color: var(--brand);
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 8px rgba(21, 32, 43, 0.08);
|
||||
}
|
||||
|
||||
.toolbar-actions {
|
||||
@@ -408,8 +516,14 @@ input {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.toolbar-actions .ant-btn {
|
||||
border-radius: 9px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.toolbar-actions .ant-btn-primary {
|
||||
font-weight: 900;
|
||||
box-shadow: 0 6px 14px rgba(255, 107, 0, 0.18);
|
||||
}
|
||||
|
||||
.listing-list {
|
||||
@@ -742,11 +856,19 @@ input {
|
||||
}
|
||||
|
||||
.filter-row,
|
||||
.range-fields label {
|
||||
.range-fields > label {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 7px;
|
||||
}
|
||||
|
||||
.sort-segment {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sort-segment button {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.compact-select .ant-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user