|
1 | | -/* |
2 | | - * Copyright (c) 2024. Devtron Inc. |
3 | | - * |
4 | | - * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | - * you may not use this file except in compliance with the License. |
6 | | - * You may obtain a copy of the License at |
7 | | - * |
8 | | - * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | - * |
10 | | - * Unless required by applicable law or agreed to in writing, software |
11 | | - * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | - * See the License for the specific language governing permissions and |
14 | | - * limitations under the License. |
15 | | - */ |
16 | | - |
| 1 | +import { useEffect, useRef, useState } from 'react' |
17 | 2 | import { ComponentSizeType } from '@Shared/constants' |
18 | | -import StyledRadioGroup from '../RadioGroup/RadioGroup' |
19 | | -import { SegmentedControlProps, SegmentedControlVariant } from './types' |
20 | | -import { SEGMENTED_CONTROL_SIZE_TO_CLASS_MAP } from './constants' |
| 3 | +import { SegmentedControlProps, SegmentType } from './types' |
| 4 | +import './segmentedControl.scss' |
| 5 | +import Segment from './Segment' |
21 | 6 |
|
22 | 7 | const SegmentedControl = ({ |
23 | | - tabs, |
24 | | - initialTab, |
| 8 | + segments, |
25 | 9 | onChange, |
26 | | - tooltips, |
27 | | - disabled = false, |
28 | | - rootClassName = '', |
29 | 10 | name, |
30 | | - variant = SegmentedControlVariant.WHITE_ON_GRAY, |
31 | 11 | size = ComponentSizeType.medium, |
32 | | - isControlled = false, |
33 | | -}: SegmentedControlProps) => ( |
34 | | - <StyledRadioGroup |
35 | | - className={`${variant} ${SEGMENTED_CONTROL_SIZE_TO_CLASS_MAP[size]} ${rootClassName}`} |
36 | | - onChange={onChange} |
37 | | - initialTab={initialTab} |
38 | | - name={name} |
39 | | - disabled={disabled} |
40 | | - > |
41 | | - {tabs.map((tab, index) => ( |
42 | | - <StyledRadioGroup.Radio |
43 | | - value={tab.value} |
44 | | - key={tab.value} |
45 | | - className="fs-12 cn-7 fw-6 lh-20" |
46 | | - showTippy={!!tooltips?.[index]} |
47 | | - tippyContent={tooltips?.[index] ?? ''} |
48 | | - dataTestId={`${name}-${tab.value}`} |
49 | | - canSelect={!isControlled} |
| 12 | + value: controlledValue, |
| 13 | + fullWidth = false, |
| 14 | + disabled, |
| 15 | +}: SegmentedControlProps) => { |
| 16 | + const isUnControlledComponent = controlledValue === undefined |
| 17 | + |
| 18 | + const segmentedControlRefContainer = useRef<HTMLDivElement>(null) |
| 19 | + /** |
| 20 | + * Using this ref to show the selected segment highlight with transition |
| 21 | + */ |
| 22 | + const selectedSegmentRef = useRef<HTMLDivElement>(null) |
| 23 | + const [selectedSegmentValue, setSelectedSegmentValue] = useState<SegmentType['value'] | null>(segments[0].value) |
| 24 | + const segmentValue = isUnControlledComponent ? selectedSegmentValue : controlledValue |
| 25 | + |
| 26 | + useEffect(() => { |
| 27 | + if (segmentValue) { |
| 28 | + const { offsetWidth, offsetLeft } = selectedSegmentRef.current |
| 29 | + const { style } = segmentedControlRefContainer.current |
| 30 | + |
| 31 | + style.setProperty('--segmented-control-highlight-width', `${offsetWidth}px`) |
| 32 | + style.setProperty('--segmented-control-highlight-x-position', `${offsetLeft}px`) |
| 33 | + } |
| 34 | + }, [segmentValue, size, fullWidth]) |
| 35 | + |
| 36 | + const handleSegmentChange = (updatedSegment: SegmentType) => { |
| 37 | + if (isUnControlledComponent) { |
| 38 | + setSelectedSegmentValue(updatedSegment.value) |
| 39 | + } |
| 40 | + onChange?.(updatedSegment) |
| 41 | + } |
| 42 | + |
| 43 | + return ( |
| 44 | + <div |
| 45 | + className={`segmented-control ${!fullWidth ? 'dc__inline-flex' : ''} ${disabled ? 'dc__disabled' : ''} br-6 ${size === ComponentSizeType.xs ? 'p-1' : 'p-2'}`} |
| 46 | + > |
| 47 | + <div |
| 48 | + className="segmented-control__container flex left dc__position-rel dc__align-items-center dc__gap-2" |
| 49 | + ref={segmentedControlRefContainer} |
50 | 50 | > |
51 | | - {tab.label} |
52 | | - </StyledRadioGroup.Radio> |
53 | | - ))} |
54 | | - </StyledRadioGroup> |
55 | | -) |
| 51 | + {segments.map((segment) => { |
| 52 | + const isSelected = segment.value === segmentValue |
| 53 | + |
| 54 | + return ( |
| 55 | + <Segment |
| 56 | + selectedSegmentRef={isSelected ? selectedSegmentRef : undefined} |
| 57 | + segment={segment} |
| 58 | + key={segment.value} |
| 59 | + name={name} |
| 60 | + onChange={handleSegmentChange} |
| 61 | + isSelected={isSelected} |
| 62 | + fullWidth={fullWidth} |
| 63 | + size={size} |
| 64 | + disabled={disabled} |
| 65 | + /> |
| 66 | + ) |
| 67 | + })} |
| 68 | + </div> |
| 69 | + </div> |
| 70 | + ) |
| 71 | +} |
56 | 72 |
|
57 | 73 | export default SegmentedControl |
0 commit comments