✨(frontend) enhance dropdown menu and quick search components
- Added a horizontal separator to the dropdown menu for better visual distinction between options. - Updated padding in the quick search input for improved layout consistency. - Adjusted margin in the quick search group for better spacing. - Increased vertical padding in quick search item content for enhanced readability. - Modified the horizontal separator to accept custom padding for more flexible styling. - Improved left panel styling to manage overflow behavior effectively. - Removed unused skeleton loading styles from globals.css to clean up the codebase.
This commit is contained in:
committed by
Anthony LC
parent
6af8d78ede
commit
1c5270e301
@@ -1,4 +1,5 @@
|
|||||||
import { PropsWithChildren, useRef, useState } from 'react';
|
import { HorizontalSeparator } from '@gouvfr-lasuite/ui-kit';
|
||||||
|
import { Fragment, PropsWithChildren, useRef, useState } from 'react';
|
||||||
import { css } from 'styled-components';
|
import { css } from 'styled-components';
|
||||||
|
|
||||||
import { Box, BoxButton, BoxProps, DropButton, Icon, Text } from '@/components';
|
import { Box, BoxButton, BoxProps, DropButton, Icon, Text } from '@/components';
|
||||||
@@ -14,6 +15,7 @@ export type DropdownMenuOption = {
|
|||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
show?: boolean;
|
show?: boolean;
|
||||||
|
showSeparator?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DropdownMenuProps = {
|
export type DropdownMenuProps = {
|
||||||
@@ -112,71 +114,76 @@ export const DropdownMenu = ({
|
|||||||
}
|
}
|
||||||
const isDisabled = option.disabled !== undefined && option.disabled;
|
const isDisabled = option.disabled !== undefined && option.disabled;
|
||||||
return (
|
return (
|
||||||
<BoxButton
|
<Fragment key={option.label}>
|
||||||
role="menuitem"
|
<BoxButton
|
||||||
aria-label={option.label}
|
role="menuitem"
|
||||||
data-testid={option.testId}
|
aria-label={option.label}
|
||||||
$direction="row"
|
data-testid={option.testId}
|
||||||
disabled={isDisabled}
|
|
||||||
onClick={(event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
onOpenChange?.(false);
|
|
||||||
void option.callback?.();
|
|
||||||
}}
|
|
||||||
key={option.label}
|
|
||||||
$align="center"
|
|
||||||
$justify="space-between"
|
|
||||||
$background={colorsTokens['greyscale-000']}
|
|
||||||
$color={colorsTokens['primary-600']}
|
|
||||||
$padding={{ vertical: 'xs', horizontal: 'base' }}
|
|
||||||
$width="100%"
|
|
||||||
$gap={spacingsTokens['base']}
|
|
||||||
$css={css`
|
|
||||||
border: none;
|
|
||||||
${index === 0 &&
|
|
||||||
css`
|
|
||||||
border-top-left-radius: 4px;
|
|
||||||
border-top-right-radius: 4px;
|
|
||||||
`}
|
|
||||||
${index === options.length - 1 &&
|
|
||||||
css`
|
|
||||||
border-bottom-left-radius: 4px;
|
|
||||||
border-bottom-right-radius: 4px;
|
|
||||||
`}
|
|
||||||
font-size: var(--c--theme--font--sizes--sm);
|
|
||||||
color: var(--c--theme--colors--greyscale-1000);
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: ${isDisabled ? 'not-allowed' : 'pointer'};
|
|
||||||
user-select: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--c--theme--colors--greyscale-050);
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
$direction="row"
|
$direction="row"
|
||||||
|
disabled={isDisabled}
|
||||||
|
onClick={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
onOpenChange?.(false);
|
||||||
|
void option.callback?.();
|
||||||
|
}}
|
||||||
|
key={option.label}
|
||||||
$align="center"
|
$align="center"
|
||||||
|
$justify="space-between"
|
||||||
|
$background={colorsTokens['greyscale-000']}
|
||||||
|
$color={colorsTokens['primary-600']}
|
||||||
|
$padding={{ vertical: 'xs', horizontal: 'base' }}
|
||||||
|
$width="100%"
|
||||||
$gap={spacingsTokens['base']}
|
$gap={spacingsTokens['base']}
|
||||||
|
$css={css`
|
||||||
|
border: none;
|
||||||
|
${index === 0 &&
|
||||||
|
css`
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
`}
|
||||||
|
${index === options.length - 1 &&
|
||||||
|
css`
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
`}
|
||||||
|
font-size: var(--c--theme--font--sizes--sm);
|
||||||
|
color: var(--c--theme--colors--greyscale-1000);
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: ${isDisabled ? 'not-allowed' : 'pointer'};
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--c--theme--colors--greyscale-050);
|
||||||
|
}
|
||||||
|
`}
|
||||||
>
|
>
|
||||||
{option.icon && (
|
<Box
|
||||||
<Icon
|
$direction="row"
|
||||||
$size="20px"
|
$align="center"
|
||||||
$theme="greyscale"
|
$gap={spacingsTokens['base']}
|
||||||
$variation={isDisabled ? '400' : '1000'}
|
>
|
||||||
iconName={option.icon}
|
{option.icon && (
|
||||||
/>
|
<Icon
|
||||||
|
$size="20px"
|
||||||
|
$theme="greyscale"
|
||||||
|
$variation={isDisabled ? '400' : '1000'}
|
||||||
|
iconName={option.icon}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Text $variation={isDisabled ? '400' : '1000'}>
|
||||||
|
{option.label}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
{(option.isSelected ||
|
||||||
|
selectedValues?.includes(option.value ?? '')) && (
|
||||||
|
<Icon iconName="check" $size="20px" $theme="greyscale" />
|
||||||
)}
|
)}
|
||||||
<Text $variation={isDisabled ? '400' : '1000'}>
|
</BoxButton>
|
||||||
{option.label}
|
{option.showSeparator && (
|
||||||
</Text>
|
<HorizontalSeparator withPadding={false} />
|
||||||
</Box>
|
|
||||||
{(option.isSelected ||
|
|
||||||
selectedValues?.includes(option.value ?? '')) && (
|
|
||||||
<Icon iconName="check" $size="20px" $theme="greyscale" />
|
|
||||||
)}
|
)}
|
||||||
</BoxButton>
|
</Fragment>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const QuickSearchGroup = <T,>({
|
|||||||
renderElement,
|
renderElement,
|
||||||
}: Props<T>) => {
|
}: Props<T>) => {
|
||||||
return (
|
return (
|
||||||
<Box $margin={{ top: 'base' }}>
|
<Box $margin={{ top: 'sm' }}>
|
||||||
<Command.Group
|
<Command.Group
|
||||||
key={group.groupName}
|
key={group.groupName}
|
||||||
heading={group.groupName}
|
heading={group.groupName}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export const QuickSearchInput = ({
|
|||||||
$align="center"
|
$align="center"
|
||||||
className="quick-search-input"
|
className="quick-search-input"
|
||||||
$gap={spacingsTokens['2xs']}
|
$gap={spacingsTokens['2xs']}
|
||||||
$padding={{ all: 'base' }}
|
$padding={{ horizontal: 'base', vertical: 'sm' }}
|
||||||
>
|
>
|
||||||
{!loading && <Icon iconName="search" $variation="600" />}
|
{!loading && <Icon iconName="search" $variation="600" />}
|
||||||
{loading && (
|
{loading && (
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ export const QuickSearchItemContent = ({
|
|||||||
<Box
|
<Box
|
||||||
$direction="row"
|
$direction="row"
|
||||||
$align="center"
|
$align="center"
|
||||||
$padding={{ horizontal: '2xs', vertical: '3xs' }}
|
$padding={{ horizontal: '2xs', vertical: '4xs' }}
|
||||||
$justify="space-between"
|
$justify="space-between"
|
||||||
|
$minHeight="34px"
|
||||||
$width="100%"
|
$width="100%"
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useCunninghamTheme } from '@/cunningham';
|
import { useCunninghamTheme } from '@/cunningham';
|
||||||
|
import { Spacings } from '@/utils';
|
||||||
|
|
||||||
import { Box } from '../Box';
|
import { Box } from '../Box';
|
||||||
|
|
||||||
@@ -10,19 +11,25 @@ export enum SeparatorVariant {
|
|||||||
type Props = {
|
type Props = {
|
||||||
variant?: SeparatorVariant;
|
variant?: SeparatorVariant;
|
||||||
$withPadding?: boolean;
|
$withPadding?: boolean;
|
||||||
|
customPadding?: Spacings;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const HorizontalSeparator = ({
|
export const HorizontalSeparator = ({
|
||||||
variant = SeparatorVariant.LIGHT,
|
variant = SeparatorVariant.LIGHT,
|
||||||
$withPadding = true,
|
$withPadding = true,
|
||||||
|
customPadding,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { colorsTokens } = useCunninghamTheme();
|
const { colorsTokens } = useCunninghamTheme();
|
||||||
|
|
||||||
|
const padding = $withPadding
|
||||||
|
? (customPadding ?? 'base')
|
||||||
|
: ('none' as Spacings);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
$height="1px"
|
$height="1px"
|
||||||
$width="100%"
|
$width="100%"
|
||||||
$margin={{ vertical: $withPadding ? 'base' : 'none' }}
|
$margin={{ vertical: padding }}
|
||||||
$background={
|
$background={
|
||||||
variant === SeparatorVariant.DARK
|
variant === SeparatorVariant.DARK
|
||||||
? '#e5e5e533'
|
? '#e5e5e533'
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ export const LeftPanel = () => {
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
transform: translateX(${isPanelOpen ? '0' : '-100dvw'});
|
transform: translateX(${isPanelOpen ? '0' : '-100dvw'});
|
||||||
background-color: var(--c--theme--colors--greyscale-000);
|
background-color: var(--c--theme--colors--greyscale-000);
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
`}
|
`}
|
||||||
className="--docs--left-panel-mobile"
|
className="--docs--left-panel-mobile"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user