fix: component styles and sign up / onboarding dark mode (#12581)

* fix divider border for addOnLeading

* fix primary button in dark mode and password input border

* signup dark mode and corner fix

* onboarding dark mode

* fix css var issue and use inline vars for light and dark mode

* Invert google icon on dark mode

* Fix typo

* fix eslint errors with yarn lint:fix

* use css vars on login page as well

* running lint manually

* Fix subtle

* Fix

* Fix

* linting

* linting

* chore: restore main yarn.lock

* fix: lint error

---------

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Sean Brydon <sean@brydon.io>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: sean-brydon <sean@cal.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
This commit is contained in:
Henrik Klee 2023-12-06 22:10:14 +01:00 committed by GitHub
parent 8bed690ed6
commit 55d44ce789
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 56 additions and 85 deletions

View File

@ -156,11 +156,8 @@ const UserProfile = () => {
{t("few_sentences_about_yourself")} {t("few_sentences_about_yourself")}
</p> </p>
</fieldset> </fieldset>
<Button <Button EndIcon={ArrowRight} type="submit" className="mt-8 w-full items-center justify-center">
type="submit"
className="text-inverted mt-8 flex w-full flex-row justify-center rounded-md border border-black bg-black p-2 text-center text-sm">
{t("finish")} {t("finish")}
<ArrowRight className="ml-2 h-4 w-4 self-center" aria-hidden="true" />
</Button> </Button>
</form> </form>
); );

View File

@ -9,7 +9,7 @@ import { FULL_NAME_LENGTH_MAX_LIMIT } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { trpc } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react";
import { Button, TimezoneSelect } from "@calcom/ui"; import { Button, TimezoneSelect, Input } from "@calcom/ui";
import { ArrowRight } from "@calcom/ui/components/icon"; import { ArrowRight } from "@calcom/ui/components/icon";
import { UsernameAvailabilityField } from "@components/ui/UsernameAvailability"; import { UsernameAvailabilityField } from "@components/ui/UsernameAvailability";
@ -76,7 +76,7 @@ const UserSettings = (props: IUserSettingsProps) => {
<label htmlFor="name" className="text-default mb-2 block text-sm font-medium"> <label htmlFor="name" className="text-default mb-2 block text-sm font-medium">
{t("full_name")} {t("full_name")}
</label> </label>
<input <Input
{...register("name", { {...register("name", {
required: true, required: true,
})} })}
@ -85,7 +85,6 @@ const UserSettings = (props: IUserSettingsProps) => {
type="text" type="text"
autoComplete="off" autoComplete="off"
autoCorrect="off" autoCorrect="off"
className="border-default w-full rounded-md border text-sm"
/> />
{errors.name && ( {errors.name && (
<p data-testid="required" className="py-2 text-xs text-red-500"> <p data-testid="required" className="py-2 text-xs text-red-500">
@ -106,7 +105,7 @@ const UserSettings = (props: IUserSettingsProps) => {
className="mt-2 w-full rounded-md text-sm" className="mt-2 w-full rounded-md text-sm"
/> />
<p className="text-subtle dark:text-inverted mt-3 flex flex-row font-sans text-xs leading-tight"> <p className="text-subtle mt-3 flex flex-row font-sans text-xs leading-tight">
{t("current_time")} {dayjs().tz(selectedTimeZone).format("LT").toString().toLowerCase()} {t("current_time")} {dayjs().tz(selectedTimeZone).format("LT").toString().toLowerCase()}
</p> </p>
</div> </div>

View File

@ -5,7 +5,6 @@ import type { GetServerSidePropsContext } from "next";
import { getCsrfToken, signIn } from "next-auth/react"; import { getCsrfToken, signIn } from "next-auth/react";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import type { CSSProperties } from "react";
import { useState } from "react"; import { useState } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { FaGoogle } from "react-icons/fa"; import { FaGoogle } from "react-icons/fa";
@ -174,15 +173,7 @@ inferSSRProps<typeof _getServerSideProps> & WithNonceProps<{}>) {
: isSAMLLoginEnabled && !isLoading && data?.connectionExists; : isSAMLLoginEnabled && !isLoading && data?.connectionExists;
return ( return (
<div <div className="dark:bg-brand dark:text-brand-contrast text-emphasis min-h-screen [--cal-brand-emphasis:#101010] [--cal-brand-subtle:9CA3AF] [--cal-brand-text:white] [--cal-brand:#111827] dark:[--cal-brand-emphasis:#e1e1e1] dark:[--cal-brand-text:black] dark:[--cal-brand:white]">
style={
{
"--cal-brand": "#111827",
"--cal-brand-emphasis": "#101010",
"--cal-brand-text": "white",
"--cal-brand-subtle": "#9CA3AF",
} as CSSProperties
}>
<AuthContainer <AuthContainer
title={t("login")} title={t("login")}
description={t("login")} description={t("login")}
@ -238,7 +229,7 @@ inferSSRProps<typeof _getServerSideProps> & WithNonceProps<{}>) {
type="submit" type="submit"
color="primary" color="primary"
disabled={formState.isSubmitting} disabled={formState.isSubmitting}
className="w-full justify-center dark:bg-white dark:text-black"> className="w-full justify-center">
{twoFactorRequired ? t("submit") : t("sign_in")} {twoFactorRequired ? t("submit") : t("sign_in")}
</Button> </Button>
</div> </div>

View File

@ -2,7 +2,6 @@ import type { GetServerSidePropsContext } from "next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import Head from "next/head"; import Head from "next/head";
import { usePathname, useRouter } from "next/navigation"; import { usePathname, useRouter } from "next/navigation";
import type { CSSProperties } from "react";
import { Suspense } from "react"; import { Suspense } from "react";
import { z } from "zod"; import { z } from "zod";
@ -106,16 +105,8 @@ const OnboardingPage = () => {
return ( return (
<div <div
className="dark:bg-brand dark:text-brand-contrast text-emphasis min-h-screen" className="dark:bg-brand dark:text-brand-contrast text-emphasis min-h-screen [--cal-brand-emphasis:#101010] [--cal-brand-subtle:9CA3AF] [--cal-brand:#111827] [--cal-brand-text:#FFFFFF] dark:[--cal-brand-emphasis:#e1e1e1] dark:[--cal-brand:white] dark:[--cal-brand-text:#000000]"
data-testid="onboarding" data-testid="onboarding"
style={
{
"--cal-brand": "#111827",
"--cal-brand-emphasis": "#101010",
"--cal-brand-text": "white",
"--cal-brand-subtle": "#9CA3AF",
} as CSSProperties
}
key={pathname}> key={pathname}>
<Head> <Head>
<title>{`${APP_NAME} - ${t("getting_started")}`}</title> <title>{`${APP_NAME} - ${t("getting_started")}`}</title>
@ -231,7 +222,6 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
}; };
}; };
OnboardingPage.isThemeSupported = false;
OnboardingPage.PageWrapper = PageWrapper; OnboardingPage.PageWrapper = PageWrapper;
export default OnboardingPage; export default OnboardingPage;

View File

@ -4,7 +4,6 @@ import type { GetServerSidePropsContext } from "next";
import { signIn } from "next-auth/react"; import { signIn } from "next-auth/react";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import type { CSSProperties } from "react";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import type { SubmitHandler } from "react-hook-form"; import type { SubmitHandler } from "react-hook-form";
import { useForm, useFormContext } from "react-hook-form"; import { useForm, useFormContext } from "react-hook-form";
@ -238,18 +237,10 @@ export default function Signup({
}; };
return ( return (
<div <div className="light bg-muted 2xl:bg-default flex min-h-screen w-full flex-col items-center justify-center [--cal-brand-emphasis:#101010] [--cal-brand:#111827] [--cal-brand-text:#FFFFFF] [--cal-brand-subtle:#9CA3AF] dark:[--cal-brand-emphasis:#e1e1e1] dark:[--cal-brand:white] dark:[--cal-brand-text:#000000]">
className="light bg-muted 2xl:bg-default flex min-h-screen w-full flex-col items-center justify-center" <div className="bg-muted 2xl:border-subtle grid w-full max-w-[1440px] grid-cols-1 grid-rows-1 overflow-hidden lg:grid-cols-2 2xl:rounded-[20px] 2xl:border 2xl:py-6">
style={
{
"--cal-brand": "#111827",
"--cal-brand-emphasis": "#101010",
"--cal-brand-text": "white",
"--cal-brand-subtle": "#9CA3AF",
} as CSSProperties
}>
<div className="bg-muted 2xl:border-subtle grid w-full max-w-[1440px] grid-cols-1 grid-rows-1 lg:grid-cols-2 2xl:rounded-[20px] 2xl:border 2xl:py-6">
<HeadSeo title={t("sign_up")} description={t("sign_up")} /> <HeadSeo title={t("sign_up")} description={t("sign_up")} />
{/* Left side */}
<div className="flex w-full flex-col px-4 pt-6 sm:px-16 md:px-20 2xl:px-28"> <div className="flex w-full flex-col px-4 pt-6 sm:px-16 md:px-20 2xl:px-28">
{/* Header */} {/* Header */}
{errors.apiError && ( {errors.apiError && (
@ -354,7 +345,10 @@ export default function Signup({
StartIcon={() => ( StartIcon={() => (
<> <>
<img <img
className={classNames("text-subtle mr-2 h-4 w-4", premiumUsername && "opacity-50")} className={classNames(
"text-subtle mr-2 h-4 w-4 dark:invert",
premiumUsername && "opacity-50"
)}
src="/google-icon.svg" src="/google-icon.svg"
alt="" alt=""
/> />
@ -648,5 +642,4 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
}; };
}; };
Signup.isThemeSupported = false;
Signup.PageWrapper = PageWrapper; Signup.PageWrapper = PageWrapper;

View File

@ -5,7 +5,7 @@ import { Toaster } from "react-hot-toast";
import { APP_NAME } from "@calcom/lib/constants"; import { APP_NAME } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Alert, Button, Form, TextField } from "@calcom/ui"; import { Alert, Button, Form, PasswordField, TextField } from "@calcom/ui";
export default function AppleCalendarSetup() { export default function AppleCalendarSetup() {
const { t } = useLocale(); const { t } = useLocale();
@ -20,8 +20,8 @@ export default function AppleCalendarSetup() {
const [errorMessage, setErrorMessage] = useState(""); const [errorMessage, setErrorMessage] = useState("");
return ( return (
<div className="bg-emphasis flex h-screen"> <div className="bg-emphasis flex h-screen dark:bg-inherit">
<div className="bg-default m-auto rounded p-5 md:w-[560px] md:p-10"> <div className="bg-default dark:bg-muted border-subtle m-auto rounded p-5 dark:border md:w-[560px] md:p-10">
<div className="flex flex-col space-y-5 md:flex-row md:space-x-5 md:space-y-0"> <div className="flex flex-col space-y-5 md:flex-row md:space-x-5 md:space-y-0">
<div> <div>
{/* eslint-disable @next/next/no-img-element */} {/* eslint-disable @next/next/no-img-element */}
@ -32,12 +32,14 @@ export default function AppleCalendarSetup() {
/> />
</div> </div>
<div> <div>
<h1 className="text-default">{t("connect_apple_server")}</h1> <h1 className="text-default dark:text-emphasis mb-3 font-semibold">
{t("connect_apple_server")}
</h1>
<div className="mt-1 text-sm"> <div className="mt-1 text-sm">
{t("apple_server_generate_password", { appName: APP_NAME })}{" "} {t("apple_server_generate_password", { appName: APP_NAME })}{" "}
<a <a
className="text-indigo-400" className="font-bold hover:underline"
href="https://appleid.apple.com/account/manage" href="https://appleid.apple.com/account/manage"
target="_blank" target="_blank"
rel="noopener noreferrer"> rel="noopener noreferrer">
@ -45,7 +47,7 @@ export default function AppleCalendarSetup() {
</a> </a>
. {t("credentials_stored_encrypted")} . {t("credentials_stored_encrypted")}
</div> </div>
<div className="my-2 mt-3"> <div className="my-2 mt-4">
<Form <Form
form={form} form={form}
handleSubmit={async (values) => { handleSubmit={async (values) => {
@ -65,7 +67,7 @@ export default function AppleCalendarSetup() {
} }
}}> }}>
<fieldset <fieldset
className="space-y-2" className="space-y-4"
disabled={form.formState.isSubmitting} disabled={form.formState.isSubmitting}
data-testid="apple-calendar-form"> data-testid="apple-calendar-form">
<TextField <TextField
@ -76,9 +78,8 @@ export default function AppleCalendarSetup() {
placeholder="appleid@domain.com" placeholder="appleid@domain.com"
data-testid="apple-calendar-email" data-testid="apple-calendar-email"
/> />
<TextField <PasswordField
required required
type="password"
{...form.register("password")} {...form.register("password")}
label={t("password")} label={t("password")}
placeholder="•••••••••••••" placeholder="•••••••••••••"

View File

@ -50,7 +50,7 @@ export const buttonClasses = cva(
primary: primary:
"bg-brand-default hover:bg-brand-emphasis focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset focus-visible:ring-brand-default text-brand disabled:bg-brand-subtle disabled:text-brand-subtle disabled:opacity-40 disabled:hover:bg-brand-subtle disabled:hover:text-brand-default disabled:hover:opacity-40", "bg-brand-default hover:bg-brand-emphasis focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset focus-visible:ring-brand-default text-brand disabled:bg-brand-subtle disabled:text-brand-subtle disabled:opacity-40 disabled:hover:bg-brand-subtle disabled:hover:text-brand-default disabled:hover:opacity-40",
secondary: secondary:
"text-emphasis border border-default bg-default hover:bg-muted hover:border-emphasis focus-visible:bg-subtle focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset focus-visible:ring-empthasis disabled:border-subtle disabled:bg-opacity-30 disabled:text-muted disabled:hover:bg-opacity-30 disabled:hover:text-muted disabled:hover:border-subtle disabled:hover:bg-default", "text-emphasis border border-default bg-default hover:bg-muted hover:border-emphasis focus-visible:bg-subtle focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset focus-visible:ring-empthasis disabled:border-subtle disabled:bg-opacity-30 disabled:text-muted disabled:hover:bg-opacity-30 disabled:hover:text-muted disabled:hover:border-subtle disabled:hover:bg-default",
minimal: minimal:
"text-emphasis hover:bg-subtle focus-visible:bg-subtle focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset focus-visible:ring-empthasis disabled:border-subtle disabled:bg-opacity-30 disabled:text-muted disabled:hover:bg-transparent disabled:hover:text-muted disabled:hover:border-subtle", "text-emphasis hover:bg-subtle focus-visible:bg-subtle focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset focus-visible:ring-empthasis disabled:border-subtle disabled:bg-opacity-30 disabled:text-muted disabled:hover:bg-transparent disabled:hover:text-muted disabled:hover:border-subtle",
destructive: destructive:

View File

@ -31,35 +31,33 @@ export const PasswordField = forwardRef<HTMLInputElement, InputFieldProps>(funct
const textLabel = isPasswordVisible ? t("hide_password") : t("show_password"); const textLabel = isPasswordVisible ? t("hide_password") : t("show_password");
return ( return (
<div className="[&_.group:hover_.addon-wrapper]:border-emphasis relative [&_.group:focus-within_.addon-wrapper]:border-neutral-300"> <InputField
<InputField type={isPasswordVisible ? "text" : "password"}
type={isPasswordVisible ? "text" : "password"} placeholder={props.placeholder || "•••••••••••••"}
placeholder={props.placeholder || "•••••••••••••"} ref={ref}
ref={ref} {...props}
{...props} className={classNames(
className={classNames( "addon-wrapper mb-0 ltr:border-r-0 ltr:pr-10 rtl:border-l-0 rtl:pl-10",
"addon-wrapper mb-0 ltr:border-r-0 ltr:pr-10 rtl:border-l-0 rtl:pl-10", props.className
props.className )}
)} addOnFilled={false}
addOnFilled={false} addOnSuffix={
addOnSuffix={ <Tooltip content={textLabel}>
<Tooltip content={textLabel}> <button
<button className="text-emphasis h-9"
className="text-emphasis h-9" tabIndex={-1}
tabIndex={-1} type="button"
type="button" onClick={() => toggleIsPasswordVisible()}>
onClick={() => toggleIsPasswordVisible()}> {isPasswordVisible ? (
{isPasswordVisible ? ( <EyeOff className="h-4 stroke-[2.5px]" />
<EyeOff className="h-4 stroke-[2.5px]" /> ) : (
) : ( <Eye className="h-4 stroke-[2.5px]" />
<Eye className="h-4 stroke-[2.5px]" /> )}
)} <span className="sr-only">{textLabel}</span>
<span className="sr-only">{textLabel}</span> </button>
</button> </Tooltip>
</Tooltip> }
} />
/>
</div>
); );
}); });

View File

@ -107,7 +107,9 @@ export const InputField = forwardRef<HTMLInputElement, InputFieldProps>(function
dir="ltr" dir="ltr"
className="focus-within:ring-brand-default group relative mb-1 flex items-center rounded-md focus-within:outline-none focus-within:ring-2"> className="focus-within:ring-brand-default group relative mb-1 flex items-center rounded-md focus-within:outline-none focus-within:ring-2">
{addOnLeading && ( {addOnLeading && (
<Addon isFilled={addOnFilled} className={classNames("rounded-l-md border-r-0", addOnClassname)}> <Addon
isFilled={addOnFilled}
className={classNames("ltr:rounded-l-md rtl:rounded-r-md", addOnClassname)}>
{addOnLeading} {addOnLeading}
</Addon> </Addon>
)} )}

View File

@ -42,7 +42,7 @@ const Switch = (
{LockedIcon && <div className="mr-2">{LockedIcon}</div>} {LockedIcon && <div className="mr-2">{LockedIcon}</div>}
<PrimitiveSwitch.Root <PrimitiveSwitch.Root
className={cx( className={cx(
isChecked ? "bg-brand-default" : "bg-emphasis", isChecked ? "bg-brand-default dark:bg-emphasis" : "bg-emphasis",
primitiveProps.disabled && "cursor-not-allowed", primitiveProps.disabled && "cursor-not-allowed",
"focus:ring-brand-default h-5 w-[34px] rounded-full shadow-none focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-neutral-800 focus:ring-offset-1", "focus:ring-brand-default h-5 w-[34px] rounded-full shadow-none focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-neutral-800 focus:ring-offset-1",
props.className props.className