Skip to content

Commit dc8731d

Browse files
authored
Add Clear button for non required args (#7775)
* Add Clear button for non required args Fixes #7772 * Add pw test steps for clear button
1 parent fa7633f commit dc8731d

File tree

4 files changed

+153
-32
lines changed

4 files changed

+153
-32
lines changed

e2e/playwright/command-bar-tests.spec.ts

Lines changed: 99 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ test.describe('Command bar tests', () => {
250250
page,
251251
homePage,
252252
cmdBar,
253+
scene,
254+
editor,
253255
}) => {
254256
await page.addInitScript(async () => {
255257
localStorage.setItem(
@@ -265,20 +267,9 @@ test.describe('Command bar tests', () => {
265267
)
266268
})
267269

268-
const u = await getUtils(page)
269270
await page.setBodyDimensions({ width: 1200, height: 500 })
270-
271271
await homePage.goToModelingScene()
272-
273-
// Make sure the stream is up
274-
await u.openDebugPanel()
275-
await u.expectCmdLog('[data-message-type="execution-done"]')
276-
277-
await expect(
278-
page.getByRole('button', { name: 'Start Sketch' })
279-
).not.toBeDisabled()
280-
await u.clearCommandLogs()
281-
await page.getByRole('button', { name: 'Extrude' }).isEnabled()
272+
await scene.settled(cmdBar)
282273

283274
let cmdSearchBar = page.getByPlaceholder('Search commands')
284275
await page.keyboard.press('ControlOrMeta+K')
@@ -288,44 +279,121 @@ test.describe('Command bar tests', () => {
288279
await cmdBar.cmdOptions.getByText('Extrude').click()
289280

290281
// Assert that we're on the selection step
291-
await expect(page.getByRole('button', { name: 'Profiles' })).toBeDisabled()
282+
await cmdBar.expectState({
283+
stage: 'arguments',
284+
commandName: 'Extrude',
285+
currentArgKey: 'sketches',
286+
currentArgValue: '',
287+
headerArguments: {
288+
Profiles: '',
289+
Length: '',
290+
},
291+
highlightedHeaderArg: 'Profiles',
292+
})
292293
// Select a face
293-
await page.mouse.move(700, 200)
294-
await page.mouse.click(700, 200)
294+
await editor.selectText('startProfile(at = [-6.95, 10.98])')
295295
await cmdBar.progressCmdBar()
296296

297297
// Assert that we're on the distance step
298-
await expect(
299-
page.getByRole('button', { name: 'length', exact: false })
300-
).toBeDisabled()
298+
await cmdBar.expectState({
299+
stage: 'arguments',
300+
commandName: 'Extrude',
301+
currentArgKey: 'length',
302+
currentArgValue: '5',
303+
headerArguments: {
304+
Profiles: '1 profile',
305+
Length: '',
306+
},
307+
highlightedHeaderArg: 'length',
308+
})
301309

302310
// Assert that the an alternative variable name is chosen,
303311
// since the default variable name is already in use (distance)
304312
await cmdBar.variableCheckbox.click()
305313
await expect(page.getByPlaceholder('Variable name')).toHaveValue(
306314
'length001'
307315
)
308-
309-
const continueButton = page.getByRole('button', { name: 'Continue' })
310-
const submitButton = page.getByTestId('command-bar-submit')
311-
await continueButton.click()
316+
await cmdBar.progressCmdBar()
312317

313318
// Review step and argument hotkeys
314-
await expect(submitButton).toBeEnabled()
315-
await expect(submitButton).toBeFocused()
316-
await submitButton.press('Shift+Backspace')
319+
await cmdBar.expectState({
320+
stage: 'review',
321+
commandName: 'Extrude',
322+
headerArguments: {
323+
Profiles: '1 profile',
324+
Length: '5',
325+
},
326+
})
327+
await page.keyboard.press('Shift+Backspace')
317328

318329
// Assert we're back on the distance step
319330
await expect(
320331
page.getByRole('button', { name: 'length', exact: false })
321332
).toBeDisabled()
322333

323-
await continueButton.click()
324-
await submitButton.click()
334+
await cmdBar.progressCmdBar()
325335

326-
await u.waitForCmdReceive('extrude')
336+
// Add optional arg
337+
await cmdBar.expectState({
338+
stage: 'review',
339+
commandName: 'Extrude',
340+
headerArguments: {
341+
Profiles: '1 profile',
342+
Length: '5',
343+
},
344+
})
345+
await cmdBar.clickOptionalArgument('bidirectionalLength')
346+
await cmdBar.expectState({
347+
stage: 'arguments',
348+
commandName: 'Extrude',
349+
currentArgKey: 'bidirectionalLength',
350+
currentArgValue: '',
351+
headerArguments: {
352+
Profiles: '1 profile',
353+
Length: '5',
354+
BidirectionalLength: '',
355+
},
356+
highlightedHeaderArg: 'bidirectionalLength',
357+
})
358+
await page.keyboard.type('10') // Set bidirectional length
359+
await cmdBar.progressCmdBar()
360+
await cmdBar.expectState({
361+
stage: 'review',
362+
commandName: 'Extrude',
363+
headerArguments: {
364+
Profiles: '1 profile',
365+
Length: '5',
366+
BidirectionalLength: '10',
367+
},
368+
})
327369

328-
await expect(page.locator('.cm-content')).toContainText(
370+
// Clear optional arg
371+
await page.getByRole('button', { name: 'BidirectionalLength' }).click()
372+
await cmdBar.expectState({
373+
stage: 'arguments',
374+
commandName: 'Extrude',
375+
currentArgKey: 'bidirectionalLength',
376+
currentArgValue: '10',
377+
headerArguments: {
378+
Profiles: '1 profile',
379+
Length: '5',
380+
BidirectionalLength: '10',
381+
},
382+
highlightedHeaderArg: 'bidirectionalLength',
383+
})
384+
await cmdBar.clearNonRequiredButton.click()
385+
await cmdBar.expectState({
386+
stage: 'review',
387+
commandName: 'Extrude',
388+
headerArguments: {
389+
Profiles: '1 profile',
390+
Length: '5',
391+
},
392+
})
393+
394+
await cmdBar.progressCmdBar()
395+
await scene.settled(cmdBar)
396+
await editor.expectEditor.toContain(
329397
'extrude001 = extrude(sketch001, length = length001)'
330398
)
331399
})
@@ -659,6 +727,8 @@ theta = 45deg
659727
)
660728
})
661729

730+
// TODO: add pw test for clear non-required arg button
731+
662732
test('Command palette can be opened via query parameter', async ({
663733
page,
664734
homePage,

e2e/playwright/fixtures/cmdBarFixture.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ export class CmdBarFixture {
160160
await expect(this.cmdBarElement).not.toBeVisible()
161161
}
162162

163+
get clearNonRequiredButton() {
164+
return this.page.getByTestId('command-bar-clear-non-required-button')
165+
}
166+
163167
get cmdSearchInput() {
164168
return this.page.getByTestId('cmd-bar-search')
165169
}

src/components/CommandBar/CommandBarArgument.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,20 @@ function CommandBarArgument({ stepBack }: { stepBack: () => void }) {
2727
})
2828
}
2929

30+
function clear() {
31+
if (!currentArgument) return
32+
33+
commandBarActor.send({
34+
type: 'Submit argument',
35+
data: {
36+
[currentArgument.name]: undefined,
37+
},
38+
})
39+
}
40+
3041
return (
3142
currentArgument && (
32-
<CommandBarHeaderFooter stepBack={stepBack}>
43+
<CommandBarHeaderFooter stepBack={stepBack} clear={clear}>
3344
<ArgumentInput
3445
arg={currentArgument}
3546
stepBack={stepBack}

src/components/CommandBar/CommandBarHeaderFooter.tsx

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ import { commandBarActor, useCommandBarState } from '@src/lib/singletons'
1818
function CommandBarHeaderFooter({
1919
children,
2020
stepBack,
21-
}: React.PropsWithChildren<object> & { stepBack: () => void }) {
21+
clear,
22+
}: React.PropsWithChildren<object> & {
23+
stepBack: () => void
24+
clear?: () => void
25+
}) {
2226
const commandBarState = useCommandBarState()
2327
const {
2428
context: { selectedCommand, currentArgument, argumentsToSubmit },
@@ -38,6 +42,10 @@ function CommandBarHeaderFooter({
3842
}, [selectedCommand])
3943
const isReviewing = commandBarState.matches('Review')
4044
const [showShortcuts, setShowShortcuts] = useState(false)
45+
const isCurrentArgRequired =
46+
typeof currentArgument?.required === 'function'
47+
? currentArgument.required(commandBarState.context)
48+
: currentArgument?.required
4149

4250
useHotkeys(
4351
'alt',
@@ -221,8 +229,10 @@ function CommandBarHeaderFooter({
221229
</div>
222230
<CommandBarDivider />
223231
{children}
224-
<div className="px-4 pb-2 flex justify-between items-center gap-2">
232+
<div className="px-4 pb-2 flex items-center gap-2">
225233
<StepBackButton stepBack={stepBack} />
234+
{!isCurrentArgRequired && clear && <ClearButton clear={clear} />}
235+
<div className="flex-grow"></div>
226236
{isReviewing ? (
227237
<ReviewingButton
228238
bgClassName={
@@ -334,4 +344,30 @@ function StepBackButton({
334344
)
335345
}
336346

347+
function ClearButton({
348+
bgClassName,
349+
iconClassName,
350+
clear,
351+
}: ButtonProps & { clear: () => void }) {
352+
return (
353+
<ActionButton
354+
Element="button"
355+
type="button"
356+
form="arg-form"
357+
className={`w-fit !p-0 rounded-sm hover:brightness-110 hover:shadow focus:outline-current bg-chalkboard-20/50 dark:bg-chalkboard-80/50 border-chalkboard-20 dark:border-chalkboard-80 ${bgClassName}`}
358+
tabIndex={0}
359+
data-testid="command-bar-clear-non-required-button"
360+
iconStart={{
361+
icon: 'trash',
362+
bgClassName: `p-1 rounded-sm bg-chalkboard-20/50 dark:bg-chalkboard-80/50 ${bgClassName}`,
363+
iconClassName: `${iconClassName}`,
364+
}}
365+
onClick={clear}
366+
>
367+
<span className={`pr-2 ${iconClassName}`}>Clear</span>
368+
<Tooltip position="bottom">Clear</Tooltip>
369+
</ActionButton>
370+
)
371+
}
372+
337373
export default CommandBarHeaderFooter

0 commit comments

Comments
 (0)