Skip to content

Commit 69bfbe6

Browse files
committed
Implementation: mockup of chatbot
1 parent 7f7731d commit 69bfbe6

6 files changed

Lines changed: 295 additions & 6 deletions

File tree

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"next": "^16.2.1",
1515
"react": "^19.2.4",
1616
"react-dom": "^19.2.4",
17-
"react-svg-inliner": "^1.2.0"
17+
"react-svg-inliner": "^1.3.0"
1818
},
1919
"devDependencies": {
2020
"@eslint/js": "^9.33.0",

public/mistral_ai_logo.svg

Lines changed: 1 addition & 0 deletions
Loading

src/app/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Menu from '../Menu.tsx';
66
import ThemeSwitcher from '../features/theme-switcher/ThemeSwitcher.tsx';
77
import ShowcaseContainer from '../features/showcase/ShowcaseContainer.tsx';
88
import ResumeeContainer from '../features/resumee/ResumeeContainer.tsx';
9+
import Chatbot from '../features/chatbot/Chatbot';
910

1011
export default function Page() {
1112
return (
@@ -168,8 +169,8 @@ export default function Page() {
168169
</a>
169170

170171
</footer>
171-
172172
</div>
173+
<Chatbot />
173174
</>
174175
)
175176
}
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
.chatbotContainer {
2+
position: fixed;
3+
bottom: 2rem;
4+
right: 2rem;
5+
z-index: 1000;
6+
font-family: 'Google Sans Text', 'Google Sans', Arial, sans-serif;
7+
}
8+
9+
.chatButton {
10+
width: 60px;
11+
height: 60px;
12+
border-radius: 50%;
13+
background-color: var(--bg-surface);
14+
border: var(--nm-border);
15+
box-shadow: 6px 6px 12px var(--nm-shadow-dark),
16+
-6px -6px 12px var(--nm-shadow-light);
17+
display: flex;
18+
align-items: center;
19+
justify-content: center;
20+
cursor: pointer;
21+
transition: all 0.3s cubic-bezier(.79, .21, .06, .81);
22+
padding: 0;
23+
margin: 0;
24+
}
25+
26+
.chatButton:hover {
27+
transform: scale(1.05);
28+
background-color: var(--bg-surface);
29+
box-shadow: 8px 8px 16px var(--nm-shadow-dark),
30+
-8px -8px 16px var(--nm-shadow-light);
31+
}
32+
33+
.chatButton:active {
34+
transform: scale(0.95);
35+
box-shadow: inset 4px 4px 8px var(--nm-shadow-dark),
36+
inset -4px -4px 8px var(--nm-shadow-light);
37+
}
38+
39+
.chatWindow {
40+
position: fixed;
41+
top: 0;
42+
right: 0;
43+
width: 400px;
44+
height: 100dvh;
45+
background-color: var(--bg-surface);
46+
border-left: var(--nm-border);
47+
box-shadow: -10px 0 20px var(--nm-shadow-dark);
48+
display: flex;
49+
flex-direction: column;
50+
overflow: hidden;
51+
animation: slideInLeft 0.3s ease-out;
52+
z-index: 1001;
53+
/* Ensure it covers everything */
54+
}
55+
56+
@keyframes slideInLeft {
57+
from {
58+
transform: translateX(100%);
59+
}
60+
61+
to {
62+
transform: translateX(0);
63+
}
64+
}
65+
66+
.chatHeader {
67+
padding: 1.5rem;
68+
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
69+
background-color: var(--bg-surface);
70+
display: flex;
71+
justify-content: space-between;
72+
align-items: center;
73+
}
74+
75+
.closeButton {
76+
background: none;
77+
border: none;
78+
color: var(--text-main);
79+
font-size: 1.5rem;
80+
cursor: pointer;
81+
padding: 0.5rem;
82+
margin: 0;
83+
width: auto;
84+
height: auto;
85+
opacity: 0.6;
86+
transition: opacity 0.2s;
87+
}
88+
89+
.closeButton:hover {
90+
opacity: 1;
91+
background-color: rgba(0, 0, 0, 0.05);
92+
}
93+
94+
.chatHeader h3 {
95+
margin: 0;
96+
font-size: 1.2rem;
97+
color: var(--text-main);
98+
}
99+
100+
.chatMessages {
101+
flex: 1;
102+
padding: 1.5rem;
103+
overflow-y: auto;
104+
display: flex;
105+
flex-direction: column;
106+
gap: 1rem;
107+
}
108+
109+
.message {
110+
padding: 0.8rem 1rem;
111+
border-radius: 12px;
112+
max-width: 85%;
113+
font-size: 0.95rem;
114+
line-height: 1.4;
115+
}
116+
117+
.aiMessage {
118+
align-self: flex-start;
119+
background-color: var(--bg-main);
120+
color: var(--text-main);
121+
border-bottom-left-radius: 4px;
122+
}
123+
124+
.introList {
125+
margin: 1.5rem 0;
126+
padding-left: 1rem;
127+
list-style-type: "- ";
128+
list-style-position: inside;
129+
font-size: 0.9rem;
130+
color: var(--text-main);
131+
}
132+
133+
.introList li {
134+
margin-bottom: 0.8rem;
135+
line-height: 1.4;
136+
}
137+
138+
.introList li {
139+
margin-bottom: 0.8rem;
140+
line-height: 1.4;
141+
}
142+
143+
.chatInputArea {
144+
padding: 1.5rem;
145+
padding-bottom: 2rem;
146+
border-top: 1px solid rgba(0, 0, 0, 0.05);
147+
display: flex;
148+
flex-direction: column;
149+
gap: 1rem;
150+
background-color: var(--bg-surface);
151+
}
152+
153+
.textarea {
154+
width: 100%;
155+
min-height: 100px;
156+
padding: 1rem;
157+
border-radius: 12px;
158+
border: 1px solid rgba(0, 0, 0, 0.1);
159+
background-color: var(--bg-main);
160+
color: var(--text-main);
161+
resize: none;
162+
font-size: 1rem;
163+
transition: border-color 0.2s;
164+
}
165+
166+
.textarea:focus {
167+
outline: none;
168+
border-color: #ff8c00;
169+
/* Mistral orange */
170+
}
171+
172+
.sendButton {
173+
align-self: flex-end;
174+
background-color: #ff8c00;
175+
color: white;
176+
border: none;
177+
padding: 0.8rem 1.5rem;
178+
border-radius: 10px;
179+
font-weight: 600;
180+
cursor: pointer;
181+
transition: all 0.2s;
182+
width: auto;
183+
height: auto;
184+
margin: 0;
185+
}
186+
187+
.sendButton:hover {
188+
background-color: #e67e00;
189+
transform: translateY(-1px);
190+
}
191+
192+
.sendButton:active {
193+
transform: translateY(0);
194+
}
195+
196+
.mistralLogo {
197+
width: 32px;
198+
height: 32px;
199+
}
200+
201+
.mistralLogo path {
202+
fill: #ff8c00;
203+
}
204+
205+
@media (max-width: 600px) {
206+
.chatWindow {
207+
width: 100dvw;
208+
height: 100dvh;
209+
border-left: none;
210+
box-shadow: none;
211+
}
212+
213+
.chatHeader {
214+
padding: 1rem;
215+
}
216+
}

src/features/chatbot/Chatbot.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React, { useState } from 'react';
2+
import { SvgInline } from 'react-svg-inliner';
3+
import styles from './Chatbot.module.css';
4+
5+
export const Chatbot: React.FC = () => {
6+
const [isOpen, setIsOpen] = useState(false);
7+
8+
const toggleChat = () => {
9+
setIsOpen(!isOpen);
10+
};
11+
12+
return (
13+
<div className={styles.chatbotContainer}>
14+
{/* 1) Button open chat */}
15+
<button
16+
className={styles.chatButton}
17+
onClick={toggleChat}
18+
aria-label={isOpen ? "Close chat" : "Open chat"}
19+
id="chatbot-trigger"
20+
>
21+
<SvgInline
22+
src="/mistral_ai_logo.svg"
23+
className={styles.mistralLogo}
24+
title="Mistral AI logo"
25+
id="mistralLogo"
26+
title="Mistral AI logo"
27+
/>
28+
</button>
29+
30+
{/* 2) Div that appears when it is clicked */}
31+
{isOpen && (
32+
<div className={styles.chatWindow}>
33+
<div className={styles.chatHeader}>
34+
<h3>Jorge's personal AI Assistant</h3>
35+
<button className={styles.closeButton} onClick={toggleChat} aria-label="Close chat">
36+
×
37+
</button>
38+
</div>
39+
40+
<div className={styles.chatMessages}>
41+
{/* 3) First automatic ai message */}
42+
<div className={`${styles.message} ${styles.aiMessage}`}>
43+
<p>Hello! 🤖 I'm Jorge's personal assistant, powered by Mistral AI. I'm here to help you explore his work and background.</p>
44+
<p>I can help you with:</p>
45+
<ul className={styles.introList}>
46+
<li><strong>More about Jorge</strong>: Skills, experience, and interests.</li>
47+
<li><strong>Explain this repo</strong>: Architecture and technologies.</li>
48+
<li><strong>Introduce myself</strong>: My role and how I'm integrated here.</li>
49+
</ul>
50+
</div>
51+
</div>
52+
53+
<div className={styles.chatInputArea}>
54+
{/* 4) textarea so the user can write */}
55+
<textarea
56+
className={styles.textarea}
57+
placeholder="Type your message..."
58+
aria-label="New message"
59+
/>
60+
{/* 5) Button of send message */}
61+
<button className={styles.sendButton}>
62+
Send
63+
</button>
64+
</div>
65+
</div>
66+
)}
67+
</div>
68+
);
69+
};
70+
71+
export default Chatbot;

0 commit comments

Comments
 (0)