Skip to content

Commit 5c435e7

Browse files
dachi-devclaude
andcommitted
Add auto-scrolling suggestion chips and company logo marquee
- Suggestion chips now scroll right-to-left with seamless loop - Added "Previously at" marquee with actual company logos (Socket, Nodies, AWS, CGI, Pocket Network) - Logos use external image URLs with hover effects Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1a93b3f commit 5c435e7

3 files changed

Lines changed: 154 additions & 33 deletions

File tree

src/App.jsx

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import ChatMessage from "./components/ChatMessage";
55
import ChatInput from "./components/ChatInput";
66
import TypingIndicator from "./components/TypingIndicator";
77
import { sendMessage } from "./api";
8+
import LogoMarquee from "./components/LogoMarquee";
89

910
const SUGGESTIONS = [
1011
"Give me a quick summary of Tommy",
@@ -99,19 +100,24 @@ export default function App() {
99100
</div>
100101
</header>
101102

102-
{/* Suggestion chips */}
103+
{/* Company logos */}
104+
{!hasMessages && <LogoMarquee />}
105+
106+
{/* Suggestion chips — auto-scrolling */}
103107
{!hasMessages && (
104-
<div className="suggestions">
105-
{SUGGESTIONS.map((s) => (
106-
<button
107-
key={s}
108-
className="suggestion-chip"
109-
onClick={() => handleSuggestion(s)}
110-
disabled={loading}
111-
>
112-
{s}
113-
</button>
114-
))}
108+
<div className="suggestions-marquee">
109+
<div className="suggestions-track">
110+
{[...SUGGESTIONS, ...SUGGESTIONS].map((s, i) => (
111+
<button
112+
key={i}
113+
className="suggestion-chip"
114+
onClick={() => handleSuggestion(s)}
115+
disabled={loading}
116+
>
117+
{s}
118+
</button>
119+
))}
120+
</div>
115121
</div>
116122
)}
117123

src/components/LogoMarquee.jsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
export default function LogoMarquee() {
2+
const companies = [
3+
{ name: "Socket", logo: "https://socket.dev/_next/image?url=%2Fimages%2Flogo-280x80.png&w=256&q=75" },
4+
{ name: "Nodies", logo: "https://www.nodies.app/_next/image?url=%2Fimages%2Fnodies-logo-dark.png&w=256&q=75" },
5+
{ name: "Amazon Web Services", logo: "https://upload.wikimedia.org/wikipedia/commons/9/93/Amazon_Web_Services_Logo.svg" },
6+
{ name: "CGI Federal", logo: "https://upload.wikimedia.org/wikipedia/commons/3/32/CGI_logo.svg" },
7+
{ name: "Pocket Network", logo: "https://pocket.network/wp-content/uploads/2025/01/logo-white.png" },
8+
];
9+
10+
// Double the list for seamless loop
11+
const items = [...companies, ...companies];
12+
13+
return (
14+
<div className="logo-marquee-wrapper">
15+
<span className="marquee-label">Previously at</span>
16+
<div className="logo-marquee">
17+
<div className="logo-marquee-track">
18+
{items.map((company, i) => (
19+
<div key={i} className="logo-marquee-item">
20+
<img
21+
src={company.logo}
22+
alt={company.name}
23+
className="logo-marquee-img"
24+
loading="lazy"
25+
/>
26+
</div>
27+
))}
28+
</div>
29+
</div>
30+
</div>
31+
);
32+
}

src/index.css

Lines changed: 104 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -247,16 +247,92 @@ body {
247247
to { opacity: 1; transform: translateY(0); }
248248
}
249249

250-
/* ======================== SUGGESTION CHIPS ======================== */
250+
/* ======================== LOGO MARQUEE ======================== */
251+
252+
.logo-marquee-wrapper {
253+
flex-shrink: 0;
254+
padding: 8px 0 4px;
255+
text-align: center;
256+
animation: fadeIn 0.6s ease-out 0.35s both;
257+
overflow: hidden;
258+
}
259+
260+
.marquee-label {
261+
display: block;
262+
font-size: 10px;
263+
font-weight: 500;
264+
color: var(--text-muted);
265+
text-transform: uppercase;
266+
letter-spacing: 0.08em;
267+
margin-bottom: 10px;
268+
opacity: 0.6;
269+
}
270+
271+
.logo-marquee {
272+
overflow: hidden;
273+
mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);
274+
-webkit-mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);
275+
}
251276

252-
.suggestions {
277+
.logo-marquee-track {
253278
display: flex;
254-
flex-wrap: wrap;
279+
gap: 32px;
280+
width: max-content;
281+
animation: marqueeScroll 20s linear infinite;
282+
}
283+
284+
.logo-marquee-item {
285+
display: flex;
286+
align-items: center;
255287
gap: 8px;
256-
justify-content: center;
257-
padding: 12px 0 8px;
258288
flex-shrink: 0;
289+
}
290+
291+
.logo-marquee-img {
292+
height: 24px;
293+
max-width: 120px;
294+
object-fit: contain;
295+
filter: brightness(0.9) grayscale(0.3);
296+
opacity: 0.8;
297+
transition: opacity 0.3s, filter 0.3s;
298+
}
299+
300+
.logo-marquee-item:hover .logo-marquee-img {
301+
opacity: 1;
302+
filter: brightness(1) grayscale(0);
303+
}
304+
305+
@keyframes marqueeScroll {
306+
0% { transform: translateX(0); }
307+
100% { transform: translateX(-50%); }
308+
}
309+
310+
/* ======================== SUGGESTION CHIPS ======================== */
311+
312+
.suggestions-marquee {
313+
flex-shrink: 0;
314+
overflow: hidden;
315+
padding: 10px 0 6px;
259316
animation: fadeIn 0.6s ease-out 0.4s both;
317+
mask-image: linear-gradient(to right, transparent, black 5%, black 95%, transparent);
318+
-webkit-mask-image: linear-gradient(to right, transparent, black 5%, black 95%, transparent);
319+
}
320+
321+
.suggestions-track {
322+
display: flex;
323+
gap: 10px;
324+
width: max-content;
325+
animation: suggestionsScroll 25s linear infinite;
326+
}
327+
328+
.suggestions-track:hover,
329+
.suggestions-track:active {
330+
animation-play-state: paused;
331+
}
332+
333+
@keyframes suggestionsScroll {
334+
0% { transform: translateX(0); }
335+
100% { transform: translateX(-50%); }
260336
}
261337

262338
@keyframes fadeIn {
@@ -741,29 +817,36 @@ body {
741817
height: 12px;
742818
}
743819

744-
/* Horizontal scroll chips on mobile like native apps */
745-
.suggestions {
746-
flex-wrap: nowrap;
747-
justify-content: flex-start;
748-
gap: 8px;
749-
padding: 8px 0 6px;
750-
overflow-x: auto;
751-
-webkit-overflow-scrolling: touch;
752-
scrollbar-width: none;
753-
-ms-overflow-style: none;
754-
scroll-snap-type: x proximity;
755-
scroll-padding: 0 12px;
820+
.logo-marquee-track {
821+
gap: 24px;
822+
animation-duration: 15s;
756823
}
757824

758-
.suggestions::-webkit-scrollbar {
759-
display: none;
825+
.logo-marquee-img {
826+
height: 20px;
827+
max-width: 100px;
828+
}
829+
830+
.logo-marquee-name {
831+
font-size: 12px;
832+
}
833+
834+
.marquee-label {
835+
font-size: 9px;
836+
margin-bottom: 8px;
837+
}
838+
839+
.suggestions-marquee {
840+
padding: 6px 0 4px;
841+
}
842+
843+
.suggestions-track {
844+
animation-duration: 20s;
760845
}
761846

762847
.suggestion-chip {
763848
font-size: 13px;
764849
padding: 10px 16px;
765-
flex-shrink: 0;
766-
scroll-snap-align: start;
767850
}
768851

769852
/* Remove hover effects on touch — use active states instead */

0 commit comments

Comments
 (0)