Skip to content

Commit

Permalink
fix(popover): add closing when click on button
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliamTraoreee committed Sep 9, 2022
1 parent bd23e5b commit 7f237bb
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 85 deletions.
67 changes: 4 additions & 63 deletions apps/app/src/app/pages/chatbox/library.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import { useDeleteChatTheme, useUserChatThemes } from '@streali/shared/hooks';
import {
Button,
ButtonColor,
Popover,
PopoverNavigation,
} from '@streali/shared/ui';
import { toastr, ToastType } from '@streali/shared/utils';
import { useUserChatThemes } from '@streali/shared/hooks';
import { Button, ChatCard } from '@streali/shared/ui';

export function LibraryChatbox() {
const { data, isLoading } = useUserChatThemes();
const { mutate: deleteChatTheme } = useDeleteChatTheme();

return (
<div className="p-10">
Expand All @@ -24,60 +17,8 @@ export function LibraryChatbox() {
{data &&
data.length > 0 &&
data?.map((theme) => (
<div
key={theme.id}
className="py-3 pl-4 pr-3 border-2 border-dark-300 rounded-md flex justify-between items-center hover:bg-primary-500"
>
<h2>{theme.title}</h2>
<Popover
align="end"
side="bottom"
trigger={
<Button iconLeft="more-line" color={ButtonColor.Dark} />
}
>
<PopoverNavigation
links={[
{
title: 'Edit',
link: `/chatbox/${theme.id}/edit`,
icon: 'edit-box-line',
},
{
title: 'Embed',
onClick: () => {
navigator.clipboard.writeText(
`${window.location.origin.toString()}/chatbox/${
theme.id
}/embed`
);
toastr(
ToastType.Success,
'Embed link copied',
'You can use this link on your streaming software'
);
},
icon: 'file-copy-line',
},
{
title: 'Delete',
icon: 'delete-bin-line',
color: 'error',
confirm: {
title: 'Delete chatbox',
text: 'Are you sure you want to delete this chatbox theme?',
word: theme.title,
confirmText:
'For delete this chatbox theme, type the name of the chatbox theme',
textButton: 'Delete',
onConfirm: () => {
theme.id && deleteChatTheme(theme.id);
},
},
},
]}
/>
</Popover>
<div key={theme.id}>
<ChatCard title={theme.title} id={theme.id} />
</div>
))}
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/app/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const root = ReactDOM.createRoot(
root.render(
<StrictMode>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
<ReactQueryDevtools initialIsOpen={false} position="bottom-right" />
<Toaster position="top-right" />
<BrowserRouter>
<App />
Expand Down
1 change: 1 addition & 0 deletions libs/shared/ui/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './lib/components/chat-card/chat-card';
export * from './lib/components/confirmation/confirmation';
export * from './lib/components/code-editor/code-editor';
export * from './lib/components/popover-navigation/popover-navigation';
Expand Down
10 changes: 10 additions & 0 deletions libs/shared/ui/src/lib/components/chat-card/chat-card.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { render } from '@testing-library/react';

import ChatCard from './chat-card';

describe('ChatCard', () => {
it('should render successfully', () => {
const { baseElement } = render(<ChatCard />);
expect(baseElement).toBeTruthy();
});
});
73 changes: 73 additions & 0 deletions libs/shared/ui/src/lib/components/chat-card/chat-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { toastr, ToastType } from '@streali/shared/utils';
import Button, { ButtonColor } from '../button/button';
import PopoverNavigation from '../popover-navigation/popover-navigation';
import Popover from '../popover/popover';
import { useDeleteChatTheme } from '@streali/shared/hooks';
import { useState } from 'react';

export interface ChatCardProps {
title: string;
id: string;
}

export function ChatCard(props: ChatCardProps) {
const { title, id } = props;
const { mutate: deleteChatTheme } = useDeleteChatTheme();
const [menuOpen, setMenuOpen] = useState(false);

return (
<div className="py-3 pl-4 pr-3 border-2 border-dark-300 rounded-md flex justify-between items-center hover:bg-primary-500">
<h2>{title}</h2>
<Popover
open={menuOpen}
onOpenChange={setMenuOpen}
align="end"
side="bottom"
trigger={<Button iconLeft="more-line" color={ButtonColor.Dark} />}
>
<PopoverNavigation
onLinkClick={() => setMenuOpen(false)}
links={[
{
title: 'Edit',
link: `/chatbox/${id}/edit`,
icon: 'edit-box-line',
},
{
title: 'Embed',
onClick: () => {
navigator.clipboard.writeText(
`${window.location.origin.toString()}/chatbox/${id}/embed`
);
toastr(
ToastType.Success,
'Embed link copied',
'You can use this link on your streaming software'
);
},
icon: 'file-copy-line',
},
{
title: 'Delete',
icon: 'delete-bin-line',
color: 'error',
confirm: {
title: 'Delete chatbox',
text: 'Are you sure you want to delete this chatbox theme?',
word: title,
confirmText:
'For delete this chatbox theme, type the name of the chatbox theme',
textButton: 'Delete',
onConfirm: () => {
id && deleteChatTheme(id);
},
},
},
]}
/>
</Popover>
</div>
);
}

export default ChatCard;
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface ConfirmationProps {
confirmText: string;
textButton?: string;
onConfirm?: () => void;
onConfirmationClose?: () => void;
}

export function Confirmation(props: ConfirmationProps) {
Expand All @@ -22,6 +23,7 @@ export function Confirmation(props: ConfirmationProps) {
confirmText,
textButton = 'Confirm',
onConfirm,
onConfirmationClose,
} = props;
const [confirm, setConfirm] = useState('');
const [isOpen, setIsOpen] = useState(false);
Expand All @@ -44,6 +46,7 @@ export function Confirmation(props: ConfirmationProps) {
open={isOpen}
onOpenChange={(open) => {
setIsOpen(open);
if (!open) onConfirmationClose && onConfirmationClose();
}}
>
<p>{text}</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useState } from 'react';
import Icon from '../../icon/icon';
import PopoverNavigation, {
PopoverLink,
} from '../../popover-navigation/popover-navigation';
import Popover from '../../popover/popover';

export interface ButtonNavProps {
icon: string;
items: PopoverLink[];
}

function ButtonNav(props: ButtonNavProps) {
const { icon, items } = props;
const [navOpen, setNavOpen] = useState(false);

return (
<Popover
open={navOpen}
onOpenChange={setNavOpen}
side="right"
align="start"
trigger={
<div className="w-10 h-10 cursor-pointer bg-dark-500 rounded-md text-white flex justify-center items-center hover:bg-primary-100 hover:text-primary-500 transition-colors duration-200 relative">
<Icon name={icon} />
</div>
}
>
<div className="flex flex-col gap-2">
<PopoverNavigation
links={items}
onLinkClick={() => setNavOpen(false)}
/>
</div>
</Popover>
);
}

export default ButtonNav;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import PopoverNavigation, {
PopoverLink,
} from '../../popover-navigation/popover-navigation';
import Popover from '../../popover/popover';
import { useAuthUser, useLogout } from "@streali/shared/hooks";
import { useAuthUser, useLogout } from '@streali/shared/hooks';
import ButtonNav from './button-nav';
import { useState } from 'react';

export interface NavVerticalItems {
icon: string;
Expand All @@ -20,6 +22,7 @@ export function NavVertical(props: NavVerticalProps) {
const { data: user } = useAuthUser();
const { mutate: logout } = useLogout();
const { navigation } = props;
const [userNavOpen, setUserNavOpen] = useState(false);

const userNavigation: PopoverLink[] = [
{
Expand All @@ -43,26 +46,16 @@ export function NavVertical(props: NavVerticalProps) {
<div className="flex flex-col gap-1">
{navigation.map((item, index) => (
<div key={index}>
<Popover
side="right"
align="start"
trigger={
<div className="w-10 h-10 cursor-pointer bg-dark-500 rounded-md text-white flex justify-center items-center hover:bg-primary-100 hover:text-primary-500 transition-colors duration-200 relative">
<Icon name={item.icon} />
</div>
}
>
<div className="flex flex-col gap-2">
<PopoverNavigation links={item.items} />
</div>
</Popover>
<ButtonNav icon={item.icon} items={item.items} />
</div>
))}
</div>
</div>
<div>
{user && (
<Popover
open={userNavOpen}
onOpenChange={setUserNavOpen}
trigger={
<Avatar
className="cursor-pointer"
Expand All @@ -73,7 +66,10 @@ export function NavVertical(props: NavVerticalProps) {
side="right"
align="end"
>
<PopoverNavigation links={userNavigation} />
<PopoverNavigation
links={userNavigation}
onLinkClick={() => setUserNavOpen(false)}
/>
</Popover>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ export interface PopoverLink {

export interface PopoverNavigationProps {
links: PopoverLink[];
onLinkClick?: () => void;
}

export function PopoverNavigation(props: PopoverNavigationProps) {
const { links } = props;
const { links, onLinkClick } = props;

const colorClassName = {
primary: 'hover:bg-primary-500',
Expand All @@ -39,6 +40,7 @@ export function PopoverNavigation(props: PopoverNavigationProps) {
{!link.onClick && link.link && (
<Link
to={link.link}
onClick={onLinkClick}
className={`inline-flex h-7 gap-2 items-center px-2 transition-colors rounded cursor-pointer w-full ${
colorClassName[link.color || 'primary']
} ${link.className}`}
Expand All @@ -52,7 +54,10 @@ export function PopoverNavigation(props: PopoverNavigationProps) {
className={`inline-flex h-7 gap-2 items-center px-2 transition-colors rounded cursor-pointer w-full ${
colorClassName[link.color || 'primary']
} ${link.className}`}
onClick={link.onClick}
onClick={(e) => {
link.onClick && link.onClick(e);
onLinkClick && onLinkClick();
}}
>
{link.icon && <Icon name={link.icon} className="mr-1" />}
{link.title}
Expand All @@ -65,13 +70,21 @@ export function PopoverNavigation(props: PopoverNavigationProps) {
word={link.confirm.word}
confirmText={link.confirm.confirmText}
textButton={link.confirm.textButton}
onConfirm={link.confirm.onConfirm}
onConfirmationClose={onLinkClick}
onConfirm={() => {
link.confirm &&
link.confirm.onConfirm &&
link.confirm.onConfirm();
onLinkClick && onLinkClick();
}}
trigger={
<div
className={`inline-flex h-7 gap-2 items-center px-2 transition-colors rounded cursor-pointer w-full ${
colorClassName[link.color || 'primary']
} ${link.className}`}
onClick={link.onClick}
onClick={(e) => {
link.onClick && link.onClick(e);
}}
>
{link.icon && <Icon name={link.icon} className="mr-1" />}
{link.title}
Expand Down
Loading

0 comments on commit 7f237bb

Please sign in to comment.