Add a "back" button to the onboarding buttons, move the dismiss button to a little corner x
button (#5296)
* Add previous button to OnboardingButtons, move dismiss to popover corner * A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores) * A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores) * Clean up diagnostics I am thoroughly enjoying nvim now * Amend "click through" test to also click back * fmt * Set this test back to fixme, that work should be its own PR --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
@ -27,7 +27,7 @@ test.describe('Onboarding tests', () => {
|
||||
},
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
async ({ context, page, homePage }) => {
|
||||
async ({ page, homePage }) => {
|
||||
const u = await getUtils(page)
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
@ -68,7 +68,7 @@ test.describe('Onboarding tests', () => {
|
||||
},
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
async ({ page, homePage }, testInfo) => {
|
||||
async ({ page }) => {
|
||||
const u = await getUtils(page)
|
||||
|
||||
const viewportSize = { width: 1200, height: 500 }
|
||||
@ -154,7 +154,7 @@ test.describe('Onboarding tests', () => {
|
||||
)
|
||||
|
||||
test(
|
||||
'Click through each onboarding step',
|
||||
'Click through each onboarding step and back',
|
||||
{
|
||||
appSettings: {
|
||||
app: {
|
||||
@ -187,15 +187,21 @@ test.describe('Onboarding tests', () => {
|
||||
).toBeVisible()
|
||||
|
||||
const nextButton = page.getByTestId('onboarding-next')
|
||||
const prevButton = page.getByTestId('onboarding-prev')
|
||||
|
||||
while ((await nextButton.innerText()) !== 'Finish') {
|
||||
await nextButton.hover()
|
||||
await nextButton.click()
|
||||
}
|
||||
|
||||
// Finish the onboarding
|
||||
await nextButton.hover()
|
||||
await nextButton.click()
|
||||
while ((await prevButton.innerText()) !== 'Dismiss') {
|
||||
await prevButton.hover()
|
||||
await prevButton.click()
|
||||
}
|
||||
|
||||
// Dismiss the onboarding
|
||||
await prevButton.hover()
|
||||
await prevButton.click()
|
||||
|
||||
// Test that the onboarding pane is gone
|
||||
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
||||
@ -269,7 +275,7 @@ test.describe('Onboarding tests', () => {
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
|
||||
async ({ context, page, homePage }) => {
|
||||
async ({ page, homePage }) => {
|
||||
const u = await getUtils(page)
|
||||
const badCode = `// This is bad code we shouldn't see`
|
||||
|
||||
@ -336,10 +342,10 @@ test.describe('Onboarding tests', () => {
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
// Test that the text in this step is correct
|
||||
const avatarLocator = await page
|
||||
const avatarLocator = page
|
||||
.getByTestId('user-sidebar-toggle')
|
||||
.locator('img')
|
||||
const onboardingOverlayLocator = await page
|
||||
const onboardingOverlayLocator = page
|
||||
.getByTestId('onboarding-content')
|
||||
.locator('div')
|
||||
.nth(1)
|
||||
@ -447,7 +453,7 @@ test.fixme(
|
||||
},
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
async ({ context, page, homePage }, testInfo) => {
|
||||
async ({ context, page }) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const routerTemplateDir = join(dir, 'router-template-slate')
|
||||
await fsp.mkdir(routerTemplateDir, { recursive: true })
|
||||
@ -486,10 +492,6 @@ test.fixme(
|
||||
})
|
||||
|
||||
await test.step('Navigate into project', async () => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
page.on('console', console.log)
|
||||
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'Your Projects' })
|
||||
).toBeVisible()
|
||||
|
@ -26,7 +26,7 @@ export default function Units() {
|
||||
<div className="fixed inset-0 z-50 grid items-end justify-start px-4 pointer-events-none">
|
||||
<div
|
||||
className={
|
||||
'pointer-events-auto max-w-2xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
'relative pointer-events-auto max-w-2xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
}
|
||||
>
|
||||
<SettingsSection
|
||||
@ -72,9 +72,7 @@ export default function Units() {
|
||||
</SettingsSection>
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.CAMERA}
|
||||
dismiss={dismiss}
|
||||
next={next}
|
||||
nextText="Next: Streaming"
|
||||
dismissClassName="right-auto left-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,19 +1,17 @@
|
||||
import usePlatform from 'hooks/usePlatform'
|
||||
import { OnboardingButtons, kbdClasses, useDismiss, useNextClick } from '.'
|
||||
import { OnboardingButtons, kbdClasses } from '.'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
import { hotkeyDisplay } from 'lib/hotkeyWrapper'
|
||||
import { COMMAND_PALETTE_HOTKEY } from 'components/CommandBar/CommandBar'
|
||||
|
||||
export default function CmdK() {
|
||||
const dismiss = useDismiss()
|
||||
const next = useNextClick(onboardingPaths.USER_MENU)
|
||||
const platformName = usePlatform()
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 grid items-end justify-center pointer-events-none">
|
||||
<div
|
||||
className={
|
||||
'pointer-events-auto max-w-full xl:max-w-4xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
'relative pointer-events-auto max-w-full xl:max-w-4xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
}
|
||||
>
|
||||
<h2 className="text-2xl font-bold">Command Bar</h2>
|
||||
@ -38,12 +36,7 @@ export default function CmdK() {
|
||||
. You can control settings, authentication, and file management from
|
||||
the command bar, as well as a growing number of modeling commands.
|
||||
</p>
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.COMMAND_K}
|
||||
dismiss={dismiss}
|
||||
next={next}
|
||||
nextText="Next: User Menu"
|
||||
/>
|
||||
<OnboardingButtons currentSlug={onboardingPaths.COMMAND_K} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,22 +1,14 @@
|
||||
import {
|
||||
kbdClasses,
|
||||
OnboardingButtons,
|
||||
useDemoCode,
|
||||
useDismiss,
|
||||
useNextClick,
|
||||
} from '.'
|
||||
import { kbdClasses, OnboardingButtons, useDemoCode } from '.'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
|
||||
export default function OnboardingCodeEditor() {
|
||||
useDemoCode()
|
||||
const dismiss = useDismiss()
|
||||
const next = useNextClick(onboardingPaths.PARAMETRIC_MODELING)
|
||||
|
||||
return (
|
||||
<div className="fixed grid justify-end items-center inset-0 z-50 pointer-events-none">
|
||||
<div
|
||||
className={
|
||||
'pointer-events-auto z-10 max-w-xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg h-[75vh] flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
'relative pointer-events-auto z-10 max-w-xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg h-[75vh] flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
}
|
||||
>
|
||||
<section className="flex-1 overflow-y-auto">
|
||||
@ -73,12 +65,7 @@ export default function OnboardingCodeEditor() {
|
||||
pressing <kbd className={kbdClasses}>Shift + C</kbd>.
|
||||
</p>
|
||||
</section>
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.EDITOR}
|
||||
dismiss={dismiss}
|
||||
next={next}
|
||||
nextText="Next: Parametric Modeling"
|
||||
/>
|
||||
<OnboardingButtons currentSlug={onboardingPaths.EDITOR} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,16 +1,13 @@
|
||||
import { APP_NAME } from 'lib/constants'
|
||||
import { OnboardingButtons, useDismiss, useNextClick } from '.'
|
||||
import { OnboardingButtons } from '.'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
|
||||
export default function Export() {
|
||||
const dismiss = useDismiss()
|
||||
const next = useNextClick(onboardingPaths.SKETCHING)
|
||||
|
||||
return (
|
||||
<div className="fixed grid justify-center items-end inset-0 z-50 pointer-events-none">
|
||||
<div
|
||||
className={
|
||||
'pointer-events-auto max-w-full xl:max-w-2xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
'relative pointer-events-auto max-w-full xl:max-w-2xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
}
|
||||
>
|
||||
<section className="flex-1">
|
||||
@ -52,12 +49,7 @@ export default function Export() {
|
||||
!
|
||||
</p>
|
||||
</section>
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.EXPORT}
|
||||
next={next}
|
||||
dismiss={dismiss}
|
||||
nextText="Next: Sketching"
|
||||
/>
|
||||
<OnboardingButtons currentSlug={onboardingPaths.EXPORT} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { OnboardingButtons, useDemoCode, useDismiss } from '.'
|
||||
import { OnboardingButtons, useDemoCode } from '.'
|
||||
import { useEffect } from 'react'
|
||||
import { useModelingContext } from 'hooks/useModelingContext'
|
||||
import { APP_NAME } from 'lib/constants'
|
||||
@ -7,7 +7,6 @@ import { sceneInfra } from 'lib/singletons'
|
||||
|
||||
export default function FutureWork() {
|
||||
const { send } = useModelingContext()
|
||||
const dismiss = useDismiss()
|
||||
|
||||
// Reset the code, the camera, and the modeling state
|
||||
useDemoCode()
|
||||
@ -19,7 +18,7 @@ export default function FutureWork() {
|
||||
|
||||
return (
|
||||
<div className="fixed grid justify-center items-center inset-0 bg-chalkboard-100/50 z-50">
|
||||
<div className="max-w-full xl:max-w-2xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded">
|
||||
<div className="relative max-w-full xl:max-w-2xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded">
|
||||
<h1 className="text-2xl font-bold">Future Work</h1>
|
||||
<p className="my-4">
|
||||
We have curves, cuts, multi-profile sketch mode, and many more CAD
|
||||
@ -59,9 +58,6 @@ export default function FutureWork() {
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.FUTURE_WORK}
|
||||
className="mt-6"
|
||||
dismiss={dismiss}
|
||||
next={dismiss}
|
||||
nextText="Finish"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,23 +1,15 @@
|
||||
import {
|
||||
OnboardingButtons,
|
||||
kbdClasses,
|
||||
useDemoCode,
|
||||
useDismiss,
|
||||
useNextClick,
|
||||
} from '.'
|
||||
import { OnboardingButtons, kbdClasses, useDemoCode } from '.'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
import { bracketWidthConstantLine } from 'lib/exampleKcl'
|
||||
|
||||
export default function OnboardingInteractiveNumbers() {
|
||||
useDemoCode()
|
||||
const dismiss = useDismiss()
|
||||
const next = useNextClick(onboardingPaths.COMMAND_K)
|
||||
|
||||
return (
|
||||
<div className="fixed grid justify-end items-center inset-0 z-50 pointer-events-none">
|
||||
<div
|
||||
className={
|
||||
'pointer-events-auto z-10 max-w-xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg h-[75vh] flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
'relative pointer-events-auto z-10 max-w-xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg h-[75vh] flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
}
|
||||
>
|
||||
<section className="flex-1 overflow-y-auto mb-6">
|
||||
@ -88,12 +80,7 @@ export default function OnboardingInteractiveNumbers() {
|
||||
your ideas for how to make it better.
|
||||
</p>
|
||||
</section>
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.INTERACTIVE_NUMBERS}
|
||||
dismiss={dismiss}
|
||||
next={next}
|
||||
nextText="Next: Command Bar"
|
||||
/>
|
||||
<OnboardingButtons currentSlug={onboardingPaths.INTERACTIVE_NUMBERS} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { OnboardingButtons, useDemoCode, useDismiss, useNextClick } from '.'
|
||||
import { OnboardingButtons, useDemoCode } from '.'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||
import { Themes, getSystemTheme } from 'lib/theme'
|
||||
@ -8,13 +8,12 @@ import { isDesktop } from 'lib/isDesktop'
|
||||
import { useNavigate, useRouteLoaderData } from 'react-router-dom'
|
||||
import { codeManager, kclManager } from 'lib/singletons'
|
||||
import { APP_NAME } from 'lib/constants'
|
||||
import { useState } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { IndexLoaderData } from 'lib/types'
|
||||
import { PATHS } from 'lib/paths'
|
||||
import { useFileContext } from 'hooks/useFileContext'
|
||||
import { useLspContext } from 'components/LspProvider'
|
||||
import { reportRejection } from 'lib/trap'
|
||||
import { toSync } from 'lib/utils'
|
||||
|
||||
/**
|
||||
* Show either a welcome screen or a warning screen
|
||||
@ -39,7 +38,7 @@ interface OnboardingResetWarningProps {
|
||||
function OnboardingResetWarning(props: OnboardingResetWarningProps) {
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 grid place-content-center bg-chalkboard-110/50">
|
||||
<div className="max-w-3xl p-8 rounded bg-chalkboard-10 dark:bg-chalkboard-90">
|
||||
<div className="relative max-w-3xl p-8 rounded bg-chalkboard-10 dark:bg-chalkboard-90">
|
||||
{!isDesktop() ? (
|
||||
<OnboardingWarningWeb {...props} />
|
||||
) : (
|
||||
@ -52,7 +51,6 @@ function OnboardingResetWarning(props: OnboardingResetWarningProps) {
|
||||
|
||||
function OnboardingWarningDesktop(props: OnboardingResetWarningProps) {
|
||||
const navigate = useNavigate()
|
||||
const dismiss = useDismiss()
|
||||
const loaderData = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
|
||||
const { context: fileContext } = useFileContext()
|
||||
const { onProjectClose, onProjectOpen } = useLspContext()
|
||||
@ -81,17 +79,28 @@ function OnboardingWarningDesktop(props: OnboardingResetWarningProps) {
|
||||
</section>
|
||||
<OnboardingButtons
|
||||
className="mt-6"
|
||||
dismiss={dismiss}
|
||||
next={toSync(onAccept, reportRejection)}
|
||||
nextText="Make a new project"
|
||||
onNextOverride={() => {
|
||||
onAccept().catch(reportRejection)
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function OnboardingWarningWeb(props: OnboardingResetWarningProps) {
|
||||
const dismiss = useDismiss()
|
||||
useEffect(() => {
|
||||
async function beforeNavigate() {
|
||||
// We do want to update both the state and editor here.
|
||||
codeManager.updateCodeStateEditor(bracket)
|
||||
await codeManager.writeToFile()
|
||||
|
||||
await kclManager.executeCode(true)
|
||||
props.setShouldShowWarning(false)
|
||||
}
|
||||
return () => {
|
||||
beforeNavigate().catch(reportRejection)
|
||||
}
|
||||
}, [])
|
||||
return (
|
||||
<>
|
||||
<h1 className="text-3xl font-bold text-warn-80 dark:text-warn-10">
|
||||
@ -101,19 +110,7 @@ function OnboardingWarningWeb(props: OnboardingResetWarningProps) {
|
||||
We see you have some of your own code written in this project. Please
|
||||
save it somewhere else before continuing the onboarding.
|
||||
</p>
|
||||
<OnboardingButtons
|
||||
className="mt-6"
|
||||
dismiss={dismiss}
|
||||
next={toSync(async () => {
|
||||
// We do want to update both the state and editor here.
|
||||
codeManager.updateCodeStateEditor(bracket)
|
||||
await codeManager.writeToFile()
|
||||
|
||||
await kclManager.executeCode(true)
|
||||
props.setShouldShowWarning(false)
|
||||
}, reportRejection)}
|
||||
nextText="Overwrite code and continue"
|
||||
/>
|
||||
<OnboardingButtons className="mt-6" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -136,12 +133,10 @@ function OnboardingIntroductionInner() {
|
||||
(theme.current === Themes.System && getSystemTheme() === Themes.Light)
|
||||
? '-dark'
|
||||
: ''
|
||||
const dismiss = useDismiss()
|
||||
const next = useNextClick(onboardingPaths.CAMERA)
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 grid place-content-center bg-chalkboard-110/50">
|
||||
<div className="max-w-3xl p-8 rounded bg-chalkboard-10 dark:bg-chalkboard-90">
|
||||
<div className="relative max-w-3xl p-8 rounded bg-chalkboard-10 dark:bg-chalkboard-90">
|
||||
<h1 className="flex flex-wrap items-center gap-4 text-3xl font-bold">
|
||||
<img
|
||||
src={`${isDesktop() ? '.' : ''}/zma-logomark${getLogoTheme()}.svg`}
|
||||
@ -192,9 +187,6 @@ function OnboardingIntroductionInner() {
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.INDEX}
|
||||
className="mt-6"
|
||||
dismiss={dismiss}
|
||||
next={next}
|
||||
nextText="Mouse Controls"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { OnboardingButtons, useDemoCode, useDismiss, useNextClick } from '.'
|
||||
import { OnboardingButtons, useDemoCode } from '.'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
import { Themes, getSystemTheme } from 'lib/theme'
|
||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||
@ -21,14 +21,12 @@ export default function OnboardingParametricModeling() {
|
||||
(theme === Themes.System && getSystemTheme() === Themes.Light)
|
||||
? '-dark'
|
||||
: ''
|
||||
const dismiss = useDismiss()
|
||||
const next = useNextClick(onboardingPaths.INTERACTIVE_NUMBERS)
|
||||
|
||||
return (
|
||||
<div className="fixed grid justify-end items-center inset-0 z-50 pointer-events-none">
|
||||
<div
|
||||
className={
|
||||
'pointer-events-auto z-10 max-w-xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg h-[75vh] flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
'relative pointer-events-auto z-10 max-w-xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg h-[75vh] flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
}
|
||||
>
|
||||
<section className="flex-1 overflow-y-auto mb-6">
|
||||
@ -77,12 +75,7 @@ export default function OnboardingParametricModeling() {
|
||||
</figcaption>
|
||||
</figure>
|
||||
</section>
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.PARAMETRIC_MODELING}
|
||||
dismiss={dismiss}
|
||||
next={next}
|
||||
nextText="Next: Interactive Numbers"
|
||||
/>
|
||||
<OnboardingButtons currentSlug={onboardingPaths.PARAMETRIC_MODELING} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,17 +1,15 @@
|
||||
import { OnboardingButtons, useDismiss, useNextClick } from '.'
|
||||
import { OnboardingButtons } from '.'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
import { isDesktop } from 'lib/isDesktop'
|
||||
|
||||
export default function ProjectMenu() {
|
||||
const dismiss = useDismiss()
|
||||
const next = useNextClick(onboardingPaths.EXPORT)
|
||||
const onDesktop = isDesktop()
|
||||
|
||||
return (
|
||||
<div className="fixed grid justify-center items-start inset-0 z-50 pointer-events-none">
|
||||
<div
|
||||
className={
|
||||
'pointer-events-auto max-w-xl flex flex-col border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
'relative pointer-events-auto max-w-xl flex flex-col border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
}
|
||||
>
|
||||
<section className="flex-1">
|
||||
@ -57,12 +55,7 @@ export default function ProjectMenu() {
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.PROJECT_MENU}
|
||||
next={next}
|
||||
dismiss={dismiss}
|
||||
nextText="Next: Export"
|
||||
/>
|
||||
<OnboardingButtons currentSlug={onboardingPaths.PROJECT_MENU} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,12 +1,9 @@
|
||||
import { OnboardingButtons, useDismiss, useNextClick } from '.'
|
||||
import { OnboardingButtons } from '.'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
import { useEffect } from 'react'
|
||||
import { codeManager, kclManager } from 'lib/singletons'
|
||||
|
||||
export default function Sketching() {
|
||||
const dismiss = useDismiss()
|
||||
const next = useNextClick(onboardingPaths.FUTURE_WORK)
|
||||
|
||||
useEffect(() => {
|
||||
async function clearEditor() {
|
||||
// We do want to update both the state and editor here.
|
||||
@ -22,7 +19,7 @@ export default function Sketching() {
|
||||
<div className="fixed grid justify-center items-end inset-0 z-50 pointer-events-none">
|
||||
<div
|
||||
className={
|
||||
'pointer-events-auto max-w-full xl:max-w-2xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
'relative pointer-events-auto max-w-full xl:max-w-2xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
}
|
||||
>
|
||||
<h1 className="text-2xl font-bold">Sketching</h1>
|
||||
@ -45,9 +42,6 @@ export default function Sketching() {
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.SKETCHING}
|
||||
className="mt-6"
|
||||
next={next}
|
||||
dismiss={dismiss}
|
||||
nextText="Next: Future Work"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,15 +1,12 @@
|
||||
import { OnboardingButtons, useDismiss, useNextClick } from '.'
|
||||
import { OnboardingButtons } from '.'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
|
||||
export default function Streaming() {
|
||||
const dismiss = useDismiss()
|
||||
const next = useNextClick(onboardingPaths.EDITOR)
|
||||
|
||||
return (
|
||||
<div className="fixed grid justify-start items-center inset-0 z-50 pointer-events-none">
|
||||
<div
|
||||
className={
|
||||
'pointer-events-auto max-w-xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg h-[75vh] flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
'relative pointer-events-auto max-w-xl border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg h-[75vh] flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
}
|
||||
>
|
||||
<section className="flex-1 overflow-y-auto">
|
||||
@ -44,9 +41,7 @@ export default function Streaming() {
|
||||
</section>
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.STREAMING}
|
||||
dismiss={dismiss}
|
||||
next={next}
|
||||
nextText="Next: Code Editor"
|
||||
dismissClassName="right-auto left-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { OnboardingButtons, useDismiss, useNextClick } from '.'
|
||||
import { OnboardingButtons } from '.'
|
||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useUser } from 'machines/appMachine'
|
||||
|
||||
export default function UserMenu() {
|
||||
const user = useUser()
|
||||
const dismiss = useDismiss()
|
||||
const next = useNextClick(onboardingPaths.PROJECT_MENU)
|
||||
const [avatarErrored, setAvatarErrored] = useState(false)
|
||||
|
||||
const errorOrNoImage = !user?.image || avatarErrored
|
||||
@ -32,7 +30,7 @@ export default function UserMenu() {
|
||||
<div className="fixed grid justify-center items-start inset-0 z-50 pointer-events-none">
|
||||
<div
|
||||
className={
|
||||
'pointer-events-auto max-w-xl flex flex-col border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
'relative pointer-events-auto max-w-xl flex flex-col border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded'
|
||||
}
|
||||
>
|
||||
<section className="flex-1">
|
||||
@ -48,12 +46,7 @@ export default function UserMenu() {
|
||||
only apply to the current project.
|
||||
</p>
|
||||
</section>
|
||||
<OnboardingButtons
|
||||
currentSlug={onboardingPaths.USER_MENU}
|
||||
dismiss={dismiss}
|
||||
next={next}
|
||||
nextText="Next: Project Menu"
|
||||
/>
|
||||
<OnboardingButtons currentSlug={onboardingPaths.USER_MENU} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -26,6 +26,9 @@ import { reportRejection } from 'lib/trap'
|
||||
import { useNetworkContext } from 'hooks/useNetworkContext'
|
||||
import { NetworkHealthState } from 'hooks/useNetworkStatus'
|
||||
import { EngineConnectionStateType } from 'lang/std/engineConnection'
|
||||
import { CustomIcon } from 'components/CustomIcon'
|
||||
import Tooltip from 'components/Tooltip'
|
||||
import { commandBarActor } from 'machines/commandBarMachine'
|
||||
|
||||
export const kbdClasses =
|
||||
'py-0.5 px-1 text-sm rounded bg-chalkboard-10 dark:bg-chalkboard-100 border border-chalkboard-50 border-b-2'
|
||||
@ -163,58 +166,99 @@ export function useStepNumber(
|
||||
: onboardingRoutes.findIndex(
|
||||
(r) => r.path === makeUrlPathRelative(slug)
|
||||
) + 1
|
||||
: undefined
|
||||
: 1
|
||||
}
|
||||
|
||||
export function OnboardingButtons({
|
||||
next,
|
||||
nextText,
|
||||
dismiss,
|
||||
currentSlug,
|
||||
className,
|
||||
dismissClassName,
|
||||
onNextOverride,
|
||||
...props
|
||||
}: {
|
||||
next: () => void
|
||||
nextText?: string
|
||||
dismiss: () => void
|
||||
currentSlug?: (typeof onboardingPaths)[keyof typeof onboardingPaths]
|
||||
className?: string
|
||||
dismissClassName?: string
|
||||
onNextOverride?: () => void
|
||||
} & React.HTMLAttributes<HTMLDivElement>) {
|
||||
const dismiss = useDismiss()
|
||||
const stepNumber = useStepNumber(currentSlug)
|
||||
const previousStep =
|
||||
!stepNumber || stepNumber === 0 ? null : onboardingRoutes[stepNumber - 2]
|
||||
const goToPrevious = useNextClick(
|
||||
onboardingPaths.INDEX + (previousStep?.path ?? '')
|
||||
)
|
||||
const nextStep =
|
||||
!stepNumber || stepNumber === onboardingRoutes.length
|
||||
? null
|
||||
: onboardingRoutes[stepNumber]
|
||||
const goToNext = useNextClick(onboardingPaths.INDEX + (nextStep?.path ?? ''))
|
||||
|
||||
return (
|
||||
<div
|
||||
className={'flex items-center justify-between ' + (className ?? '')}
|
||||
{...props}
|
||||
>
|
||||
<ActionButton
|
||||
Element="button"
|
||||
<>
|
||||
<button
|
||||
onClick={dismiss}
|
||||
iconStart={{
|
||||
icon: 'close',
|
||||
className: 'text-chalkboard-10',
|
||||
bgClassName: 'bg-destroy-80 group-hover:bg-destroy-80',
|
||||
}}
|
||||
className="hover:border-destroy-40 hover:bg-destroy-10/50 dark:hover:bg-destroy-80/50"
|
||||
className={
|
||||
'group block !absolute left-auto right-full top-[-3px] m-2.5 p-0 border-none bg-transparent hover:bg-transparent ' +
|
||||
dismissClassName
|
||||
}
|
||||
data-testid="onboarding-dismiss"
|
||||
>
|
||||
Dismiss
|
||||
</ActionButton>
|
||||
{stepNumber !== undefined && (
|
||||
<p className="font-mono text-xs text-center m-0">
|
||||
{stepNumber} / {onboardingRoutes.length}
|
||||
</p>
|
||||
)}
|
||||
<ActionButton
|
||||
autoFocus
|
||||
Element="button"
|
||||
onClick={next}
|
||||
iconStart={{ icon: 'arrowRight', bgClassName: 'dark:bg-chalkboard-80' }}
|
||||
className="dark:hover:bg-chalkboard-80/50"
|
||||
data-testid="onboarding-next"
|
||||
<CustomIcon
|
||||
name="close"
|
||||
className="w-5 h-5 rounded-sm bg-destroy-10 text-destroy-80 dark:bg-destroy-80 dark:text-destroy-10 group-hover:brightness-110"
|
||||
/>
|
||||
<Tooltip position="bottom" delay={500}>
|
||||
Dismiss <kbd className="hotkey ml-4 dark:!bg-chalkboard-80">esc</kbd>
|
||||
</Tooltip>
|
||||
</button>
|
||||
<div
|
||||
className={'flex items-center justify-between ' + (className ?? '')}
|
||||
{...props}
|
||||
>
|
||||
{nextText ?? 'Next'}
|
||||
</ActionButton>
|
||||
</div>
|
||||
<ActionButton
|
||||
Element="button"
|
||||
onClick={() =>
|
||||
previousStep?.path || previousStep?.index
|
||||
? goToPrevious()
|
||||
: dismiss()
|
||||
}
|
||||
iconStart={{
|
||||
icon: previousStep ? 'arrowLeft' : 'close',
|
||||
className: 'text-chalkboard-10',
|
||||
bgClassName: 'bg-destroy-80 group-hover:bg-destroy-80',
|
||||
}}
|
||||
className="hover:border-destroy-40 hover:bg-destroy-10/50 dark:hover:bg-destroy-80/50"
|
||||
data-testid="onboarding-prev"
|
||||
>
|
||||
{previousStep ? `Back` : 'Dismiss'}
|
||||
</ActionButton>
|
||||
{stepNumber !== undefined && (
|
||||
<p className="font-mono text-xs text-center m-0">
|
||||
{stepNumber} / {onboardingRoutes.length}
|
||||
</p>
|
||||
)}
|
||||
<ActionButton
|
||||
autoFocus
|
||||
Element="button"
|
||||
onClick={() => {
|
||||
if (nextStep?.path) {
|
||||
onNextOverride ? onNextOverride() : goToNext()
|
||||
} else {
|
||||
dismiss()
|
||||
}
|
||||
}}
|
||||
iconStart={{
|
||||
icon: nextStep ? 'arrowRight' : 'checkmark',
|
||||
bgClassName: 'dark:bg-chalkboard-80',
|
||||
}}
|
||||
className="dark:hover:bg-chalkboard-80/50"
|
||||
data-testid="onboarding-next"
|
||||
>
|
||||
{nextStep ? `Next` : 'Finish'}
|
||||
</ActionButton>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user