Skip to content

Commit 2b0a7da

Browse files
committed
feat: add tooltip, icon and aria label
1 parent 74b78e6 commit 2b0a7da

File tree

3 files changed

+101
-34
lines changed

3 files changed

+101
-34
lines changed

src/Common/SegmentedControl/NSegmentedControl.component.tsx

Lines changed: 79 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,58 @@
1-
import { useState } from 'react'
2-
import { SelectPickerOptionType } from '@Shared/Components'
1+
import { ReactElement, useState } from 'react'
2+
import { Icon, IconsProps, SelectPickerOptionType } from '@Shared/Components'
33
import { ComponentSizeType } from '@Shared/constants'
4+
import './segmentedControl.scss'
5+
import { ConditionalWrap, Tooltip, TooltipProps } from '..'
46

5-
type SegmentType = Pick<SelectPickerOptionType, 'label' | 'value' | 'startIcon' | 'tooltipProps'>
7+
type SegmentTooltipProps = Omit<
8+
TooltipProps,
9+
'alwaysShowTippyOnHover' | 'showOnTruncate' | 'shortcutKeyCombo' | 'placement'
10+
>
11+
12+
type SegmentType = Pick<SelectPickerOptionType, 'value'> & {
13+
isError?: boolean
14+
icon?: IconsProps['name']
15+
} & (
16+
| ({
17+
label: SelectPickerOptionType['label']
18+
icon?: IconsProps['name']
19+
tooltipProps?: SegmentTooltipProps
20+
ariaLabel?: never
21+
} & Pick<SelectPickerOptionType, 'label'>)
22+
| {
23+
label?: never
24+
tooltipProps: SegmentTooltipProps
25+
icon: IconsProps['name']
26+
ariaLabel: string
27+
}
28+
)
629

730
export interface NSegmentedControlProps {
831
segments: SegmentType[]
932
// initialSelectedTab: TabType['value']
1033
onChange?: (selectedTab: SegmentType) => void
11-
// disabled?: boolean
1234
name: string
1335
size?: Extract<ComponentSizeType, ComponentSizeType.xs | ComponentSizeType.small | ComponentSizeType.medium>
1436
}
1537

1638
export const COMPONENT_SIZE_TO_SEGMENT_CLASS_MAP: Record<NSegmentedControlProps['size'], string> = {
17-
[ComponentSizeType.xs]: 'py-1 px-5',
18-
[ComponentSizeType.small]: 'py-1 px-5',
19-
[ComponentSizeType.medium]: 'py-3 px-7',
39+
[ComponentSizeType.xs]: 'py-2 px-6 fs-12 lh-18',
40+
[ComponentSizeType.small]: 'py-2 px-6 fs-12 lh-20',
41+
[ComponentSizeType.medium]: 'py-4 px-8 fs-13 lh-20',
42+
} as const
43+
44+
export const COMPONENT_SIZE_TO_ICON_CLASS_MAP: Record<NSegmentedControlProps['size'], string> = {
45+
[ComponentSizeType.xs]: 'py-1',
46+
[ComponentSizeType.small]: 'py-2',
47+
[ComponentSizeType.medium]: 'py-2',
2048
} as const
2149

50+
const wrapWithTooltip = (tooltipProps: SegmentType['tooltipProps']) => (children: ReactElement) => (
51+
<Tooltip content={tooltipProps.content} placement="bottom" {...tooltipProps} alwaysShowTippyOnHover>
52+
{children}
53+
</Tooltip>
54+
)
55+
2256
const NSegmentedControl = ({ segments, onChange, name, size = ComponentSizeType.medium }: NSegmentedControlProps) => {
2357
const [selectedSegmentValue, setSelectedSegmentValue] = useState<SegmentType['value'] | null>(segments[0].value)
2458

@@ -28,47 +62,60 @@ const NSegmentedControl = ({ segments, onChange, name, size = ComponentSizeType.
2862
}
2963

3064
return (
31-
<div>
32-
<div
33-
className={`dc__inline-flex dc__content-center dc__align-items-center dc__gap-2 br-6 bg__tertiary ${size === ComponentSizeType.xs ? 'p-1' : 'p-2'}`}
34-
>
35-
{segments.map((segment) => {
36-
const isSelected = segment.value === selectedSegmentValue
65+
<div
66+
className={`dc__inline-flex dc__content-center dc__align-items-center dc__gap-2 br-6 bg__tertiary ${size === ComponentSizeType.xs ? 'p-1' : 'p-2'}`}
67+
>
68+
{segments.map((segment) => {
69+
const { value, icon, isError, label, tooltipProps, ariaLabel } = segment
70+
const isSelected = value === selectedSegmentValue
3771

38-
return (
72+
return (
73+
<ConditionalWrap
74+
key={value}
75+
condition={!!tooltipProps?.content}
76+
wrap={wrapWithTooltip(tooltipProps)}
77+
>
3978
<div
40-
key={segment.value}
41-
// className={`segment ${i === activeIndex ? 'active' : 'inactive'}`}
4279
// ref={item.ref}
4380
className="dc__position-rel dc__text-center"
4481
>
4582
<input
4683
type="radio"
47-
value={segment.value}
48-
id={`${name}-${segment.value}`}
84+
value={value}
85+
id={`${name}-${value}`}
4986
name={name}
5087
onChange={() => handleSegmentChange(segment)}
5188
checked={isSelected}
5289
className="dc__opacity-0 m-0-imp dc__top-0 dc__left-0 dc__position-abs dc__bottom-0 dc__right-0 w-100 pointer h-100"
5390
/>
91+
5492
<label
55-
htmlFor={`${name}-${segment.value}`}
56-
className={`pointer m-0 dc__block br-4 flex py-1 px-5 flex dc__gap-4 ${isSelected ? 'bg__primary' : ''} ${COMPONENT_SIZE_TO_SEGMENT_CLASS_MAP[size]}`}
57-
style={
58-
isSelected
59-
? {
60-
border: '1px solid var(--border-secondary)',
61-
boxShadow: '0px 1px 2px 0px var(--black-20)',
62-
}
63-
: {}
64-
}
93+
htmlFor={`${name}-${value}`}
94+
className={`pointer m-0 flex left dc__gap-4 br-4 dc__gap-4 segmented-control__segment segmented-control__segment--${size} ${isSelected ? 'bg__primary fw-6 segmented-control__segment--selected' : 'fw-4'} ${segment.isError ? 'cr-5' : 'cn-9'} ${COMPONENT_SIZE_TO_SEGMENT_CLASS_MAP[size]}`}
95+
aria-label={ariaLabel}
6596
>
66-
{segment.label}
97+
{(isError || icon) && (
98+
<span className={`flex ${COMPONENT_SIZE_TO_ICON_CLASS_MAP[size]}`}>
99+
<Icon
100+
{...(isError
101+
? {
102+
name: 'ic-error',
103+
color: null,
104+
}
105+
: {
106+
name: icon,
107+
color: isSelected ? 'N900' : 'N700',
108+
})}
109+
size={size === ComponentSizeType.xs ? 14 : 16}
110+
/>
111+
</span>
112+
)}
113+
{label && <span>{label}</span>}
67114
</label>
68115
</div>
69-
)
70-
})}
71-
</div>
116+
</ConditionalWrap>
117+
)
118+
})}
72119
</div>
73120
)
74121
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
.segmented-control {
2+
&__segment {
3+
$parent-selector: &;
4+
5+
&--selected {
6+
border: 0.5px solid var(--border-secondary);
7+
box-shadow: 0px 1px 2px 0px var(--black-20);
8+
9+
&#{$parent-selector} {
10+
&--xs, &--small {
11+
padding-block: 1.5px;
12+
padding-inline: 5.5px;
13+
}
14+
15+
&--medium {
16+
padding-block: 3.5px;
17+
padding-inline: 7.5px;
18+
}
19+
}
20+
}
21+
}
22+
}

src/Shared/Components/Button/button.scss

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@
6060
}
6161

6262
@mixin pseudo-states($hover-bg-color, $active-bg-color, $hover-border-color: null, $color: null) {
63-
$parent-selector: &;
64-
6563
&:hover:not([disabled]) {
6664
background: $hover-bg-color;
6765

0 commit comments

Comments
 (0)