diff --git a/packages/react-core/src/components/LoginPage/LoginFooterItem.tsx b/packages/react-core/src/components/LoginPage/LoginFooterItem.tsx index 236d32f2953..d454cee2e49 100644 --- a/packages/react-core/src/components/LoginPage/LoginFooterItem.tsx +++ b/packages/react-core/src/components/LoginPage/LoginFooterItem.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; export interface LoginFooterItemProps extends React.HTMLProps { - /** Content rendered inside the footer Link Item */ + /** Content rendered inside the footer link item */ children?: React.ReactNode; - /** Additional classes added to the Footer Link Item */ + /** Additional classes added to the footer link item */ className?: string; - /** The URL of the Footer Link Item */ + /** The URL of the footer link item */ href?: string; /** Specifies where to open the linked document */ target?: string; diff --git a/packages/react-core/src/components/LoginPage/LoginForm.tsx b/packages/react-core/src/components/LoginPage/LoginForm.tsx index 43aab801498..037c6fad35e 100644 --- a/packages/react-core/src/components/LoginPage/LoginForm.tsx +++ b/packages/react-core/src/components/LoginPage/LoginForm.tsx @@ -11,29 +11,29 @@ import EyeIcon from '@patternfly/react-icons/dist/esm/icons/eye-icon'; export interface LoginFormProps extends React.HTMLProps { /** Flag to indicate if the first dropdown item should not gain initial focus */ noAutoFocus?: boolean; - /** Additional classes added to the Login Main Body's Form */ + /** Additional classes added to the login main body's form */ className?: string; - /** Flag indicating the Helper Text is visible * */ + /** Flag indicating the helper text is visible * */ showHelperText?: boolean; - /** Content displayed in the Helper Text component * */ + /** Content displayed in the helper text component * */ helperText?: React.ReactNode; - /** Icon displayed to the left in the Helper Text */ + /** Icon displayed to the left in the helper text */ helperTextIcon?: React.ReactNode; - /** Label for the Username Input Field */ + /** Label for the username input field */ usernameLabel?: string; - /** Value for the Username */ + /** Value for the username */ usernameValue?: string; - /** Function that handles the onChange event for the Username */ + /** Function that handles the onChange event for the username */ onChangeUsername?: (value: string, event: React.FormEvent) => void; - /** Flag indicating if the Username is valid */ + /** Flag indicating if the username is valid */ isValidUsername?: boolean; - /** Label for the Password Input Field */ + /** Label for the password input field */ passwordLabel?: string; - /** Value for the Password */ + /** Value for the password */ passwordValue?: string; - /** Function that handles the onChange event for the Password */ + /** Function that handles the onChange event for the password */ onChangePassword?: (value: string, event: React.FormEvent) => void; - /** Flag indicating if the Password is valid */ + /** Flag indicating if the password is valid */ isValidPassword?: boolean; /** Flag indicating if the user can toggle hiding the password */ isShowPasswordEnabled?: boolean; @@ -41,17 +41,17 @@ export interface LoginFormProps extends React.HTMLProps { showPasswordAriaLabel?: string; /** Accessible label for the hide password button */ hidePasswordAriaLabel?: string; - /** Label for the Log in Button Input */ + /** Label for the log in button input */ loginButtonLabel?: string; - /** Flag indicating if the Login Button is disabled */ + /** Flag indicating if the login button is disabled */ isLoginButtonDisabled?: boolean; - /** Function that is called when the Login button is clicked */ + /** Function that is called when the login button is clicked */ onLoginButtonClick?: (event: React.MouseEvent) => void; - /** Label for the Remember Me Checkbox that indicates the user should be kept logged in. If the label is not provided, the checkbox will not show. */ + /** Label for the remember me checkbox that indicates the user should be kept logged in. If the label is not provided, the checkbox will not show. */ rememberMeLabel?: string; - /** Flag indicating if the remember me Checkbox is checked. */ + /** Flag indicating if the remember me checkbox is checked. */ isRememberMeChecked?: boolean; - /** Function that handles the onChange event for the Remember Me Checkbox */ + /** Function that handles the onChange event for the remember me checkbox */ onChangeRememberMe?: (checked: boolean, event: React.FormEvent) => void; } diff --git a/packages/react-core/src/components/LoginPage/LoginHeader.tsx b/packages/react-core/src/components/LoginPage/LoginHeader.tsx index 292d0871067..9d94a48c350 100644 --- a/packages/react-core/src/components/LoginPage/LoginHeader.tsx +++ b/packages/react-core/src/components/LoginPage/LoginHeader.tsx @@ -7,7 +7,7 @@ export interface LoginHeaderProps extends React.HTMLProps { children?: React.ReactNode; /** Additional classes added to the login header */ className?: string; - /** Header Brand component (e.g. ) */ + /** Header brand component (e.g. ) */ headerBrand?: React.ReactNode; } diff --git a/packages/react-core/src/components/LoginPage/LoginMainBody.tsx b/packages/react-core/src/components/LoginPage/LoginMainBody.tsx index bec369f23bb..55ea572ff90 100644 --- a/packages/react-core/src/components/LoginPage/LoginMainBody.tsx +++ b/packages/react-core/src/components/LoginPage/LoginMainBody.tsx @@ -3,9 +3,9 @@ import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Login/login'; export interface LoginMainBodyProps extends React.HTMLProps { - /** Content rendered inside the Login Main Body */ + /** Content rendered inside the login main body */ children?: React.ReactNode; - /** Additional classes added to the Login Main Body */ + /** Additional classes added to the login main body */ className?: string; } diff --git a/packages/react-core/src/components/LoginPage/LoginMainFooter.tsx b/packages/react-core/src/components/LoginPage/LoginMainFooter.tsx index 51c087f1a28..c5583f224a4 100644 --- a/packages/react-core/src/components/LoginPage/LoginMainFooter.tsx +++ b/packages/react-core/src/components/LoginPage/LoginMainFooter.tsx @@ -3,15 +3,15 @@ import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Login/login'; export interface LoginMainFooterProps extends React.HTMLProps { - /** Additional classes added to the Login Main Footer */ + /** Additional classes added to the login main footer */ className?: string; - /** Content rendered inside the Login Main Footer */ + /** Content rendered inside the login main footer */ children?: React.ReactNode; - /** Content rendered inside the Login Main Footer as Social Media Links* */ + /** Content rendered inside the login main footer as social media links* */ socialMediaLoginContent?: React.ReactNode; - /** Content rendered inside of Login Main Footer Band to display a sign up for account message */ + /** Content rendered inside of login main footer band to display a sign up for account message */ signUpForAccountMessage?: React.ReactNode; - /** Content rendered inside of Login Main Footer Band do display a forgot credentials link* */ + /** Content rendered inside of login main footer band do display a forgot credentials link* */ forgotCredentials?: React.ReactNode; } diff --git a/packages/react-core/src/components/LoginPage/LoginMainFooterBandItem.tsx b/packages/react-core/src/components/LoginPage/LoginMainFooterBandItem.tsx index d40aeb74e45..69fe8ccf7ba 100644 --- a/packages/react-core/src/components/LoginPage/LoginMainFooterBandItem.tsx +++ b/packages/react-core/src/components/LoginPage/LoginMainFooterBandItem.tsx @@ -3,9 +3,9 @@ import styles from '@patternfly/react-styles/css/components/Login/login'; import { css } from '@patternfly/react-styles'; export interface LoginMainFooterBandItemProps extends React.HTMLProps { - /** Content rendered inside the footer Link Item */ + /** Content rendered inside the footer link item */ children?: React.ReactNode; - /** Additional classes added to the Footer Link Item */ + /** Additional classes added to the footer link item */ className?: string; } diff --git a/packages/react-core/src/components/LoginPage/LoginMainFooterLinksItem.tsx b/packages/react-core/src/components/LoginPage/LoginMainFooterLinksItem.tsx index e0f65d389db..45306e051bc 100644 --- a/packages/react-core/src/components/LoginPage/LoginMainFooterLinksItem.tsx +++ b/packages/react-core/src/components/LoginPage/LoginMainFooterLinksItem.tsx @@ -3,15 +3,15 @@ import styles from '@patternfly/react-styles/css/components/Login/login'; import { css } from '@patternfly/react-styles'; export interface LoginMainFooterLinksItemProps extends React.HTMLProps { - /** Content rendered inside the footer Link Item */ + /** Content rendered inside the footer link item */ children?: React.ReactNode; - /** HREF for Footer Link Item */ + /** HREF for footer link item */ href?: string; - /** Target for Footer Link Item */ + /** Target for footer link item */ target?: string; - /** Additional classes added to the Footer Link Item */ + /** Additional classes added to the footer link item */ className?: string; - /** Component used to render the Footer Link Item */ + /** Component used to render the footer link item */ linkComponent?: React.ReactNode; /** Props for the LinkComponent */ linkComponentProps?: any; diff --git a/packages/react-core/src/components/LoginPage/LoginMainHeader.tsx b/packages/react-core/src/components/LoginPage/LoginMainHeader.tsx index 2d682dec2c9..2b9552e9db3 100644 --- a/packages/react-core/src/components/LoginPage/LoginMainHeader.tsx +++ b/packages/react-core/src/components/LoginPage/LoginMainHeader.tsx @@ -4,14 +4,16 @@ import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Login/login'; export interface LoginMainHeaderProps extends React.HTMLProps { - /** Content rendered inside the Login Main Header */ + /** Content rendered inside the login main header */ children?: React.ReactNode; - /** Additional classes added to the Login Main Header */ + /** Additional classes added to the login main header */ className?: string; - /** Title for the Login Main Header */ + /** Title for the login main header */ title?: string; - /** Subtitle that contains the Text, URL, and URL Text for the Login Main Header */ + /** Subtitle that contains the text, URL, and URL text for the login main header */ subtitle?: string; + /** Actions that render for the login main header */ + headerUtilities?: React.ReactNode; } export const LoginMainHeader: React.FunctionComponent = ({ @@ -19,6 +21,7 @@ export const LoginMainHeader: React.FunctionComponent = ({ className = '', title = '', subtitle = '', + headerUtilities = null, ...props }: LoginMainHeaderProps) => (
@@ -28,6 +31,7 @@ export const LoginMainHeader: React.FunctionComponent = ({ )} {subtitle &&

{subtitle}

} + {headerUtilities &&
{headerUtilities}
} {children}
); diff --git a/packages/react-core/src/components/LoginPage/LoginPage.tsx b/packages/react-core/src/components/LoginPage/LoginPage.tsx index a617dc34f9e..3ad9bcdba80 100644 --- a/packages/react-core/src/components/LoginPage/LoginPage.tsx +++ b/packages/react-core/src/components/LoginPage/LoginPage.tsx @@ -13,33 +13,35 @@ import { LoginMainBody } from './LoginMainBody'; import { LoginMainFooter } from './LoginMainFooter'; export interface LoginPageProps extends React.HTMLProps { - /** Anything that can be rendered inside of the LoginPage (e.g. ) */ + /** Anything that can be rendered inside of the login page (e.g. ) */ children?: React.ReactNode; - /** Additional classes added to the LoginPage. */ + /** Additional classes added to the login page */ className?: string; - /** Attribute that specifies the URL of the brand image for the LoginPage */ + /** Attribute that specifies the URL of the brand image for the login page */ brandImgSrc?: string; - /** Attribute that specifies the alt text of the brand image for the LoginPage. */ + /** Attribute that specifies the alt text of the brand image for the login page */ brandImgAlt?: string; - /** Attribute that specifies the URL of the background image for the LoginPage */ + /** Attribute that specifies the URL of the background image for the login page */ backgroundImgSrc?: string | BackgroundImageSrcMap; - /** Attribute that specifies the alt text of the background image for the LoginPage. */ + /** Attribute that specifies the alt text of the background image for the login page */ backgroundImgAlt?: string; - /** Content rendered inside of the Text Component of the LoginPage */ + /** Content rendered inside of the text component of the login page */ textContent?: string; - /** Items rendered inside of the Footer List Component of the LoginPage */ + /** Items rendered inside of the footer list component of the login page */ footerListItems?: React.ReactNode; - /** Adds list variant styles for the Footer List component of the LoginPage. The only current value is'inline' */ + /** Adds list variant styles for the footer list component of the login page. The only current value is'inline' */ footerListVariants?: ListVariant.inline; - /** Title for the Login Main Body Header of the LoginPage */ + /** Title for the login main body header of the login page */ loginTitle: string; - /** Subtitle for the Login Main Body Header of the LoginPage */ + /** Subtitle for the login main body header of the login page */ loginSubtitle?: string; - /** Content rendered inside of Login Main Footer Band to display a sign up for account message */ + /** @beta Header utilities for the login main body header of the login page */ + headerUtilities?: React.ReactNode; + /** Content rendered inside of login main footer band to display a sign up for account message */ signUpForAccountMessage?: React.ReactNode; - /** Content rendered inside of Login Main Footer Band to display a forgot credentials link* */ + /** Content rendered inside of login main footer band to display a forgot credentials link. */ forgotCredentials?: React.ReactNode; - /** Content rendered inside of Social Media Login footer section . */ + /** Content rendered inside of social media login footer section */ socialMediaLoginContent?: React.ReactNode; } @@ -55,6 +57,7 @@ export const LoginPage: React.FunctionComponent = ({ footerListVariants, loginTitle, loginSubtitle, + headerUtilities, signUpForAccountMessage = null, forgotCredentials = null, socialMediaLoginContent = null, @@ -77,7 +80,7 @@ export const LoginPage: React.FunctionComponent = ({ {backgroundImgSrc && } - + {children} {(socialMediaLoginContent || forgotCredentials || signUpForAccountMessage) && ( { brandImgSrc={brandImg2} brandImgAlt="PatternFly logo" backgroundImgSrc={images} - backgroundImgAlt="Images" footerListItems={listItem} textContent="This is placeholder text only. Use this area to place any information or introductory message about your application that may be relevant to users." loginTitle="Log in to your account" diff --git a/packages/react-core/src/components/LoginPage/examples/LoginPageLanguageSelect.tsx b/packages/react-core/src/components/LoginPage/examples/LoginPageLanguageSelect.tsx new file mode 100644 index 00000000000..6cb92c984ea --- /dev/null +++ b/packages/react-core/src/components/LoginPage/examples/LoginPageLanguageSelect.tsx @@ -0,0 +1,194 @@ +import React from 'react'; +import brandImg2 from './brandImgColor2.svg'; +import { + LoginFooterItem, + LoginForm, + LoginMainFooterBandItem, + LoginMainFooterLinksItem, + LoginPage, + ListItem, + ListVariant, + Select, + SelectOption, + SelectOptionObject +} from '@patternfly/react-core'; +import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon'; + +export const LoginPageLanguageSelect: React.FunctionComponent = () => { + const [showHelperText, setShowHelperText] = React.useState(false); + const [username, setUsername] = React.useState(''); + const [isValidUsername, setIsValidUsername] = React.useState(true); + const [password, setPassword] = React.useState(''); + const [isValidPassword, setIsValidPassword] = React.useState(true); + const [isRememberMeChecked, setIsRememberMeChecked] = React.useState(false); + const [isHeaderUtilsOpen, setIsHeaderUtilsOpen] = React.useState(false); + const [selectedHeaderUtils, setSelectedHeaderUtils] = React.useState('English'); + + /** i18n object is used to simulate i18n integration of native language translation */ + const i18n = { + English: 'English', + Mandarin: '普通话', + Hindi: 'हिन्दी', + Spanish: 'Español', + Portuguese: 'Português', + Arabic: 'عربى', + Bengali: 'বাংলা' + }; + + const headerUtilsOptions = [ + , + , + , + , + , + , + + ]; + + const onHeaderUtilsToggle = (isExpanded: boolean) => { + setIsHeaderUtilsOpen(isExpanded); + }; + + const onHeaderUtilsSelect = ( + _event: React.MouseEvent | React.ChangeEvent, + value: string | SelectOptionObject + ) => { + setSelectedHeaderUtils(value); + setIsHeaderUtilsOpen(false); + }; + + const headerUtils = ( + + ); + + const handleUsernameChange = (value: string) => { + setUsername(value); + }; + + const handlePasswordChange = (value: string) => { + setPassword(value); + }; + + const onRememberMeClick = () => { + setIsRememberMeChecked(!isRememberMeChecked); + }; + + const onLoginButtonClick = (event: React.MouseEvent) => { + event.preventDefault(); + setIsValidUsername(!!username); + setIsValidPassword(!!password); + setShowHelperText(!username || !password); + }; + + const socialMediaLoginContent = ( + + + + + + + + + + + + + + + + + + ); + + const signUpForAccountMessage = ( + + Need an account? Sign up. + + ); + + const forgotCredentials = ( + + Forgot username or password? + + ); + + const listItem = ( + + + Terms of Use + + + Help + + + Privacy Policy + + + ); + + const loginForm = ( + } + usernameLabel="Username" + usernameValue={username} + onChangeUsername={handleUsernameChange} + isValidUsername={isValidUsername} + passwordLabel="Password" + passwordValue={password} + onChangePassword={handlePasswordChange} + isValidPassword={isValidPassword} + rememberMeLabel="Keep me logged in for 30 days." + isRememberMeChecked={isRememberMeChecked} + onChangeRememberMe={onRememberMeClick} + onLoginButtonClick={onLoginButtonClick} + loginButtonLabel="Log in" + /> + ); + + const images = { + lg: '/assets/images/pfbg_1200.jpg', + sm: '/assets/images/pfbg_768.jpg', + sm2x: '/assets/images/pfbg_768@2x.jpg', + xs: '/assets/images/pfbg_576.jpg', + xs2x: '/assets/images/pfbg_576@2x.jpg' + }; + + return ( + + {loginForm} + + ); +}; diff --git a/packages/react-core/src/components/LoginPage/examples/LoginPageShowHidePassword.tsx b/packages/react-core/src/components/LoginPage/examples/LoginPageShowHidePassword.tsx index 346c90ddec5..b20dec0be4f 100644 --- a/packages/react-core/src/components/LoginPage/examples/LoginPageShowHidePassword.tsx +++ b/packages/react-core/src/components/LoginPage/examples/LoginPageShowHidePassword.tsx @@ -130,7 +130,6 @@ export const LoginPageHideShowPassword: React.FunctionComponent = () => { brandImgSrc={brandImg2} brandImgAlt="PatternFly logo" backgroundImgSrc={images} - backgroundImgAlt="Images" footerListItems={listItem} textContent="This is placeholder text only. Use this area to place any information or introductory message about your application that may be relevant to users." loginTitle="Log in to your account"