Skip to content

Commit 3311cc6

Browse files
committed
feat: Add label filtering to IssueBacklog panel
1 parent aa98992 commit 3311cc6

1 file changed

Lines changed: 46 additions & 2 deletions

File tree

frontend/src/components/IssueBacklog.tsx

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { ListTodo } from 'lucide-react';
1+
import { useState } from 'react';
2+
import { ListTodo, X } from 'lucide-react';
23
import { OpenIssue } from '../types/campaign';
34
import { EmptyState } from './EmptyState';
45

@@ -8,6 +9,8 @@ interface IssueBacklogProps {
89
}
910

1011
export function IssueBacklog({ issues, isLoading = false }: IssueBacklogProps) {
12+
const [activeLabels, setActiveLabels] = useState<string[]>([]);
13+
1114
if (isLoading) {
1215
return (
1316
<section className="card">
@@ -30,15 +33,56 @@ export function IssueBacklog({ issues, isLoading = false }: IssueBacklogProps) {
3033
);
3134
}
3235

36+
const allLabels = Array.from(new Set(issues.flatMap(issue => issue.labels))).sort();
37+
38+
const toggleLabel = (label: string) => {
39+
setActiveLabels(prev =>
40+
prev.includes(label) ? prev.filter(l => l !== label) : [...prev, label]
41+
);
42+
};
43+
44+
const filteredIssues = activeLabels.length === 0
45+
? issues
46+
: issues.filter(issue => issue.labels.some(label => activeLabels.includes(label)));
47+
3348
return (
3449
<section className="card">
3550
<div className="section-heading">
3651
<h2>Contribution backlog</h2>
3752
<p className="muted">Ready-to-open issue ideas for your public repo after you push it.</p>
3853
</div>
3954

55+
{allLabels.length > 0 && (
56+
<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap', marginBottom: '16px', alignItems: 'center' }}>
57+
{allLabels.map(label => (
58+
<button
59+
key={label}
60+
onClick={() => toggleLabel(label)}
61+
className={`chip ${activeLabels.includes(label) ? 'active' : ''}`}
62+
style={{
63+
cursor: 'pointer',
64+
border: activeLabels.includes(label) ? '2px solid var(--primary-accent)' : '1px solid var(--border-color)',
65+
backgroundColor: activeLabels.includes(label) ? 'var(--primary-subtle)' : 'transparent',
66+
outline: 'none'
67+
}}
68+
>
69+
{label}
70+
</button>
71+
))}
72+
{activeLabels.length > 0 && (
73+
<button
74+
onClick={() => setActiveLabels([])}
75+
className="control-button"
76+
style={{ display: 'flex', alignItems: 'center', gap: '4px', padding: '4px 8px', fontSize: '0.85rem' }}
77+
>
78+
<X size={14} /> Clear all
79+
</button>
80+
)}
81+
</div>
82+
)}
83+
4084
<div className="issue-list">
41-
{issues.map((issue) => (
85+
{filteredIssues.map((issue) => (
4286
<article key={issue.id} className="issue-item">
4387
<div className="issue-topline">
4488
<strong>

0 commit comments

Comments
 (0)