a ton of mobile improvements to save space (#4336)

* made /booking more responsive friendly

* hiding headline and description on mobile, moving CTA to bottom right fixed on mobile

* more padding on full screen mode on iPhone

* nit fixes to wipemycal

* nit fixes to wipemycal

* lint fix

* Update apps/web/styles/globals.css

Massive nit, lol.

Co-authored-by: Alex van Andel <me@alexvanandel.com>
This commit is contained in:
Peer Richelsen
2022-09-09 15:02:31 +00:00
committed by GitHub
co-authored by Alex van Andel
parent 770c35039d
commit 5cd2ce9246
14 changed files with 73 additions and 66 deletions
+17 -25
View File
@@ -13,6 +13,7 @@ import { Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader } from "
import { Icon } from "@calcom/ui/Icon";
import { Tooltip } from "@calcom/ui/Tooltip";
import { TextArea } from "@calcom/ui/form/fields";
import Badge from "@calcom/ui/v2/core/Badge";
import Button from "@calcom/ui/v2/core/Button";
import useMeQuery from "@lib/hooks/useMeQuery";
@@ -261,7 +262,7 @@ function BookingListItem(booking: BookingItemProps) {
</Dialog>
<tr className="flex hover:bg-neutral-50">
<td className="hidden align-top ltr:pl-6 rtl:pr-6 sm:table-cell sm:w-44" onClick={onClick}>
<td className="hidden align-top ltr:pl-6 rtl:pr-6 sm:table-cell sm:w-28" onClick={onClick}>
<div className="cursor-pointer py-4">
<div className="text-sm leading-6 text-gray-900">{startTime}</div>
<div className="text-sm text-gray-500">
@@ -304,17 +305,21 @@ function BookingListItem(booking: BookingItemProps) {
</td>
<td className={"flex-1 px-4" + (isRejected ? " line-through" : "")} onClick={onClick}>
<div className="cursor-pointer py-4">
<div className="sm:hidden">
{isPending && <Tag className="mb-2 ltr:mr-2 rtl:ml-2">{t("unconfirmed")}</Tag>}
{!!booking?.eventType?.price && !booking.paid && (
<Tag className="mb-2 ltr:mr-2 rtl:ml-2">Pending payment</Tag>
)}
<div className="text-sm font-medium text-gray-900">
{startTime}:{" "}
<small className="text-sm text-gray-500">
{dayjs(booking.startTime).format("HH:mm")} - {dayjs(booking.endTime).format("HH:mm")}
</small>
</div>
{isPending && (
<Badge variant="orange" className="mb-2 ltr:mr-2 rtl:ml-2">
{t("unconfirmed")}
</Badge>
)}
{!!booking?.eventType?.price && !booking.paid && (
<Badge variant="orange" className="mb-2 ltr:mr-2 rtl:ml-2">
{t("pending_payment")}
</Badge>
)}
<div className="text-sm font-medium text-gray-900">
{startTime}:{" "}
<small className="text-sm text-gray-500">
{dayjs(booking.startTime).format("HH:mm")} - {dayjs(booking.endTime).format("HH:mm")}
</small>
</div>
<div
title={booking.title}
@@ -324,10 +329,6 @@ function BookingListItem(booking: BookingItemProps) {
)}>
{booking.eventType?.team && <strong>{booking.eventType.team.name}: </strong>}
{booking.title}
{!!booking?.eventType?.price && !booking.paid && (
<Tag className="hidden ltr:ml-2 rtl:mr-2 sm:inline-flex">Pending payment</Tag>
)}
{isPending && <Tag className="hidden ltr:ml-2 rtl:mr-2 sm:inline-flex">{t("unconfirmed")}</Tag>}
</div>
{booking.description && (
<div
@@ -372,13 +373,4 @@ function BookingListItem(booking: BookingItemProps) {
);
}
const Tag = ({ children, className = "" }: React.PropsWithChildren<{ className?: string }>) => {
return (
<span
className={`inline-flex items-center rounded-sm bg-yellow-100 px-1.5 py-0.5 text-xs font-medium text-yellow-800 ${className}`}>
{children}
</span>
);
};
export default BookingListItem;
+1 -1
View File
@@ -38,7 +38,7 @@ const DropdownActions = ({
<Dropdown>
{!actionTrigger ? (
<DropdownMenuTrigger asChild>
<Button type="button" color="minimal" size="icon" StartIcon={Icon.FiMoreHorizontal} />
<Button type="button" color="secondary" size="icon" StartIcon={Icon.FiMoreHorizontal} />
</DropdownMenuTrigger>
) : (
<DropdownMenuTrigger asChild>{actionTrigger}</DropdownMenuTrigger>
+1 -1
View File
@@ -7,7 +7,7 @@ export default function MorePage() {
const { t } = useLocale();
return (
<Shell>
<div className="max-w-screen-lg">
<div className="mt-8 max-w-screen-lg">
<MobileNavigationMoreItems />
<div className="mt-6">
<UserV2OptInBanner />
+1 -1
View File
@@ -40,7 +40,7 @@ export function AvailabilityList({ schedules }: inferQueryOutput<"viewer.availab
/>
</div>
) : (
<div className="-mx-4 mb-16 overflow-hidden rounded-md border border-gray-200 bg-white sm:mx-0">
<div className="mb-16 overflow-hidden rounded-md border border-gray-200 bg-white">
<ul className="divide-y divide-neutral-200" data-testid="schedules">
{schedules.map((schedule) => (
<ScheduleListItem
+1 -1
View File
@@ -87,7 +87,7 @@ export default function Bookings() {
)}
{(query.status === "loading" || query.status === "idle") && <SkeletonLoader />}
{query.status === "success" && !isEmpty && (
<div className="pt-2 xl:mx-6 xl:pt-0">
<div className="pt-2 xl:pt-0">
<WipeMyCalActionButton bookingStatus={status} bookingsEmpty={isEmpty} />
{/* TODO: add today only for the current day
<p className="pb-3 text-xs font-medium uppercase leading-4 text-gray-500">{t("today")}</p>
@@ -1186,5 +1186,6 @@
"routing_forms_description": "You can see all forms and routes you have created here.",
"add_new_form": "Add new form",
"form_description": "Create your form to route a booker",
"copy_link_to_form": "Copy link to form"
"copy_link_to_form": "Copy link to form",
"pending_payment": "Pending payment"
}
+4
View File
@@ -220,6 +220,10 @@ button[role="switch"][data-state="checked"] {
.bottom-nav {
padding-bottom: 24px;
}
.cta {
bottom: 100px;
}
}
/* hide chat bubble on mobile */
@@ -40,7 +40,7 @@ export default function RoutingForms({
/>
) : null}
{forms.length ? (
<div className="-mx-4 mb-16 overflow-hidden bg-white sm:mx-0">
<div className="mb-16 overflow-hidden bg-white">
<List data-testid="routing-forms-list">
{forms.map((form, index) => {
if (!form) {
@@ -7,8 +7,8 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import logger from "@calcom/lib/logger";
import showToast from "@calcom/lib/notification";
import { trpc } from "@calcom/trpc/react";
import Button from "@calcom/ui/Button";
import { Dialog, DialogContent, DialogFooter, DialogHeader } from "@calcom/ui/Dialog";
import Button from "@calcom/ui/v2/core/Button";
interface IConfirmDialogWipe {
isOpenDialog: boolean;
@@ -93,7 +93,7 @@ export const ConfirmDialog = (props: IConfirmDialogWipe) => {
{initialDate.format(dateFormat)} - {endDate.format(dateFormat)}
</strong>
</p>
<p className="mt-6 mb-2 text-sm font-bold text-black">Are you sure? This can&apos;t be undone</p>
<p className="mt-6 mb-2 text-sm">Are you sure? This can&apos;t be undone</p>
</div>
</div>
@@ -103,6 +103,7 @@ export const ConfirmDialog = (props: IConfirmDialogWipe) => {
</Button>
<Button
color="primary"
data-testid="send_request"
disabled={isLoading}
onClick={async () => {
@@ -1,7 +1,7 @@
import { useState } from "react";
import { trpc } from "@calcom/trpc/react";
import Button from "@calcom/ui/Button";
import Button from "@calcom/ui/v2/core/Button";
import { ConfirmDialog } from "./confirmDialog";
@@ -30,7 +30,7 @@ const WipeMyCalActionButton = (props: IWipeMyCalActionButtonProps) => {
{data && isSuccess && !isLoading && credentialId && (
<div className="mb-4">
<ConfirmDialog isOpenDialog={openDialog} setIsOpenDialog={setOpenDialog} />
<Button onClick={() => setOpenDialog(true)} data-testid="wipe-today-button">
<Button color="primary" onClick={() => setOpenDialog(true)} data-testid="wipe-today-button">
Wipe Today
</Button>
</div>
@@ -79,7 +79,7 @@ export default function WorkflowDetailsPage(props: Props) {
return (
<>
<div className="md:flex">
<div className="my-8 sm:my-0 md:flex">
<div className="pl-2 pr-3 md:pl-0">
<div className="mb-5">
<TextField label={`${t("workflow_name")}:`} type="text" {...form.register("name")} />
+1 -1
View File
@@ -33,7 +33,7 @@ export const Badge = function Badge(props: BadgeProps) {
<div
{...passThroughProps}
className={classNames(
"inline-flex items-center justify-center rounded py-0.5 px-[6px] text-sm",
"inline-flex items-center justify-center rounded py-0.5 px-[6px] text-xs",
bold ? "font-semibold" : "font-normal",
!StartIcon ? classNameBySize[size] : "",
badgeClassNameByVariant[variant],
+36 -27
View File
@@ -557,7 +557,7 @@ const MobileNavigation = () => {
<>
<nav
className={classNames(
"bottom-nav fixed bottom-0 z-30 -mx-4 flex w-full border border-t border-gray-200 bg-gray-50 px-1 shadow md:hidden",
"bottom-nav fixed bottom-0 z-30 -mx-4 flex w-full border border-t border-gray-200 bg-gray-50 bg-opacity-40 px-1 shadow backdrop-blur-md md:hidden",
isEmbed && "hidden"
)}>
{mobileNavigationBottomItems.map((item) => (
@@ -721,7 +721,7 @@ export function ShellMain(props: LayoutProps) {
const { isLocaleReady } = useLocale();
return (
<>
<div className="flex items-baseline">
<div className="flex items-baseline sm:mt-0">
{!!props.backPath && (
<Icon.FiArrowLeft
className="mr-3 hover:cursor-pointer"
@@ -735,7 +735,7 @@ export function ShellMain(props: LayoutProps) {
"mb-4 flex w-full items-center pt-4 md:p-0 lg:mb-10"
)}>
{props.HeadingLeftIcon && <div className="ltr:mr-4">{props.HeadingLeftIcon}</div>}
<div className="w-full ltr:mr-4 rtl:ml-4">
<div className="hidden w-full ltr:mr-4 rtl:ml-4 sm:block">
{props.heading && (
<h1 className="font-cal mb-1 text-xl font-bold capitalize tracking-wide text-black">
{!isLocaleReady ? null : props.heading}
@@ -747,11 +747,18 @@ export function ShellMain(props: LayoutProps) {
</p>
)}
</div>
{props.CTA && <div className="mb-4 flex-shrink-0">{props.CTA}</div>}
{props.CTA && (
<div className="cta fixed right-4 bottom-[75px] z-40 mb-4 flex-shrink-0 sm:relative sm:bottom-auto sm:right-auto sm:z-0">
{props.CTA}
</div>
)}
</header>
)}
</div>
<div className={classNames(props.flexChildrenContainer && "flex flex-1 flex-col")}>
{/* add padding to top for mobile when App Bar is fixed */}
<div className="pt-8 sm:hidden" />
{props.children}
</div>
</>
@@ -805,29 +812,31 @@ function TopNav() {
const isEmbed = useIsEmbed();
const { t } = useLocale();
return (
<nav
style={isEmbed ? { display: "none" } : {}}
className="flex items-center justify-between border-b border-gray-200 bg-gray-50 py-1.5 px-4 sm:p-4 md:hidden">
<Link href="/event-types">
<a>
<Logo />
</a>
</Link>
<div className="flex items-center gap-2 self-center">
<span className="group flex items-center rounded-full text-sm font-medium text-gray-700 hover:bg-gray-50 hover:text-neutral-900 lg:hidden">
<KBarTrigger />
</span>
<button className="rounded-full p-1 text-gray-400 hover:bg-gray-50 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2">
<span className="sr-only">{t("settings")}</span>
<Link href="/settings/profile">
<a>
<Icon.FiSettings className="h-4 w-4 text-gray-700" aria-hidden="true" />
</a>
</Link>
</button>
<UserDropdown small />
</div>
</nav>
<>
<nav
style={isEmbed ? { display: "none" } : {}}
className="fixed z-40 flex w-full items-center justify-between border-b border-gray-200 bg-gray-50 bg-opacity-50 py-1.5 px-4 backdrop-blur-lg sm:relative sm:p-4 md:hidden">
<Link href="/event-types">
<a>
<Logo />
</a>
</Link>
<div className="flex items-center gap-2 self-center">
<span className="group flex items-center rounded-full text-sm font-medium text-gray-700 hover:bg-gray-50 hover:text-neutral-900 lg:hidden">
<KBarTrigger />
</span>
<button className="rounded-full p-1 text-gray-400 hover:bg-gray-50 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2">
<span className="sr-only">{t("settings")}</span>
<Link href="/settings/profile">
<a>
<Icon.FiSettings className="h-4 w-4 text-gray-700" aria-hidden="true" />
</a>
</Link>
</button>
<UserDropdown small />
</div>
</nav>
</>
);
}
@@ -43,14 +43,14 @@ export default function BookingLayout({
}: { children: React.ReactNode } & ComponentProps<typeof Shell>) {
return (
<Shell {...rest}>
<div className="flex flex-col xl:flex-row ">
<div className="flex flex-col sm:space-x-2 xl:flex-row">
<div className="hidden xl:block">
<VerticalTabs tabs={tabs} sticky />
</div>
<div className="block xl:hidden">
<HorizontalTabs tabs={tabs} />
</div>
<main className="w-full">{children}</main>
<main className="w-full max-w-6xl">{children}</main>
</div>
</Shell>
);