Skip to content

Commit 12d28f7

Browse files
committed
Merge branch 'develop' into chore/main-sync
2 parents 745b918 + fdf2c98 commit 12d28f7

31 files changed

+744
-405
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtron-labs/devtron-fe-common-lib",
3-
"version": "1.10.0-patch-3",
3+
"version": "1.10.6",
44
"description": "Supporting common component library",
55
"type": "module",
66
"main": "dist/index.js",

src/Common/ChartVersionAndTypeSelector.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ const ChartVersionAndTypeSelector = ({ setSelectedChartRefId }: ChartVersionAndT
8383
value={selectedChartType ?? chartTypeOptions[0]}
8484
options={chartTypeOptions}
8585
onChange={handleChartTypeChange}
86-
variant={SelectPickerVariantType.BORDER_LESS}
86+
variant={SelectPickerVariantType.COMPACT}
8787
/>
8888
</div>
8989
<div className="chart-version-options flex" data-testid="chart-version-options">
@@ -93,7 +93,7 @@ const ChartVersionAndTypeSelector = ({ setSelectedChartRefId }: ChartVersionAndT
9393
value={selectedChartVersion ?? chartVersionOptions[0]}
9494
options={chartVersionOptions}
9595
onChange={handleChartVersionChange}
96-
variant={SelectPickerVariantType.BORDER_LESS}
96+
variant={SelectPickerVariantType.COMPACT}
9797
/>
9898
</div>
9999
</div>

src/Common/DeleteCINodeButton/DeleteCINodeButton.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ export const DeleteCINodeButton = ({
117117
disabled={disabled}
118118
onClick={onClickDeleteShowModal}
119119
text="Delete Pipeline"
120+
variant={ButtonVariantType.secondary}
120121
style={ButtonStyleType.negative}
121122
/>
122123
)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { ReactElement } from 'react'
2+
import { Icon } from '@Shared/Components'
3+
import { ComponentSizeType } from '@Shared/constants'
4+
import { Tooltip } from '@Common/Tooltip'
5+
import { SegmentProps, SegmentType } from './types'
6+
import { COMPONENT_SIZE_TO_ICON_CLASS_MAP, COMPONENT_SIZE_TO_SEGMENT_CLASS_MAP } from './constants'
7+
import { ConditionalWrap } from '../Helper'
8+
9+
const wrapWithTooltip = (tooltipProps: SegmentType['tooltipProps']) => (children: ReactElement) => (
10+
<Tooltip content={tooltipProps.content} placement="bottom" {...tooltipProps} alwaysShowTippyOnHover>
11+
{children}
12+
</Tooltip>
13+
)
14+
15+
const Segment = ({
16+
segment,
17+
isSelected,
18+
name,
19+
selectedSegmentRef,
20+
onChange,
21+
fullWidth,
22+
size,
23+
disabled,
24+
}: SegmentProps) => {
25+
const { value, icon, isError, label, tooltipProps, ariaLabel } = segment
26+
const handleChange = () => {
27+
onChange(segment)
28+
}
29+
30+
return (
31+
<ConditionalWrap key={value} condition={!!tooltipProps?.content} wrap={wrapWithTooltip(tooltipProps)}>
32+
<div
33+
className={`dc__position-rel dc__text-center ${fullWidth ? 'flex-grow-1' : ''}`}
34+
ref={selectedSegmentRef}
35+
>
36+
<input
37+
type="radio"
38+
value={value}
39+
id={`${name}-${value}`}
40+
name={name}
41+
onChange={handleChange}
42+
checked={isSelected}
43+
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 dc__visibility-hidden"
44+
disabled={disabled}
45+
/>
46+
47+
<label
48+
htmlFor={`${name}-${value}`}
49+
className={`pointer m-0 flex ${!fullWidth ? 'left' : ''} dc__gap-4 br-4 segmented-control__segment segmented-control__segment--${size} ${isSelected ? 'fw-6 segmented-control__segment--selected' : 'fw-4'} ${segment.isError ? 'cr-5' : 'cn-9'} ${disabled ? 'cursor-not-allowed' : ''} ${COMPONENT_SIZE_TO_SEGMENT_CLASS_MAP[size]}`}
50+
aria-label={ariaLabel}
51+
>
52+
{(isError || icon) && (
53+
<span className={`flex ${COMPONENT_SIZE_TO_ICON_CLASS_MAP[size]}`}>
54+
<Icon
55+
{...(isError
56+
? {
57+
name: 'ic-error',
58+
color: null,
59+
}
60+
: {
61+
name: icon,
62+
color: isSelected ? 'N900' : 'N700',
63+
})}
64+
size={size === ComponentSizeType.xs ? 14 : 16}
65+
/>
66+
</span>
67+
)}
68+
{label && <span>{label}</span>}
69+
</label>
70+
</div>
71+
</ConditionalWrap>
72+
)
73+
}
74+
75+
export default Segment
Lines changed: 64 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,73 @@
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'
172
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'
216

227
const SegmentedControl = ({
23-
tabs,
24-
initialTab,
8+
segments,
259
onChange,
26-
tooltips,
27-
disabled = false,
28-
rootClassName = '',
2910
name,
30-
variant = SegmentedControlVariant.WHITE_ON_GRAY,
3111
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}
5050
>
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+
}
5672

5773
export default SegmentedControl
Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
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-
171
import { ComponentSizeType } from '@Shared/constants'
182
import { SegmentedControlProps } from './types'
193

20-
export const SEGMENTED_CONTROL_SIZE_TO_CLASS_MAP: Record<SegmentedControlProps['size'], string> = {
21-
[ComponentSizeType.medium]: '',
22-
[ComponentSizeType.large]: 'gui-yaml-switch--lg',
23-
}
4+
export const COMPONENT_SIZE_TO_SEGMENT_CLASS_MAP: Record<SegmentedControlProps['size'], string> = {
5+
[ComponentSizeType.xs]: 'py-2 px-6 fs-12 lh-18',
6+
[ComponentSizeType.small]: 'py-2 px-6 fs-12 lh-20',
7+
[ComponentSizeType.medium]: 'py-4 px-8 fs-13 lh-20',
8+
} as const
9+
10+
export const COMPONENT_SIZE_TO_ICON_CLASS_MAP: Record<SegmentedControlProps['size'], string> = {
11+
[ComponentSizeType.xs]: 'py-1',
12+
[ComponentSizeType.small]: 'py-2',
13+
[ComponentSizeType.medium]: 'py-2',
14+
} as const

src/Common/SegmentedControl/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@
1414
* limitations under the License.
1515
*/
1616

17-
export { type SegmentedControlProps, SegmentedControlVariant } from './types'
1817
export { default as SegmentedControl } from './SegmentedControl.component'
18+
export { type SegmentedControlProps } from './types'
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
.segmented-control {
2+
$segmented-control-selector: &;
3+
4+
background: var(--bg-segmented-control);
5+
6+
&__container {
7+
--segmented-control-highlight-width: auto;
8+
--segmented-control-highlight-x-position: 0;
9+
10+
&::before {
11+
content: '';
12+
background: var(--bg-primary);
13+
border-radius: 4px;
14+
width: var(--segmented-control-highlight-width);
15+
transform: translateX(var(--segmented-control-highlight-x-position));
16+
position: absolute;
17+
left: 0;
18+
z-index: 0;
19+
border: 0.5px solid var(--border-primary);
20+
box-shadow: 0px 1px 2px 0px var(--black-20);
21+
height: 100%;
22+
transition: transform 0.3s ease, width 0.3s ease;
23+
24+
&:has(#{$segmented-control-selector}__segment--xs) {
25+
top: 1px;
26+
bottom: 1px;
27+
}
28+
29+
&:has(#{$segmented-control-selector}__segment--small),
30+
&:has(#{$segmented-control-selector}__segment--medium) {
31+
top: 2px;
32+
bottom: 2px;
33+
}
34+
}
35+
}
36+
37+
&__segment {
38+
$parent-selector: &;
39+
transition: color 0.3s ease;
40+
41+
&:hover:not(#{$parent-selector}--selected) {
42+
background-color: var(--bg-secondary);
43+
}
44+
45+
&--selected {
46+
&#{$parent-selector} {
47+
48+
&--xs,
49+
&--small {
50+
padding-block: 1.5px;
51+
padding-inline: 5.5px;
52+
}
53+
54+
&--medium {
55+
padding-block: 3.5px;
56+
padding-inline: 7.5px;
57+
}
58+
}
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)