Skip to content

Conversation

knollengewaechs
Copy link
Contributor

@knollengewaechs knollengewaechs commented Jan 10, 2025

URL of deployed dev instance (used for testing):

Steps to test:

  • With at least two sliders (number and log slider, such as gamma correction and opacity in the layer setting tab, try the following:
    • the sliders only scroll on focus (e.g. after being clicked)
    • in the case that the layer settings tab is scrollable, e.g. for an annotation with many layers, scrolling the slider should not scroll the layer settings tab.
    • double clicking on the gamma correction value resets it to 1.0 (not 0.33 as before).
      (- you can also test this with double clicking the slider for the brush size in the tool bar (having the brush tool active): it should be reset to 50)

TODOs:

  • fix the following: focus slider, lose focus. then you can slide just a bit. I dont know why this is, isFocused is false in that case!

Issues:


(Please delete unneeded items, merge only when none are left open)

Copy link
Contributor

coderabbitai bot commented Jan 10, 2025

📝 Walkthrough

Walkthrough

The pull request introduces enhancements to the Slider component in the frontend, focusing on wheel event handling, a reset-to-default functionality, and improved user interaction. Key changes include the addition of an optional onResetToDefault callback, restructuring the wheel event handling with performance optimizations using useCallback, and implementing focus-based scrolling behavior. These modifications aim to resolve issues with slider interactions, particularly for log-based sliders.

Changes

File Change Summary
frontend/javascripts/components/slider.tsx - Added onResetToDefault optional prop
- Improved wheel event handling with useCallback
- Added focus-based event listener
- Updated double-click handling
frontend/javascripts/oxalis/view/components/setting_input_views.tsx - Added resetToDefaultValue method to LogSliderSetting
- Integrated onResetToDefault prop for slider reset
CHANGELOG.unreleased.md - Updated changelog with improvements to slider scrolling behavior
frontend/javascripts/oxalis/view/left-border-tabs/layer_settings_tab.tsx - Updated to use getSpecificDefaultsForLayer for layer settings
- Removed unused imports
frontend/javascripts/types/schemas/dataset_view_configuration_defaults.ts - Renamed getSpecificDefaultsForLayers to getSpecificDefaultsForLayer and updated parameters

Assessment against linked issues

Objective Addressed Explanation
Fix scrolling to NaN
Fix default values of log sliders
Only scroll sliders on focus

Possibly related PRs

Suggested labels

css

Poem

🐰 A slider's tale, with wheel so fine,
Scrolling gently, line by line,
Focus tracked, default restored,
Performance optimized, users adored!
Code rabbit hops with pure delight 🎉

Tip

🌐 Web search-backed reviews and chat
  • We have enabled web search-based reviews and chat for all users. This feature allows CodeRabbit to access the latest documentation and information on the web.
  • You can disable this feature by setting web_search: false in the knowledge_base settings.
  • Please share any feedback in the Discord discussion.

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

if (sliderElement) {
sliderElement.addEventListener("wheel", handleWheelEvent, { passive: false });
}
}, [handleWheelEvent]);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was a little surprised about this solution.
In my view the dependency that makes sense would be sliderRef.current. I read that components are not rerendered if refs change, which makes sense because the concepts behind refs is to reference objects that are not needed for rendering (according to react.dev. I thought that hooks would still be updated, but this must be the wrong assumption.

@knollengewaechs knollengewaechs marked this pull request as ready for review January 22, 2025 11:14
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
frontend/javascripts/components/slider.tsx (1)

50-71: Consider simplifying the wheel event handler conditions.

The wheel event handler implementation is correct but could be more maintainable.

Consider this refactoring to improve readability:

 const handleWheelEvent = useCallback(
   (event: { preventDefault: () => void; deltaY: number }) => {
-    // differentiate between single value and range slider
-    if (onWheelDisabled || value == null || min == null || max == null || !isFocused.current)
-      return _.noop;
+    if (onWheelDisabled || !isFocused.current || value == null || min == null || max == null) {
+      return;
+    }
+
+    event.preventDefault();
+    const diff = getWheelStepFromEvent(ensuredStep, event.deltaY, wheelStep);
+
     if (range === false || range == null) {
-      event.preventDefault();
-      const newValue = value - getWheelStepFromEvent(ensuredStep, event.deltaY, wheelStep);
+      const newValue = value - diff;
       const clampedNewValue = clamp(min, newValue, max);
       if (onChange != null) onChange(clampedNewValue);
     } else if (range === true || typeof range === "object") {
-      event.preventDefault();
-      const diff = getWheelStepFromEvent(ensuredStep, event.deltaY, wheelStep);
       const newLowerValue = Math.round(value[0] + diff);
       const newUpperValue = Math.round(value[1] - diff);
       const clampedNewLowerValue = clamp(min, newLowerValue, Math.min(newUpperValue, max));
       const clampedNewUpperValue = clamp(newLowerValue, newUpperValue, max);
       if (onChange != null) onChange([clampedNewLowerValue, clampedNewUpperValue]);
     }
   },
   [value, min, max, onChange, range, onWheelDisabled],
 );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a04bca6 and 0f5ced1.

📒 Files selected for processing (2)
  • frontend/javascripts/components/slider.tsx (4 hunks)
  • frontend/javascripts/oxalis/view/components/setting_input_views.tsx (2 hunks)
🔇 Additional comments (4)
frontend/javascripts/components/slider.tsx (3)

5-5: LGTM! Clean prop and import additions.

The new optional callback prop and React hooks imports are appropriate for implementing the reset and focus-based scrolling functionality.

Also applies to: 13-13


47-48: LGTM! Proper focus management implementation.

Using useRef for focus tracking is the correct approach as it persists across renders without causing re-renders.


87-106: LGTM! Well-implemented reset functionality.

The double-click handler correctly implements the reset-to-default functionality with proper type handling. The focus/blur handlers and touchAction style are appropriate additions.

frontend/javascripts/oxalis/view/components/setting_input_views.tsx (1)

197-200: LGTM! Clean implementation of reset functionality.

The resetToDefaultValue method is properly implemented with null checks, and the onResetToDefault prop is correctly connected to the Slider component.

Also applies to: 218-218

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
CHANGELOG.unreleased.md (1)

16-16: Consider more concise wording.

The phrase "In order to" can be shortened for better readability.

-- Improved the scrolling behaviour of sliders: In order to scroll them, sliders need to be focused. It is also prevented that the parent element is scrolled together with the slider itself. [#8321](https://github.com/scalableminds/webknossos/pull/8321)
++ Improved the scrolling behaviour of sliders: Sliders must be focused to scroll them. Additionally, parent element scrolling is prevented when using the slider. [#8321](https://github.com/scalableminds/webknossos/pull/8321)
🧰 Tools
🪛 LanguageTool

[style] ~16-~16: Consider a shorter alternative to avoid wordiness.
Context: ...ved the scrolling behaviour of sliders: In order to scroll them, sliders need to be focused...

(IN_ORDER_TO_PREMIUM)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f5ced1 and 80a47d7.

📒 Files selected for processing (2)
  • CHANGELOG.unreleased.md (1 hunks)
  • frontend/javascripts/components/slider.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/javascripts/components/slider.tsx
🧰 Additional context used
🪛 LanguageTool
CHANGELOG.unreleased.md

[style] ~16-~16: Consider a shorter alternative to avoid wordiness.
Context: ...ved the scrolling behaviour of sliders: In order to scroll them, sliders need to be focused...

(IN_ORDER_TO_PREMIUM)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: circleci_build
🔇 Additional comments (1)
CHANGELOG.unreleased.md (1)

16-16: LGTM! The changelog entry is well-structured.

The entry correctly documents the slider improvements, follows the changelog format, and includes the appropriate PR reference.

🧰 Tools
🪛 LanguageTool

[style] ~16-~16: Consider a shorter alternative to avoid wordiness.
Context: ...ved the scrolling behaviour of sliders: In order to scroll them, sliders need to be focused...

(IN_ORDER_TO_PREMIUM)

Copy link
Member

@philippotto philippotto left a comment

Choose a reason for hiding this comment

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

cool! the code looks good and testing went smoothly mostly, too. I noticed two things, though:

  • double clicking the opacity slider for a segmentation layer, resets the value to 100. however, the default value is 20 for segmentation layers. can you have a look whether it's easy to fix this?

  • I already noticed this on master and maybe it's unrelated to the new slider wrapper, but could you please doublecheck this: when dragging the slider and moving on the y axis, text in the UI is selected. this is not critical, but maybe related to the following problem: sometimes the cursor changes into a "grab" pointer and the slider knob does not move anymore. if I release the mouse button, the knob is still moved when I move the mouse. i have to click again to get rid of it. can you try to reproduce this and afterwards temporarily remove the custom slider component and test whether the problem still exists? I can provoke this by clicking and holding for a moment and only then start to move my mouse.

https://github.com/user-attachments/assets/036f8861-6083-4a46-863e-c9981903e7d9
https://github.com/user-attachments/assets/4da1f440-1b60-4da7-9edd-b7ae339fddf1

by the way, the one moment where the slider jumps to 255, I did a doubleclick, so this is fine :)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
frontend/javascripts/components/slider.tsx (2)

26-31: Simplify the wheel step calculation.

While the edge case handling is good, the function can be simplified by combining conditions.

 const getWheelStepFromEvent = (step: number, deltaY: number, wheelStep: number) => {
-  const absDeltaY = Math.abs(deltaY);
-  if (absDeltaY === 0 || step === 0) return 0;
+  if (!deltaY || !step) return 0;
   // Make sure that result is a multiple of step
   return step * Math.round((wheelStep * deltaY) / Math.abs(deltaY) / step);
 };

50-90: Extract range slider logic for better readability.

The wheel event handler is well-implemented with proper cleanup, but the range slider logic could be extracted to improve readability.

+  const handleRangeSliderWheel = (diff: number) => {
+    const newLowerValue = Math.round(value[0] + diff);
+    const newUpperValue = Math.round(value[1] - diff);
+    const clampedNewLowerValue = clamp(min, newLowerValue, Math.min(newUpperValue, max));
+    const clampedNewUpperValue = clamp(newLowerValue, newUpperValue, max);
+    onChange([clampedNewLowerValue, clampedNewUpperValue]);
+  };
+
   const handleWheelEvent = useCallback(
     (event: { preventDefault: () => void; deltaY: number }) => {
       if (
         onWheelDisabled ||
         value == null ||
         min == null ||
         max == null ||
-        !isFocused.current ||
+        !isFocused ||
         onChange == null
       )
         return;
       event.preventDefault();
       const diff = getWheelStepFromEvent(ensuredStep, event.deltaY, wheelStep);
       if (range === false || range == null) {
         const newValue = value - diff;
         const clampedNewValue = clamp(min, newValue, max);
         onChange(clampedNewValue);
       } else if (range === true || typeof range === "object") {
-        const newLowerValue = Math.round(value[0] + diff);
-        const newUpperValue = Math.round(value[1] - diff);
-        const clampedNewLowerValue = clamp(min, newLowerValue, Math.min(newUpperValue, max));
-        const clampedNewUpperValue = clamp(newLowerValue, newUpperValue, max);
-        onChange([clampedNewLowerValue, clampedNewUpperValue]);
+        handleRangeSliderWheel(diff);
       }
     },
-    [value, min, max, onChange, range, onWheelDisabled],
+    [value, min, max, onChange, range, onWheelDisabled, isFocused],
   );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f6ae32 and 45394bc.

📒 Files selected for processing (2)
  • CHANGELOG.unreleased.md (1 hunks)
  • frontend/javascripts/components/slider.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.unreleased.md
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: circleci_build
🔇 Additional comments (1)
frontend/javascripts/components/slider.tsx (1)

10-14: LGTM: Well-typed prop addition.

The new onResetToDefault prop is properly typed as an optional callback, maintaining backward compatibility.

@knollengewaechs
Copy link
Contributor Author

knollengewaechs commented Feb 5, 2025

when dragging the slider and moving on the y axis, text in the UI is selected.

@philippotto did I understand it correctly that this is happening in the current master, too? I'm asking because I can only reproduce it on this branch. To be honest I am not 100% sure why this is happening. I think it has something to do with the focusing but I didnt dive deep. I may have found an easy solution though, so maybe thats enough :)

edit: I was able to reproduce the second issue on wk.org. I think my solution should fix both, by disabling userSelect when the slider is focused via CSS.
next edit: I suspect what is happening is that you are selecting text and the slider by being able to select text while sliding. this leads to the grabbing cursor and the weird behaviour. I think by not being able to select text this should be fixed. I didnt find out why this is not a problem within the AntD demos though.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (3)
frontend/javascripts/components/slider.tsx (3)

47-48: ⚠️ Potential issue

Switch to useState for focus management.

Using useRef for focus state could lead to race conditions in concurrent mode.

Apply this fix:

-  const isFocused = useRef(false);
+  const [isFocused, setIsFocused] = useState(false);
   const sliderRef = useRef<HTMLDivElement>(null);

99-109: ⚠️ Potential issue

Fix else branch placement in double-click handler.

The else branch is incorrectly placed outside the if block.

Apply this fix:

   const handleDoubleClick: React.MouseEventHandler<HTMLDivElement> = (event) => {
     if (
       event.target instanceof HTMLElement &&
       event.target.className.includes("ant-slider-handle") &&
       defaultValue != null
-    )
-      if (onResetToDefault != null) onResetToDefault();
+    ) {
+      if (onResetToDefault != null) {
+        onResetToDefault();
+      } else {
       // @ts-ignore Argument of type 'number | number[]' is not assignable to parameter of type 'number'.
       //TypeScript doesn't understand that onChange always takes the type of defaultValue.
-      else onChange(defaultValue);
+        onChange(defaultValue);
+      }
+    }
   };

115-117: 🛠️ Refactor suggestion

Update focus handlers to use setState.

The focus handlers should use setState for consistency with the earlier suggestion.

Apply this fix:

-      style={{ flexGrow: 1, touchAction: "none", userSelect: isFocused.current ? "none" : "auto" }}
-      onFocus={() => (isFocused.current = true)}
-      onBlur={() => (isFocused.current = false)}
+      style={{ flexGrow: 1, touchAction: "none", userSelect: isFocused ? "none" : "auto" }}
+      onFocus={() => setIsFocused(true)}
+      onBlur={() => setIsFocused(false)}
🧹 Nitpick comments (1)
frontend/javascripts/components/slider.tsx (1)

50-77: Optimize guard clauses in wheel event handler.

The implementation is correct but can be simplified.

Combine the conditions and use early return:

   const handleWheelEvent = useCallback(
     (event: { preventDefault: () => void; deltaY: number }) => {
-      if (
-        onWheelDisabled ||
-        value == null ||
-        min == null ||
-        max == null ||
-        !isFocused.current ||
-        onChange == null
-      )
-        return;
+      if (onWheelDisabled || !isFocused.current) return;
+      if (value == null || min == null || max == null || onChange == null) return;
       event.preventDefault();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 45394bc and 38f5fd1.

📒 Files selected for processing (3)
  • frontend/javascripts/components/slider.tsx (4 hunks)
  • frontend/javascripts/oxalis/view/left-border-tabs/layer_settings_tab.tsx (3 hunks)
  • frontend/javascripts/types/schemas/dataset_view_configuration_defaults.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: circleci_build
🔇 Additional comments (7)
frontend/javascripts/types/schemas/dataset_view_configuration_defaults.ts (2)

33-40: Great refactoring of getSpecificDefaultsForLayer!

The function signature has been improved by:

  1. Accepting simpler primitive types instead of the complex APIDataLayer type
  2. Making the color layer check explicit through a boolean parameter
  3. Following a more descriptive naming convention

This change reduces coupling and improves maintainability.


76-78: LGTM - Function call correctly updated!

The call to getSpecificDefaultsForLayer has been properly adapted to use the new signature.

frontend/javascripts/oxalis/view/left-border-tabs/layer_settings_tab.tsx (3)

133-133: LGTM - Import statement updated!

The import statement correctly reflects the renamed function.


1014-1019: LGTM - Proper usage of the new function!

The getSpecificDefaultsForLayer function is called with the correct parameters and its result is appropriately used for the layer settings.


1046-1046: LGTM - Correct usage of defaults!

The alpha default value is properly obtained from the layer-specific defaults.

frontend/javascripts/components/slider.tsx (2)

5-5: LGTM! Clean type definition for the reset functionality.

The optional onResetToDefault prop is well-defined and the imports are properly updated.

Also applies to: 13-13


27-28: LGTM! Improved robustness of wheel step calculation.

The additional checks for zero values prevent potential edge cases and ensure consistent behavior.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
frontend/javascripts/components/slider.tsx (3)

10-14: Consider improving type safety for onResetToDefault.

The onResetToDefault callback is correctly added to the SliderProps type. However, consider making it more type-safe by ensuring it's only available when defaultValue is provided.

 type SliderProps = (SliderSingleProps | SliderRangeProps) & {
   wheelFactor?: number;
   onWheelDisabled?: boolean;
-  onResetToDefault?: () => void;
+  onResetToDefault?: NonNullable<SliderSingleProps['defaultValue']> extends never ? never : () => void;
 };

50-77: Consider extracting range slider logic.

The wheel event handler handles both single and range sliders. Consider extracting the range slider logic into a separate function for better maintainability.

+const handleRangeSliderWheel = (
+  min: number,
+  max: number,
+  value: [number, number],
+  diff: number,
+) => {
+  const newLowerValue = Math.round(value[0] + diff);
+  const newUpperValue = Math.round(value[1] - diff);
+  const clampedNewLowerValue = clamp(min, newLowerValue, Math.min(newUpperValue, max));
+  const clampedNewUpperValue = clamp(newLowerValue, newUpperValue, max);
+  return [clampedNewLowerValue, clampedNewUpperValue] as [number, number];
+};

 const handleWheelEvent = useCallback(
   (event: { preventDefault: () => void; deltaY: number }) => {
     // ... early returns ...
     if (range === false || range == null) {
       const newValue = value - diff;
       const clampedNewValue = clamp(min, newValue, max);
       onChange(clampedNewValue);
     } else if (range === true || typeof range === "object") {
-      const newLowerValue = Math.round(value[0] + diff);
-      const newUpperValue = Math.round(value[1] - diff);
-      const clampedNewLowerValue = clamp(min, newLowerValue, Math.min(newUpperValue, max));
-      const clampedNewUpperValue = clamp(newLowerValue, newUpperValue, max);
-      onChange([clampedNewLowerValue, clampedNewUpperValue]);
+      onChange(handleRangeSliderWheel(min, max, value as [number, number], diff));
     }
   },
   [value, min, max, onChange, range, onWheelDisabled],
 );

99-112: Remove @ts-ignore by improving type handling.

The TypeScript ignore comment can be avoided by properly typing the onChange handler.

 const handleDoubleClick: React.MouseEventHandler<HTMLDivElement> = (event) => {
   if (
     event.target instanceof HTMLElement &&
     event.target.className.includes("ant-slider-handle") &&
     defaultValue != null
   )
     if (onResetToDefault != null) {
       onResetToDefault();
     } else {
-      // @ts-ignore Argument of type 'number | number[]' is not assignable to parameter of type 'number'.
-      //TypeScript doesn't understand that onChange always takes the type of defaultValue.
-      onChange(defaultValue);
+      onChange(defaultValue as typeof value);
     }
 };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 38f5fd1 and 576725d.

📒 Files selected for processing (1)
  • frontend/javascripts/components/slider.tsx (4 hunks)
🧰 Additional context used
📓 Learnings (1)
frontend/javascripts/components/slider.tsx (1)
Learnt from: knollengewaechs
PR: scalableminds/webknossos#8321
File: frontend/javascripts/components/slider.tsx:0-0
Timestamp: 2025-02-05T20:16:45.712Z
Learning: When tracking focus state that needs to be accessed by native event listeners (e.g., wheel events), use `useRef` instead of `useState` to ensure the event handlers always have access to the current value. This is because event listeners added via `addEventListener` would capture the initial state value if `useState` were used.
🔇 Additional comments (2)
frontend/javascripts/components/slider.tsx (2)

47-48: LGTM! Correct usage of useRef for focus state.

Using useRef for focus state is the right choice here since it needs to be accessed by the wheel event listener. This aligns with the best practice of using refs for values that shouldn't trigger re-renders.


115-121: LGTM! Good handling of user interactions.

The implementation correctly:

  • Prevents text selection during slider interaction with userSelect
  • Disables touch actions to prevent interference with wheel events
  • Manages focus state appropriately

Copy link
Member

@philippotto philippotto left a comment

Choose a reason for hiding this comment

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

awesome :) thank you for fixing the issues I found!

@knollengewaechs
Copy link
Contributor Author

thank you for the thorough review and for dog-fooding the slider! 😊

@knollengewaechs knollengewaechs merged commit 5447c6e into master Feb 6, 2025
3 checks passed
@knollengewaechs knollengewaechs deleted the slider-improvement-improvements branch February 6, 2025 14:45
@coderabbitai coderabbitai bot mentioned this pull request Jul 28, 2025
9 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Follow-up for slider improvements

2 participants