Skip to content

Commit 88bd3e5

Browse files
authored
feat: select elements disabled (#374)
1 parent 614e97c commit 88bd3e5

File tree

14 files changed

+196
-137
lines changed

14 files changed

+196
-137
lines changed

src/components/input-elements/DateRangePicker/DateRangePicker.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export interface DateRangePickerProps
4646
placeholder?: string;
4747
dropdownPlaceholder?: string;
4848
enableYearPagination?: boolean;
49+
disabled?: boolean;
4950
color?: Color;
5051
locale?: Locale;
5152
}
@@ -61,6 +62,7 @@ const DateRangePicker = React.forwardRef<HTMLDivElement, DateRangePickerProps>((
6162
maxDate = null,
6263
placeholder = "Select",
6364
dropdownPlaceholder = "Select",
65+
disabled = false,
6466
color = BaseColors.Blue,
6567
enableYearPagination = false,
6668
locale = enUS,
@@ -145,6 +147,7 @@ const DateRangePicker = React.forwardRef<HTMLDivElement, DateRangePickerProps>((
145147
value={[selectedStartDate, selectedEndDate, selectedDropdownValue]}
146148
options={dropdownOptions}
147149
placeholder={placeholder}
150+
disabled={disabled}
148151
calendarRef={calendarRef}
149152
showCalendar={showCalendar}
150153
setShowCalendar={setShowCalendar}

src/components/input-elements/DateRangePicker/DateRangePickerButton.tsx

Lines changed: 13 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React, { Dispatch, Ref, SetStateAction } from "react";
22
import { twMerge } from "tailwind-merge";
3-
import { isEqual } from "date-fns";
43

54
import { ArrowDownHeadIcon, CalendarIcon } from "assets";
65

@@ -18,54 +17,14 @@ import {
1817

1918
import { DateRangePickerOption, DateRangePickerValue } from "./DateRangePicker";
2019
import { DEFAULT_COLOR, colorPalette } from "lib/theme";
21-
import { makeDateRangePickerClassName } from "./dateRangePickerUtils";
22-
23-
const formatSelectedDates = (startDate: Date | null, endDate: Date | null, locale?: Locale) => {
24-
const localeCode = locale?.code || "en-US";
25-
if (!startDate && !endDate) {
26-
return "";
27-
} else if (startDate && !endDate) {
28-
const options: Intl.DateTimeFormatOptions = {
29-
year: "numeric",
30-
month: "short",
31-
day: "numeric",
32-
};
33-
return startDate.toLocaleDateString(localeCode, options);
34-
} else if (startDate && endDate) {
35-
if (isEqual(startDate, endDate)) {
36-
const options: Intl.DateTimeFormatOptions = {
37-
year: "numeric",
38-
month: "short",
39-
day: "numeric",
40-
};
41-
return startDate.toLocaleDateString(localeCode, options);
42-
} else if (
43-
startDate.getMonth() === endDate.getMonth() &&
44-
startDate.getFullYear() === endDate.getFullYear()
45-
) {
46-
const optionsStartDate: Intl.DateTimeFormatOptions = {
47-
month: "short",
48-
day: "numeric",
49-
};
50-
return `${startDate.toLocaleDateString(localeCode, optionsStartDate)} -
51-
${endDate.getDate()}, ${endDate.getFullYear()}`;
52-
} else {
53-
const options: Intl.DateTimeFormatOptions = {
54-
year: "numeric",
55-
month: "short",
56-
day: "numeric",
57-
};
58-
return `${startDate.toLocaleDateString(localeCode, options)} -
59-
${endDate.toLocaleDateString(localeCode, options)}`;
60-
}
61-
}
62-
return "";
63-
};
20+
import { formatSelectedDates, makeDateRangePickerClassName } from "./dateRangePickerUtils";
21+
import { getSelectButtonColors, hasValue } from "../selectUtils";
6422

6523
interface DateRangePickerButtonProps {
6624
value: DateRangePickerValue;
6725
options: DateRangePickerOption[];
6826
placeholder: string;
27+
disabled: boolean;
6928
calendarRef: Ref<HTMLButtonElement>;
7029
showCalendar: boolean;
7130
setShowCalendar: Dispatch<SetStateAction<boolean>>;
@@ -83,6 +42,7 @@ const DateRangePickerButton = ({
8342
value,
8443
options,
8544
placeholder,
45+
disabled,
8646
calendarRef,
8747
showCalendar,
8848
setShowCalendar,
@@ -96,8 +56,11 @@ const DateRangePickerButton = ({
9656
dropdownPlaceholder = "Select",
9757
}: DateRangePickerButtonProps) => {
9858
const [startDate, endDate, dropdownValue] = value;
99-
const hasSelection = (startDate || endDate) !== null;
100-
const calendarText = hasSelection
59+
60+
const hasDateSelection = (startDate || endDate) !== null && (startDate || endDate) !== undefined;
61+
const hasDropdownSelection = hasValue(dropdownValue);
62+
63+
const calendarText = hasDateSelection
10164
? formatSelectedDates(startDate as Date, endDate as Date, locale)
10265
: placeholder;
10366
const dropdownText = dropdownValue
@@ -110,7 +73,6 @@ const DateRangePickerButton = ({
11073
makeDateRangePickerClassName("button"),
11174
"flex items-center justify-between",
11275
getColorClassNames("white").bgColor,
113-
getColorClassNames(DEFAULT_COLOR, colorPalette.darkText).textColor,
11476
borderRadius.md.all,
11577
boxShadow.sm,
11678
)}
@@ -123,15 +85,15 @@ const DateRangePickerButton = ({
12385
className={twMerge(
12486
makeDateRangePickerClassName("calendarButton"),
12587
"flex items-center w-full truncate focus:outline-none focus:ring-2",
88+
getSelectButtonColors(hasDateSelection, disabled),
12689
enableDropdown ? border.none.right : twMerge(borderRadius.md.right, border.sm.right),
127-
getColorClassNames(DEFAULT_COLOR, colorPalette.ring).borderColor,
12890
getColorClassNames(BaseColors.Blue, colorPalette.lightRing).focusRingColor,
129-
getColorClassNames(DEFAULT_COLOR, colorPalette.canvasBackground).hoverBgColor,
13091
spacing.twoXl.paddingX,
13192
spacing.sm.paddingY,
13293
borderRadius.md.left,
13394
border.sm.all,
13495
)}
96+
disabled={disabled}
13597
>
13698
<CalendarIcon
13799
className={twMerge(
@@ -151,9 +113,6 @@ const DateRangePickerButton = ({
151113
"whitespace-nowrap truncate",
152114
fontSize.sm,
153115
fontWeight.md,
154-
hasSelection
155-
? getColorClassNames(DEFAULT_COLOR, colorPalette.darkText).textColor
156-
: getColorClassNames(DEFAULT_COLOR, colorPalette.text).textColor,
157116
)}
158117
>
159118
{calendarText}
@@ -167,26 +126,23 @@ const DateRangePickerButton = ({
167126
className={twMerge(
168127
makeDateRangePickerClassName("dropdownButton"),
169128
"inline-flex justify-between w-48 truncate focus:outline-none focus:ring-2",
170-
getColorClassNames(DEFAULT_COLOR, colorPalette.ring).borderColor,
129+
getSelectButtonColors(hasDropdownSelection, disabled),
171130
getColorClassNames(BaseColors.Blue, colorPalette.lightRing).focusRingColor,
172-
getColorClassNames(DEFAULT_COLOR, colorPalette.canvasBackground).hoverBgColor,
173131
spacing.twoXl.paddingX,
174132
spacing.sm.paddingY,
175133
spacing.px.negativeMarginLeft,
176134
borderRadius.md.right,
177135
border.sm.all,
178136
)}
179137
onKeyDown={onDropdownKeyDown}
138+
disabled={disabled}
180139
>
181140
<p
182141
className={twMerge(
183142
makeDateRangePickerClassName("dropdownButtonText"),
184143
"whitespace-nowrap truncate",
185144
fontSize.sm,
186145
fontWeight.md,
187-
dropdownValue
188-
? getColorClassNames(DEFAULT_COLOR, colorPalette.darkText).textColor
189-
: getColorClassNames(DEFAULT_COLOR, colorPalette.text).textColor,
190146
)}
191147
>
192148
{dropdownText}

src/components/input-elements/DateRangePicker/dateRangePickerUtils.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,49 @@ const getDayHoverBgColorClassName = (
325325
}
326326
return "hover:bg-gray-200";
327327
};
328+
329+
export const formatSelectedDates = (
330+
startDate: Date | null,
331+
endDate: Date | null,
332+
locale?: Locale,
333+
) => {
334+
const localeCode = locale?.code || "en-US";
335+
if (!startDate && !endDate) {
336+
return "";
337+
} else if (startDate && !endDate) {
338+
const options: Intl.DateTimeFormatOptions = {
339+
year: "numeric",
340+
month: "short",
341+
day: "numeric",
342+
};
343+
return startDate.toLocaleDateString(localeCode, options);
344+
} else if (startDate && endDate) {
345+
if (isEqual(startDate, endDate)) {
346+
const options: Intl.DateTimeFormatOptions = {
347+
year: "numeric",
348+
month: "short",
349+
day: "numeric",
350+
};
351+
return startDate.toLocaleDateString(localeCode, options);
352+
} else if (
353+
startDate.getMonth() === endDate.getMonth() &&
354+
startDate.getFullYear() === endDate.getFullYear()
355+
) {
356+
const optionsStartDate: Intl.DateTimeFormatOptions = {
357+
month: "short",
358+
day: "numeric",
359+
};
360+
return `${startDate.toLocaleDateString(localeCode, optionsStartDate)} -
361+
${endDate.getDate()}, ${endDate.getFullYear()}`;
362+
} else {
363+
const options: Intl.DateTimeFormatOptions = {
364+
year: "numeric",
365+
month: "short",
366+
day: "numeric",
367+
};
368+
return `${startDate.toLocaleDateString(localeCode, options)} -
369+
${endDate.toLocaleDateString(localeCode, options)}`;
370+
}
371+
}
372+
return "";
373+
};

src/components/input-elements/Dropdown/Dropdown.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
border,
1313
borderRadius,
1414
boxShadow,
15-
constructValueToNameMapping,
1615
fontSize,
1716
fontWeight,
1817
getColorClassNames,
@@ -21,6 +20,7 @@ import {
2120
sizing,
2221
spacing,
2322
} from "lib";
23+
import { constructValueToNameMapping, getSelectButtonColors, hasValue } from "../selectUtils";
2424
import { DropdownItemProps } from "./DropdownItem";
2525
import Modal from "components/util-elements/Modal";
2626
import { DEFAULT_COLOR, colorPalette } from "lib/theme";
@@ -32,6 +32,7 @@ export interface DropdownProps extends React.HTMLAttributes<HTMLDivElement> {
3232
defaultValue?: string;
3333
onValueChange?: (value: string) => void;
3434
placeholder?: string;
35+
disabled?: boolean;
3536
icon?: React.JSXElementConstructor<any>;
3637
children: React.ReactElement[] | React.ReactElement;
3738
}
@@ -42,6 +43,7 @@ const Dropdown = React.forwardRef<HTMLDivElement, DropdownProps>((props, ref) =>
4243
value,
4344
onValueChange,
4445
placeholder = "Select...",
46+
disabled = false,
4547
icon,
4648
children,
4749
className,
@@ -73,6 +75,8 @@ const Dropdown = React.forwardRef<HTMLDivElement, DropdownProps>((props, ref) =>
7375
selectedValue,
7476
);
7577

78+
const hasSelection = hasValue(selectedValue);
79+
7680
return (
7781
<div
7882
ref={mergeRefs([dropdownRef, ref])}
@@ -85,18 +89,17 @@ const Dropdown = React.forwardRef<HTMLDivElement, DropdownProps>((props, ref) =>
8589
className={twMerge(
8690
makeDropdownClassName("button"),
8791
"flex justify-between items-center w-full focus:outline-none focus:ring-2",
88-
getColorClassNames("white").bgColor,
89-
getColorClassNames(DEFAULT_COLOR, colorPalette.canvasBackground).hoverBgColor,
92+
getSelectButtonColors(hasSelection, disabled),
93+
getColorClassNames(BaseColors.Blue, colorPalette.lightRing).focusRingColor,
9094
Icon ? spacing.xl.paddingLeft : spacing.twoXl.paddingLeft,
9195
spacing.twoXl.paddingRight,
9296
spacing.sm.paddingY,
9397
borderRadius.md.all,
9498
border.sm.all,
9599
boxShadow.sm,
96-
getColorClassNames(DEFAULT_COLOR, colorPalette.ring).borderColor,
97-
getColorClassNames(BaseColors.Blue, colorPalette.lightRing).focusRingColor,
98100
)}
99101
onClick={() => setIsFocused(!isFocused)}
102+
disabled={disabled}
100103
>
101104
<div className="flex justify-start items-center truncate">
102105
{Icon ? (
@@ -118,9 +121,6 @@ const Dropdown = React.forwardRef<HTMLDivElement, DropdownProps>((props, ref) =>
118121
"whitespace-nowrap truncate",
119122
fontSize.sm,
120123
fontWeight.md,
121-
selectedValue
122-
? getColorClassNames(DEFAULT_COLOR, colorPalette.darkText).textColor
123-
: getColorClassNames(DEFAULT_COLOR, colorPalette.text).textColor,
124124
)}
125125
>
126126
{selectedValue ? valueToNameMapping.get(selectedValue) : placeholder}

src/components/input-elements/MultiSelectBox/MultiSelectBox.tsx

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ import {
1414
fontSize,
1515
fontWeight,
1616
getColorClassNames,
17-
getFilteredOptions,
1817
isValueInArray,
1918
makeClassName,
2019
mergeRefs,
2120
removeValueFromArray,
2221
sizing,
2322
spacing,
2423
} from "lib";
24+
import { getFilteredOptions, getSelectButtonColors } from "../selectUtils";
2525
import Modal from "components/util-elements/Modal";
2626
import { MultiSelectBoxItemProps } from "./MultiSelectBoxItem";
2727
import { DEFAULT_COLOR, colorPalette } from "lib/theme";
@@ -33,6 +33,7 @@ export interface MultiSelectBoxProps extends React.HTMLAttributes<HTMLDivElement
3333
value?: string[];
3434
onValueChange?: (value: string[]) => void;
3535
placeholder?: string;
36+
disabled?: boolean;
3637
icon?: React.ElementType | React.JSXElementConstructor<any>;
3738
children: React.ReactElement[] | React.ReactElement;
3839
}
@@ -43,6 +44,7 @@ const MultiSelectBox = React.forwardRef<HTMLDivElement, MultiSelectBoxProps>((pr
4344
value,
4445
onValueChange,
4546
placeholder = "Select...",
47+
disabled = false,
4648
icon,
4749
children,
4850
className,
@@ -58,8 +60,8 @@ const MultiSelectBox = React.forwardRef<HTMLDivElement, MultiSelectBoxProps>((pr
5860
const [searchQuery, setSearchQuery] = useState("");
5961

6062
const selectedItems = selectedValue ?? [];
61-
const displayText = selectedItems.length !== 0 ? `${selectedItems.length} Selected` : placeholder;
62-
const showResetButton = selectedItems.length > 0;
63+
const hasSelection = selectedItems.length > 0;
64+
const displayText = hasSelection ? `${selectedItems.length} Selected` : placeholder;
6365

6466
const options = React.Children.map(children, (child: { props: MultiSelectBoxItemProps }) => ({
6567
...child.props,
@@ -115,9 +117,7 @@ const MultiSelectBox = React.forwardRef<HTMLDivElement, MultiSelectBoxProps>((pr
115117
className={twMerge(
116118
makeMultiSelectBoxClassName("button"),
117119
"flex justify-between items-center w-full focus:outline-none focus:ring-2",
118-
getColorClassNames("white").bgColor,
119-
getColorClassNames(DEFAULT_COLOR, colorPalette.canvasBackground).hoverBgColor,
120-
getColorClassNames(DEFAULT_COLOR, colorPalette.ring).borderColor,
120+
getSelectButtonColors(hasSelection, disabled),
121121
getColorClassNames("blue", colorPalette.lightRing).focusRingColor,
122122
borderRadius.md.all,
123123
border.sm.all,
@@ -127,6 +127,7 @@ const MultiSelectBox = React.forwardRef<HTMLDivElement, MultiSelectBoxProps>((pr
127127
spacing.sm.paddingY,
128128
)}
129129
onClick={() => handleModalToggle(!showModal)}
130+
disabled={disabled}
130131
>
131132
<div className="flex justify-start items-center truncate">
132133
{Icon ? (
@@ -148,16 +149,13 @@ const MultiSelectBox = React.forwardRef<HTMLDivElement, MultiSelectBoxProps>((pr
148149
"whitespace-nowrap truncate",
149150
fontSize.sm,
150151
fontWeight.md,
151-
selectedItems.length !== 0
152-
? getColorClassNames(DEFAULT_COLOR, colorPalette.darkText).textColor
153-
: getColorClassNames(DEFAULT_COLOR, colorPalette.text).textColor,
154152
)}
155153
>
156154
{displayText}
157155
</p>
158156
</div>
159157
<div className="flex items-center">
160-
{showResetButton ? (
158+
{hasSelection && !disabled ? (
161159
<div
162160
role="button"
163161
className={twMerge(

0 commit comments

Comments
 (0)