Skip to content

Commit

Permalink
Feature/f 36 implement information popup and tooltip (#23)
Browse files Browse the repository at this point in the history
* feat: added sandbox page, added component skeletons for tooltip and information-popup components, added props interfaces for both components as well

* feat: setup sandbox

* feat: setup NextUI components

* feat: first working Tooltip wrapper component

* feat: finished tooptip components

* feat: setup information popup component and finished styling

* feat: finalized information popup

* feat: comments and cleanup

* feat: minor fixes

* feat: using h tags for title elements of tooltip and modal

* feat: removed testing sandbox page
  • Loading branch information
plaume8 authored Nov 11, 2024
1 parent 4335166 commit 11b9744
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# JetBrains
*.idea
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@nextui-org/kbd": "2.0.34",
"@nextui-org/link": "2.0.35",
"@nextui-org/listbox": "^2.1.27",
"@nextui-org/modal": "^2.0.41",
"@nextui-org/navbar": "2.0.37",
"@nextui-org/popover": "^2.1.29",
"@nextui-org/react": "^2.4.8",
Expand Down
79 changes: 79 additions & 0 deletions src/components/InformationPopup/InformationPopup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Modal, ModalBody, ModalContent, ModalHeader, useDisclosure } from '@nextui-org/modal';
import React, { useEffect } from 'react';

import InformationPopupProps from '@/domain/props/InformationPopupProps';

/**
* The InformationPopup component renders a popup with text content only. When the popup is open, the screen is dimmed,
* and only the popup is shown. The text content is specified using `content`, which can include multiple sections
* with a `title` (optional) and multiple text 'paragraphs'.
*
* To trigger the opening of the popup, a boolean variable `popupOpen` must be passed to the InformationPopup,
* so it knows whether it should be open or closed. To allow the popup to close itself, the `closePopup` function needs
* to be passed that the InformationPopup can trigger, which will then set popupOpen to false. This should usually
* be implemented using React’s `useState`.
* @param popupOpen state if popup is open or closed
* @param closePopup function that can be called by the popup, which changes the popupOpen to `false`
* @param title title of the entire popup
* @param content popups text sections - each section contains an title (optional) and a list of paragraphs
* @param warning selected if the popup should be highlighted (optional)
* @constructor
*/
export function InformationPopup({ popupOpen, closePopup, title, content, warning }: InformationPopupProps) {
const SIZE = 'md';
const PLACEMENT = 'auto'; // bigger screens: centered, mobile: bottom
const BACKDROP = 'opaque';
const RADIUS = 'sm';
const SCROLL_BEHAVIOUR = 'inside';

/**
* If the InformationPopup is opened by the parent component, popupOpen is set to `true` by the parent.
* When the InformationPopup is closed, the parent component should be notified so that popupOpen can set to false.
*/
const { isOpen, onOpen, onOpenChange } = useDisclosure();

useEffect(() => {
if (popupOpen) onOpen();
}, [popupOpen]);

useEffect(() => {
if (!isOpen) closePopup();
}, [isOpen]);

/**
* Setup content.
*/

const borderStyle = warning ? 'border-4 border-warning' : '';

const textContent = content.map((c) => {
return (
<>
<h2 className="text-small font-bold mt-4"> {c.subtitle} </h2>
{c.paragraphs.map((t, idx) => (
<p id={t + idx} className="text-small font-normal">
{t}
</p>
))}
</>
);
});

return (
<Modal
backdrop={BACKDROP}
isOpen={isOpen}
onOpenChange={onOpenChange}
radius={RADIUS}
size={SIZE}
placement={PLACEMENT}
scrollBehavior={SCROLL_BEHAVIOUR}
className="bg-background"
>
<ModalContent className={`${borderStyle} pb-3`}>
<ModalHeader className="flex flex-col text-medium font-bold gap-1"> {title} </ModalHeader>
<ModalBody className="gap-1"> {...textContent} </ModalBody>
</ModalContent>
</Modal>
);
}
2 changes: 1 addition & 1 deletion src/components/PopupModal/PopupModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { Modal, ModalBody, ModalContent, ModalHeader } from '@nextui-org/react';
import { Modal, ModalBody, ModalContent, ModalHeader } from '@nextui-org/modal';

import PopupModalProps from '@/domain/props/PopupModalProps';

Expand Down
46 changes: 46 additions & 0 deletions src/components/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Tooltip as NextUITooltip } from '@nextui-org/tooltip';

import TooltipProps from '@/domain/props/TooltipProps';

/**
* The Tooltip component renders a customizable tooltip. It is based on the NextUI Tooltip component.
* It should be used as a wrapper for one or more components.
* When hovering over these wrapped components, the tooltip appears with a delay.
* @param children the wrapped components
* @param title title of the tooltip (optional)
* @param text textual content of the tooltip
* @param warning selected if the tooltip should be highlighted (optional)
* @constructor
*/
export function Tooltip({ children, title, text, warning }: TooltipProps) {
const DELAY: number = 1000;
const OFFSET: number = 10;
const RADIUS = 'sm';
const SHADOW = 'md';
const COLOR = 'default';

const borderStyle = warning ? 'border-2 border-warning' : '';

const tooltipContent = title ? (
<div>
<h3 className="text-small font-bold mb-1"> {title} </h3>
<p className="text-small font-normal"> {text} </p>
</div>
) : (
<p className="text-small font-normal"> {text} </p>
);

return (
<NextUITooltip
className={`${borderStyle} px-2.5 py-1.5 max-w-2xl`}
content={tooltipContent}
color={COLOR}
delay={DELAY}
offset={OFFSET}
radius={RADIUS}
shadow={SHADOW}
>
{Array.isArray(children) ? <> {...children} </> : children}
</NextUITooltip>
);
}
10 changes: 10 additions & 0 deletions src/domain/props/InformationPopupProps.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default interface InformationPopupProps {
popupOpen: boolean;
closePopup: () => void;
title: string;
content: {
subtitle?: string;
paragraphs: string[];
}[];
warning?: boolean;
}
8 changes: 8 additions & 0 deletions src/domain/props/TooltipProps.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ReactNode } from 'react';

export default interface TooltipProps {
children: ReactNode | ReactNode[];
title?: string;
text: string;
warning?: boolean;
}

0 comments on commit 11b9744

Please sign in to comment.