Update Chat/App/Profile Pages to be Mobile Friendly #61
@@ -4,6 +4,7 @@ import { useState, useEffect } from "react";
|
||||
|
||||
// Dependencies
|
||||
import { useGeolocated } from "react-geolocated";
|
||||
import Drawer from '@mui/material/Drawer';
|
||||
|
||||
// Firebase Imports
|
||||
import { auth, database } from "../../../firebase-config";
|
||||
@@ -14,6 +15,7 @@ import { useAuthState } from "react-firebase-hooks/auth"
|
||||
import { Header } from "../../components/app/header";
|
||||
import { HomePage } from "../../components/app/page/home";
|
||||
import { Sidebar } from "../../components/app/sidebar/home";
|
||||
import {useWindowSize} from "../../components/app/datatypes";
|
||||
|
||||
/**
|
||||
* Contains most everything for the app homepage
|
||||
@@ -24,6 +26,16 @@ function Home() {
|
||||
const [user, setUser] = useState(null); // user data
|
||||
const [loadingLoc, setLoadingLoc] = useState(true); // location variable loading, true = loading, false = finished loading
|
||||
const [authUser] = useAuthState(auth) // auth user object (used to obtain other user object)
|
||||
const [drawerOpen, setDrawerOpen] = useState(true); // drawer open state
|
||||
|
||||
var windowSize = useWindowSize()
|
||||
useEffect(() => {
|
||||
if (windowSize.width < 767) {
|
||||
setDrawerOpen(false)
|
||||
} else {
|
||||
setDrawerOpen(true)
|
||||
}
|
||||
}, [windowSize])
|
||||
|
||||
// Authentication Verification / Redirection if Profile Data not Filled out
|
||||
useEffect(() => {
|
||||
@@ -55,15 +67,16 @@ function Home() {
|
||||
}, [coords])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="overflow-hidden h-dvh">
|
||||
{user && (
|
||||
<div className="grid grid-cols-4 auto-cols-max overflow-hidden">
|
||||
<div className="overflow-hidden h-dvh">
|
||||
{/* Left Side of Page */}
|
||||
<div className="col-span-3 h-dvh">
|
||||
<div className="overflow-hidden h-dvh md:mr-[405px]">
|
||||
{/* Header */}
|
||||
<Header
|
||||
mainTab={"home"}
|
||||
user={user}
|
||||
sidebarControl={() => {setDrawerOpen(!drawerOpen)}}
|
||||
/>
|
||||
{/* Main Page Section */}
|
||||
<div className="mr-2 h-[calc(100%-110px)]">
|
||||
@@ -76,11 +89,19 @@ function Home() {
|
||||
</div>
|
||||
</div>
|
||||
{/* Sidebar (Right Side of Page) */}
|
||||
<Sidebar
|
||||
user={user}
|
||||
location={coords}
|
||||
loadingLoc={loadingLoc}
|
||||
/>
|
||||
<Drawer open={drawerOpen} anchor={"right"} variant={windowSize.width > 767? "persistent": "temporary"} onClose={() => {setDrawerOpen(false)}} sx={{
|
||||
width: windowSize.width > 767? 400: "80%",
|
||||
marginTop: 10,
|
||||
flexShrink: 0,
|
||||
'& .MuiDrawer-paper': {
|
||||
width: windowSize.width > 767? 400: "80%",
|
||||
borderLeft: 0,
|
||||
},
|
||||
}}>
|
||||
<div className="shadow-2xl">
|
||||
<Sidebar user={user} location={coords} loadingLoc={loadingLoc}/>
|
||||
</div>
|
||||
</Drawer>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
"use client";
|
||||
// System Imports
|
||||
import Drawer from '@mui/material/Drawer';
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
// Firebase Imports
|
||||
import { auth, database } from "../../../firebase-config";
|
||||
import { ref, onValue, set, onDisconnect, serverTimestamp } from "firebase/database";
|
||||
import { ref, onValue, set, onDisconnect } from "firebase/database";
|
||||
import { useAuthState } from "react-firebase-hooks/auth"
|
||||
|
||||
// Component Imports
|
||||
import { Header } from "../../components/app/header";
|
||||
import { ChatRoom } from "../../components/app/page/chat";
|
||||
import { Sidebar } from "../../components/app/sidebar/chat";
|
||||
import {useWindowSize} from "../../components/app/datatypes";
|
||||
|
||||
|
||||
/**
|
||||
* Chat Page
|
||||
@@ -22,6 +25,16 @@ function Chat() {
|
||||
const [chatRoomObj, setChatRoomObj] = useState(null); // Current chatroom object
|
||||
const [doneLoading, setDoneLoading] = useState(false) // is the page done loading or not
|
||||
const [authUser] = useAuthState(auth) // auth user object (used to obtain other user object)
|
||||
const [drawerOpen, setDrawerOpen] = useState(true); // drawer open state
|
||||
|
||||
var windowSize = useWindowSize()
|
||||
useEffect(() => {
|
||||
if (windowSize.width < 767) {
|
||||
setDrawerOpen(false)
|
||||
} else {
|
||||
setDrawerOpen(true)
|
||||
}
|
||||
}, [windowSize])
|
||||
|
||||
// Authentication Verification / Redirection if Profile Data not Filled out
|
||||
useEffect(() => {
|
||||
@@ -88,14 +101,15 @@ function Chat() {
|
||||
return (
|
||||
<div>
|
||||
{(authUser && doneLoading) && (
|
||||
<div className="grid grid-cols-4 auto-cols-max overflow-hidden">
|
||||
<div className="overflow-hidden h-dvh">
|
||||
{/* Left Side of Page */}
|
||||
<div className="col-span-3 h-dvh">
|
||||
<div className="overflow-hidden h-dvh md:mr-[400px]">
|
||||
{/* Header */}
|
||||
<Header
|
||||
mainTab={"chat"}
|
||||
chatRoomObj={chatRoomObj}
|
||||
user={user}
|
||||
sidebarControl={() => {setDrawerOpen(!drawerOpen)}}
|
||||
/>
|
||||
{/* Main Page Section */}
|
||||
<div className="mr-2 h-[calc(100%-110px)]">
|
||||
@@ -103,9 +117,19 @@ function Chat() {
|
||||
</div>
|
||||
</div>
|
||||
{/* Sidebar (Right Side of Page) */}
|
||||
<Sidebar
|
||||
chatRoomObj={chatRoomObj}
|
||||
/>
|
||||
<Drawer open={drawerOpen} anchor={"right"} variant={windowSize.width > 767? "persistent": "temporary"} onClose={() => {setDrawerOpen(false)}} sx={{
|
||||
width: windowSize.width > 767? 400: "80%",
|
||||
marginTop: 10,
|
||||
flexShrink: 0,
|
||||
'& .MuiDrawer-paper': {
|
||||
width: windowSize.width > 767? 400: "80%",
|
||||
borderLeft: 0,
|
||||
},
|
||||
}}>
|
||||
<div className="shadow-2xl">
|
||||
<Sidebar chatRoomObj={chatRoomObj}/>
|
||||
</div>
|
||||
</Drawer>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Inter } from "next/font/google";
|
||||
import "../../globals.css";
|
||||
import "../globals.css";
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
"use client";
|
||||
// System Imports
|
||||
import { useState, useEffect } from "react";
|
||||
import { auth, database } from "../../../../firebase-config";
|
||||
import { auth, database } from "../../../firebase-config";
|
||||
import { ref, onValue, get } from "firebase/database";
|
||||
import { onAuthStateChanged } from "firebase/auth";
|
||||
|
||||
// Refactored Component Imports
|
||||
|
||||
// Data Structure Imports
|
||||
import { ProfileRoom } from "../../../components/app/profile/ProfileRoom";
|
||||
import { ProfileEdit } from "../../../components/app/profile/ProfileEdit";
|
||||
import { Interest } from "../../../components/app/profile/Interest";
|
||||
import { ProfileRoom } from "../../components/app/profile/ProfileRoom";
|
||||
import { ProfileEdit } from "../../components/app/profile/ProfileEdit";
|
||||
import { Interest } from "../../components/app/profile/Interest";
|
||||
|
||||
// Header Import
|
||||
import { Header } from "../../../components/app/header";
|
||||
import { Header } from "../../components/app/header";
|
||||
|
||||
/**
|
||||
* User Profile Page
|
||||
* @param {URLSearchParams} params - URL Parameters
|
||||
* @returns {Object} - User Profile Page
|
||||
*/
|
||||
function UserProfile({ params }) {
|
||||
function UserProfile() {
|
||||
const [profileData, setProfileData] = useState(null); // Profile Data
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false); // Determines if user is authenticated
|
||||
const [user, setUser] = useState(null); // User Data
|
||||
@@ -36,12 +35,15 @@ function UserProfile({ params }) {
|
||||
|
||||
// Authentication
|
||||
useEffect(() => {
|
||||
|
||||
onAuthStateChanged(auth, (user) => {
|
||||
const searchParams = new URLSearchParams(document.location.search);
|
||||
var userUID = searchParams.get("uid")
|
||||
if (user) {
|
||||
get(ref(database, `users/${user.uid}`)).then((userData) => {
|
||||
userData = userData.val();
|
||||
if (userData) {
|
||||
if (userData.uid == params.stub) {
|
||||
if (userData.uid == userUID) {
|
||||
setIsOwner(true);
|
||||
}
|
||||
setUser(userData);
|
||||
@@ -59,7 +61,9 @@ function UserProfile({ params }) {
|
||||
|
||||
// Grabs profile user data
|
||||
useEffect(() => {
|
||||
onValue(ref(database, "/users/" + params.stub), (snapshot) => {
|
||||
const searchParams = new URLSearchParams(document.location.search);
|
||||
var userUID = searchParams.get("uid")
|
||||
onValue(ref(database, "/users/" + userUID), (snapshot) => {
|
||||
setProfileData(snapshot.val());
|
||||
|
||||
// Populates array with user's interests
|
||||
@@ -91,14 +95,14 @@ function UserProfile({ params }) {
|
||||
return (
|
||||
<div>
|
||||
{isAuthenticated && (
|
||||
<div className="overflow-hidden">
|
||||
<div className="md:overflow-hidden">
|
||||
{/* Left Side of Page */}
|
||||
<div className="h-dvh overflow-hidden">
|
||||
<div className="h-dvh md:overflow-hidden">
|
||||
{/* Header */}
|
||||
<Header user={user} />
|
||||
{/* Main Page Section */}
|
||||
<div className="grid grid-cols-3 mr-2 h-[calc(100%-110px)] pl-5 pr-5 pt-2">
|
||||
<div className="cols-span-1 bg-white shadow-2xl rounded-xl pt-5">
|
||||
<div className="md:grid md:grid-cols-3 mr-2 h-[calc(100%-110px)] pl-5 pr-5 pt-2 max-md:mb-10">
|
||||
<div className="cols-span-1 bg-white shadow-2xl rounded-xl pt-5 max-md:pb-5">
|
||||
{!isEditing && (
|
||||
<div>
|
||||
<img
|
||||
@@ -142,7 +146,7 @@ function UserProfile({ params }) {
|
||||
)}
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<div className="grid grid-cols-3 gap-y-1 pl-5 gap-1 h-[100%] w-[100%]">
|
||||
<div className="grid md:grid-cols-3 max-md:grid-cols-1 max-md:mt-5 md:pl-5 justify-items-center gap-y-5 gap-1 h-[100%] w-[100%]">
|
||||
{userRoomsArray}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,4 +1,5 @@
|
||||
import Link from "next/link"
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
// Colors for Messages
|
||||
const userColors = [
|
||||
@@ -26,6 +27,31 @@ let dateOptions = {
|
||||
minute: "2-digit",
|
||||
};
|
||||
|
||||
/**
|
||||
* Grabs Window Size
|
||||
* @returns {Object} - Window Size Object (width, height)
|
||||
*/
|
||||
export function useWindowSize() {
|
||||
const [windowSize, setWindowSize] = useState({
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
function handleResize() {
|
||||
setWindowSize({
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
});
|
||||
}
|
||||
window.addEventListener("resize", handleResize);
|
||||
handleResize();
|
||||
return () => window.removeEventListener("resize", handleResize);
|
||||
}, []);
|
||||
return windowSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates Color based on string hash
|
||||
* @param {String} user_str - Username / String for hashing
|
||||
@@ -52,7 +78,7 @@ export function Chat({ chatObj }) {
|
||||
<div className="width-[100%] bg-white rounded-lg mt-1 text-left p-1 grid grid-cols-2 mr-2">
|
||||
<div>
|
||||
<span style={{ color: userColors[generateColor(chatObj.user)] }}>
|
||||
<Link href={`/user/${chatObj.uid}`}
|
||||
<Link href={`/user?uid=${chatObj.uid}`}
|
||||
className="hover:font-bold cursor-pointer"
|
||||
target="_blank">
|
||||
{chatObj.user}
|
||||
@@ -78,7 +104,7 @@ export function SystemMessage({ chatObj }) {
|
||||
<div className="width-[100%] bg-white rounded-lg mt-1 text-left p-1 grid grid-cols-2 mr-2">
|
||||
<div className="text-[#d1d1d1]">
|
||||
<span style={{ color: userColors[generateColor(chatObj.user)] }}>
|
||||
<Link href={`/user/${chatObj.uid}`}
|
||||
<Link href={`/user?uid=${chatObj.uid}`}
|
||||
className="hover:font-bold cursor-pointer"
|
||||
target="_blank">
|
||||
{chatObj.user}
|
||||
@@ -100,7 +126,7 @@ export function SystemMessage({ chatObj }) {
|
||||
*/
|
||||
export function Member({ memberObj }) {
|
||||
return (
|
||||
<Link href={"/user/" + memberObj.uid} target="_blank">
|
||||
<Link href={"/user?uid=" + memberObj.uid} target="_blank">
|
||||
<div className="cursor-pointer g-[aliceblue] rounded-lg m-3 shadow-xl p-2">
|
||||
{memberObj.username}
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,12 @@ import { ref, set, remove } from "firebase/database";
|
||||
import { NotificationPanel } from "./notifications/notifications";
|
||||
import { ProfilePanel } from "./profile/ProfilePanel"
|
||||
|
||||
// Icons
|
||||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import RemoveIcon from '@mui/icons-material/Remove';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
|
||||
/**
|
||||
* Closes Chat
|
||||
* @param {JSON} chatRoomObj - Chat Room Object
|
||||
@@ -69,7 +75,7 @@ function removeFromMyRooms(chatRoomObj, user) {
|
||||
* @prop {JSON} chatRoomObj - Chat Room Object
|
||||
* @prop {JSON} user - User Object
|
||||
*/
|
||||
export function Header({mainTab,chatRoomObj,user,}) {
|
||||
export function Header({mainTab,chatRoomObj,user,sidebarControl}) {
|
||||
|
||||
if (mainTab == "chat") {
|
||||
var roomName = chatRoomObj.name + "-" + chatRoomObj.timestamp;
|
||||
@@ -86,7 +92,8 @@ export function Header({mainTab,chatRoomObj,user,}) {
|
||||
<div className="flex m-2 rounded-lg h-[63px] bg-white shadow-2xl p-1">
|
||||
<div className="flex shrink h-[60px]">
|
||||
<Link href="/app">
|
||||
<img src="/logos/logo_transparent_inverse.png" className="h-[60px]" />
|
||||
<img src="/logos/logo_transparent_inverse.png" className="h-[60px] max-xl:hidden" />
|
||||
<img src="/logos/icon.png" className="h-[50px] mt-[5px] mb-[5px] xl:hidden" />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="grow grid grid-rows-1 grid-flow-col auto-cols-max justify-end gap-2 h-[60px] p-2">
|
||||
@@ -96,9 +103,9 @@ export function Header({mainTab,chatRoomObj,user,}) {
|
||||
addToMyRooms(chatRoomObj, user);
|
||||
|
||||
}}
|
||||
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center"
|
||||
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-2 flex items-center"
|
||||
>
|
||||
Add to "My Rooms"
|
||||
<AddIcon/>
|
||||
</a>
|
||||
)}
|
||||
{mainTab == "chat" && isMyRoom == true && (
|
||||
@@ -107,18 +114,18 @@ export function Header({mainTab,chatRoomObj,user,}) {
|
||||
removeFromMyRooms(chatRoomObj, user);
|
||||
|
||||
}}
|
||||
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center"
|
||||
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-2 flex items-center"
|
||||
>
|
||||
Remove from "My Rooms"
|
||||
<RemoveIcon/>
|
||||
</a>
|
||||
)}
|
||||
{mainTab == "chat" && (
|
||||
<Link
|
||||
href="/app"
|
||||
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center"
|
||||
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-2 flex items-center"
|
||||
onClick={() => {closeChat(chatRoomObj,user)}}
|
||||
>
|
||||
Close Chat
|
||||
<CloseIcon/>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
@@ -127,6 +134,14 @@ export function Header({mainTab,chatRoomObj,user,}) {
|
||||
|
||||
{/*Profile Dropdown */}
|
||||
<ProfilePanel user={user}/>
|
||||
|
||||
{/* Sidebar Control (for small screens) */}
|
||||
<div
|
||||
className="md:hidden p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center"
|
||||
onClick={() => {sidebarControl()}}
|
||||
>
|
||||
<MenuIcon/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -86,7 +86,7 @@ export function NotificationPanel({user}) {
|
||||
</div>
|
||||
</Popover.Button>
|
||||
|
||||
<Popover.Panel className="absolute z-10 bg-white mt-[4px] rounded-xl ml-3 shadow-2xl w-64 right-[0px]">
|
||||
<Popover.Panel className="absolute z-10 bg-white mt-[4px] rounded-xl ml-3 shadow-2xl w-64 md:right-[0px] max-md:right-[-300%]">
|
||||
<div className="grid grid-cols-1">
|
||||
{isNotifications && notificationsMap}
|
||||
{!isNotifications &&
|
||||
|
||||
@@ -74,17 +74,11 @@ export function ChatRoom({ roomObj, user }) {
|
||||
<Form
|
||||
onSubmit={handleSubmit(sendMessage)}
|
||||
control={control}
|
||||
className="w-[100%] p-[0px]"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
{...register("message")}
|
||||
placeholder="Enter message"
|
||||
className="w-[83%] border-[0px] mt-[8px] mb-[8px]"
|
||||
/>
|
||||
<button className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 w-[8%]">
|
||||
Send
|
||||
</button>
|
||||
<div className="width-[100%] grid grid-cols-6">
|
||||
<input type="text" {...register("message")} placeholder="Enter message" className="col-span-5 border-[0px] mt-[8px] mb-[8px]" />
|
||||
<button className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 w-[60px]">Send</button>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@ export function ProfilePanel({user}) {
|
||||
return (
|
||||
<Popover className="relative">
|
||||
<Popover.Button as="div">
|
||||
<div className="mr-5 h-[44px] p-[2px] pr-[15px] cursor-pointer bg-cyan-500 text-white font-bold rounded-full shadow-2xl flex">
|
||||
<div className="h-[44px] p-[2px] pr-[15px] cursor-pointer bg-cyan-500 text-white font-bold rounded-full shadow-2xl flex">
|
||||
<div className="flex items-center pl-1">{user.firstName}</div>
|
||||
<div className="ml-3 rounded-lg">
|
||||
<img
|
||||
@@ -39,7 +39,7 @@ export function ProfilePanel({user}) {
|
||||
<div className="grid grid-cols-1">
|
||||
<Link
|
||||
className="rounded-xl p-4 hover:bg-[#C0C0C0]"
|
||||
href={"/user/" + user.uid}
|
||||
href={"/user?uid=" + user.uid}
|
||||
>
|
||||
View Profile
|
||||
</Link>
|
||||
|
||||
@@ -33,7 +33,7 @@ export function Sidebar({chatRoomObj}) {
|
||||
var chatroomUsers = allUsers
|
||||
}
|
||||
return (
|
||||
<div className="h-dvh">
|
||||
<div className="overflow-hidden h-dvh">
|
||||
<div className="m-2 h-[98%] grid grid-cols-1">
|
||||
<div className="bg-white rounded-lg m-2 shadow-2xl relative">
|
||||
<div className="w-[100%] h-[100%] opacity-50 absolute rounded-lg z-10">
|
||||
|
||||
@@ -86,7 +86,6 @@ export function Sidebar({user,location,loadingLoc}) {
|
||||
const [tab, setTab] = useState("nearby");
|
||||
const [nearbyArr, setNearbyArr] = useState([])
|
||||
const [nearbyArrReady, setNearbyArrReady] = useState(false)
|
||||
|
||||
// Add myRooms to Sidebar
|
||||
var myRoomArr = [];
|
||||
for (var room in user.rooms) {
|
||||
@@ -124,27 +123,27 @@ export function Sidebar({user,location,loadingLoc}) {
|
||||
}, [location])
|
||||
|
||||
return (
|
||||
<div className="h-dvh">
|
||||
<div className="bg-white shadow-2xl rounded-lg m-2 h-[98%]">
|
||||
<div className="h-dvh bg-[aliceblue] pt-2 pb-2 pl-2 pr-1">
|
||||
<div className="bg-white rounded-lg h-[98%] mb-[10px] mt-[-18px] mr-2">
|
||||
<Tab.Group>
|
||||
<Tab.List className="bg-[#D3D3D3] rounded-lg mt-5">
|
||||
<Tab className={({ selected }) =>
|
||||
classNames(
|
||||
'w-[31%]',
|
||||
'w-[30%]',
|
||||
selected
|
||||
? 'bg-cyan-500 text-white font-bold shadow hover:bg-white/[0.6] hover:text-black'
|
||||
: 'hover:bg-cyan-500/[0.6] hover:text-white hover:font-bold'
|
||||
)} defaultIndex={1}>Nearby</Tab>
|
||||
<Tab className={({ selected }) =>
|
||||
classNames(
|
||||
'w-[31%]',
|
||||
'w-[30%]',
|
||||
selected
|
||||
? 'bg-cyan-500 text-white font-bold shadow hover:bg-white/[0.6] hover:text-black'
|
||||
: 'hover:bg-cyan-500/[0.6] hover:text-white hover:font-bold'
|
||||
)}>My Rooms</Tab>
|
||||
<Tab className={({ selected }) =>
|
||||
classNames(
|
||||
'w-[31%]',
|
||||
'w-[30%]',
|
||||
selected
|
||||
? 'bg-cyan-500 text-white font-bold shadow hover:bg-white/[0.6] hover:text-black'
|
||||
: 'hover:bg-cyan-500/[0.6] hover:text-white hover:font-bold'
|
||||
|
||||
Reference in New Issue
Block a user