style: optimize layout

main
Justin Xiao 2023-07-21 18:10:42 +08:00
parent d90e19284a
commit 419af7a9d5
3 changed files with 92 additions and 71 deletions

View File

@ -124,56 +124,76 @@ export default function Home() {
return (
<>
<Container size="md" h={"100vh"}>
<Card shadow="sm" padding="sm" radius="md" withBorder h={"100%"}>
<Card.Section withBorder inheritPadding py="xs" h={"10%"}>
<Card
shadow="sm"
padding="sm"
radius="md"
withBorder
h={"100%"}
className="flex flex-col"
>
<Card.Section
component="a"
withBorder
inheritPadding
py="xs"
h={"10%"}
display={"flex"}
mih={"65px"}
>
<ChatroomTitle
targetSocketId={targetSocketId}
setTargetSocketId={setTargetSocketId}
/>
</Card.Section>
<ScrollArea offsetScrollbars viewportRef={chatViewportRef} h={"85%"}>
{messages.map((message, index) => {
return (
<div
className={
message.me
? classes.rightMessageField
: classes.leftMessageField
}
key={message.timestamp + index}
>
{!message.me && (
<div className={classes.avatar}>
<Avatar alt="User" color="blue" radius="xl">
{onlineUsers[message.from] &&
onlineUsers[message.from].length > 5
? `${onlineUsers[message.from].slice(0, 1)}`
: onlineUsers[message.from]}
</Avatar>
</div>
)}
<Text
<Card.Section withBorder inheritPadding py="xs" h={"85%"} mih={"300px"}>
<ScrollArea offsetScrollbars viewportRef={chatViewportRef} h={"100%"}>
{messages.map((message, index) => {
return (
<div
className={
message.me ? classes.rightMessage : classes.leftMessage
message.me
? classes.rightMessageField
: classes.leftMessageField
}
key={message.timestamp + index}
>
{message.message.split("\n").map((line, index) => {
return (
<span key={message.timestamp + index}>
{line}
<br />
</span>
);
})}
</Text>
<Text size="xs" className={classes.timestamp}>
{new Date(message.timestamp).toLocaleTimeString()}
</Text>
</div>
);
})}
</ScrollArea>
<Card.Section withBorder inheritPadding h={"10%"}>
{!message.me && (
<div className={classes.avatar}>
<Avatar alt="User" color="blue" radius="xl">
{onlineUsers[message.from] &&
onlineUsers[message.from].length > 5
? `${onlineUsers[message.from].slice(0, 1)}`
: onlineUsers[message.from]}
</Avatar>
</div>
)}
<Text
className={
message.me
? classes.rightMessage
: classes.leftMessage
}
>
{message.message.split("\n").map((line, index) => {
return (
<span key={message.timestamp + index}>
{line}
<br />
</span>
);
})}
</Text>
<Text size="xs" className={classes.timestamp}>
{new Date(message.timestamp).toLocaleTimeString()}
</Text>
</div>
);
})}
</ScrollArea>
</Card.Section>
<Card.Section withBorder h={"5%"} mih={"80px"}>
<ChatroomInput targetSocketId={targetSocketId} />
</Card.Section>
</Card>

View File

@ -8,7 +8,7 @@ type Props = {
targetSocketId: string;
};
const useStyles = createStyles((theme) => ({
inputWithoutBorder: {
Textarea: {
border: "none",
},
}));
@ -58,25 +58,21 @@ const ChatroomInput: FC<Props> = ({ targetSocketId }) => {
};
return (
<Group w={"100%"} align="center">
<Group w={"100%"} display={"flex"} className="gap-0" position="apart" noWrap>
<Textarea
classNames={{ input: classes.inputWithoutBorder }}
h={"100%"}
w={"100%"}
classNames={{ input: classes.Textarea }}
minRows={3}
maxRows={7}
ref={messageInputRef}
value={message}
onChange={(e) => setMessage(e.currentTarget.value)}
// radius="xl"
// size="md"
rightSection={
<ActionIcon size={32} radius="xl">
<IconSend size="1.5rem" stroke={1.5} onClick={sendMessage} />
</ActionIcon>
}
placeholder="Type something..."
rightSectionWidth={42}
onKeyDown={handleKeyDown}
/>
<ActionIcon radius="xl">
<IconSend stroke={1.5} onClick={sendMessage} />
</ActionIcon>
</Group>
);
};

View File

@ -39,9 +39,9 @@ type Props = {
const ChatroomTitle: FC<Props> = ({ targetSocketId, setTargetSocketId }) => {
const { socket, emitMode, setEmitMode, connect, disconnect } = useSocketStore(); // deconstructing socket and its method from socket store
const [popoverOpened, setPopoverOpened] = useState(false); // control popover open/close
const [avatarPopoverOpen, setAvatarPopoverOpen] = useState(false); // control popover open/close
const [onlineUsers, setOnlineUsers] = useState<Record<string, string>>({}); // online users
const [opened, setOpened] = useState(false);
const [socketIdPopoverOpen, setSocketIdPopoverOpen] = useState(false);
useEffect(() => {
if (!socket) return;
@ -56,22 +56,21 @@ const ChatroomTitle: FC<Props> = ({ targetSocketId, setTargetSocketId }) => {
return (
<>
<Group position="apart" mt="xs" mb="xs" noWrap h={"5vh"}>
<Group position="apart" mt="xs" mb="xs" noWrap align="center" w={"100%"}>
<Group noWrap>
<Avatar />
<Popover
width="fit-content"
position="bottom"
withArrow
shadow="md"
opened={popoverOpened}
onChange={setPopoverOpened}
opened={avatarPopoverOpen}
onChange={setAvatarPopoverOpen}
>
<Popover.Target>
<ActionIcon
variant="subtle"
onClick={() => setPopoverOpened((open) => !open)}
onClick={() => setAvatarPopoverOpen((open) => !open)}
>
<IconChevronDown size="1rem" />
</ActionIcon>
@ -135,20 +134,25 @@ const ChatroomTitle: FC<Props> = ({ targetSocketId, setTargetSocketId }) => {
crossAxis: 30,
}}
shadow="md"
opened={opened}
onChange={setOpened}
opened={socketIdPopoverOpen}
onChange={setSocketIdPopoverOpen}
>
<Popover.Target>
<SegmentedControl
size="xs"
value={emitMode}
onClick={() => {
if (emitMode === "private_message") {
setSocketIdPopoverOpen(true);
}
}}
onChange={(value: "broadcast" | "private_message") => {
setEmitMode(value);
if (value === "broadcast") {
setTargetSocketId("");
setOpened(false);
setSocketIdPopoverOpen(false);
} else {
setOpened(true);
setSocketIdPopoverOpen(true);
}
}}
data={[
@ -165,10 +169,7 @@ const ChatroomTitle: FC<Props> = ({ targetSocketId, setTargetSocketId }) => {
value: "private_message",
label: (
<Center>
<IconUserShare
size="1rem"
onClick={() => setOpened(true)}
/>
<IconUserShare size="1rem" />
<Box ml={10}>To</Box>
</Center>
),
@ -205,7 +206,7 @@ const ChatroomTitle: FC<Props> = ({ targetSocketId, setTargetSocketId }) => {
/>
</Popover.Dropdown>
</Popover>
<Menu shadow="md" width="fit-content">
<Menu shadow="md">
<Menu.Target>
<ActionIcon variant="subtle">
<IconUserCog size="1.25em" />
@ -224,7 +225,11 @@ const ChatroomTitle: FC<Props> = ({ targetSocketId, setTargetSocketId }) => {
.map((socketId) => (
<Menu.Item
key={socketId}
onClick={() => setTargetSocketId(socketId)}
onClick={() => {
setEmitMode("private_message");
setSocketIdPopoverOpen(true);
setTargetSocketId(socketId);
}}
>
<Group
position="apart"