Compare commits

...

6 Commits

Author SHA1 Message Date
7d6427ab64 Add cursor-not-allowed to onboarding backdrops that block clicks (#6789)
* Add `cursor-not-allowed` to onboarding backdrops that block clicks

Some follow-up feedback after #6714 from @jacebrowning, so that users
know why they can't click around.

* Make anything in the onboarding card `cursor-auto`
2025-05-09 13:28:45 -04:00
4abbe0d57a Result of npm prune (#6807)
pierremtb/adhoc/npm-prune
2025-05-09 17:07:06 +00:00
a631ff689f Remove unnecessary checks for execution completion from onboarding test (#6804)
We don't care if the axial fan loads under 15s on a cheap CI machine, at
least not in this test.
2025-05-09 17:01:42 +00:00
e1d401adfe Remove snapshottoken variable and playwright-secrets.env file (#6801)
* Remove snapshottoken
Fixes #6800

* Add placeholder in .env.development

* Clean up language

* Update CONTRIBUTING.md

Co-authored-by: Jace Browning <jacebrowning@gmail.com>

* Add dotenv to secrets for local testing

* Lint

* Reorg things

* Quick fix

* Last one for windows

---------

Co-authored-by: Jace Browning <jacebrowning@gmail.com>
2025-05-09 12:32:35 -04:00
6f49c88382 Remove dev.zoo.dev from contributing (#6799) 2025-05-09 10:20:22 -04:00
374d07b995 Turn on Billing UI in releases (#6788)
* Turn on Billing UI in releases

* Update most snapshots but one, and new masks
2025-05-09 09:04:45 -04:00
40 changed files with 91 additions and 133 deletions

View File

@ -9,10 +9,11 @@ VITE_KC_SITE_BASE_URL=https://dev.zoo.dev
VITE_KC_SITE_APP_URL=https://app.dev.zoo.dev
VITE_KC_SKIP_AUTH=false
VITE_KC_CONNECTION_TIMEOUT_MS=5000
#VITE_KC_DEV_TOKEN="optional token from dev.zoo.dev to skip auth in the app"
#VITE_KC_DEV_TOKEN="optional token to skip auth in the app"
#token="required token for playwright. TODO: clean up env vars in #3973"
RUST_BACKTRACE=1
PYO3_PYTHON=/usr/local/bin/python3
#KITTYCAD_API_TOKEN="required token from dev.zoo.dev for engine testing"
#KITTYCAD_API_TOKEN="required token for engine testing"
FAIL_ON_CONSOLE_ERRORS=true

View File

@ -229,7 +229,6 @@ jobs:
max_attempts: 5
env:
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
TAB_API_URL: ${{ secrets.TAB_API_URL }}
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}

View File

@ -63,7 +63,7 @@ If you're not a Zoo employee you won't be able to access the dev environment, yo
### Development environment variables
The Copilot LSP plugin in the editor requires a Zoo API token to run. In production, we authenticate this with a token via cookie in the browser and device auth token in the desktop environment, but this token is inaccessible in the dev browser version because the cookie is considered "cross-site" (from `localhost` to `dev.zoo.dev`). There is an optional environment variable called `VITE_KC_DEV_TOKEN` that you can populate with a dev token in a `.env.development.local` file to not check it into Git, which will use that token instead of other methods for the LSP service.
The Copilot LSP plugin in the editor requires a Zoo API token to run. In production, we authenticate this with a token via cookie in the browser and device auth token in the desktop environment, but this token is inaccessible in the dev browser version because the cookie is considered "cross-site" (from `localhost` to `zoo.dev`). There is an optional environment variable called `VITE_KC_DEV_TOKEN` that you can populate with a dev token in a `.env.development.local` file to not check it into Git, which will use that token instead of other methods for the LSP service.
### Developing in Chrome
@ -198,15 +198,9 @@ For more information on fuzzing you can check out
### Playwright tests
You will need a `./e2e/playwright/playwright-secrets.env` file:
Prepare these system dependencies:
```bash
$ touch ./e2e/playwright/playwright-secrets.env
$ cat ./e2e/playwright/playwright-secrets.env
token=<dev.zoo.dev/account/api-tokens>
snapshottoken=<zoo.dev/account/api-tokens>
```
or use `export` to set the environment variables `token` and `snapshottoken`.
- Set $token from https://zoo.dev/account/api-tokens
#### Snapshot tests (Google Chrome on Ubuntu only)
@ -302,7 +296,7 @@ Which will run our suite of [Vitest unit](https://vitest.dev/) and [React Testin
Prepare these system dependencies:
- Set `$KITTYCAD_API_TOKEN` from https://dev.zoo.dev/account/api-tokens
- Set `$KITTYCAD_API_TOKEN` from https://zoo.dev/account/api-tokens
- Install `just` following [these instructions](https://just.systems/man/en/packages.html)
then run tests that target the KCL language:

View File

@ -1,5 +1,5 @@
import type { Locator, Page } from '@playwright/test'
import { secrets } from '@e2e/playwright/secrets'
import { token } from '@e2e/playwright/test-utils'
export class SignInPageFixture {
public page: Page
@ -25,7 +25,7 @@ export class SignInPageFixture {
// Device flow: stolen from the tauri days
// https://github.com/KittyCAD/modeling-app/blob/d916c7987452e480719004e6d11fd2e595c7d0eb/e2e/tauri/specs/app.spec.ts#L19
const headers = {
Authorization: `Bearer ${secrets.token}`,
Authorization: `Bearer ${token}`,
Accept: 'application/json',
'Content-Type': 'application/json',
}

View File

@ -63,7 +63,6 @@ test.describe('Onboarding tests', () => {
shouldNormalise: true,
})
await scene.connectionEstablished()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
})
await test.step('Go home and verify we still see the tutorial button, then begin it.', async () => {
@ -91,8 +90,6 @@ test.describe('Onboarding tests', () => {
await test.step('Ensure we see the welcome screen in a new project', async () => {
await expect(toolbar.projectName).toContainText('tutorial-project')
await expect(tutorialWelcomeHeading).toBeVisible()
await scene.connectionEstablished()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
})
await test.step('Test the clicking through the onboarding flow', async () => {
@ -132,8 +129,6 @@ test.describe('Onboarding tests', () => {
await test.step('Gets to the onboarding start', async () => {
await expect(toolbar.projectName).toContainText('tutorial-project')
await expect(tutorialWelcomeHeading).toBeVisible()
await scene.connectionEstablished()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
})
await test.step('Dismiss the onboarding', async () => {
@ -168,7 +163,6 @@ test.describe('Onboarding tests', () => {
await expect(toolbar.projectName).toContainText('tutorial-project')
await expect(tutorialWelcomeHeading).toBeVisible()
await scene.connectionEstablished()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
})
await test.step('Dismiss the onboarding', async () => {

View File

@ -1,28 +0,0 @@
import { readFileSync } from 'fs'
const secrets: Record<string, string> = {}
const secretsPath = './e2e/playwright/playwright-secrets.env'
try {
const file = readFileSync(secretsPath, 'utf8')
file
.split('\n')
.filter((line) => line && line.length > 1)
.forEach((line) => {
// Allow line comments.
if (line.trimStart().startsWith('#')) return
const [key, value] = line.split('=')
// prefer env vars over secrets file
secrets[key] = process.env[key] || (value as any).replaceAll('"', '')
})
} catch (error: unknown) {
void error
// probably running in CI
console.warn(
`Error reading ${secretsPath}; environment variables will be used`
)
}
secrets.token = secrets.token || process.env.token || ''
secrets.snapshottoken = secrets.snapshottoken || process.env.snapshottoken || ''
// add more env vars here to make them available in CI
export { secrets }

View File

@ -5,7 +5,7 @@ import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
import {
getUtils,
headerMasks,
networkingMasks,
lowerRightMasks,
settingsToToml,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
@ -88,7 +88,7 @@ const extrudeDefaultPlane = async (
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
await u.openKclCodePanel()
}
@ -173,7 +173,7 @@ test(
await page.waitForTimeout(500)
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
const lineEndClick = () =>
@ -200,7 +200,7 @@ test(
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
await endOfTangentClk()
@ -210,7 +210,7 @@ test(
await threePointArcMidPointMv()
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
await threePointArcMidPointClk()
await page.waitForTimeout(100)
@ -219,7 +219,7 @@ test(
await page.waitForTimeout(500)
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
await threePointArcEndPointClk()
@ -239,7 +239,7 @@ test(
await page.waitForTimeout(500)
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
await arcEndClk()
}
@ -286,7 +286,7 @@ test(
// Ensure the draft rectangle looks the same as it usually does
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
}
)
@ -328,7 +328,7 @@ test(
// Ensure the draft rectangle looks the same as it usually does
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
await expect(page.locator('.cm-content')).toHaveText(
`sketch001 = startSketchOn(XZ)profile001 = circle(sketch001, center = [366.89, -62.01], radius = 1)`
@ -395,7 +395,7 @@ test.describe(
// screen shot should show the sketch
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
await u.doAndWaitForImageDiff(
@ -408,7 +408,7 @@ test.describe(
// second screen shot should look almost identical, i.e. scale should be the same.
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
})
@ -490,7 +490,7 @@ test.describe(
// screen shot should show the sketch
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
// exit sketch
@ -504,7 +504,7 @@ test.describe(
// second screen shot should look almost identical, i.e. scale should be the same.
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
})
}
@ -563,7 +563,7 @@ part002 = startSketchOn(part001, face = seg01)
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
}
)
@ -599,7 +599,7 @@ test(
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
}
)
@ -636,7 +636,7 @@ test(
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
}
)
@ -701,7 +701,7 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await expect(stream).toHaveScreenshot({
maxDiffPixels: 100,
mask: [...headerMasks(page), ...networkingMasks(page)],
mask: [...headerMasks(page), ...lowerRightMasks(page)],
})
})
@ -722,7 +722,7 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await expect(stream).toHaveScreenshot({
maxDiffPixels: 100,
mask: [...headerMasks(page), ...networkingMasks(page)],
mask: [...headerMasks(page), ...lowerRightMasks(page)],
})
})
@ -761,7 +761,7 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await expect(stream).toHaveScreenshot({
maxDiffPixels: 100,
mask: [...headerMasks(page), ...networkingMasks(page)],
mask: [...headerMasks(page), ...lowerRightMasks(page)],
})
})
})
@ -829,7 +829,7 @@ test('theme persists', async ({ page, context }) => {
await expect(page, 'expect screenshot to have light theme').toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
})
@ -870,7 +870,7 @@ sweepSketch = startSketchOn(XY)
await expect(page, 'expect small color widget').toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
})
@ -923,7 +923,7 @@ sweepSketch = startSketchOn(XY)
'expect small color widget to have window open'
).toHaveScreenshot({
maxDiffPixels: 100,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
})
})
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -13,11 +13,15 @@ import fsp from 'fs/promises'
import pixelMatch from 'pixelmatch'
import type { Protocol } from 'playwright-core/types/protocol'
import { PNG } from 'pngjs'
import dotenv from 'dotenv'
const NODE_ENV = process.env.NODE_ENV || 'development'
dotenv.config({ path: [`.env.${NODE_ENV}.local`, `.env.${NODE_ENV}`] })
export const token = process.env.token || ''
import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
import { isErrorWhitelisted } from '@e2e/playwright/lib/console-error-whitelist'
import { secrets } from '@e2e/playwright/secrets'
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
import { test } from '@e2e/playwright/zoo-test'
@ -31,8 +35,9 @@ export const headerMasks = (page: Page) => [
page.locator('#sidebar-bottom-ribbon'),
]
export const networkingMasks = (page: Page) => [
export const lowerRightMasks = (page: Page) => [
page.getByTestId('network-toggle'),
page.getByTestId('billing-remaining-bar'),
]
export type TestColor = [number, number, number]
@ -890,7 +895,7 @@ export async function setup(
localStorage.setItem('PLAYWRIGHT_TEST_DIR', PLAYWRIGHT_TEST_DIR)
},
{
token: secrets.token,
token,
settingsKey: TEST_SETTINGS_KEY,
settings: settingsToToml({
settings: {
@ -918,7 +923,7 @@ export async function setup(
await context.addCookies([
{
name: COOKIE_NAME,
value: secrets.token,
value: token,
path: '/',
domain: 'localhost',
secure: true,

View File

@ -20,7 +20,7 @@ import {
createProject,
executorInputPath,
getUtils,
networkingMasks,
lowerRightMasks,
settingsToToml,
tomlToSettings,
} from '@e2e/playwright/test-utils'
@ -1061,7 +1061,7 @@ fn cube`
'toggle-settings-initial.png',
{
maxDiffPixels: 15,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
}
)
@ -1078,7 +1078,7 @@ fn cube`
'toggle-settings-initial.png',
{
maxDiffPixels: 15,
mask: networkingMasks(page),
mask: lowerRightMasks(page),
}
)
})

1
package-lock.json generated
View File

@ -2492,7 +2492,6 @@
},
"node_modules/@clack/prompts/node_modules/is-unicode-supported": {
"version": "1.3.0",
"extraneous": true,
"inBundle": true,
"license": "MIT",
"engines": {

View File

@ -137,8 +137,8 @@
"test:unit:components": "jest -c jest-component-unit-tests/jest.config.ts --rootDir jest-component-unit-tests/",
"test:unit:kcl-samples": "vitest run --mode development ./src/lang/kclSamples.test.ts",
"test:playwright:electron": "playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot",
"test:playwright:electron:local": "npm run tronb:vite:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot --grep-invert=\"$(curl --silent https://test-analysis-bot.hawk-dinosaur.ts.net/projects/KittyCAD/modeling-app/tests/disabled/regex)\"",
"test:playwright:electron:local-engine": "npm run tronb:vite:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert='@snapshot|@skipLocalEngine' --grep-invert=\"$(curl --silent https://test-analysis-bot.hawk-dinosaur.ts.net/projects/KittyCAD/modeling-app/tests/disabled/regex)\"",
"test:playwright:electron:local": "npm run tronb:vite:dev && playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot --grep-invert=\"$(curl --silent https://test-analysis-bot.hawk-dinosaur.ts.net/projects/KittyCAD/modeling-app/tests/disabled/regex)\"",
"test:playwright:electron:local-engine": "npm run tronb:vite:dev && playwright test --config=playwright.electron.config.ts --grep-invert='@snapshot|@skipLocalEngine' --grep-invert=\"$(curl --silent https://test-analysis-bot.hawk-dinosaur.ts.net/projects/KittyCAD/modeling-app/tests/disabled/regex)\"",
"test:unit:local": "npm run simpleserver:bg && npm run test:unit; kill-port 3000",
"test:unit:kcl-samples:local": "npm run simpleserver:bg && npm run test:unit:kcl-samples; kill-port 3000"
},

View File

@ -14,11 +14,7 @@ import Tooltip from '@src/components/Tooltip'
import { useAbsoluteFilePath } from '@src/hooks/useAbsoluteFilePath'
import { openExternalBrowserIfDesktop } from '@src/lib/openWindow'
import { PATHS } from '@src/lib/paths'
import {
APP_VERSION,
IS_NIGHTLY_OR_DEBUG,
getReleaseUrl,
} from '@src/routes/utils'
import { APP_VERSION, getReleaseUrl } from '@src/routes/utils'
import { billingActor } from '@src/lib/singletons'
@ -39,22 +35,23 @@ export function LowerRightControls({
<section className="fixed bottom-2 right-2 flex flex-col items-end gap-3 pointer-events-none">
{children}
<menu className="flex items-center justify-end gap-3 pointer-events-auto">
{IS_NIGHTLY_OR_DEBUG && (
<Popover className="relative">
<Popover.Button className="p-0 !border-transparent">
<BillingRemaining
mode={BillingRemainingMode.ProgressBarFixed}
billingActor={billingActor}
/>
<Tooltip position="top" contentClassName="text-xs">
Text-to-CAD credits
</Tooltip>
</Popover.Button>
<Popover.Panel className="absolute right-0 left-auto bottom-full mb-1 w-64 flex flex-col gap-1 align-stretch rounded-lg shadow-lg text-sm">
<BillingDialog billingActor={billingActor} />
</Popover.Panel>
</Popover>
)}
<Popover className="relative">
<Popover.Button
className="p-0 !border-transparent"
data-testid="billing-remaining-bar"
>
<BillingRemaining
mode={BillingRemainingMode.ProgressBarFixed}
billingActor={billingActor}
/>
<Tooltip position="top" contentClassName="text-xs">
Text-to-CAD credits
</Tooltip>
</Popover.Button>
<Popover.Panel className="absolute right-0 left-auto bottom-full mb-1 w-64 flex flex-col gap-1 align-stretch rounded-lg shadow-lg text-sm">
<BillingDialog billingActor={billingActor} />
</Popover.Panel>
</Popover>
<a
onClick={openExternalBrowserIfDesktop(getReleaseUrl())}
href={getReleaseUrl()}

View File

@ -1,4 +1,3 @@
import { IS_NIGHTLY_OR_DEBUG } from '@src/routes/utils'
import type { FormEvent, HTMLProps } from 'react'
import { useEffect } from 'react'
import { toast } from 'react-hot-toast'
@ -351,13 +350,11 @@ const Home = () => {
</li>
</ul>
<ul className="flex flex-col">
{IS_NIGHTLY_OR_DEBUG && (
<li className="contents">
<div className="my-2">
<BillingDialog billingActor={billingActor} />
</div>
</li>
)}
<li className="contents">
<div className="my-2">
<BillingDialog billingActor={billingActor} />
</div>
</li>
<li className="contents">
<ActionButton
Element="externalLink"

View File

@ -79,7 +79,7 @@ function Welcome() {
}, [])
return (
<div className="fixed inset-0 z-50 grid items-end justify-center p-2">
<div className="cursor-not-allowed fixed inset-0 z-50 grid items-end justify-center p-2">
<OnboardingCard>
<h1 className="text-xl font-bold">Welcome to Zoo Design Studio</h1>
<p className="my-4">
@ -149,7 +149,7 @@ function Toolbar() {
useOnboardingPanes()
return (
<div className="fixed inset-0 z-[99] grid items-start justify-center p-16">
<div className="cursor-not-allowed fixed inset-0 z-[99] grid items-start justify-center p-16">
<OnboardingCard>
<h1 className="text-xl font-bold">This is the toolbar</h1>
<p className="my-4">
@ -170,7 +170,7 @@ function TextToCad() {
useOnboardingPanes()
return (
<div className="fixed inset-0 z-50 grid items-start justify-center p-16">
<div className="cursor-not-allowed fixed inset-0 z-50 grid items-start justify-center p-16">
<OnboardingCard>
<h1 className="text-xl font-bold">Text-to-CAD</h1>
<p className="my-4">
@ -229,7 +229,7 @@ function TextToCadPrompt() {
useAdvanceOnboardingOnFormSubmit(thisOnboardingStatus)
return (
<div className="fixed inset-0 z-[99] grid items-center justify-center">
<div className="cursor-not-allowed fixed inset-0 z-[99] grid items-center justify-center">
<OnboardingCard>
<h1 className="text-xl font-bold">Text-to-CAD prompt</h1>
<p className="my-4">
@ -325,7 +325,7 @@ function PromptToEdit() {
useAdvanceOnboardingOnFormSubmit(thisOnboardingStatus)
return (
<div className="fixed inset-0 z-50 grid items-center justify-center p-16">
<div className="cursor-not-allowed fixed inset-0 z-50 grid items-center justify-center p-16">
<OnboardingCard className="col-start-3 col-span-2">
<h1 className="text-xl font-bold">Modify with Zoo Text-to-CAD</h1>
<p className="my-4">
@ -381,7 +381,7 @@ function PromptToEditPrompt() {
useAdvanceOnboardingOnFormSubmit(thisOnboardingStatus)
return (
<div className="fixed inset-0 z-[99] grid items-center justify-center">
<div className="cursor-not-allowed fixed inset-0 z-[99] grid items-center justify-center">
<OnboardingCard className="pointer-events-auto">
<h1 className="text-xl font-bold">Modify with Text-to-CAD prompt</h1>
{!isReady && (
@ -429,7 +429,7 @@ function PromptToEditResult() {
}, [])
return (
<div className="fixed inset-0 z-[99] p-8 grid justify-center items-end">
<div className="cursor-not-allowed fixed inset-0 z-[99] p-8 grid justify-center items-end">
<OnboardingCard className="col-start-3 col-span-2">
<h1 className="text-xl font-bold">Result</h1>
<p className="my-4">
@ -462,7 +462,7 @@ function OnboardingConclusion() {
useOnboardingPanes()
return (
<div className="fixed inset-0 z-50 p-16 grid justify-center items-center">
<div className="cursor-not-allowed fixed inset-0 z-50 p-16 grid justify-center items-center">
<OnboardingCard>
<h1 className="text-xl font-bold">Download the desktop app</h1>
<p className="my-4">

View File

@ -78,7 +78,7 @@ function Welcome() {
}, [loaderData?.project?.name])
return (
<div className="fixed inset-0 z-50 grid items-end justify-center p-2">
<div className="cursor-not-allowed fixed inset-0 z-50 grid items-end justify-center p-2">
<OnboardingCard>
<h1 className="text-xl font-bold">Welcome to Zoo Design Studio</h1>
<p className="my-4">
@ -140,7 +140,7 @@ function Toolbar() {
useOnboardingPanes()
return (
<div className="fixed inset-0 z-[99] grid items-start justify-center p-16">
<div className="cursor-not-allowed fixed inset-0 z-[99] grid items-start justify-center p-16">
<OnboardingCard>
<h1 className="text-xl font-bold">This is the toolbar</h1>
<p className="my-4">
@ -161,7 +161,7 @@ function TextToCad() {
useOnboardingPanes()
return (
<div className="fixed inset-0 z-50 grid items-start justify-center p-16">
<div className="cursor-not-allowed fixed inset-0 z-50 grid items-start justify-center p-16">
<OnboardingCard>
<h1 className="text-xl font-bold">Text-to-CAD</h1>
<p className="my-4">
@ -220,7 +220,7 @@ function TextToCadPrompt() {
useAdvanceOnboardingOnFormSubmit(thisOnboardingStatus, 'desktop')
return (
<div className="fixed inset-0 z-[99] grid items-center justify-center">
<div className="cursor-not-allowed fixed inset-0 z-[99] grid items-center justify-center">
<OnboardingCard className="pointer-events-auto">
<h1 className="text-xl font-bold">Text-to-CAD prompt</h1>
<p className="my-4">
@ -266,7 +266,7 @@ function FeatureTreePane() {
}, [])
return (
<div className="fixed inset-0 z-[99] p-8 grid justify-center items-end">
<div className="cursor-not-allowed fixed inset-0 z-[99] p-8 grid justify-center items-end">
<OnboardingCard className="col-start-3 col-span-2">
<h1 className="text-xl font-bold">CPU Fan Housing</h1>
<p className="my-4">
@ -297,7 +297,7 @@ function CodePane() {
useOnboardingPanes(['code'])
return (
<div className="fixed inset-0 z-50 p-8 grid justify-center items-end">
<div className="cursor-not-allowed fixed inset-0 z-50 p-8 grid justify-center items-end">
<OnboardingCard className="col-start-3 col-span-2">
<h1 className="text-xl font-bold">KCL Code</h1>
<p className="my-4">
@ -328,7 +328,7 @@ function ProjectPane() {
useOnboardingPanes(['files'])
return (
<div className="fixed inset-0 z-50 p-8 grid justify-center items-end">
<div className="cursor-not-allowed fixed inset-0 z-50 p-8 grid justify-center items-end">
<OnboardingCard className="col-start-3 col-span-2">
<h1 className="text-xl font-bold">Files Pane</h1>
<p className="my-4">
@ -355,7 +355,7 @@ function OtherPanes() {
useOnboardingPanes(['logs', 'variables'])
return (
<div className="fixed inset-0 z-50 p-8 grid justify-center items-end">
<div className="cursor-not-allowed fixed inset-0 z-50 p-8 grid justify-center items-end">
<OnboardingCard className="col-start-3 col-span-2">
<h1 className="text-xl font-bold">Other panes</h1>
<p className="my-4">
@ -400,7 +400,7 @@ function PromptToEdit() {
useAdvanceOnboardingOnFormSubmit(thisOnboardingStatus, 'desktop')
return (
<div className="fixed inset-0 z-50 p-8 grid justify-center items-center">
<div className="cursor-not-allowed fixed inset-0 z-50 p-8 grid justify-center items-center">
<OnboardingCard className="col-start-3 col-span-2">
<h1 className="text-xl font-bold">Modify with Zoo Text-to-CAD</h1>
<p className="my-4">
@ -456,7 +456,7 @@ function PromptToEditPrompt() {
useAdvanceOnboardingOnFormSubmit(thisOnboardingStatus, 'desktop')
return (
<div className="fixed inset-0 z-[99] grid items-center justify-center">
<div className="cursor-not-allowed fixed inset-0 z-[99] grid items-center justify-center">
<OnboardingCard className="pointer-events-auto">
<h1 className="text-xl font-bold">Modify with Text-to-CAD prompt</h1>
{!isReady && (
@ -510,7 +510,7 @@ function PromptToEditResult() {
}, [])
return (
<div className="fixed inset-0 z-[99] p-8 grid justify-center items-end">
<div className="cursor-not-allowed fixed inset-0 z-[99] p-8 grid justify-center items-end">
<OnboardingCard className="col-start-3 col-span-2">
<h1 className="text-xl font-bold">Result</h1>
<p className="my-4">
@ -548,7 +548,7 @@ function Imports() {
useOnboardingPanes()
return (
<div className="fixed inset-0 z-50 p-16 flex flex-col gap-8 items-center">
<div className="cursor-not-allowed fixed inset-0 z-50 p-16 flex flex-col gap-8 items-center">
<OnboardingCard>
<h1 className="text-xl font-bold">Add file(s) to project</h1>
<p className="my-4">
@ -579,7 +579,7 @@ function Exports() {
useOnboardingPanes()
return (
<div className="fixed inset-0 z-50 p-16 grid justify-start items-center">
<div className="cursor-not-allowed fixed inset-0 z-50 p-16 grid justify-start items-center">
<OnboardingCard>
<h1 className="text-xl font-bold">Exporting</h1>
<p className="my-4">
@ -607,7 +607,7 @@ function OnboardingConclusion() {
)
return (
<div className="fixed inset-0 z-50 p-16 grid justify-center items-center">
<div className="cursor-not-allowed fixed inset-0 z-50 p-16 grid justify-center items-center">
<OnboardingCard>
<h1 className="text-xl font-bold">Time to start building</h1>
<p className="my-4">

View File

@ -54,7 +54,7 @@ export const OnboardingCard = ({
...props
}: React.HTMLAttributes<HTMLDivElement>) => (
<div
className={`relative max-w-3xl min-w-80 bg-chalkboard-10 dark:bg-chalkboard-90 py-6 px-8 rounded border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg ${className || ''}`}
className={`relative max-w-3xl min-w-80 cursor-auto bg-chalkboard-10 dark:bg-chalkboard-90 py-6 px-8 rounded border border-chalkboard-50 dark:border-chalkboard-80 shadow-lg ${className || ''}`}
{...props}
>
{children}