diff --git a/chat-page/index.html b/chat-page/index.html
new file mode 100644
index 0000000..50d7e5d
--- /dev/null
+++ b/chat-page/index.html
@@ -0,0 +1,79 @@
+
+
+
+
+
+ Halaman Chat
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Hai, ada kabar terbaru?
+
+
10:00
+
+
+
+
+
+ Iya, proyek baru sudah selesai!
+
+
10:01
+
+
+
+
+
+
+
+
+
+
diff --git a/chat-page/script.js b/chat-page/script.js
new file mode 100644
index 0000000..26a17fa
--- /dev/null
+++ b/chat-page/script.js
@@ -0,0 +1,126 @@
+// Fungsi untuk menambahkan pesan baru ke area chat
+function addMessage(content, isSent) {
+ const chatArea = document.querySelector('.chat-area');
+
+ // Buat elemen pesan
+ const message = document.createElement('div');
+ message.className = `message ${isSent ? 'sent' : 'received'}`;
+
+ // Tambahkan konten pesan
+ const messageContent = document.createElement('div');
+ messageContent.className = 'message-content';
+ messageContent.textContent = content;
+
+ // Tambahkan waktu pesan
+ const now = new Date();
+ const time = now.getHours().toString().padStart(2, '0') + ':' +
+ now.getMinutes().toString().padStart(2, '0');
+
+ const messageTime = document.createElement('div');
+ messageTime.className = 'message-time';
+ messageTime.textContent = time;
+
+ // Gabungkan semua elemen
+ message.appendChild(messageContent);
+ message.appendChild(messageTime);
+
+ // Tambahkan ke area chat dengan animasi
+ chatArea.appendChild(message);
+
+ // Scroll ke bawah untuk melihat pesan terbaru
+ chatArea.scrollTop = chatArea.scrollHeight;
+}
+
+// Fungsi untuk menampilkan indikator mengetik
+function showTypingIndicator() {
+ const chatArea = document.querySelector('.chat-area');
+ const typingIndicator = document.createElement('div');
+ typingIndicator.className = 'typing-indicator';
+ typingIndicator.innerHTML = `
+
+
+
+
+
+ `;
+ chatArea.appendChild(typingIndicator);
+ chatArea.scrollTop = chatArea.scrollHeight;
+ return typingIndicator;
+}
+
+// Fungsi untuk menyembunyikan indikator mengetik
+function hideTypingIndicator(indicator) {
+ if (indicator) {
+ indicator.remove();
+ }
+}
+
+// Setup Intersection Observer untuk efek fade-out
+function setupMessageObserver() {
+ const observer = new IntersectionObserver((entries) => {
+ entries.forEach(entry => {
+ if (!entry.isIntersecting) {
+ // Ketika elemen keluar dari viewport
+ entry.target.style.opacity = '0.3';
+ entry.target.style.transform = 'translateY(10px)';
+ } else {
+ // Ketika elemen masuk ke viewport
+ entry.target.style.opacity = '1';
+ entry.target.style.transform = 'translateY(0)';
+ }
+ });
+ }, {
+ threshold: 0.1 // Trigger ketika 10% elemen masih terlihat
+ });
+
+ // Terapkan observer ke semua pesan
+ document.querySelectorAll('.message').forEach(message => {
+ observer.observe(message);
+ });
+}
+
+// Fungsi untuk mengirim pesan
+function sendMessage() {
+ const input = document.querySelector('.message-input');
+ const message = input.value.trim();
+
+ if (message) {
+ addMessage(message, true);
+ input.value = '';
+
+ // Simulasikan balasan otomatis setelah 2 detik
+ setTimeout(() => {
+ const typingIndicator = showTypingIndicator();
+
+ // Setelah 3 detik, sembunyikan indikator dan tampilkan balasan
+ setTimeout(() => {
+ hideTypingIndicator(typingIndicator);
+ addMessage('Pesan Anda sudah saya terima. Terima kasih!', false);
+ }, 3000);
+ }, 2000);
+ }
+}
+
+// Event listener untuk tombol kirim
+document.querySelector('.send-btn').addEventListener('click', sendMessage);
+
+// Event listener untuk tombol Enter
+document.querySelector('.message-input').addEventListener('keypress', (e) => {
+ if (e.key === 'Enter') {
+ sendMessage();
+ }
+});
+
+// Inisialisasi chat setelah DOM selesai dimuat
+document.addEventListener('DOMContentLoaded', () => {
+ // Tampilkan indikator mengetik saat halaman pertama dimuat
+ const initialTyping = showTypingIndicator();
+
+ // Setelah 3 detik, tampilkan pesan sapaan
+ setTimeout(() => {
+ hideTypingIndicator(initialTyping);
+ addMessage('Hai, ada yang bisa saya bantu?', false);
+ }, 3000);
+
+ setupMessageObserver();
+});
diff --git a/chat-page/style.css b/chat-page/style.css
new file mode 100644
index 0000000..8b31a1d
--- /dev/null
+++ b/chat-page/style.css
@@ -0,0 +1,412 @@
+/* Reset CSS */
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+}
+
+body {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 100vh;
+ background:
+ linear-gradient(135deg, #6a11cb 0%, #2575fc 100%),
+ repeating-linear-gradient(45deg, rgba(255,255,255,0.05) 0px, rgba(255,255,255,0.05) 10px, transparent 10px, transparent 20px);
+ padding: 20px;
+}
+
+/* Chat container styling */
+.chat-container {
+ background: rgba(255, 255, 255, 0.92);
+ backdrop-filter: blur(12px);
+ border-radius: 20px;
+ box-shadow:
+ 0 20px 50px rgba(0, 0, 0, 0.3),
+ 0 0 0 2px rgba(255, 255, 255, 0.1) inset,
+ 0 10px 30px rgba(0, 0, 0, 0.1) inset;
+ width: 100%;
+ max-width: 800px;
+ height: 90vh;
+ max-height: 800px;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ position: relative;
+}
+
+/* Glass effect header styling */
+.chat-header {
+ padding: 15px 20px;
+ background: rgba(255, 255, 255, 0.25);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.3);
+ display: flex;
+ align-items: center;
+ border-radius: 20px 20px 0 0;
+ backdrop-filter: blur(12px);
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
+ position: sticky;
+ top: 0;
+ z-index: 10;
+}
+
+/* Enhanced glass effect for both header and input area */
+.chat-header, .input-area {
+ background: rgba(255, 255, 255, 0.18);
+ backdrop-filter: blur(15px);
+ -webkit-backdrop-filter: blur(15px);
+ border: 1px solid rgba(255, 255, 255, 0.25);
+}
+
+.user-info {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+}
+
+.avatar {
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ background: linear-gradient(to right, #6a11cb, #2575fc);
+ color: white;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 20px;
+ font-weight: bold;
+}
+
+/* Floating circles background */
+.floating-circles {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ z-index: -1;
+}
+
+.floating-circles li {
+ position: absolute;
+ display: block;
+ list-style: none;
+ width: 20px;
+ height: 20px;
+ background: rgba(106, 17, 203, 0.15);
+ animation: floating 25s linear infinite;
+ bottom: -150px;
+ border-radius: 50%;
+}
+
+.floating-circles li:nth-child(1) {
+ left: 25%;
+ width: 80px;
+ height: 80px;
+ animation-delay: 0s;
+}
+
+.floating-circles li:nth-child(2) {
+ left: 10%;
+ width: 20px;
+ height: 20px;
+ animation-delay: 2s;
+ animation-duration: 12s;
+}
+
+.floating-circles li:nth-child(3) {
+ left: 70%;
+ width: 20px;
+ height: 20px;
+ animation-delay: 4s;
+}
+
+.floating-circles li:nth-child(4) {
+ left: 40%;
+ width: 60px;
+ height: 60px;
+ animation-delay: 0s;
+ animation-duration: 18s;
+}
+
+.floating-circles li:nth-child(5) {
+ left: 65%;
+ width: 20px;
+ height: 20px;
+ animation-delay: 0s;
+}
+
+.floating-circles li:nth-child(6) {
+ left: 75%;
+ width: 110px;
+ height: 110px;
+ animation-delay: 3s;
+}
+
+.floating-circles li:nth-child(7) {
+ left: 35%;
+ width: 150px;
+ height: 150px;
+ animation-delay: 7s;
+}
+
+.floating-circles li:nth-child(8) {
+ left: 50%;
+ width: 25px;
+ height: 25px;
+ animation-delay: 15s;
+ animation-duration: 45s;
+}
+
+.floating-circles li:nth-child(9) {
+ left: 20%;
+ width: 15px;
+ height: 15px;
+ animation-delay: 2s;
+ animation-duration: 35s;
+}
+
+.floating-circles li:nth-child(10) {
+ left: 85%;
+ width: 150px;
+ height: 150px;
+ animation-delay: 0s;
+ animation-duration: 11s;
+}
+
+/* Floating animation */
+@keyframes floating {
+ 0% {
+ transform: translateY(0) rotate(0deg);
+ opacity: 0.7;
+ border-radius: 50%;
+ }
+ 100% {
+ transform: translateY(-1000px) rotate(720deg);
+ opacity: 0;
+ border-radius: 50%;
+ }
+}
+
+/* Chat area styling */
+.chat-area {
+ flex-grow: 1;
+ padding: 20px;
+ overflow-y: auto;
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+ position: relative;
+}
+
+.message {
+ max-width: 70%;
+ padding: 12px 16px;
+ border-radius: 18px;
+ position: relative;
+ animation: fadeIn 0.3s ease;
+ transition: opacity 0.5s ease, transform 0.5s ease;
+}
+
+.message.received {
+ align-self: flex-start;
+ background: #f0f0f0;
+ border-bottom-left-radius: 4px;
+}
+
+.message.sent {
+ align-self: flex-end;
+ background: linear-gradient(to right, #6a11cb, #2575fc);
+ color: white;
+ border-bottom-right-radius: 4px;
+}
+
+.message-content {
+ word-wrap: break-word;
+ line-height: 1.4;
+}
+
+.message-time {
+ font-size: 0.7rem;
+ text-align: right;
+ margin-top: 5px;
+ opacity: 0.7;
+}
+
+.message.sent .message-time {
+ color: rgba(255, 255, 255, 0.7);
+}
+
+.message.received .message-time {
+ color: rgba(0, 0, 0, 0.5);
+}
+
+/* Input area styling with animation and glass effect */
+.input-area {
+ display: flex;
+ padding: 15px;
+ border-top: 1px solid rgba(0, 0, 0, 0.05);
+ align-items: center;
+ gap: 10px;
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
+ position: sticky;
+ bottom: 0;
+ z-index: 10;
+}
+
+.input-area:focus-within {
+ transform: translateY(-5px);
+ box-shadow: 0 -5px 20px rgba(106, 17, 203, 0.2);
+}
+
+.icon-btn {
+ background: none;
+ border: none;
+ cursor: pointer;
+ width: 40px;
+ height: 40px;
+ border-radius: 50%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ transition: background 0.3s ease;
+}
+
+.icon-btn:hover {
+ background: rgba(106, 17, 203, 0.1);
+}
+
+.icon-btn svg {
+ width: 24px;
+ height: 24px;
+ fill: #6a11cb;
+}
+
+/* Efek untuk pesan saat keluar dari viewport */
+.message:not(:hover) {
+ transition: opacity 0.5s ease, transform 0.5s ease;
+}
+
+.message-input {
+ flex-grow: 1;
+ padding: 12px 15px;
+ border: 1px solid #ddd;
+ border-radius: 25px;
+ background: white;
+ font-size: 16px;
+ transition: all 0.3s ease;
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05) inset;
+}
+
+.message-input:focus {
+ border-color: #6a11cb;
+ box-shadow: 0 0 0 3px rgba(106, 17, 203, 0.2);
+ outline: none;
+}
+
+.send-btn {
+ background: linear-gradient(to right, #6a11cb, #2575fc);
+ border: none;
+ border-radius: 50%;
+ width: 45px;
+ height: 45px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ box-shadow: 0 5px 15px rgba(37, 117, 252, 0.4);
+}
+
+.send-btn:active {
+ transform: scale(0.95);
+}
+
+.send-btn:hover {
+ transform: scale(1.05);
+ box-shadow: 0 8px 20px rgba(37, 117, 252, 0.6);
+}
+
+.send-btn svg {
+ width: 24px;
+ height: 24px;
+ fill: white;
+}
+
+/* Animations */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: translateY(10px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+/* Typing animation */
+@keyframes wave {
+ 0%, 60%, 100% {
+ transform: scaleY(0.4);
+ }
+ 30% {
+ transform: scaleY(1);
+ }
+}
+
+/* Typing indicator */
+.typing-indicator {
+ display: flex;
+ align-self: flex-start;
+ background: #f0f0f0;
+ padding: 10px 15px;
+ border-radius: 18px;
+ margin-bottom: 15px;
+}
+
+.typing-dots {
+ display: flex;
+ align-items: center;
+ height: 17px;
+}
+
+.typing-dots span {
+ display: block;
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background: #6a11cb;
+ margin: 0 2px;
+}
+
+.typing-dots span:nth-child(1) {
+ animation: wave 1.2s infinite;
+}
+
+.typing-dots span:nth-child(2) {
+ animation: wave 1.2s infinite 0.2s;
+}
+
+.typing-dots span:nth-child(3) {
+ animation: wave 1.2s infinite 0.4s;
+}
+
+/* Responsive design */
+@media (max-width: 768px) {
+ .chat-container {
+ height: 100vh;
+ max-height: none;
+ border-radius: 0;
+ }
+
+ .message {
+ max-width: 85%;
+ }
+
+ body {
+ padding: 0;
+ }
+}