Separates New Components from the branch

This commit is contained in:
Nithin David Thomas 2025-10-16 13:39:27 +05:30
parent 630a53df8f
commit 4e4ea4381b
41 changed files with 0 additions and 5242 deletions

View file

@ -1,308 +0,0 @@
import React from 'react';
import { Alert, AlertTitle, AlertDescription } from '../../components/ui/Alert/Alert';
import { Info, AlertTriangle, AlertCircle, CheckCircle } from 'lucide-react';
// Storybook configuration
export default {
title: 'Components/Alert',
component: Alert,
tags: ['autodocs'],
parameters: {
layout: 'padded',
docs: {
description: {
component:
'Alert component for displaying important messages to users with various types and background variants.',
},
},
},
argTypes: {
type: {
control: { type: 'select' },
options: ['info', 'warning', 'danger'],
description: 'The type of alert',
},
background: {
control: { type: 'select' },
options: ['none', 'grey', 'white', 'state-specific'],
description: 'The background variant of the alert',
},
children: {
control: 'text',
description: 'The message content to display in the alert',
},
className: {
control: 'text',
description: 'Additional CSS classes to apply to the alert container',
},
},
};
// Template for stories
const Template = (args) => <Alert {...args} />;
// Default alert
export const Default = Template.bind({});
Default.args = {
type: 'info',
background: 'none',
children: (
<>
<Info className="tw-w-4 tw-h-4 tw-text-icon-brand" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>Default Alert</AlertTitle>
<AlertDescription>This is a default alert message.</AlertDescription>
</div>
</>
),
};
// Alert variants with different types
export const InfoAlert = Template.bind({});
InfoAlert.args = {
type: 'info',
background: 'none',
children: (
<>
<Info className="tw-w-4 tw-h-4 tw-text-icon-brand" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>Information</AlertTitle>
<AlertDescription>This is an informational alert message.</AlertDescription>
</div>
</>
),
};
export const Warning = Template.bind({});
Warning.args = {
type: 'warning',
background: 'none',
children: (
<>
<AlertTriangle className="tw-w-4 tw-h-4 tw-text-icon-warning" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>Warning</AlertTitle>
<AlertDescription>This is a warning alert message.</AlertDescription>
</div>
</>
),
};
export const Danger = Template.bind({});
Danger.args = {
type: 'danger',
background: 'none',
children: (
<>
<AlertCircle className="tw-w-4 tw-h-4 tw-text-icon-danger" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>Error</AlertTitle>
<AlertDescription>This is an error alert message.</AlertDescription>
</div>
</>
),
};
// Background variants
export const GreyBackground = Template.bind({});
GreyBackground.args = {
type: 'info',
background: 'grey',
children: (
<>
<Info className="tw-w-4 tw-h-4 tw-text-icon-brand" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>Grey Background</AlertTitle>
<AlertDescription>This alert has a grey background.</AlertDescription>
</div>
</>
),
};
export const WhiteBackground = Template.bind({});
WhiteBackground.args = {
type: 'info',
background: 'white',
children: (
<>
<Info className="tw-w-4 tw-h-4 tw-text-icon-brand" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>White Background</AlertTitle>
<AlertDescription>This alert has a white background with shadow.</AlertDescription>
</div>
</>
),
};
export const StateSpecificBackground = Template.bind({});
StateSpecificBackground.args = {
type: 'info',
background: 'state-specific',
children: (
<>
<Info className="tw-w-4 tw-h-4 tw-text-icon-brand" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>State Specific Background</AlertTitle>
<AlertDescription>This alert has a state-specific colored background.</AlertDescription>
</div>
</>
),
};
// Long message variant
export const LongMessage = Template.bind({});
LongMessage.args = {
type: 'warning',
background: 'white',
children: (
<>
<AlertTriangle className="tw-w-4 tw-h-4 tw-text-icon-warning" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>Long Message Alert</AlertTitle>
<AlertDescription>
This is a very long alert message that demonstrates how the alert component handles text wrapping and
overflow. The message should wrap properly and maintain good readability even with extended content that spans
multiple lines.
</AlertDescription>
</div>
</>
),
};
// No icon variant
export const NoIcon = Template.bind({});
NoIcon.args = {
type: 'info',
background: 'none',
children: (
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>No Icon Alert</AlertTitle>
<AlertDescription>This alert has no icon.</AlertDescription>
</div>
),
};
// All variants showcase
export const AllVariants = () => {
const types = ['info', 'warning', 'danger'];
const backgrounds = ['none', 'grey', 'white', 'state-specific'];
const icons = {
info: Info,
warning: AlertTriangle,
danger: AlertCircle,
};
const titles = {
info: 'Information',
warning: 'Warning',
danger: 'Error',
};
const descriptions = {
info: 'This is an informational message.',
warning: 'Please review your settings before proceeding.',
danger: 'Something went wrong. Please try again.',
};
return (
<div className="tw-space-y-8">
<div>
<h2 className="tw-text-2xl tw-font-bold tw-mb-4">Alert Component - All Variants</h2>
<p className="tw-text-gray-600 tw-mb-6">Showcasing all 12 variants (3 types × 4 backgrounds)</p>
</div>
{types.map((type) => (
<div key={type} className="tw-space-y-4">
<h3 className="tw-text-lg tw-font-semibold tw-capitalize tw-text-gray-800">{type} Type</h3>
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4">
{backgrounds.map((background) => {
const Icon = icons[type];
return (
<div key={`${type}-${background}`} className="tw-space-y-2">
<div className="tw-text-sm tw-font-medium tw-text-gray-600 tw-capitalize">
{background.replace('-', ' ')} Background
</div>
<Alert type={type} background={background}>
<Icon className="tw-w-4 tw-h-4" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>{titles[type]}</AlertTitle>
<AlertDescription>{descriptions[type]}</AlertDescription>
</div>
</Alert>
</div>
);
})}
</div>
</div>
))}
</div>
);
};
// Background variants showcase
export const BackgroundVariants = () => (
<div className="tw-space-y-4">
<h3 className="tw-text-lg tw-font-semibold tw-mb-4">Background Variants</h3>
<Alert type="info" background="none">
<Info className="tw-w-4 tw-h-4 tw-text-icon-brand" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>No Background</AlertTitle>
<AlertDescription>Alert with no background</AlertDescription>
</div>
</Alert>
<Alert type="info" background="grey">
<Info className="tw-w-4 tw-h-4 tw-text-icon-brand" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>Grey Background</AlertTitle>
<AlertDescription>Alert with grey background</AlertDescription>
</div>
</Alert>
<Alert type="info" background="white">
<Info className="tw-w-4 tw-h-4 tw-text-icon-brand" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>White Background</AlertTitle>
<AlertDescription>Alert with white background and shadow</AlertDescription>
</div>
</Alert>
<Alert type="info" background="state-specific">
<Info className="tw-w-4 tw-h-4 tw-text-icon-brand" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>State Specific Background</AlertTitle>
<AlertDescription>Alert with state-specific colored background</AlertDescription>
</div>
</Alert>
</div>
);
// Type variants showcase
export const TypeVariants = () => (
<div className="tw-space-y-4">
<h3 className="tw-text-lg tw-font-semibold tw-mb-4">Type Variants</h3>
<Alert type="info" background="state-specific">
<Info className="tw-w-4 tw-h-4 tw-text-icon-brand" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>Information</AlertTitle>
<AlertDescription>This is an informational alert with blue accent</AlertDescription>
</div>
</Alert>
<Alert type="warning" background="state-specific">
<AlertTriangle className="tw-w-4 tw-h-4 tw-text-icon-warning" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>Warning</AlertTitle>
<AlertDescription>This is a warning alert with orange accent</AlertDescription>
</div>
</Alert>
<Alert type="danger" background="state-specific">
<AlertCircle className="tw-w-4 tw-h-4 tw-text-icon-danger" />
<div className="tw-flex tw-flex-col tw-gap-2">
<AlertTitle>Error</AlertTitle>
<AlertDescription>This is an error alert with red accent</AlertDescription>
</div>
</Alert>
</div>
);

View file

@ -1,9 +0,0 @@
import React from "react";
export const AuthCenteredLayout = ({ children }) => {
return (
<div className="tw-flex tw-min-h-svh tw-w-full tw-items-center tw-justify-center tw-p-6 md:tw-p-10">
<div className="tw-w-full tw-max-w-sm">{children}</div>
</div>
);
};

View file

@ -1,19 +0,0 @@
import React from 'react';
import FeatureList from './FeatureList';
export const AuthLayout = ({ children }) => {
return (
<div className="tw-grid tw-min-h-svh lg:tw-grid-cols-[38%_1fr] tw-bg-background-surface-layer-01">
<div className="tw-flex tw-flex-col tw-gap-4 tw-p-6 md:tw-p-10">
<div className="tw-flex tw-flex-1 tw-items-center tw-justify-center">
<div className="tw-w-full tw-max-w-xs">{children}</div>
</div>
</div>
<div className="tw-bg-muted tw-relative tw-hidden lg:tw-block tw-h-full tw-w-full tw-p-4">
<div className="tw-h-full tw-w-full tw-rounded-2xl tw-object-cover tw-bg-[linear-gradient(90deg,hsla(176,61%,87%,1)_0%,hsla(150,54%,86%,1)_50%,hsla(301,68%,84%,1)_100%)] tw-flex tw-items-center tw-justify-center tw-p-8">
<FeatureList />
</div>
</div>
</div>
);
};

View file

@ -1,57 +0,0 @@
import React from 'react';
import { DynamicIcon } from 'lucide-react/dynamic';
const FeatureList = () => {
const features = [
{
icon: 'zap',
title: 'Build apps, fast',
description: 'Turn ideas into production-ready business\napplications in minutes with AI and low-code.',
className: 'tw-text-[#FBCA73]',
},
{
icon: 'workflow',
title: 'Automate business processes',
description: 'Use workflows and AI agents to streamline\nprocesses and drive real outcomes.',
className: 'tw-text-[#486AE1]',
},
{
icon: 'puzzle',
title: 'Connect your data',
description: 'Integrate with 70+ data sources instantly.',
className: 'tw-text-[#9D78E7]',
},
{
icon: 'key-round',
title: 'Secure by default',
description: 'Enterprise-grade compliance: authentication,\nauthorization, CI/CD, audit logs, and more.',
className: 'tw-text-[#33B480]',
},
];
return (
<div className="tw-flex tw-flex-col tw-gap-16 tw-items-start tw-relative tw-w-full tw-max-w-md">
{features.map((feature) => (
<div key={feature.icon} className="tw-flex tw-gap-5 tw-items-start tw-relative tw-shrink-0 tw-w-full">
<div className="tw-overflow-clip tw-relative tw-shrink-0 tw-w-16 tw-h-16 tw-flex tw-items-center tw-justify-center">
<DynamicIcon name={feature.icon} size={30} className={feature.className} />
</div>
<div className="tw-flex tw-flex-col tw-gap-1.5 tw-items-start tw-relative tw-shrink-0 tw-flex-1">
<div className="tw-flex tw-flex-col tw-items-start tw-relative tw-shrink-0 tw-w-full">
<div className="tw-flex tw-gap-3 tw-items-center tw-relative tw-shrink-0">
<h3 className="tw-font-medium tw-leading-8 tw-not-italic tw-relative tw-shrink-0 tw-text-text-default tw-text-xl tw-tracking-[-0.4px] tw-m-0">
{feature.title}
</h3>
</div>
</div>
<p className="tw-font-normal tw-leading-6 tw-not-italic tw-relative tw-shrink-0 tw-text-text-placeholder tw-text-[15px] tw-tracking-[-0.3px] tw-w-full tw-whitespace-pre-line tw-m-0">
{feature.description}
</p>
</div>
</div>
))}
</div>
);
};
export default FeatureList;

View file

@ -1,189 +0,0 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { CornerDownLeft, Info } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { FormWrapper } from '@/components/Auth/FormWrapper';
import { InlineInfoCompound } from '@/components/ui/InlineInfo/InlineInfo';
export function ForgotPasswordForm({ className, ...props }) {
const {
// Header and sign up section
headerText,
signupText,
signupUrl,
signupCTA,
showSignup,
// Form fields
emailLabel,
emailPlaceholder,
// Button
buttonText,
// Admin banner
adminContactText,
showAdminBanner,
showSeparator,
// Form functionality
onSubmit,
emailValue,
onEmailChange,
// Validation and state
emailValidation,
emailValidationMessage,
isLoading,
disabled,
} = props;
return (
<FormWrapper>
<form className={cn('tw-flex tw-flex-col tw-gap-6', className)} onSubmit={onSubmit} {...props}>
<div className="tw-flex tw-flex-col tw-gap-0.5 tw-min-w-96">
<h1 className="tw-text-4xl tw-tracking-tight tw-font-medium tw-mb-0" data-cy="forgot-password-header">
{headerText}
</h1>
{showSignup && (
<p className="tw-text-balance tw-text-sm tw-text-text-placeholder tw-mb-0">
<span>{signupText}</span>
<span>
<Link
to={signupUrl}
className="tw-text-text-brand tw-text-[11px] tw-font-medium tw-no-underline tw-pl-1.5 tw-pb-0.5 tw-self-center hover:tw-text-button-primary-hover"
tabIndex="-1"
data-cy="create-an-account-link"
>
{signupCTA}
</Link>
</span>
</p>
)}
</div>
<div className="tw-grid tw-gap-4">
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="email" size="large">
{emailLabel}
</Label>
<Input
type="email"
placeholder={emailPlaceholder}
value={emailValue}
onChange={onEmailChange}
disabled={disabled}
required
validation={emailValidation}
isValidatedMessages={emailValidationMessage}
size="large"
/>
</div>
<Button
size="large"
type="submit"
className="tw-w-fit"
disabled={disabled || isLoading}
isLoading={isLoading}
>
{buttonText}
<CornerDownLeft width="16" height="16" />
</Button>
{showSeparator && (
<div className="tw-relative tw-flex tw-items-center tw-text-center tw-text-sm">
<div className="tw-flex-1 tw-h-px tw-bg-border-weak" />
<span className="tw-px-2 tw-text-text-placeholder tw-text-lg tw-font-medium">OR</span>
<div className="tw-flex-1 tw-h-px tw-bg-border-weak" />
</div>
)}
{showAdminBanner && (
<InlineInfoCompound
type="info"
background="state-specific"
icon={Info}
description={adminContactText}
data-cy="admin-contact-banner"
/>
)}
</div>
</form>
</FormWrapper>
);
}
ForgotPasswordForm.propTypes = {
className: PropTypes.string,
// Header and sign up section
headerText: PropTypes.string,
signupText: PropTypes.string,
signupUrl: PropTypes.string,
signupCTA: PropTypes.string,
showSignup: PropTypes.bool,
// Form fields
emailLabel: PropTypes.string,
emailPlaceholder: PropTypes.string,
// Button
buttonText: PropTypes.string,
// Admin banner
adminContactText: PropTypes.string,
showAdminBanner: PropTypes.bool,
showSeparator: PropTypes.bool,
// Form functionality
onSubmit: PropTypes.func,
emailValue: PropTypes.string,
onEmailChange: PropTypes.func,
// Validation and state
emailValidation: PropTypes.func,
emailValidationMessage: PropTypes.object,
isLoading: PropTypes.bool,
disabled: PropTypes.bool,
};
ForgotPasswordForm.defaultProps = {
className: '',
// Header and sign up section
headerText: 'Forgot Password',
signupText: 'New to ToolJet?',
signupUrl: '#',
signupCTA: 'Create an account',
showSignup: true,
// Form fields
emailLabel: 'Email address',
emailPlaceholder: 'Enter email address',
// Button
buttonText: 'Send a reset link',
// Admin banner
adminContactText: 'Contact admin to reset your password',
showAdminBanner: true,
showSeparator: true,
// Form functionality
onSubmit: undefined,
emailValue: undefined,
onEmailChange: undefined,
// Validation and state
emailValidation: undefined,
emailValidationMessage: undefined,
isLoading: false,
disabled: false,
};

View file

@ -1,123 +0,0 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { ArrowLeft } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { FormWrapper } from '@/components/Auth/FormWrapper';
export function ForgotPasswordInfoScreen({ className, ...props }) {
const {
// Header
headerText,
// Message content
messageText,
email,
// Info text
infoText,
showInfo,
// Button
buttonText,
onBackToLogin,
// Separator
showSeparator,
} = props;
return (
<FormWrapper>
<div className={cn('tw-flex tw-flex-col tw-gap-6 tw-min-w-96', className)} {...props}>
<div className="tw-flex tw-flex-col tw-gap-0.5">
<h1 className="tw-text-4xl tw-tracking-tight tw-font-medium tw-mb-0" data-cy="forgot-password-info-header">
{headerText}
</h1>
</div>
<div className="tw-flex tw-flex-col tw-gap-4">
<p className="tw-text-balance tw-text-sm tw-text-text-placeholder tw-mb-0" data-cy="forgot-password-message">
{messageText}
{email && (
<>
{' '}
<span className="tw-font-medium tw-text-text-brand">{email}</span>
</>
)}
.
</p>
{showInfo && (
<p className="tw-text-sm tw-text-text-placeholder tw-mb-0" data-cy="forgot-password-info">
{infoText}
</p>
)}
{showSeparator && (
<div className="tw-relative tw-flex tw-items-center tw-text-center tw-text-sm">
<div className="tw-flex-1 tw-h-px tw-bg-border-weak" />
<span className="tw-px-2 tw-text-muted-foreground">OR</span>
<div className="tw-flex-1 tw-h-px tw-bg-border-weak" />
</div>
)}
<Button
size="default"
variant="outline"
className="tw-w-fit"
onClick={onBackToLogin}
data-cy="back-to-login-button"
>
<ArrowLeft width="16" height="16" />
{buttonText}
</Button>
</div>
</div>
</FormWrapper>
);
}
ForgotPasswordInfoScreen.propTypes = {
className: PropTypes.string,
// Header
headerText: PropTypes.string,
// Message content
messageText: PropTypes.string,
email: PropTypes.string,
// Info text
infoText: PropTypes.string,
showInfo: PropTypes.bool,
// Button
buttonText: PropTypes.string,
onBackToLogin: PropTypes.func,
// Separator
showSeparator: PropTypes.bool,
};
ForgotPasswordInfoScreen.defaultProps = {
className: '',
// Header
headerText: 'Check your mail',
// Message content
messageText: "We've sent a password reset link to",
email: '',
// Info text
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
// Button
buttonText: 'Back to login',
onBackToLogin: undefined,
// Separator
showSeparator: true,
};

View file

@ -1,12 +0,0 @@
import * as React from 'react';
import Logo from '@/modules/common/resources/images/Logo';
export const FormWrapper = ({ children }) => {
return (
<div className="tw-flex tw-flex-col tw-gap-9">
<Logo />
{children}
</div>
);
};

View file

@ -1,21 +0,0 @@
import React from 'react';
import { Button } from '@/components/ui/button';
import SolidIcon from '@/_ui/Icon/SolidIcons';
export const GitHubSigninButton = ({ onClick, icon, text, dataCy }) => {
return (
<Button
onClick={onClick}
data-cy={dataCy}
type="button"
variant="outline"
size="large"
className="tw-justify-center"
>
<SolidIcon name="github" />
<span className="sso-text" data-cy={`${dataCy}-text`}>
{text}
</span>
</Button>
);
};

View file

@ -1,21 +0,0 @@
import React from 'react';
import { Button } from '@/components/ui/button';
import SolidIcon from '@/_ui/Icon/SolidIcons';
export const GoogleSigninButton = ({ onClick, icon, text, dataCy }) => {
return (
<Button
onClick={onClick}
data-cy={dataCy}
type="button"
variant="outline"
size="large"
className="tw-justify-center"
>
<SolidIcon name="google" />
<span className="sso-text" data-cy={`${dataCy}-text`}>
{text}
</span>
</Button>
);
};

View file

@ -1,163 +0,0 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { CornerDownLeft } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { FormWrapper } from '@/components/Auth/FormWrapper';
export function InviteSignupForm({ className, ...props }) {
const {
// Header section
headerText,
descriptionText,
// Form fields
emailLabel,
emailPlaceholder,
emailValue,
emailDisabled,
passwordLabel,
passwordPlaceholder,
passwordValue,
onPasswordChange,
passwordValidation,
passwordValidationMessage,
// Button
buttonText,
// Form functionality
onSubmit,
// Validation and state
isLoading,
disabled,
} = props;
return (
<FormWrapper>
<form className={cn('tw-flex tw-flex-col tw-gap-6', className)} onSubmit={onSubmit} {...props}>
<div className="tw-flex tw-flex-col tw-gap-2 tw-min-w-20">
<h1 className="tw-text-4xl tw-tracking-tight tw-font-medium tw-mb-0" data-cy="">
{headerText}
</h1>
{descriptionText && (
<p className="tw-text-balance tw-text-sm tw-text-text-placeholder tw-mb-0">{descriptionText}</p>
)}
</div>
<div className="tw-grid tw-gap-4">
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="email" size="large">
{emailLabel}
</Label>
<Input
type="email"
placeholder={emailPlaceholder}
value={emailValue}
disabled={emailDisabled || disabled}
required
size="large"
/>
</div>
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="password" size="large">
{passwordLabel}
</Label>
<Input
type="password"
placeholder={passwordPlaceholder}
value={passwordValue}
onChange={onPasswordChange}
disabled={disabled}
showEncryption={false}
required
validation={passwordValidation}
isValidatedMessages={passwordValidationMessage}
size="large"
/>
</div>
<Button
size="large"
type="submit"
className="tw-w-fit"
disabled={disabled || isLoading}
isLoading={isLoading}
>
{buttonText}
<CornerDownLeft width="16" height="16" />
</Button>
</div>
</form>
</FormWrapper>
);
}
InviteSignupForm.propTypes = {
className: PropTypes.string,
// Header section
headerText: PropTypes.string,
descriptionText: PropTypes.string,
// Form fields
emailLabel: PropTypes.string,
emailPlaceholder: PropTypes.string,
emailValue: PropTypes.string,
emailDisabled: PropTypes.bool,
passwordLabel: PropTypes.string,
passwordPlaceholder: PropTypes.string,
passwordValue: PropTypes.string,
onPasswordChange: PropTypes.func,
passwordValidation: PropTypes.func,
passwordValidationMessage: PropTypes.object,
// Button
buttonText: PropTypes.string,
// Form functionality
onSubmit: PropTypes.func,
// Validation and state
isLoading: PropTypes.bool,
disabled: PropTypes.bool,
};
InviteSignupForm.defaultProps = {
className: '',
// Header section
headerText: 'Sign up',
descriptionText: '',
// Form fields
emailLabel: 'Email',
emailPlaceholder: 'Enter your email',
emailValue: '',
emailDisabled: true,
passwordLabel: 'Password',
passwordPlaceholder: 'Create password',
passwordValue: '',
onPasswordChange: undefined,
passwordValidation: undefined,
passwordValidationMessage: undefined,
// Button
buttonText: 'Create account',
// Form functionality
onSubmit: undefined,
// Validation and state
isLoading: false,
disabled: false,
};

View file

@ -1,171 +0,0 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { CornerDownLeft } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { FormWrapper } from '@/components/Auth/FormWrapper';
export function JoinWorkspaceForm({ className, ...props }) {
const {
// Header section
headerText,
descriptionText,
// Form fields
nameLabel,
namePlaceholder,
nameValue,
onNameChange,
nameValidation,
nameValidationMessage,
emailLabel,
emailPlaceholder,
emailValue,
onEmailChange,
emailValidation,
emailValidationMessage,
// Button
buttonText,
// Form functionality
onSubmit,
// Validation and state
isLoading,
disabled,
} = props;
return (
<FormWrapper>
<form className={cn('tw-flex tw-flex-col tw-gap-6', className)} onSubmit={onSubmit} {...props}>
<div className="tw-flex tw-flex-col tw-gap-2 tw-min-w-20">
<h1 className="tw-text-4xl tw-tracking-tight tw-font-medium tw-mb-0" data-cy="">
{headerText}
</h1>
{descriptionText && (
<p className="tw-text-balance tw-text-sm tw-text-text-placeholder tw-mb-0">{descriptionText}</p>
)}
</div>
<div className="tw-grid tw-gap-4">
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="name" size="large">
{nameLabel}
</Label>
<Input
type="text"
placeholder={namePlaceholder}
value={nameValue}
onChange={onNameChange}
disabled={disabled}
required
validation={nameValidation}
isValidatedMessages={nameValidationMessage}
size="large"
/>
</div>
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="email" size="large">
{emailLabel}
</Label>
<Input
type="email"
placeholder={emailPlaceholder}
value={emailValue}
onChange={onEmailChange}
disabled={disabled}
required
validation={emailValidation}
isValidatedMessages={emailValidationMessage}
size="large"
/>
</div>
<Button
size="large"
type="submit"
className="tw-w-fit"
disabled={disabled || isLoading}
isLoading={isLoading}
>
{buttonText}
<CornerDownLeft width="16" height="16" />
</Button>
</div>
</form>
</FormWrapper>
);
}
JoinWorkspaceForm.propTypes = {
className: PropTypes.string,
// Header section
headerText: PropTypes.string,
descriptionText: PropTypes.string,
// Form fields
nameLabel: PropTypes.string,
namePlaceholder: PropTypes.string,
nameValue: PropTypes.string,
onNameChange: PropTypes.func,
nameValidation: PropTypes.func,
nameValidationMessage: PropTypes.object,
emailLabel: PropTypes.string,
emailPlaceholder: PropTypes.string,
emailValue: PropTypes.string,
onEmailChange: PropTypes.func,
emailValidation: PropTypes.func,
emailValidationMessage: PropTypes.object,
// Button
buttonText: PropTypes.string,
// Form functionality
onSubmit: PropTypes.func,
// Validation and state
isLoading: PropTypes.bool,
disabled: PropTypes.bool,
};
JoinWorkspaceForm.defaultProps = {
className: '',
// Header section
headerText: 'Join workspace',
descriptionText: '',
// Form fields
nameLabel: 'Name',
namePlaceholder: 'Enter your name',
nameValue: '',
onNameChange: undefined,
nameValidation: undefined,
nameValidationMessage: undefined,
emailLabel: 'Email',
emailPlaceholder: 'Enter your email',
emailValue: '',
onEmailChange: undefined,
emailValidation: undefined,
emailValidationMessage: undefined,
// Button
buttonText: 'Accept Invite',
// Form functionality
onSubmit: undefined,
// Validation and state
isLoading: false,
disabled: false,
};

View file

@ -1,240 +0,0 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { CornerDownLeft } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { FormWrapper } from '@/components/Auth/FormWrapper';
export function LoginForm({ className, ...props }) {
const {
// Header and sign up section
signinHeader,
signUpText,
signUpUrl,
signUpCTA,
showSignup,
organizationName,
// Form fields
emailLabel,
emailPlaceholder,
passwordLabel,
passwordPlaceholder,
// Forgot password
showForgotPassword,
forgotPasswordUrl,
forgotPasswordText,
// Button and separator
signinButtonText,
orText,
showOrSeparator,
// Form functionality
onSubmit,
emailValue,
passwordValue,
onEmailChange,
onPasswordChange,
// Validation and state
emailValidation,
passwordValidation,
emailValidationMessage,
passwordValidationMessage,
isLoading,
disabled,
} = props;
return (
<FormWrapper>
<form className={cn('tw-flex tw-flex-col tw-gap-6', className)} onSubmit={onSubmit} {...props}>
<div className="tw-flex tw-flex-col tw-gap-2 tw-min-w-20">
<h1 className="tw-text-4xl tw-tracking-tight tw-font-medium tw-mb-0" data-cy="">
{signinHeader}
</h1>
{(organizationName || showSignup) && (
<p className="tw-text-balance tw-text-sm tw-text-text-placeholder tw-mb-0">
{organizationName && (
<>
Sign in to the workspace -{' '}
<span className="tw-font-medium" data-cy="workspace-name">
{organizationName}
</span>
.
</>
)}{' '}
{showSignup && (
<>
<span>{signUpText}</span>
<span>
<Link
to={signUpUrl}
className="tw-text-text-brand tw-text-[11px] tw-font-medium tw-no-underline tw-pl-1.5 tw-pb-0.5 tw-self-center hover:tw-text-button-primary-hover"
tabIndex="-1"
data-cy="create-an-account-link"
>
{signUpCTA}
</Link>
</span>
</>
)}
</p>
)}
</div>
<div className="tw-grid tw-gap-4">
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="email" size="large">
{emailLabel}
</Label>
<Input
type="email"
placeholder={emailPlaceholder}
value={emailValue}
onChange={onEmailChange}
disabled={disabled}
required
validation={emailValidation}
isValidatedMessages={emailValidationMessage}
size="large"
/>
</div>
<div className="tw-grid tw-gap-0.5">
<div className="tw-flex tw-items-center tw-justify-between">
<Label htmlFor="password" size="large">
{passwordLabel}
</Label>
{showForgotPassword && (
<Link
to={forgotPasswordUrl}
tabIndex="-1"
className="tw-text-text-brand tw-text-[11px] tw-font-medium tw-no-underline tw-pl-1.5 tw-pb-0.5 tw-self-center hover:tw-text-button-primary-hover"
data-cy="forgot-password-link"
>
{forgotPasswordText}
</Link>
)}
</div>
<Input
type="password"
placeholder={passwordPlaceholder}
value={passwordValue}
onChange={onPasswordChange}
disabled={disabled}
showEncryption={false}
required
validation={passwordValidation}
isValidatedMessages={passwordValidationMessage}
size="large"
/>
</div>
<Button
size="large"
type="submit"
className="tw-w-fit"
disabled={disabled || isLoading}
isLoading={isLoading}
>
{signinButtonText}
<CornerDownLeft width="16" height="16" />
</Button>
{showOrSeparator && (
<div className="tw-relative tw-flex tw-items-center tw-text-center tw-text-sm">
<div className="tw-flex-1 tw-h-px tw-bg-border-weak" />
<span className="tw-px-2 tw-text-muted-foreground">{orText}</span>
<div className="tw-flex-1 tw-h-px tw-bg-border-weak" />
</div>
)}
</div>
</form>
</FormWrapper>
);
}
LoginForm.propTypes = {
className: PropTypes.string,
// Header and sign up section
signinHeader: PropTypes.string,
signUpText: PropTypes.string,
signUpUrl: PropTypes.string,
signUpCTA: PropTypes.string,
showSignup: PropTypes.bool,
organizationName: PropTypes.string,
// Form fields
emailLabel: PropTypes.string,
emailPlaceholder: PropTypes.string,
passwordLabel: PropTypes.string,
// Forgot password
showForgotPassword: PropTypes.bool,
forgotPasswordUrl: PropTypes.string,
forgotPasswordText: PropTypes.string,
// Button and separator
signinButtonText: PropTypes.string,
orText: PropTypes.string,
showOrSeparator: PropTypes.bool,
// Form functionality
onSubmit: PropTypes.func,
emailValue: PropTypes.string,
passwordValue: PropTypes.string,
onEmailChange: PropTypes.func,
onPasswordChange: PropTypes.func,
// Validation and state
emailValidation: PropTypes.func,
passwordValidation: PropTypes.func,
emailValidationMessage: PropTypes.object,
passwordValidationMessage: PropTypes.object,
isLoading: PropTypes.bool,
disabled: PropTypes.bool,
};
LoginForm.defaultProps = {
className: '',
// Header and sign up section
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
showSignup: true,
organizationName: '',
// Form fields
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
// Forgot password
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
// Button and separator
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
// Form functionality
onSubmit: undefined,
emailValue: undefined,
passwordValue: undefined,
onEmailChange: undefined,
onPasswordChange: undefined,
// Validation and state
emailValidation: undefined,
passwordValidation: undefined,
emailValidationMessage: undefined,
passwordValidationMessage: undefined,
isLoading: false,
disabled: false,
};

View file

@ -1,215 +0,0 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { CornerDownLeft } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { FormWrapper } from '@/components/Auth/FormWrapper';
export function SetupAdminForm({ className, ...props }) {
const {
// Header
headerText,
// Form fields
nameLabel,
namePlaceholder,
emailLabel,
emailPlaceholder,
passwordLabel,
passwordPlaceholder,
// Button
buttonText,
// Terms and privacy
termsText,
showTerms,
// Form functionality
onSubmit,
nameValue,
emailValue,
passwordValue,
onNameChange,
onEmailChange,
onPasswordChange,
// Validation and state
nameValidation,
emailValidation,
passwordValidation,
nameValidationMessage,
emailValidationMessage,
passwordValidationMessage,
isLoading,
disabled,
} = props;
return (
<FormWrapper>
<form className={cn('tw-flex tw-flex-col tw-gap-6', className)} onSubmit={onSubmit} {...props}>
<div className="tw-flex tw-flex-col tw-gap-0.5 tw-min-w-96">
<h1 className="tw-text-4xl tw-tracking-tight tw-font-medium tw-mb-0" data-cy="setup-admin-header">
{headerText}
</h1>
</div>
<div className="tw-grid tw-gap-4">
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="name" size="large">
{nameLabel}
</Label>
<Input
type="text"
placeholder={namePlaceholder}
value={nameValue}
onChange={onNameChange}
disabled={disabled}
required
validation={nameValidation}
isValidatedMessages={nameValidationMessage}
size="large"
/>
</div>
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="email" size="large">
{emailLabel}
</Label>
<Input
type="email"
placeholder={emailPlaceholder}
value={emailValue}
onChange={onEmailChange}
disabled={disabled}
required
validation={emailValidation}
isValidatedMessages={emailValidationMessage}
size="large"
/>
</div>
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="password" size="large">
{passwordLabel}
</Label>
<Input
type="password"
placeholder={passwordPlaceholder}
value={passwordValue}
onChange={onPasswordChange}
disabled={disabled}
showEncryption={false}
required
validation={passwordValidation}
isValidatedMessages={passwordValidationMessage}
size="large"
/>
</div>
<Button
size="large"
type="submit"
className="tw-w-fit"
disabled={disabled || isLoading}
isLoading={isLoading}
>
{buttonText}
<CornerDownLeft width="16" height="16" />
</Button>
{showTerms && (
<p className="tw-text-xs tw-text-text-placeholder tw-mb-0" data-cy="terms-and-privacy">
{termsText}
</p>
)}
</div>
</form>
</FormWrapper>
);
}
SetupAdminForm.propTypes = {
className: PropTypes.string,
// Header
headerText: PropTypes.string,
// Form fields
nameLabel: PropTypes.string,
namePlaceholder: PropTypes.string,
emailLabel: PropTypes.string,
emailPlaceholder: PropTypes.string,
passwordLabel: PropTypes.string,
passwordPlaceholder: PropTypes.string,
// Button
buttonText: PropTypes.string,
// Terms and privacy
termsText: PropTypes.string,
showTerms: PropTypes.bool,
// Form functionality
onSubmit: PropTypes.func,
nameValue: PropTypes.string,
emailValue: PropTypes.string,
passwordValue: PropTypes.string,
onNameChange: PropTypes.func,
onEmailChange: PropTypes.func,
onPasswordChange: PropTypes.func,
// Validation and state
nameValidation: PropTypes.func,
emailValidation: PropTypes.func,
passwordValidation: PropTypes.func,
nameValidationMessage: PropTypes.object,
emailValidationMessage: PropTypes.object,
passwordValidationMessage: PropTypes.object,
isLoading: PropTypes.bool,
disabled: PropTypes.bool,
};
SetupAdminForm.defaultProps = {
className: '',
// Header
headerText: 'Set up your admin account',
// Form fields
nameLabel: 'Name',
namePlaceholder: 'Enter your name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
// Button
buttonText: 'Sign up',
// Terms and privacy
termsText: 'By signing up, you agree to our Terms of Service and Privacy Policy',
showTerms: true,
// Form functionality
onSubmit: undefined,
nameValue: undefined,
emailValue: undefined,
passwordValue: undefined,
onNameChange: undefined,
onEmailChange: undefined,
onPasswordChange: undefined,
// Validation and state
nameValidation: undefined,
emailValidation: undefined,
passwordValidation: undefined,
nameValidationMessage: undefined,
emailValidationMessage: undefined,
passwordValidationMessage: undefined,
isLoading: false,
disabled: false,
};

View file

@ -1,166 +0,0 @@
import * as React from "react";
import PropTypes from "prop-types";
import { CornerDownLeft } from "lucide-react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { FormWrapper } from "@/components/Auth/FormWrapper";
export function InviteSignupForm({ className, ...props }) {
const {
// Header section
headerText,
descriptionText,
// Form fields
emailLabel,
emailPlaceholder,
emailValue,
emailDisabled,
passwordLabel,
passwordPlaceholder,
passwordValue,
onPasswordChange,
passwordValidation,
passwordValidationMessage,
// Button
buttonText,
// Form functionality
onSubmit,
// Validation and state
isLoading,
disabled,
} = props;
return (
<FormWrapper>
<form
className={cn("tw-flex tw-flex-col tw-gap-6", className)}
onSubmit={onSubmit}
{...props}
>
<div className="tw-flex tw-flex-col tw-gap-2">
<h1 className="tw-text-2xl tw-font-semibold tw-text-text-default">
{headerText}
</h1>
{descriptionText && (
<p className="tw-text-sm tw-text-text-muted">{descriptionText}</p>
)}
</div>
<div className="tw-grid tw-gap-4">
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="email" size="large">
{emailLabel}
</Label>
<Input
type="email"
placeholder={emailPlaceholder}
value={emailValue}
disabled={emailDisabled || disabled}
required
size="large"
/>
</div>
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="password" size="large">
{passwordLabel}
</Label>
<Input
type="password"
placeholder={passwordPlaceholder}
value={passwordValue}
onChange={onPasswordChange}
disabled={disabled}
showEncryption={false}
required
validation={passwordValidation}
isValidatedMessages={passwordValidationMessage}
size="large"
/>
</div>
<Button
size="large"
type="submit"
className="tw-w-fit"
disabled={disabled || isLoading}
isLoading={isLoading}
>
{buttonText}
<CornerDownLeft width="16" height="16" />
</Button>
</div>
</form>
</FormWrapper>
);
}
InviteSignupForm.propTypes = {
className: PropTypes.string,
// Header section
headerText: PropTypes.string,
descriptionText: PropTypes.string,
// Form fields
emailLabel: PropTypes.string,
emailPlaceholder: PropTypes.string,
emailValue: PropTypes.string,
emailDisabled: PropTypes.bool,
passwordLabel: PropTypes.string,
passwordPlaceholder: PropTypes.string,
passwordValue: PropTypes.string,
onPasswordChange: PropTypes.func,
passwordValidation: PropTypes.func,
passwordValidationMessage: PropTypes.object,
// Button
buttonText: PropTypes.string,
// Form functionality
onSubmit: PropTypes.func,
// Validation and state
isLoading: PropTypes.bool,
disabled: PropTypes.bool,
};
InviteSignupForm.defaultProps = {
className: "",
// Header section
headerText: "Sign in",
descriptionText: "",
// Form fields
emailLabel: "Email",
emailPlaceholder: "Enter your email",
emailValue: "",
emailDisabled: true,
passwordLabel: "Password",
passwordPlaceholder: "Enter password",
passwordValue: "",
onPasswordChange: undefined,
passwordValidation: undefined,
passwordValidationMessage: undefined,
// Button
buttonText: "Sign in",
// Form functionality
onSubmit: undefined,
// Validation and state
isLoading: false,
disabled: false,
};

View file

@ -1,291 +0,0 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { CornerDownLeft } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { FormWrapper } from '@/components/Auth/FormWrapper';
import { GoogleSigninButton } from '@/components/Auth/GoogleSigninButton';
import { GitHubSigninButton } from '@/components/Auth/GitHubSigninButton';
export function SignupFormWithSSO({ className, ...props }) {
const {
// Header and sign in section
signupHeader,
signinText,
signinUrl,
signinCTA,
showSignin,
organizationName,
// Form fields
nameLabel,
namePlaceholder,
nameValue,
onNameChange,
nameValidation,
nameValidationMessage,
emailLabel,
emailPlaceholder,
emailValue,
onEmailChange,
emailValidation,
emailValidationMessage,
passwordLabel,
passwordPlaceholder,
passwordValue,
onPasswordChange,
passwordValidation,
passwordValidationMessage,
// Button and separator
signupButtonText,
orText,
showOrSeparator,
// SSO buttons
showSSOButtons,
googleButtonText,
githubButtonText,
onGoogleSignup,
onGitHubSignup,
// Form functionality
onSubmit,
// Validation and state
isLoading,
disabled,
} = props;
return (
<FormWrapper>
<form className={cn('tw-flex tw-flex-col tw-gap-6', className)} onSubmit={onSubmit} {...props}>
<div className="tw-flex tw-flex-col tw-gap-2 tw-min-w-20">
<h1 className="tw-text-4xl tw-tracking-tight tw-font-medium tw-mb-0" data-cy="">
{signupHeader}
</h1>
{(organizationName || showSignin) && (
<p className="tw-text-balance tw-text-sm tw-text-text-placeholder tw-mb-0">
{organizationName && (
<>
Join the workspace -{' '}
<span className="tw-font-medium" data-cy="workspace-name">
{organizationName}
</span>
.
</>
)}{' '}
{showSignin && (
<>
<span>{signinText}</span>
<span>
<a
href={signinUrl}
className="tw-text-text-brand tw-text-[11px] tw-font-medium tw-no-underline tw-pl-1.5 tw-pb-0.5 tw-self-center hover:tw-text-button-primary-hover"
tabIndex="-1"
data-cy="sign-in-link"
>
{signinCTA}
</a>
</span>
</>
)}
</p>
)}
</div>
<div className="tw-grid tw-gap-4">
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="name" size="large">
{nameLabel}
</Label>
<Input
type="text"
placeholder={namePlaceholder}
value={nameValue}
onChange={onNameChange}
disabled={disabled}
required
validation={nameValidation}
isValidatedMessages={nameValidationMessage}
size="large"
/>
</div>
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="email" size="large">
{emailLabel}
</Label>
<Input
type="email"
placeholder={emailPlaceholder}
value={emailValue}
onChange={onEmailChange}
disabled={disabled}
required
validation={emailValidation}
isValidatedMessages={emailValidationMessage}
size="large"
/>
</div>
<div className="tw-grid tw-gap-0.5">
<Label htmlFor="password" size="large">
{passwordLabel}
</Label>
<Input
type="password"
placeholder={passwordPlaceholder}
value={passwordValue}
onChange={onPasswordChange}
disabled={disabled}
showEncryption={false}
required
validation={passwordValidation}
isValidatedMessages={passwordValidationMessage}
size="large"
/>
</div>
<Button
size="large"
type="submit"
className="tw-w-fit"
disabled={disabled || isLoading}
isLoading={isLoading}
>
{signupButtonText}
<CornerDownLeft width="16" height="16" />
</Button>
{showOrSeparator && (
<div className="tw-relative tw-flex tw-items-center tw-text-center tw-text-sm">
<div className="tw-flex-1 tw-h-px tw-bg-border-weak" />
<span className="tw-px-2 tw-text-muted-foreground">{orText}</span>
<div className="tw-flex-1 tw-h-px tw-bg-border-weak" />
</div>
)}
{showSSOButtons && (
<div className="tw-flex tw-flex-col tw-gap-3">
<GoogleSigninButton onClick={onGoogleSignup} text={googleButtonText} dataCy="google-signup-button" />
<GitHubSigninButton onClick={onGitHubSignup} text={githubButtonText} dataCy="github-signup-button" />
</div>
)}
</div>
</form>
</FormWrapper>
);
}
SignupFormWithSSO.propTypes = {
className: PropTypes.string,
// Header and sign in section
signupHeader: PropTypes.string,
signinText: PropTypes.string,
signinUrl: PropTypes.string,
signinCTA: PropTypes.string,
showSignin: PropTypes.bool,
organizationName: PropTypes.string,
// Form fields
nameLabel: PropTypes.string,
namePlaceholder: PropTypes.string,
nameValue: PropTypes.string,
onNameChange: PropTypes.func,
nameValidation: PropTypes.func,
nameValidationMessage: PropTypes.object,
emailLabel: PropTypes.string,
emailPlaceholder: PropTypes.string,
emailValue: PropTypes.string,
onEmailChange: PropTypes.func,
emailValidation: PropTypes.func,
emailValidationMessage: PropTypes.object,
passwordLabel: PropTypes.string,
passwordPlaceholder: PropTypes.string,
passwordValue: PropTypes.string,
onPasswordChange: PropTypes.func,
passwordValidation: PropTypes.func,
passwordValidationMessage: PropTypes.object,
// Button and separator
signupButtonText: PropTypes.string,
orText: PropTypes.string,
showOrSeparator: PropTypes.bool,
// SSO buttons
showSSOButtons: PropTypes.bool,
googleButtonText: PropTypes.string,
githubButtonText: PropTypes.string,
onGoogleSignup: PropTypes.func,
onGitHubSignup: PropTypes.func,
// Form functionality
onSubmit: PropTypes.func,
// Validation and state
isLoading: PropTypes.bool,
disabled: PropTypes.bool,
};
SignupFormWithSSO.defaultProps = {
className: '',
// Header and sign in section
signupHeader: 'Sign up',
signinText: 'Already have an account?',
signinUrl: '/login',
signinCTA: 'Sign in',
showSignin: true,
organizationName: '',
// Form fields
nameLabel: 'Name',
namePlaceholder: 'Enter your full name',
nameValue: '',
onNameChange: undefined,
nameValidation: undefined,
nameValidationMessage: undefined,
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
emailValue: '',
onEmailChange: undefined,
emailValidation: undefined,
emailValidationMessage: undefined,
passwordLabel: 'Password',
passwordPlaceholder: 'Create password',
passwordValue: '',
onPasswordChange: undefined,
passwordValidation: undefined,
passwordValidationMessage: undefined,
// Button and separator
signupButtonText: 'Sign up',
orText: 'OR',
showOrSeparator: true,
// SSO buttons
showSSOButtons: true,
googleButtonText: 'Sign up with',
githubButtonText: 'Sign up with',
onGoogleSignup: undefined,
onGitHubSignup: undefined,
// Form functionality
onSubmit: undefined,
// Validation and state
isLoading: false,
disabled: false,
};

View file

@ -1,165 +0,0 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { ArrowLeft, Mail } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { FormWrapper } from '@/components/Auth/FormWrapper';
export function SignupSuccessInfo({ className, ...props }) {
const {
// Header
headerText,
// Message content
messageText,
email,
name,
// Info text
infoText,
showInfo,
// Resend email
resendButtonText,
resendCountdownText,
showResendButton,
resendDisabled,
resendCountdown,
// Back button
backButtonText,
onBackToSignup,
// Separator
showSeparator,
} = props;
return (
<FormWrapper>
<div className={cn('tw-flex tw-flex-col tw-gap-6 tw-min-w-96', className)} {...props}>
<div className="tw-flex tw-flex-col tw-gap-0.5">
<h1 className="tw-text-4xl tw-tracking-tight tw-font-medium tw-mb-0" data-cy="signup-success-header">
{headerText}
</h1>
</div>
<div className="tw-flex tw-flex-col tw-gap-4">
<p className="tw-text-balance tw-text-sm tw-text-text-placeholder tw-mb-0" data-cy="signup-success-message">
{messageText}
{email && (
<>
{' '}
<span className="tw-font-medium tw-text-text-brand">{email}</span>
</>
)}
.{' '}
{name && (
<>
Welcome, <span className="tw-font-medium tw-text-text-brand">{name}</span>!
</>
)}
</p>
{showInfo && (
<p className="tw-text-sm tw-text-text-placeholder tw-mb-0" data-cy="signup-success-info">
{infoText}
</p>
)}
{showSeparator && (
<div className="tw-relative tw-flex tw-items-center tw-text-center tw-text-sm">
<div className="tw-flex-1 tw-h-px tw-bg-border-weak" />
<span className="tw-px-2 tw-text-text-placeholder tw-text-lg tw-font-medium">OR</span>
<div className="tw-flex-1 tw-h-px tw-bg-border-weak" />
</div>
)}
{showResendButton && (
<Button
size="default"
variant="outline"
className="tw-w-fit"
disabled={resendDisabled}
data-cy="resend-verification-email-button"
>
<Mail width="16" height="16" />
{resendDisabled && resendCountdown > 0 ? `${resendCountdownText} ${resendCountdown}s` : resendButtonText}
</Button>
)}
<Button
size="default"
variant="outline"
className="tw-w-fit"
onClick={onBackToSignup}
data-cy="back-to-signup-button"
>
<ArrowLeft width="16" height="16" />
{backButtonText}
</Button>
</div>
</div>
</FormWrapper>
);
}
SignupSuccessInfo.propTypes = {
className: PropTypes.string,
// Header
headerText: PropTypes.string,
// Message content
messageText: PropTypes.string,
email: PropTypes.string,
name: PropTypes.string,
// Info text
infoText: PropTypes.string,
showInfo: PropTypes.bool,
// Resend email
resendButtonText: PropTypes.string,
resendCountdownText: PropTypes.string,
showResendButton: PropTypes.bool,
resendDisabled: PropTypes.bool,
resendCountdown: PropTypes.number,
// Back button
backButtonText: PropTypes.string,
onBackToSignup: PropTypes.func,
// Separator
showSeparator: PropTypes.bool,
};
SignupSuccessInfo.defaultProps = {
className: '',
// Header
headerText: 'Check your mail',
// Message content
messageText: "We've sent a verification email to",
email: '',
name: '',
// Info text
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
// Resend email
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: true,
resendDisabled: false,
resendCountdown: 0,
// Back button
backButtonText: 'Back to sign up',
onBackToSignup: undefined,
// Separator
showSeparator: true,
};

View file

@ -1,85 +0,0 @@
import React from 'react';
import { AuthCenteredLayout } from '../AuthCenteredLayout';
import { LoginForm } from '../LoginForm';
import { SignupSuccessInfo } from '../SignupSuccessInfo';
import { ForgotPasswordInfoScreen } from '../ForgotPasswordInfoScreen';
export default {
title: 'Auth/Blocks/AuthCenteredLayout',
component: AuthCenteredLayout,
parameters: {
layout: 'fullscreen',
viewport: {
viewports: {
desktop: {
name: 'Desktop',
styles: {
width: '1440px',
height: '900px',
},
},
tablet: {
name: 'Tablet',
styles: {
width: '768px',
height: '1024px',
},
},
mobile: {
name: 'Mobile',
styles: {
width: '375px',
height: '667px',
},
},
},
},
},
tags: ['autodocs'],
argTypes: {
children: {
control: false,
description: 'Content to be displayed within the centered auth layout',
},
},
};
// Signup Success Examples
export const WithSignupSuccess = {
args: {
children: (
<SignupSuccessInfo
headerText="Check your mail"
messageText="We've sent a verification email to"
email="john.doe@example.com"
name="John"
infoText="Did not receive an email? Check your spam folder!"
showInfo={true}
resendButtonText="Resend verification email"
resendCountdownText="Resend verification email in"
showResendButton={true}
resendDisabled={false}
resendCountdown={0}
backButtonText="Back to sign up"
showSeparator={true}
/>
),
},
};
// Forgot Password Examples
export const WithForgotPasswordInfo = {
args: {
children: (
<ForgotPasswordInfoScreen
headerText="Check your mail"
messageText="We've sent a password reset link to"
email="user@example.com"
infoText="Did not receive an email? Check your spam folder!"
showInfo={true}
buttonText="Back to login"
showSeparator={true}
/>
),
},
};

View file

@ -1,160 +0,0 @@
import React from 'react';
import { AuthLayout } from '../AuthLayout';
import { LoginForm } from '../LoginForm';
import { SetupAdminForm } from '../SetupAdminForm';
export default {
title: 'Auth/Blocks/AuthLayout',
component: AuthLayout,
parameters: {
layout: 'fullscreen',
viewport: {
viewports: {
desktop: {
name: 'Desktop',
styles: {
width: '1440px',
height: '900px',
},
},
tablet: {
name: 'Tablet',
styles: {
width: '768px',
height: '1024px',
},
},
mobile: {
name: 'Mobile',
styles: {
width: '375px',
height: '667px',
},
},
},
},
},
tags: ['autodocs'],
argTypes: {
children: {
control: false,
description: 'Content to be displayed within the auth layout',
},
},
};
export const WithLoginFormOrganization = {
args: {
children: (
<LoginForm
signinHeader="Sign in"
signUpText="New to ToolJet?"
signUpUrl="#"
signUpCTA="Create an account"
showSignup={true}
organizationName="Acme Corporation"
emailLabel="Email"
emailPlaceholder="Enter your work email"
passwordLabel="Password"
passwordPlaceholder="Enter password"
showForgotPassword={true}
forgotPasswordUrl="/forgot-password"
forgotPasswordText="Forgot?"
signinButtonText="Sign in"
orText="OR"
showOrSeparator={true}
/>
),
},
};
// Responsive Examples
export const DesktopView = {
parameters: {
viewport: {
defaultViewport: 'desktop',
},
},
args: {
children: (
<LoginForm
signinHeader="Sign in"
signUpText="New to ToolJet?"
signUpUrl="#"
signUpCTA="Create an account"
showSignup={true}
organizationName="Acme Corporation"
emailLabel="Email"
emailPlaceholder="Enter your work email"
passwordLabel="Password"
passwordPlaceholder="Enter password"
showForgotPassword={true}
forgotPasswordUrl="/forgot-password"
forgotPasswordText="Forgot?"
signinButtonText="Sign in"
orText="OR"
showOrSeparator={true}
/>
),
},
};
export const TabletView = {
parameters: {
viewport: {
defaultViewport: 'tablet',
},
},
args: {
children: (
<LoginForm
signinHeader="Sign in"
signUpText="New to ToolJet?"
signUpUrl="#"
signUpCTA="Create an account"
showSignup={true}
organizationName="Acme Corporation"
emailLabel="Email"
emailPlaceholder="Enter your work email"
passwordLabel="Password"
passwordPlaceholder="Enter password"
showForgotPassword={true}
forgotPasswordUrl="/forgot-password"
forgotPasswordText="Forgot?"
signinButtonText="Sign in"
orText="OR"
showOrSeparator={true}
/>
),
},
};
export const MobileView = {
parameters: {
viewport: {
defaultViewport: 'mobile',
},
},
args: {
children: (
<LoginForm
signinHeader="Sign in"
signUpText="New to ToolJet?"
signUpUrl="#"
signUpCTA="Create an account"
showSignup={true}
organizationName="Acme Corporation"
emailLabel="Email"
emailPlaceholder="Enter your work email"
passwordLabel="Password"
passwordPlaceholder="Enter password"
showForgotPassword={true}
forgotPasswordUrl="/forgot-password"
forgotPasswordText="Forgot?"
signinButtonText="Sign in"
orText="OR"
showOrSeparator={true}
/>
),
},
};

View file

@ -1,92 +0,0 @@
import React from 'react';
import { AuthLayout } from '../AuthLayout';
import { AuthCenteredLayout } from '../AuthCenteredLayout';
import { ForgotPasswordForm } from '../ForgotPasswordForm';
import { ForgotPasswordInfoScreen } from '../ForgotPasswordInfoScreen';
export default {
title: 'Auth/Flows/ForgotPassword',
component: AuthLayout,
parameters: {
layout: 'fullscreen',
viewport: {
viewports: {
desktop: {
name: 'Desktop',
styles: {
width: '1440px',
height: '900px',
},
},
tablet: {
name: 'Tablet',
styles: {
width: '768px',
height: '1024px',
},
},
mobile: {
name: 'Mobile',
styles: {
width: '375px',
height: '667px',
},
},
},
},
},
tags: ['autodocs'],
argTypes: {
children: {
control: false,
description: 'Content to be displayed within the auth layout',
},
},
};
// Forgot Password Flow - Form
export const ForgotPasswordFlow = {
parameters: {
viewport: {
defaultViewport: 'desktop',
},
},
args: {
children: (
<ForgotPasswordForm
headerText="Forgot Password"
signupText="New to ToolJet?"
signupUrl="#"
signupCTA="Create an account"
showSignup={true}
emailLabel="Email address"
emailPlaceholder="Enter email address"
buttonText="Send a reset link"
adminContactText="Contact admin to reset your password"
showAdminBanner={true}
/>
),
},
};
// Forgot Password Flow - Info Screen
export const ForgotPasswordInfoFlow = {
render: (args) => (
<AuthCenteredLayout {...args}>
<ForgotPasswordInfoScreen
headerText="Check your mail"
messageText="We've sent a password reset link to"
email="user@example.com"
infoText="Did not receive an email? Check your spam folder!"
showInfo={true}
buttonText="Back to login"
showSeparator={true}
/>
</AuthCenteredLayout>
),
parameters: {
viewport: {
defaultViewport: 'desktop',
},
},
};

View file

@ -1,188 +0,0 @@
import React from 'react';
import { ForgotPasswordForm } from '../ForgotPasswordForm';
export default {
title: 'Auth/Blocks/ForgotPasswordForm',
component: ForgotPasswordForm,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
headerText: {
control: 'text',
description: 'The main heading text for the forgot password form',
},
signupText: {
control: 'text',
description: 'Text before the sign up link',
},
signupUrl: {
control: 'text',
description: 'URL for the sign up link',
},
signupCTA: {
control: 'text',
description: 'Call-to-action text for the sign up link',
},
showSignup: {
control: 'boolean',
description: 'Show or hide the signup section',
},
emailLabel: {
control: 'text',
description: 'Label for the email input field',
},
emailPlaceholder: {
control: 'text',
description: 'Placeholder text for the email input',
},
buttonText: {
control: 'text',
description: 'Text for the submit button',
},
adminContactText: {
control: 'text',
description: 'Text for the admin contact banner',
},
showAdminBanner: {
control: 'boolean',
description: 'Show or hide the admin contact banner',
},
emailValue: {
control: 'text',
description: 'Controlled value for email input',
},
isLoading: {
control: 'boolean',
description: 'Loading state for the form',
},
disabled: {
control: 'boolean',
description: 'Disabled state for the form',
},
onSubmit: {
action: 'submitted',
description: 'Form submission handler',
},
onEmailChange: {
action: 'email changed',
description: 'Email input change handler',
},
emailValidation: {
control: false,
description: 'Email validation function',
},
emailValidationMessage: {
control: 'object',
description: 'External email validation message object',
},
},
};
export const Default = {
args: {
headerText: 'Forgot Password',
signupText: 'New to ToolJet?',
signupUrl: '#',
signupCTA: 'Create an account',
showSignup: true,
emailLabel: 'Email address',
emailPlaceholder: 'Enter email address',
buttonText: 'Send a reset link',
adminContactText: 'Contact admin to reset your password',
showAdminBanner: true,
},
};
export const NoSignup = {
args: {
headerText: 'Forgot Password',
signupText: '',
signupUrl: '#',
signupCTA: '',
showSignup: false,
emailLabel: 'Email address',
emailPlaceholder: 'Enter email address',
buttonText: 'Send a reset link',
adminContactText: 'Contact admin to reset your password',
showAdminBanner: true,
},
};
export const NoAdminBanner = {
args: {
headerText: 'Forgot Password',
signupText: 'New to ToolJet?',
signupUrl: '#',
signupCTA: 'Create an account',
showSignup: true,
emailLabel: 'Email address',
emailPlaceholder: 'Enter email address',
buttonText: 'Send a reset link',
adminContactText: 'Contact admin to reset your password',
showAdminBanner: false,
},
};
export const Loading = {
args: {
headerText: 'Forgot Password',
signupText: 'New to ToolJet?',
signupUrl: '#',
signupCTA: 'Create an account',
showSignup: true,
emailLabel: 'Email address',
emailPlaceholder: 'Enter email address',
buttonText: 'Sending...',
adminContactText: 'Contact admin to reset your password',
showAdminBanner: true,
emailValue: 'user@example.com',
isLoading: true,
disabled: true,
},
};
export const Disabled = {
args: {
headerText: 'Forgot Password',
signupText: 'New to ToolJet?',
signupUrl: '#',
signupCTA: 'Create an account',
showSignup: true,
emailLabel: 'Email address',
emailPlaceholder: 'Enter email address',
buttonText: 'Send a reset link',
adminContactText: 'Contact admin to reset your password',
showAdminBanner: true,
disabled: true,
},
};
export const WithValidation = {
args: {
headerText: 'Forgot Password',
signupText: 'New to ToolJet?',
signupUrl: '#',
signupCTA: 'Create an account',
showSignup: true,
emailLabel: 'Email address',
emailPlaceholder: 'Enter email address',
buttonText: 'Send a reset link',
adminContactText: 'Contact admin to reset your password',
showAdminBanner: true,
emailValidation: (e) => {
const value = e.target.value;
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!value) {
return { valid: false, message: 'Email is required' };
}
if (!emailRegex.test(value)) {
return { valid: false, message: 'Please enter a valid email address' };
}
return { valid: true, message: 'Email looks good!' };
},
},
};

View file

@ -1,167 +0,0 @@
import React from 'react';
import { ForgotPasswordInfoScreen } from '../ForgotPasswordInfoScreen';
export default {
title: 'Auth/Blocks/ForgotPasswordInfoScreen',
component: ForgotPasswordInfoScreen,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
headerText: {
control: 'text',
description: 'The main heading text for the info screen',
},
messageText: {
control: 'text',
description: 'Main message text',
},
email: {
control: 'text',
description: 'Email address to display in the message',
},
infoText: {
control: 'text',
description: 'Additional info text',
},
showInfo: {
control: 'boolean',
description: 'Show or hide the info text',
},
buttonText: {
control: 'text',
description: 'Text for the back to login button',
},
onBackToLogin: {
action: 'back to login clicked',
description: 'Back to login button handler',
},
showSeparator: {
control: 'boolean',
description: 'Show or hide the separator',
},
},
};
export const Default = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a password reset link to",
email: 'user@example.com',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
buttonText: 'Back to login',
showSeparator: true,
},
};
export const CustomHeader = {
args: {
headerText: 'Password Reset Sent',
messageText: "We've sent a password reset link to",
email: 'user@example.com',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
buttonText: 'Back to login',
showSeparator: true,
},
};
export const LongEmail = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a password reset link to",
email: 'very.long.email.address@verylongdomainname.com',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
buttonText: 'Back to login',
showSeparator: true,
},
};
export const NoEmail = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a password reset link to your registered email address",
email: '',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
buttonText: 'Back to login',
showSeparator: true,
},
};
export const NoInfo = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a password reset link to",
email: 'user@example.com',
infoText: '',
showInfo: false,
buttonText: 'Back to login',
showSeparator: true,
},
};
export const NoSeparator = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a password reset link to",
email: 'user@example.com',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
buttonText: 'Back to login',
showSeparator: false,
},
};
export const CustomMessage = {
args: {
headerText: 'Check your mail',
messageText: 'A password reset link has been sent to your email address',
email: 'user@example.com',
infoText: 'Please check your inbox and follow the instructions to reset your password',
showInfo: true,
buttonText: 'Return to login',
showSeparator: true,
},
};
export const Minimal = {
args: {
headerText: 'Email Sent',
messageText: 'Check your email for reset instructions',
email: '',
infoText: '',
showInfo: false,
buttonText: 'Back',
showSeparator: false,
},
};
export const CustomButtonText = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a password reset link to",
email: 'user@example.com',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
buttonText: 'Return to sign in',
showSeparator: true,
},
};
export const LongMessage = {
args: {
headerText: 'Check your mail',
messageText:
"We've sent a password reset link to your registered email address. Please check your inbox and click the link to reset your password",
email: 'user@example.com',
infoText:
'Did not receive an email? Please check your spam folder or contact support if you continue to have issues',
showInfo: true,
buttonText: 'Back to login',
showSeparator: true,
},
};

View file

@ -1,62 +0,0 @@
import React from 'react';
import { GitHubSigninButton } from '../GitHubSigninButton';
export default {
title: 'Auth/Blocks/GitHubSigninButton',
component: GitHubSigninButton,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
onClick: {
action: 'clicked',
description: 'Function called when the button is clicked',
},
text: {
control: 'text',
description: 'Text displayed on the button',
},
dataCy: {
control: 'text',
description: 'Data-cy attribute for testing',
},
},
};
// Template for creating stories
const Template = (args) => <GitHubSigninButton {...args} />;
// Default story
export const Default = Template.bind({});
Default.args = {
text: 'Continue with GitHub',
dataCy: 'github-signin-button',
};
// Custom text story
export const CustomText = Template.bind({});
CustomText.args = {
text: 'Sign in with GitHub',
dataCy: 'github-signin-custom',
};
// Short text story
export const ShortText = Template.bind({});
ShortText.args = {
text: 'GitHub',
dataCy: 'github-signin-short',
};
// Long text story
export const LongText = Template.bind({});
LongText.args = {
text: 'Continue with your GitHub account',
dataCy: 'github-signin-long',
};
// Without data-cy story
export const WithoutDataCy = Template.bind({});
WithoutDataCy.args = {
text: 'Continue with GitHub',
};

View file

@ -1,62 +0,0 @@
import * as React from 'react';
import { GoogleSigninButton } from '../GoogleSigninButton';
export default {
title: 'Auth/Blocks/GoogleSigninButton',
component: GoogleSigninButton,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
onClick: {
action: 'clicked',
description: 'Function called when the button is clicked',
},
text: {
control: 'text',
description: 'Text displayed on the button',
},
dataCy: {
control: 'text',
description: 'Data-cy attribute for testing',
},
},
};
// Template for creating stories
const Template = (args) => <GoogleSigninButton {...args} />;
// Default story
export const Default = Template.bind({});
Default.args = {
text: 'Continue with Google',
dataCy: 'google-signin-button',
};
// Custom text story
export const CustomText = Template.bind({});
CustomText.args = {
text: 'Sign in with Google',
dataCy: 'google-signin-custom',
};
// Short text story
export const ShortText = Template.bind({});
ShortText.args = {
text: 'Google',
dataCy: 'google-signin-short',
};
// Long text story
export const LongText = Template.bind({});
LongText.args = {
text: 'Continue with your Google account',
dataCy: 'google-signin-long',
};
// Without data-cy story
export const WithoutDataCy = Template.bind({});
WithoutDataCy.args = {
text: 'Continue with Google',
};

View file

@ -1,94 +0,0 @@
import React from 'react';
import { AuthLayout } from '../AuthLayout';
import { LoginForm } from '../LoginForm';
import { GoogleSigninButton } from '../GoogleSigninButton';
import { GitHubSigninButton } from '../GitHubSigninButton';
export default {
title: 'Auth/Flows/Login',
component: AuthLayout,
parameters: {
layout: 'fullscreen',
viewport: {
viewports: {
desktop: {
name: 'Desktop',
styles: {
width: '1440px',
height: '900px',
},
},
tablet: {
name: 'Tablet',
styles: {
width: '768px',
height: '1024px',
},
},
mobile: {
name: 'Mobile',
styles: {
width: '375px',
height: '667px',
},
},
},
},
},
tags: ['autodocs'],
argTypes: {
children: {
control: false,
description: 'Content to be displayed within the auth layout',
},
},
};
// Login with Organization
export const LoginWithOrganization = {
args: {
children: (
<div className="tw-flex tw-flex-col tw-gap-6 tw-w-full">
<LoginForm
signinHeader="Sign in"
signUpText="New to ToolJet?"
signUpUrl="#"
signUpCTA="Create an account"
showSignup={true}
organizationName=""
emailLabel="Email"
emailPlaceholder="Enter your work email"
passwordLabel="Password"
passwordPlaceholder="Enter password"
showForgotPassword={true}
forgotPasswordUrl="/forgot-password"
forgotPasswordText="Forgot?"
signinButtonText="Sign in"
orText="OR"
showOrSeparator={true}
emailValue=""
passwordValue=""
onEmailChange={() => {}}
onPasswordChange={() => {}}
onSubmit={() => {}}
isLoading={false}
disabled={false}
/>
{/* SSO Buttons */}
<div className="tw-flex tw-flex-col tw-gap-3">
<GoogleSigninButton
onClick={() => console.log('Google sign in clicked')}
text="Continue with"
dataCy="google-signin-button"
/>
<GitHubSigninButton
onClick={() => console.log('GitHub sign in clicked')}
text="Continue with"
dataCy="github-signin-button"
/>
</div>
</div>
),
},
};

View file

@ -1,504 +0,0 @@
import { LoginForm } from '../LoginForm';
export default {
title: 'Auth/Blocks/LoginForm',
component: LoginForm,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
signinHeader: {
control: 'text',
description: 'The main heading text for the login form',
},
signUpText: {
control: 'text',
description: 'Text before the sign up link',
},
signUpUrl: {
control: 'text',
description: 'URL for the sign up link',
},
signUpCTA: {
control: 'text',
description: 'Call-to-action text for the sign up link',
},
showSignup: {
control: 'boolean',
description: 'Show or hide the signup section',
},
organizationName: {
control: 'text',
description: 'Organization name to display in the header',
},
emailLabel: {
control: 'text',
description: 'Label for the email input field',
},
emailPlaceholder: {
control: 'text',
description: 'Placeholder text for the email input',
},
passwordLabel: {
control: 'text',
description: 'Label for the password input field',
},
passwordPlaceholder: {
control: 'text',
description: 'Placeholder text for the password input',
},
showForgotPassword: {
control: 'boolean',
description: 'Show or hide the forgot password link',
},
forgotPasswordUrl: {
control: 'text',
description: 'URL for the forgot password link',
},
forgotPasswordText: {
control: 'text',
description: 'Text for the forgot password link',
},
signinButtonText: {
control: 'text',
description: 'Text for the submit button',
},
orText: {
control: 'text',
description: 'Text for the OR separator',
},
showOrSeparator: {
control: 'boolean',
description: 'Show or hide the OR separator',
},
emailValue: {
control: 'text',
description: 'Controlled value for email input',
},
passwordValue: {
control: 'text',
description: 'Controlled value for password input',
},
isLoading: {
control: 'boolean',
description: 'Loading state for the form',
},
disabled: {
control: 'boolean',
description: 'Disabled state for the form',
},
onSubmit: {
action: 'submitted',
description: 'Form submission handler',
},
onEmailChange: {
action: 'email changed',
description: 'Email input change handler',
},
onPasswordChange: {
action: 'password changed',
description: 'Password input change handler',
},
emailValidation: {
control: false,
description: 'Email validation function',
},
passwordValidation: {
control: false,
description: 'Password validation function',
},
emailValidationMessage: {
control: 'object',
description: 'External email validation message object',
},
passwordValidationMessage: {
control: 'object',
description: 'External password validation message object',
},
},
};
export const Default = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
showSignup: true,
organizationName: '',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
},
};
export const CustomHeader = {
args: {
signinHeader: 'Welcome Back',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
showSignup: true,
organizationName: '',
emailLabel: 'Email',
emailPlaceholder: 'm@example.com',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
},
};
export const WithOrganization = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
showSignup: true,
organizationName: 'Acme Corporation',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
},
};
export const OrganizationOnly = {
args: {
signinHeader: 'Sign in',
signUpText: '',
signUpUrl: '#',
signUpCTA: '',
showSignup: false,
organizationName: 'TechCorp Inc.',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
},
};
export const LongOrganizationName = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
showSignup: true,
organizationName: 'Very Long Organization Name That Might Wrap',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
},
};
export const OrganizationWithSpecialChars = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
showSignup: true,
organizationName: 'Acme & Co. (Ltd.)',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
},
};
export const EmptyOrganizationName = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
showSignup: true,
organizationName: '',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
},
};
export const NoOrganizationNoSignup = {
args: {
signinHeader: 'Sign in',
signUpText: '',
signUpUrl: '#',
signUpCTA: '',
showSignup: false,
organizationName: '',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
},
};
export const WithErrors = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
emailLabel: 'Email',
emailPlaceholder: 'm@example.com',
passwordLabel: 'Password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
emailValue: 'invalid-email',
passwordValue: '123',
emailValidationMessage: {
valid: false,
message: 'Please enter a valid email address',
},
passwordValidationMessage: {
valid: false,
message: 'Password must be at least 8 characters',
},
},
};
export const Loading = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
emailLabel: 'Email',
emailPlaceholder: 'm@example.com',
passwordLabel: 'Password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Signing in...',
orText: 'OR',
showOrSeparator: true,
emailValue: 'user@example.com',
passwordValue: 'password123',
isLoading: true,
disabled: true,
},
};
export const CustomSeparator = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
emailLabel: 'Email',
emailPlaceholder: 'm@example.com',
passwordLabel: 'Password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR CONTINUE WITH',
showOrSeparator: true,
},
};
export const NoSeparator = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
emailLabel: 'Email',
emailPlaceholder: 'm@example.com',
passwordLabel: 'Password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: false,
},
};
export const Minimal = {
args: {
signinHeader: 'Login',
signUpText: '',
signUpUrl: '#',
signUpCTA: '',
showSignup: false,
organizationName: '',
emailLabel: 'Email',
emailPlaceholder: 'Enter your email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
showForgotPassword: false,
signinButtonText: 'Login',
orText: 'OR',
showOrSeparator: false,
},
};
export const WithValidation = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
emailLabel: 'Email',
emailPlaceholder: 'Enter your email',
passwordLabel: 'Password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
emailValidation: (e) => {
const value = e.target.value;
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!value) {
return { valid: false, message: 'Email is required' };
}
if (!emailRegex.test(value)) {
return { valid: false, message: 'Please enter a valid email address' };
}
return { valid: true, message: 'Email looks good!' };
},
passwordValidation: (e) => {
const value = e.target.value;
if (!value) {
return { valid: false, message: 'Password is required' };
}
if (value.length < 8) {
return {
valid: false,
message: 'Password must be at least 8 characters',
};
}
if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(value)) {
return {
valid: false,
message: 'Password must contain uppercase, lowercase, and number',
};
}
return { valid: true, message: 'Password is strong!' };
},
},
};
export const WithExternalValidation = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
emailLabel: 'Email',
emailPlaceholder: 'Enter your email',
passwordLabel: 'Password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
emailValue: 'user@example.com',
passwordValue: 'password123',
emailValidationMessage: {
valid: true,
message: 'Email is valid and available',
},
passwordValidationMessage: {
valid: true,
message: 'Password meets all requirements',
},
},
};
export const WithValidationErrors = {
args: {
signinHeader: 'Sign in',
signUpText: 'New to ToolJet?',
signUpUrl: '#',
signUpCTA: 'Create an account',
emailLabel: 'Email',
emailPlaceholder: 'Enter your email',
passwordLabel: 'Password',
showForgotPassword: true,
forgotPasswordUrl: '/forgot-password',
forgotPasswordText: 'Forgot?',
signinButtonText: 'Sign in',
orText: 'OR',
showOrSeparator: true,
emailValue: 'invalid-email',
passwordValue: '123',
emailValidationMessage: {
valid: false,
message: 'Please enter a valid email address',
},
passwordValidationMessage: {
valid: false,
message: 'Password must be at least 8 characters',
},
},
};

View file

@ -1,99 +0,0 @@
import React from 'react';
import { AuthLayout } from '../AuthLayout';
import { LoginForm } from '../LoginForm';
import { GoogleSigninButton } from '../GoogleSigninButton';
import { GitHubSigninButton } from '../GitHubSigninButton';
export default {
title: 'Auth/Blocks/LoginPage',
component: AuthLayout,
parameters: {
layout: 'fullscreen',
viewport: {
viewports: {
desktop: {
name: 'Desktop',
styles: {
width: '1440px',
height: '900px',
},
},
tablet: {
name: 'Tablet',
styles: {
width: '768px',
height: '1024px',
},
},
mobile: {
name: 'Mobile',
styles: {
width: '375px',
height: '667px',
},
},
},
},
},
tags: ['autodocs'],
argTypes: {
children: {
control: false,
description: 'Content to be displayed within the auth layout',
},
},
};
// Login Page with Organization
export const LoginPageWithOrganization = {
parameters: {
viewport: {
defaultViewport: 'desktop',
},
},
args: {
children: (
<div className="tw-flex tw-flex-col tw-gap-6 tw-w-full">
<LoginForm
signinHeader="Sign in"
signUpText="New to ToolJet?"
signUpUrl="#"
signUpCTA="Create an account"
showSignup={true}
organizationName="Acme Corporation"
emailLabel="Email"
emailPlaceholder="Enter your work email"
passwordLabel="Password"
passwordPlaceholder="Enter password"
showForgotPassword={true}
forgotPasswordUrl="/forgot-password"
forgotPasswordText="Forgot?"
signinButtonText="Sign in"
orText="OR"
showOrSeparator={true}
emailValue=""
passwordValue=""
onEmailChange={() => {}}
onPasswordChange={() => {}}
onSubmit={() => {}}
isLoading={false}
disabled={false}
/>
{/* SSO Buttons */}
<div className="tw-flex tw-flex-col tw-gap-3">
<GoogleSigninButton
onClick={() => console.log('Google sign in clicked')}
text="Continue with"
dataCy="google-signin-button"
/>
<GitHubSigninButton
onClick={() => console.log('GitHub sign in clicked')}
text="Continue with"
dataCy="github-signin-button"
/>
</div>
</div>
),
},
};

View file

@ -1,328 +0,0 @@
import React from 'react';
import { SetupAdminForm } from '../SetupAdminForm';
export default {
title: 'Auth/Blocks/SetupAdminForm',
component: SetupAdminForm,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
headerText: {
control: 'text',
description: 'The main heading text for the setup admin form',
},
nameLabel: {
control: 'text',
description: 'Label for the name input field',
},
namePlaceholder: {
control: 'text',
description: 'Placeholder text for the name input',
},
emailLabel: {
control: 'text',
description: 'Label for the email input field',
},
emailPlaceholder: {
control: 'text',
description: 'Placeholder text for the email input',
},
passwordLabel: {
control: 'text',
description: 'Label for the password input field',
},
passwordPlaceholder: {
control: 'text',
description: 'Placeholder text for the password input',
},
buttonText: {
control: 'text',
description: 'Text for the submit button',
},
termsText: {
control: 'text',
description: 'Text for the terms and privacy notice',
},
showTerms: {
control: 'boolean',
description: 'Show or hide the terms and privacy notice',
},
nameValue: {
control: 'text',
description: 'Controlled value for name input',
},
emailValue: {
control: 'text',
description: 'Controlled value for email input',
},
passwordValue: {
control: 'text',
description: 'Controlled value for password input',
},
isLoading: {
control: 'boolean',
description: 'Loading state for the form',
},
disabled: {
control: 'boolean',
description: 'Disabled state for the form',
},
onSubmit: {
action: 'submitted',
description: 'Form submission handler',
},
onNameChange: {
action: 'name changed',
description: 'Name input change handler',
},
onEmailChange: {
action: 'email changed',
description: 'Email input change handler',
},
onPasswordChange: {
action: 'password changed',
description: 'Password input change handler',
},
nameValidation: {
control: false,
description: 'Name validation function',
},
emailValidation: {
control: false,
description: 'Email validation function',
},
passwordValidation: {
control: false,
description: 'Password validation function',
},
nameValidationMessage: {
control: 'object',
description: 'External name validation message object',
},
emailValidationMessage: {
control: 'object',
description: 'External email validation message object',
},
passwordValidationMessage: {
control: 'object',
description: 'External password validation message object',
},
},
};
export const Default = {
args: {
headerText: 'Set up your admin account',
nameLabel: 'Name',
namePlaceholder: 'Enter your name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
buttonText: 'Sign up',
termsText: 'By signing up, you agree to our Terms of Service and Privacy Policy',
showTerms: true,
},
};
export const CustomHeader = {
args: {
headerText: 'Create Admin Account',
nameLabel: 'Full Name',
namePlaceholder: 'Enter your full name',
emailLabel: 'Work Email',
emailPlaceholder: 'Enter your work email address',
passwordLabel: 'Password',
passwordPlaceholder: 'Create a secure password',
buttonText: 'Create Account',
termsText: 'By creating an account, you agree to our Terms of Service and Privacy Policy',
showTerms: true,
},
};
export const WithValues = {
args: {
headerText: 'Set up your admin account',
nameLabel: 'Name',
namePlaceholder: 'Enter your name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
buttonText: 'Sign up',
termsText: 'By signing up, you agree to our Terms of Service and Privacy Policy',
showTerms: true,
nameValue: 'John Doe',
emailValue: 'john.doe@company.com',
passwordValue: 'SecurePassword123!',
},
};
export const WithValidationErrors = {
args: {
headerText: 'Set up your admin account',
nameLabel: 'Name',
namePlaceholder: 'Enter your name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
buttonText: 'Sign up',
termsText: 'By signing up, you agree to our Terms of Service and Privacy Policy',
showTerms: true,
nameValue: '',
emailValue: 'invalid-email',
passwordValue: '123',
nameValidationMessage: {
valid: false,
message: 'Name is required',
},
emailValidationMessage: {
valid: false,
message: 'Please enter a valid email address',
},
passwordValidationMessage: {
valid: false,
message: 'Password must be at least 8 characters',
},
},
};
export const Loading = {
args: {
headerText: 'Set up your admin account',
nameLabel: 'Name',
namePlaceholder: 'Enter your name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
buttonText: 'Creating Account...',
termsText: 'By signing up, you agree to our Terms of Service and Privacy Policy',
showTerms: true,
nameValue: 'John Doe',
emailValue: 'john.doe@company.com',
passwordValue: 'SecurePassword123!',
isLoading: true,
disabled: true,
},
};
export const Disabled = {
args: {
headerText: 'Set up your admin account',
nameLabel: 'Name',
namePlaceholder: 'Enter your name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
buttonText: 'Sign up',
termsText: 'By signing up, you agree to our Terms of Service and Privacy Policy',
showTerms: true,
disabled: true,
},
};
export const NoTerms = {
args: {
headerText: 'Set up your admin account',
nameLabel: 'Name',
namePlaceholder: 'Enter your name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
buttonText: 'Sign up',
termsText: '',
showTerms: false,
},
};
export const WithValidation = {
args: {
headerText: 'Set up your admin account',
nameLabel: 'Name',
namePlaceholder: 'Enter your name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
buttonText: 'Sign up',
termsText: 'By signing up, you agree to our Terms of Service and Privacy Policy',
showTerms: true,
nameValidation: (e) => {
const value = e.target.value;
if (!value.trim()) {
return { valid: false, message: 'Name is required' };
}
if (value.length < 2) {
return { valid: false, message: 'Name must be at least 2 characters' };
}
return { valid: true, message: 'Name looks good!' };
},
emailValidation: (e) => {
const value = e.target.value;
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!value) {
return { valid: false, message: 'Email is required' };
}
if (!emailRegex.test(value)) {
return { valid: false, message: 'Please enter a valid email address' };
}
return { valid: true, message: 'Email looks good!' };
},
passwordValidation: (e) => {
const value = e.target.value;
if (!value) {
return { valid: false, message: 'Password is required' };
}
if (value.length < 8) {
return {
valid: false,
message: 'Password must be at least 8 characters',
};
}
if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(value)) {
return {
valid: false,
message: 'Password must contain uppercase, lowercase, and number',
};
}
return { valid: true, message: 'Password is strong!' };
},
},
};
export const Minimal = {
args: {
headerText: 'Admin Setup',
nameLabel: 'Name',
namePlaceholder: 'Enter name',
emailLabel: 'Email',
emailPlaceholder: 'Enter email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
buttonText: 'Setup',
termsText: '',
showTerms: false,
},
};
export const CustomTerms = {
args: {
headerText: 'Set up your admin account',
nameLabel: 'Name',
namePlaceholder: 'Enter your name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter password',
buttonText: 'Sign up',
termsText:
'By creating an admin account, you acknowledge that you have read and agree to our Terms of Service, Privacy Policy, and Data Processing Agreement.',
showTerms: true,
},
};

View file

@ -1,145 +0,0 @@
import React from 'react';
import { AuthLayout } from '../AuthLayout';
import { AuthCenteredLayout } from '../AuthCenteredLayout';
import { SignupFormWithSSO } from '../SignupFormWithSSO';
import { SignupSuccessInfo } from '../SignupSuccessInfo';
export default {
title: 'Auth/Flows/Signup',
component: AuthLayout,
parameters: {
layout: 'fullscreen',
viewport: {
viewports: {
desktop: {
name: 'Desktop',
styles: {
width: '1440px',
height: '900px',
},
},
tablet: {
name: 'Tablet',
styles: {
width: '768px',
height: '1024px',
},
},
mobile: {
name: 'Mobile',
styles: {
width: '375px',
height: '667px',
},
},
},
},
},
tags: ['autodocs'],
argTypes: {
children: {
control: false,
description: 'Content to be displayed within the auth layout',
},
},
};
// Signup Flow - Step 1: Signup Form with SSO
export const SignupFormFlow = {
parameters: {
viewport: {
defaultViewport: 'desktop',
},
},
args: {
children: (
<SignupFormWithSSO
signupHeader="Sign up"
signinText="Already have an account?"
signinUrl="/login"
signinCTA="Sign in"
showSignin={true}
organizationName=""
nameLabel="Name"
namePlaceholder="Enter your full name"
emailLabel="Email"
emailPlaceholder="Enter your work email"
passwordLabel="Password"
passwordPlaceholder="Create password"
signupButtonText="Sign up"
orText="OR"
showOrSeparator={true}
showSSOButtons={true}
googleButtonText="Sign up with"
githubButtonText="Sign up with"
onGoogleSignup={() => console.log('Google signup clicked')}
onGitHubSignup={() => console.log('GitHub signup clicked')}
/>
),
},
};
// Signup Flow - Step 1: With Organization
export const SignupFormWithOrganizationFlow = {
parameters: {
viewport: {
defaultViewport: 'desktop',
},
},
args: {
children: (
<SignupFormWithSSO
signupHeader="Sign up"
signinText="Already have an account?"
signinUrl="/login"
signinCTA="Sign in"
showSignin={true}
organizationName="Acme Corporation"
nameLabel="Name"
namePlaceholder="Enter your full name"
emailLabel="Email"
emailPlaceholder="Enter your work email"
passwordLabel="Password"
passwordPlaceholder="Create password"
signupButtonText="Sign up"
orText="OR"
showOrSeparator={true}
showSSOButtons={true}
googleButtonText="Sign up with"
githubButtonText="Sign up with"
onGoogleSignup={() => console.log('Google signup clicked')}
onGitHubSignup={() => console.log('GitHub signup clicked')}
/>
),
},
};
// Signup Flow - Step 2: Signup Confirmation
export const SignupConfirmationFlow = {
render: (args) => (
<AuthCenteredLayout {...args}>
<SignupSuccessInfo
headerText="Check your mail"
messageText="We've sent a verification email to"
email="user@example.com"
name="John Doe"
infoText="Did not receive an email? Check your spam folder!"
showInfo={true}
resendButtonText="Resend verification email"
resendCountdownText="Resend verification email in"
showResendButton={true}
resendDisabled={false}
resendCountdown={0}
onResendEmail={() => console.log('Resend email clicked')}
backButtonText="Back to sign up"
onBackToSignup={() => console.log('Back to signup clicked')}
showSeparator={true}
/>
</AuthCenteredLayout>
),
parameters: {
viewport: {
defaultViewport: 'desktop',
},
},
};

View file

@ -1,280 +0,0 @@
import React from 'react';
import { SignupFormWithSSO } from '../SignupFormWithSSO';
export default {
title: 'Auth/Blocks/SignupFormWithSSO',
component: SignupFormWithSSO,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
signupHeader: {
control: 'text',
description: 'The main heading text for the signup form',
},
signinText: {
control: 'text',
description: 'Text for the sign in link',
},
signinUrl: {
control: 'text',
description: 'URL for the sign in link',
},
signinCTA: {
control: 'text',
description: 'Call to action text for the sign in link',
},
showSignin: {
control: 'boolean',
description: 'Show or hide the sign in link',
},
organizationName: {
control: 'text',
description: 'Name of the organization to display',
},
nameLabel: {
control: 'text',
description: 'Label for the name input field',
},
namePlaceholder: {
control: 'text',
description: 'Placeholder text for the name input field',
},
emailLabel: {
control: 'text',
description: 'Label for the email input field',
},
emailPlaceholder: {
control: 'text',
description: 'Placeholder text for the email input field',
},
passwordLabel: {
control: 'text',
description: 'Label for the password input field',
},
passwordPlaceholder: {
control: 'text',
description: 'Placeholder text for the password input field',
},
signupButtonText: {
control: 'text',
description: 'Text for the signup button',
},
orText: {
control: 'text',
description: 'Text for the OR separator',
},
showOrSeparator: {
control: 'boolean',
description: 'Show or hide the OR separator',
},
showSSOButtons: {
control: 'boolean',
description: 'Show or hide the SSO buttons',
},
googleButtonText: {
control: 'text',
description: 'Text for the Google signup button',
},
githubButtonText: {
control: 'text',
description: 'Text for the GitHub signup button',
},
onGoogleSignup: {
action: 'google signup clicked',
description: 'Google signup button handler',
},
onGitHubSignup: {
action: 'github signup clicked',
description: 'GitHub signup button handler',
},
onSubmit: {
action: 'form submitted',
description: 'Form submission handler',
},
isLoading: {
control: 'boolean',
description: 'Loading state for the form',
},
disabled: {
control: 'boolean',
description: 'Disabled state for the form',
},
},
};
export const Default = {
args: {
signupHeader: 'Sign up',
signinText: 'Already have an account?',
signinUrl: '/login',
signinCTA: 'Sign in',
showSignin: true,
organizationName: '',
nameLabel: 'Name',
namePlaceholder: 'Enter your full name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Create password',
signupButtonText: 'Sign up',
orText: 'OR',
showOrSeparator: true,
showSSOButtons: true,
googleButtonText: 'Sign up with',
githubButtonText: 'Sign up with',
isLoading: false,
disabled: false,
},
};
export const WithOrganization = {
args: {
signupHeader: 'Sign up',
signinText: 'Already have an account?',
signinUrl: '/login',
signinCTA: 'Sign in',
showSignin: true,
organizationName: 'Acme Corporation',
nameLabel: 'Name',
namePlaceholder: 'Enter your full name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Create password',
signupButtonText: 'Sign up',
orText: 'OR',
showOrSeparator: true,
showSSOButtons: true,
googleButtonText: 'Sign up with',
githubButtonText: 'Sign up with',
isLoading: false,
disabled: false,
},
};
export const WithoutSSO = {
args: {
signupHeader: 'Sign up',
signinText: 'Already have an account?',
signinUrl: '/login',
signinCTA: 'Sign in',
showSignin: true,
organizationName: '',
nameLabel: 'Name',
namePlaceholder: 'Enter your full name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Create password',
signupButtonText: 'Sign up',
orText: 'OR',
showOrSeparator: false,
showSSOButtons: false,
googleButtonText: 'Sign up with',
githubButtonText: 'Sign up with',
isLoading: false,
disabled: false,
},
};
export const WithoutSigninLink = {
args: {
signupHeader: 'Sign up',
signinText: 'Already have an account?',
signinUrl: '/login',
signinCTA: 'Sign in',
showSignin: false,
organizationName: '',
nameLabel: 'Name',
namePlaceholder: 'Enter your full name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Create password',
signupButtonText: 'Sign up',
orText: 'OR',
showOrSeparator: true,
showSSOButtons: true,
googleButtonText: 'Sign up with',
githubButtonText: 'Sign up with',
isLoading: false,
disabled: false,
},
};
export const Loading = {
args: {
signupHeader: 'Sign up',
signinText: 'Already have an account?',
signinUrl: '/login',
signinCTA: 'Sign in',
showSignin: true,
organizationName: '',
nameLabel: 'Name',
namePlaceholder: 'Enter your full name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Create password',
signupButtonText: 'Sign up',
orText: 'OR',
showOrSeparator: true,
showSSOButtons: true,
googleButtonText: 'Sign up with',
githubButtonText: 'Sign up with',
isLoading: true,
disabled: false,
},
};
export const Disabled = {
args: {
signupHeader: 'Sign up',
signinText: 'Already have an account?',
signinUrl: '/login',
signinCTA: 'Sign in',
showSignin: true,
organizationName: '',
nameLabel: 'Name',
namePlaceholder: 'Enter your full name',
emailLabel: 'Email',
emailPlaceholder: 'Enter your work email',
passwordLabel: 'Password',
passwordPlaceholder: 'Create password',
signupButtonText: 'Sign up',
orText: 'OR',
showOrSeparator: true,
showSSOButtons: true,
googleButtonText: 'Sign up with',
githubButtonText: 'Sign up with',
isLoading: false,
disabled: true,
},
};
export const CustomTexts = {
args: {
signupHeader: 'Create Account',
signinText: 'Have an existing account?',
signinUrl: '/login',
signinCTA: 'Log in',
showSignin: true,
organizationName: 'TechCorp',
nameLabel: 'Full Name',
namePlaceholder: 'Enter your complete name',
emailLabel: 'Work Email',
emailPlaceholder: 'Enter your company email',
passwordLabel: 'Secure Password',
passwordPlaceholder: 'Create a strong password',
signupButtonText: 'Create Account',
orText: 'OR',
showOrSeparator: true,
showSSOButtons: true,
googleButtonText: 'Continue with',
githubButtonText: 'Continue with',
isLoading: false,
disabled: false,
},
};

View file

@ -1,305 +0,0 @@
import React from 'react';
import { SignupSuccessInfo } from '../SignupSuccessInfo';
export default {
title: 'Auth/Blocks/SignupSuccessInfo',
component: SignupSuccessInfo,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
headerText: {
control: 'text',
description: 'The main heading text for the signup success screen',
},
messageText: {
control: 'text',
description: 'Main message text',
},
email: {
control: 'text',
description: 'Email address to display in the message',
},
name: {
control: 'text',
description: 'User name to display in the message',
},
infoText: {
control: 'text',
description: 'Additional info text',
},
showInfo: {
control: 'boolean',
description: 'Show or hide the info text',
},
resendButtonText: {
control: 'text',
description: 'Text for the resend verification email button',
},
resendCountdownText: {
control: 'text',
description: 'Text for the resend countdown',
},
showResendButton: {
control: 'boolean',
description: 'Show or hide the resend button',
},
resendDisabled: {
control: 'boolean',
description: 'Disabled state for the resend button',
},
resendCountdown: {
control: 'number',
description: 'Countdown value for resend button',
},
backButtonText: {
control: 'text',
description: 'Text for the back to signup button',
},
onBackToSignup: {
action: 'back to signup clicked',
description: 'Back to signup button handler',
},
showSeparator: {
control: 'boolean',
description: 'Show or hide the separator',
},
},
};
export const Default = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a verification email to",
email: 'user@example.com',
name: 'John Doe',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: true,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Back to sign up',
showSeparator: true,
},
};
export const CustomHeader = {
args: {
headerText: 'Account Created Successfully',
messageText: "We've sent a verification email to",
email: 'user@example.com',
name: 'John Doe',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: true,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Back to sign up',
showSeparator: true,
},
};
export const WithEmailOnly = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a verification email to",
email: 'user@example.com',
name: '',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: true,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Back to sign up',
showSeparator: true,
},
};
export const WithNameOnly = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a verification email to your registered email address",
email: '',
name: 'John Doe',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: true,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Back to sign up',
showSeparator: true,
},
};
export const LongEmail = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a verification email to",
email: 'very.long.email.address@verylongdomainname.com',
name: 'John Doe',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: true,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Back to sign up',
showSeparator: true,
},
};
export const NoInfo = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a verification email to",
email: 'user@example.com',
name: 'John Doe',
infoText: '',
showInfo: false,
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: true,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Back to sign up',
showSeparator: true,
},
};
export const NoResendButton = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a verification email to",
email: 'user@example.com',
name: 'John Doe',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: false,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Back to sign up',
showSeparator: true,
},
};
export const ResendDisabled = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a verification email to",
email: 'user@example.com',
name: 'John Doe',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: true,
resendDisabled: true,
resendCountdown: 15,
backButtonText: 'Back to sign up',
showSeparator: true,
},
};
export const NoSeparator = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a verification email to",
email: 'user@example.com',
name: 'John Doe',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: true,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Back to sign up',
showSeparator: false,
},
};
export const CustomMessage = {
args: {
headerText: 'Account Created',
messageText: 'A verification email has been sent to your email address',
email: 'user@example.com',
name: 'John Doe',
infoText: 'Please check your inbox and follow the instructions to verify your account',
showInfo: true,
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: true,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Return to signup',
showSeparator: true,
},
};
export const Minimal = {
args: {
headerText: 'Email Sent',
messageText: 'Check your email for verification instructions',
email: '',
name: '',
infoText: '',
showInfo: false,
resendButtonText: 'Resend',
resendCountdownText: 'Resend in',
showResendButton: false,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Back',
showSeparator: false,
},
};
export const CustomButtonTexts = {
args: {
headerText: 'Check your mail',
messageText: "We've sent a verification email to",
email: 'user@example.com',
name: 'John Doe',
infoText: 'Did not receive an email? Check your spam folder!',
showInfo: true,
resendButtonText: 'Send another verification email',
resendCountdownText: 'Send another email in',
showResendButton: true,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Return to registration',
showSeparator: true,
},
};
export const LongMessage = {
args: {
headerText: 'Check your mail',
messageText:
"We've sent a verification email to your registered email address. Please check your inbox and click the link to verify your account and continue with the setup process",
email: 'user@example.com',
name: 'John Doe',
infoText:
'Did not receive an email? Please check your spam folder or contact support if you continue to have issues with email delivery',
showInfo: true,
resendButtonText: 'Resend verification email',
resendCountdownText: 'Resend verification email in',
showResendButton: true,
resendDisabled: false,
resendCountdown: 0,
backButtonText: 'Back to sign up',
showSeparator: true,
},
};

View file

@ -1,92 +0,0 @@
import React from 'react';
import { AuthLayout } from '../AuthLayout';
import { InviteSignupForm } from '../InviteSignupForm';
import { JoinWorkspaceForm } from '../JoinWorkspaceForm';
export default {
title: 'Auth/Flows/TeamInvite',
component: AuthLayout,
parameters: {
layout: 'fullscreen',
viewport: {
viewports: {
desktop: {
name: 'Desktop',
styles: {
width: '1440px',
height: '900px',
},
},
tablet: {
name: 'Tablet',
styles: {
width: '768px',
height: '1024px',
},
},
mobile: {
name: 'Mobile',
styles: {
width: '375px',
height: '667px',
},
},
},
},
},
tags: ['autodocs'],
argTypes: {
children: {
control: false,
description: 'Content to be displayed within the auth layout',
},
},
};
// Team Invite Flow - Step 1: Invite Signup
export const TeamInviteSignupFlow = {
parameters: {
viewport: {
defaultViewport: 'desktop',
},
},
args: {
children: (
<InviteSignupForm
headerText="Sign up"
descriptionText="You have been invited to join a workspace. Please create your account to continue."
emailLabel="Email"
emailPlaceholder="Enter your email"
emailValue="nithin@dev.io"
emailDisabled={true}
passwordLabel="Password"
passwordPlaceholder="Create password"
buttonText="Create account"
/>
),
},
};
// Team Invite Flow - Step 2: Join Workspace
export const TeamInviteJoinWorkspaceFlow = {
parameters: {
viewport: {
defaultViewport: 'desktop',
},
},
args: {
children: (
<JoinWorkspaceForm
headerText="Join Dev's workspace"
descriptionText="You are invited to a workspace Dev's workspace. Accept the invite to join the workspace."
nameLabel="Name"
namePlaceholder="Enter your name"
nameValue="Nithin"
emailLabel="Email"
emailPlaceholder="Enter your email"
emailValue="nithin@dev.io"
buttonText="Accept Invite"
/>
),
},
};

View file

@ -1,68 +0,0 @@
import * as React from 'react';
import { cva } from 'class-variance-authority';
import { cn } from '@/lib/utils';
const alertVariants = cva('tw-relative tw-w-full tw-rounded-md tw-p-3 tw-text-xs tw-flex tw-gap-1.5 tw-items-start', {
variants: {
type: {
info: '',
warning: '',
danger: '',
},
background: {
none: '',
grey: 'tw-bg-interactive-default',
white: 'tw-bg-background-surface-layer-01 tw-shadow-elevation-100',
'state-specific': '',
},
},
compoundVariants: [
// Info variants
{
type: 'info',
background: 'state-specific',
class: 'tw-bg-background-accent-weak',
},
// Warning variants
{
type: 'warning',
background: 'state-specific',
class: 'tw-bg-background-warning-weak',
},
// Danger variants
{
type: 'danger',
background: 'state-specific',
class: 'tw-bg-background-error-weak',
},
],
defaultVariants: {
type: 'info',
background: 'none',
},
});
const Alert = React.forwardRef(({ className, type, background, ...props }, ref) => (
<div ref={ref} role="alert" className={cn(alertVariants({ type, background }), className)} {...props} />
));
Alert.displayName = 'Alert';
const AlertTitle = React.forwardRef(({ className, ...props }, ref) => (
<h5
ref={ref}
className={cn('tw-font-medium tw-leading-[18px] tw-text-[#2d343b] tw-text-[12px] tw-mb-0', className)}
{...props}
/>
));
AlertTitle.displayName = 'AlertTitle';
const AlertDescription = React.forwardRef(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn('tw-font-normal tw-leading-[18px] tw-text-text-placeholder tw-text-[12px]', className)}
{...props}
/>
));
AlertDescription.displayName = 'AlertDescription';
export { Alert, AlertTitle, AlertDescription };

View file

@ -1,40 +0,0 @@
import React from 'react';
import { Button } from '@/components/ui/button';
import { generateCypressDataCy } from '../../../modules/common/helpers/cypressHelpers.js';
const EncryptedField = ({ propertyKey, isEditing, handleEncryptedFieldsToggle, isDisabled, children }) => {
return (
<div>
<div className="d-flex justify-content-between w-100">
<div className="mx-1 col">
<Button
type="a"
variant="tertiary"
target="_blank"
rel="noreferrer"
disabled={isDisabled}
onClick={(e) => handleEncryptedFieldsToggle(e, propertyKey)}
data-cy={`button-${generateCypressDataCy(isEditing ? 'Cancel' : 'Edit')}`}
>
{isEditing ? 'Cancel' : 'Edit'}
</Button>
</div>
<div className="col-auto mb-2">
<small className="text-green" data-cy="encrypted-text">
<img
className="mx-2 encrypted-icon"
src="assets/images/icons/padlock.svg"
width="12"
height="12"
alt="Encrypted"
/>
Encrypted
</small>
</div>
</div>
{children}
</div>
);
};
export default EncryptedField;

View file

@ -1,38 +0,0 @@
import * as React from 'react';
import { cn } from '@/lib/utils';
import { Alert, AlertTitle, AlertDescription } from '../Alert/Alert';
// Icon color variants based on type
const getIconColor = (type) => {
switch (type) {
case 'info':
return 'tw-text-icon-brand';
case 'warning':
return 'tw-text-icon-warning';
case 'danger':
return 'tw-text-icon-danger';
default:
return 'tw-text-icon-brand';
}
};
// Compound component that accepts title, icon, description, and button props
const InlineInfoCompound = React.forwardRef(
({ className, type = 'info', background = 'none', title, icon: Icon, description, button, ...props }, ref) => (
<Alert ref={ref} type={type} background={background} className={className} {...props}>
{Icon && (
<div className="tw-shrink-0 tw-w-[18px] tw-h-[18px]">
<Icon className={cn('tw-w-full tw-h-full', getIconColor(type))} />
</div>
)}
<div className="tw-flex tw-flex-col tw-gap-2 tw-items-start">
{title && <AlertTitle>{title}</AlertTitle>}
{description && <AlertDescription>{description}</AlertDescription>}
{button && <div className="tw-mt-1">{button}</div>}
</div>
</Alert>
)
);
InlineInfoCompound.displayName = 'InlineInfoCompound';
export { InlineInfoCompound };

View file

@ -1,200 +0,0 @@
import React from 'react';
import { InlineInfoCompound } from './InlineInfo';
import { Info, AlertTriangle, AlertCircle } from 'lucide-react';
import { Button } from '../Button/Button';
export default {
title: 'UI/InlineInfo',
component: InlineInfoCompound,
parameters: {
layout: 'padded',
},
argTypes: {
type: {
control: { type: 'select' },
options: ['info', 'warning', 'danger'],
},
background: {
control: { type: 'select' },
options: ['none', 'grey', 'white', 'state-specific'],
},
title: {
control: { type: 'text' },
},
description: {
control: { type: 'text' },
},
},
};
const Template = (args) => <InlineInfoCompound {...args} />;
export const Default = Template.bind({});
Default.args = {
type: 'info',
background: 'none',
title: 'Information',
description: 'This is an informational message.',
icon: Info,
button: (
<Button size="small" variant="outline">
Learn More
</Button>
),
};
// All Variants Grid
export const AllVariants = () => {
const types = ['info', 'warning', 'danger'];
const backgrounds = ['none', 'grey', 'white', 'state-specific'];
const icons = {
info: Info,
warning: AlertTriangle,
danger: AlertCircle,
};
const titles = {
info: 'Information',
warning: 'Warning',
danger: 'Error',
};
const descriptions = {
info: 'This is an informational message.',
warning: 'Please review your settings before proceeding.',
danger: 'Something went wrong. Please try again.',
};
return (
<div className="tw-space-y-8">
<div>
<h2 className="tw-text-2xl tw-font-bold tw-mb-4">InlineInfo Compound Component - All Variants</h2>
<p className="tw-text-gray-600 tw-mb-6">
Showcasing all 12 variants from Figma design (3 types × 4 backgrounds)
</p>
</div>
{types.map((type) => (
<div key={type} className="tw-space-y-4">
<h3 className="tw-text-lg tw-font-semibold tw-capitalize tw-text-gray-800">{type} Type</h3>
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4">
{backgrounds.map((background) => (
<div key={`${type}-${background}`} className="tw-space-y-2">
<div className="tw-text-sm tw-font-medium tw-text-gray-600 tw-capitalize">
{background.replace('-', ' ')} Background
</div>
<InlineInfoCompound
type={type}
background={background}
icon={icons[type]}
title={titles[type]}
description={descriptions[type]}
button={
<Button size="sm" variant={type === 'danger' ? 'destructive' : 'outline'}>
Action
</Button>
}
/>
</div>
))}
</div>
</div>
))}
</div>
);
};
// Individual Type Stories
export const InfoVariants = () => (
<div className="tw-space-y-4">
<h3 className="tw-text-lg tw-font-semibold">Info Type Variants</h3>
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4">
{['none', 'grey', 'white', 'state-specific'].map((background) => (
<div key={background} className="tw-space-y-2">
<div className="tw-text-sm tw-font-medium tw-text-gray-600 tw-capitalize">
{background.replace('-', ' ')} Background
</div>
<InlineInfoCompound
type="info"
background={background}
icon={Info}
title="Information"
description="This is an informational message."
button={
<Button size="sm" variant="outline">
Learn More
</Button>
}
/>
</div>
))}
</div>
</div>
);
export const WarningVariants = () => (
<div className="tw-space-y-4">
<h3 className="tw-text-lg tw-font-semibold">Warning Type Variants</h3>
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4">
{['none', 'grey', 'white', 'state-specific'].map((background) => (
<div key={background} className="tw-space-y-2">
<div className="tw-text-sm tw-font-medium tw-text-gray-600 tw-capitalize">
{background.replace('-', ' ')} Background
</div>
<InlineInfoCompound
type="warning"
background={background}
icon={AlertTriangle}
title="Warning"
description="Please review your settings before proceeding."
button={
<Button size="sm" variant="outline">
Review
</Button>
}
/>
</div>
))}
</div>
</div>
);
export const DangerVariants = () => (
<div className="tw-space-y-4">
<h3 className="tw-text-lg tw-font-semibold">Danger Type Variants</h3>
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 lg:tw-grid-cols-4 tw-gap-4">
{['none', 'grey', 'white', 'state-specific'].map((background) => (
<div key={background} className="tw-space-y-2">
<div className="tw-text-sm tw-font-medium tw-text-gray-600 tw-capitalize">
{background.replace('-', ' ')} Background
</div>
<InlineInfoCompound
type="danger"
background={background}
icon={AlertCircle}
title="Error"
description="Something went wrong. Please try again."
button={
<Button size="sm" variant="destructive">
Retry
</Button>
}
/>
</div>
))}
</div>
</div>
);
// Interactive Playground
export const Playground = Template.bind({});
Playground.args = {
type: 'info',
background: 'none',
title: 'Custom Title',
description: 'Custom description text goes here.',
icon: Info,
button: (
<Button size="sm" variant="outline">
Custom Button
</Button>
),
};

View file

@ -1,3 +0,0 @@
import { Button, buttonVariants } from './InlineInfo/InlineInfo';
export { Button, buttonVariants };

View file

@ -1,3 +0,0 @@
import { Button, buttonVariants } from './Button/Button';
export { Button, buttonVariants };

View file

@ -1,3 +0,0 @@
import { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } from './Card/Index';
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };

View file

@ -1,4 +0,0 @@
import InputComponent from './Input/Index';
import EditableTitleInput from './Input/EditableTitleInput/Index';
export { InputComponent as Input, EditableTitleInput };

View file

@ -1,3 +0,0 @@
import { Label } from './Label/Label';
export { Label };

View file

@ -1,47 +0,0 @@
import { useState, useEffect } from 'react';
/**
* Custom hook for password input functionality
* @param {Object} options - Configuration options
* @param {Function} options.onChange - Change handler function
* @param {Function} options.validation - Validation function
* @param {Object} options.isValidatedMessages - External validation messages
* @param {boolean} options.disabled - Whether input is disabled
* @returns {Object} Password input state and handlers
*/
export const usePasswordInput = ({ onChange, validation, isValidatedMessages }) => {
const [isValid, setIsValid] = useState(null);
const [message, setMessage] = useState('');
/**
* Handle input change with validation
* @param {Event} e - Input change event
*/
const handleChange = (e) => {
if (validation) {
const validateObj = validation(e);
setIsValid(validateObj.valid);
setMessage(validateObj.message);
onChange(e, validateObj);
} else {
onChange(e);
}
};
// Update validation state when external validation messages change
useEffect(() => {
if (isValidatedMessages) {
setIsValid(isValidatedMessages.valid);
setMessage(isValidatedMessages.message);
}
}, [isValidatedMessages]);
return {
// State
isValid,
message,
// Handlers
handleChange,
};
};