Skip to content

Show "experimental" badges around ML functionality #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: base-sha/6866c9d418663087e674bb32da089b29b6bf72c0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 48 additions & 24 deletions src/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export function Toolbar({

const tooltipContentClassName = !showRichContent
? ''
: '!text-left text-wrap !text-xs !p-0 !pb-2 flex gap-2 !max-w-none !w-72 flex-col items-stretch'
: '!text-left text-wrap !text-xs !p-0 !pb-2 flex !max-w-none !w-72 flex-col items-stretch'
const richContentTimeout = useRef<number | null>(null)
const richContentClearTimeout = useRef<number | null>(null)
// On mouse enter, show rich content after a 1s delay
Expand Down Expand Up @@ -155,9 +155,12 @@ export function Toolbar({
maybeIconConfig: ToolbarItem,
dropdownId?: string
): ToolbarItemResolved {
const isConfiguredAvailable = ['available', 'experimental'].includes(
maybeIconConfig.status
)
const isDisabled =
disableAllButtons ||
maybeIconConfig.status !== 'available' ||
!isConfiguredAvailable ||
maybeIconConfig.disabled?.(state) === true

return {
Expand Down Expand Up @@ -248,7 +251,9 @@ export function Toolbar({
onClick: () => itemConfig.onClick(configCallbackProps),
disabled:
disableAllButtons ||
itemConfig.status !== 'available' ||
!['available', 'experimental'].includes(
itemConfig.status
) ||
itemConfig.disabled === true,
status: itemConfig.status,
}))}
Expand Down Expand Up @@ -276,7 +281,9 @@ export function Toolbar({
aria-pressed={selectedIcon.isActive}
disabled={
disableAllButtons ||
selectedIcon.status !== 'available' ||
!['available', 'experimental'].includes(
selectedIcon.status
) ||
selectedIcon.disabled
}
name={selectedIcon.title}
Expand Down Expand Up @@ -347,7 +354,7 @@ export function Toolbar({
aria-pressed={itemConfig.isActive}
disabled={
disableAllButtons ||
itemConfig.status !== 'available' ||
!['available', 'experimental'].includes(itemConfig.status) ||
itemConfig.disabled
}
onClick={() => itemConfig.onClick(configCallbackProps)}
Expand Down Expand Up @@ -409,7 +416,7 @@ const ToolbarItemTooltip = memo(function ToolbarItemContents({
},
{
enabled:
itemConfig.status === 'available' &&
['available', 'experimental'].includes(itemConfig.status) &&
!!itemConfig.hotkey &&
!itemConfig.disabled &&
!itemConfig.disableHotkey,
Expand Down Expand Up @@ -444,28 +451,47 @@ const ToolbarItemTooltipShortContent = ({
title: string
hotkey?: string | string[]
}) => (
<span
className={`text-sm ${
status !== 'available' ? 'text-chalkboard-70 dark:text-chalkboard-40' : ''
<div
className={`text-sm flex flex-col ${
!['available', 'experimental'].includes(status)
? 'text-chalkboard-70 dark:text-chalkboard-40'
: ''
}`}
>
{title}
{hotkey && (
<kbd className="inline-block ml-2 flex-none hotkey">
{displayHotkeys(hotkey)}
</kbd>
{status === 'experimental' && (
<div className="text-xs flex justify-center item-center gap-1 pb-1 border-b border-chalkboard-50">
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (typo): Possible typo in flex alignment class.

Tailwind's class is 'items-center', not 'item-center'. Please update it.

Suggested change
<div className="text-xs flex justify-center item-center gap-1 pb-1 border-b border-chalkboard-50">
<div className="text-xs flex justify-center items-center gap-1 pb-1 border-b border-chalkboard-50">

<CustomIcon name="beaker" className="w-4 h-4" />
<span>Experimental</span>
</div>
)}
</span>
<div className={`flex gap-4 ${status === 'experimental' ? 'pt-1' : 'p-0'}`}>
{title}
{hotkey && (
<kbd className="inline-block ml-2 flex-none hotkey">
{displayHotkeys(hotkey)}
</kbd>
)}
</div>
</div>
)

const ToolbarItemTooltipRichContent = ({
itemConfig,
}: {
itemConfig: ToolbarItemResolved
}) => {
const shouldBeEnabled = ['available', 'experimental'].includes(
itemConfig.status
)
const { state } = useModelingContext()
return (
<>
{itemConfig.status === 'experimental' && (
<div className="text-xs flex items-center justify-center self-stretch gap-1 p-1 border-b">
<CustomIcon name="beaker" className="w-4 h-4" />
<span className="block">Experimental</span>
</div>
)}
<div className="rounded-top flex items-center gap-2 pt-3 pb-2 px-2 bg-chalkboard-20/50 dark:bg-chalkboard-80/50">
{itemConfig.icon && (
<CustomIcon
Expand All @@ -474,16 +500,14 @@ const ToolbarItemTooltipRichContent = ({
name={itemConfig.icon}
/>
)}
<span
className={`text-sm flex-1 ${
itemConfig.status !== 'available'
? 'text-chalkboard-70 dark:text-chalkboard-40'
: ''
<div
className={`text-sm flex-1 flex flex-col gap-1 ${
!shouldBeEnabled ? 'text-chalkboard-70 dark:text-chalkboard-40' : ''
}`}
>
{itemConfig.title}
</span>
{itemConfig.status === 'available' && itemConfig.hotkey ? (
</div>
{shouldBeEnabled && itemConfig.hotkey ? (
<kbd className="flex-none hotkey">
{displayHotkeys(itemConfig.hotkey)}
</kbd>
Expand Down Expand Up @@ -511,12 +535,12 @@ const ToolbarItemTooltipRichContent = ({
)
)}
</div>
<p className="px-2 text-ch font-sans">{itemConfig.description}</p>
<p className="px-2 my-2 text-ch font-sans">{itemConfig.description}</p>
{/* Add disabled reason if item is disabled */}
{itemConfig.disabled && itemConfig.disabledReason && (
<>
<hr className="border-chalkboard-20 dark:border-chalkboard-80" />
<p className="px-2 text-ch font-sans text-chalkboard-70 dark:text-chalkboard-40">
<p className="px-2 my-2 text-ch font-sans text-chalkboard-70 dark:text-chalkboard-40">
{typeof itemConfig.disabledReason === 'function'
? itemConfig.disabledReason(state)
: itemConfig.disabledReason}
Expand Down
5 changes: 4 additions & 1 deletion src/components/ActionButtonDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type ActionButtonSplitProps = ActionButtonProps & { Element: 'button' } & {
shortcut?: string
onClick: () => void
disabled?: boolean
status?: 'available' | 'unavailable' | 'kcl-only'
status?: 'available' | 'unavailable' | 'kcl-only' | 'experimental'
}[]
}

Expand Down Expand Up @@ -101,6 +101,9 @@ export function ActionButtonDropdown({
{item.shortcut}
</kbd>
) : null}
{item.status === 'experimental' ? (
<CustomIcon name="beaker" className="w-4 h-4" />
) : null}
</button>
</li>
))}
Expand Down
6 changes: 6 additions & 0 deletions src/components/CommandComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ function CommandComboBox({
</p>
)}
</div>
{option.status === 'experimental' && (
<div className="text-xs flex items-center justify-center gap-1 text-primary">
<CustomIcon name="beaker" className="w-4 h-4" />
<span>Experimental</span>
</div>
)}
</Combobox.Option>
))}
</Combobox.Options>
Expand Down
8 changes: 8 additions & 0 deletions src/components/CustomIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ const CustomIconMap = {
/>
</svg>
),
beaker: (
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M13.4747 4.1582L12.5353 6.97363L15.8322 14.3906L15.9015 14.5781C16.1808 15.5181 15.4786 16.5 14.4611 16.5H5.61828C4.50321 16.5 3.77781 15.3265 4.27649 14.3291L7.96008 6.96191L7.02551 4.1582L7.50012 3.5H13.0001L13.4747 4.1582ZM13.6183 11.873C13.2276 11.7045 12.8282 11.6908 12.38 11.7686C11.8504 11.8605 11.3185 12.0648 10.6671 12.2764C9.48553 12.6601 8.08344 12.9938 6.49133 12.1348L5.17102 14.7764C5.00479 15.1088 5.24659 15.5 5.61828 15.5H14.4611C14.8002 15.5 15.0346 15.1727 14.9415 14.8594L14.9181 14.7969L13.6183 11.873ZM8.97473 6.8418L9.04016 7.03809L6.9386 11.2402C8.17525 11.9192 9.24713 11.6862 10.3585 11.3252C10.9385 11.1368 11.5865 10.8913 12.2091 10.7832C12.5041 10.732 12.8059 10.7103 13.1124 10.7344L11.5431 7.20312L11.464 7.02539L11.5255 6.8418L12.3058 4.5H8.19445L8.97473 6.8418Z"
fill="currentColor"
/>
</svg>
),
booleanExclude: (
<svg
viewBox="0 0 20 20"
Expand Down
7 changes: 5 additions & 2 deletions src/lib/commandBarConfigs/applicationCommandConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { SystemIOMachineEvents } from '@src/machines/systemIO/utils'
import { isDesktop } from '@src/lib/isDesktop'
import { kclSamplesManifestWithNoMultipleFiles } from '@src/lib/kclSamples'
import { getUniqueProjectName } from '@src/lib/desktopFS'
import { FILE_EXT } from '@src/lib/constants'
import { FILE_EXT, IS_ML_EXPERIMENTAL } from '@src/lib/constants'
import toast from 'react-hot-toast'
import { reportRejection } from '@src/lib/trap'
import { relevantFileExtensions } from '@src/lang/wasmUtils'
Expand All @@ -17,10 +17,12 @@ export function createApplicationCommands({
}) {
const textToCADCommand: Command = {
name: 'Text-to-CAD',
description: 'Use the Zoo Text-to-CAD API to generate part starters.',
description:
'Generate parts from text prompts. This feature is experimental and undergoing constant improvment, stay tuned for updates.',
displayName: `Text to CAD`,
groupId: 'application',
needsReview: false,
status: IS_ML_EXPERIMENTAL ? 'experimental' : 'active',
icon: 'sparkles',
onSubmit: (record) => {
if (record) {
Expand Down Expand Up @@ -91,6 +93,7 @@ export function createApplicationCommands({
description:
'Add KCL file, Zoo sample, or 3D model to new or existing project.',
needsReview: false,
status: IS_ML_EXPERIMENTAL ? 'experimental' : 'active',
icon: 'importFile',
groupId: 'application',
onSubmit(data) {
Expand Down
7 changes: 5 additions & 2 deletions src/lib/commandBarConfigs/modelingCommandConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type {
StateMachineCommandSetConfig,
} from '@src/lib/commandTypes'
import {
IS_ML_EXPERIMENTAL,
KCL_DEFAULT_CONSTANT_PREFIXES,
KCL_DEFAULT_DEGREE,
KCL_DEFAULT_LENGTH,
Expand Down Expand Up @@ -964,8 +965,10 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
},
},
'Prompt-to-edit': {
description: 'Use Zoo AI to edit your kcl',
icon: 'chat',
description:
'Use Zoo AI to edit your kcl. This feature is experimental and undergoing constant improvment, stay tuned for updates.',
icon: 'sparkles',
status: IS_ML_EXPERIMENTAL ? 'experimental' : 'active',
args: {
selection: {
inputType: 'selectionMixed',
Expand Down
5 changes: 3 additions & 2 deletions src/lib/commandTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export interface KclExpressionWithVariable extends KclExpression {
}
export type KclCommandValue = KclExpression | KclExpressionWithVariable
export type CommandInputType = INPUT_TYPE[number]

type CommandStatus = 'active' | 'development' | 'inactive' | 'experimental'
export type FileFilter = {
name: string
extensions: string[]
Expand Down Expand Up @@ -103,6 +103,7 @@ export type Command<
icon?: Icon
hide?: PLATFORM[number]
hideFromSearch?: boolean
status?: CommandStatus
}

export type CommandConfig<
Expand All @@ -115,7 +116,7 @@ export type CommandConfig<
'name' | 'groupId' | 'onSubmit' | 'onCancel' | 'args' | 'needsReview'
> & {
needsReview?: boolean
status?: 'active' | 'development' | 'inactive'
status?: CommandStatus
args?: {
[ArgName in keyof CommandSchema]: CommandArgumentConfig<
CommandSchema[ArgName],
Expand Down
3 changes: 3 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,6 @@ export type ExecutionType =

/** Key for setting window.localStorage.setItem and .getItem to determine if the runtime is playwright for browsers */
export const IS_PLAYWRIGHT_KEY = 'playwright'

/** Should we mark all the ML features as "beta"? */
export const IS_ML_EXPERIMENTAL = true
3 changes: 3 additions & 0 deletions src/lib/createMachineCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ export function createMachineCommand<
if ('reviewMessage' in commandConfig) {
command.reviewMessage = commandConfig.reviewMessage
}
if ('status' in commandConfig) {
command.status = commandConfig.status
}

return command
}
Expand Down
7 changes: 4 additions & 3 deletions src/lib/toolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
isEditingExistingSketch,
pipeHasCircle,
} from '@src/machines/modelingMachine'
import { IS_ML_EXPERIMENTAL } from './constants'

export type ToolbarModeName = 'modeling' | 'sketching'

Expand All @@ -36,7 +37,7 @@ export type ToolbarItem = {
icon?: CustomIconName
iconColor?: string
alwaysDark?: true
status: 'available' | 'unavailable' | 'kcl-only'
status: 'available' | 'unavailable' | 'kcl-only' | 'experimental'
disabled?: (state: StateFrom<typeof modelingMachine>) => boolean
disableHotkey?: (state: StateFrom<typeof modelingMachine>) => boolean
title: string | ((props: ToolbarItemCallbackProps) => string)
Expand Down Expand Up @@ -440,7 +441,7 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
icon: 'sparkles',
iconColor: '#29FFA4',
alwaysDark: true,
status: 'available',
status: IS_ML_EXPERIMENTAL ? 'experimental' : 'available',
title: 'Create with Zoo Text-to-CAD',
description: 'Create geometry with AI / ML.',
links: [
Expand All @@ -460,7 +461,7 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
icon: 'sparkles',
iconColor: '#29FFA4',
alwaysDark: true,
status: 'available',
status: IS_ML_EXPERIMENTAL ? 'experimental' : 'available',
title: 'Modify with Zoo Text-to-CAD',
description: 'Edit geometry with AI / ML.',
links: [],
Expand Down
14 changes: 14 additions & 0 deletions src/routes/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import {
} from '@src/machines/systemIO/utils'
import type { WebContentSendPayload } from '@src/menu/channels'
import { openExternalBrowserIfDesktop } from '@src/lib/openWindow'
import { CustomIcon } from '@src/components/CustomIcon'
import Tooltip from '@src/components/Tooltip'

type ReadWriteProjectState = {
value: boolean
Expand Down Expand Up @@ -250,6 +252,18 @@ const Home = () => {
data-testid="home-text-to-cad"
>
Generate with Text-to-CAD
<Tooltip position="bottom-left">
<div className="text-sm flex flex-col max-w-xs">
<div className="text-xs flex justify-center item-center gap-1 pb-1 border-b border-chalkboard-50">
<CustomIcon name="beaker" className="w-4 h-4" />
<span>Experimental</span>
</div>
<p className="pt-2 text-left">
This feature is experimental and undergoing constant
improvment, stay tuned for updates.
</p>
</div>
</Tooltip>
</ActionButton>
</li>
<li className="contents">
Expand Down