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
102 changes: 88 additions & 14 deletions client/src/components/TextContainer/TextContainer.css
Original file line number Diff line number Diff line change
@@ -1,33 +1,107 @@
/* ===========================
TextContainer Styles
Updated for better clarity,
modern look, and accessibility
=========================== */

.textContainer {
display: flex;
flex-direction: column;
margin-left: 100px;
color: white;
height: 60%;
justify-content: space-between;
justify-content: flex-start;
align-items: center;
padding: 1rem;
font-family: 'Arial', sans-serif;
color: #333;
text-align: center;
background-color: #fafafa;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
}

/* Intro Section */
.intro h1 {
font-size: 2rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: #111;
}

.intro h2 {
font-size: 1.1rem;
margin-bottom: 0.5rem;
color: #555;
}

/* Users Section */
.usersSection {
margin-top: 2rem;
width: 100%;
max-width: 320px;
}

/* Active User List Container */
.activeContainer {
display: flex;
align-items: center;
margin-bottom: 50%;
flex-direction: column;
gap: 0.6rem;
max-height: 220px;
overflow-y: auto;
padding: 0.7rem;
border: 1px solid #e2e2e2;
border-radius: 0.6rem;
background-color: #ffffff;
scrollbar-width: thin;
scrollbar-color: #ccc transparent;
}

/* Scrollbar Styling for WebKit browsers */
.activeContainer::-webkit-scrollbar {
width: 6px;
}
.activeContainer::-webkit-scrollbar-thumb {
background-color: #ccc;
border-radius: 3px;
}

/* Individual Active Item */
.activeItem {
display: flex;
align-items: center;
gap: 0.6rem;
padding: 0.4rem 0.6rem;
border-radius: 0.4rem;
transition: background-color 0.2s ease, transform 0.1s ease;
cursor: default;
}

.activeItem:hover {
background-color: #e6f7ff;
transform: scale(1.02);
}

.activeContainer img {
padding-left: 10px;
/* Online Icon */
.onlineIcon {
width: 16px;
height: 16px;
}

.textContainer h1 {
margin-bottom: 0px;
/* Username Text */
.username {
font-weight: 500;
color: #222;
}

@media (min-width: 320px) and (max-width: 1200px) {
.textContainer {
display: none;
/* Responsive Design */
@media (max-width: 480px) {
.intro h1 {
font-size: 1.6rem;
}
}

.usersSection {
max-width: 90%;
}

.activeContainer {
max-height: 180px;
}
}
49 changes: 24 additions & 25 deletions client/src/components/TextContainer/TextContainer.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@
import React from 'react';

import onlineIcon from '../../icons/onlineIcon.png';

import './TextContainer.css';

const TextContainer = ({ users }) => (
<div className="textContainer">
<div>
<h1>Realtime Chat Application <span role="img" aria-label="emoji">💬</span></h1>
<h2>Created with React, Express, Node and Socket.IO <span role="img" aria-label="emoji">❤️</span></h2>
<h2>Try it out right now! <span role="img" aria-label="emoji">⬅️</span></h2>
<div className="intro">
<h1>
Realtime Chat Application <span role="img" aria-label="chat">💬</span>
</h1>
<h2>
Created with React, Express, Node and Socket.IO <span role="img" aria-label="heart">❤️</span>
</h2>
<h2>
Try it out right now! <span role="img" aria-label="arrow">⬅️</span>
</h2>
</div>
{
users
? (
<div>
<h1>People currently chatting:</h1>
<div className="activeContainer">
<h2>
{users.map(({name}) => (
<div key={name} className="activeItem">
{name}
<img alt="Online Icon" src={onlineIcon}/>
</div>
))}
</h2>

{users && users.length > 0 && (
<div className="usersSection">
<h1>People currently chatting:</h1>
<div className="activeContainer">
{users.map(({ name }) => (
<div key={name} className="activeItem">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider using a more unique key.

Using name as the React key assumes all usernames are unique. If duplicate names exist, React may have reconciliation issues. Consider using a unique identifier like userId or falling back to an index if unavailable.

Example approach:

-            <div key={name} className="activeItem">
+            <div key={`${name}-${index}`} className="activeItem">

Note: This requires updating the map callback to include the index parameter.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In client/src/components/TextContainer/TextContainer.js around line 24, the JSX
uses key={name} which can collide when usernames repeat; change the map callback
to accept the index and use a truly unique key (preferably the user's unique id
property like userId) and if that id is not available fall back to a stable
composite key such as combining name with the index; update the map signature to
include the index and replace key usage accordingly to avoid reconciliation
issues.

<img alt="Online Icon" src={onlineIcon} className="onlineIcon" />
<span className="username">{name}</span>
</div>
</div>
)
: null
}
))}
</div>
</div>
)}
Comment on lines +19 to +31
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Type mismatch between users initialization and usage.

In client/src/components/Chat/Chat.js (line 18), users is initialized as an empty string (useState('')), but this component treats it as an array. If users is set to a non-empty string, the conditional check users.length > 0 will pass, but users.map will throw a runtime error since strings don't have the expected .map behavior for object destructuring.

Apply this verification script to confirm how users is set throughout the codebase:

#!/bin/bash
# Description: Verify how users state is initialized and updated in Chat.js

# Find where users state is set
rg -A 3 'setUsers' client/src/components/Chat/Chat.js

# Check if users is expected to be an array elsewhere
ast-grep --pattern 'users.map'
🤖 Prompt for AI Agents
In client/src/components/TextContainer/TextContainer.js around lines 19 to 31,
the component assumes users is an array but upstream code may initialize it as a
string, causing users.map to throw; ensure users is always an array by changing
the Chat.js users state default to an empty array (useState([])) and/or add a
runtime guard in this file to only map when Array.isArray(users) and
users.length > 0 (or coerce non-array to an empty array) so mapping never runs
on a string or other non-iterable value.

</div>
);

export default TextContainer;
export default TextContainer;