4
0
forked from crowetic/commerce

Adding Modal Component and Login View

This commit is contained in:
Belen Curcio 2020-10-19 15:22:48 -03:00
parent a3e021ec79
commit 26535b7c7f
11 changed files with 122 additions and 12 deletions

View File

@ -2,12 +2,11 @@
} }
.list { .list {
@apply flex flex-row items-center; @apply flex flex-row items-center h-full;
} }
.item { .item {
@apply mr-6 cursor-pointer relative transition ease-in-out duration-100 text-base; @apply mr-6 cursor-pointer relative transition ease-in-out duration-100 text-base flex items-center;
&:hover { &:hover {
@apply text-accents-8; @apply text-accents-8;
} }

View File

@ -20,3 +20,7 @@
.loading { .loading {
@apply bg-accents-1 text-accents-3 border-accents-2 cursor-not-allowed; @apply bg-accents-1 text-accents-3 border-accents-2 cursor-not-allowed;
} }
.slim {
@apply py-2 transform-none normal-case;
}

View File

@ -13,7 +13,7 @@ import { LoadingDots } from '@components/ui'
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
href?: string href?: string
className?: string className?: string
variant?: 'filled' | 'outlined' | 'flat' | 'none' variant?: 'flat' | 'slim'
active?: boolean active?: boolean
type?: 'submit' | 'reset' | 'button' type?: 'submit' | 'reset' | 'button'
Component?: string | JSXElementConstructor<any> Component?: string | JSXElementConstructor<any>
@ -24,7 +24,7 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
const Button: React.FC<ButtonProps> = forwardRef((props, buttonRef) => { const Button: React.FC<ButtonProps> = forwardRef((props, buttonRef) => {
const { const {
className, className,
variant = 'filled', variant = 'flat',
children, children,
active, active,
onClick, onClick,
@ -50,6 +50,7 @@ const Button: React.FC<ButtonProps> = forwardRef((props, buttonRef) => {
const rootClassName = cn( const rootClassName = cn(
s.root, s.root,
{ {
[s.slim]: variant === 'slim',
[s.loading]: loading, [s.loading]: loading,
}, },
className className
@ -57,16 +58,16 @@ const Button: React.FC<ButtonProps> = forwardRef((props, buttonRef) => {
return ( return (
<Component <Component
className={rootClassName}
aria-pressed={active} aria-pressed={active}
data-variant={variant} data-variant={variant}
ref={mergeRefs([ref, buttonRef])} ref={mergeRefs([ref, buttonRef])}
{...buttonProps} {...buttonProps}
data-active={isPressed ? '' : undefined}
className={rootClassName}
style={{ style={{
width, width,
...style, ...style,
}} }}
data-active={isPressed ? '' : undefined}
> >
{children} {children}
{loading && ( {loading && (

View File

@ -1,12 +1,14 @@
const Logo = () => ( const Logo = ({ className = '', ...props }) => (
<svg <svg
width="32" width="32"
height="32" height="32"
viewBox="0 0 32 32" viewBox="0 0 32 32"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
className={className}
{...props}
> >
<rect width="32" height="32" rx="16" fill="var(--secondary)" /> <rect width="100%" height="100%" rx="16" fill="var(--secondary)" />
<path <path
fillRule="evenodd" fillRule="evenodd"
clipRule="evenodd" clipRule="evenodd"

View File

@ -0,0 +1,8 @@
.root {
@apply fixed bg-black flex items-center inset-0 z-50 justify-center;
background-color: rgba(0, 0, 0, 0.35);
}
.modal {
@apply bg-white p-12;
}

View File

@ -0,0 +1,52 @@
import cn from 'classnames'
import { FC, useRef } from 'react'
import s from './Modal.module.css'
import { useDialog } from '@react-aria/dialog'
import {
useOverlay,
usePreventScroll,
useModal,
OverlayProvider,
OverlayContainer,
} from '@react-aria/overlays'
import { FocusScope } from '@react-aria/focus'
interface Props {
className?: string
children?: any
show?: boolean
close: () => void
}
const Modal: FC<Props> = ({
className,
children,
show = true,
close,
...props
}) => {
const rootClassName = cn(s.root, className)
let ref = useRef() as React.MutableRefObject<HTMLInputElement>
usePreventScroll()
let { modalProps } = useModal()
let { overlayProps } = useOverlay(props, ref)
let { dialogProps } = useDialog(props, ref)
return (
<div className={rootClassName}>
<FocusScope contain restoreFocus autoFocus>
<div
{...overlayProps}
{...dialogProps}
{...modalProps}
ref={ref}
className={s.modal}
>
{children}
</div>
</FocusScope>
</div>
)
}
export default Modal

View File

@ -0,0 +1 @@
export { default } from './Modal'

View File

@ -7,3 +7,4 @@ export { default as Marquee } from './Marquee'
export { default as Container } from './Container' export { default as Container } from './Container'
export { default as LoadingDots } from './LoadingDots' export { default as LoadingDots } from './LoadingDots'
export { default as Skeleton } from './Skeleton' export { default as Skeleton } from './Skeleton'
export { default as Modal } from './Modal'

View File

@ -19,10 +19,12 @@ export default function useCart<T>(
swrOptions?: ConfigInterface<T | null> swrOptions?: ConfigInterface<T | null>
) { ) {
const { cartCookie } = useCommerce() const { cartCookie } = useCommerce()
const fetcher: typeof fetcherFn = (options, input, fetch) => { const fetcher: typeof fetcherFn = (options, input, fetch) => {
input.cartId = Cookies.get(cartCookie) input.cartId = Cookies.get(cartCookie)
return fetcherFn(options, input, fetch) return fetcherFn(options, input, fetch)
} }
const response = useData(options, input, fetcher, swrOptions) const response = useData(options, input, fetcher, swrOptions)
return Object.assign(response, { isEmpty: true }) as CartResponse<T> return Object.assign(response, { isEmpty: true }) as CartResponse<T>

View File

@ -28,7 +28,7 @@ export default function Home({
return ( return (
<div className="mt-3"> <div className="mt-3">
<Grid> <Grid>
{featuredProducts.map((p: any) => ( {featuredProducts.slice(0, 3).map((p: any) => (
<ProductCard key={p.id} {...p} /> <ProductCard key={p.id} {...p} />
))} ))}
</Grid> </Grid>
@ -48,12 +48,12 @@ export default function Home({
Natural." Natural."
/> />
<Grid layout="B"> <Grid layout="B">
{products.slice(3, 6).map((p: any) => ( {featuredProducts.slice(3, 6).map((p: any) => (
<ProductCard key={p.id} {...p} /> <ProductCard key={p.id} {...p} />
))} ))}
</Grid> </Grid>
<Marquee> <Marquee>
{products.slice(0, 3).map((p: any) => ( {products.slice(3, 6).map((p: any) => (
<ProductCard key={p.id} {...p} variant="slim" /> <ProductCard key={p.id} {...p} variant="slim" />
))} ))}
</Marquee> </Marquee>

40
pages/login.tsx Normal file
View File

@ -0,0 +1,40 @@
import { Layout } from '@components/core'
import { Logo, Modal, Button } from '@components/ui'
export default function Login() {
return (
<div className="pb-20">
<Modal close={() => {}}>
<div className="h-80 w-80 flex flex-col justify-between py-3 px-3">
<div className="flex justify-center pb-12">
<Logo width="64px" height="64px" />
</div>
<div className="flex flex-col space-y-3">
<div className="border border-accents-3 text-accents-6">
<input
placeholder="Email"
className="focus:outline-none focus:shadow-outline-gray border-none py-2 px-6 w-full appearance-none transition duration-150 ease-in-out placeholder-accents-5 pr-10"
/>
</div>
<div className="border border-accents-3 text-accents-6">
<input
placeholder="Password"
className="focus:outline-none focus:shadow-outline-gray border-none py-2 px-6 w-full appearance-none transition duration-150 ease-in-out placeholder-accents-5 pr-10"
/>
</div>
<Button variant="slim">Log In</Button>
<span className="pt-3 text-center text-sm">
<span className="text-accents-7">Don't have an account?</span>
{` `}
<a className="text-accent-9 font-bold hover:underline cursor-pointer">
Sign Up
</a>
</span>
</div>
</div>
</Modal>
</div>
)
}
Login.Layout = Layout