Fix timezone select - create two variants (#7875)

* Fix timezone select - create two variants

* Remove menu is open

* Timezone fixes

---------

Co-authored-by: Efraín Rochín <roae.85@gmail.com>
This commit is contained in:
sean-brydon 2023-03-27 03:19:13 +08:00 committed by GitHub
parent 8dd9b8d74b
commit 04c634ec4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 118 deletions

View File

@ -1,12 +1,9 @@
import type { FC } from "react";
import { useEffect, useState } from "react";
import useTheme from "@calcom/lib/hooks/useTheme";
import type { ITimezoneOption } from "@calcom/ui";
import { TimezoneSelect } from "@calcom/ui";
import useMeQuery from "@lib/hooks/useMeQuery";
import { timeZone } from "../../lib/clock";
type Props = {
@ -15,8 +12,6 @@ type Props = {
const TimeOptions: FC<Props> = ({ onSelectTimeZone }) => {
const [selectedTimeZone, setSelectedTimeZone] = useState("");
const query = useMeQuery();
const userTheme = useTheme(query?.data?.theme).resolvedTheme;
useEffect(() => {
setSelectedTimeZone(timeZone());
@ -28,59 +23,16 @@ const TimeOptions: FC<Props> = ({ onSelectTimeZone }) => {
}
}, [selectedTimeZone, onSelectTimeZone]);
const customStyles = {
option: (_provided: object, state: { isSelected: boolean; isFocused: boolean }) => ({
padding: "10px 12px !important",
color: state.isSelected || state.isFocused ? "#101010" : "#374151",
backgroundColor: state.isSelected ? "#E5E7EB !important" : "white",
...(userTheme === "dark" && {
color: state.isSelected || state.isFocused ? "white" : "#80868B",
}),
}),
control: () => ({
display: "flex",
cursor: "pointer",
backgroundColor: "transparent !important",
minWidth: "5rem",
height: "24px",
minHeight: "24px !important",
boxShadow: "none !important",
}),
singleValue: (provided: object, state: { selectProps: { menuIsOpen: boolean } }) => ({
...provided,
color: state.selectProps.menuIsOpen ? "#111827" : "#4B5563",
...(userTheme === "dark" && {
color: "#a5a5a5 !important",
}),
}),
menu: (provided: object) => ({
...provided,
minWidth: "20rem",
margin: "8px 0 0 -20px",
}),
valueContainer: (provided: object) => ({
...provided,
padding: "0 0 0 6px",
}),
dropdownIndicator: (provided: object, state: { selectProps: { menuIsOpen: boolean } }) => ({
...provided,
transform: state.selectProps.menuIsOpen ? "rotate(180deg)" : "",
color: state.selectProps.menuIsOpen ? "#111827" : "#4B5563",
marginLeft: 4,
padding: 0,
...(userTheme === "dark" && {
color: "#80868B",
}),
}),
};
return !!selectedTimeZone ? (
<TimezoneSelect
id="timeZone"
classNames={{
singleValue: () => "dark:text-darkgray-600 text-gray-600",
menu: () => "!w-64 max-w-[90vw]",
}}
variant="minimal"
value={selectedTimeZone}
onChange={(tz: ITimezoneOption) => setSelectedTimeZone(tz.value)}
className="flex h-6 text-sm font-medium"
styles={customStyles}
/>
) : null;
};

View File

@ -17,8 +17,8 @@ export function TimezoneDropdown({
return (
<>
<div className="dark:focus-within:bg-darkgray-200 dark:bg-darkgray-100 dark:hover:bg-darkgray-200 -mx-[2px] !mt-3 flex w-fit max-w-[20rem] items-center rounded-[4px] px-1 py-[2px] text-sm font-medium focus-within:bg-gray-200 hover:bg-gray-100 lg:max-w-[12rem] [&_p]:focus-within:text-gray-900 dark:[&_p]:focus-within:text-white [&_svg]:focus-within:text-gray-900 dark:[&_svg]:focus-within:text-white">
<FiGlobe className="dark:text-darkgray-600 flex h-4 w-4 text-gray-600 ltr:mr-[2px] rtl:ml-[2px]" />
<div className="dark:focus-within:bg-darkgray-200 dark:bg-darkgray-100 dark:hover:bg-darkgray-200 !mt-3 flex w-full max-w-[20rem] items-center rounded-[4px] px-1 text-sm font-medium focus-within:bg-gray-200 hover:bg-gray-100 lg:max-w-[12rem] [&_p]:focus-within:text-gray-900 dark:[&_p]:focus-within:text-white [&_svg]:focus-within:text-gray-900 dark:[&_svg]:focus-within:text-white">
<FiGlobe className="dark:text-darkgray-600 flex h-4 w-4 text-gray-600 ltr:mr-2 rtl:ml-2" />
<TimeOptions onSelectTimeZone={handleSelectTimeZone} />
</div>
</>

View File

@ -13,7 +13,12 @@ export interface ICity {
timezone: string;
}
export function TimezoneSelect({ className, components, ...props }: SelectProps) {
export function TimezoneSelect({
className,
components,
variant = "default",
...props
}: SelectProps & { variant?: "default" | "minimal" }) {
const [cities, setCities] = useState<ICity[]>([]);
const { data, isLoading } = trpc.viewer.public.cityTimezones.useQuery(undefined, {
trpc: { context: { skipBatch: true } },
@ -44,7 +49,8 @@ export function TimezoneSelect({ className, components, ...props }: SelectProps)
formatOptionLabel={(option) => <p className="truncate">{(option as ITimezoneOption).value}</p>}
getOptionLabel={(option) => handleOptionLabel(option as ITimezoneOption, cities)}
classNames={{
input: () => classNames("dark:text-darkgray-900 text-gray-900", props.classNames?.input),
input: (state) =>
classNames("dark:text-darkgray-900 text-gray-900", props.classNames?.input?.(state)),
option: (state) =>
classNames(
"dark:bg-darkgray-100 flex cursor-pointer justify-between py-2.5 px-3 rounded-none text-gray-700 dark:text-darkgray-700",
@ -55,28 +61,35 @@ export function TimezoneSelect({ className, components, ...props }: SelectProps)
placeholder: (state) =>
classNames("text-gray-400 text-sm dark:text-darkgray-400", state.isFocused && "hidden"),
dropdownIndicator: () => "text-gray-600 dark:text-darkgray-400",
control: () => classNames("", props.classNames?.control), // We remove all styling here to fit theme of booking page - no min-h also
singleValue: () =>
control: (state) =>
classNames(
variant === "default"
? "dark:bg-darkgray-100 dark:border-darkgray-300 !min-h-9 border-gray-300 bg-white text-sm leading-4 placeholder:text-sm placeholder:font-normal focus-within:ring-2 focus-within:ring-gray-800 hover:border-gray-400 dark:focus-within:ring-darkgray-900 rounded-md border py-2 px-3"
: "text-sm ",
props.classNames?.control?.(state)
), // We remove all styling here to fit theme of booking page - no min-h also
singleValue: (state) =>
classNames(
"dark:text-darkgray-900 dark:placeholder:text-darkgray-500 text-black placeholder:text-gray-400",
props.classNames?.singleValue
props.classNames?.singleValue?.(state)
),
valueContainer: () =>
valueContainer: (state) =>
classNames(
"dark:text-darkgray-900 dark:placeholder:text-darkgray-500 text-black placeholder:text-gray-400 flex gap-1",
props.classNames?.valueContainer
props.classNames?.valueContainer?.(state)
),
multiValue: () =>
multiValue: (state) =>
classNames(
"dark:bg-darkgray-200 dark:text-darkgray-700 rounded-md bg-gray-100 text-gray-700 py-1.5 px-2 flex items-center text-sm leading-none",
props.classNames?.multiValue
props.classNames?.multiValue?.(state)
),
menu: () =>
menu: (state) =>
classNames(
"dark:bg-darkgray-100 rounded-md bg-white text-sm leading-4 dark:text-white mt-1 border border-gray-200 dark:border-darkgray-200 ",
props.classNames?.menu
props.classNames?.menu?.(state)
),
menuList: () => classNames("scroll-bar scrollbar-track-w-20 rounded-md", props.classNames?.menuList),
menuList: (state) =>
classNames("scroll-bar scrollbar-track-w-20 rounded-md", props.classNames?.menuList?.(state)),
indicatorsContainer: (state) =>
classNames(
state.selectProps.menuIsOpen

View File

@ -1,51 +0,0 @@
import classNames from "classnames";
import { components } from "react-select";
import type { ITimezone, ITimezoneOption, Props as SelectProps } from "react-timezone-select";
import BaseSelect, { allTimezones } from "react-timezone-select";
import { InputComponent } from "../components/form/select/components";
function TimezoneSelect({ className, ...props }: SelectProps) {
// @TODO: remove borderRadius and haveRoundedClassName logic from theme so we use only new style
const haveRoundedClassName = !!(className && className.indexOf("rounded-") > -1);
const defaultBorderRadius = 2;
return (
<BaseSelect
theme={(theme) => ({
...theme,
...(haveRoundedClassName ? {} : { borderRadius: defaultBorderRadius }),
colors: {
...theme.colors,
primary: "var(--brand-color)",
primary50: "rgba(209 , 213, 219, var(--tw-bg-opacity))",
primary25: "rgba(244, 245, 246, var(--tw-bg-opacity))",
},
})}
styles={{
option: (provided, state) => ({
...provided,
color: state.isSelected ? "var(--brand-text-color)" : "black",
":active": {
backgroundColor: state.isSelected ? "" : "var(--brand-color)",
color: "var(--brand-text-color)",
},
}),
}}
timezones={{
...allTimezones,
"America/Asuncion": "Asuncion",
}}
components={{
...components,
IndicatorSeparator: () => null,
Input: InputComponent,
}}
className={classNames("text-sm", className)}
{...props}
/>
);
}
export default TimezoneSelect;
export type { ITimezone, ITimezoneOption };