diff --git a/apps/web/package.json b/apps/web/package.json index 306f934d05..6f3fea6f6d 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -38,7 +38,7 @@ "@calcom/tsconfig": "*", "@calcom/ui": "*", "@daily-co/daily-js": "^0.26.0", - "@formkit/auto-animate": "^1.0.0-beta.1", + "@formkit/auto-animate": "^1.0.0-beta.5", "@glidejs/glide": "^3.5.2", "@heroicons/react": "^1.0.6", "@hookform/error-message": "^2.0.0", diff --git a/apps/web/pages/apps/index.tsx b/apps/web/pages/apps/index.tsx index 51382a5b1a..ffe4a16fa0 100644 --- a/apps/web/pages/apps/index.tsx +++ b/apps/web/pages/apps/index.tsx @@ -1,21 +1,55 @@ +import { useAutoAnimate } from "@formkit/auto-animate/react"; import { InferGetStaticPropsType, NextPageContext } from "next"; +import { ChangeEventHandler, useState } from "react"; import { getAppRegistry, getAppRegistryWithCredentials } from "@calcom/app-store/_appRegistry"; +import { classNames } from "@calcom/lib"; import { getSession } from "@calcom/lib/auth"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { AppCategories } from "@calcom/prisma/client"; -import { AllApps, AppsLayout, AppStoreCategories, TrendingAppsSlider } from "@calcom/ui"; +import { AllApps, AppsLayout, AppStoreCategories, Icon, TextField, TrendingAppsSlider } from "@calcom/ui"; import { ssgInit } from "@server/lib/ssg"; +function AppsSearch({ + onChange, + className, +}: { + onChange: ChangeEventHandler; + className?: string; +}) { + return ( + } + addOnClassname="!border-gray-100" + containerClassName={classNames("focus:!ring-offset-0", className)} + type="search" + autoComplete="false" + onChange={onChange} + /> + ); +} + export default function Apps({ appStore, categories }: InferGetStaticPropsType) { const { t } = useLocale(); + const [searchText, setSearchText] = useState(undefined); return ( - - - - + ( + setSearchText(e.target.value)} /> + )}> + {!searchText && ( + <> + + + + )} + ); } diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index b2ff6557fd..22f1860fe7 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -52,6 +52,7 @@ "still_waiting_for_approval": "An event is still waiting for approval", "event_is_still_waiting": "Event request is still waiting: {{attendeeName}} - {{date}} - {{eventType}}", "no_more_results": "No more results", + "no_results": "No results", "load_more_results": "Load more results", "integration_meeting_id": "{{integrationName}} meeting ID: {{meetingId}}", "confirmed_event_type_subject": "Confirmed: {{eventType}} with {{name}} at {{date}}", diff --git a/apps/web/styles/globals.css b/apps/web/styles/globals.css index 772b4abfdd..96f970be69 100644 --- a/apps/web/styles/globals.css +++ b/apps/web/styles/globals.css @@ -499,4 +499,8 @@ hr { .h-screen { height: -webkit-fill-available; } +} + +::-webkit-search-cancel-button { + -webkit-appearance: none; } \ No newline at end of file diff --git a/packages/features/ee/teams/components/CreateANewTeamForm.tsx b/packages/features/ee/teams/components/CreateANewTeamForm.tsx index 66b05ee030..a3479de4ae 100644 --- a/packages/features/ee/teams/components/CreateANewTeamForm.tsx +++ b/packages/features/ee/teams/components/CreateANewTeamForm.tsx @@ -63,7 +63,7 @@ export const CreateANewTeamForm = () => { className="mt-2" name="name" label={t("team_name")} - value={value} + defaultValue={value} onChange={(e) => { newTeamFormMethods.setValue("name", e?.target.value); if (newTeamFormMethods.formState.touchedFields["slug"] === undefined) { @@ -91,7 +91,7 @@ export const CreateANewTeamForm = () => { "http://", "" )}/`} - value={value} + defaultValue={value} onChange={(e) => { newTeamFormMethods.setValue("slug", slugify(e?.target.value), { shouldTouch: true, diff --git a/packages/ui/components/form/inputs/Input.tsx b/packages/ui/components/form/inputs/Input.tsx index d5df01896b..04f56aff67 100644 --- a/packages/ui/components/form/inputs/Input.tsx +++ b/packages/ui/components/form/inputs/Input.tsx @@ -6,7 +6,7 @@ import classNames from "@calcom/lib/classNames"; import { getErrorFromUnknown } from "@calcom/lib/errors"; import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { Alert, showToast, Skeleton, Tooltip, UnstyledSelect } from "../../.."; +import { Alert, showToast, Icon, Skeleton, Tooltip, UnstyledSelect } from "../../.."; import { HintsOrErrors } from "./HintOrErrors"; import { Label } from "./Label"; @@ -44,9 +44,8 @@ type InputFieldProps = { addOnLeading?: ReactNode; addOnSuffix?: ReactNode; inputIsFullWidth?: boolean; - /**@Default paddingX 12px */ - addOnPadding?: number; addOnFilled?: boolean; + addOnClassname?: string; error?: string; labelSrOnly?: boolean; containerClassName?: string; @@ -61,13 +60,15 @@ type AddonProps = { isFilled?: boolean; className?: string; error?: boolean; - paddingX?: number; }; -const Addon = ({ isFilled, children, className, error, paddingX = 12 }: AddonProps) => ( +const Addon = ({ isFilled, children, className, error }: AddonProps) => (
+ className={classNames( + "addon-wrapper h-9 border border-gray-300 px-3", + isFilled && "bg-gray-100", + className + )}>
{children}
@@ -88,9 +89,10 @@ export const InputField = forwardRef(function addOnLeading, addOnSuffix, addOnFilled = true, - addOnPadding, + addOnClassname, inputIsFullWidth, hint, + type, hintErrors, labelSrOnly, containerClassName, @@ -99,6 +101,8 @@ export const InputField = forwardRef(function ...passThrough } = props; + const [inputValue, setInputValue] = useState(""); + return (
{!!name && ( @@ -114,28 +118,45 @@ export const InputField = forwardRef(function {addOnLeading || addOnSuffix ? (
{addOnLeading && ( - + {addOnLeading} )} { + setInputValue(e.target.value); + props.onChange && props.onChange(e); + }, + value: inputValue, + })} isFullWidth={inputIsFullWidth} className={classNames( className, addOnLeading && "rounded-l-none", addOnSuffix && "rounded-r-none", + type === "search" && "pr-8", "!my-0 !ring-0" )} - {...passThrough} ref={ref} /> {addOnSuffix && ( - + {addOnSuffix} )} + {type === "search" && inputValue?.toString().length > 0 && ( + { + setInputValue(""); + props.onChange && props.onChange(e as unknown as React.ChangeEvent); + }} + /> + )}
) : ( } /> ); diff --git a/packages/ui/package.json b/packages/ui/package.json index a5c1632915..857821b0be 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -15,7 +15,7 @@ "dependencies": { "@calcom/lib": "*", "@calcom/trpc": "*", - "@formkit/auto-animate": "^1.0.0-beta.1", + "@formkit/auto-animate": "^1.0.0-beta.5", "@radix-ui/react-dialog": "^1.0.0", "@radix-ui/react-portal": "^1.0.0", "@radix-ui/react-select": "^0.1.1", diff --git a/packages/ui/v2/core/Shell.tsx b/packages/ui/v2/core/Shell.tsx index 2267e94ce2..1e82d9a6eb 100644 --- a/packages/ui/v2/core/Shell.tsx +++ b/packages/ui/v2/core/Shell.tsx @@ -183,6 +183,8 @@ type LayoutProps = { withoutMain?: boolean; // Gives you the option to skip HeadSEO and render your own. withoutSeo?: boolean; + // Gives the ability to include actions to the right of the heading + actions?: JSX.Element; }; const CustomBrandingContainer = () => { @@ -840,6 +842,7 @@ export function ShellMain(props: LayoutProps) { {props.CTA}
)} + {props.actions && props.actions} )}
diff --git a/packages/ui/v2/core/apps/AllApps.tsx b/packages/ui/v2/core/apps/AllApps.tsx index 8da15525b2..cb63fb5765 100644 --- a/packages/ui/v2/core/apps/AllApps.tsx +++ b/packages/ui/v2/core/apps/AllApps.tsx @@ -36,14 +36,15 @@ export function useShouldShowArrows() { return { ref, calculateScroll, leftVisible: showArrowScroll.left, rightVisible: showArrowScroll.right }; } -type AllAppsPropsType = { apps: (App & { credentials: Credential[] | undefined })[] }; +type AllAppsPropsType = { apps: (App & { credentials: Credential[] | undefined })[]; searchText?: string }; interface CategoryTabProps { selectedCategory: string | null; categories: string[]; + searchText?: string; } -function CategoryTab({ selectedCategory, categories }: CategoryTabProps) { +function CategoryTab({ selectedCategory, categories, searchText }: CategoryTabProps) { const { t } = useLocale(); const router = useRouter(); const { ref, calculateScroll, leftVisible, rightVisible } = useShouldShowArrows(); @@ -60,12 +61,14 @@ function CategoryTab({ selectedCategory, categories }: CategoryTabProps) { }; return (
-

- {t("explore_apps", { - category: - (selectedCategory && selectedCategory[0].toUpperCase() + selectedCategory.slice(1)) || - t("all_apps"), - })} +

+ {searchText + ? t("search") + : t("explore_apps", { + category: + (selectedCategory && selectedCategory[0].toUpperCase() + selectedCategory.slice(1)) || + t("all_apps"), + })}

{leftVisible && (