js-draw 1.14.0 → 1.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. package/dist/Editor.css +285 -1
  2. package/dist/bundle.js +2 -2
  3. package/dist/bundledStyles.js +1 -1
  4. package/dist/cjs/Editor.js +5 -0
  5. package/dist/cjs/components/util/StrokeSmoother.js +11 -4
  6. package/dist/cjs/rendering/caching/CacheRecordManager.js +1 -1
  7. package/dist/cjs/testing/sendHtmlSwipe.d.ts +4 -0
  8. package/dist/cjs/testing/sendHtmlSwipe.js +14 -0
  9. package/dist/cjs/toolbar/EdgeToolbar.d.ts +1 -0
  10. package/dist/cjs/toolbar/EdgeToolbar.js +30 -110
  11. package/dist/cjs/toolbar/IconProvider.d.ts +1 -0
  12. package/dist/cjs/toolbar/IconProvider.js +27 -0
  13. package/dist/cjs/toolbar/localization.d.ts +28 -1
  14. package/dist/cjs/toolbar/localization.js +30 -1
  15. package/dist/cjs/toolbar/utils/HelpDisplay.d.ts +37 -0
  16. package/dist/cjs/toolbar/utils/HelpDisplay.js +442 -0
  17. package/dist/cjs/toolbar/utils/HelpDisplay.test.d.ts +1 -0
  18. package/dist/cjs/toolbar/utils/localization.d.ts +9 -0
  19. package/dist/cjs/toolbar/utils/localization.js +11 -0
  20. package/dist/cjs/toolbar/utils/makeDraggable.d.ts +16 -0
  21. package/dist/cjs/toolbar/utils/makeDraggable.js +130 -0
  22. package/dist/cjs/toolbar/widgets/ActionButtonWidget.d.ts +7 -0
  23. package/dist/cjs/toolbar/widgets/ActionButtonWidget.js +14 -2
  24. package/dist/cjs/toolbar/widgets/BaseWidget.d.ts +8 -1
  25. package/dist/cjs/toolbar/widgets/BaseWidget.js +25 -3
  26. package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.d.ts +3 -1
  27. package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.js +19 -4
  28. package/dist/cjs/toolbar/widgets/HandToolWidget.d.ts +3 -1
  29. package/dist/cjs/toolbar/widgets/HandToolWidget.js +19 -7
  30. package/dist/cjs/toolbar/widgets/InsertImageWidget.js +1 -0
  31. package/dist/cjs/toolbar/widgets/PenToolWidget.d.ts +4 -2
  32. package/dist/cjs/toolbar/widgets/PenToolWidget.js +27 -8
  33. package/dist/cjs/toolbar/widgets/SelectionToolWidget.d.ts +3 -1
  34. package/dist/cjs/toolbar/widgets/SelectionToolWidget.js +19 -5
  35. package/dist/cjs/toolbar/widgets/components/makeColorInput.d.ts +2 -0
  36. package/dist/cjs/toolbar/widgets/components/makeColorInput.js +17 -7
  37. package/dist/cjs/toolbar/widgets/components/makeGridSelector.d.ts +6 -0
  38. package/dist/cjs/toolbar/widgets/components/makeGridSelector.js +3 -0
  39. package/dist/cjs/tools/FindTool.js +18 -5
  40. package/dist/cjs/util/addLongPressOrHoverCssClasses.d.ts +3 -1
  41. package/dist/cjs/util/addLongPressOrHoverCssClasses.js +2 -1
  42. package/dist/cjs/util/cloneElementWithStyles.d.ts +6 -0
  43. package/dist/cjs/util/cloneElementWithStyles.js +32 -0
  44. package/dist/cjs/version.js +1 -1
  45. package/dist/mjs/Editor.mjs +5 -0
  46. package/dist/mjs/components/util/StrokeSmoother.mjs +11 -4
  47. package/dist/mjs/rendering/caching/CacheRecordManager.mjs +1 -1
  48. package/dist/mjs/testing/sendHtmlSwipe.d.ts +4 -0
  49. package/dist/mjs/testing/sendHtmlSwipe.mjs +12 -0
  50. package/dist/mjs/toolbar/EdgeToolbar.d.ts +1 -0
  51. package/dist/mjs/toolbar/EdgeToolbar.mjs +30 -110
  52. package/dist/mjs/toolbar/IconProvider.d.ts +1 -0
  53. package/dist/mjs/toolbar/IconProvider.mjs +27 -0
  54. package/dist/mjs/toolbar/localization.d.ts +28 -1
  55. package/dist/mjs/toolbar/localization.mjs +30 -1
  56. package/dist/mjs/toolbar/utils/HelpDisplay.d.ts +37 -0
  57. package/dist/mjs/toolbar/utils/HelpDisplay.mjs +437 -0
  58. package/dist/mjs/toolbar/utils/HelpDisplay.test.d.ts +1 -0
  59. package/dist/mjs/toolbar/utils/localization.d.ts +9 -0
  60. package/dist/mjs/toolbar/utils/localization.mjs +8 -0
  61. package/dist/mjs/toolbar/utils/makeDraggable.d.ts +16 -0
  62. package/dist/mjs/toolbar/utils/makeDraggable.mjs +128 -0
  63. package/dist/mjs/toolbar/widgets/ActionButtonWidget.d.ts +7 -0
  64. package/dist/mjs/toolbar/widgets/ActionButtonWidget.mjs +14 -2
  65. package/dist/mjs/toolbar/widgets/BaseWidget.d.ts +8 -1
  66. package/dist/mjs/toolbar/widgets/BaseWidget.mjs +25 -3
  67. package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.d.ts +3 -1
  68. package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.mjs +19 -4
  69. package/dist/mjs/toolbar/widgets/HandToolWidget.d.ts +3 -1
  70. package/dist/mjs/toolbar/widgets/HandToolWidget.mjs +19 -7
  71. package/dist/mjs/toolbar/widgets/InsertImageWidget.mjs +1 -0
  72. package/dist/mjs/toolbar/widgets/PenToolWidget.d.ts +4 -2
  73. package/dist/mjs/toolbar/widgets/PenToolWidget.mjs +27 -8
  74. package/dist/mjs/toolbar/widgets/SelectionToolWidget.d.ts +3 -1
  75. package/dist/mjs/toolbar/widgets/SelectionToolWidget.mjs +19 -5
  76. package/dist/mjs/toolbar/widgets/components/makeColorInput.d.ts +2 -0
  77. package/dist/mjs/toolbar/widgets/components/makeColorInput.mjs +17 -7
  78. package/dist/mjs/toolbar/widgets/components/makeGridSelector.d.ts +6 -0
  79. package/dist/mjs/toolbar/widgets/components/makeGridSelector.mjs +3 -0
  80. package/dist/mjs/tools/FindTool.mjs +18 -5
  81. package/dist/mjs/util/addLongPressOrHoverCssClasses.d.ts +3 -1
  82. package/dist/mjs/util/addLongPressOrHoverCssClasses.mjs +2 -1
  83. package/dist/mjs/util/cloneElementWithStyles.d.ts +6 -0
  84. package/dist/mjs/util/cloneElementWithStyles.mjs +30 -0
  85. package/dist/mjs/version.mjs +1 -1
  86. package/package.json +2 -2
  87. package/src/toolbar/EdgeToolbar.scss +23 -2
  88. package/src/toolbar/toolbar.scss +2 -0
  89. package/src/toolbar/utils/HelpDisplay.scss +315 -0
  90. package/src/toolbar/widgets/components/makeColorInput.scss +7 -0
@@ -13,7 +13,7 @@ const makeFormatMenu = (editor, selectionTool, localizationTable) => {
13
13
  container.classList.add('selection-format-menu', `${toolbarCSSPrefix}spacedList`, `${toolbarCSSPrefix}indentedList`);
14
14
  const colorRow = document.createElement('div');
15
15
  const colorLabel = document.createElement('label');
16
- const { input: colorInput, container: colorInputContainer, setValue: setColorInputValue } = makeColorInput(editor, color => {
16
+ const colorInputControl = makeColorInput(editor, color => {
17
17
  const selection = selectionTool.getSelection();
18
18
  if (selection) {
19
19
  const updateStyleCommands = [];
@@ -26,6 +26,7 @@ const makeFormatMenu = (editor, selectionTool, localizationTable) => {
26
26
  editor.dispatch(unitedCommand);
27
27
  }
28
28
  });
29
+ const { input: colorInput, container: colorInputContainer } = colorInputControl;
29
30
  colorLabel.innerText = localizationTable.colorLabel;
30
31
  const update = () => {
31
32
  const selection = selectionTool.getSelection();
@@ -41,12 +42,12 @@ const makeFormatMenu = (editor, selectionTool, localizationTable) => {
41
42
  }
42
43
  }
43
44
  }
44
- setColorInputValue(Color4.average(colors));
45
+ colorInputControl.setValue(Color4.average(colors));
45
46
  }
46
47
  else {
47
48
  colorInput.disabled = true;
48
49
  container.classList.add('disabled');
49
- setColorInputValue(Color4.transparent);
50
+ colorInputControl.setValue(Color4.transparent);
50
51
  }
51
52
  };
52
53
  colorRow.replaceChildren(colorLabel, colorInputContainer);
@@ -56,6 +57,10 @@ const makeFormatMenu = (editor, selectionTool, localizationTable) => {
56
57
  parent.appendChild(container);
57
58
  },
58
59
  update,
60
+ registerHelpText: (helpDisplay) => {
61
+ helpDisplay.registerTextHelpForElement(colorRow, localizationTable.selectionDropdown__changeColorHelpText);
62
+ colorInputControl.registerWithHelpTextDisplay(helpDisplay);
63
+ },
59
64
  };
60
65
  };
61
66
  export default class SelectionToolWidget extends BaseToolWidget {
@@ -66,16 +71,19 @@ export default class SelectionToolWidget extends BaseToolWidget {
66
71
  const resizeButton = new ActionButtonWidget(editor, 'resize-btn', () => editor.icons.makeResizeImageToSelectionIcon(), this.localizationTable.resizeImageToSelection, () => {
67
72
  this.resizeImageToSelection();
68
73
  }, localization);
74
+ resizeButton.setHelpText(this.localizationTable.selectionDropdown__resizeToHelpText);
69
75
  const deleteButton = new ActionButtonWidget(editor, 'delete-btn', () => editor.icons.makeDeleteSelectionIcon(), this.localizationTable.deleteSelection, () => {
70
76
  const selection = this.tool.getSelection();
71
77
  this.editor.dispatch(selection.deleteSelectedObjects());
72
78
  this.tool.clearSelection();
73
79
  }, localization);
80
+ deleteButton.setHelpText(this.localizationTable.selectionDropdown__deleteHelpText);
74
81
  const duplicateButton = new ActionButtonWidget(editor, 'duplicate-btn', () => editor.icons.makeDuplicateSelectionIcon(), this.localizationTable.duplicateSelection, async () => {
75
82
  const selection = this.tool.getSelection();
76
83
  this.editor.dispatch(await selection.duplicateSelectedObjects());
77
84
  this.setDropdownVisible(false);
78
85
  }, localization);
86
+ duplicateButton.setHelpText(this.localizationTable.selectionDropdown__duplicateHelpText);
79
87
  this.addSubWidget(resizeButton);
80
88
  this.addSubWidget(deleteButton);
81
89
  this.addSubWidget(duplicateButton);
@@ -124,8 +132,11 @@ export default class SelectionToolWidget extends BaseToolWidget {
124
132
  createIcon() {
125
133
  return this.editor.icons.makeSelectionIcon();
126
134
  }
127
- fillDropdown(dropdown) {
128
- super.fillDropdown(dropdown);
135
+ getHelpText() {
136
+ return this.localizationTable.selectionDropdown__baseHelpText;
137
+ }
138
+ fillDropdown(dropdown, helpDisplay) {
139
+ super.fillDropdown(dropdown, helpDisplay);
129
140
  const controlsContainer = document.createElement('div');
130
141
  controlsContainer.classList.add(`${toolbarCSSPrefix}nonbutton-controls-main-list`);
131
142
  dropdown.appendChild(controlsContainer);
@@ -133,6 +144,9 @@ export default class SelectionToolWidget extends BaseToolWidget {
133
144
  const formatMenu = makeFormatMenu(this.editor, this.tool, this.localizationTable);
134
145
  formatMenu.addTo(controlsContainer);
135
146
  this.updateFormatMenu = () => formatMenu.update();
147
+ if (helpDisplay) {
148
+ formatMenu.registerHelpText(helpDisplay);
149
+ }
136
150
  formatMenu.update();
137
151
  return true;
138
152
  }
@@ -1,10 +1,12 @@
1
1
  import { Color4 } from '@js-draw/math';
2
2
  import Editor from '../../../Editor';
3
+ import type HelpDisplay from '../../utils/HelpDisplay';
3
4
  type OnColorChangeListener = (color: Color4) => void;
4
5
  export declare const makeColorInput: (editor: Editor, onColorChange: OnColorChangeListener) => {
5
6
  input: HTMLInputElement;
6
7
  container: HTMLSpanElement;
7
8
  setValue: (color: Color4 | string) => void;
8
9
  closePicker: () => void;
10
+ registerWithHelpTextDisplay: (helpDisplay: HelpDisplay) => void;
9
11
  };
10
12
  export default makeColorInput;
@@ -3,13 +3,16 @@ import PipetteTool from '../../../tools/PipetteTool.mjs';
3
3
  import { EditorEventType } from '../../../types.mjs';
4
4
  // Returns [ color input, input container, callback to change the color value ].
5
5
  export const makeColorInput = (editor, onColorChange) => {
6
- const colorInputContainer = document.createElement('span');
6
+ const container = document.createElement('span');
7
+ const inputWrapper = document.createElement('span');
7
8
  const colorInput = document.createElement('input');
8
9
  colorInput.type = 'button';
9
10
  colorInput.classList.add('coloris_input');
10
- colorInputContainer.classList.add('color-input-container');
11
- colorInputContainer.appendChild(colorInput);
12
- const pipetteController = addPipetteTool(editor, colorInputContainer, (color) => {
11
+ container.classList.add('color-input-container');
12
+ inputWrapper.classList.add('color-input-wrapper');
13
+ inputWrapper.appendChild(colorInput);
14
+ container.appendChild(inputWrapper);
15
+ const pipetteController = addPipetteTool(editor, container, (color) => {
13
16
  colorInput.value = color.toHexString();
14
17
  onInputEnd();
15
18
  // Update the color preview, if it exists (may be managed by Coloris).
@@ -44,7 +47,7 @@ export const makeColorInput = (editor, onColorChange) => {
44
47
  open: true,
45
48
  });
46
49
  pipetteController.cancel();
47
- colorInputContainer.classList.add('picker-open');
50
+ container.classList.add('picker-open');
48
51
  // Focus the Coloris color picker, if it exists.
49
52
  // Don't focus the text input within the color picker, however,
50
53
  // as this displays a keyboard on mobile devices.
@@ -60,7 +63,7 @@ export const makeColorInput = (editor, onColorChange) => {
60
63
  onInputEnd();
61
64
  // Restore focus to the input that opened the color picker
62
65
  colorInput.focus();
63
- colorInputContainer.classList.remove('picker-open');
66
+ container.classList.remove('picker-open');
64
67
  };
65
68
  colorInput.addEventListener('close', () => {
66
69
  onClose();
@@ -76,13 +79,17 @@ export const makeColorInput = (editor, onColorChange) => {
76
79
  };
77
80
  return {
78
81
  input: colorInput,
79
- container: colorInputContainer,
82
+ container,
80
83
  setValue: setColorInputValue,
81
84
  closePicker: () => {
82
85
  if (isOpen) {
83
86
  onInputEnd();
84
87
  }
85
88
  },
89
+ registerWithHelpTextDisplay: (helpDisplay) => {
90
+ helpDisplay.registerTextHelpForElement(inputWrapper, editor.localization.colorPickerToggleHelpText);
91
+ pipetteController.registerWithHelpTextDisplay(helpDisplay);
92
+ },
86
93
  };
87
94
  };
88
95
  const addPipetteTool = (editor, container, onColorChange) => {
@@ -136,6 +143,9 @@ const addPipetteTool = (editor, container, onColorChange) => {
136
143
  cancel: () => {
137
144
  endColorSelectMode();
138
145
  },
146
+ registerWithHelpTextDisplay: (helpDisplay) => {
147
+ helpDisplay.registerTextHelpForElement(pipetteButton, editor.localization.colorPickerPipetteHelpText);
148
+ },
139
149
  };
140
150
  };
141
151
  export default makeColorInput;
@@ -7,8 +7,14 @@ interface GridSelectChoice<ChoiceIdType> {
7
7
  }
8
8
  interface GridSelector<ChoiceIdType> {
9
9
  value: MutableReactiveValue<ChoiceIdType>;
10
+ /**
11
+ * Connects this grid selector with `other` such that only one item in
12
+ * either this or `other` can be selected at a time.
13
+ */
10
14
  linkWith: (other: GridSelector<ChoiceIdType>) => void;
15
+ /** Re-builds the icons shown in the grid selector. */
11
16
  updateIcons: () => void;
17
+ getRootElement: () => HTMLElement;
12
18
  addTo: (parent: HTMLElement) => void;
13
19
  /** Used internally @internal */
14
20
  _radiogroupName: string;
@@ -131,6 +131,9 @@ labelText, defaultId, choices) => {
131
131
  updateIcons: () => {
132
132
  buttons.forEach(button => button.updateIcon());
133
133
  },
134
+ getRootElement() {
135
+ return outerContainer;
136
+ },
134
137
  addTo: (parent) => {
135
138
  parent.appendChild(outerContainer);
136
139
  },
@@ -2,6 +2,7 @@
2
2
  //
3
3
  // @packageDocumentation
4
4
  import TextComponent from '../components/TextComponent.mjs';
5
+ import ImageComponent from '../components/ImageComponent.mjs';
5
6
  import BaseTool from './BaseTool.mjs';
6
7
  import { toggleFindVisibleShortcutId } from './keybindings.mjs';
7
8
  const cssPrefix = 'find-tool';
@@ -20,11 +21,23 @@ export default class FindTool extends BaseTool {
20
21
  return true;
21
22
  }
22
23
  getMatches(searchFor) {
23
- searchFor = searchFor.toLocaleLowerCase();
24
- const allTextComponents = this.editor.image.getAllElements()
25
- .filter(elem => elem instanceof TextComponent);
26
- const matches = allTextComponents.filter(text => text.getText().toLocaleLowerCase().indexOf(searchFor) !== -1);
27
- return matches.map(match => match.getBBox());
24
+ const lowerSearchFor = searchFor.toLocaleLowerCase();
25
+ const matchingComponents = this.editor.image.getAllElements().filter(component => {
26
+ let text = '';
27
+ if (component instanceof TextComponent) {
28
+ text = component.getText();
29
+ }
30
+ else if (component instanceof ImageComponent) {
31
+ text = component.getAltText() ?? '';
32
+ }
33
+ else {
34
+ return false;
35
+ }
36
+ const hasLowercaseMatch = text.toLocaleLowerCase().indexOf(lowerSearchFor) !== -1;
37
+ const hasSameCaseMatch = text.indexOf(searchFor) !== -1;
38
+ return hasLowercaseMatch || hasSameCaseMatch;
39
+ });
40
+ return matchingComponents.map(match => match.getBBox());
28
41
  }
29
42
  focusCurrentMatch() {
30
43
  const matches = this.getMatches(this.searchInput.value);
@@ -4,7 +4,9 @@
4
4
  *
5
5
  * When no pointers are inside `element`, adds the CSS class `no-long-press-or-hover`.
6
6
  */
7
- declare const addLongPressOrHoverCssClasses: (element: HTMLElement) => {
7
+ declare const addLongPressOrHoverCssClasses: (element: HTMLElement, options?: {
8
+ timeout: number;
9
+ }) => {
8
10
  removeEventListeners: () => void;
9
11
  };
10
12
  export default addLongPressOrHoverCssClasses;
@@ -5,7 +5,7 @@ import listenForLongPressOrHover from './listenForLongPressOrHover.mjs';
5
5
  *
6
6
  * When no pointers are inside `element`, adds the CSS class `no-long-press-or-hover`.
7
7
  */
8
- const addLongPressOrHoverCssClasses = (element) => {
8
+ const addLongPressOrHoverCssClasses = (element, options) => {
9
9
  const hasLongPressClass = 'has-long-press-or-hover';
10
10
  const noLongPressClass = 'no-long-press-or-hover';
11
11
  element.classList.add('no-long-press-or-hover');
@@ -18,6 +18,7 @@ const addLongPressOrHoverCssClasses = (element) => {
18
18
  element.classList.add(noLongPressClass);
19
19
  element.classList.remove(hasLongPressClass);
20
20
  },
21
+ longPressTimeout: options?.timeout,
21
22
  });
22
23
  return {
23
24
  removeEventListeners: () => {
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Makes a clone of `element` and recursively applies styles from the original to the
3
+ * clone's children.
4
+ */
5
+ declare const cloneElementWithStyles: (element: HTMLElement) => HTMLElement;
6
+ export default cloneElementWithStyles;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Makes a clone of `element` and recursively applies styles from the original to the
3
+ * clone's children.
4
+ */
5
+ const cloneElementWithStyles = (element) => {
6
+ const restyle = (originalElement, clonedElement) => {
7
+ const originalComputedStyle = getComputedStyle(originalElement);
8
+ // jsdom doesn't support iterators in CSSStyleDeclarations. Iterate with
9
+ // an index.
10
+ for (let index = 0; index < originalComputedStyle.length; index++) {
11
+ const propertyName = originalComputedStyle.item(index);
12
+ const propertyValue = originalComputedStyle.getPropertyValue(propertyName);
13
+ clonedElement.style.setProperty(propertyName, propertyValue);
14
+ }
15
+ for (let i = 0; i < originalElement.children.length; i++) {
16
+ const originalChild = originalElement.children.item(i);
17
+ const clonedChild = clonedElement.children.item(i);
18
+ if (originalChild && clonedChild) {
19
+ restyle(originalChild, clonedChild);
20
+ }
21
+ else {
22
+ console.warn('CloneElement: Missing child');
23
+ }
24
+ }
25
+ };
26
+ const elementClone = element.cloneNode(true);
27
+ restyle(element, elementClone);
28
+ return elementClone;
29
+ };
30
+ export default cloneElementWithStyles;
@@ -1,3 +1,3 @@
1
1
  export default {
2
- number: '1.14.0',
2
+ number: '1.15.0',
3
3
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-draw",
3
- "version": "1.14.0",
3
+ "version": "1.15.0",
4
4
  "description": "Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript. ",
5
5
  "types": "./dist/mjs/lib.d.ts",
6
6
  "main": "./dist/cjs/lib.js",
@@ -86,5 +86,5 @@
86
86
  "freehand",
87
87
  "svg"
88
88
  ],
89
- "gitHead": "6870036bd8c8160dcb00ded1a4e13b3d9b75071a"
89
+ "gitHead": "d723c028faa43c7661df54606064f6237a8a767b"
90
90
  }
@@ -5,12 +5,22 @@
5
5
  to { transform: translate(0, 0); }
6
6
  }
7
7
 
8
+ @keyframes toolbar--edgemenu-transition-in-reduce-motion {
9
+ from { opacity: 0; }
10
+ to { opacity: 1; }
11
+ }
12
+
8
13
  @keyframes toolbar--edgemenu-transition-out {
9
14
  // Don't include `from { translate: 0 }` because initially,
10
15
  // the translation might not be zero (e.g. during a drag).
11
16
  to { transform: translate(0, 100%); }
12
17
  }
13
18
 
19
+ @keyframes toolbar--edgemenu-transition-out-reduce-motion {
20
+ from { opacity: 1; }
21
+ to { opacity: 0; }
22
+ }
23
+
14
24
  @keyframes toolbar--edgemenu-container-transition-in {
15
25
  // Include overflow-y: hidden so that the bottom of the menu doesn't go below
16
26
  // the editor.
@@ -269,9 +279,11 @@
269
279
  .toolbar-edgemenu-container {
270
280
  background-color: var(--background-color-transparent);
271
281
 
272
- transition: 0.15s ease-in-out height, 0.15s ease-in-out background-color, 0.2s ease-in-out opacity;
282
+ $motion-transition: 0.15s ease-in-out height;
283
+ $non-motion-transition: 0.15s ease-in-out background-color, 0.2s ease-in-out opacity;
284
+ transition: $motion-transition, $non-motion-transition;
273
285
  @media (prefers-reduced-motion: reduce) {
274
- transition: none;
286
+ transition: $non-motion-transition;
275
287
  }
276
288
 
277
289
  position: absolute;
@@ -312,6 +324,10 @@
312
324
  --button-label-hover-offset-y: var(--button-size);
313
325
  @include labelVisibleOnHover.label-visible-on-hover('label > .button-label-text');
314
326
  }
327
+
328
+ .toolbar-help-overlay-button {
329
+ align-items: last baseline;
330
+ }
315
331
  }
316
332
 
317
333
  .toolbar-edgemenu-container .toolbar-edgemenu {
@@ -432,6 +448,11 @@
432
448
  margin-top: 5px;
433
449
  min-height: 35px;
434
450
 
451
+ // No extra space above the first
452
+ &:first-child {
453
+ margin-top: 0;
454
+ }
455
+
435
456
  // Align inputs (assumes labels come first)
436
457
  & > label {
437
458
  padding-right: 35px;
@@ -9,3 +9,5 @@
9
9
  @use "./AbstractToolbar.scss";
10
10
  @use "./EdgeToolbar.scss";
11
11
  @use "./DropdownToolbar.scss";
12
+
13
+ @use "./utils/HelpDisplay.scss";