/
githubmirror
/
client
Обзор
Документация
Войти
/
githubmirror
/
client
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
shared/signup/common.tsx
330 строк
10 KB
chrisnojima
refactor(styles): theme via hooks, no android remount (#29515)
08 авг 2026, 02:24
Не верифицирован
08 авг 2026, 02:24
a41d38e
Код
Авторство
О чём код?
import * as C from '@/constants' import type * as React from 'react' import * as Kb from '@/common-adapters' import {type ButtonProps} from '@/common-adapters/button' import {openURL} from '@/util/misc' import {useConfigState} from '@/stores/config' import ProvisionWaitingOverlay from '@/provision/waiting-overlay' export const desktopInputWidth = Kb.Styles.platformStyles({ isElectron: {width: 368}, isTablet: {width: 368}, }) type InfoIconProps = { invisible?: boolean style?: Kb.Styles.StylesCrossPlatform } export const InfoIcon = (props: InfoIconProps) => { const styles = useStyles() const loggedIn = useConfigState(s => s.loggedIn) const navigateAppend = C.Router2.navigateAppend const makePopup = (p: Kb.Popup2Parms) => { const {attachTo, hidePopup} = p const onDocumentation = () => { void openURL('https://book.keybase.io/docs') } const onFeedback = () => { navigateAppend({ name: loggedIn ? 'signupSendFeedbackLoggedIn' : 'signupSendFeedbackLoggedOut', params: {}, }) } return ( <Kb.FloatingMenu items={[ {onClick: onFeedback, title: 'Send feedback'}, {onClick: onDocumentation, title: 'Documentation'}, ]} attachTo={attachTo} visible={true} onHidden={hidePopup} closeOnSelect={true} /> ) } const {showPopup, popup, popupAnchor} = Kb.usePopup2(makePopup) return ( <> <Kb.Box2 direction="vertical" ref={popupAnchor} style={Kb.Styles.collapseStyles([props.invisible && styles.opacityNone, props.style])}> <Kb.Icon type="iconfont-question-mark" onClick={props.invisible ? undefined : showPopup} style={Kb.Styles.platformStyles({isElectron: {...Kb.Styles.desktopStyles.windowDraggingClickable}})} /> </Kb.Box2> {popup} </> ) } type HeaderProps = { onBack?: () => void title?: string titleComponent?: React.ReactNode showInfoIcon: boolean showInfoIconRow: boolean style: Kb.Styles.StylesCrossPlatform negative: boolean rightActionLabel?: string onRightAction?: () => void } // Only used on desktop const Header = (props: HeaderProps) => { const styles = useStyles() const theme = Kb.Styles.useTheme() return ( <Kb.Box2 direction="vertical" fullWidth={true} style={Kb.Styles.collapseStyles([styles.headerContainer, props.style])} > {(props.showInfoIcon || props.showInfoIconRow) && ( <Kb.Box2 direction="horizontal" fullWidth={true} style={styles.infoIconContainer} justifyContent="flex-end"> <InfoIcon invisible={props.negative || (props.showInfoIconRow && !props.showInfoIcon)} /> </Kb.Box2> )} <Kb.Box2 direction="horizontal" centerChildren={true} relative={true} style={styles.titleContainer} fullWidth={true}> {props.onBack && ( <Kb.ClickableBox onClick={props.onBack} direction="horizontal" alignItems="center" gap="xtiny" style={styles.backButton}> <Kb.Icon type="iconfont-arrow-left" color={props.negative ? theme.white : theme.black_50} sizeType="Small" style={styles.fixIconAlignment} /> <Kb.Text type="Body" style={props.negative ? undefined : styles.backText} negative={props.negative} > Back </Kb.Text> </Kb.ClickableBox> )} {props.titleComponent || <Kb.Text type="Header">{props.title}</Kb.Text>} {props.onRightAction && !!props.rightActionLabel && ( <Kb.Button type="Default" mode="Secondary" small={true} label={props.rightActionLabel} onClick={props.onRightAction} style={styles.rightActionButton} /> )} </Kb.Box2> </Kb.Box2> ) } type ButtonMeta = { disabled?: boolean label: string onClick: () => void type?: ButtonProps['type'] waiting?: boolean waitingKey?: string // makes this a WaitingButton } type SignupScreenProps = { banners?: React.ReactNode buttons?: Array<ButtonMeta> children: React.ReactNode negativeHeader?: boolean noBackground?: boolean onBack?: () => void headerStyle?: Kb.Styles.StylesCrossPlatform containerStyle?: Kb.Styles.StylesCrossPlatform contentContainerStyle?: Kb.Styles.StylesCrossPlatform footer?: React.ReactNode title?: string titleComponent?: React.ReactNode header?: React.ReactNode rightActionLabel?: string onRightAction?: () => void showHeaderInfoIcon?: boolean showHeaderInfoIconRow?: boolean hideDesktopHeader?: boolean waitingOverlay?: boolean } // Screens with header + body bg color (i.e. all but join-or-login) export const SignupScreen = (props: SignupScreenProps) => { const styles = useStyles() // When logged out, React Navigation's header owns the title/back/action row, so this screen-level // header would be a second header. Only draw it for logged-in uses (e.g. the feedback modal). const loggedIn = useConfigState(s => s.loggedIn) const showDesktopHeader = !isMobile && !props.hideDesktopHeader && loggedIn return ( <Kb.Box2 direction="vertical" fullWidth={true} fullHeight={true} alignItems="center" relative={true} style={styles.whiteBackground} > {showDesktopHeader && ( <Header onBack={props.onBack} title={props.title} titleComponent={props.titleComponent} showInfoIcon={!!props.showHeaderInfoIcon} showInfoIconRow={!!props.showHeaderInfoIconRow} style={Kb.Styles.collapseStyles([ props.noBackground && styles.whiteHeaderContainer, props.headerStyle, ])} negative={!!props.negativeHeader} rightActionLabel={props.rightActionLabel} onRightAction={props.onRightAction} /> )} {isMobile && props.header} <Kb.Box2 alignItems="center" direction="vertical" relative={true} flex={1} style={Kb.Styles.collapseStyles([ props.noBackground ? styles.whiteBackground : styles.blueBackground, props.containerStyle, ])} fullWidth={true} > <Kb.Box2 alignItems="center" direction="vertical" style={Kb.Styles.collapseStyles([styles.body, props.contentContainerStyle])} fullWidth={true} > {props.children} </Kb.Box2> {!!props.footer && ( <Kb.Box2 direction="vertical" fullWidth={true} style={styles.footer}> {props.footer} </Kb.Box2> )} {!!props.banners && <Kb.Box2 direction="vertical" style={styles.banners}>{props.banners}</Kb.Box2>} {!!props.buttons && ( <Kb.ButtonBar direction="column" fullWidth={isMobile && !Kb.Styles.isTablet} style={styles.buttonBar} > {props.buttons.map(b => b.waitingKey !== undefined ? ( <Kb.WaitingButton key={b.label} style={styles.button} {...b} waitingKey={b.waitingKey} fullWidth={true} /> ) : ( <Kb.Button key={b.label} style={styles.button} {...b} fullWidth={true} /> ) )} </Kb.ButtonBar> )} </Kb.Box2> {props.waitingOverlay && <ProvisionWaitingOverlay />} </Kb.Box2> ) } export const errorBanner = (error: string) => error.trim() ? ( <Kb.Banner key="generalError" color="red"> <Kb.BannerParagraph bannerColor="red" content={error} /> </Kb.Banner> ) : null const useStyles = Kb.Styles.createStyleHook( theme => ({ backButton: { bottom: Kb.Styles.globalMargins.small, left: Kb.Styles.globalMargins.small, position: 'absolute', }, backText: { color: theme.black_50, }, banners: { left: 0, position: 'absolute', right: 0, top: 0, }, blueBackground: { backgroundColor: theme.blueGrey, }, body: { ...Kb.Styles.padding( isMobile ? Kb.Styles.globalMargins.small : Kb.Styles.globalMargins.xlarge, Kb.Styles.globalMargins.small ), flex: 1, }, button: Kb.Styles.platformStyles({ isElectron: { height: 32, width: 368, }, isMobile: { height: 40, width: '100%', }, isTablet: { maxWidth: 368, }, }), buttonBar: Kb.Styles.platformStyles({ isElectron: { paddingBottom: Kb.Styles.globalMargins.xlarge - Kb.Styles.globalMargins.tiny, // tiny added inside buttonbar }, isMobile: { ...Kb.Styles.padding(0, Kb.Styles.globalMargins.small, Kb.Styles.globalMargins.tiny), }, }), fixIconAlignment: { position: 'relative', top: 2, }, footer: Kb.Styles.platformStyles({ isMobile: { ...Kb.Styles.padding(0, Kb.Styles.globalMargins.small, Kb.Styles.globalMargins.tiny), }, }), headerContainer: Kb.Styles.platformStyles({ common: {backgroundColor: theme.white}, isElectron: Kb.Styles.desktopStyles.windowDragging, }), infoIconContainer: { ...Kb.Styles.padding(Kb.Styles.globalMargins.small, Kb.Styles.globalMargins.small, 0), }, opacityNone: { opacity: 0, }, rightActionButton: Kb.Styles.platformStyles({ common: { position: 'absolute', right: Kb.Styles.globalMargins.small, top: 10, }, isElectron: Kb.Styles.desktopStyles.windowDraggingClickable, }), titleContainer: { ...Kb.Styles.padding(Kb.Styles.globalMargins.xsmall, 0, Kb.Styles.globalMargins.small), }, whiteBackground: { backgroundColor: theme.white, }, whiteHeaderContainer: Kb.Styles.bottomDivider(theme), }) as const )