From 1e9a04be55f3cd9643e82a7f89f47cf2d863bcb1 Mon Sep 17 00:00:00 2001 From: sjschlapbach Date: Sat, 17 Feb 2024 21:44:50 +0100 Subject: [PATCH] feat(Dropdown): restyle dropdown menu with modern appearance --- src/Dropdown.stories.tsx | 27 ++++++- src/Dropdown.tsx | 162 ++++++++++++++++++++------------------- 2 files changed, 109 insertions(+), 80 deletions(-) diff --git a/src/Dropdown.stories.tsx b/src/Dropdown.stories.tsx index 71ca68c8..66a7bfb5 100644 --- a/src/Dropdown.stories.tsx +++ b/src/Dropdown.stories.tsx @@ -1,4 +1,4 @@ -import { faFilter } from '@fortawesome/free-solid-svg-icons' +import { faFilter, faList } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import React, { useState } from 'react' import { twMerge } from 'tailwind-merge' @@ -15,7 +15,29 @@ export const Default = () => { not displayed. alert('Element 1 clicked'), + }, + { label: 'Element 2', onClick: () => alert('Element 2 clicked') }, + { + label: 'Element 3 short', + onClick: () => alert('Element 3 clicked'), + }, + { label: 'Element 4', onClick: () => alert('Element 4 clicked') }, + ]} + /> + + ) +} + +export const CustomIcon = () => { + return ( +
+ { }, { label: 'Element 4', onClick: () => alert('Element 4 clicked') }, ]} + triggerIcon={faList} />
) diff --git a/src/Dropdown.tsx b/src/Dropdown.tsx index c35886cb..354a54a5 100644 --- a/src/Dropdown.tsx +++ b/src/Dropdown.tsx @@ -1,3 +1,5 @@ +import { IconDefinition } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import * as RadixDropdown from '@radix-ui/react-dropdown-menu' import React from 'react' import { twMerge } from 'tailwind-merge' @@ -20,12 +22,11 @@ interface DropdownProps { test?: string } trigger: string | React.ReactNode + triggerIcon?: IconDefinition items?: Item[] activeItems?: string[] groups?: Item[][] className?: { - triggerOverride?: string - viewportOverride?: string trigger?: string triggerDisabled?: string viewport?: string @@ -52,6 +53,7 @@ export interface DropdownWithGroupsProps extends DropdownProps { * @param id - The id of the dropdown. * @param data - The object of data attributes that can be used for testing (e.g. data-test or data-cy) * @param trigger - The content of the trigger button or a custom trigger component to replace the default button. + * @param triggerIcon - The icon that is displayed next to the trigger content. * @param items - The items that are displayed in the dropdown menu. This attribute should not be set, if groups are used. * @param activeItems - List of labels that should be considered active. This attribute has a similar function as the "select" attribute on the item props and should not be used at the same time. * @param groups - The groups of items that are displayed in the dropdown menu. This attribute should not be set, if items are used. @@ -63,77 +65,13 @@ export function Dropdown({ id, data, trigger, + triggerIcon, items, activeItems, groups, className, disabled = false, }: DropdownWithItemsProps | DropdownWithGroupsProps) { - const DropdownItem = ({ - id, - data, - label, - active = false, - onClick, - shorting, - selected, - className, - }: { - id?: string - data?: { - cy?: string - test?: string - } - label: string | React.ReactNode - active?: boolean - onClick: () => void - shorting?: string - selected?: boolean - className?: { - override?: string - root?: string - active?: string - } - }) => { - if (typeof label === 'string') { - return ( - -
- {label} -
- {shorting &&
{shorting}
} -
- ) - } - return ( - - {label} - - ) - } - return ( {typeof trigger === 'string' ? ( @@ -142,15 +80,18 @@ export function Dropdown({ data-cy={data?.cy} data-test={data?.test} className={twMerge( - className?.triggerOverride, - `rounded-md border border-solid border-uzh-grey-60 px-2 py-1 hover:bg-primary-20`, - disabled && 'cursor-not-allowed text-gray-500 hover:bg-white', - className?.trigger, - className?.triggerDisabled + 'inline-flex h-7 items-center justify-between gap-3 rounded-md border', + 'bg-white py-1.5 pl-2 pr-2 shadow-sm hover:bg-primary-20 sm:hover:text-primary', + disabled && + 'hover:bg-none, sm:hover:text-none cursor-not-allowed bg-uzh-grey-20 opacity-70 shadow-sm', + className?.trigger )} disabled={disabled} > - {trigger} +
{trigger}
+ {triggerIcon && ( + + )} ) : ( {items && ( -
+
{items.map((item, index) => ( void + shorting?: string + selected?: boolean + className?: { + override?: string + root?: string + active?: string + } +}) => { + if (typeof label === 'string') { + return ( + +
+ {label} +
+ + {shorting &&
{shorting}
} +
+ ) + } + + return ( + + {label} + + ) +} + export default Dropdown