(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:
Nathan Panchout
2025-07-02 14:32:14 +02:00
committed by Anthony LC
parent 6af8d78ede
commit 1c5270e301
6 changed files with 81 additions and 64 deletions

View File

@@ -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 { Box, BoxButton, BoxProps, DropButton, Icon, Text } from '@/components';
@@ -14,6 +15,7 @@ export type DropdownMenuOption = {
isSelected?: boolean;
disabled?: boolean;
show?: boolean;
showSeparator?: boolean;
};
export type DropdownMenuProps = {
@@ -112,71 +114,76 @@ export const DropdownMenu = ({
}
const isDisabled = option.disabled !== undefined && option.disabled;
return (
<BoxButton
role="menuitem"
aria-label={option.label}
data-testid={option.testId}
$direction="row"
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
<Fragment key={option.label}>
<BoxButton
role="menuitem"
aria-label={option.label}
data-testid={option.testId}
$direction="row"
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);
}
`}
>
{option.icon && (
<Icon
$size="20px"
$theme="greyscale"
$variation={isDisabled ? '400' : '1000'}
iconName={option.icon}
/>
<Box
$direction="row"
$align="center"
$gap={spacingsTokens['base']}
>
{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'}>
{option.label}
</Text>
</Box>
{(option.isSelected ||
selectedValues?.includes(option.value ?? '')) && (
<Icon iconName="check" $size="20px" $theme="greyscale" />
</BoxButton>
{option.showSeparator && (
<HorizontalSeparator withPadding={false} />
)}
</BoxButton>
</Fragment>
);
})}
</Box>

View File

@@ -18,7 +18,7 @@ export const QuickSearchGroup = <T,>({
renderElement,
}: Props<T>) => {
return (
<Box $margin={{ top: 'base' }}>
<Box $margin={{ top: 'sm' }}>
<Command.Group
key={group.groupName}
heading={group.groupName}

View File

@@ -44,7 +44,7 @@ export const QuickSearchInput = ({
$align="center"
className="quick-search-input"
$gap={spacingsTokens['2xs']}
$padding={{ all: 'base' }}
$padding={{ horizontal: 'base', vertical: 'sm' }}
>
{!loading && <Icon iconName="search" $variation="600" />}
{loading && (

View File

@@ -24,8 +24,9 @@ export const QuickSearchItemContent = ({
<Box
$direction="row"
$align="center"
$padding={{ horizontal: '2xs', vertical: '3xs' }}
$padding={{ horizontal: '2xs', vertical: '4xs' }}
$justify="space-between"
$minHeight="34px"
$width="100%"
>
<Box

View File

@@ -1,4 +1,5 @@
import { useCunninghamTheme } from '@/cunningham';
import { Spacings } from '@/utils';
import { Box } from '../Box';
@@ -10,19 +11,25 @@ export enum SeparatorVariant {
type Props = {
variant?: SeparatorVariant;
$withPadding?: boolean;
customPadding?: Spacings;
};
export const HorizontalSeparator = ({
variant = SeparatorVariant.LIGHT,
$withPadding = true,
customPadding,
}: Props) => {
const { colorsTokens } = useCunninghamTheme();
const padding = $withPadding
? (customPadding ?? 'base')
: ('none' as Spacings);
return (
<Box
$height="1px"
$width="100%"
$margin={{ vertical: $withPadding ? 'base' : 'none' }}
$margin={{ vertical: padding }}
$background={
variant === SeparatorVariant.DARK
? '#e5e5e533'

View File

@@ -70,6 +70,8 @@ export const LeftPanel = () => {
position: fixed;
transform: translateX(${isPanelOpen ? '0' : '-100dvw'});
background-color: var(--c--theme--colors--greyscale-000);
overflow-y: auto;
overflow-x: hidden;
`}
className="--docs--left-panel-mobile"
>