Skip to content

Shadcn low-hanging fruit follow-up#1693

Merged
myieye merged 19 commits into
developfrom
1688-shadcn-low-hanging-fruit-follow-up
May 23, 2025
Merged

Shadcn low-hanging fruit follow-up#1693
myieye merged 19 commits into
developfrom
1688-shadcn-low-hanging-fruit-follow-up

Conversation

@myieye

@myieye myieye commented May 21, 2025

Copy link
Copy Markdown
Collaborator

The most visual changes:

"I don't see my project" accidently got inside the bordered list if projects. I moved it out:
image

image

Scroll to top and focus first field:
https://github.com/user-attachments/assets/34c5520a-66b0-4f92-8ce2-3d4e5d754a8e

Tabbing:
https://github.com/user-attachments/assets/dab3ce70-0bd7-4d67-8786-cdb4fb1a0d6e

FieldWorks and Lexbox icons now share the Icon component (i.e. sizing), so alignment should always just work:
image

Autofocusing first field of new senses and examples:

localhost_5137_fwdata_rmunn-thai-food-test_browse_entryId.346b4126-a24a-4bf5-91eb-a567a647f6db.-.Google.Chrome.2025-05-21.16-20-52.mp4

@coderabbitai

coderabbitai Bot commented May 21, 2025

Copy link
Copy Markdown

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

This update introduces a new tabbable dependency and utility for improved focus management, centralizes and enhances icon rendering via a polymorphic <Icon> component, and standardizes cursor and button behaviors across menu components. Refactoring includes improved focus handling in editors, prop typing adjustments, and minor UI consistency changes for menus, buttons, and project icons.

Changes

Files/Groups Change Summary
frontend/viewer/package.json Added the tabbable package to dependencies.
frontend/viewer/src/home/HomeView.svelte, OpenInFieldWorksButton.svelte Replaced <img> elements for logos/avatars with the <Icon> component.
frontend/viewer/src/home/Server.svelte Moved "I don't see my project" button outside the projects loop and adjusted padding.
frontend/viewer/src/lib/components/editor/editor-root.svelte Changed props destructuring to let; bound ref to root <div> for DOM access.
frontend/viewer/src/lib/components/reorderer/reorderer-item-list.svelte Removed cursor-pointer class from dropdown menu items.
frontend/viewer/src/lib/components/responsive-menu/responsive-menu-item.svelte Swapped Button for DrawerClose in fallback UI; updated prop types and event binding.
frontend/viewer/src/lib/components/ui/button/index.ts Reorganized and duplicated exports for clarity; added Props alias for ButtonProps.
frontend/viewer/src/lib/components/ui/context-menu/context-menu-item.svelte,
dropdown-menu/dropdown-menu-item.svelte
Changed cursor style from default to pointer for menu items.
frontend/viewer/src/lib/components/ui/icon/icon.svelte Made <Icon> polymorphic: renders <span> for icon classes or <img> for images; added iconVariants and updated prop types.
frontend/viewer/src/lib/components/ui/icon/index.ts Now exports IconProps and iconVariants alongside Icon.
frontend/viewer/src/lib/components/ui/scroll-area/scroll-area.svelte Added bindable viewportRef prop for accessing the viewport DOM element.
frontend/viewer/src/lib/entry-editor/EntryOrSenseItemList.svelte,
ItemListItem.svelte
Added or adjusted cursor-pointer class on dropdown items; wrapped Link with snippet for prop spreading.
frontend/viewer/src/lib/entry-editor/object-editors/EntryEditor.svelte Enhanced highlighted entity state with autofocus flag; improved focus logic and added ref prop.
frontend/viewer/src/lib/entry-editor/object-editors/EntryEditorPrimitive.svelte,
ExampleEditorPrimitive.svelte,
SenseEditorPrimitive.svelte
Added editor-primitive class to editor grid containers.
frontend/viewer/src/lib/utils/tabbable.ts Added findFirstTabbable utility to locate the first tabbable element in a container.
frontend/viewer/src/project/ProjectDropdown.svelte Centralized project icon rendering with a reusable snippet; adjusted empty state rendering.
frontend/viewer/src/project/browse/BrowseView.svelte Replaced Badge component with a button styled via badgeVariants for sort toggle.
frontend/viewer/src/project/browse/EntriesList.svelte Added 300ms debounce to entries resource fetch.
frontend/viewer/src/project/browse/EntryMenu.svelte Made the "Open in FieldWorks" menu item always display if the feature is enabled.
frontend/viewer/src/project/browse/EntryView.svelte Added focus and scroll-to-top logic on entry load using new refs and findFirstTabbable; bound refs to ScrollArea and EntryEditor.
frontend/viewer/src/project/browse/SearchFilter.svelte Used mergeProps to dynamically compose props for the Toggle component in filter UI.

Poem

In the warren of code, a new path appears,
With icons that shimmer and focus that steers.
A tabbable hop, a pointery dance,
Editors now twinkle with every glance.
Menus feel snappier, buttons more bright—
This rabbit approves: the UI feels right!
🐇✨


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @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.

@github-actions

github-actions Bot commented May 21, 2025

Copy link
Copy Markdown
Contributor

UI unit Tests

12 tests   12 ✅  0s ⏱️
 4 suites   0 💤
 1 files     0 ❌

Results for commit 8f5e9b0.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented May 21, 2025

Copy link
Copy Markdown
Contributor

C# Unit Tests

116 tests  ±0   116 ✅ ±0   10s ⏱️ ±0s
 17 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 8f5e9b0. ± Comparison against base commit 7040f15.

♻️ This comment has been updated with latest results.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (4)
frontend/viewer/src/lib/components/reorderer/reorderer-item-list.svelte (1)

46-46: Confirm removal of pointer cursor for reorder items.
Dropping cursor-pointer changes the hover feedback on draggable items. If intentional, ensure this aligns with the UX guidelines. Alternatively, consider using a cursor-grab or cursor-move to indicate draggable functionality.

frontend/viewer/src/project/browse/EntryMenu.svelte (1)

66-66: Simplify conditional logic

The current condition uses || true which effectively makes the condition only dependent on features.openWithFlex. This approach adds unnecessary complexity.

-    {#if features.openWithFlex && (appLauncher || !IsMobile.value || true)}
+    {#if features.openWithFlex}
frontend/viewer/src/lib/utils/tabbable.ts (1)

1-17: Well-implemented focus utility function

This utility function is a clean implementation for finding the first tabbable element in a container. It properly handles null/undefined containers and uses the efficient TreeWalker API for DOM traversal.

Consider adding JSDoc comments to document the purpose and usage of this function, especially since it's likely to be used across multiple components.

+/**
+ * Finds the first tabbable element within a container.
+ * @param container - The container element to search within
+ * @returns The first tabbable HTMLElement or undefined if none found
+ */
 export function findFirstTabbable(container: Element | null | undefined): HTMLElement | undefined {
frontend/viewer/src/lib/components/ui/icon/icon.svelte (1)

25-25: Consider explicitly extracting the size prop.

The size variant is defined in iconVariants but not explicitly extracted from props.

- const { class: className, ...restProps }: IconProps = $props();
+ const { class: className, size = "default", ...restProps }: IconProps = $props();

Then use it when applying variants:

- <img {...restProps} class={cn(iconVariants(), className)} />
+ <img {...restProps} class={cn(iconVariants({ size }), className)} />

(And similar for the span element)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 7040f15 and 5452b93.

⛔ Files ignored due to path filters (1)
  • frontend/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (26)
  • frontend/viewer/package.json (1 hunks)
  • frontend/viewer/src/home/HomeView.svelte (3 hunks)
  • frontend/viewer/src/home/Server.svelte (1 hunks)
  • frontend/viewer/src/lib/OpenInFieldWorksButton.svelte (2 hunks)
  • frontend/viewer/src/lib/components/editor/editor-root.svelte (1 hunks)
  • frontend/viewer/src/lib/components/reorderer/reorderer-item-list.svelte (1 hunks)
  • frontend/viewer/src/lib/components/responsive-menu/responsive-menu-item.svelte (2 hunks)
  • frontend/viewer/src/lib/components/ui/button/index.ts (1 hunks)
  • frontend/viewer/src/lib/components/ui/context-menu/context-menu-item.svelte (1 hunks)
  • frontend/viewer/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte (1 hunks)
  • frontend/viewer/src/lib/components/ui/icon/icon.svelte (1 hunks)
  • frontend/viewer/src/lib/components/ui/icon/index.ts (1 hunks)
  • frontend/viewer/src/lib/components/ui/scroll-area/scroll-area.svelte (2 hunks)
  • frontend/viewer/src/lib/entry-editor/EntryOrSenseItemList.svelte (1 hunks)
  • frontend/viewer/src/lib/entry-editor/ItemListItem.svelte (1 hunks)
  • frontend/viewer/src/lib/entry-editor/object-editors/EntryEditor.svelte (9 hunks)
  • frontend/viewer/src/lib/entry-editor/object-editors/EntryEditorPrimitive.svelte (1 hunks)
  • frontend/viewer/src/lib/entry-editor/object-editors/ExampleEditorPrimitive.svelte (1 hunks)
  • frontend/viewer/src/lib/entry-editor/object-editors/SenseEditorPrimitive.svelte (1 hunks)
  • frontend/viewer/src/lib/utils/tabbable.ts (1 hunks)
  • frontend/viewer/src/project/ProjectDropdown.svelte (3 hunks)
  • frontend/viewer/src/project/browse/BrowseView.svelte (2 hunks)
  • frontend/viewer/src/project/browse/EntriesList.svelte (1 hunks)
  • frontend/viewer/src/project/browse/EntryMenu.svelte (1 hunks)
  • frontend/viewer/src/project/browse/EntryView.svelte (5 hunks)
  • frontend/viewer/src/project/browse/SearchFilter.svelte (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Build API / publish-api
  • GitHub Check: Build UI / publish-ui
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: check-and-lint
  • GitHub Check: Build FW Lite and run tests
  • GitHub Check: Analyze (csharp)
🔇 Additional comments (43)
frontend/viewer/package.json (1)

100-100: Appropriate dependency addition for focus management

Adding the "tabbable" library aligns with the PR objective of improving keyboard navigation and enhancing tabbing behavior. This library helps identify and manage focus on interactive elements.

frontend/viewer/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte (1)

18-18: Improved usability with cursor-pointer

Changing from cursor-default to cursor-pointer provides better visual feedback to users that the dropdown items are interactive. This is consistent with standard UI patterns and aligns with the visual improvements mentioned in the PR objectives.

frontend/viewer/src/lib/components/editor/editor-root.svelte (2)

9-14: Appropriate change from const to let for DOM binding

The change from const to let for the destructured props is necessary to support the DOM element binding added in line 17. This is standard practice in Svelte when variables need to be reassigned.


17-17: Improved accessibility with ref binding

Binding the ref to the root div element enables parent components to access this DOM element directly, supporting the PR objectives of improved focus management and scrolling behavior.

frontend/viewer/src/lib/components/ui/scroll-area/scroll-area.svelte (2)

9-9: Well-implemented viewport reference property

Adding the viewportRef bindable property with proper typing enables external components to access the viewport DOM element, supporting the scrolling and focus management improvements mentioned in the PR objectives.

Also applies to: 21-21


28-28: Proper DOM binding implementation

The binding between the viewportRef prop and the ScrollAreaPrimitive.Viewport element is correctly implemented, allowing parent components to control scrolling behavior programmatically.

frontend/viewer/src/lib/entry-editor/object-editors/EntryEditorPrimitive.svelte (1)

38-38: Verify presence of editor-primitive CSS definition.
You added the editor-primitive class to the editor grid container to unify styling and focus behavior. Please ensure this class is defined in your global or component stylesheet (e.g., in a shared CSS module or Tailwind config) so that it has the intended effect.

frontend/viewer/src/lib/entry-editor/object-editors/ExampleEditorPrimitive.svelte (1)

32-32: Consistent addition of editor-primitive class.
This aligns the example editor primitive with others, enabling uniform styling and focus behavior. Ensure that your focus management logic (e.g., findFirstTabbable) targets this class appropriately.

frontend/viewer/src/lib/entry-editor/ItemListItem.svelte (1)

71-71: Enhanced click affordance by adding pointer cursor.
The cursor-pointer class clearly indicates interactivity on the Remove item, improving usability and consistency with other menu items. Great enhancement!

frontend/viewer/src/lib/components/ui/context-menu/context-menu-item.svelte (1)

18-18: Switch to pointer cursor for better affordance.
Replacing cursor-default with cursor-pointer improves the visual feedback on hover, signaling that the item is clickable. This aligns with similar updates in dropdown menus.

frontend/viewer/src/lib/OpenInFieldWorksButton.svelte (2)

11-11: Good import addition for icon standardization.

Adding the Icon component import aligns with the PR objective of unifying icons across the application.


56-56: Improved icon rendering approach.

Replacing direct image usage with the Icon component ensures consistent sizing and alignment for the FieldWorks logo, as mentioned in the PR objectives.

frontend/viewer/src/project/browse/EntriesList.svelte (1)

70-72: Good optimization with debounce.

Adding a 300ms debounce to the resource call prevents excessive API requests when search parameters change rapidly, improving performance and user experience.

frontend/viewer/src/lib/entry-editor/object-editors/SenseEditorPrimitive.svelte (1)

36-36: Good addition for focus management.

Adding the editor-primitive class standardizes styling across editor components and enables improved focus management with the new tabbable utility, supporting the PR's goal of enhancing keyboard navigation.

frontend/viewer/src/project/browse/BrowseView.svelte (2)

7-7: Good refactoring of badge import.

Switching from the Badge component to badgeVariants function import follows a more flexible styling utility approach.


59-65: Improved button implementation.

Replacing the Badge component with a native button element styled using badgeVariants provides better semantics while maintaining consistent styling. This approach is more flexible and aligns with modern UI development patterns.

frontend/viewer/src/lib/components/ui/icon/index.ts (1)

1-10: Improved component exports with proper type information

The Icon component is now properly exported along with its type definitions and variants, following best practices for component modularity and reuse.

frontend/viewer/src/home/HomeView.svelte (3)

32-32: LGTM: Icon component import added

The Icon component is now imported to be used for standardizing icon rendering throughout the file.


108-108: Standardized logo rendering

Replacing the direct <img> with the Icon component improves consistency across the UI.


226-226: Consistent FieldWorks logo implementation

The FieldWorks logo is now also using the Icon component, ensuring consistent rendering and styling.

frontend/viewer/src/home/Server.svelte (1)

126-132: Improved UI structure for helper button

Moving the "I don't see my project" button outside the project list container creates a better visual hierarchy and ensures the button appears only once regardless of the number of projects.

frontend/viewer/src/lib/entry-editor/EntryOrSenseItemList.svelte (1)

22-28: Improved menu item interactivity and composition

The addition of cursor-pointer class makes the dropdown item's clickability more evident to users. The use of the {#snippet child({props})} pattern enables better component composition by allowing props to be passed down to the Link component.

frontend/viewer/src/project/browse/SearchFilter.svelte (1)

10-10: Enhanced component composition with prop merging

The addition of mergeProps and the {#snippet child({props})} pattern creates a more composable UI by allowing props to be passed down and merged with existing ones. This approach ensures the Toggle maintains its required properties while accepting additional ones from its parent.

Also applies to: 51-55

frontend/viewer/src/project/browse/EntryView.svelte (4)

5-5: Added necessary imports for enhanced user experience features

The new imports support the added functionality for improved focus management and viewport scrolling.

Also applies to: 20-21


45-45: Properly handled promise with void operator

Good practice to use the void operator to explicitly ignore the promise returned by refetch().


57-63: Enhanced user experience with automatic scrolling and focus

This watch effect is well-implemented to improve the user experience when navigating between entries by:

  1. Automatically scrolling to the top of the entry
  2. Setting focus on the first interactive element (skipping this on mobile devices)

The conditional check for mobile is a good UX consideration as automatic focus can be disruptive on touch devices.


98-98: Proper binding of DOM references

The component references are properly bound to enable the scrolling and focus functionality implemented in the watch effect.

Also applies to: 103-103

frontend/viewer/src/project/ProjectDropdown.svelte (3)

65-71: Well-organized icon rendering logic!

Creating a reusable snippet for the project icon rendering is a great DRY improvement that centralizes the conditional logic in one place.


84-84: Clean implementation of the icon snippet

Replacing the duplicated icon rendering logic with the snippet calls makes the code more maintainable and consistent.

Also applies to: 115-115


108-108: Proper placement of Command.Empty

Moving the Command.Empty inside the else block ensures it only appears after loading completes and when no projects are found, which is the correct behavior.

frontend/viewer/src/lib/components/ui/button/index.ts (1)

10-20: Improved export organization

The reorganized exports with additional aliases provide more flexible and consistent API usage patterns across the UI components.

frontend/viewer/src/lib/components/responsive-menu/responsive-menu-item.svelte (4)

7-13: Well-structured imports

The reorganized imports properly separate direct component imports from type imports, which improves code organization.


20-20: Improved type definition

The Props type now correctly combines ContextMenuItemProps and DrawerCloseProps while avoiding conflicts with the onclick handler.


48-49: Consistent event binding

Direct binding of the onSelect handler is more consistent with the component's API design.

Also applies to: 53-54


58-64: Semantic improvement with DrawerClose

Replacing Button with DrawerClose for the mobile view is semantically more appropriate and provides better integration with the drawer component.

frontend/viewer/src/lib/entry-editor/object-editors/EntryEditor.svelte (5)

10-10: Good component API enhancement

Adding the ref prop and binding it to the root element allows external components to access and manipulate the editor's DOM element when needed.

Also applies to: 35-35, 156-156


31-31: Improved focus management setup

The findFirstTabbable utility import and enhanced highlightedEntity state structure provide better support for focus management.

Also applies to: 113-113


53-53: Good distinction between highlight and focus behaviors

The code now properly distinguishes between operations that should trigger autofocus (adding new items) and those that should only highlight (moving items).

Also applies to: 60-60, 80-80, 99-99


124-126: Well-implemented autofocus logic

The conditional focus handling respects mobile devices (where focus can be problematic) and uses the findFirstTabbable utility to locate the appropriate element to focus.


161-161: Updated class bindings

The class bindings have been correctly updated to work with the new highlightedEntity structure.

Also applies to: 179-179

frontend/viewer/src/lib/components/ui/icon/icon.svelte (3)

8-18: Good implementation of tailwind-variants for consistent styling.

The use of tailwind-variants for centralizing icon styling is a good approach. The base styles and size variants are well-defined, making it easy to maintain consistent styling across different usages of the component.


20-21: Strong type definition for polymorphic component.

The union type approach for IconProps is a good solution to support both icon classes and image sources in a type-safe manner. This ensures proper type checking for both usage patterns.


30-34: Good technique for baseline alignment.

The non-breaking space in the span element is a clever way to ensure consistent baseline alignment. The descriptive comment is also helpful for future maintainers.

Comment thread frontend/viewer/src/lib/components/ui/icon/icon.svelte
Comment thread frontend/viewer/src/lib/entry-editor/object-editors/EntryEditor.svelte Outdated
Comment thread frontend/viewer/src/lib/entry-editor/object-editors/EntryEditorPrimitive.svelte Outdated
Comment thread frontend/viewer/src/lib/entry-editor/object-editors/EntryEditor.svelte Outdated
Comment thread frontend/viewer/src/project/browse/EntryMenu.svelte Outdated
Comment thread frontend/viewer/src/project/browse/EntryView.svelte Outdated

@hahn-kev hahn-kev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

looks good, I left a few things to discuss

@hahn-kev

Copy link
Copy Markdown
Collaborator

we're fixing nitpicks so here's one:
image
click the search input, and reverse tab, we probably shouldn't have 2 focus rings, the same thing happens when I tab to the filter icon.

@myieye myieye merged commit 3561600 into develop May 23, 2025
23 checks passed
@myieye myieye deleted the 1688-shadcn-low-hanging-fruit-follow-up branch May 23, 2025 06:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants