[WEB-4488] feat: brand revamp (#7544)

* chore: empty state asset and theme improvement (#7542)

* chore: empty state asset and theme improvement

* chore: upgrade modal improvement and code refactor

* feat: onboarding revamp and theme changes (#7541)

* refactor: consolidate password strength indicator into shared UI package

* chore: remove old password strength meter implementations

* chore: update package dependencies for password strength refactor

* chore: code refactor

* chore: brand logo added

* chore:  terms and conditions refactor

* chore: auth form refactor

* chore: oauth enhancements and refactor

* chore: plane new logos added

* chore: auth input form field added to ui package

* chore: password input component added

* chore: web auth refactor

* chore: update brand colors and remove onboarding-specific styles

* chore: clean up unused assets

* chore: profile menu text overflow

* chore: theme related changes

* chore: logo spinner updated

* chore: onboarding constant and types updated

* chore: theme changes and code refactor

* feat: onboarding flow revamp

* fix:  build error and code refactoring

* chore: code refactor

* fix: build error

* chore: consent option added to onboarding and code refactor

* fix: build fix

* chore: code refactor

* chore: auth screen revamp and code refactor

* chore: onboarding enhancements

* chore: code refactor

* chore: onboarding logic improvement

* chore: code refactor

* fix: onboarding pre release improvements

* chore: color token updated

* chore: color token updated

* chore: auth screen line height and size improvements

* chore: input height updated

* chore: n-progress theme updated

* chore: theme and logo enhancements

* chore: space auth and code refactor

* chore: update new brand empty states (#7543)

* [WEB-4585]chore: branding updates (#7540)

* chore: updated logo, og image, and loaders

* chore: updated branding colors

* chore: tour modal logo

* chore: updated logo spinner size

* chore: updated email templates logos and colors

* chore: code refactor

* fix: removed conditional hook render

* fix: space app loader

---------

Co-authored-by: Vamsi Krishna <46787868+vamsikrishnamathala@users.noreply.github.com>
Co-authored-by: vamsikrishnamathala <matalav55@gmail.com>
This commit is contained in:
Anmol Singh Bhatia 2025-08-06 22:24:47 +05:30 committed by GitHub
parent 6450793d72
commit 51e146f8ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
345 changed files with 5158 additions and 2515 deletions

View file

@ -0,0 +1,77 @@
import React, { useState } from "react";
import { cn } from "@plane/utils";
import { AuthInput } from "./auth-input";
export interface AuthConfirmPasswordInputProps
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "autoComplete"> {
password: string;
label?: string;
error?: string;
showPasswordToggle?: boolean;
containerClassName?: string;
labelClassName?: string;
errorClassName?: string;
autoComplete?: "on" | "off";
onPasswordMatchChange?: (matches: boolean) => void;
}
export const AuthConfirmPasswordInput: React.FC<AuthConfirmPasswordInputProps> = ({
password,
label = "Confirm Password",
error,
showPasswordToggle = true,
containerClassName = "",
errorClassName = "",
className = "",
value = "",
onChange,
onPasswordMatchChange,
...props
}) => {
const [isFocused, setIsFocused] = useState(false);
const confirmPassword = value as string;
const passwordsMatch = password === confirmPassword && password.length > 0;
const showMatchError =
confirmPassword.length > 0 && !passwordsMatch && (!isFocused || confirmPassword.length >= password.length);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newConfirmPassword = e.target.value;
onChange?.(e);
onPasswordMatchChange?.(password === newConfirmPassword && password.length > 0);
};
const handleFocus = () => {
setIsFocused(true);
};
const handleBlur = () => {
setIsFocused(false);
};
const getError = () => {
if (error) return error;
if (showMatchError) return "Passwords don't match";
return "";
};
return (
<div className={cn("space-y-2", containerClassName)}>
<AuthInput
{...props}
type="password"
label={label}
error={getError()}
showPasswordToggle={showPasswordToggle}
errorClassName={errorClassName}
className={className}
value={value}
onChange={handleChange}
onFocus={handleFocus}
onBlur={handleBlur}
autoComplete="on"
/>
{confirmPassword && passwordsMatch && <p className="text-sm text-green-500">Passwords match</p>}
</div>
);
};

View file

@ -0,0 +1,41 @@
import React from "react";
import { cn } from "../../helpers";
export interface AuthForgotPasswordProps {
onForgotPassword?: () => void;
className?: string;
text?: string;
disabled?: boolean;
}
export const AuthForgotPassword: React.FC<AuthForgotPasswordProps> = ({
onForgotPassword,
className = "",
text = "Forgot your password?",
disabled = false,
}) => {
const handleClick = (e: React.MouseEvent) => {
e.preventDefault();
if (!disabled && onForgotPassword) {
onForgotPassword();
}
};
return (
<button
type="button"
onClick={handleClick}
disabled={disabled}
className={cn(
"text-sm text-custom-primary-100 hover:text-custom-primary-200 transition-colors duration-200",
{
"opacity-50 cursor-not-allowed": disabled,
"cursor-pointer": !disabled,
},
className
)}
>
{text}
</button>
);
};

View file

@ -0,0 +1,207 @@
import React, { useState, useMemo } from "react";
import { E_PASSWORD_STRENGTH } from "@plane/constants";
import { cn } from "../../helpers";
import { Button } from "../button/button";
import { Spinner } from "../spinners/circular-spinner";
import { AuthConfirmPasswordInput } from "./auth-confirm-password-input";
import { AuthForgotPassword } from "./auth-forgot-password";
import { AuthInput } from "./auth-input";
import { AuthPasswordInput } from "./auth-password-input";
export type AuthMode = "sign-in" | "sign-up";
export interface AuthFormData {
email: string;
password: string;
confirmPassword?: string;
}
export interface AuthFormProps {
mode: AuthMode;
initialData?: Partial<AuthFormData>;
onSubmit?: (data: AuthFormData) => void;
onForgotPassword?: () => void;
onModeChange?: (mode: AuthMode) => void;
loading?: boolean;
disabled?: boolean;
className?: string;
showForgotPassword?: boolean;
showPasswordStrength?: boolean;
emailError?: string;
passwordError?: string;
confirmPasswordError?: string;
submitButtonText?: string;
alternateModeText?: string;
alternateModeButtonText?: string;
}
export const AuthForm: React.FC<AuthFormProps> = ({
mode,
initialData = {},
onSubmit,
onForgotPassword,
onModeChange,
loading = false,
disabled = false,
className = "",
showForgotPassword = true,
showPasswordStrength = true,
emailError,
passwordError,
confirmPasswordError,
submitButtonText,
alternateModeText,
alternateModeButtonText,
}) => {
const [formData, setFormData] = useState<AuthFormData>({
email: initialData.email || "",
password: initialData.password || "",
confirmPassword: initialData.confirmPassword || "",
});
const [passwordStrength, setPasswordStrength] = useState<E_PASSWORD_STRENGTH>(E_PASSWORD_STRENGTH.EMPTY);
const [passwordsMatch, setPasswordsMatch] = useState(false);
const handleInputChange = (field: keyof AuthFormData) => (e: React.ChangeEvent<HTMLInputElement>) => {
setFormData((prev) => ({
...prev,
[field]: e.target.value,
}));
};
const handlePasswordChange = (password: string) => {
setFormData((prev) => ({
...prev,
password,
}));
};
const handlePasswordStrengthChange = (strength: E_PASSWORD_STRENGTH) => {
setPasswordStrength(strength);
};
const handleConfirmPasswordChange = (matches: boolean) => {
setPasswordsMatch(matches);
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (onSubmit && isFormValid) {
onSubmit(formData);
}
};
const handleModeChange = () => {
const newMode = mode === "sign-in" ? "sign-up" : "sign-in";
onModeChange?.(newMode);
};
const isFormValid = useMemo(() => {
const hasEmail = formData.email.length > 0;
const hasPassword = formData.password.length > 0;
if (mode === "sign-in") {
return hasEmail && hasPassword && !loading && !disabled;
} else {
const isPasswordStrong = passwordStrength === E_PASSWORD_STRENGTH.STRENGTH_VALID;
const passwordsMatch = formData.password === formData.confirmPassword && formData.password.length > 0;
return hasEmail && hasPassword && isPasswordStrong && passwordsMatch && !loading && !disabled;
}
}, [mode, formData, passwordStrength, loading, disabled]);
const getSubmitButtonText = () => {
if (submitButtonText) return submitButtonText;
return mode === "sign-in" ? "Sign In" : "Create Account";
};
const getAlternateModeText = () => {
if (alternateModeText) return alternateModeText;
return mode === "sign-in" ? "Don't have an account?" : "Already have an account?";
};
const getAlternateModeButtonText = () => {
if (alternateModeButtonText) return alternateModeButtonText;
return mode === "sign-in" ? "Sign Up" : "Sign In";
};
return (
<form onSubmit={handleSubmit} className={cn("space-y-4", className)}>
{/* Email Input */}
<AuthInput
id="email"
name="email"
type="email"
label="Email"
value={formData.email}
onChange={handleInputChange("email")}
placeholder="name@company.com"
error={emailError}
disabled={disabled}
// autoComplete="email"
required
/>
{/* Password Input */}
<AuthPasswordInput
id="password"
name="password"
label={mode === "sign-in" ? "Password" : "Set a password"}
value={formData.password}
onChange={handleInputChange("password")}
onPasswordChange={handlePasswordChange}
onPasswordStrengthChange={handlePasswordStrengthChange}
placeholder="Enter password"
error={passwordError}
showPasswordStrength={showPasswordStrength && mode === "sign-up"}
disabled={disabled}
// autoComplete={mode === "sign-in" ? "current-password" : "new-password"}
required
/>
{/* Confirm Password Input (Sign Up Only) */}
{mode === "sign-up" && (
<AuthConfirmPasswordInput
id="confirmPassword"
name="confirmPassword"
password={formData.password}
value={formData.confirmPassword}
onChange={handleInputChange("confirmPassword")}
onPasswordMatchChange={handleConfirmPasswordChange}
error={confirmPasswordError}
disabled={disabled}
// autoComplete="new-password"
required
/>
)}
{/* Forgot Password Link (Sign In Only) */}
{mode === "sign-in" && showForgotPassword && (
<div className="flex justify-end">
<AuthForgotPassword onForgotPassword={onForgotPassword} disabled={disabled} />
</div>
)}
{/* Submit Button */}
<div className="space-y-2.5">
<Button type="submit" variant="primary" className="w-full" size="lg" disabled={!isFormValid} loading={loading}>
{loading ? <Spinner height="20px" width="20px" /> : getSubmitButtonText()}
</Button>
{/* Alternate Mode Button */}
{onModeChange && (
<div className="text-center">
<span className="text-sm text-custom-text-300">{getAlternateModeText()}</span>
<button
type="button"
onClick={handleModeChange}
className="ml-1 text-sm text-custom-primary-100 hover:text-custom-primary-200 transition-colors duration-200"
disabled={disabled}
>
{getAlternateModeButtonText()}
</button>
</div>
)}
</div>
</form>
);
};

View file

@ -0,0 +1,66 @@
import { Eye, EyeOff } from "lucide-react";
import React, { useState } from "react";
import { cn } from "../../helpers";
import { Input } from "../form-fields/input";
export interface AuthInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "autoComplete"> {
label?: string;
error?: string;
showPasswordToggle?: boolean;
errorClassName?: string;
autoComplete?: "on" | "off";
}
const baseContainerClassName = "flex flex-col gap-1.5";
export const AuthInput: React.FC<AuthInputProps> = ({
label,
error,
showPasswordToggle = false,
errorClassName = "",
className = "",
type = "text",
...props
}) => {
const { id } = props;
const [showPassword, setShowPassword] = useState(false);
const isPasswordType = type === "password";
const inputType = isPasswordType && showPasswordToggle && showPassword ? "text" : type;
return (
<div className={cn(baseContainerClassName)}>
{label && (
<label htmlFor={id} className={cn("text-sm font-semibold text-custom-text-300")}>
{label}
</label>
)}
<div
className={cn("relative flex items-center rounded-md border border-custom-border-300 py-2 px-3 transition-all")}
>
<Input
{...props}
type={inputType}
className={cn(
"rounded-md disable-autofill-style h-6 w-full placeholder:text-base placeholder:text-custom-text-400 p-0 border-none",
{
"border-red-500": error,
},
className
)}
/>
{showPasswordToggle && isPasswordType && (
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer"
>
{showPassword ? <EyeOff className="h-5 w-5" /> : <Eye className="h-5 w-5" />}
</button>
)}
</div>
{error && <p className={cn("text-sm text-red-500", errorClassName)}>{error}</p>}
</div>
);
};

View file

@ -0,0 +1,77 @@
import React, { useState } from "react";
import { E_PASSWORD_STRENGTH } from "@plane/constants";
import { cn, getPasswordStrength } from "@plane/utils";
import { PasswordStrengthIndicator } from "../form-fields/password/indicator";
import { AuthInput } from "./auth-input";
export interface AuthPasswordInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "autoComplete"> {
label?: string;
error?: string;
showPasswordStrength?: boolean;
showPasswordToggle?: boolean;
containerClassName?: string;
errorClassName?: string;
autoComplete?: "on" | "off";
onPasswordChange?: (password: string) => void;
onPasswordStrengthChange?: (strength: E_PASSWORD_STRENGTH) => void;
}
export const AuthPasswordInput: React.FC<AuthPasswordInputProps> = ({
label = "Password",
error,
showPasswordStrength = true,
showPasswordToggle = true,
containerClassName = "",
errorClassName = "",
className = "",
value = "",
onChange,
onPasswordChange,
onPasswordStrengthChange,
...props
}) => {
const [isFocused, setIsFocused] = useState(false);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newPassword = e.target.value;
onChange?.(e);
onPasswordChange?.(newPassword);
};
const handleFocus = () => {
setIsFocused(true);
};
const handleBlur = () => {
setIsFocused(false);
};
const passwordStrength = getPasswordStrength(value as string);
// Notify parent of strength change
React.useEffect(() => {
onPasswordStrengthChange?.(passwordStrength);
}, [passwordStrength, onPasswordStrengthChange]);
return (
<div className={cn("space-y-2", containerClassName)}>
<AuthInput
{...props}
type="password"
label={label}
error={error}
showPasswordToggle={showPasswordToggle}
errorClassName={errorClassName}
className={className}
value={value}
onChange={handleChange}
onFocus={handleFocus}
onBlur={handleBlur}
autoComplete="on"
/>
{showPasswordStrength && value && isFocused && (
<PasswordStrengthIndicator password={value as string} showCriteria />
)}
</div>
);
};

View file

@ -0,0 +1,11 @@
export { AuthForm } from "./auth-form";
export { AuthInput } from "./auth-input";
export { AuthPasswordInput } from "./auth-password-input";
export { AuthConfirmPasswordInput } from "./auth-confirm-password-input";
export { AuthForgotPassword } from "./auth-forgot-password";
export type { AuthFormProps, AuthFormData, AuthMode } from "./auth-form";
export type { AuthInputProps } from "./auth-input";
export type { AuthPasswordInputProps } from "./auth-password-input";
export type { AuthConfirmPasswordInputProps } from "./auth-confirm-password-input";
export type { AuthForgotPasswordProps } from "./auth-forgot-password";

View file

@ -156,7 +156,7 @@ export const Avatar: React.FC<Props> = (props) => {
className
)}
style={{
backgroundColor: fallbackBackgroundColor ?? "rgba(var(--color-primary-500))",
backgroundColor: fallbackBackgroundColor ?? "#028375",
color: fallbackTextColor ?? "#ffffff",
}}
>

View file

@ -2,4 +2,5 @@ export * from "./input";
export * from "./textarea";
export * from "./input-color-picker";
export * from "./checkbox";
export * from "./root";
export * from "./password";

View file

@ -49,7 +49,7 @@ export const getStrengthInfo = (strength: E_PASSWORD_STRENGTH): StrengthInfo =>
*/
export const getFragmentColor = (fragmentIndex: number, activeFragments: number): string => {
if (fragmentIndex >= activeFragments) {
return "bg-custom-background-90";
return "bg-custom-background-80";
}
switch (activeFragments) {
@ -60,6 +60,6 @@ export const getFragmentColor = (fragmentIndex: number, activeFragments: number)
case 3:
return "bg-green-500";
default:
return "bg-custom-background-90";
return "bg-custom-background-80";
}
};

View file

@ -1,2 +1,3 @@
export * from "./indicator";
export * from "./helper";
export * from "./password-input";

View file

@ -0,0 +1,69 @@
import { Eye, EyeClosed } from "lucide-react";
import React, { useState } from "react";
import { cn } from "@plane/utils";
import { Tooltip } from "../../tooltip";
interface PasswordInputProps {
id: string;
value: string;
onChange: (value: string) => void;
placeholder?: string;
className?: string;
showToggle?: boolean;
error?: boolean;
}
export const PasswordInput: React.FC<PasswordInputProps> = ({
id,
value,
onChange,
placeholder = "Enter your password",
className,
showToggle = true,
error = false,
}) => {
const [showPassword, setShowPassword] = useState(false);
return (
<div className="relative">
<input
id={id}
type={showPassword ? "text" : "password"}
value={value}
onChange={(e) => onChange(e.target.value)}
className={cn(
"w-full px-3 py-2 pr-10 text-custom-text-200 border rounded-md bg-custom-background-100 focus:outline-none focus:ring-2 focus:ring-custom-primary-100 placeholder:text-custom-text-400 focus:border-transparent transition-all duration-200",
{
"border-custom-border-300": !error,
"border-red-500": error,
},
className
)}
placeholder={placeholder}
/>
{showToggle && (
<Tooltip tooltipContent={showPassword ? "Hide password" : "Show password"} position="top">
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute inset-y-0 right-0 pr-3 flex items-center text-custom-text-200 hover:text-custom-text-100 transition-colors duration-200"
>
<div className="relative w-4 h-4">
<Eye
className={cn(
"absolute inset-0 h-4 w-4 transition-all duration-300 ease-in-out",
showPassword ? "opacity-0 scale-75 rotate-12" : "opacity-100 scale-100 rotate-0"
)}
/>
<EyeClosed
className={cn(
"absolute inset-0 h-4 w-4 transition-all duration-300 ease-in-out",
showPassword ? "opacity-100 scale-100 rotate-0" : "opacity-0 scale-75 -rotate-12"
)}
/>
</div>
</button>
</Tooltip>
)}
</div>
);
};

View file

@ -0,0 +1,56 @@
import React from "react";
import { cn } from "@plane/utils";
// Reusable Label Component
interface LabelProps {
htmlFor: string;
children: React.ReactNode;
className?: string;
}
export const Label: React.FC<LabelProps> = ({ htmlFor, children, className }) => (
<label htmlFor={htmlFor} className={cn("block text-sm font-medium text-custom-text-100", className)}>
{children}
</label>
);
// Reusable Form Field Component
interface FormFieldProps {
label: string;
htmlFor: string;
children: React.ReactNode;
className?: string;
optional?: boolean;
}
export const FormField: React.FC<FormFieldProps> = ({ label, htmlFor, children, className, optional = false }) => (
<div className={cn("flex flex-col gap-1.5", className)}>
<Label htmlFor={htmlFor}>
{label}
{optional && <span className="text-custom-text-400 text-sm"> (optional)</span>}
</Label>
{children}
</div>
);
// Reusable Validation Message Component
interface ValidationMessageProps {
type: "error" | "success";
message: string;
className?: string;
}
export const ValidationMessage: React.FC<ValidationMessageProps> = ({ type, message, className }) => (
<p
className={cn(
"text-sm",
{
"text-red-500": type === "error",
"text-green-500": type === "success",
},
className
)}
>
{message}
</p>
);

View file

@ -0,0 +1,28 @@
import * as React from "react";
import { ISvgIcons } from "../type";
export const AccentureLogo: React.FC<ISvgIcons> = ({
width = "51",
height = "16",
className,
color = "currentColor",
}) => (
<svg
width={width}
height={height}
viewBox="0 0 51 16"
fill={color}
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M29.73 2.48282V1L34.5913 2.96305V4.16785L29.73 6.13932V4.6228L32.5693 3.56966L29.73 2.48282Z"
fill="#A100FF"
/>
<path
d="M2.87038 13.9915C1.84251 13.9915 1 13.4776 1 12.3318V12.2728C1 10.8827 2.20479 10.4024 3.68762 10.4024H4.37848V10.1328C4.37848 9.55992 4.13415 9.22291 3.53597 9.22291C2.98833 9.22291 2.71873 9.52622 2.69345 9.94747H1.18535C1.3033 8.67528 2.3059 8.0771 3.62864 8.0771C4.95139 8.0771 5.98768 8.65 5.98768 10.0739V13.882H4.44588V13.2164C4.14257 13.6377 3.62864 14 2.8788 14L2.87038 13.9915ZM4.3869 11.9948V11.4471H3.75502C2.97148 11.4471 2.5755 11.6578 2.5755 12.1717V12.2307C2.5755 12.6267 2.81983 12.8963 3.35904 12.8963C3.90667 12.8626 4.3869 12.5677 4.3869 11.9864V11.9948ZM9.57679 13.9915C8.00971 13.9915 6.85547 13.0226 6.85547 11.0933V11.0006C6.85547 9.07126 8.06026 8.0434 9.57679 8.0434C10.8743 8.0434 11.9358 8.70898 12.0538 10.1918H10.5457C10.453 9.64417 10.1497 9.28189 9.61049 9.28189C8.9449 9.28189 8.46467 9.82952 8.46467 10.9416V11.127C8.46467 12.2728 8.88592 12.7867 9.61049 12.7867C10.1581 12.7867 10.5457 12.3908 10.6384 11.7589H12.0875C11.9948 13.09 11.1186 13.9915 9.57679 13.9915ZM15.4997 13.9915C13.9326 13.9915 12.7783 13.0226 12.7783 11.0933V11.0006C12.7783 9.07126 13.9831 8.0434 15.4997 8.0434C16.7971 8.0434 17.8587 8.70898 17.9766 10.1918H16.4685C16.3759 9.64417 16.0726 9.28189 15.5334 9.28189C14.8678 9.28189 14.3875 9.82952 14.3875 10.9416V11.127C14.3875 12.2728 14.8088 12.7867 15.5334 12.7867C16.081 12.7867 16.4685 12.3908 16.5612 11.7589H18.0103C17.9177 13.09 17.0415 13.9915 15.4997 13.9915ZM21.4478 13.9915C19.8133 13.9915 18.7012 13.0226 18.7012 11.1186V11.0006C18.7012 9.09654 19.8807 8.0434 21.4225 8.0434C22.8464 8.0434 24.0175 8.82693 24.0175 10.731V11.4219H20.302C20.361 12.4497 20.8159 12.8457 21.4815 12.8457C22.0881 12.8457 22.4167 12.5171 22.5346 12.1212H24.0175C23.8321 13.1743 22.9306 13.9915 21.4478 13.9915ZM20.3357 10.3687H22.4504C22.4167 9.52622 22.0291 9.16394 21.3972 9.16394C20.917 9.19764 20.4621 9.46724 20.3441 10.3687H20.3357ZM24.9864 8.18662H26.5871V9.02913C26.8567 8.4815 27.4296 8.06025 28.3059 8.06025C29.3337 8.06025 30.0246 8.69213 30.0246 10.057V13.8652H28.4238V10.3013C28.4238 9.63574 28.1542 9.33244 27.5813 9.33244C27.0337 9.33244 26.5871 9.66102 26.5871 10.3856V13.8567H24.9864V8.1782V8.18662ZM32.965 6.4679V8.18662H34.0518V9.36614H32.965V12.0538C32.965 12.475 33.1503 12.6856 33.5379 12.6856C33.7822 12.6856 33.9338 12.6519 34.0855 12.593V13.8315C33.9001 13.8904 33.5716 13.9494 33.1756 13.9494C31.9371 13.9494 31.3642 13.3765 31.3642 12.2307V9.35771H30.6986V8.1782H31.3642V7.12506L32.965 6.45947V6.4679ZM40.0336 13.8652H38.4666V13.0226C38.197 13.5703 37.6493 13.9915 36.8068 13.9915C35.7789 13.9915 35.0207 13.3596 35.0207 12.0285V8.19505H36.6215V11.8178C36.6215 12.4834 36.8911 12.7867 37.4387 12.7867C37.9863 12.7867 38.4329 12.4245 38.4329 11.7336V8.19505H40.0336V13.8736V13.8652ZM41.2047 8.18662H42.8055V9.23976C43.1341 8.4815 43.6817 8.11922 44.5242 8.11922V9.68629C43.4374 9.68629 42.8055 10.0149 42.8055 10.9585V13.8904H41.2047V8.1782V8.18662ZM47.7679 13.9915C46.1334 13.9915 45.0213 13.0226 45.0213 11.1186V11.0006C45.0213 9.09654 46.2008 8.0434 47.7426 8.0434C49.1665 8.0434 50.3376 8.82693 50.3376 10.731V11.4219H46.6558C46.7148 12.4497 47.1697 12.8457 47.8353 12.8457C48.4419 12.8457 48.7705 12.5171 48.8885 12.1212H50.3713C50.127 13.1743 49.2507 13.9915 47.7763 13.9915H47.7679ZM46.6137 10.3687H48.7621C48.7284 9.52622 48.3408 9.16394 47.7089 9.16394C47.2287 9.19764 46.7738 9.46724 46.6221 10.3687H46.6137Z"
fill={color}
/>
</svg>
);

View file

@ -0,0 +1,40 @@
import * as React from "react";
import { ISvgIcons } from "../type";
export const DolbyLogo: React.FC<ISvgIcons> = ({ width = "40", height = "16", className, color = "currentColor" }) => (
<svg
width={width}
height={height}
viewBox="0 0 40 16"
fill={color}
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M11.7241 13.4334H10.643C8.57552 13.4334 6.92627 11.7447 6.92627 9.71672C6.92627 7.6887 8.61498 6 10.643 6H11.7241V13.4255V13.4334Z"
fill={color}
/>
<path
d="M1 6.00806H2.08109C4.14857 6.00806 5.79782 7.69676 5.79782 9.72477C5.79782 11.7528 4.10911 13.4415 2.08109 13.4415H1V6.01595V6.00806Z"
fill={color}
/>
<path d="M26.8042 6.00781V13.4334H27.9247V6.00781H26.8042Z" fill={color} />
<path
d="M23.5051 8.28845C22.0847 8.28845 20.9326 9.44056 20.9326 10.861C20.9326 12.2814 22.0847 13.4335 23.5051 13.4335C24.9255 13.4335 26.0776 12.2814 26.0776 10.861C26.0776 9.44056 24.9255 8.28845 23.5051 8.28845ZM23.5051 12.3997C22.6529 12.4076 21.9506 11.7211 21.9348 10.8688C21.9269 10.0166 22.6134 9.3143 23.4657 9.29852C23.4815 9.29852 23.4893 9.29852 23.5051 9.29852C24.3574 9.29852 25.0518 10.0008 25.0518 10.8452C25.0518 11.6974 24.3574 12.3918 23.5051 12.3918V12.3997Z"
fill={color}
/>
<path
d="M31.4678 8.2964C30.9391 8.2964 30.4261 8.45423 30 8.76198V6.01587H28.8716V13.4414H30V12.9758C31.16 13.7886 32.7619 13.5045 33.5747 12.3367C34.3875 11.1767 34.1034 9.57476 32.9355 8.76198C32.5015 8.46212 31.9886 8.2964 31.4678 8.2964ZM31.4678 12.3998C30.6155 12.3919 29.929 11.6896 29.9369 10.8295C29.9448 9.9851 30.6234 9.30647 31.4678 9.29858C32.32 9.29858 33.0144 10.0009 33.0144 10.8452C33.0144 11.6975 32.32 12.3919 31.4678 12.3919V12.3998Z"
fill={color}
/>
<path
d="M16.6561 6.00781H13.981V13.4255H16.6561C18.6999 13.4255 20.3649 11.7604 20.3649 9.71664C20.3649 7.67284 18.6999 6.00781 16.6561 6.00781ZM16.6561 12.297H15.1015V7.12835H16.6561C18.0765 7.12835 19.2365 8.28835 19.2365 9.71664C19.2365 11.1449 18.0765 12.297 16.6561 12.297Z"
fill={color}
/>
<path
d="M38.1592 8.29634L36.6914 11.5869L35.2237 8.29634H33.9927L36.068 12.9679C36.068 12.9679 35.563 14.1121 35.5551 14.1121C35.421 14.412 35.0659 14.5461 34.766 14.4199L34.6082 14.3488L34.1505 15.3668L34.5372 15.5404C35.271 15.8639 36.1312 15.5404 36.4547 14.7986L39.3665 8.28845H38.1355L38.1592 8.29634Z"
fill={color}
/>
</svg>
);

View file

@ -0,0 +1,7 @@
export * from "./accenture-logo";
export * from "./dolby-logo";
export * from "./sony-logo";
export * from "./zerodha-logo";
export * from "./plane-lockup";
export * from "./plane-logo";
export * from "./plane-wordmark";

View file

@ -0,0 +1,48 @@
import * as React from "react";
import { ISvgIcons } from "../type";
export const PlaneLockup: React.FC<ISvgIcons> = ({
width = "253",
height = "53",
className,
color = "currentColor",
}) => (
<svg
width={width}
height={height}
viewBox="0 0 253 53"
fill={color}
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<g clip-path="url(#clip0_27_76)">
<path
d="M217.077 51.4468H210.972L210.98 31.4317C210.717 27.7545 208.786 25.1545 205.03 24.6199C198.587 23.7006 194.663 27.8828 194.21 34.0258L194.218 51.4468H188.041V20.2543H192.158L194.255 26.8846H194.6C195.825 22.8701 198.684 20.4831 202.898 19.5757C210.126 18.0231 216.643 22.2724 217.079 29.8239V51.4468H217.077Z"
fill={color}
/>
<path
d="M163.812 19.7315C158.03 20.9566 153.67 25.2354 153.222 31.264H159.395C159.669 28.3484 161.561 25.9969 164.267 24.9553C167.418 23.7401 172.805 23.8881 175.178 26.6005C176.774 28.4253 177.305 31.5816 175.212 33.2249C172.675 35.2173 166.39 34.6117 163.214 34.7636C158.631 34.9826 154.141 36.8429 153.183 41.7727C151.1 52.5042 165.035 54.9267 171.902 49.8963C174.095 48.2885 175.672 45.8443 176.261 43.1792H176.577L178.788 51.4508H182.61V29.964C182.517 20.3214 171.462 18.108 163.81 19.7315H163.812ZM174.847 41.2637C172.484 45.649 166.958 49.0441 162.218 47.3318C158.44 45.9686 158.268 40.4095 161.973 38.9181C165.613 37.4524 173.732 38.9694 176.368 34.949C176.275 37.0855 175.906 39.2989 174.849 41.2637H174.847Z"
fill={color}
/>
<path
d="M113.082 35.5652V51.4475H106.611V9.00063H124.863C125.007 8.99274 125.141 9.06178 125.283 9.06967C133.732 9.53129 139.297 13.601 139.104 22.6025C138.928 30.7991 132.663 35.2199 124.934 35.5671H113.082V35.5652ZM113.082 14.4828V30.2941H124.088C129.595 29.8956 133.071 27.1022 132.491 21.265C131.967 15.9781 127.802 14.6544 123.107 14.4788C119.795 14.3546 116.402 14.5795 113.082 14.4808V14.4828Z"
fill={color}
/>
<path d="M148.647 9H142.529V51.4468H148.647V9Z" fill={color} />
<path
d="M245.872 42.418C244.911 44.4953 243.138 46.1603 240.934 46.8981C238.368 47.7562 234.479 47.5431 232.083 46.2569C228.67 44.4263 227.145 40.6485 227.137 36.8984H251.891C252.194 33.6908 251.902 30.3648 250.496 27.4333C247.083 20.3177 238.859 17.7236 231.513 19.9429C222.868 22.5568 220.165 31.4162 221.462 39.6543C222.86 48.5611 230.197 52.976 238.958 52.3585C244.884 51.9423 250.271 48.1192 251.788 42.4161H245.874L245.872 42.418ZM227.208 32.4381C227.778 26.2457 233.347 23.2018 239.163 24.4269C243.361 25.3107 245.75 28.9523 245.842 33.1068H227.145C227.145 33.1068 227.19 32.6255 227.208 32.4401V32.4381Z"
fill={color}
/>
<path
d="M44.3223 2.9264C44.3223 0.754665 46.6083 -0.65811 48.5508 0.313121L80.4551 16.2653C82.9294 17.5024 84.4922 20.0321 84.4922 22.7985V48.2487C84.4922 50.4204 82.2071 51.833 80.2646 50.8619L62.3281 41.8932V22.7975C62.3281 20.0311 60.7653 17.5015 58.291 16.2643L44.3223 9.27992V2.9264ZM0 2.92543C8.01645e-05 0.753753 2.28609 -0.659069 4.22852 0.312144L22.1582 9.27699V28.3766C22.1582 31.1428 23.7213 33.6716 26.1953 34.9088L40.1699 41.8952V48.2487C40.1697 50.4202 37.8847 51.832 35.9424 50.861L4.03711 34.9088C1.56305 33.6716 0 31.1428 0 28.3766V2.92543ZM22.1582 2.92543C22.1583 0.753753 24.4443 -0.659069 26.3867 0.312144L44.3223 9.27992V28.3776C44.3223 31.1439 45.8861 33.6727 48.3604 34.9098L62.3281 41.8932V48.2487C62.3279 50.4202 60.0429 51.832 58.1006 50.861L40.1699 41.8952V22.7975C40.1699 20.0311 38.6071 17.5015 36.1328 16.2643L22.1582 9.27699V2.92543Z"
fill={color}
/>
</g>
<defs>
<clipPath id="clip0_27_76">
<rect width="252" height="53" fill="white" />
</clipPath>
</defs>
</svg>
);

View file

@ -0,0 +1,19 @@
import * as React from "react";
import { ISvgIcons } from "../type";
export const PlaneLogo: React.FC<ISvgIcons> = ({ width = "85", height = "52", className, color = "currentColor" }) => (
<svg
width={width}
height={height}
viewBox="0 0 85 52"
fill={color}
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M44.3223 2.9264C44.3223 0.754665 46.6083 -0.65811 48.5508 0.313121L80.4551 16.2653C82.9294 17.5024 84.4922 20.0321 84.4922 22.7985V48.2487C84.4922 50.4204 82.2071 51.833 80.2646 50.8619L62.3281 41.8932V22.7975C62.3281 20.0311 60.7653 17.5015 58.291 16.2643L44.3223 9.27992V2.9264ZM0 2.92543C8.01645e-05 0.753753 2.28609 -0.659069 4.22852 0.312144L22.1582 9.27699V28.3766C22.1582 31.1428 23.7213 33.6716 26.1953 34.9088L40.1699 41.8952V48.2487C40.1697 50.4202 37.8847 51.832 35.9424 50.861L4.03711 34.9088C1.56305 33.6716 0 31.1428 0 28.3766V2.92543ZM22.1582 2.92543C22.1583 0.753753 24.4443 -0.659069 26.3867 0.312144L44.3223 9.27992V28.3776C44.3223 31.1439 45.8861 33.6727 48.3604 34.9098L62.3281 41.8932V48.2487C62.3279 50.4202 60.0429 51.832 58.1006 50.861L40.1699 41.8952V22.7975C40.1699 20.0311 38.6071 17.5015 36.1328 16.2643L22.1582 9.27699V2.92543Z"
fill={color}
/>
</svg>
);

View file

@ -0,0 +1,37 @@
import * as React from "react";
import { ISvgIcons } from "../type";
export const PlaneWordmark: React.FC<ISvgIcons> = ({
width = "146",
height = "44",
className,
color = "currentColor",
}) => (
<svg
width={width}
height={height}
viewBox="0 0 146 44"
fill={color}
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M111.077 42.4468H104.972L104.98 22.4317C104.717 18.7545 102.786 16.1545 99.03 15.6199C92.587 14.7006 88.663 18.8828 88.21 25.0258L88.218 42.4468H82.041V11.2543H86.158L88.255 17.8846H88.6C89.825 13.8701 92.684 11.4831 96.898 10.5757C104.126 9.0231 110.643 13.2724 111.079 20.8239V42.4468H111.077Z"
fill={color}
/>
<path
d="M57.812 10.7315C52.03 11.9566 47.67 16.2354 47.222 22.264H53.395C53.669 19.3484 55.561 16.9969 58.267 15.9553C61.418 14.7401 66.805 14.8881 69.178 17.6005C70.774 19.4253 71.305 22.5816 69.212 24.2249C66.675 26.2173 60.39 25.6117 57.214 25.7636C52.631 25.9826 48.141 27.8429 47.183 32.7727C45.1 43.5042 59.035 45.9267 65.902 40.8963C68.095 39.2885 69.672 36.8443 70.261 34.1792H70.577L72.788 42.4508H76.61V20.964C76.517 11.3214 65.462 9.108 57.81 10.7315H57.812ZM68.847 32.2637C66.484 36.649 60.958 40.0441 56.218 38.3318C52.44 36.9686 52.268 31.4095 55.973 29.9181C59.613 28.4524 67.732 29.9694 70.368 25.949C70.275 28.0855 69.906 30.2989 68.849 32.2637H68.847Z"
fill={color}
/>
<path
d="M7.08199 26.5652V42.4475H0.610992V0.000626947H18.863C19.007 -0.00726305 19.141 0.0617763 19.283 0.0696663C27.732 0.531286 33.297 4.601 33.104 13.6025C32.928 21.7991 26.663 26.2199 18.934 26.5671H7.08199V26.5652ZM7.08199 5.4828V21.2941H18.088C23.595 20.8956 27.071 18.1022 26.491 12.265C25.967 6.9781 21.802 5.6544 17.107 5.4788C13.795 5.3546 10.402 5.5795 7.08199 5.4808V5.4828Z"
fill={color}
/>
<path d="M42.647 0H36.529V42.4468H42.647V0Z" fill={color} />
<path
d="M139.872 33.418C138.911 35.4953 137.138 37.1603 134.934 37.8981C132.368 38.7562 128.479 38.5431 126.083 37.2569C122.67 35.4263 121.145 31.6485 121.137 27.8984H145.891C146.194 24.6908 145.902 21.3648 144.496 18.4333C141.083 11.3177 132.859 8.7236 125.513 10.9429C116.868 13.5568 114.165 22.4162 115.462 30.6543C116.86 39.5611 124.197 43.976 132.958 43.3585C138.884 42.9423 144.271 39.1192 145.788 33.4161H139.874L139.872 33.418ZM121.208 23.4381C121.778 17.2457 127.347 14.2018 133.163 15.4269C137.361 16.3107 139.75 19.9523 139.842 24.1068H121.145C121.145 24.1068 121.19 23.6255 121.208 23.4401V23.4381Z"
fill={color}
/>
</svg>
);

View file

@ -0,0 +1,19 @@
import * as React from "react";
import { ISvgIcons } from "../type";
export const SonyLogo: React.FC<ISvgIcons> = ({ width = "44", height = "16", className, color = "currentColor" }) => (
<svg
width={width}
height={height}
viewBox="0 0 44 16"
fill={color}
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M16.1608 13.9C14.6192 13.9 13.1911 13.4366 12.2358 12.5854C11.5454 11.9706 11.1576 11.0816 11.1671 10.1548C11.1671 9.22789 11.5549 8.34832 12.2358 7.73357C13.1248 6.92966 14.6854 6.41894 16.1608 6.41894C17.7875 6.41894 19.0927 6.82562 20.0952 7.73357C20.7762 8.35778 21.1545 9.23735 21.1451 10.1548C21.1451 11.0722 20.7573 11.9517 20.0952 12.5854C19.1683 13.4461 17.7024 13.9 16.1608 13.9V12.9164C16.9742 12.9164 17.7402 12.6327 18.2699 12.1031C18.7995 11.5734 19.0359 10.9397 19.0359 10.1453C19.0359 9.35084 18.7711 8.6888 18.2699 8.18754C17.7497 7.67682 16.9742 7.38363 16.1608 7.38363C15.3474 7.38363 14.5719 7.66736 14.0517 8.18754C13.5505 8.6888 13.2857 9.39813 13.2857 10.1453C13.2668 10.8735 13.5505 11.5734 14.0517 12.1031C14.5719 12.6232 15.3474 12.9164 16.1608 12.9164V13.9ZM4.89665 6.40948C4.07382 6.40948 3.13749 6.56081 2.34304 6.9202C1.60534 7.25122 1 7.78086 1 8.66043C1 9.12386 1.17026 9.56837 1.49182 9.89939C1.70935 10.098 2.04987 10.429 2.94835 10.6276C3.35504 10.7128 4.20623 10.8452 5.06688 10.9397C5.92754 11.0343 6.75032 11.11 7.0908 11.2046C7.36507 11.2708 7.81906 11.3653 7.81906 11.8761C7.81906 12.3868 7.33675 12.5381 7.26109 12.5759C7.17597 12.6138 6.59901 12.8691 5.56811 12.8691C4.88715 12.8502 4.20619 12.7367 3.55361 12.5192C3.16584 12.3773 2.76863 12.1976 2.39032 11.7437C2.239 11.5261 2.15387 11.2708 2.14441 11.006H1.2081V13.6257H2.24843V13.2664C2.24843 13.1812 2.31467 13.115 2.39979 13.115C2.42816 13.115 2.45655 13.115 2.47547 13.1339C2.96727 13.3515 3.47797 13.5123 3.99815 13.6257C4.5467 13.7392 4.89662 13.8244 5.57758 13.8244C6.29637 13.8338 7.00569 13.7392 7.69611 13.5217C8.15008 13.3988 8.57569 13.1907 8.954 12.8975C9.3796 12.5665 9.63498 12.0558 9.62553 11.5167C9.62553 11.0154 9.43636 10.5236 9.08643 10.1642C8.88781 9.97506 8.66081 9.82373 8.41491 9.71024C8.15009 9.58729 7.87582 9.49271 7.59209 9.42651C7.05299 9.2941 5.84238 9.13332 5.26546 9.06711C4.66016 9.00091 3.60094 8.91579 3.1848 8.78338C3.06185 8.74555 2.797 8.6226 2.797 8.31995C2.797 8.10242 2.91994 7.92272 3.14693 7.7714C3.51578 7.53495 4.27242 7.39309 5.05741 7.39309C5.81403 7.39309 6.57062 7.53495 7.2705 7.82814C7.45965 7.91326 7.63935 8.0173 7.80013 8.14025C8.06495 8.36724 8.24469 8.66988 8.32035 9.01036H9.16205V6.73105H8.22574V6.99586C8.22574 7.08098 8.14066 7.19448 7.97042 7.0999C7.54482 6.88237 6.36255 6.40948 4.90606 6.40002L4.89665 6.40948ZM25.4389 6.83508L30.0164 10.9587L29.9691 8.17808C29.9691 7.80923 29.8935 7.65791 29.5057 7.65791H28.6451V6.82562H32.5606V7.65791H31.7188C31.3216 7.65791 31.2932 7.79031 31.2838 8.17808L31.35 13.4839H30.007L24.739 8.78338V12.122C24.739 12.4814 24.7579 12.6516 25.1362 12.6516H26.0725V13.4839H22.2327V12.6516H23.1312C23.4622 12.6516 23.4528 12.33 23.4528 12.1031V8.20646C23.4528 7.9511 23.4149 7.65791 22.8947 7.65791H22.1665V6.82562H25.4389V6.83508ZM37.0151 12.6516C37.0908 12.6516 37.1665 12.6516 37.2421 12.6327C37.3272 12.6043 37.3935 12.5476 37.4218 12.4719C37.4313 12.4152 37.4408 12.349 37.4408 12.2922V10.9776C37.4408 10.9776 37.4408 10.9303 37.384 10.8641C37.3273 10.7979 34.9912 8.14025 34.8777 8.02676C34.7453 7.88489 34.5089 7.65791 34.1589 7.65791H33.3455V6.82562H37.9326V7.65791H37.384C37.2611 7.65791 37.176 7.78086 37.28 7.91326C37.28 7.91326 38.8216 9.75753 38.8405 9.77644C38.8594 9.79536 38.8689 9.80482 38.8878 9.77644C38.9067 9.74807 40.4673 7.92272 40.4767 7.90381C40.5335 7.8376 40.5145 7.73357 40.4483 7.67682C40.4199 7.65791 40.3821 7.63899 40.3443 7.64845H39.7768V6.81617H43.5316V7.64845H42.6898C42.3872 7.64845 42.2642 7.70519 42.0277 7.96055L39.4931 10.8452C39.4931 10.8452 39.4553 10.9208 39.4647 10.9681V12.2827C39.4647 12.3395 39.4647 12.4057 39.4836 12.4624C39.5214 12.5381 39.5782 12.5949 39.6633 12.6232C39.739 12.6327 39.8147 12.6421 39.8903 12.6421H40.751V13.4744H36.1923V12.6421H37.0057L37.0151 12.6516Z"
fill={color}
/>
</svg>
);

View file

@ -0,0 +1,30 @@
import * as React from "react";
import { ISvgIcons } from "../type";
export const ZerodhaLogo: React.FC<ISvgIcons> = ({
width = "64",
height = "16",
className,
color = "currentColor",
}) => (
<svg
width={width}
height={height}
viewBox="0 0 64 16"
fill={color}
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M7.46267 8.1456C7.92616 8.74901 8.31095 9.42239 8.60828 10.157V6.29163H5.32886C6.11592 6.72014 6.84177 7.34104 7.46267 8.1456ZM2.7403 6.70265C2.13689 6.70265 1.55094 6.83382 1 7.06994V13.8999H8.27596C8.22349 9.91211 5.75737 6.6939 2.73155 6.6939"
fill={color}
/>
<path
d="M12.9634 12.7281L17.0299 7.80457H13.0858V6.72892H18.604V7.62093L14.5375 12.5444H18.604V13.6201H12.9634V12.7281ZM20.1257 6.72892H25.2241V7.82206H21.3237V9.59733H24.778V10.6905H21.3237V12.5357H25.2765V13.6288H20.1257V6.73767V6.72892ZM26.7282 6.72892H29.7978C30.235 6.72892 30.6111 6.79014 30.9521 6.91257C31.2932 7.035 31.5643 7.20116 31.7917 7.41979C31.9753 7.61218 32.1152 7.83081 32.2114 8.07567C32.3076 8.32054 32.3601 8.60038 32.3601 8.90646V8.92395C32.3601 9.2038 32.3164 9.4574 32.2377 9.68478C32.1589 9.91215 32.0453 10.1133 31.8966 10.2882C31.7479 10.4631 31.5818 10.6118 31.3806 10.7342C31.1795 10.8566 30.9609 10.9528 30.716 11.014L32.5787 13.6201H31.1533L29.4567 11.2152H27.9351V13.6201H26.737V6.72892H26.7282ZM29.7016 10.1483C30.1388 10.1483 30.4799 10.0433 30.7422 9.83345C31.0046 9.62356 31.127 9.34372 31.127 8.98517V8.96768C31.127 8.59164 31.0046 8.30305 30.751 8.11065C30.4974 7.91826 30.1476 7.82206 29.6928 7.82206H27.9263V10.1483H29.7016ZM37.1349 13.7425C36.6015 13.7425 36.1205 13.6463 35.6745 13.4627C35.2285 13.279 34.8612 13.0254 34.5376 12.7019C34.2141 12.3783 33.9779 12.0022 33.803 11.5737C33.6281 11.1452 33.5407 10.6817 33.5407 10.2007V10.1833C33.5407 9.69352 33.6281 9.23878 33.803 8.81026C33.9779 8.38175 34.2316 8.00571 34.5551 7.6734C34.8787 7.34108 35.2547 7.08747 35.7007 6.90382C36.1467 6.72018 36.6277 6.61523 37.1612 6.61523C37.6946 6.61523 38.1756 6.71143 38.6216 6.89508C39.0589 7.07873 39.4349 7.34108 39.7585 7.65591C40.082 7.97073 40.3182 8.35552 40.4931 8.78403C40.668 9.21254 40.7554 9.67603 40.7554 10.157V10.1745C40.7554 10.6642 40.668 11.119 40.4931 11.5475C40.3182 11.976 40.0646 12.352 39.741 12.6844C39.4174 13.0079 39.0414 13.2703 38.5954 13.4539C38.1494 13.6376 37.6684 13.7425 37.1349 13.7425ZM37.1524 12.6319C37.4935 12.6319 37.8083 12.5707 38.0882 12.4395C38.368 12.3083 38.6129 12.1334 38.8227 11.9148C39.0326 11.6962 39.1813 11.4338 39.295 11.1452C39.4087 10.8566 39.4699 10.5331 39.4699 10.2007V10.1833C39.4699 9.85094 39.4087 9.52737 39.295 9.23003C39.1813 8.9327 39.0239 8.67034 38.814 8.45171C38.6041 8.23309 38.3593 8.05818 38.0707 7.92701C37.7821 7.79583 37.4672 7.72587 37.1262 7.72587C36.7851 7.72587 36.4703 7.78708 36.1905 7.91826C35.9106 8.04944 35.6658 8.22434 35.4559 8.44297C35.246 8.6616 35.0973 8.92395 34.9836 9.21254C34.87 9.50113 34.8087 9.8247 34.8087 10.157V10.1745C34.8087 10.5068 34.87 10.8304 34.9836 11.1277C35.0973 11.4251 35.2547 11.6874 35.4646 11.906C35.6745 12.1247 35.9194 12.2996 36.208 12.4308C36.4965 12.5619 36.8114 12.6319 37.1524 12.6319ZM42.2159 6.72892H44.7869C45.3291 6.72892 45.8189 6.81637 46.2736 6.99128C46.7284 7.16618 47.1131 7.4023 47.4367 7.71712C47.7603 8.03195 48.0139 8.3905 48.1888 8.80152C48.3637 9.21254 48.4511 9.66729 48.4511 10.157V10.1745C48.4511 10.6642 48.3637 11.1102 48.1888 11.53C48.0139 11.9498 47.7603 12.3171 47.4367 12.6231C47.1131 12.9292 46.7284 13.1741 46.2736 13.349C45.8189 13.5239 45.3291 13.6113 44.7869 13.6113H42.2159V6.72018V6.72892ZM44.7782 12.5357C45.1367 12.5357 45.469 12.4745 45.7664 12.3608C46.0637 12.2471 46.3173 12.0809 46.5185 11.8798C46.7196 11.6787 46.8858 11.4251 46.9995 11.1365C47.1131 10.8479 47.1744 10.5418 47.1744 10.2007V10.1833C47.1744 9.85094 47.1131 9.53611 46.9995 9.24752C46.8858 8.95893 46.7196 8.70532 46.5185 8.50418C46.3173 8.30305 46.0637 8.13689 45.7664 8.01446C45.469 7.89202 45.1455 7.83955 44.7782 7.83955H43.4227V12.5444H44.7782V12.5357ZM49.9203 6.72892H51.1184V9.59733H54.4241V6.72892H55.6222V13.6201H54.4241V10.7167H51.1184V13.6201H49.9203V6.72892ZM59.8461 6.6852H60.9654L64 13.6288H62.7232L62.0236 11.9673H58.7617L58.0533 13.6288H56.8115L59.8461 6.6852ZM61.5776 10.8916L60.3883 8.13689L59.2077 10.8916H61.5776Z"
fill={color}
/>
</svg>
);

View file

@ -55,3 +55,4 @@ export * from "./display-properties";
export * from "./ai-icon";
export * from "./plane-icon";
export * from "./wiki-icon";
export * from "./brand";

View file

@ -36,3 +36,4 @@ export * from "./tooltip";
export * from "./typography";
export * from "./utils";
export * from "./billing";
export * from "./oauth";

View file

@ -0,0 +1 @@
export * from "./oauth-options";

View file

@ -0,0 +1,32 @@
import * as React from "react";
import { cn } from "../../helpers";
export interface OAuthButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
text: string;
icon: React.ReactNode;
compact?: boolean;
}
const OAuthButton = React.forwardRef<HTMLButtonElement, OAuthButtonProps>((props, ref) => {
const { text, icon, compact = false, className = "", ...rest } = props;
return (
<button
ref={ref}
className={cn(
"flex h-9 w-full items-center justify-center gap-2 rounded-md border border-custom-border-300 px-4 py-2.5 text-sm font-medium text-custom-text-100 duration-300 bg-onboarding-background-200 hover:bg-onboarding-background-300",
className
)}
{...rest}
>
<div className="flex flex-shrink-0 items-center justify-center">{icon}</div>
{!compact && (
<div className="flex flex-grow items-center justify-center transition-opacity duration-300">{text}</div>
)}
</button>
);
});
OAuthButton.displayName = "plane-ui-oauth-button";
export { OAuthButton };

View file

@ -0,0 +1,57 @@
import * as React from "react";
import { cn } from "../../helpers";
import { OAuthButton } from "./oauth-button";
export type TOAuthOption = {
id: string;
text: string;
icon: React.ReactNode;
onClick: () => void;
enabled?: boolean;
};
type OAuthOptionsProps = {
options: TOAuthOption[];
compact?: boolean;
className?: string;
containerClassName?: string;
};
export const OAuthOptions = (props: OAuthOptionsProps) => {
const { options, compact = false, className = "", containerClassName = "" } = props;
// Filter enabled options
const enabledOptions = options.filter((option) => option.enabled !== false);
if (enabledOptions.length === 0) return null;
return (
<div className={cn("w-full", containerClassName)}>
<div
className={cn(
"flex gap-4 overflow-hidden transition-all duration-500 ease-in-out",
compact ? "flex-row" : "flex-col",
className
)}
>
{enabledOptions.map((option) => (
<OAuthButton
key={option.id}
text={option.text}
icon={option.icon}
onClick={option.onClick}
compact={compact}
className="transition-all duration-300 ease-in-out"
/>
))}
</div>
<div className="mt-4 flex items-center transition-all duration-300">
<hr className="w-full border-custom-border-300 transition-colors duration-300" />
<p className="mx-3 flex-shrink-0 text-center text-sm text-custom-text-400 transition-colors duration-300">or</p>
<hr className="w-full border-custom-border-300 transition-colors duration-300" />
</div>
</div>
);
};