feat(web): show initial letter only on first sound of each group

Instead of displaying the letter (A, B, C...) on every sound card,
only show it on the first card that starts with that letter. Makes
the grid much cleaner and easier to scan.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Bot 2026-03-01 15:28:53 +01:00
parent da0ae2b9a6
commit 5f0b06550e

View file

@ -282,6 +282,16 @@ export default function App() {
return m; return m;
}, [visibleFolders]); }, [visibleFolders]);
const firstOfInitial = useMemo(() => {
const seen = new Set<string>();
const result = new Set<number>();
displaySounds.forEach((s, idx) => {
const ch = s.name.charAt(0).toUpperCase();
if (!seen.has(ch)) { seen.add(ch); result.add(idx); }
});
return result;
}, [displaySounds]);
const channelsByGuild = useMemo(() => { const channelsByGuild = useMemo(() => {
const groups: Record<string, VoiceChannelInfo[]> = {}; const groups: Record<string, VoiceChannelInfo[]> = {};
channels.forEach(c => { channels.forEach(c => {
@ -503,12 +513,13 @@ export default function App() {
const isPlaying = lastPlayed === s.name; const isPlaying = lastPlayed === s.name;
const isNew = s.isRecent || s.badges?.includes('new'); const isNew = s.isRecent || s.badges?.includes('new');
const initial = s.name.charAt(0).toUpperCase(); const initial = s.name.charAt(0).toUpperCase();
const showInitial = firstOfInitial.has(idx);
const folderColor = s.folder ? (folderColorMap[s.folder] || 'var(--accent)') : 'var(--accent)'; const folderColor = s.folder ? (folderColorMap[s.folder] || 'var(--accent)') : 'var(--accent)';
return ( return (
<div <div
key={key} key={key}
className={`sound-card ${isPlaying ? 'playing' : ''}`} className={`sound-card ${isPlaying ? 'playing' : ''} ${showInitial ? 'has-initial' : ''}`}
style={{ animationDelay: `${Math.min(idx * 20, 400)}ms` }} style={{ animationDelay: `${Math.min(idx * 20, 400)}ms` }}
onClick={e => { onClick={e => {
const card = e.currentTarget; const card = e.currentTarget;
@ -541,7 +552,7 @@ export default function App() {
> >
<span className="material-icons fav-icon">{isFav ? 'star' : 'star_border'}</span> <span className="material-icons fav-icon">{isFav ? 'star' : 'star_border'}</span>
</span> </span>
<span className="sound-emoji" style={{ color: folderColor }}>{initial}</span> {showInitial && <span className="sound-emoji" style={{ color: folderColor }}>{initial}</span>}
<span className="sound-name">{s.name}</span> <span className="sound-name">{s.name}</span>
{s.folder && <span className="sound-duration">{s.folder}</span>} {s.folder && <span className="sound-duration">{s.folder}</span>}
<div className="playing-indicator"> <div className="playing-indicator">