Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: community floating window #616

Merged
merged 2 commits into from
Mar 14, 2024
Merged
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
1 change: 1 addition & 0 deletions apps/u3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.7",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-hover-card": "^1.0.7",
"@rainbow-me/rainbowkit": "^2.0.0",
"@react-spring/web": "^9.6.1",
"@reduxjs/toolkit": "^1.8.3",
Expand Down
6 changes: 5 additions & 1 deletion apps/u3/src/components/common/select/Select2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ export default function SelectWithOptions({
<SelectContent className="rounded-[10px] bg-[#1B1E23] text-[#FFF] text-[14px] font-medium border-none">
{options.map(({ value, label }) => {
return (
<SelectItem value={value} className="hover:bg-[#20262F]">
<SelectItem
key={value}
value={value}
className="hover:bg-[#20262F]"
>
{label}
</SelectItem>
);
Expand Down
26 changes: 26 additions & 0 deletions apps/u3/src/components/community/CommunityInfoAndAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ComponentPropsWithRef } from 'react';
import { CommunityInfo } from '@/services/community/types/community';
import CommunityBaseInfo from './CommunityBaseInfo';
import { JoinCommunityTextBtn } from './JoinCommunityBtn';
import { cn } from '@/lib/utils';

export default function CommunityInfoAndAction({
className,
communityInfo,
...props
}: ComponentPropsWithRef<'div'> & {
communityInfo: CommunityInfo;
}) {
return (
<div
className={cn(`w-full box-border flex flex-col gap-[20px]`, className)}
{...props}
>
<CommunityBaseInfo communityInfo={communityInfo} />
<hr className="border-[#39424C]" />
<div>
<JoinCommunityTextBtn communityInfo={communityInfo} />
</div>
</div>
);
}
39 changes: 39 additions & 0 deletions apps/u3/src/components/community/JoinCommunityBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,42 @@ export default function JoinCommunityBtn({
</ColorButton>
);
}

export function JoinCommunityTextBtn({
className,
communityInfo,
...props
}: ComponentPropsWithRef<'button'> & {
communityInfo: CommunityInfo;
}) {
const { joined, isPending, isDisabled, joinChangeAction } =
useJoinCommunityAction(communityInfo);
return (
<button
type="button"
className={cn(
'w-auto text-[#F41F4C] text-[12px] font-normal leading-[15px]',
className
)}
disabled={isDisabled}
onClick={(e) => {
e.stopPropagation();
joinChangeAction();
}}
{...props}
>
{(() => {
if (joined) {
if (isPending) {
return 'Leaving ...';
}
return 'Leave Community';
}
if (isPending) {
return 'Joining ...';
}
return 'Join Community';
})()}
</button>
);
}
56 changes: 56 additions & 0 deletions apps/u3/src/components/community/SidebarCommunityItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { useNavigate } from 'react-router-dom';
import { CommunityInfo } from '@/services/community/types/community';
import { getCommunityPath } from '@/route/path';
import { cn } from '@/lib/utils';
import {
HoverCard,
HoverCardArrow,
HoverCardContent,
HoverCardTrigger,
} from '@/components/ui/hover-card';
import CommunityInfoAndAction from './CommunityInfoAndAction';

export default function SidebarCommunityItem({
communityInfo,
active,
}: {
communityInfo: CommunityInfo;
active?: boolean;
}) {
const navigate = useNavigate();
const url = getCommunityPath(communityInfo.channelId);
return (
<HoverCard>
<HoverCardTrigger asChild>
<a
href={url}
onClick={(e) => {
e.preventDefault();
navigate(url);
}}
className="w-full flex justify-center items-center cursor-pointer relative"
>
<div
className={cn(
'w-[5px] h-[40px] rounded-tl-none rounded-br-[10px] rounded-tr-[10px] rounded-bl-none bg-[#FFF] absolute left-0',
'transition-all duration-300',
active ? 'block' : 'hidden'
)}
/>
<img
src={communityInfo.logo}
alt={communityInfo.name}
className="rounded-md w-[40px] h-[40px]"
/>
</a>
</HoverCardTrigger>
<HoverCardContent
side="right"
className="w-[280px] h-auto bg-[#14171A] border-none"
>
<HoverCardArrow className="w-[30px] h-[10px] fill-[#14171A]" />
<CommunityInfoAndAction communityInfo={communityInfo} />
</HoverCardContent>
</HoverCard>
);
}
38 changes: 3 additions & 35 deletions apps/u3/src/components/layout/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import styled from 'styled-components';
import { useNavigate } from 'react-router-dom';
import { ComponentPropsWithRef } from 'react';
import { ReactComponent as LogoIconSvg } from '../common/assets/imgs/logo-icon.svg';
import { getCommunityPath } from '@/route/path';
import { cn } from '@/lib/utils';
import useAllJoinedCommunities from '@/hooks/community/useAllJoinedCommunities';
import { CommunityInfo } from '@/services/community/types/community';
import useBrowsingCommunity from '@/hooks/community/useBrowsingCommunity';
import SidebarCommunityItem from '../community/SidebarCommunityItem';

export default function Menu({
className,
Expand Down Expand Up @@ -66,7 +65,8 @@ function UserCommunities() {
return (
<div className="w-full overflow-scroll h-full flex gap-5 flex-col">
{showCommunities.map((item) => (
<CommunityItem
<SidebarCommunityItem
key={item.id}
communityInfo={item}
active={browsingCommunity?.id === item.id}
/>
Expand All @@ -75,38 +75,6 @@ function UserCommunities() {
);
}

function CommunityItem({
communityInfo,
active,
}: {
communityInfo: CommunityInfo;
active?: boolean;
}) {
const navigate = useNavigate();

return (
<div
onClick={() => {
navigate(getCommunityPath(communityInfo.channelId));
}}
className="w-full flex justify-center items-center cursor-pointer relative"
>
<div
className={cn(
'w-[5px] h-[40px] rounded-tl-none rounded-br-[10px] rounded-tr-[10px] rounded-bl-none bg-[#FFF] absolute left-0',
'transition-all duration-300',
active ? 'block' : 'hidden'
)}
/>
<img
src={communityInfo.logo}
alt={communityInfo.name}
className="rounded-md w-[40px] h-[40px]"
/>
</div>
);
}

const LogoIconBox = styled.div`
width: 36px;
height: 36px;
Expand Down
33 changes: 33 additions & 0 deletions apps/u3/src/components/ui/hover-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* eslint-disable react/prop-types */

'use client';

import * as React from 'react';
import * as HoverCardPrimitive from '@radix-ui/react-hover-card';

import { cn } from '@/lib/utils';

const HoverCard = HoverCardPrimitive.Root;

const HoverCardTrigger = HoverCardPrimitive.Trigger;

const HoverCardArrow = HoverCardPrimitive.Arrow;

const HoverCardContent = React.forwardRef<
React.ElementRef<typeof HoverCardPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
<HoverCardPrimitive.Content
ref={ref}
align={align}
sideOffset={sideOffset}
className={cn(
'z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className
)}
{...props}
/>
));
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;

export { HoverCard, HoverCardTrigger, HoverCardArrow, HoverCardContent };
29 changes: 28 additions & 1 deletion apps/u3/src/components/ui/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,34 @@ import * as SelectPrimitive from '@radix-ui/react-select';

import { cn } from '@/lib/utils';

const Select = SelectPrimitive.Root;
// TODO see issue: https://github.com/radix-ui/primitives/issues/1658

// const Select = SelectPrimitive.Root;
const Select = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root>
>(({ open: openSelect, onOpenChange, ...props }) => {
const [open, setOpen] = React.useState(openSelect);
return (
<SelectPrimitive.Root
open={openSelect !== undefined ? openSelect : open}
onOpenChange={(o) => {
setTimeout(() => {
const selection = document.getSelection();
if (selection) {
selection.removeAllRanges();
}
if (openSelect !== undefined && onOpenChange) {
onOpenChange(o);
} else {
setOpen(o);
}
}, 10);
}}
{...props}
/>
);
});

const SelectGroup = SelectPrimitive.Group;

Expand Down
50 changes: 3 additions & 47 deletions apps/u3/src/container/community/CommunityMobileHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ import {
import { MobileHeaderWrapper } from '@/components/layout/mobile/MobileHeaderCommon';
import SearchIconBtn from '@/components/layout/SearchIconBtn';
import AddPostMobileBtn from '@/components/social/AddPostMobileBtn';
import CommunityBaseInfo from '@/components/community/CommunityBaseInfo';
import { Drawer, DrawerContent, DrawerTrigger } from '@/components/ui/drawer';
import getCommunityNavs from '@/utils/community/getCommunityNavs';
import useJoinCommunityAction from '@/hooks/community/useJoinCommunityAction';
import CommunityInfoAndAction from '@/components/community/CommunityInfoAndAction';

export default function CommunityMobileHeader({
className,
Expand Down Expand Up @@ -78,12 +77,8 @@ export default function CommunityMobileHeader({
Info
</button>
</DrawerTrigger>
<DrawerContent className="rounded-tl-[20px] rounded-br-none rounded-tr-[20px] rounded-bl-none bg-[#20262F] border-none outline-none p-[20px] flex flex-col gap-[20px]">
<CommunityBaseInfo communityInfo={communityInfo} />
<hr className="border-[#39424C]" />
<div>
<JoinCommunityBtn communityInfo={communityInfo} />
</div>
<DrawerContent className="rounded-tl-[20px] rounded-br-none rounded-tr-[20px] rounded-bl-none bg-[#20262F] border-none outline-none p-[20px]">
<CommunityInfoAndAction communityInfo={communityInfo} />
</DrawerContent>
</Drawer>
</SelectContent>
Expand All @@ -95,42 +90,3 @@ export default function CommunityMobileHeader({
</MobileHeaderWrapper>
);
}

function JoinCommunityBtn({
className,
communityInfo,
...props
}: ComponentPropsWithRef<'button'> & {
communityInfo: CommunityInfo;
}) {
const { joined, isPending, isDisabled, joinChangeAction } =
useJoinCommunityAction(communityInfo);
return (
<button
type="button"
className={cn(
'w-auto text-[#F41F4C] text-[12px] font-normal leading-[15px]',
className
)}
disabled={isDisabled}
onClick={(e) => {
e.stopPropagation();
joinChangeAction();
}}
{...props}
>
{(() => {
if (joined) {
if (isPending) {
return 'Leaving ...';
}
return 'Leave Community';
}
if (isPending) {
return 'Joining ...';
}
return 'Join Community';
})()}
</button>
);
}