Skip to content

Commit

Permalink
feat: dismissable notice, dark mode support (#18)
Browse files Browse the repository at this point in the history
* feat: added darkmode support

* feat: dismissable notice

* refactor: Update Tooltip trigger to use asChild prop

* feat: Update Notice component styles for dark mode

* feat: add dismissible option to `Notice` component

* Add support for HTML in SwitchInput help text

* refactor(Modal): Update Modal styling for dark mode
  • Loading branch information
tareq1988 authored Feb 13, 2024
1 parent 7750550 commit 8115f26
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 15 deletions.
9 changes: 7 additions & 2 deletions src/Components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const Modal = ({ isOpen, onClose, maxWidth = 'lg', children }: PropsWithChildren
>
<div
className={classNames(
'inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:w-full',
'inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:w-full',
maxWidthClass
)}
>
Expand All @@ -75,7 +75,12 @@ const Modal = ({ isOpen, onClose, maxWidth = 'lg', children }: PropsWithChildren

const ModalHeader = ({ children, className }: PropsWithChildren<{ className?: string }>) => {
return (
<div className={classNames('text-lg font-medium text-gray-900 mb-4 px-5 pt-5', className)}>
<div
className={classNames(
'text-lg font-medium text-gray-900 dark:text-gray-300 mb-4 px-5 pt-5',
className
)}
>
{children}
</div>
);
Expand Down
45 changes: 34 additions & 11 deletions src/Components/Notice/Notice.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import React from 'react';
import React, { useState } from 'react';
import { twMerge } from 'tailwind-merge';
import {
ExclamationTriangleIcon,
XCircleIcon,
CheckCircleIcon,
InformationCircleIcon,
} from '@heroicons/react/20/solid';
import { XMarkIcon } from '@heroicons/react/24/outline';

export interface NoticeProps {
label?: React.ReactNode;
type?: 'success' | 'warning' | 'error' | 'info';
className?: string;
children?: React.ReactNode;
dismissible?: boolean;
}

const getNoticeColor = (type: NoticeProps['type']) => {
switch (type) {
case 'warning':
return 'bg-yellow-50 text-yellow-800 ring-yellow-600/20';
return 'bg-yellow-50 text-yellow-800 ring-yellow-600/20 dark:bg-yellow-700 dark:text-yellow-200 dark:ring-yellow-500/50';
case 'error':
return 'bg-red-50 text-red-700 ring-red-600/10';
return 'bg-red-50 text-red-700 ring-red-600/10 dark:bg-red-700 dark:text-red-200 dark:ring-red-500/50';
case 'info':
return 'bg-blue-50 text-blue-700 ring-blue-700/10';
return 'bg-blue-50 text-blue-700 ring-blue-700/10 dark:bg-blue-700 dark:text-blue-200 dark:ring-blue-500/50';
case 'success':
default:
return 'bg-green-50 text-green-700 ring-green-600/20';
return 'bg-green-50 text-green-700 ring-green-600/20 dark:bg-green-700 dark:text-green-200 dark:ring-green-500/50';
}
};

Expand All @@ -42,17 +44,38 @@ const getIcon = (type: NoticeProps['type']) => {
}
};

const Notice: React.FC<NoticeProps> = ({ label, type = 'success', className, children }) => {
const Notice: React.FC<NoticeProps> = ({
label,
type = 'success',
className,
dismissible = false,
children,
}) => {
const [isVisible, setIsVisible] = useState(true);
const color = getNoticeColor(type);

if (!isVisible) return null;

return (
<div className={twMerge('rounded-md p-4 ring-1 ring-inset w-full', color, className)}>
<div className="flex">
<div className="flex-shrink-0">{getIcon(type)}</div>
<div className="ml-3">
{label && <h3 className="text-sm font-medium">{label}</h3>}
{children && <div className="text-sm mt-2">{children}</div>}
<div className="flex justify-between">
<div className="flex">
<div className="flex-shrink-0">{getIcon(type)}</div>
<div className="ml-3">
{label && <h3 className="text-sm font-medium">{label}</h3>}
{children && <div className="text-sm mt-2">{children}</div>}
</div>
</div>

{dismissible && (
<button
onClick={() => setIsVisible(false)}
className="flex-shrink-0 ml-4"
title="Dismiss the notice"
>
<XMarkIcon className="h-4 w-4 text-gray-500 dark:text-gray-300" aria-hidden="true" />
</button>
)}
</div>
</div>
);
Expand Down
11 changes: 10 additions & 1 deletion src/Components/SwitchInput/SwitchInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type Props = {
initialValue?: boolean;
help?: ReactNode;
disabled?: boolean;
html?: boolean;
className?: string;
onChange?: (status: boolean) => void;
};
Expand All @@ -17,6 +18,7 @@ const SwitchInput = ({
label,
help,
disabled = false,
html = false,
className,
onChange,
}: Props) => {
Expand Down Expand Up @@ -61,7 +63,14 @@ const SwitchInput = ({
{label}
</label>

{help && <p className="text-gray-500 dark:text-gray-400 text-sm">{help}</p>}
{help && !html && <p className="text-gray-500 dark:text-gray-400 text-sm">{help}</p>}

{help && html && (
<p
className="text-gray-500 dark:text-gray-400 text-sm"
dangerouslySetInnerHTML={{ __html: help }}
/>
)}
</div>
</Switch.Label>
</Switch.Group>
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const Tooltip: React.FC<TooltipProps> = ({
return (
<TooltipPrimitive.Provider delayDuration={100}>
<TooltipPrimitive.Root>
<TooltipPrimitive.Trigger>{children}</TooltipPrimitive.Trigger>
<TooltipPrimitive.Trigger asChild>{children}</TooltipPrimitive.Trigger>
<TooltipPrimitive.Content
sideOffset={offset}
side={side}
Expand Down

0 comments on commit 8115f26

Please sign in to comment.