Merge pull request #1063 from filecoin-project/@aminejv/fixes

@aminejv/fixes
This commit is contained in:
martinalong 2022-02-07 11:56:38 -08:00 committed by GitHub
commit 42fe6545d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 378 additions and 191 deletions

View File

@ -9,6 +9,7 @@ export const sizes = {
intercomWidget: 60,
sidebar: 416,
filterNavbar: 42,
carouselMobileFooterHeight: 52,
topOffset: 0, //NOTE(martina): Pushes UI down. 16 when there is a persistent announcement banner, 0 otherwise
mobile: 768,
@ -149,8 +150,8 @@ export const zindex = {
sidebar: 5,
modal: 6,
jumper: 7,
tooltip: 8,
cta: 9,
tooltip: 9,
cta: 11,
};
export const font = {

View File

@ -51,6 +51,9 @@ export const useForm = ({
if (event) event(e);
});
const setFormValues = ({ name, value }) =>
setState((prev) => ({ ...prev, values: { ...prev.values, [name]: value } }));
/** ---------- NOTE(amine): Input Handlers ---------- */
const createOnChangeHandler = (type) => (e) => {
const prevValue = state.values[e.target.name];
@ -165,6 +168,7 @@ export const useForm = ({
getFieldProps,
getFormProps,
submitForm: submitAsync,
setFormValues,
values: state.values,
isSubmitting: internal.isSubmitting,
isValidating: internal.isValidating,
@ -527,3 +531,9 @@ export const usePrevious = (value) => {
return ref.current;
};
export const useToggle = () => {
const [isVisible, setVisibility] = React.useState(false);
const toggleVisibility = () => setVisibility((prev) => !prev);
return [isVisible, toggleVisibility];
};

View File

@ -2269,7 +2269,7 @@ export const FileText = (props) => (
/>
<path
d="M9.333 1.333v4h4M10.667 8.667H5.333M10.667 11.333H5.333M6.667 6H5.333"
stroke="#00050A"
stroke="currentColor"
strokeWidth={1.25}
strokeLinecap="round"
strokeLinejoin="round"
@ -2398,7 +2398,7 @@ export const FilePlus = (props) => (
/>
<path
d="M9.333 1.333v4h4M8 12V8M6 10h4"
stroke="#00050A"
stroke="currentColor"
strokeWidth={1.25}
strokeLinecap="round"
strokeLinejoin="round"

View File

@ -94,10 +94,11 @@ const STYLES_HEADER = (theme) => css`
top: 0;
`;
const STYLES_UPLOAD_BUTTON = css`
const STYLES_UPLOAD_BUTTON = (theme) => css`
position: relative;
${Styles.CONTAINER_CENTERED};
background-color: ${Constants.semantic.bgGrayLight};
color: ${theme.semantic.textBlack};
border-radius: 8px;
width: 24px;
height: 24px;
@ -159,7 +160,7 @@ export default function ApplicationHeader({ viewer, page, data, onAction, isMobi
) : (
<UploadOnboarding onAction={onAction} viewer={viewer} isMobile={isMobile}>
<Upload.Provider page={page} data={data} viewer={viewer}>
<Upload.Root data={data} isMobile={isMobile}>
<Upload.Root page={page} data={data} isMobile={isMobile}>
<div css={STYLES_RIGHT}>
<UserActions viewer={viewer} />
</div>

View File

@ -8,11 +8,10 @@ import * as SVG from "~/common/svg";
import * as Styles from "~/common/styles";
import { css } from "@emotion/react";
import { useField, useForm } from "~/common/hooks";
import { Toggle, SignUpPopover, ArrowButton } from "~/components/core/Auth/components";
import { useField, useForm, useIsomorphicLayoutEffect } from "~/common/hooks";
import { Toggle, SignUpPopover, ArrowButton, AuthField } from "~/components/core/Auth/components";
import { AnimateSharedLayout, motion } from "framer-motion";
import Field from "~/components/core/Field";
import { LoaderSpinner } from "~/components/system/components/Loaders";
const STYLES_INITIAL_CONTAINER = css`
display: flex;
@ -41,6 +40,34 @@ const STYLES_LINK_ITEM = (theme) => css`
}
`;
const STYLES_MESSAGE = (theme) => css`
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-top: 16px;
border: 1px solid ${theme.system.white};
background-color: white;
@supports ((-webkit-backdrop-filter: blur(25px)) or (backdrop-filter: blur(25px))) {
background-color: ${theme.semantic.bgBlurWhiteTRN};
backdrop-filter: blur(75px);
}
padding: 8px 12px;
border-radius: 8px;
& > * + * {
margin-left: 16px;
}
`;
const STYLES_MESSAGE_PARAGRAPH = (theme) => css`
font-size: ${theme.typescale.lvlN1};
color: ${theme.system.blue};
`;
const STYLES_MESSAGE_BUTTON = (theme) => css`
${Styles.BUTTON_RESET};
color: ${theme.semantic.textGray};
`;
// NOTE(amine): used to remove content jumping
// when switching between signin/signup in mobile
const STYLES_SPACER = css`
@ -79,12 +106,18 @@ function Initial(
onAction,
});
const [signinMessage, setSigninMessage] = React.useState(null);
const showSigninMessage = (message) => setSigninMessage(message);
const hideSigninMessage = () => setSigninMessage(null);
// NOTE(amine): Signup view form
const {
getFieldProps: getSignupFielProps,
getFormProps: getSigninFormProps,
isSubmitting: isCheckingSignupEmail,
setFormValues: setSignupFormValues,
submitForm: submitSignupForm,
isSubmitting: isCheckingSignupEmail,
values: signupFormValues,
} = useForm({
validateOnBlur: false,
initialValues: { email: initialEmail || "" },
@ -118,9 +151,36 @@ function Initial(
});
// NOTE(amine): Signin view form
const { getFieldProps: getSigninFieldProps, submitField: submitSigninField } = useField({
const {
getFieldProps: getSigninFieldProps,
setFieldValue: setSigninFieldValue,
submitField: submitSigninField,
value: signinFormValue,
isSubmitting: isCheckingSigninEmail,
} = useField({
validateOnBlur: false,
onSubmit: async (emailOrUsername) => goToSigninScene({ emailOrUsername }),
onSubmit: async (emailOrUsername) => {
let response;
if (Validations.email(emailOrUsername)) {
response = await Actions.checkEmail({ email: emailOrUsername });
} else {
response = await Actions.checkUsername({
username: emailOrUsername,
});
}
if (response?.data) {
goToSigninScene({ emailOrUsername });
return;
}
const message = (
<>
There isn't an account associated with this{" "}
{Validations.email(emailOrUsername) ? "email" : "username"}, <br /> please choose sign up
instead.
</>
);
showSigninMessage(message);
},
validate: (emailOrUsername) => {
if (Strings.isEmpty(emailOrUsername)) return "Please enter a username or email";
if (!Validations.username(emailOrUsername) && !Validations.email(emailOrUsername))
@ -129,6 +189,16 @@ function Initial(
initialValue: initialEmail,
});
// NOTE(amine): sync signup and signin values
useIsomorphicLayoutEffect(() => {
if (toggleValue === "signup") {
setSignupFormValues({ name: "email", value: signinFormValue });
} else {
setSigninFieldValue(signupFormValues.email);
}
hideSigninMessage();
}, [toggleValue]);
// NOTE(amine): allow other components to submit this form via a ref
React.useImperativeHandle(ref, () => ({
submitSignupForm,
@ -168,9 +238,21 @@ function Initial(
onChange={handleToggleChange}
/>
</div>
{signinMessage && (
<div css={STYLES_MESSAGE}>
<System.P1 css={STYLES_MESSAGE_PARAGRAPH}>{signinMessage}</System.P1>
<button
css={STYLES_MESSAGE_BUTTON}
style={{ marginTop: 4 }}
onClick={hideSigninMessage}
>
<SVG.Dismiss height={16} width={16} />
</button>
</div>
)}
{toggleValue === "signup" ? (
<form {...getSigninFormProps()}>
<Field
<AuthField
autoFocus
label="Sign up with email"
placeholder="Email"
@ -199,18 +281,34 @@ function Initial(
</AnimateSharedLayout>
</form>
) : (
<Field
autoFocus
label="Email address or username"
placeholder="Email/username"
icon={ArrowButton}
name="email/username"
type="text"
full
{...getSigninFieldProps()}
// NOTE(amine): the input component internally is using 16px margin top
containerStyle={{ marginTop: "4px" }}
/>
<AnimateSharedLayout>
<motion.div layoutId="auth_signin_field">
<AuthField
autoFocus
label="Email address or username"
placeholder="Email/username"
icon={
isCheckingSigninEmail
? ({ style, ...props }) => (
<div
style={{ width: 20, height: 20, ...style }}
css={Styles.CONTAINER_CENTERED}
{...props}
>
<LoaderSpinner height="16px" />
</div>
)
: ArrowButton
}
name="email/username"
type="text"
full
{...getSigninFieldProps()}
// NOTE(amine): the input component internally is using 16px margin top
containerStyle={{ marginTop: "4px" }}
/>
</motion.div>
</AnimateSharedLayout>
)}
{showTermsAndServices && (

View File

@ -5,14 +5,12 @@ import * as Actions from "~/common/actions";
import * as Utilities from "~/common/utilities";
import * as SVG from "~/common/svg";
import Field from "~/components/core/Field";
import { AnimateSharedLayout, motion } from "framer-motion";
import { P1 } from "~/components/system";
import { useForm } from "~/common/hooks";
import { css } from "@emotion/react";
import { SignUpPopover, Verification } from "~/components/core/Auth/components";
import { SignUpPopover, Verification, AuthField } from "~/components/core/Auth/components";
const STYLES_BACK_BUTTON = css`
background: none;
@ -110,7 +108,7 @@ export default function ResetPassword({
return (
<SignUpPopover title={<>Enter new password</>}>
<form {...getNewPasswordFormProps()} style={{ marginTop: 72 }}>
<Field
<AuthField
autoFocus
containerStyle={{ marginTop: 16 }}
placeholder="New password"
@ -153,7 +151,7 @@ export default function ResetPassword({
}
>
<form {...getFormProps()} style={{ marginTop: 72 }}>
<Field
<AuthField
autoFocus
containerStyle={{ marginTop: 16 }}
placeholder="Email"

View File

@ -6,13 +6,10 @@ import * as Constants from "~/common/constants";
import * as SVG from "~/common/svg";
import * as Styles from "~/common/styles";
import Field from "~/components/core/Field";
import { P1 } from "~/components/system";
import { AnimateSharedLayout, motion } from "framer-motion";
import { useForm } from "~/common/hooks";
import { css } from "@emotion/react";
import { SignUpPopover, Verification } from "~/components/core/Auth/components";
import { SignUpPopover, Verification, AuthField } from "~/components/core/Auth/components";
const STYLES_BACK_BUTTON = css`
color: ${Constants.semantic.textGrayDark};
@ -69,15 +66,8 @@ const STYLES_MESSAGE_PARAGRAPH = (theme) => css`
`;
const STYLES_MESSAGE_BUTTON = (theme) => css`
background: none;
border: none;
padding: 0;
margin: 0;
svg {
color: ${theme.semantic.textGrayDark};
height: 16px;
width: 16px;
}
${Styles.BUTTON_RESET};
color: ${theme.semantic.textGray};
`;
const handleValidation = ({ password }, errors) => {
@ -155,7 +145,7 @@ export default function Signin({
return (
<SignUpPopover title={`Please add an email address for ${emailOrUsername}`}>
<form {...getEmailFormProps()} style={{ marginTop: 72 }}>
<Field
<AuthField
autoFocus
containerStyle={{ marginTop: 16 }}
placeholder="Email"
@ -186,13 +176,13 @@ export default function Signin({
<form {...getFormProps()} style={{ marginTop: message ? 24 : 41 }}>
{message && (
<div css={STYLES_MESSAGE}>
<P1 css={STYLES_MESSAGE_PARAGRAPH}>{message}</P1>
<button css={STYLES_MESSAGE_BUTTON} onClick={clearMessages}>
<SVG.Dismiss />
<System.P1 css={STYLES_MESSAGE_PARAGRAPH}>{message}</System.P1>
<button css={STYLES_MESSAGE_BUTTON} style={{ marginTop: 4 }} onClick={clearMessages}>
<SVG.Dismiss height={16} width={16} />
</button>
</div>
)}
<Field
<AuthField
autoFocus
containerStyle={{ marginTop: message ? 24 : 16 }}
placeholder="Password"
@ -215,7 +205,7 @@ export default function Signin({
Sign in
</System.ButtonPrimary>
<button type="button" onClick={goToResetPassword} css={STYLES_FORGOT_PASSWORD_BUTTON}>
<P1 css={Styles.H5}> Forgot Password?</P1>
<System.P1 css={Styles.H5}> Forgot Password?</System.P1>
</button>
</motion.div>
</AnimateSharedLayout>
@ -223,7 +213,7 @@ export default function Signin({
<button css={STYLES_BACK_BUTTON} type="button" onClick={goBack}>
<span>
<SVG.RightArrow height="16px" style={{ transform: "rotate(180deg)" }} />
<P1 css={Styles.H5}>Back</P1>
<System.P1 css={Styles.H5}>Back</System.P1>
</span>
</button>
</SignUpPopover>

View File

@ -4,12 +4,15 @@ import * as Validations from "~/common/validations";
import * as SVG from "~/common/svg";
import * as Actions from "~/common/actions";
import Field from "~/components/core/Field";
import { AnimateSharedLayout, motion } from "framer-motion";
import { LoaderSpinner } from "~/components/system/components/Loaders";
import { useForm } from "~/common/hooks";
import { SignUpPopover, Verification, AuthCheckBox } from "~/components/core/Auth/components";
import {
SignUpPopover,
Verification,
AuthCheckBox,
AuthField,
} from "~/components/core/Auth/components";
const useSignup = () => {
const [scene, setScene] = React.useState("verification");
@ -94,7 +97,7 @@ export default function Signup({ verifyEmail, createUser, resendEmailVerificatio
<SignUpPopover title="Create an account">
<AnimateSharedLayout>
<form {...getFormProps()}>
<Field
<AuthField
autoFocus
containerStyle={{ marginTop: 46 }}
placeholder="Username"
@ -122,7 +125,7 @@ export default function Signup({ verifyEmail, createUser, resendEmailVerificatio
/>
<motion.div layout>
<Field
<AuthField
containerStyle={{ marginTop: 16 }}
placeholder="Password"
type={showPassword ? "text" : "password"}

View File

@ -4,12 +4,15 @@ import * as Validations from "~/common/validations";
import * as System from "~/components/system";
import * as Strings from "~/common/strings";
import Field from "~/components/core/Field";
import { AnimateSharedLayout, motion } from "framer-motion";
import { useForm } from "~/common/hooks";
import { SignUpPopover, Verification, AuthCheckBox } from "~/components/core/Auth/components";
import {
SignUpPopover,
Verification,
AuthCheckBox,
AuthField,
} from "~/components/core/Auth/components";
const useTwitterLinking = () => {
// NOTE(amine): can be either 'account' | 'email' | 'verificatiom'
@ -97,7 +100,7 @@ export default function TwitterLinking({
<div>
<SignUpPopover title={`Please add an email address for ${username}`}>
<form {...getEmailFormProps()} style={{ marginTop: 72 }}>
<Field
<AuthField
autoFocus
containerStyle={{ marginTop: 16 }}
placeholder="Email"
@ -127,7 +130,7 @@ export default function TwitterLinking({
return (
<SignUpPopover title="Create an account">
<form {...getFormProps()}>
<Field
<AuthField
autoFocus
containerStyle={{ marginTop: 41 }}
placeholder="Username"
@ -137,7 +140,7 @@ export default function TwitterLinking({
{...getFieldProps("username")}
/>
<AnimateSharedLayout>
<Field
<AuthField
containerStyle={{ marginTop: 16 }}
containerAs={MotionLayout}
errorAs={MotionLayout}

View File

@ -6,14 +6,17 @@ import * as Actions from "~/common/actions";
import * as Styles from "~/common/styles";
import * as Strings from "~/common/strings";
import Field from "~/components/core/Field";
import { AnimateSharedLayout, motion } from "framer-motion";
import { LoaderSpinner } from "~/components/system/components/Loaders";
import { css } from "@emotion/react";
import { useForm } from "~/common/hooks";
import { SignUpPopover, Verification, AuthCheckBox } from "~/components/core/Auth/components";
import {
SignUpPopover,
Verification,
AuthCheckBox,
AuthField,
} from "~/components/core/Auth/components";
const STYLES_LINK = (theme) => css`
padding: 0;
@ -124,7 +127,7 @@ export default function TwitterSignup({
return (
<SignUpPopover title="Create an account">
<form {...getFormProps()}>
<Field
<AuthField
autoFocus
containerStyle={{ marginTop: 41 }}
placeholder="Username"
@ -150,7 +153,7 @@ export default function TwitterSignup({
full
/>
<AnimateSharedLayout>
<Field
<AuthField
containerStyle={{ marginTop: 16 }}
containerAs={MotionLayout}
errorAs={MotionLayout}

View File

@ -0,0 +1,15 @@
import * as React from "react";
import Field from "~/components/core/Field";
import { css } from "@emotion/react";
const STYLES_INPUT = (theme) => css`
background-color: rgba(242, 242, 247, 0.5);
box-shadow: ${theme.shadow.lightLarge};
border-radius: 12px;
`;
export default function AuthField({ css, ...props }) {
return <Field inputCss={[STYLES_INPUT, css]} {...props} />;
}

View File

@ -1,16 +1,13 @@
import * as React from "react";
import * as System from "~/components/system";
import * as SVG from "~/common/svg";
import * as Validations from "~/common/validations";
import * as Styles from "~/common/styles";
import Field from "~/components/core/Field";
import { AnimateSharedLayout, motion } from "framer-motion";
import { LoaderSpinner } from "~/components/system/components/Loaders";
import { css } from "@emotion/react";
import { useField } from "~/common/hooks";
import { SignUpPopover, ArrowButton } from "~/components/core/Auth/components";
import { SignUpPopover, ArrowButton, AuthField } from "~/components/core/Auth/components";
const STYLES_HELPER = (theme) => css`
text-align: center;
@ -101,16 +98,17 @@ export default function Verification({ onVerify, title = DEFAULT_TITLE, onResend
return (
<SignUpPopover logoStyle={{ width: 56, height: 56 }} title={title}>
<div style={{ marginTop: 40 }}>
<Field
<AuthField
autoFocus
label="Enter the 6 digit code sent to your email"
full
icon={
isSubmitting
? () => (
? ({ style, ...props }) => (
<div
style={{ width: 24, height: 24, marginRight: 4 }}
style={{ width: 20, height: 20, ...style }}
css={Styles.CONTAINER_CENTERED}
{...props}
>
<LoaderSpinner height="16px" />
</div>

View File

@ -2,5 +2,6 @@ export { default as Toggle } from "~/components/core/Auth/components/Toggle";
export { default as SignUpPopover } from "~/components/core/Auth/components/SignUpPopover";
export { default as Verification } from "~/components/core/Auth/components/Verification";
export { default as AuthCheckBox } from "~/components/core/Auth/components/AuthCheckBox";
export { default as AuthField } from "~/components/core/Auth/components/AuthField";
export { default as ArrowButton } from "~/components/core/Auth/components/ArrowButton";
export { default as AuthWrapper } from "~/components/core/Auth/components/AuthWrapper";

View File

@ -103,7 +103,9 @@ export default class CTATransition extends React.Component {
const currentURL = Strings.getCurrentURL(this.props.page?.params);
this.props.onAction({
type: "NAVIGATE",
href: `/_/auth?tab=signin&email=${emailOrUsername}&redirect=${encodeURI(currentURL)}`,
href: `/_/auth?tab=signin&email=${encodeURIComponent(emailOrUsername)}&redirect=${encodeURI(
currentURL
)}`,
});
this._handleClose();
};
@ -112,7 +114,9 @@ export default class CTATransition extends React.Component {
const currentURL = Strings.getCurrentURL(this.props.page?.params);
this.props.onAction({
type: "NAVIGATE",
href: `/_/auth?tab=signup&email=${email}&redirect=${encodeURI(currentURL)}`,
href: `/_/auth?tab=signup&email=${encodeURIComponent(email)}&redirect=${encodeURI(
currentURL
)}`,
});
this._handleClose();
};

View File

@ -1,5 +1,4 @@
import * as React from "react";
import * as SVG from "~/common/svg";
import { P1 } from "~/components/system/components/Typography";
import { Input } from "~/components/system";
@ -22,14 +21,13 @@ const STYLES_PASSWORD_VALIDATIONS = (theme) => css`
border-radius: 12px;
`;
const STYLES_PASSWORD_VALIDATION = (theme) =>
css`
display: flex;
align-items: center;
& > * + * {
margin-left: 8px;
}
`;
const STYLES_PASSWORD_VALIDATION = css`
display: flex;
align-items: center;
& > * + * {
margin-left: 8px;
}
`;
const STYLES_CIRCLE = (theme) => css`
height: 8px;
@ -42,29 +40,11 @@ const STYLES_CIRCLE_SUCCESS = (theme) => css`
border: 1.25px solid ${theme.system.green};
`;
const STYLES_INPUT = (theme) => css`
background-color: rgba(242, 242, 247, 0.5);
box-shadow: ${theme.shadow.lightLarge};
border-radius: 12px;
&::placeholder {
color: ${theme.semantic.textGrayDark};
}
`;
const STYLES_INPUT_ERROR = (theme) => css`
background-color: rgba(242, 242, 247, 0.5);
border: 1px solid ${theme.system.red};
border-radius: 8px;
&::placeholder {
color: ${theme.semantic.textGrayDark};
}
box-shadow: 0 0 0 1px ${theme.system.red};
`;
const STYLES_INPUT_SUCCESS = (theme) => css`
background-color: rgba(242, 242, 247, 0.5);
border: 1px solid ${theme.system.green};
border-radius: 8px;
&::placeholder {
color: ${theme.semantic.textGrayDark};
}
box-shadow: 0 0 0 1px ${theme.system.green};
`;
const PasswordValidations = ({ validations }) => {
@ -103,15 +83,16 @@ export default function Field({
validations,
errorAs,
containerAs,
inputCss,
...props
}) {
const showError = touched && error;
const showSuccess = touched && !error;
const STYLES = React.useMemo(() => {
const STYLES_VALIDATIONS = React.useMemo(() => {
if (showError) return STYLES_INPUT_ERROR;
if (showSuccess) return STYLES_INPUT_SUCCESS;
return STYLES_INPUT;
return null;
}, [touched, error]);
const ContainerComponent = containerAs || "div";
@ -119,7 +100,7 @@ export default function Field({
return (
<div>
<ContainerComponent>
<Input inputCss={STYLES} {...props} />
<Input inputCss={[inputCss, STYLES_VALIDATIONS]} {...props} />
</ContainerComponent>
{props.name === "password" && validations ? (
<PasswordValidations validations={validations} />

View File

@ -67,11 +67,11 @@ const STYLES_FILTERS_GROUP = css`
`;
const STYLES_ICON_CONTAINER = css`
height: 20px;
width: 20px;
padding: 2px;
display: flex;
justify-content: center;
align-items: center;
color: inherit;
`;
const FilterButton = React.forwardRef(({ children, Icon, image, isSelected, ...props }, ref) => (
@ -83,7 +83,7 @@ const FilterButton = React.forwardRef(({ children, Icon, image, isSelected, ...p
</div>
) : null}
{image ? image : null}
<Typography.P2 as="span" nbrOflines={1} style={{ marginLeft: 6 }}>
<Typography.P2 as="span" nbrOflines={1} style={{ marginLeft: 6, color: "inherit" }}>
{children}
</Typography.P2>
</span>

View File

@ -12,6 +12,12 @@ import { css } from "@emotion/react";
* Popup trigger
* -----------------------------------------------------------------------------------------------*/
const STYLES_POPUP_TRIGGER = (theme) => css`
${Styles.HORIZONTAL_CONTAINER_CENTERED};
perspective: 1000px;
color: ${theme.semantic.textBlack};
`;
export function PopupTrigger({ children, isMobile, ...props }) {
const [{ sidebarState, popupState }, { hidePopup, togglePopup }] = useFilterContext();
@ -26,11 +32,13 @@ export function PopupTrigger({ children, isMobile, ...props }) {
return (
<System.ButtonPrimitive
onClick={togglePopup}
css={Styles.HORIZONTAL_CONTAINER_CENTERED}
css={STYLES_POPUP_TRIGGER}
//NOTE(amine): fix to a bug where elements using rotate disappear in safari https://stackoverflow.com/questions/22621544/webkit-transform-breaks-z-index-on-safari
{...props}
>
{children}
<motion.div
style={{ color: "inherit" }}
initial={{ rotateX: popupState.isVisible ? 0 : 180 }}
animate={{ rotateX: popupState.isVisible ? 0 : 180 }}
>

View File

@ -5,6 +5,8 @@ import * as Search from "~/components/core/Search";
import * as Filters from "~/components/core/Filter/Filters";
import * as Constants from "~/common/constants";
import WebsitePrototypeWrapper from "~/components/core/WebsitePrototypeWrapper";
import { css } from "@emotion/react";
import { Provider } from "~/components/core/Filter/Provider";
import { Sidebar, SidebarTrigger } from "~/components/core/Filter/Sidebar";
@ -38,6 +40,8 @@ function Title({ page, data }) {
if (page.id === "NAV_DATA") return "Recent";
if (page.id === "NAV_SLATE" && data?.slatename) return "# " + data?.slatename;
if (page.id === "NAV_PROFILE") return "@ " + data.username;
if (page.id === "NAV_SETTINGS") return page.name;
if (page.id === "NAV_API") return page.name;
return null;
}, [page, data, isFetchingResults, isSearching]);
@ -147,7 +151,12 @@ export default function Filter({
if (disabled) {
return showSearchResult ? (
<Search.Content viewer={viewer} page={page} onAction={onAction} isMobile={isMobile} />
<WebsitePrototypeWrapper
title={`${page.pageTitle} • Slate`}
url={`${Constants.hostname}${page.pathname}`}
>
<Search.Content viewer={viewer} page={page} onAction={onAction} isMobile={isMobile} />
</WebsitePrototypeWrapper>
) : (
children
);
@ -169,7 +178,7 @@ export default function Filter({
>
<div css={STYLES_NAVBAR}>
<div css={STYLES_NAVBAR_BACKGROUND} />
<div css={STYLES_FILTER_POPUP_WRAPPER}>
<div css={STYLES_FILTER_POPUP_WRAPPER} style={{ perspective: "1000px" }}>
<Popup
viewer={viewer}
onAction={onAction}
@ -210,7 +219,12 @@ export default function Filter({
/>
<div style={{ flexGrow: 1 }}>
{showSearchResult ? (
<Search.Content viewer={viewer} page={page} onAction={onAction} isMobile={isMobile} />
<WebsitePrototypeWrapper
title={`${page.pageTitle} • Slate`}
url={`${Constants.hostname}${page.pathname}`}
>
<Search.Content viewer={viewer} page={page} onAction={onAction} isMobile={isMobile} />
</WebsitePrototypeWrapper>
) : (
children
)}

View File

@ -63,6 +63,7 @@ const STYLES_MOBILE_SHOW_CONTROLS = (theme) => css`
padding: 8px;
border-radius: 8px;
box-shadow: 0 0 0 1px ${theme.system.grayLight5}, ${theme.shadow.lightLarge};
color: ${theme.semantic.textBlack};
background-color: ${theme.semantic.bgWhite};
@supports ((-webkit-backdrop-filter: blur(25px)) or (backdrop-filter: blur(25px))) {

View File

@ -14,6 +14,7 @@ const STYLES_BUTTON = (theme) => css`
border-radius: 8px;
box-shadow: 0 0 0 1px ${theme.system.grayLight5}, ${theme.shadow.lightLarge};
transition: box-shadow 0.3s;
color: ${theme.semantic.textBlack};
:hover {
box-shadow: 0 0 0 1px ${theme.system.pink}, ${theme.shadow.lightLarge};
}

View File

@ -13,6 +13,7 @@ const STYLES_BUTTON_HOVER = (theme) => css`
border-radius: 8px;
box-shadow: 0 0 0 1px ${theme.system.grayLight5}, ${theme.shadow.lightLarge};
transition: box-shadow 0.3s;
color: ${theme.semantic.textBlack};
:hover {
box-shadow: 0 0 0 1px ${theme.system.pink}, ${theme.shadow.lightLarge};
}

View File

@ -11,6 +11,7 @@ const STYLES_BUTTON = (theme) => css`
border-radius: 8px;
box-shadow: 0 0 0 1px ${theme.system.grayLight5}, ${theme.shadow.lightLarge};
transition: box-shadow 0.3s;
color: ${theme.semantic.textBlack};
:hover {
box-shadow: 0 0 0 1px ${theme.system.blue}, ${theme.shadow.lightLarge};
}

View File

@ -8,6 +8,7 @@ import { Input as InputPrimitive } from "~/components/system/components/Input";
import { useSearchStore } from "~/components/core/Search/store";
import { FileTypeGroup } from "~/components/core/FileTypeIcon";
import { Link } from "~/components/core/Link";
import { useIsomorphicLayoutEffect } from "~/common/hooks";
import DataView from "~/components/core/DataView";
import CollectionPreviewBlock from "~/components/core/CollectionPreviewBlock";
@ -126,6 +127,12 @@ function Input({ viewer, data, page, onAction }) {
const handleChange = useDebouncedOnChange({ setQuery, handleSearch });
// NOTE(amine): cleanup input's value when query is empty.
const inputRef = React.useRef();
useIsomorphicLayoutEffect(() => {
if (!query && inputRef.current) inputRef.current.value = "";
}, [query]);
return (
<div
style={{
@ -140,6 +147,7 @@ function Input({ viewer, data, page, onAction }) {
}}
>
<InputPrimitive
ref={inputRef}
full
containerStyle={{ height: "100%" }}
inputCss={STYLES_SEARCH_COMPONENT}

View File

@ -248,7 +248,7 @@ export function MobileUploadJumper({ data }) {
</div>
<MobileJumper.Divider />
<div style={{ padding: "40px 16px", textAlign: "center" }}>
<SVG.Airplay color="textBlack" />
<SVG.Airplay style={{ color: Constants.semantic.textGrayDark }} />
<System.H5 as="p" color="textGrayDark" style={{ marginTop: 6, textAlign: "center" }}>
open Slate on desktop to upload files
</System.H5>

View File

@ -28,6 +28,14 @@ const STYLES_POPUP_WRAPPER = (theme) => css`
bottom: 24px;
right: 24px;
z-index: ${theme.zindex.tooltip};
border-radius: 12px;
box-shadow: ${theme.shadow.lightLarge};
`;
const STYLES_POPUP_CAROUSEL_POSITION = (theme) => css`
@media (max-width: ${theme.sizes.mobile}px) {
bottom: ${Constants.sizes.carouselMobileFooterHeight + 16}px;
}
`;
const STYLES_DISMISS_BUTTON = (theme) => css`
@ -59,7 +67,7 @@ const STYLES_POPUP_CONTENT = css`
const useUploadPopup = ({ totalFilesSummary }) => {
const {
state: { isFinished },
state: { isFinished, isUploading },
handlers: { resetUploadState },
} = useUploadStore();
@ -75,12 +83,11 @@ const useUploadPopup = ({ totalFilesSummary }) => {
const timeoutRef = React.useRef();
//NOTE(amine): show the upload summary, then automatically collapse the upload summary after 3 seconds
const isStarted = totalFilesSummary.total > 0;
React.useEffect(() => {
if (!isStarted) return;
if (!isUploading) return;
expandUploadSummary();
timeoutRef.current = setTimeout(collapseUploadSummary, 3000);
}, [isStarted]);
}, [isUploading]);
/**
* NOTE(amine): show the upload summary when a file fails to upload or is added to the queue,
@ -89,7 +96,7 @@ const useUploadPopup = ({ totalFilesSummary }) => {
const isSummaryExpandedRef = React.useRef();
isSummaryExpandedRef.current = popupState.isSummaryExpanded;
React.useEffect(() => {
if (isSummaryExpandedRef.current || totalFilesSummary.total === 0) return;
if (isSummaryExpandedRef.current || totalFilesSummary.total === 0 || !isUploading) return;
expandUploadSummary();
clearTimeout(timeoutRef.current);
timeoutRef.current = setTimeout(collapseUploadSummary, 3000);
@ -160,7 +167,7 @@ const useUploadSummary = ({ fileLoading }) =>
};
}, [fileLoading]);
export function Popup({ isMobile }) {
export function Popup({ page, isMobile }) {
const {
state: { isFinished, fileLoading },
handlers: { resetUploadState },
@ -175,11 +182,12 @@ export function Popup({ isMobile }) {
{ hideUploadPopup, expandUploadSummary, collapseUploadSummary, cancelAutoCollapseOnMouseEnter },
] = useUploadPopup({ totalFilesSummary });
const isGlobalCarouselOpen = !!page.params.id;
return (
<AnimatePresence>
{popupState.isVisible ? (
<motion.div
css={STYLES_POPUP_WRAPPER}
css={[STYLES_POPUP_WRAPPER, isGlobalCarouselOpen && STYLES_POPUP_CAROUSEL_POSITION]}
initial={{ opacity: 0, y: 0 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
@ -190,9 +198,9 @@ export function Popup({ isMobile }) {
<AnimatePresence>
{popupState.isSummaryExpanded ? (
<motion.div
initial={{ y: 400 }}
animate={{ y: 0 }}
exit={{ y: 400 }}
initial={{ willChange: "height", height: 0 }}
animate={{ height: "auto" }}
exit={{ height: 0 }}
transition={{ type: "spring", stiffness: 170, damping: 26 }}
onMouseEnter={cancelAutoCollapseOnMouseEnter}
>
@ -304,7 +312,11 @@ function Header({ totalFilesSummary, popupState, expandUploadSummary, collapseUp
aria-label="Upload Summary"
onClick={popupState.isSummaryExpanded ? collapseUploadSummary : expandUploadSummary}
>
<span css={Styles.HORIZONTAL_CONTAINER_CENTERED}>
<span
css={Styles.HORIZONTAL_CONTAINER_CENTERED}
//NOTE(amine): fix to a bug where elements using rotate disappear in safari https://stackoverflow.com/questions/22621544/webkit-transform-breaks-z-index-on-safari
style={{ perspective: "1000px" }}
>
<System.P2 color="textBlack" style={{ width: "5ch" }}>
{uploadProgress}%
</System.P2>

View File

@ -14,13 +14,13 @@ import DropIndicator from "~/components/core/Upload/DropIndicator";
/* -------------------------------------------------------------------------------------------------
* Root
* -----------------------------------------------------------------------------------------------*/
const Root = ({ children, data, isMobile }) => {
const Root = ({ children, page, data, isMobile }) => {
return (
<>
{children}
{isMobile ? <MobileUploadJumper data={data} /> : <UploadJumper data={data} />}
<ModalPortal>
<Popup isMobile={isMobile} />
<Popup page={page} isMobile={isMobile} />
<DropIndicator data={data} />
</ModalPortal>
</>

View File

@ -128,10 +128,13 @@ const STYLES_CODE_BLOCK = css`
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
border-radius: 4px;
padding: 20px 24px;
width: 100%;
display: flex;
overflow-x: auto;
* {
white-space: pre-wrap;
overflow-wrap: break-word;
word-break: break-word;
::-webkit-scrollbar {
-webkit-appearance: none;
width: 0;
@ -193,7 +196,7 @@ const STYLES_LINE = css`
justify-content: space-between;
`;
const STYLES_TOPBAR = css`
const STYLES_TOPBAR = (theme) => css`
display: flex;
justify-content: space-between;
align-items: center;
@ -204,6 +207,11 @@ const STYLES_TOPBAR = css`
border-top-left-radius: 4px;
margin-bottom: -4px;
box-sizing: border-box;
@media (max-width: ${theme.sizes.mobile}px) {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
`;
const STYLES_TOPBAR_PLAIN = css`
@ -220,6 +228,7 @@ const STYLES_TOPBAR_PLAIN = css`
`;
const STYLES_TOPBAR_TITLE = css`
flex-grow: 1;
text-transform: uppercase;
color: ${Constants.semantic.textGray};
font-size: ${Constants.typescale.lvlN1};
@ -229,7 +238,6 @@ const STYLES_TOPBAR_TITLE = css`
`;
const STYLES_LANGSWITCHER = css`
margin-left: auto;
display: flex;
align-items: center;
flex-shrink: 0;

View File

@ -50,7 +50,7 @@ const VisitLinkButton = ({ file }) => {
type="link"
>
<LinkIcon file={file} width={16} height={16} style={{ marginRight: 4 }} key={file.id} />
<span style={{ whiteSpace: "nowrap" }}>Visit site</span>
<span style={{ whiteSpace: "nowrap", color: "inherit" }}>Visit site</span>
</System.ButtonTertiary>
);
};
@ -77,7 +77,8 @@ export const useSaveHandler = ({ file, viewer, onAction }) => {
}
if (isSaved) {
const fileLibraryURL = `/_/data?id=${file.id}`;
const fileId = viewer.library.find((item) => item.cid === file.cid).id;
const fileLibraryURL = `/_/data?id=${fileId}`;
onAction({
type: "NAVIGATE",
href: fileLibraryURL,
@ -160,6 +161,7 @@ const STYLES_HEADER_WRAPPER = (theme) => css`
const STYLES_ACTION_BUTTON = (theme) => css`
padding: 8px;
border-radius: 8px;
color: ${theme.semantic.textGrayDark};
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: ${theme.semantic.bgGrayLight};
@ -565,8 +567,6 @@ function CarouselHeaderMobile({
);
}
const MOBILE_FOOTER_HEIGHT = 52;
const STYLES_CAROUSEL_MOBILE_FOOTER = (theme) => css`
${Styles.HORIZONTAL_CONTAINER_CENTERED};
position: fixed;
@ -577,7 +577,7 @@ const STYLES_CAROUSEL_MOBILE_FOOTER = (theme) => css`
padding: 8px 16px;
border-top: 1px solid ${theme.semantic.borderGrayLight};
color: ${theme.semantic.textGrayDark};
height: ${MOBILE_FOOTER_HEIGHT}px;
height: ${Constants.sizes.carouselMobileFooterHeight}px;
background-color: ${theme.semantic.bgWhite};
@supports ((-webkit-backdrop-filter: blur(15px)) or (backdrop-filter: blur(15px))) {
@ -637,7 +637,7 @@ function CarouselFooterMobile({ file, onAction, external, isOwner, data, viewer
<AnimatePresence>
{isEditInfoVisible && (
<Jumpers.EditInfoMobile
footerStyle={{ bottom: MOBILE_FOOTER_HEIGHT }}
footerStyle={{ bottom: Constants.sizes.carouselMobileFooterHeight }}
file={file}
onClose={hideEditInfo}
/>
@ -773,6 +773,7 @@ const STYLES_CONTROLS_BUTTON = (theme) => css`
border: 1px solid ${theme.semantic.borderGrayLight};
padding: 10px;
box-shadow: ${theme.shadow.lightMedium};
color: ${theme.semantic.textGrayDark};
svg {
display: block;
}

View File

@ -285,6 +285,7 @@ const STYLES_APPLIED_SLATE_BUTTON = (theme) => css`
background-color: ${theme.semantic.bgWhite};
border: 1px solid ${theme.semantic.borderGrayLight};
box-shadow: ${theme.shadow.lightSmall};
color: ${theme.semantic.textBlack};
`;
const STYLES_APPLIED_COLOR_TEXTBLACK = (theme) => css`
@ -423,8 +424,9 @@ const STYLES_SLATES_MENU_BUTTON_SELECTED = (theme) => css`
background-color: ${theme.semantic.bgGrayLight4};
`;
const STYLES_SLATES_MENU_BUTTON = css`
const STYLES_SLATES_MENU_BUTTON = (theme) => css`
${Styles.HORIZONTAL_CONTAINER_CENTERED};
color: ${theme.semantic.textBlack};
justify-content: space-between;
position: relative;
padding: 9px 8px 11px;
@ -459,9 +461,9 @@ const STYLES_SLATES_MENU_BUTTON_BLUE = (theme) => css`
}
`;
const STYLES_SLATES_MENU_BUTTON_TEXTBLACK = (theme) => css`
color: ${theme.system.textBlack};
color: ${theme.semantic.textBlack};
&:hover {
color: ${theme.system.textBlack};
color: ${theme.semantic.textBlack};
}
`;
@ -486,21 +488,21 @@ const ComboboxSlatesMenuButton = ({
index={index}
{...props}
>
<div>
{hasPublicIcon && (
<div style={{ position: "absolute", padding: "2px", left: "8px", top: "9x" }}>
<SVG.Users width={16} height={16} />
</div>
)}
<System.H5
as="span"
nbrOflines={isCreateAction ? 2 : 1}
title={children}
style={{ marginLeft: 32, maxWidth: "46ch" }}
{hasPublicIcon && (
<div
style={{ position: "absolute", color: "inherit", padding: "2px", left: "8px", top: "9x" }}
>
{children}
</System.H5>
</div>
<SVG.Users width={16} height={16} />
</div>
)}
<System.H5
as="span"
nbrOflines={isCreateAction ? 2 : 1}
title={children}
style={{ marginLeft: 32, maxWidth: "46ch", color: "inherit" }}
>
{children}
</System.H5>
{!isCreateAction && isSelected && (
<div css={Styles.HORIZONTAL_CONTAINER_CENTERED} style={{ marginLeft: "auto" }}>
<System.P3 color="textGrayDark">{isSlateApplied ? "remove tag" : "apply tag"}</System.P3>

View File

@ -228,8 +228,11 @@ function CoverImageUpload({ file, viewer, isMobile, isFileOwner }) {
onChange={handleInputChange}
tabIndex="-1"
/>
<SVG.UploadCloud width={16} />
<System.P3 style={{ maxWidth: 140, textAlign: "center", marginTop: 8 }}>
<SVG.UploadCloud style={{ color: Constants.semantic.textBlack }} width={16} />
<System.P3
color="textBlack"
style={{ maxWidth: 140, textAlign: "center", marginTop: 8 }}
>
{isMobile
? "Select an image as object preview"
: "Drop or select an image as object preview"}
@ -288,7 +291,7 @@ function FileMetadata({ file, ...props }) {
style={{ marginTop: 6, padding: "4px 0px", justifyContent: "space-between" }}
>
<System.P3 color="textGray">Type</System.P3>
<System.P3>{Strings.capitalize(file.type)}</System.P3>
<System.P3 color="textBlack">{Strings.capitalize(file.type)}</System.P3>
</div>
<System.Divider
color="borderGrayLight4"
@ -300,7 +303,7 @@ function FileMetadata({ file, ...props }) {
style={{ padding: "4px 0px", justifyContent: "space-between" }}
>
<System.P3 color="textGray">Size</System.P3>
<System.P3>{Strings.bytesToSize(file.size, 0)}</System.P3>
<System.P3 color="textBlack">{Strings.bytesToSize(file.size, 0)}</System.P3>
</div>
{Validations.isPreviewableImage(file?.type || "") ? (
<>
@ -314,7 +317,7 @@ function FileMetadata({ file, ...props }) {
style={{ padding: "4px 0px", justifyContent: "space-between" }}
>
<System.P3 color="textGray">Dimension</System.P3>
<System.P3>
<System.P3 color="textBlack">
<ImageDimension file={file} />
</System.P3>
</div>
@ -330,7 +333,7 @@ function FileMetadata({ file, ...props }) {
style={{ padding: "4px 0px", justifyContent: "space-between" }}
>
<System.P3 color="textGray">Created</System.P3>
<System.P3>{Utilities.formatDateToString(file.createdAt)}</System.P3>
<System.P3 color="textBlack">{Utilities.formatDateToString(file.createdAt)}</System.P3>
</div>
<System.Divider
color="borderGrayLight4"
@ -346,6 +349,7 @@ function FileMetadata({ file, ...props }) {
>
<System.P3 color="textGray">CID</System.P3>
<System.P3
color="textBlack"
style={{
wordBreak: "break-all",
textAlign: "right",

View File

@ -19,6 +19,7 @@ const STYLES_SHARING_BUTTON = (theme) => css`
padding: 9px 8px 11px;
border-radius: 12px;
width: 100%;
color: ${theme.semantic.textBlack};
:hover,
:active {
background-color: ${theme.semantic.bgGrayLight};
@ -26,6 +27,9 @@ const STYLES_SHARING_BUTTON = (theme) => css`
:hover {
color: ${theme.semantic.textBlack};
}
* {
color: inherit;
}
@media (max-width: ${theme.sizes.mobile}px) {
padding: 9px 0px 11px;
@ -63,21 +67,29 @@ function FileSharingButtons({ file, data, viewer }) {
return (
<>
<System.ButtonPrimitive css={STYLES_SHARING_BUTTON} onClick={handleTwitterSharing} autoFocus>
<SVG.Twitter width={20} />
<div style={{ padding: 2 }}>
<SVG.Twitter width={16} height={16} />
</div>
<System.P2 style={{ marginLeft: 12 }}>Share via Twitter</System.P2>
</System.ButtonPrimitive>
<System.ButtonPrimitive css={STYLES_SHARING_BUTTON} onClick={handleEmailSharing}>
<SVG.Mail width={20} />
<div style={{ padding: 2 }}>
<SVG.Mail width={16} height={16} />
</div>
<System.P2 style={{ marginLeft: 12 }}>Share via email </System.P2>
</System.ButtonPrimitive>
<System.ButtonPrimitive css={STYLES_SHARING_BUTTON} onClick={handleLinkCopy}>
<SVG.Link width={20} />
<div style={{ padding: 2 }}>
<SVG.Link width={16} height={16} />
</div>
<System.P2 style={{ marginLeft: 12 }}>
{copyState.isLinkCopied ? "Copied" : "Copy public link"}
</System.P2>
</System.ButtonPrimitive>
<System.ButtonPrimitive css={STYLES_SHARING_BUTTON} onClick={handleCidCopy}>
<SVG.Hexagon width={20} />
<div style={{ padding: 2 }}>
<SVG.Hexagon width={16} height={16} />
</div>
<System.P2 style={{ marginLeft: 12 }}>
{copyState.isCidCopied ? "Copied" : "Copy CID "}
</System.P2>
@ -116,9 +128,13 @@ function DownloadButton({ file, viewer, ...props }) {
<div ref={downloadRef}>
<System.ButtonPrimitive css={STYLES_SHARING_BUTTON} onClick={handleDownload} {...props}>
{isDownloading ? (
<LoaderSpinner style={{ height: 16, width: 16 }} />
<div style={{ padding: 2 }}>
<LoaderSpinner style={{ height: 16, width: 16 }} />
</div>
) : (
<SVG.Download width={16} />
<div style={{ padding: 2 }}>
<SVG.Download width={16} height={16} />
</div>
)}
<System.P2 style={{ marginLeft: 12 }}>Download file</System.P2>
</System.ButtonPrimitive>
@ -163,7 +179,9 @@ export function Share({ file, data, viewer, onClose }) {
rel="noreferrer"
>
<SVG.InfoCircle width={16} />
<System.P2 style={{ marginLeft: 4 }}>What is a CID?</System.P2>
<System.P2 color="textGrayDark" style={{ marginLeft: 4 }}>
What is a CID?
</System.P2>
</a>
</Jumper.Item>
</Jumper.Root>

View File

@ -5,7 +5,7 @@ import * as Strings from "~/common/strings";
import { css } from "@emotion/react";
import { DescriptionGroup } from "~/components/system/components/fragments/DescriptionGroup";
import { FocusRing } from "~/components/core/FocusRing";
import { mergeRefs } from "~/common/utilities";
const INPUT_STYLES = (theme) => css`
box-sizing: border-box;
@ -70,7 +70,7 @@ const STYLES_INPUT = css`
justify-content: flex-start;
height: 40px;
border-radius: 12px;
padding: 10px 12px;
padding: 0px 12px;
background: ${Constants.system.white};
text-overflow: ellipsis;
white-space: nowrap;
@ -130,21 +130,25 @@ const INPUT_COLOR_MAP = {
class InputPrimitive extends React.Component {
_unit;
_input;
_isPin = this.props.type === "pin";
constructor(props) {
super(props);
this._input = React.createRef();
}
componentDidMount = () => {
if (this.props.unit) {
this._input.style.paddingRight = `${this._unit.offsetWidth + 48}px`;
this._input.current.style.paddingRight = `${this._unit.offsetWidth + 48}px`;
}
if (this.props.autoFocus) {
this._input.focus();
this._input.current.focus();
}
};
_handleCopy = (e) => {
this._input.select();
this._input.current.select();
document.execCommand("copy");
};
@ -240,12 +244,7 @@ class InputPrimitive extends React.Component {
}}
>
<input
ref={(c) => {
this._input = c;
if (this.props.innerRef) {
this.props.innerRef?.(c);
}
}}
ref={mergeRefs([this._input, this.props.innerRef])}
css={[INPUT_STYLES, this._isPin && STYLES_PIN_INPUT]}
autoFocus={this.props.autoFocus}
value={this._isPin ? this._formatPin(this.props.value) : this.props.value}
@ -256,7 +255,7 @@ class InputPrimitive extends React.Component {
onFocus={
this.props.autoHighlight
? () => {
this._input.select();
this._input.current.select();
}
: this.props.onFocus
}

View File

@ -108,10 +108,11 @@ function Header({ children, style, ...props }) {
* Dismiss
* -----------------------------------------------------------------------------------------------*/
const STYLES_DISMISS_BUTTON = css`
const STYLES_DISMISS_BUTTON = (theme) => css`
width: 24px;
height: 24px;
margin-left: 12px;
color: ${theme.semantic.textGrayDark};
`;
const Dismiss = React.forwardRef(({ css, ...props }, ref) => {

View File

@ -9,11 +9,11 @@ import * as Strings from "~/common/strings";
import WebsitePrototypeWrapper from "~/components/core/WebsitePrototypeWrapper";
import WebsiteHeader from "~/components/core/WebsiteHeader";
import WebsiteFooter from "~/components/core/WebsiteFooter";
import Field from "~/components/core/Field";
import { css } from "@emotion/react";
import { useForm } from "~/common/hooks";
import { motion, AnimateSharedLayout } from "framer-motion";
import { AuthField } from "~/components/core/Auth/components";
const INTEGRATION = [
{
@ -847,7 +847,7 @@ export default function IndexPage() {
return errors;
},
onSubmit: async ({ email }) => {
window.open(`/_/auth?tab=signup&email=${email}`, "_self");
window.open(`/_/auth?tab=signup&email=${encodeURIComponent(email)}`, "_self");
},
});
@ -1084,7 +1084,7 @@ export default function IndexPage() {
</System.ButtonPrimaryFull>
<div css={STYLES_DIVIDER} />
<form {...getSigninFormProps()} style={{ width: "100%" }}>
<Field
<AuthField
{...getSignupFielProps("email")}
label="Sign up with email"
placeholder="Email"

View File

@ -161,10 +161,9 @@ const AuthScene = ({ onAuthenticate, onTwitterAuthenticate, page, onAction, ...p
);
}
// NOTE(amine): if the user goes back, we should prefill the email
const emailParam = page?.params?.email ? decodeURIComponent(page?.params?.email) : "";
const initialEmail =
prevScene === "signin" && context.emailOrUsername
? context.emailOrUsername
: page?.params?.email || "";
prevScene === "signin" && context.emailOrUsername ? context.emailOrUsername : emailParam;
return (
<Initial

View File

@ -48,7 +48,8 @@ const STYLES_API_KEY = css`
background-color: ${Constants.semantic.bgLight};
outline: none;
border: none;
width: 380px;
width: 100%;
max-width: 380px;
font-family: ${Constants.font.code};
padding: 0 16px;
font-size: 14px;

View File

@ -68,7 +68,7 @@ const STYLES_SECURITY_LOCK_WRAPPER = (theme) => css`
`;
const STYLES_EMPTY_STATE_WRAPPER = (theme) => css`
// NOTE(amine): 100vh - headers' height - Dataviewer's bottom padding
// NOTE(amine): 100vh - headers' height - Dataview's bottom padding
height: calc(100vh - ${theme.sizes.filterNavbar + theme.sizes.header}px - 44px);
margin: 20px;
@media (max-width: ${theme.sizes.mobile}px) {
@ -509,7 +509,9 @@ class SlatePage extends React.Component {
</EmptyState>
</div>
) : (
<EmptyState>There's nothing here :)</EmptyState>
<div css={Styles.PAGE_EMPTY_STATE_WRAPPER}>
<EmptyState>There's nothing here :)</EmptyState>
</div>
)}
<input
ref={(c) => {