Skip to content
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
1fa9d2d
Improve ActionButtonDropdown selection
andrewvarga Mar 17, 2025
dc718bf
center rectangle icon fixed
andrewvarga Mar 17, 2025
c1933b7
ignore Esc key when displaying hotkeys
andrewvarga Mar 17, 2025
bee4e00
add ability to escape 3 point circle tool
andrewvarga Mar 17, 2025
e53a0ef
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 17, 2025
1fe5d5c
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 18, 2025
34e929a
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 19, 2025
d33ec31
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 19, 2025
9141669
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 20, 2025
2f5dfc3
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 20, 2025
b21f8c0
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 20, 2025
34f60db
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 20, 2025
8134d6a
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 21, 2025
1294767
remove focus from ActionButton, ActionButtonDropdown
andrewvarga Mar 22, 2025
5489501
merge from main
andrewvarga Mar 22, 2025
7c275c4
remove focus outline from buttons
andrewvarga Mar 22, 2025
5963761
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 24, 2025
b8c84e0
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 24, 2025
fedef61
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 25, 2025
202955f
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 26, 2025
2416bcc
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 26, 2025
c35d7c6
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 26, 2025
644d4bd
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 26, 2025
aadd595
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 27, 2025
eca69b8
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 28, 2025
60a171f
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 28, 2025
905f0d8
remember lastly selected multi action item
andrewvarga Mar 28, 2025
43ce6e8
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Mar 29, 2025
858ab30
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 1, 2025
4429a51
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 1, 2025
42bdde3
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 2, 2025
e09fcaa
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 2, 2025
100fdcf
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 2, 2025
07b2691
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 3, 2025
0597485
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 3, 2025
97632c3
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 4, 2025
8078145
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 4, 2025
16cdd9b
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 4, 2025
107570a
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 4, 2025
a9ea3df
Add tests for toolbar buttons
andrewvarga Apr 5, 2025
0d127ad
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 5, 2025
4727d68
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 6, 2025
d17836d
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 7, 2025
61f6b1b
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 7, 2025
635abbd
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 8, 2025
d0e643a
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 8, 2025
688c8a7
fix sketch-tests by turning toolbar dropdown arrays into an object wi…
andrewvarga Apr 9, 2025
84bdc48
Merge branch 'main' into andrewvarga/4469/improve-toolbar-ux
andrewvarga Apr 9, 2025
a6581c1
update other tests with open menu click
andrewvarga Apr 9, 2025
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
76 changes: 49 additions & 27 deletions src/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ export function Toolbar({
}
}, [currentMode, disableAllButtons, configCallbackProps])

// To remember the last selected item in an ActionButtonDropdown
const [lastSelectedMultiActionItem, _] = useState(
new Map<
number /* index in currentModeItems */,
number /* index in maybeIconConfig */
>()
)
Comment on lines +188 to +193

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe this should be put in local storage too.
I think maybe once this has been in for a while, if we find ourselves thinking "I wish It remembered after I closed the app" might be a good idea.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I can see that being useful. Or a step further, save it per user data / project, in case they log in another device..


return (
<menu
data-current-mode={currentMode}
Expand All @@ -199,13 +207,22 @@ export function Toolbar({
)
} else if (isArray(maybeIconConfig)) {
// A button with a dropdown
const selectedIcon =
maybeIconConfig.find((c) => c.isActive) ||
maybeIconConfig[lastSelectedMultiActionItem.get(i) ?? 0]

// Save the last selected item in the dropdown
lastSelectedMultiActionItem.set(
i,
maybeIconConfig.indexOf(selectedIcon)
)
return (
<ActionButtonDropdown
Element="button"
key={maybeIconConfig[0].id}
data-testid={maybeIconConfig[0].id + '-dropdown'}
id={maybeIconConfig[0].id + '-dropdown'}
name={maybeIconConfig[0].title}
key={selectedIcon.id}
data-testid={selectedIcon.id + '-dropdown'}
id={selectedIcon.id + '-dropdown'}
name={selectedIcon.title}
className={
(maybeIconConfig[0].alwaysDark
? 'dark bg-chalkboard-90 '
Expand Down Expand Up @@ -234,52 +251,48 @@ export function Toolbar({
>
<ActionButton
Element="button"
id={maybeIconConfig[0].id}
data-testid={maybeIconConfig[0].id}
id={selectedIcon.id}
data-testid={selectedIcon.id}
iconStart={{
icon: maybeIconConfig[0].icon,
iconColor: maybeIconConfig[0].iconColor,
icon: selectedIcon.icon,
iconColor: selectedIcon.iconColor,
className: iconClassName,
bgClassName: bgClassName,
}}
className={
'!border-transparent !px-0 pressed:!text-chalkboard-10 pressed:enabled:hovered:!text-chalkboard-10 ' +
buttonBgClassName
}
aria-pressed={maybeIconConfig[0].isActive}
aria-pressed={selectedIcon.isActive}
disabled={
disableAllButtons ||
maybeIconConfig[0].status !== 'available' ||
maybeIconConfig[0].disabled
selectedIcon.status !== 'available' ||
selectedIcon.disabled
}
name={maybeIconConfig[0].title}
name={selectedIcon.title}
// aria-description is still in ARIA 1.3 draft.
// eslint-disable-next-line jsx-a11y/aria-props
aria-description={maybeIconConfig[0].description}
onClick={() =>
maybeIconConfig[0].onClick(configCallbackProps)
}
aria-description={selectedIcon.description}
onClick={() => selectedIcon.onClick(configCallbackProps)}
>
<span
className={!maybeIconConfig[0].showTitle ? 'sr-only' : ''}
>
{maybeIconConfig[0].title}
<span className={!selectedIcon.showTitle ? 'sr-only' : ''}>
{selectedIcon.title}
</span>
<ToolbarItemTooltip
itemConfig={maybeIconConfig[0]}
itemConfig={selectedIcon}
configCallbackProps={configCallbackProps}
wrapperClassName="ui-open:!hidden"
contentClassName={tooltipContentClassName}
>
{showRichContent ? (
<ToolbarItemTooltipRichContent
itemConfig={maybeIconConfig[0]}
itemConfig={selectedIcon}
/>
) : (
<ToolbarItemTooltipShortContent
status={maybeIconConfig[0].status}
title={maybeIconConfig[0].title}
hotkey={maybeIconConfig[0].hotkey}
status={selectedIcon.status}
title={selectedIcon.title}
hotkey={selectedIcon.hotkey}
/>
)}
</ToolbarItemTooltip>
Expand Down Expand Up @@ -428,7 +441,9 @@ const ToolbarItemTooltipShortContent = ({
>
{title}
{hotkey && (
<kbd className="inline-block ml-2 flex-none hotkey">{hotkey}</kbd>
<kbd className="inline-block ml-2 flex-none hotkey">
{displayHotkeys(hotkey)}
</kbd>
)}
</span>
)
Expand Down Expand Up @@ -459,7 +474,9 @@ const ToolbarItemTooltipRichContent = ({
{itemConfig.title}
</span>
{itemConfig.status === 'available' && itemConfig.hotkey ? (
<kbd className="flex-none hotkey">{itemConfig.hotkey}</kbd>
<kbd className="flex-none hotkey">
{displayHotkeys(itemConfig.hotkey)}
</kbd>
) : itemConfig.status === 'kcl-only' ? (
<>
<span className="text-wrap font-sans flex-0 text-chalkboard-70 dark:text-chalkboard-40">
Expand Down Expand Up @@ -520,3 +537,8 @@ const ToolbarItemTooltipRichContent = ({
</>
)
}

// We don't want to display Esc hotkeys to avoid confusion in the Toolbar UI (eg. "EscR")
function displayHotkeys(hotkey: string | string[]) {
return (isArray(hotkey) ? hotkey : [hotkey]).filter((h) => h !== 'Esc')
}
1 change: 1 addition & 0 deletions src/components/ActionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export const ActionButton = forwardRef((props: ActionButtonProps, ref) => {
<button
ref={ref as ForwardedRef<HTMLButtonElement>}
className={classNames}
tabIndex={-1}
{...rest}
>
{iconStart && <ActionIcon {...iconStart} />}
Expand Down
1 change: 1 addition & 0 deletions src/components/ActionButtonDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export function ActionButtonDropdown({
close()
}}
className="group/button flex items-center gap-6 px-3 py-1 font-sans text-xs hover:bg-primary/10 dark:hover:bg-chalkboard-80 border-0 m-0 w-full rounded-none text-left disabled:!bg-transparent dark:disabled:text-chalkboard-60"
tabIndex={-1}
disabled={item.disabled}
data-testid={'dropdown-' + item.id}
>
Expand Down
4 changes: 2 additions & 2 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,15 @@ textarea,

button {
@apply border border-chalkboard-30 m-0.5 px-3 rounded text-xs;
@apply focus-visible:outline-chalkboard-100;
@apply focus-visible:outline-none;
}

button:hover {
@apply border-chalkboard-40 bg-primary/5;
}

.dark button {
@apply border-chalkboard-70 focus-visible:outline-chalkboard-10;
@apply border-chalkboard-70;
}

.dark button:hover {
Expand Down
10 changes: 6 additions & 4 deletions src/lib/toolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,7 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
status: 'available',
title: 'Center circle',
disabled: (state) => state.matches('Sketch no face'),
isActive: (state) =>
state.matches({ Sketch: 'Circle tool' }) ||
state.matches({ Sketch: 'Circle three point tool' }),
isActive: (state) => state.matches({ Sketch: 'Circle tool' }),
hotkey: (state) =>
state.matches({ Sketch: 'Circle tool' }) ? ['Esc', 'C'] : 'C',
showTitle: false,
Expand All @@ -533,6 +531,10 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
icon: 'circle',
status: 'available',
title: '3-point circle',
isActive: (state) =>
state.matches({ Sketch: 'Circle three point tool' }),
hotkey: (state) =>
state.matches({ Sketch: 'Circle three point tool' }) ? 'Esc' : [],
showTitle: false,
description: 'Draw a circle defined by three points',
links: [],
Expand Down Expand Up @@ -573,7 +575,7 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
: 'none',
},
}),
icon: 'arc',
icon: 'rectangle',
status: 'available',
disabled: (state) => state.matches('Sketch no face'),
title: 'Center rectangle',
Expand Down