Update onboarding based on team feedback (#1665)

* Make onboarding links underlined and a different color

* Override underlined links that shouldn't be

* Update "KittyCAD" to "Zoo" camera controls, copy edits

* Copy edits through CodeEditor step, add counter to onboarding

* Notes through ParametricModeling step

* Notes through UserMenu step

* Add three-dots icon, separate Zoo logo link from project button

* Feedback through end of onboarding

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Fix ESLint warnings

* Revert cameraControls to 'KittyCAD', ensure we get type errors if that isn't correct in the future

* fmt

* Missed a reverted "Zoo" cameraControls item

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Frank Noirot
2024-03-08 17:59:14 -05:00
committed by GitHub
parent fbc458b6e6
commit cad64fb780
34 changed files with 328 additions and 136 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -1,6 +1,6 @@
.button {
@apply flex justify-between items-center gap-2 px-2 py-1 text-left border-none rounded-sm;
@apply font-mono text-xs font-bold select-none text-chalkboard-90;
@apply font-mono !no-underline text-xs font-bold select-none text-chalkboard-90;
@apply ui-active:bg-energy-10/50 ui-active:text-inherit;
@apply transition-colors ease-out;
}

View File

@ -1,9 +1,6 @@
import { Menu } from '@headlessui/react'
import { PropsWithChildren } from 'react'
import {
faArrowUpRightFromSquare,
faEllipsis,
} from '@fortawesome/free-solid-svg-icons'
import { faArrowUpRightFromSquare } from '@fortawesome/free-solid-svg-icons'
import { ActionIcon } from './ActionIcon'
import styles from './CodeMenu.module.css'
import { useConvertToVariable } from 'hooks/useToolbarGuards'
@ -29,7 +26,7 @@ export const CodeMenu = ({ children }: PropsWithChildren) => {
>
<Menu.Button className="p-0 border-none relative">
<ActionIcon
icon={faEllipsis}
icon="three-dots"
className="p-1"
size="sm"
bgClassName={

View File

@ -29,6 +29,7 @@ export type CustomIconName =
| 'search'
| 'settings'
| 'sketch'
| 'three-dots'
| 'vertical'
export const CustomIcon = ({
@ -516,6 +517,22 @@ export const CustomIcon = ({
/>
</svg>
)
case 'three-dots':
return (
<svg
{...props}
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.5 10C6.5 10.8284 5.82843 11.5 5 11.5C4.17157 11.5 3.5 10.8284 3.5 10C3.5 9.17157 4.17157 8.5 5 8.5C5.82843 8.5 6.5 9.17157 6.5 10ZM11.5 10C11.5 10.8284 10.8284 11.5 10 11.5C9.17157 11.5 8.5 10.8284 8.5 10C8.5 9.17157 9.17157 8.5 10 8.5C10.8284 8.5 11.5 9.17157 11.5 10ZM15 11.5C15.8284 11.5 16.5 10.8284 16.5 10C16.5 9.17157 15.8284 8.5 15 8.5C14.1716 8.5 13.5 9.17157 13.5 10C13.5 10.8284 14.1716 11.5 15 11.5Z"
fill="currentColor"
/>
</svg>
)
case 'vertical':
return (
<svg

View File

@ -106,7 +106,7 @@ function ProjectCard({
<>
<div className="p-1 flex flex-col h-full gap-2">
<Link
className="flex-1 text-liquid-100 after:content-[''] after:absolute after:inset-0"
className="flex-1 !no-underline text-liquid-100 after:content-[''] after:absolute after:inset-0"
to={`${paths.FILE}/${encodeURIComponent(project.path)}`}
data-testid="project-link"
>

View File

@ -11,6 +11,7 @@ import { sep } from '@tauri-apps/api/path'
import { Logo } from './Logo'
import { APP_NAME } from 'lib/constants'
import { useCommandsContext } from 'hooks/useCommandsContext'
import { CustomIcon } from './CustomIcon'
const ProjectSidebarMenu = ({
project,
@ -21,15 +22,18 @@ const ProjectSidebarMenu = ({
project?: IndexLoaderData['project']
file?: IndexLoaderData['file']
}) => {
const { commandBarSend } = useCommandsContext()
return renderAsLink ? (
return (
<div className="rounded-sm !no-underline h-9 mr-auto max-h-min min-w-max border-0 py-1 px-2 flex items-center gap-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-energy-50 dark:hover:bg-chalkboard-90">
<Link to={paths.HOME} className="group">
<Logo className="w-auto h-5 text-chalkboard-120 dark:text-chalkboard-10 group-hover:text-energy-10" />
</Link>
{renderAsLink ? (
<>
<Link
to={paths.HOME}
className="rounded-sm h-9 mr-auto max-h-min min-w-max border-0 py-1 px-2 flex items-center gap-3 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-energy-50 dark:hover:bg-chalkboard-90"
className="!no-underline"
data-testid="project-sidebar-link"
>
<Logo />
<span
className="hidden text-sm text-chalkboard-110 dark:text-chalkboard-20 whitespace-nowrap lg:block"
data-testid="project-sidebar-link-name"
@ -37,13 +41,30 @@ const ProjectSidebarMenu = ({
{project?.name ? project.name : APP_NAME}
</span>
</Link>
</>
) : (
<ProjectMenuPopover project={project} file={file} />
)}
</div>
)
}
function ProjectMenuPopover({
project,
file,
}: {
project?: IndexLoaderData['project']
file?: IndexLoaderData['file']
}) {
const { commandBarSend } = useCommandsContext()
return (
<Popover className="relative">
<Popover.Button
className="rounded-sm h-9 mr-auto max-h-min min-w-max border-0 py-1 px-2 flex items-center gap-3 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-energy-50 dark:hover:bg-chalkboard-90"
className="rounded-sm h-9 mr-auto max-h-min min-w-max border-0 py-1 pl-0 pr-2 flex items-center focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-energy-50 dark:hover:bg-chalkboard-90"
data-testid="project-sidebar-toggle"
>
<Logo />
<CustomIcon name="three-dots" className="w-5 h-5 rotate-90" />
<div className="flex flex-col items-start py-0.5">
<span className="hidden text-sm text-chalkboard-110 dark:text-chalkboard-20 whitespace-nowrap lg:block">
{isTauri() && file?.name
@ -85,7 +106,6 @@ const ProjectSidebarMenu = ({
{({ close }) => (
<>
<div className="flex items-center gap-4 px-4 py-3">
<Logo />
<div>
<p
className="m-0 text-chalkboard-100 dark:text-energy-10 text-mono"

View File

@ -88,11 +88,11 @@ button:disabled {
}
a:not(.action-button) {
@apply text-energy-70 hover:text-energy-60;
@apply text-energy-70 hover:text-energy-60 underline;
}
.dark a:not(.action-button) {
@apply text-chalkboard-20 hover:text-energy-10;
@apply text-energy-20 hover:text-energy-10;
}
input {

View File

@ -27,22 +27,34 @@ export type Toggle = 'On' | 'Off'
export const SETTINGS_PERSIST_KEY = 'SETTINGS_PERSIST_KEY'
type SettingsMachineContext = {
baseUnit: BaseUnit
cameraControls: CameraSystem
defaultDirectory: string
defaultProjectName: string
onboardingStatus: string
showDebugPanel: boolean
textWrapping: Toggle
theme: Themes
unitSystem: UnitSystem
}
export const settingsMachine = createMachine(
{
/** @xstate-layout N4IgpgJg5mDOIC5QGUwBc0EsB2VYDpMIAbMAYlTQAIAVACzAFswBtABgF1FQAHAe1iYsfbNxAAPRAA42+AEwB2KQFYAzGznKAnADZli1QBoQAT2kBGKfm37lOned3nzqgL6vjlLLgJFSFdCoAETAAMwBDAFdiagAFACc+ACswAGNqADlw5nYuJBB+QWFRfMkEABY5fDYa2rra83LjMwQdLWV8BXLyuxlVLU1Ld090bzxCEnJKYLComODMeLS0PniTXLFCoUwRMTK7fC1zNql7NgUjtnKjU0RlBSqpLVUVPVUda60tYZAvHHG-FNAgBVbBCKjIEywNBMDb5LbFPaILqdfRSORsS4qcxXZqIHqyK6qY4XOxsGTKco-P4+Cb+aYAIXCsDAVFBQjhvAE212pWkskUKnUml0+gUNxaqkU+EccnKF1UCnucnMcjcHl+o3+vkmZBofCgUFIMwARpEoFRYuFsGBiJyCtzEXzWrJlGxlKdVFKvfY1XiEBjyvhVOVzBdzu13pYFNStbTAQFqAB5bAmvjheIQf4QtDhNCRWD2hE7EqgfayHTEh7lHQNSxSf1Scz4cpHHFyFVujTKczuDXYPgQOBiGl4TaOktIhAAWg6X3nC4Xp39050sYw2rpYHHRUnztVhPJqmUlIGbEriv9WhrLZ6uibHcqUr7riAA */
id: 'Settings',
predictableActionArguments: true,
context: {
baseUnit: 'mm' as BaseUnit,
cameraControls: 'KittyCAD' as CameraSystem,
baseUnit: 'mm',
cameraControls: 'KittyCAD',
defaultDirectory: '',
defaultProjectName: DEFAULT_PROJECT_NAME,
onboardingStatus: '',
showDebugPanel: false,
textWrapping: 'On' as Toggle,
textWrapping: 'On',
theme: Themes.System,
unitSystem: UnitSystem.Metric,
},
} as SettingsMachineContext,
initial: 'idle',
states: {
idle: {

View File

@ -33,9 +33,10 @@ export default function Units() {
}
>
<SettingsSection
title="Camera Controls"
description="How you want to control the camera in the 3D view. Try them out above and choose the one that feels most comfortable to you."
title="Mouse Controls"
description="Choose what buttons you want to use on your mouse or trackpad to move around the 3D view. Try them out above and choose the one that feels most comfortable to you."
className="my-4 last-of-type:mb-12"
headingClassName="text-3xl font-bold"
>
<select
id="camera-controls"
@ -70,6 +71,7 @@ export default function Units() {
</ul>
</SettingsSection>
<OnboardingButtons
currentSlug={onboardingPaths.CAMERA}
dismiss={dismiss}
next={next}
nextText="Next: Streaming"

View File

@ -1,5 +1,5 @@
import usePlatform from 'hooks/usePlatform'
import { OnboardingButtons, useDismiss, useNextClick } from '.'
import { OnboardingButtons, kbdClasses, useDismiss, useNextClick } from '.'
import { onboardingPaths } from 'routes/Onboarding/paths'
import { useStore } from '../../useStore'
@ -24,11 +24,11 @@ export default function CmdK() {
Press{' '}
{platformName === 'darwin' ? (
<>
<kbd></kbd> + <kbd>K</kbd>
<kbd className={kbdClasses}>K</kbd>
</>
) : (
<>
<kbd>Ctrl</kbd> + <kbd>/</kbd>
<kbd className={kbdClasses}>Ctrl + /</kbd>
</>
)}{' '}
to open the command bar. Try changing your theme with it.
@ -44,11 +44,11 @@ export default function CmdK() {
>
XState
</a>
. Currently you can only control settings, authentication, and file
management from the command bar, but we will be powering modeling
commands with it soon.
. 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"

View File

@ -13,7 +13,7 @@ export default function CodeEditor() {
return (
<div className="fixed grid justify-end items-center inset-0 z-50 pointer-events-none">
<div
className="fixed inset-0 bg-black opacity-50 pointer-events-none"
className="fixed inset-0 bg-black opacity-50 dark:opacity-80 pointer-events-none"
style={{ clipPath: useBackdropHighlight('code-pane') }}
></div>
<div
@ -23,24 +23,45 @@ export default function CodeEditor() {
}
>
<section className="flex-1">
<h2 className="text-2xl font-bold">
Editing code with <code>kcl</code>
<h2 className="text-3xl font-bold">
Editing code with{' '}
<span className="text-energy-60 dark:text-energy-20">kcl</span>
</h2>
<p className="my-4">
The left pane is where you write your code. It's a code editor with
syntax highlighting and autocompletion. We've decided to take the
difficult route of writing our own languagecalled <code>kcl</code>
for describing geometry, because we don't want to inherit all the
other functionality from existing languages. We have a lot of ideas
about how <code>kcl</code> will evolve, and we want to hear your
thoughts on it.
kcl is our language for describing geometry. Building our own
language is difficult, but we chose to do it to have a language
honed for spatial relationships and geometric computation. It'll
always be open-source, and we hope it can grow into a new standard
for describing parametric objects.
</p>
<p className="my-4">
We've built a language server for <code>kcl</code> that provides
documentation and autocompletion automatically generated from our
compiler code. You can try it out by hovering over some of the
function names in the pane now. If you like using VSCode, you can
try out our{' '}
The left pane is where you write your code. It's a code editor with
syntax highlighting and autocompletion for kcl. New features arrive
in kcl before they're available as point-and-click tools, so it's
good to have a link to{' '}
<a
href="https://github.com/KittyCAD/modeling-app/blob/main/docs/kcl/std.md"
rel="noreferrer noopener"
target="_blank"
>
our kcl docs
</a>{' '}
handy while you design for now. It's also available in the menu in
the corner of the code pane.
</p>
<p className="my-4">
We've built a{' '}
<a
href="https://github.com/KittyCAD/kcl-lsp"
rel="noreferrer noopener"
target="_blank"
>
language server
</a>{' '}
for kcl that provides documentation and autocompletion automatically
generated from our compiler code. You can try it out by hovering
over some of the function names in the pane now. If you like using
VSCode, you can try out our{' '}
<a
href="https://marketplace.visualstudio.com/items?itemName=KittyCAD.kcl-language-server"
rel="noreferrer noopener"
@ -57,6 +78,7 @@ export default function CodeEditor() {
</p>
</section>
<OnboardingButtons
currentSlug={onboardingPaths.EDITOR}
dismiss={dismiss}
next={next}
nextText="Next: Parametric Modeling"

View File

@ -32,7 +32,7 @@ export default function Export() {
>
our open-source extension proposal
</a>{' '}
for the GLTF file format.{' '}
for the gLTF file format.{' '}
<a
href="https://zoo.dev/docs/api/convert-cad-file"
rel="noopener noreferrer"
@ -43,8 +43,20 @@ export default function Export() {
can convert to and from most common CAD file formats, allowing
export to almost any CAD software.
</p>
<p className="my-4">
Our teammate David is working on the file format, check out{' '}
<a
href="https://www.youtube.com/watch?v=8SuW0qkYCZo"
target="_blank"
rel="noreferrer noopener"
>
his talk with the Metaverse Standards Forum
</a>
!
</p>
</section>
<OnboardingButtons
currentSlug={onboardingPaths.EXPORT}
next={next}
dismiss={dismiss}
nextText="Next: Sketching"

View File

@ -4,6 +4,7 @@ import { bracket } from 'lib/exampleKcl'
import { kclManager } from 'lang/KclSingleton'
import { useModelingContext } from 'hooks/useModelingContext'
import { APP_NAME } from 'lib/constants'
import { onboardingPaths } from './paths'
export default function FutureWork() {
const { send } = useModelingContext()
@ -28,16 +29,39 @@ export default function FutureWork() {
<p className="my-4">
We have curves, cuts, and many more CAD features coming soon. We want
your feedback on this user interface, and we want to know what
features you want to see next. Please message us in the Discord server
and open issues on GitHub.
features you want to see next. Please message us in{' '}
<a
href="https://discord.gg/JQEpHR7Nt2"
target="_blank"
rel="noreferrer noopener"
>
our Discord server
</a>
and{' '}
<a
href="https://github.com/KittyCAD/modeling-app/issues/new/choose"
rel="noreferrer noopener"
target="_blank"
>
open issues on GitHub
</a>
.
</p>
<p className="my-4">
If you make anything with the app we'd love to see it! Thank you for
taking time to try out {APP_NAME}, and build the future of hardware
design with us.
If you make anything with the app we'd love to see it, feel free to{' '}
<a
href="https://twitter.com/zoodotdev"
target="_blank"
rel="noreferrer noopener"
>
tag us on X
</a>
! Thank you for taking time to try out {APP_NAME}, and build the
future of hardware design with us.
</p>
<p className="my-4">💚 The Zoo Team</p>
<OnboardingButtons
currentSlug={onboardingPaths.FUTURE_WORK}
className="mt-6"
dismiss={dismiss}
next={dismiss}

View File

@ -1,4 +1,4 @@
import { OnboardingButtons, useDismiss, useNextClick } from '.'
import { OnboardingButtons, kbdClasses, useDismiss, useNextClick } from '.'
import { onboardingPaths } from 'routes/Onboarding/paths'
import { useStore } from '../../useStore'
import { useBackdropHighlight } from 'hooks/useBackdropHighlight'
@ -23,52 +23,32 @@ export default function InteractiveNumbers() {
}
>
<section className="flex-1 overflow-y-auto mb-6">
<h2 className="text-2xl font-bold">Interactive Numbers</h2>
<h2 className="text-3xl font-bold">Hybrid editing</h2>
<p className="my-4">
Let's do a little bit of hybrid editing to this part.
</p>
<p className="my-4">
Try changing the value of <code>width</code> on line 3 by holding
the <kbd>Alt</kbd> (or <kbd>Option</kbd>) key and dragging the
Try changing the value of <code>width</code> on line 2 by holding
the <kbd className={kbdClasses}>Alt</kbd> (or{' '}
<kbd className={kbdClasses}>Option</kbd>) key and dragging the
number left and right. You can hold down different modifier keys to
change the value by different increments:
</p>
<table className="border-collapse text-sm mx-auto my-4">
<tbody>
<tr>
<td className="border border-solid w-1/2 py-1 px-2 border-chalkboard-40 dark:border-chalkboard-70">
<kbd>Alt + Shift + Cmd/Win</kbd>
</td>
<td className="border border-solid w-1/2 py-1 px-2 border-chalkboard-40 dark:border-chalkboard-70 text-right">
0.01
</td>
</tr>
<tr>
<td className="border border-solid w-1/2 py-1 px-2 border-chalkboard-40 dark:border-chalkboard-70">
<kbd>Alt + Cmd/Win</kbd>
</td>
<td className="border border-solid w-1/2 py-1 px-2 border-chalkboard-40 dark:border-chalkboard-70 text-right">
0.1
</td>
</tr>
<tr>
<td className="border border-solid w-1/2 py-1 px-2 border-chalkboard-40 dark:border-chalkboard-70">
<kbd>Alt</kbd>
</td>
<td className="border border-solid w-1/2 py-1 px-2 border-chalkboard-40 dark:border-chalkboard-70 text-right">
1
</td>
</tr>
<tr>
<td className="border border-solid w-1/2 py-1 px-2 border-chalkboard-40 dark:border-chalkboard-70">
<kbd>Alt + Shift</kbd>
</td>
<td className="border border-solid w-1/2 py-1 px-2 border-chalkboard-40 dark:border-chalkboard-70 text-right">
10
</td>
</tr>
</tbody>
</table>
<ul className="flex flex-col text-sm my-4 mx-12 divide-y divide-chalkboard-20 dark:divide-chalkboard-70">
<li className="flex justify-between m-0 px-0 py-2">
<kbd className={kbdClasses}>Alt + Shift + Cmd/Win</kbd>
±0.01
</li>
<li className="flex justify-between m-0 px-0 py-2">
<kbd className={kbdClasses}>Alt + Cmd/Win</kbd>
±0.1
</li>
<li className="flex justify-between m-0 px-0 py-2">
<kbd className={kbdClasses}>Alt</kbd>±1
</li>
<li className="flex justify-between m-0 px-0 py-2">
<kbd className={kbdClasses}>Alt + Shift</kbd>
±10
</li>
</ul>
<p className="my-4">
Our code editor is built with{' '}
<a
@ -90,13 +70,14 @@ export default function InteractiveNumbers() {
lets you interact with numbers in your code by dragging them around.
</p>
<p className="my-4">
Editing code should feel as interactive as point-and-click when you
want it to be, so that you can work in the way that feels most
We believe editing in Modeling App should feel fluid between code
and point-and-click, so that you can work in the way that feels most
natural to you. We're going to keep extending the text editor, and
we'd love to hear your ideas for how to make it better.
</p>
</section>
<OnboardingButtons
currentSlug={onboardingPaths.INTERACTIVE_NUMBERS}
dismiss={dismiss}
next={next}
nextText="Next: Command Bar"

View File

@ -58,7 +58,7 @@ function OnboardingWithNewFile() {
<div className="max-w-3xl p-8 rounded bg-chalkboard-10 dark:bg-chalkboard-90">
{!isTauri() ? (
<>
<h1 className="text-2xl font-bold text-warn-80 dark:text-warn-10">
<h1 className="text-3xl font-bold text-warn-80 dark:text-warn-10">
Replaying onboarding resets your code
</h1>
<p className="my-4">
@ -77,7 +77,7 @@ function OnboardingWithNewFile() {
</>
) : (
<>
<h1 className="flex flex-wrap items-center gap-4 text-2xl font-bold">
<h1 className="flex flex-wrap items-center gap-4 text-3xl font-bold">
Would you like to create a new project?
</h1>
<section className="my-12">
@ -128,7 +128,7 @@ export default function Introduction() {
return isStarterCode ? (
<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">
<h1 className="flex flex-wrap items-center gap-4 text-2xl font-bold">
<h1 className="flex flex-wrap items-center gap-4 text-3xl font-bold">
<img
src={`/zma-logomark${getLogoTheme()}.svg`}
alt={APP_NAME}
@ -156,11 +156,20 @@ export default function Introduction() {
>
expectations for alpha users here
</a>
. Please give us feedback on your experience! We are trying to
release as early as possible to get feedback from users like you.
, and please give us feedback on your experience{' '}
<a
href="https://discord.com/invite/JQEpHR7Nt2"
target="_blank"
rel="noreferrer noopener"
>
our Discord
</a>
! We are trying to release as early as possible to get feedback from
users like you.
</p>
</section>
<OnboardingButtons
currentSlug={onboardingPaths.INDEX}
className="mt-6"
dismiss={dismiss}
next={next}

View File

@ -25,7 +25,7 @@ export default function ParametricModeling() {
return (
<div className="fixed grid justify-end items-center inset-0 z-50 pointer-events-none">
<div
className="fixed inset-0 bg-black opacity-50 pointer-events-none"
className="fixed inset-0 bg-black dark:bg-black-80 opacity-50 pointer-events-none"
style={{ clipPath: useBackdropHighlight('code-pane') }}
></div>
<div
@ -35,16 +35,21 @@ export default function ParametricModeling() {
}
>
<section className="flex-1 overflow-y-auto mb-6">
<h2 className="text-2xl font-bold">
Towards true parametric modeling
</h2>
<h2 className="text-3xl font-bold">Parametric modeling with kcl</h2>
<p className="my-4">
This example script shows how having access to the code
representation of a part can allow us to do things that are tedious
or impossible in traditional CAD software. Here we are building a
simplified shelf bracket out of aluminum:
This example script shows how a code representation of your design
makes easy work of tedious tasks in traditional CAD software, such
as calculating a safety factor.
</p>
<figure className="my-4 w-3/4 mx-auto">
<p className="my-4">
We've received this sketch from a designer highlighting an{' '}
<em className="text-energy-60 dark:text-energy-20">
aluminum bracket
</em>{' '}
they need for this shelf:
</p>
<figure className="my-4 w-2/3 mx-auto">
<img
src={`/onboarding-bracket${getImageTheme()}.png`}
alt="Bracket"
@ -55,10 +60,12 @@ export default function ParametricModeling() {
</figure>
<p className="my-4">
We are able to easily calculate the thickness of the material based
on the width of the bracket to meet a set safety factor on line 6.
on the width of the bracket to meet a set safety factor on{' '}
<em className="text-energy-60 dark:text-energy-20">line 6</em>.
</p>
</section>
<OnboardingButtons
currentSlug={onboardingPaths.PARAMETRIC_MODELING}
dismiss={dismiss}
next={next}
nextText="Next: Interactive Numbers"

View File

@ -9,6 +9,7 @@ export default function ProjectMenu() {
}))
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.EXPORT)
const tauri = isTauri()
return (
<div className="fixed grid justify-center items-start inset-0 z-50 pointer-events-none">
@ -21,13 +22,47 @@ export default function ProjectMenu() {
<section className="flex-1">
<h2 className="text-2xl font-bold">Project Menu</h2>
<p className="my-4">
Click on the Zoo logo in the upper left to open the project menu.
You can only {isTauri() && 'go home or '}export your modelwhich
we'll talk about next—for now. We'll add more options here soon,
especially as we add support for multi-file assemblies.
Click on your part's name in the upper left to open the project
menu.
{tauri && (
<> You can click the Zoo logo to quickly navigate home.</>
)}
</p>
{tauri ? (
<>
<p className="my-4">
From here you can manage files in your project and export your
current part. Your projects are{' '}
<strong>all saved locally</strong> as a folder on your device.
You can configure where projects are saved in the settings.
</p>
<p className="my-4">
We are working to support assemblies as separate kcl files
importing parts from each other, but for now you can only open
and export individual parts.
</p>
</>
) : (
<>
<p className="my-4">
From here you can export your part. You can't manage separate
files and separate projects from the browser; you have to{' '}
<a
href="https://zoo.dev/modeling-app/download"
target="_blank"
rel="noreferrer noopener"
>
download the desktop app
</a>{' '}
for that. We aren't hosting files for you at this time but are
considering supporting it in the future, so we're building
Modeling App with a browser-first experience in mind.
</p>
</>
)}
</section>
<OnboardingButtons
currentSlug={onboardingPaths.PROJECT_MENU}
next={next}
dismiss={dismiss}
nextText="Next: Export"

View File

@ -39,6 +39,7 @@ export default function Sketching() {
always just modifying and generating code in Zoo Modeling App.
</p>
<OnboardingButtons
currentSlug={onboardingPaths.SKETCHING}
className="mt-6"
next={next}
dismiss={dismiss}

View File

@ -18,18 +18,28 @@ export default function Streaming() {
}
>
<section className="flex-1">
<h2 className="text-2xl font-bold">Streaming Video</h2>
<h2 className="text-3xl font-bold">Streaming Video</h2>
<p className="my-4">
The 3D view is not running on your computer. Instead, our
infrastructure spins up our Geometry Engine on a remote GPU,
Modeling App sends it a series of commands via Websockets and
WebRTC, and the Geometry Engine sends back a video stream of the 3D
view.
Historically, CAD programs run on your computer, so to run
performance-heavy apps you have to have a powerful, expensive
desktop. But the 3D scene you see here is not running on your
computer.
</p>
<p className="my-4">
This means that you could run our Modeling App on a Chromebook, a
tablet, or even a phone, as long as you have a good internet
connection.
Instead, our infrastructure spins up our Geometry Engine on a remote
GPU, Modeling App sends it a series of commands{' '}
<a
href="https://zoo.dev/blog/cad-webrtc"
rel="noopener noreferrer"
target="_blank"
>
via Websockets and WebRTC
</a>
, and the Geometry Engine sends back a video stream of the 3D view.
</p>
<p className="my-4">
This means that you could run our Modeling App on nearly any device
with a good internet connection.
</p>
<p className="my-4">
It also means that whatever tools you build on top of our Geometry
@ -38,6 +48,7 @@ export default function Streaming() {
</p>
</section>
<OnboardingButtons
currentSlug={onboardingPaths.STREAMING}
dismiss={dismiss}
next={next}
nextText="Next: Code Editor"

View File

@ -23,8 +23,21 @@ export default function UserMenu() {
Click your avatar on the upper right to open the user menu. You can
change your settings, sign out, or request a feature.
</p>
<p className="my-4">
We only support global settings at the moment, but we are working to
implement{' '}
<a
href="https://github.com/KittyCAD/modeling-app/issues/1503"
target="_blank"
rel="noreferrer noopener"
>
per-project settings
</a>{' '}
now.
</p>
</section>
<OnboardingButtons
currentSlug={onboardingPaths.USER_MENU}
dismiss={dismiss}
next={next}
nextText="Next: Project Menu"

View File

@ -21,6 +21,8 @@ import { ActionButton } from 'components/ActionButton'
import { onboardingPaths } from 'routes/Onboarding/paths'
export const ONBOARDING_PROJECT_NAME = 'Tutorial Project $nn'
export const kbdClasses =
'p-0.5 text-sm rounded-sm bg-chalkboard-10 dark:bg-chalkboard-100 border border-chalkboard-50'
export const onboardingRoutes = [
{
@ -106,20 +108,40 @@ export function useDismiss() {
}, [send, navigate, filePath])
}
// Get the 1-indexed step number of the current onboarding step
export function useStepNumber(
slug?: (typeof onboardingPaths)[keyof typeof onboardingPaths]
) {
return slug
? slug === onboardingPaths.INDEX
? 1
: onboardingRoutes.findIndex(
(r) => r.path === makeUrlPathRelative(slug)
) + 1
: undefined
}
export function OnboardingButtons({
next,
nextText,
dismiss,
currentSlug,
className,
...props
}: {
next: () => void
nextText?: string
dismiss: () => void
currentSlug?: (typeof onboardingPaths)[keyof typeof onboardingPaths]
className?: string
} & React.HTMLAttributes<HTMLDivElement>) {
const stepNumber = useStepNumber(currentSlug)
return (
<div className={'flex justify-between ' + (className ?? '')} {...props}>
<div
className={'flex items-center justify-between ' + (className ?? '')}
{...props}
>
<ActionButton
Element="button"
onClick={dismiss}
@ -132,6 +154,11 @@ export function OnboardingButtons({
>
Dismiss
</ActionButton>
{stepNumber !== undefined && (
<p className="font-mono text-xs text-center m-0">
{stepNumber} / {onboardingRoutes.length}
</p>
)}
<ActionButton
Element="button"
onClick={next}

View File

@ -12,4 +12,4 @@ export const onboardingPaths = {
MOVE: '/move',
SKETCHING: '/sketching',
FUTURE_WORK: '/future-work',
}
} as const

View File

@ -327,6 +327,7 @@ interface SettingsSectionProps extends React.PropsWithChildren {
title: string
description?: string
className?: string
headingClassName?: string
}
export function SettingsSection({
@ -334,6 +335,7 @@ export function SettingsSection({
description,
className,
children,
headingClassName = 'text-2xl font-bold',
}: SettingsSectionProps) {
return (
<section
@ -343,7 +345,7 @@ export function SettingsSection({
}
>
<div className="w-80">
<h2 className="text-2xl font-bold">{title}</h2>
<h2 className={headingClassName}>{title}</h2>
<p className="mt-2 text-sm">{description}</p>
</div>
<div>{children}</div>