New sign-in page and signed-in on-load animation (#3684)

* Basic sign-in page layout

* Better responsive styling

* Add wipe animation

* Fix mobile button styling

* Add juicy on-load animation to logo in app header

* Make video card a link to the sample's code

* Fix video URL on bundled desktop app, add "open default browser" behavior to links

* Revert "Add juicy on-load animation to logo in app header"

This reverts commit c167569d7e.

---------

Co-authored-by: 49fl <ircsurfer33@gmail.com>
This commit is contained in:
Frank Noirot
2024-08-29 14:21:42 -04:00
committed by GitHub
parent 03c6f6d60e
commit bbdca7421e
7 changed files with 252 additions and 58 deletions

BIN
public/wheel-loop-dark.mp4 Normal file

Binary file not shown.

BIN
public/wheel-loop.mp4 Normal file

Binary file not shown.

View File

@ -42,7 +42,13 @@ export type ActionButtonProps =
export const ActionButton = forwardRef((props: ActionButtonProps, ref) => {
const classNames = `action-button p-0 m-0 group mono text-xs leading-none flex items-center gap-2 rounded-sm border-solid border border-chalkboard-30 hover:border-chalkboard-40 enabled:dark:border-chalkboard-70 dark:hover:border-chalkboard-60 dark:bg-chalkboard-90/50 text-chalkboard-100 dark:text-chalkboard-10 ${
props.iconStart ? (props.iconEnd ? 'px-0' : 'pr-2') : 'px-2'
props.iconStart
? props.iconEnd
? 'px-0'
: 'pr-2'
: props.iconEnd
? 'px-2'
: 'pl-2'
} ${props.className ? props.className : ''}`
switch (props.Element) {

View File

@ -35,7 +35,7 @@ export const ActionIcon = ({
return (
<div
className={
`w-fit inline-grid place-content-center ${className} ` +
`w-fit self-stretch inline-grid place-content-center ${className} ` +
computedBgClassName
}
>

View File

@ -332,7 +332,7 @@ const CustomIconMap = {
fillRule="evenodd"
clipRule="evenodd"
d="M5.5 4C4.11929 4 3 5.11929 3 6.5V7C3 10.0376 5.46243 12.5 8.5 12.5H8.96482C9.46635 12.5 9.93469 12.2493 10.2129 11.8321L10.5173 11.3755C11.1396 12.0849 12.0423 12.5 13 12.5H13.75H15V14C15 14.2626 14.9483 14.5227 14.8478 14.7654C14.7472 15.008 14.5999 15.2285 14.4142 15.4142C14.2285 15.5999 14.008 15.7472 13.7654 15.8478C13.5227 15.9483 13.2626 16 13 16C12.7374 16 12.4773 15.9483 12.2346 15.8478C11.992 15.7472 11.7715 15.5999 11.5858 15.4142C11.4001 15.2285 11.2528 15.008 11.1522 14.7654C11.1164 14.6789 11.0868 14.5902 11.0635 14.5H11.8544C11.9168 14.6431 12.0056 14.7734 12.1161 14.8839C12.2322 15 12.37 15.092 12.5216 15.1548C12.6733 15.2177 12.8358 15.25 13 15.25C13.1642 15.25 13.3267 15.2177 13.4784 15.1548C13.63 15.092 13.7678 15 13.8839 14.8839C14 14.7678 14.092 14.63 14.1548 14.4784C14.2177 14.3267 14.25 14.1642 14.25 14V13H13.25V14C13.25 14.0328 13.2435 14.0653 13.231 14.0957C13.2184 14.126 13.2 14.1536 13.1768 14.1768C13.1536 14.2 13.126 14.2184 13.0957 14.231C13.0653 14.2435 13.0328 14.25 13 14.25C12.9672 14.25 12.9347 14.2435 12.9043 14.231C12.874 14.2184 12.8464 14.2 12.8232 14.1768C12.8 14.1536 12.7816 14.126 12.769 14.0957C12.7565 14.0653 12.75 14.0328 12.75 14V13.5H12.25H10.5H10V14C10 14.394 10.0776 14.7841 10.2284 15.1481C10.3791 15.512 10.6001 15.8427 10.8787 16.1213C11.1573 16.3999 11.488 16.6209 11.8519 16.7716C12.2159 16.9224 12.606 17 13 17C13.394 17 13.7841 16.9224 14.1481 16.7716C14.512 16.6209 14.8427 16.3999 15.1213 16.1213C15.3999 15.8427 15.6209 15.512 15.7716 15.1481C15.9224 14.7841 16 14.394 16 14V12.5H17V11.5H16V8.5C16 6.01472 13.9853 4 11.5 4H5.5ZM11.084 10.4746L10.9226 10.2326L9.42875 7.74275L8.57125 8.25725L9.90846 10.4859L9.38084 11.2773C9.28811 11.4164 9.13199 11.5 8.96482 11.5H8.5C6.01472 11.5 4 9.48528 4 7V6.5C4 5.67157 4.67157 5 5.5 5H11.5C13.433 5 15 6.567 15 8.5V11.5H13.75H13C12.2301 11.5 11.5111 11.1152 11.084 10.4746ZM13.5 8.5C13.5 9.05228 13.0523 9.5 12.5 9.5C11.9477 9.5 11.5 9.05228 11.5 8.5C11.5 7.94772 11.9477 7.5 12.5 7.5C13.0523 7.5 13.5 7.94772 13.5 8.5Z"
fill="black"
fill="currentColor"
/>
</svg>
),

View File

@ -109,7 +109,7 @@ button:disabled {
}
a {
@apply text-primary underline hover:hue-rotate-15;
@apply text-primary hover:hue-rotate-15;
}
.dark a {
@ -286,6 +286,35 @@ code {
}
}
@layer utilities {
/* Modified from the very helpful https://www.transition.style/#in:circle:hesitate */
@keyframes circle-in-hesitate {
0% {
clip-path: circle(
var(--circle-size-start, 0%) at var(--circle-x, 50%)
var(--circle-y, 50%)
);
}
40% {
clip-path: circle(
var(--circle-size-mid, 40%) at var(--circle-x, 50%) var(--circle-y, 50%)
);
}
100% {
clip-path: circle(
var(--circle-size-end, 125%) at var(--circle-x, 50%)
var(--circle-y, 50%)
);
}
}
.in-circle-hesitate {
animation: var(--circle-duration, 2.5s)
var(--circle-timing, cubic-bezier(0.25, 1, 0.3, 1)) circle-in-hesitate
both;
}
}
#code-mirror-override .cm-scroller,
#code-mirror-override .cm-editor {
height: 100% !important;

View File

@ -5,6 +5,16 @@ import { Themes, getSystemTheme } from '../lib/theme'
import { PATHS } from 'lib/paths'
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
import { APP_NAME } from 'lib/constants'
import { CSSProperties, useCallback } from 'react'
import { Logo } from 'components/Logo'
import { CustomIcon } from 'components/CustomIcon'
import { Link } from 'react-router-dom'
import { APP_VERSION } from './Settings'
import { openExternalBrowserIfDesktop } from 'lib/openWindow'
const subtleBorder =
'border border-solid border-chalkboard-30 dark:border-chalkboard-80'
const cardArea = `${subtleBorder} rounded-lg px-6 py-3 text-chalkboard-70 dark:text-chalkboard-30`
const SignIn = () => {
const {
@ -17,12 +27,25 @@ const SignIn = () => {
},
},
} = useSettingsAuthContext()
const signInUrl = `${VITE_KC_SITE_BASE_URL}${
PATHS.SIGN_IN
}?callbackUrl=${encodeURIComponent(
typeof window !== 'undefined' && window.location.href.replace('signin', '')
)}`
const kclSampleUrl = `${VITE_KC_SITE_BASE_URL}/docs/kcl-samples/car-wheel`
const getLogoTheme = () =>
theme.current === Themes.Light ||
(theme.current === Themes.System && getSystemTheme() === Themes.Light)
? '-dark'
: ''
const getThemeText = useCallback(
(shouldContrast = true) =>
theme.current === Themes.Light ||
(theme.current === Themes.System && getSystemTheme() === Themes.Light)
? shouldContrast
? '-dark'
: ''
: shouldContrast
? ''
: '-dark',
[theme.current]
)
const signInDesktop = async () => {
// We want to invoke our command to login via device auth.
@ -35,56 +58,192 @@ const SignIn = () => {
}
return (
<main className="body-bg h-full min-h-screen m-0 p-0 pt-24">
<div className="max-w-2xl mx-auto">
<div>
<img
src={`./zma-logomark${getLogoTheme()}.svg`}
alt="Zoo Modeling App"
className="w-48 inline-block"
/>
<main className="bg-primary h-screen grid place-items-stretch m-0 p-2">
<div
style={
{
height: 'calc(100vh - 16px)',
'--circle-x': '14%',
'--circle-y': '12%',
'--circle-size-mid': '15%',
'--circle-size-end': '200%',
'--circle-timing': 'cubic-bezier(0.25, 1, 0.4, 0.9)',
} as CSSProperties
}
className="in-circle-hesitate body-bg py-5 px-12 rounded-lg grid place-items-center overflow-y-auto"
>
<div className="max-w-7xl grid gap-5 grid-cols-3 xl:grid-cols-4 xl:grid-rows-5">
<div className="col-span-2 xl:col-span-3 xl:row-span-3 max-w-3xl mr-8 mb-8">
<div className="flex items-baseline mb-8">
<Logo className="text-primary h-10 lg:h-12 xl:h-16 relative translate-y-1 mr-4 lg:mr-6 xl:mr-8" />
<h1 className="text-3xl lg:text-4xl xl:text-5xl">{APP_NAME}</h1>
<span className="px-3 py-1 text-base rounded-full bg-primary/10 text-primary self-start">
alpha v{APP_VERSION}
</span>
</div>
<p className="my-4 text-lg xl:text-xl">
Thank you for using our hardware design application. It is built
on a novel CAD engine and crafted to help you create parametric,
version-controlled, and accurate parts ready for manufacturing.
</p>
<p className="my-4 text-lg xl:text-xl">
As alpha software, Zoo Modeling App is still in heavy development.
We encourage feedback and feature requests that align with{' '}
<a
href="https://github.com/KittyCAD/modeling-app/issues/729"
target="_blank"
rel="noreferrer"
>
our roadmap to v1.0
</a>
.
</p>
{isDesktop() ? (
<button
onClick={signInDesktop}
className={
'm-0 mt-8 flex gap-4 items-center px-3 py-1 ' +
'!border-transparent !text-lg !text-chalkboard-10 !bg-primary hover:hue-rotate-15'
}
data-testid="sign-in-button"
>
Sign in to get started
<CustomIcon name="arrowRight" className="w-6 h-6" />
</button>
) : (
<Link
onClick={openExternalBrowserIfDesktop(signInUrl)}
to={signInUrl}
className={
'w-fit m-0 mt-8 flex gap-4 items-center px-3 py-1 ' +
'!border-transparent !text-lg !text-chalkboard-10 !bg-primary hover:hue-rotate-15'
}
data-testid="sign-in-button"
>
Sign in to get started
<CustomIcon name="arrowRight" className="w-6 h-6" />
</Link>
)}
</div>
<Link
className={`group relative xl:h-full xl:row-span-full col-start--1 xl:col-start-4 rounded-lg overflow-hidden grid place-items-center ${subtleBorder}`}
to={kclSampleUrl}
onClick={openExternalBrowserIfDesktop(kclSampleUrl)}
target="_blank"
rel="noreferrer noopener"
>
<video
autoPlay
loop
muted
playsInline
className="h-full object-cover object-center"
>
<source
src={`${isDesktop() ? '.' : ''}/wheel-loop${getThemeText(
false
)}.mp4`}
type="video/mp4"
/>
</video>
<div
className={
'absolute bottom-0 left-0 right-0 transition translate-y-4 opacity-0 ' +
'group-hover:translate-y-0 group-hover:opacity-100 ' +
'm-0 mt-8 flex gap-4 items-center px-3 py-1 ' +
'!border-transparent !text-lg !text-chalkboard-10 !bg-primary hover:hue-rotate-15'
}
data-testid="sign-in-button"
>
View this sample
<CustomIcon name="arrowRight" className="w-6 h-6" />
</div>
</Link>
<div className="self-end h-min col-span-3 xl:row-span-2 grid grid-cols-2 gap-5">
<div className={cardArea}>
<h2 className="text-xl">Built in the open</h2>
<p className="text-xs my-4">
Open-source and open discussions. Check our public code base and
join our Discord.
</p>
<div className="flex gap-4 flex-wrap items-center">
<ActionButton
Element="externalLink"
to="https://github.com/KittyCAD/modeling-app"
iconStart={{ icon: 'code' }}
className="border-chalkboard-30 dark:border-chalkboard-80"
>
<span className="py-2 lg:py-0">Read our source code</span>
</ActionButton>
<ActionButton
Element="externalLink"
to="https://discord.gg/JQEpHR7Nt2"
iconStart={{ icon: 'keyboard' }}
className="border-chalkboard-30 dark:border-chalkboard-80"
>
<span className="py-2 lg:py-0">Join our community</span>
</ActionButton>
</div>
</div>
<div className={cardArea}>
<h2 className="text-xl">Ready for the future</h2>
<p className="text-xs my-4">
Modern software ideas being brought together to create a
familiar modeling experience with new superpowers.
</p>
<div className="flex gap-4 flex-wrap items-center">
<ActionButton
Element="externalLink"
to="https://zoo.dev/docs/kcl-samples/ball-bearing"
iconStart={{ icon: 'settings' }}
className="border-chalkboard-30 dark:border-chalkboard-80"
>
<span className="py-2 lg:py-0">
Parametric design with KCL
</span>
</ActionButton>
<ActionButton
Element="externalLink"
to="https://zoo.dev/docs/tutorials/text-to-cad"
iconStart={{ icon: 'sparkles' }}
className="border-chalkboard-30 dark:border-chalkboard-80"
>
<span className="py-2 lg:py-0">AI-unlocked CAD</span>
</ActionButton>
</div>
</div>
<div className={cardArea + ' col-span-2'}>
<h2 className="text-xl">
Built on the first infrastructure for hardware design
</h2>
<p className="text-xs my-4">
You can make your own niche hardware design tools with our
design and machine learning interfaces. We're building Modeling
App in the same way.
</p>
<div className="flex gap-4 flex-wrap items-center">
<ActionButton
Element="externalLink"
to="https://zoo.dev/design-api"
iconStart={{ icon: 'sketch' }}
className="border-chalkboard-30 dark:border-chalkboard-80"
>
<span className="py-2 lg:py-0">KittyCAD Design API</span>
</ActionButton>
<ActionButton
Element="externalLink"
to="https://zoo.dev/machine-learning-api"
iconStart={{ icon: 'elephant' }}
className="border-chalkboard-30 dark:border-chalkboard-80"
>
<span className="py-2 lg:py-0">
ML-ephant Machine Learning API
</span>
</ActionButton>
</div>
</div>
</div>
</div>
<h1 className="font-bold text-2xl mt-12 mb-6">
Sign in to get started with the {APP_NAME}
</h1>
<p className="py-4">
ZMA is an open-source CAD application for creating accurate 3D models
for use in manufacturing. It is built on top of KittyCAD, the design
API from Zoo. Zoo is the first software infrastructure company built
specifically for the needs of the manufacturing industry. With ZMA we
are showing how the KittyCAD API from Zoo can be used to build
entirely new kinds of software for manufacturing.
</p>
<p className="py-4">
ZMA is currently in development. If you would like to be notified when
ZMA is ready for production, please sign up for our mailing list at{' '}
<a href="https://zoo.dev">zoo.dev</a>.
</p>
{isDesktop() ? (
<ActionButton
Element="button"
onClick={signInDesktop}
iconStart={{ icon: 'arrowRight' }}
className="w-fit mt-4"
data-testid="sign-in-button"
>
Sign in
</ActionButton>
) : (
<ActionButton
Element="link"
to={`${VITE_KC_SITE_BASE_URL}${
PATHS.SIGN_IN
}?callbackUrl=${encodeURIComponent(
typeof window !== 'undefined' &&
window.location.href.replace('signin', '')
)}`}
iconStart={{ icon: 'arrowRight' }}
className="w-fit mt-4"
>
Sign in
</ActionButton>
)}
</div>
</main>
)