Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/components/SearchBar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
export default function SearchBar({ searchTerm, onSearchChange, selectedDifficulty, onDifficultyChange }) {
const difficulties = ['all', 'beginner', 'intermediate', 'advanced']

return (
<div style={{ marginBottom: '24px' }}>
<input
type="text"
placeholder="Search resources..."
value={searchTerm}
onChange={(e) => onSearchChange(e.target.value)}
style={{
width: '100%',
padding: '10px 14px',
fontSize: '16px',
borderRadius: '8px',
border: '1px solid #ccc',
marginBottom: '12px',
boxSizing: 'border-box',
}}
/>
<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
{difficulties.map((level) => (
<button
key={level}
onClick={() => onDifficultyChange(level)}
style={{
padding: '6px 16px',
borderRadius: '20px',
border: '1px solid #ccc',
background: selectedDifficulty === level ? '#6c47ff' : '#fff',
color: selectedDifficulty === level ? '#fff' : '#333',
cursor: 'pointer',
fontWeight: selectedDifficulty === level ? 'bold' : 'normal',
}}
>
{level.charAt(0).toUpperCase() + level.slice(1)}
</button>
))}
</div>
</div>
)
}
107 changes: 62 additions & 45 deletions src/components/Storyboards.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { useState } from 'react'
import { storyboards } from '../data/storyboards'
import SearchBar from './SearchBar'

const difficultyColors = {
beginner: { bg: 'rgba(123,92,240,0.15)', color: '#A78BFA' },
Expand All @@ -7,6 +9,18 @@ const difficultyColors = {
}

export default function Storyboards() {
const [searchTerm, setSearchTerm] = useState('')
const [selectedDifficulty, setSelectedDifficulty] = useState('all')

const filtered = storyboards.filter((s) => {
const matchesSearch =
s.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
s.description.toLowerCase().includes(searchTerm.toLowerCase())
const matchesDifficulty =
selectedDifficulty === 'all' || s.difficulty === selectedDifficulty
return matchesSearch && matchesDifficulty
})

return (
<section id="concepts" className="py-24 px-16" style={{ background: 'var(--ink)' }}>
<div className="flex justify-between items-end mb-12">
Expand All @@ -18,59 +32,62 @@ export default function Storyboards() {
Big ideas, made visual
</h2>
</div>
<a
href="#"
className="btn-secondary hidden md:inline-flex"
style={{ color: 'rgba(255,255,255,0.6)', borderColor: 'rgba(255,255,255,0.15)' }}
>
<a href="#" className="btn-secondary hidden md:inline-flex" style={{ color: 'rgba(255,255,255,0.6)', borderColor: 'rgba(255,255,255,0.15)' }}>
View all concepts →
</a>
</div>

<div className="grid grid-cols-1 md:grid-cols-3 gap-5">
{storyboards.slice(0, 3).map((s) => (
<div
key={s.id}
className="rounded-2xl overflow-hidden cursor-pointer transition-all duration-200"
style={{ border: '1px solid rgba(255,255,255,0.08)' }}
onMouseEnter={e => {
e.currentTarget.style.transform = 'translateY(-4px)'
e.currentTarget.style.borderColor = 'rgba(255,255,255,0.2)'
}}
onMouseLeave={e => {
e.currentTarget.style.transform = 'translateY(0)'
e.currentTarget.style.borderColor = 'rgba(255,255,255,0.08)'
}}
>
<SearchBar
searchTerm={searchTerm}
onSearchChange={setSearchTerm}
selectedDifficulty={selectedDifficulty}
onDifficultyChange={setSelectedDifficulty}
/>

{filtered.length === 0 ? (
<div style={{ color: 'rgba(255,255,255,0.4)', textAlign: 'center', marginTop: '48px', fontSize: '18px' }}>
No results found. Try a different search or filter.
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-3 gap-5">
{filtered.map((s) => (
<div
className="h-44 flex items-center justify-center text-6xl relative"
style={{ background: s.gradient }}
key={s.id}
className="rounded-2xl overflow-hidden cursor-pointer transition-all duration-200"
style={{ border: '1px solid rgba(255,255,255,0.08)' }}
onMouseEnter={(e) => {
e.currentTarget.style.transform = 'translateY(-4px)'
e.currentTarget.style.borderColor = 'rgba(255,255,255,0.2)'
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = 'translateY(0)'
e.currentTarget.style.borderColor = 'rgba(255,255,255,0.08)'
}}
>
{s.emoji}
<div
className="absolute bottom-3 left-3 text-xs font-semibold uppercase tracking-widest"
style={{ color: 'rgba(255,255,255,0.4)' }}
>
Visual Explainer
</div>
</div>
<div className="p-5" style={{ background: 'rgba(255,255,255,0.04)' }}>
<div className="font-display font-bold text-base mb-1.5" style={{ color: 'white' }}>
{s.title}
<div className="h-44 flex items-center justify-center text-6xl relative" style={{ background: s.gradient }}>
{s.emoji}
<div className="absolute bottom-3 left-3 text-xs font-semibold uppercase tracking-widest" style={{ color: 'rgba(255,255,255,0.4)' }}>
Visual Explainer
</div>
</div>
<div className="text-sm leading-relaxed font-light" style={{ color: 'rgba(255,255,255,0.45)' }}>
{s.description}
<div className="p-5" style={{ background: 'rgba(255,255,255,0.04)' }}>
<div className="font-display font-bold text-base mb-1.5" style={{ color: 'white' }}>
{s.title}
</div>
<div className="text-sm leading-relaxed font-light" style={{ color: 'rgba(255,255,255,0.45)' }}>
{s.description}
</div>
<span
className="inline-block mt-3 text-xs font-semibold px-2.5 py-0.5 rounded-full uppercase tracking-wider"
style={difficultyColors[s.difficulty]}
>
{s.difficulty}
</span>
</div>
<span
className="inline-block mt-3 text-xs font-semibold px-2.5 py-0.5 rounded-full uppercase tracking-wider"
style={difficultyColors[s.difficulty]}
>
{s.difficulty}
</span>
</div>
</div>
))}
</div>
))}
</div>
)}
</section>
)
}
}