Skip to content

Conversation

@elibosley
Copy link
Member

@elibosley elibosley commented Aug 29, 2025

Summary by CodeRabbit

  • New Features

    • Fullscreen dialogs now use dedicated open/close animations for smoother transitions.
  • UX

    • Added a “Loading Notifications...” message while notifications are being fetched.
  • Style

    • Standardized Tailwind utility class ordering across numerous components for consistent styling; no functional or visual changes expected.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 29, 2025

Walkthrough

This PR predominantly reorders Tailwind utility classes across many Vue components. Two minor behavioral adjustments are included: a static “Loading Notifications...” message appears during the loading state in Error.vue, and DialogContent/DialogScrollContent add a fullscreen-aware animation path. No public APIs are changed.

Changes

Cohort / File(s) Summary
Global class reordering — Common components
unraid-ui/src/components/brand/BrandButton.vue, .../common/dialog/Dialog.vue, .../common/loading/Bar.vue, .../common/loading/Spinner.vue, .../common/popover/PopoverContent.vue, .../common/scroll-area/ScrollBar.vue, .../common/sheet/SheetContent.vue, .../common/sheet/SheetDescription.vue, .../common/sheet/SheetTitle.vue, .../common/stepper/*, .../common/tabs/*, .../common/tooltip/TooltipContent.vue
Tailwind class tokens reordered in templates; no classes added/removed; no logic changes.
Global class reordering — Form controls
unraid-ui/src/components/form/combobox/*, .../form/input/Input.vue, .../form/label/Label.vue, .../form/lightswitch/Lightswitch.vue, .../form/number/*, .../form/switch/Switch.vue
Reordered class lists across combobox, input, label, lightswitch, number field, and switch components; behavior unchanged.
Global class reordering — UI primitives
unraid-ui/src/components/ui/accordion/AccordionContent.vue, .../ui/dialog/DialogTitle.vue, .../ui/dropdown-menu/*, .../ui/select/*
Class order normalized in accordion, dialog title, dropdown-menu, and select components; no API or control-flow changes.
Layout and forms containers
unraid-ui/src/components/layout/*, unraid-ui/src/forms/*
Reordered class attributes in CardWrapper, PageContainer, SettingsGrid and multiple forms (AccordionLayout, ComboBoxField, FormErrors, HorizontalLayout, LabelRenderer, MultiSelect, ObjectArrayField, PreconditionsLabel, SteppedLayout, StringArrayField); structure and logic unchanged.
Dialog animations update
unraid-ui/src/components/ui/dialog/DialogContent.vue, .../ui/dialog/DialogScrollContent.vue
Class reordering plus addition of a fullscreen-aware animation path; close icon class order adjusted; no API changes.
Loading copy addition
unraid-ui/src/components/common/loading/Error.vue
Adds static message “Loading Notifications...” in loading state; also reorders classes elsewhere in file.

Sequence Diagram(s)

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • feat: tailwind v4 #1522 — Also updates Tailwind-related class usage across shared UI; likely adjacent to this class reordering sweep.

Suggested reviewers

  • mdatelle
  • zackspear
  • pujitm

Poem

I tidied my tails, each class in a row,
A whisker of order, a gentle UI glow.
Dialogs now swirl when fullscreen they leap,
“Loading Notifications...” softly we keep.
Hop, hop—no APIs to fear,
Just neat little stacks, from ear to ear. 🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/lint-unraid-ui

🪧 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit 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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@claude
Copy link

claude bot commented Aug 29, 2025

Claude finished @elibosley's task —— View job


Code Review Analysis

Reviewing the diff/changeset for critical issues only (bugs, security, breaking changes, data loss risks).

Todo List:

  • Examine sample changed files to understand the nature of changes
  • Analyze diffs for critical issues in changed lines only
  • Provide findings focused on high-priority issues

Review Findings

After analyzing the diffs from multiple representative files, the changes are purely CSS class reordering for Tailwind CSS consistency. The changes include:

  • Reordering Tailwind CSS classes (e.g., h-full flexflex h-full)
  • Moving color classes to the front (e.g., text-unraid-red h-10text-unraid-red h-10)
  • Standardizing class order patterns across components

✅ No critical issues found in changes

These are cosmetic formatting changes that maintain identical functionality. No bugs, security issues, breaking changes, or data loss risks were identified in the modified lines.

@github-actions
Copy link
Contributor

🚀 Storybook has been deployed to staging: https://unraid-ui-storybook-staging.unraid-workers.workers.dev

@github-actions
Copy link
Contributor

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR1638/dynamix.unraid.net.plg

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
unraid-ui/src/components/ui/select/SelectContent.vue (1)

38-42: Non-standard Tailwind syntax unsupported Replace the parentheses-based arbitrary values with valid bracket syntax (e.g. h-[var(--reka-select-trigger-height)] and min-w-[var(--reka-select-trigger-width)]) or add a plugin/config that enables the current h-(…)/min-w-(…) syntax. [unraid-ui/src/components/ui/select/SelectContent.vue:51]

unraid-ui/src/components/common/loading/Error.vue (1)

39-42: Don’t hardcode “Loading Notifications…” in a generic loader; expose it via a slot.

This component is used broadly; a notification-specific string reduces reusability and could be misleading.

Apply this diff to make the text overridable:

   <div v-if="loading" class="contents">
     <LoadingSpinner />
-    <p>Loading Notifications...</p>
+    <!-- Optional named slot for loading text -->
+    <slot name="loading-text" />
   </div>

(Consumers can provide <template #loading-text>Loading Notifications...</template> only where appropriate.)

unraid-ui/src/forms/SteppedLayout.vue (1)

44-48: Possible lost reactivity by destructuring injected store.

const { core } = jsonforms may stop tracking if jsonforms.core is replaced (common with JSON Forms). Use a ref/toRef so computed values update reliably.

[ suggest_essential_refactor ]
Apply this diff and adjust usages:

-import { computed, inject, ref, type Ref } from 'vue';
+import { computed, inject, ref, toRef, type Ref } from 'vue';

-const { core } = jsonforms; // Extract core state
+const core = toRef(jsonforms, 'core'); // keep reactivity to core replacement

Then update reads of core (outside the changed hunk) to core.value?.data?.configStep.

🧹 Nitpick comments (15)
unraid-ui/src/forms/HorizontalLayout.vue (1)

27-30: Defensive read of uischema elements (optional).

Guard against missing uischema to avoid a runtime error.

-  return layout.layout.value.uischema.elements || [];
+  return layout.layout.value.uischema?.elements ?? [];
unraid-ui/src/components/common/loading/Spinner.vue (1)

11-16: Respect prefers-reduced-motion and add ARIA hints (optional).

Consider stopping animation for users who prefer reduced motion and expose status to AT.

-        'text-primary inline-block h-8 w-8 animate-spin rounded-full border-2 border-solid border-current border-e-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]',
+        'text-primary inline-block h-8 w-8 animate-spin rounded-full border-2 border-solid border-current border-e-transparent align-[-0.125em] motion-reduce:animate-none',
-    role="status"
+    role="status" aria-live="polite" aria-busy="true"
unraid-ui/src/components/form/number/NumberFieldDecrement.vue (1)

25-25: Class reordering is fine; verify disabled state matches Reka UI.

If RekaNumberFieldDecrement sets data-disabled (common in headless libs) instead of the native disabled attr, the current disabled:* utilities won’t apply. Consider supporting both to be safe.

Apply this diff if needed:

-        'absolute top-1/2 left-0 -translate-y-1/2 p-3 disabled:cursor-not-allowed disabled:opacity-20',
+        'absolute top-1/2 left-0 -translate-y-1/2 p-3 disabled:cursor-not-allowed disabled:opacity-20 data-disabled:cursor-not-allowed data-disabled:opacity-20',
unraid-ui/src/components/ui/select/SelectItem.vue (1)

26-26: LGTM; class reorder only.

No functional changes. Optional: if RTL support is a goal, consider logical paddings (ps-8 pe-2) instead of pl-8 pr-2.

unraid-ui/src/forms/StringArrayField.vue (1)

44-61: Avoid index as v-for key to prevent input state mis-association on delete.

Using the array index as the key can cause inputs to retain the wrong value/focus after removals. Prefer a stable key derived from the item (or introduce ids if duplicates are possible).

Minimal, low-risk improvement:

-    <div v-for="(item, index) in items" :key="index" class="flex gap-2">
+    <div v-for="(item, index) in items" :key="`${index}:${item}`" class="flex gap-2">

If duplicates are common, consider evolving items to { id, value } with id: crypto.randomUUID() on add.

unraid-ui/src/forms/FormErrors.vue (1)

15-17: Add role="alert" for better a11y of validation errors

Ensures errors are announced by screen readers as they appear.

Apply:

-  <div v-if="normalizedErrors.length > 0" class="mt-2 text-sm text-red-500">
+  <div v-if="normalizedErrors.length > 0" class="mt-2 text-sm text-red-500" role="alert">
unraid-ui/src/components/form/input/Input.vue (1)

27-27: Confirm nonstandard utility “outline-hidden”.

Tailwind’s common token is outline-none. If outline-hidden is a custom util, ignore; otherwise, consider aligning.

unraid-ui/src/components/form/number/NumberFieldInput.vue (1)

16-16: Optional: drop flex if unused.

If no children rely on flex formatting for this input, flex can be removed.

unraid-ui/src/components/common/stepper/StepperSeparator.vue (1)

23-23: Suggestion: enforce class order via tooling.

To avoid churn, ensure eslint-plugin-tailwindcss or Prettier Tailwind sorting is configured consistently across the repo.

unraid-ui/src/components/form/lightswitch/Lightswitch.vue (1)

21-22: Consider using focus-visible for outline suppression.

You use focus:outline-hidden here while other files use focus-visible:outline-hidden. Prefer focus-visible to avoid hiding outlines for mouse users and to stay consistent.

Apply:

- '... focus:ring-offset-2 focus:outline-hidden',
+ '... focus:ring-offset-2 focus-visible:outline-hidden',
unraid-ui/src/components/brand/BrandButton.vue (1)

73-73: Add pointer-events-none to the fill overlay; confirm gradient utility name.

  • Prevents accidental hit-testing if stacking/context changes. Also, verify bg-linear-to-r is intentional (custom alias) vs Tailwind’s bg-gradient-to-r.
-      class="from-unraid-red to-orange absolute -top-[2px] -right-[2px] -bottom-[2px] -left-[2px] -z-10 rounded-md bg-linear-to-r opacity-100 transition-all group-hover:!opacity-60 group-focus:!opacity-60"
+      class="from-unraid-red to-orange pointer-events-none absolute -top-[2px] -right-[2px] -bottom-[2px] -left-[2px] -z-10 rounded-md bg-linear-to-r opacity-100 transition-all group-hover:!opacity-60 group-focus:!opacity-60"
unraid-ui/src/components/form/combobox/ComboboxItem.vue (1)

24-24: Verify non-standard Tailwind token "outline-hidden"

Tailwind core exposes outline-none (not outline-hidden). If "outline-hidden" isn’t added via plugin/safelist, this utility will be dropped in production builds.

Apply if unintentional:

-        'data-highlighted:bg-accent data-highlighted:text-accent-foreground relative flex cursor-default items-center justify-between gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0',
+        'data-highlighted:bg-accent data-highlighted:text-accent-foreground relative flex cursor-default items-center justify-between gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:outline-none select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0',
unraid-ui/src/components/ui/accordion/AccordionContent.vue (1)

15-15: Confirm intent: consumer classes apply to inner wrapper, not root

As written, props.class affects the inner div only. If the contract is to allow callers to style the root AccordionContent, shift props.class to the root and keep padding on the inner wrapper.

Optional change:

-  <AccordionContent
-    v-bind="delegatedProps"
-    class="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm transition-all"
-  >
-    <div :class="cn('pt-0 pb-4', props.class)">
+  <AccordionContent
+    v-bind="delegatedProps"
+    :class="cn('data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm transition-all', props.class)"
+  >
+    <div class="pt-0 pb-4">

Also applies to: 17-17

unraid-ui/src/components/ui/dropdown-menu/DropdownMenuContent.vue (1)

35-35: Optional: respect reduced-motion users for menu animations

Consider guarding animation/transition utilities with motion-safe/motion-reduce variants.

Apply within this line:

-'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-32 overflow-hidden rounded-lg border p-1 shadow-md'
+'bg-popover text-popover-foreground motion-safe:data-[state=open]:animate-in motion-safe:data-[state=closed]:animate-out motion-safe:data-[state=closed]:fade-out-0 motion-safe:data-[state=open]:fade-in-0 motion-safe:data-[state=closed]:zoom-out-95 motion-safe:data-[state=open]:zoom-in-95 motion-safe:data-[side=bottom]:slide-in-from-top-2 motion-safe:data-[side=left]:slide-in-from-right-2 motion-safe:data-[side=right]:slide-in-from-left-2 motion-safe:data-[side=top]:slide-in-from-bottom-2 motion-reduce:transition-none motion-reduce:transform-none z-50 min-w-32 overflow-hidden rounded-lg border p-1 shadow-md'
unraid-ui/src/components/form/number/NumberFieldIncrement.vue (1)

25-25: Optional a11y: add an accessible name

Icon-only control may be silent to AT. Provide an aria-label or sr-only text.

Example:

<RekaNumberFieldIncrement aria-label="Increment value" ...>
  <slot>
    <span class="sr-only">Increment</span>
    <Plus class="h-4 w-4" aria-hidden="true" />
  </slot>
</RekaNumberFieldIncrement>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a1ee915 and 84e868d.

📒 Files selected for processing (64)
  • unraid-ui/src/components/brand/BrandButton.vue (2 hunks)
  • unraid-ui/src/components/common/dialog/Dialog.vue (1 hunks)
  • unraid-ui/src/components/common/loading/Bar.vue (1 hunks)
  • unraid-ui/src/components/common/loading/Error.vue (2 hunks)
  • unraid-ui/src/components/common/loading/Spinner.vue (1 hunks)
  • unraid-ui/src/components/common/popover/PopoverContent.vue (1 hunks)
  • unraid-ui/src/components/common/scroll-area/ScrollBar.vue (1 hunks)
  • unraid-ui/src/components/common/sheet/SheetContent.vue (1 hunks)
  • unraid-ui/src/components/common/sheet/SheetDescription.vue (1 hunks)
  • unraid-ui/src/components/common/sheet/SheetTitle.vue (1 hunks)
  • unraid-ui/src/components/common/stepper/StepperDescription.vue (1 hunks)
  • unraid-ui/src/components/common/stepper/StepperIndicator.vue (1 hunks)
  • unraid-ui/src/components/common/stepper/StepperSeparator.vue (1 hunks)
  • unraid-ui/src/components/common/stepper/StepperTrigger.vue (1 hunks)
  • unraid-ui/src/components/common/tabs/TabsContent.vue (1 hunks)
  • unraid-ui/src/components/common/tabs/TabsList.vue (1 hunks)
  • unraid-ui/src/components/common/tabs/TabsTrigger.vue (1 hunks)
  • unraid-ui/src/components/common/tooltip/TooltipContent.vue (1 hunks)
  • unraid-ui/src/components/form/combobox/ComboboxGroup.vue (1 hunks)
  • unraid-ui/src/components/form/combobox/ComboboxInput.vue (1 hunks)
  • unraid-ui/src/components/form/combobox/ComboboxItem.vue (1 hunks)
  • unraid-ui/src/components/form/combobox/ComboboxList.vue (1 hunks)
  • unraid-ui/src/components/form/combobox/ComboboxSeparator.vue (1 hunks)
  • unraid-ui/src/components/form/input/Input.vue (1 hunks)
  • unraid-ui/src/components/form/label/Label.vue (1 hunks)
  • unraid-ui/src/components/form/lightswitch/Lightswitch.vue (1 hunks)
  • unraid-ui/src/components/form/number/NumberField.vue (1 hunks)
  • unraid-ui/src/components/form/number/NumberFieldContent.vue (1 hunks)
  • unraid-ui/src/components/form/number/NumberFieldDecrement.vue (1 hunks)
  • unraid-ui/src/components/form/number/NumberFieldIncrement.vue (1 hunks)
  • unraid-ui/src/components/form/number/NumberFieldInput.vue (1 hunks)
  • unraid-ui/src/components/form/switch/Switch.vue (1 hunks)
  • unraid-ui/src/components/layout/CardWrapper.vue (1 hunks)
  • unraid-ui/src/components/layout/PageContainer.vue (1 hunks)
  • unraid-ui/src/components/layout/SettingsGrid.vue (1 hunks)
  • unraid-ui/src/components/ui/accordion/AccordionContent.vue (1 hunks)
  • unraid-ui/src/components/ui/dialog/DialogContent.vue (2 hunks)
  • unraid-ui/src/components/ui/dialog/DialogDescription.vue (1 hunks)
  • unraid-ui/src/components/ui/dialog/DialogScrollContent.vue (2 hunks)
  • unraid-ui/src/components/ui/dialog/DialogTitle.vue (1 hunks)
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue (1 hunks)
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuContent.vue (1 hunks)
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuItem.vue (1 hunks)
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue (1 hunks)
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue (1 hunks)
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue (1 hunks)
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue (1 hunks)
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue (1 hunks)
  • unraid-ui/src/components/ui/select/SelectContent.vue (1 hunks)
  • unraid-ui/src/components/ui/select/SelectGroup.vue (1 hunks)
  • unraid-ui/src/components/ui/select/SelectItem.vue (1 hunks)
  • unraid-ui/src/components/ui/select/SelectLabel.vue (1 hunks)
  • unraid-ui/src/components/ui/select/SelectSeparator.vue (1 hunks)
  • unraid-ui/src/components/ui/select/SelectTrigger.vue (1 hunks)
  • unraid-ui/src/forms/AccordionLayout.vue (1 hunks)
  • unraid-ui/src/forms/ComboBoxField.vue (3 hunks)
  • unraid-ui/src/forms/FormErrors.vue (1 hunks)
  • unraid-ui/src/forms/HorizontalLayout.vue (1 hunks)
  • unraid-ui/src/forms/LabelRenderer.vue (1 hunks)
  • unraid-ui/src/forms/MultiSelect.vue (5 hunks)
  • unraid-ui/src/forms/ObjectArrayField.vue (4 hunks)
  • unraid-ui/src/forms/PreconditionsLabel.vue (1 hunks)
  • unraid-ui/src/forms/SteppedLayout.vue (1 hunks)
  • unraid-ui/src/forms/StringArrayField.vue (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/components/**/*.vue

📄 CodeRabbit inference engine (.cursor/rules/web-testing-rules.mdc)

Some Vue files may require explicit imports like ref or computed due to Nuxt auto-imports not applying in tests

Files:

  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue
  • unraid-ui/src/components/form/number/NumberField.vue
  • unraid-ui/src/components/layout/SettingsGrid.vue
  • unraid-ui/src/components/form/lightswitch/Lightswitch.vue
  • unraid-ui/src/components/common/stepper/StepperDescription.vue
  • unraid-ui/src/components/form/number/NumberFieldContent.vue
  • unraid-ui/src/components/common/stepper/StepperTrigger.vue
  • unraid-ui/src/components/layout/PageContainer.vue
  • unraid-ui/src/components/ui/dialog/DialogTitle.vue
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue
  • unraid-ui/src/components/ui/accordion/AccordionContent.vue
  • unraid-ui/src/components/common/loading/Bar.vue
  • unraid-ui/src/components/ui/dialog/DialogDescription.vue
  • unraid-ui/src/components/common/scroll-area/ScrollBar.vue
  • unraid-ui/src/components/ui/select/SelectSeparator.vue
  • unraid-ui/src/components/common/stepper/StepperIndicator.vue
  • unraid-ui/src/components/ui/select/SelectLabel.vue
  • unraid-ui/src/components/form/combobox/ComboboxSeparator.vue
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue
  • unraid-ui/src/components/common/tabs/TabsList.vue
  • unraid-ui/src/components/common/stepper/StepperSeparator.vue
  • unraid-ui/src/components/common/loading/Spinner.vue
  • unraid-ui/src/components/form/number/NumberFieldDecrement.vue
  • unraid-ui/src/components/common/sheet/SheetTitle.vue
  • unraid-ui/src/components/common/sheet/SheetContent.vue
  • unraid-ui/src/components/ui/select/SelectItem.vue
  • unraid-ui/src/components/form/number/NumberFieldIncrement.vue
  • unraid-ui/src/components/common/loading/Error.vue
  • unraid-ui/src/components/ui/select/SelectGroup.vue
  • unraid-ui/src/components/common/sheet/SheetDescription.vue
  • unraid-ui/src/components/common/tabs/TabsContent.vue
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuContent.vue
  • unraid-ui/src/components/form/combobox/ComboboxItem.vue
  • unraid-ui/src/components/common/dialog/Dialog.vue
  • unraid-ui/src/components/form/label/Label.vue
  • unraid-ui/src/components/common/tooltip/TooltipContent.vue
  • unraid-ui/src/components/common/tabs/TabsTrigger.vue
  • unraid-ui/src/components/brand/BrandButton.vue
  • unraid-ui/src/components/form/switch/Switch.vue
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue
  • unraid-ui/src/components/ui/dialog/DialogContent.vue
  • unraid-ui/src/components/ui/select/SelectTrigger.vue
  • unraid-ui/src/components/common/popover/PopoverContent.vue
  • unraid-ui/src/components/form/combobox/ComboboxInput.vue
  • unraid-ui/src/components/layout/CardWrapper.vue
  • unraid-ui/src/components/ui/select/SelectContent.vue
  • unraid-ui/src/components/ui/dialog/DialogScrollContent.vue
  • unraid-ui/src/components/form/input/Input.vue
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue
  • unraid-ui/src/components/form/number/NumberFieldInput.vue
  • unraid-ui/src/components/form/combobox/ComboboxList.vue
  • unraid-ui/src/components/ui/dropdown-menu/DropdownMenuItem.vue
  • unraid-ui/src/components/form/combobox/ComboboxGroup.vue
🧠 Learnings (6)
📚 Learning: 2025-02-21T18:59:47.977Z
Learnt from: mdatelle
PR: unraid/api#1183
File: web/components/Modal.vue:120-120
Timestamp: 2025-02-21T18:59:47.977Z
Learning: In the Modal.vue component, the modal's width is controlled through the `maxWidth` prop (defaults to 'sm:max-w-lg'). The parent containers with `w-screen` and `w-full` classes ensure proper width behavior, making additional width classes on the inner modal content div redundant.

Applied to files:

  • unraid-ui/src/components/layout/PageContainer.vue
📚 Learning: 2024-12-06T17:38:40.999Z
Learnt from: elibosley
PR: unraid/api#974
File: web/components/Loading/Error.vue:1-3
Timestamp: 2024-12-06T17:38:40.999Z
Learning: In Nuxt.js projects, components are automatically imported, so explicit import statements for components like `LoadingSpinner` in `web/components/Loading/Error.vue` are not necessary.

Applied to files:

  • unraid-ui/src/components/common/loading/Spinner.vue
  • unraid-ui/src/components/common/loading/Error.vue
📚 Learning: 2024-11-01T17:52:55.311Z
Learnt from: pujitm
PR: unraid/api#941
File: web/components/Notifications/Item.vue:0-0
Timestamp: 2024-11-01T17:52:55.311Z
Learning: In the `web/components/Notifications/Item.vue` component, ensure that when delete or archive mutations fail, the notification remains displayed, and an error message is shown below the action buttons to inform the user.

Applied to files:

  • unraid-ui/src/components/common/loading/Error.vue
📚 Learning: 2024-12-06T17:34:16.133Z
Learnt from: pujitm
PR: unraid/api#974
File: web/components/Loading/Error.vue:50-50
Timestamp: 2024-12-06T17:34:16.133Z
Learning: In this project, the `Button` component from `~/components/shadcn/Button.vue` is autoloaded and does not need to be imported manually in components like `web/components/Loading/Error.vue`.

Applied to files:

  • unraid-ui/src/components/common/loading/Error.vue
📚 Learning: 2025-02-06T17:24:58.784Z
Learnt from: mdatelle
PR: unraid/api#1122
File: web/components/UserProfile/DropdownLaunchpad.vue:38-42
Timestamp: 2025-02-06T17:24:58.784Z
Learning: In the DropdownLaunchpad.vue component, the current implementation of conditional icon rendering using `h(BrandLoading, { variant: 'white' })` is a temporary fix to maintain build stability, with a proper refactoring being handled in a separate branch.

Applied to files:

  • unraid-ui/src/components/brand/BrandButton.vue
📚 Learning: 2025-02-18T18:38:24.981Z
Learnt from: zackspear
PR: unraid/api#1143
File: web/pages/webComponents.vue:28-29
Timestamp: 2025-02-18T18:38:24.981Z
Learning: In Vue components, when there's a repeating pattern of heading + content + divider, prefer using a wrapper component that takes the heading as a prop and content via slots, rather than duplicating the structure. This improves maintainability and reduces code duplication.

Applied to files:

  • unraid-ui/src/components/form/combobox/ComboboxGroup.vue
🔇 Additional comments (71)
unraid-ui/src/forms/HorizontalLayout.vue (1)

34-34: LGTM — class order only.

No behavior change; utilities remain identical.

unraid-ui/src/components/common/sheet/SheetDescription.vue (1)

16-16: LGTM — class reorder is safe.

Purely presentational; keeps override-friendly base + props.class order.

unraid-ui/src/components/common/stepper/StepperDescription.vue (1)

22-22: LGTM — class reorder only.

No functional impact; keeps base styles before consumer overrides.

unraid-ui/src/components/common/tabs/TabsTrigger.vue (1)

22-22: LGTM — standardized utility order.

No behavior change; ring and active-state utilities unaffected by order.

unraid-ui/src/components/ui/select/SelectGroup.vue (1)

13-13: LGTM on Tailwind order tweak.

Purely cosmetic reorder; no behavioral changes.

unraid-ui/src/forms/LabelRenderer.vue (1)

77-77: LGTM on wrapper class order change.

No impact beyond readability/consistency.

unraid-ui/src/components/common/loading/Bar.vue (1)

8-8: LGTM; cosmetic Tailwind reorder.

ARIA usage unchanged and appropriate for an indeterminate skeleton.

unraid-ui/src/components/form/number/NumberFieldContent.vue (1)

15-17: LGTM: class-order normalization only.

Reordering the decrement/increment padding variants is a no-op; selectors don’t conflict. No behavioral impact.

unraid-ui/src/components/ui/dialog/DialogTitle.vue (1)

17-17: LGTM: non-functional Tailwind token reorder.

Props forwarding and reactivity remain intact.

unraid-ui/src/components/common/sheet/SheetTitle.vue (1)

16-16: LGTM: reordered utility classes.

Explicit import of computed satisfies the tests/auto-import guideline.

unraid-ui/src/components/common/dialog/Dialog.vue (1)

86-87: LGTM: fullscreen class string reorder preserves intent.

max-w-none still comes after sizeClasses.full in the cn(...) call, so it continues to override max-w-full when size === 'full'. No change in runtime behavior.

unraid-ui/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue (1)

11-11: LGTM: trigger class order reshuffle.

No API/behavioral change.

unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue (1)

17-17: LGTM: purely presentational reorder.

Class order change is no-op; cn usage and delegated props remain correct and consistent with SelectSeparator.

unraid-ui/src/components/layout/SettingsGrid.vue (1)

13-16: LGTM: Tailwind class reorder only.

No functional impact; layout utilities and selector group remain intact.

unraid-ui/src/forms/StringArrayField.vue (1)

65-65: LGTM: class order nit only.

No behavioral change to the Add Item button.

unraid-ui/src/components/ui/select/SelectSeparator.vue (1)

13-14: LGTM: presentational-only class reorder.

Delegation and cn merge stay unchanged; matches DropdownMenuSeparator.

unraid-ui/src/components/ui/select/SelectLabel.vue (1)

10-12: LGTM: class token swap only.

No impact on layout or accessibility; slot structure unchanged.

unraid-ui/src/components/common/stepper/StepperTrigger.vue (1)

23-25: LGTM — class reorder only

No conflicting utilities introduced; behavior unchanged.

unraid-ui/src/components/layout/PageContainer.vue (1)

13-15: LGTM — class reorder only

Container sizing via w-full + :class="maxWidth" remains intact.

unraid-ui/src/components/common/tabs/TabsList.vue (1)

20-22: LGTM — class reorder only

No semantic or accessibility impact from the change.

unraid-ui/src/components/form/label/Label.vue (1)

20-22: LGTM — class reorder only

No behavior change; props forwarding unaffected.

unraid-ui/src/components/form/input/Input.vue (1)

27-27: LGTM — class reordering only.

No logic or API changes; utility set remains equivalent.

unraid-ui/src/components/form/number/NumberFieldInput.vue (1)

16-16: LGTM — cosmetic reorder.

Classes and variants preserved; no behavioral change.

unraid-ui/src/components/form/combobox/ComboboxSeparator.vue (1)

17-17: LGTM — order-only change.

No risk; props forwarding and slot intact.

unraid-ui/src/components/common/stepper/StepperSeparator.vue (1)

23-23: LGTM — order-only change with variants preserved.

group-data-* variants are unchanged; visual behavior remains consistent.

unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue (1)

25-25: LGTM — animation/layout tokens reordered.

Same utilities retained; no side-effects expected.

unraid-ui/src/components/common/popover/PopoverContent.vue (1)

38-39: Safe to reorder—cn uses twMerge for Tailwind class merging.

unraid-ui/src/components/ui/dialog/DialogDescription.vue (1)

15-15: LGTM — purely cosmetic order change.

No behavior change; explicit imports present (good for tests without Nuxt auto-imports).

unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue (1)

20-21: LGTM — class order shuffle only.

No functional differences; explicit imports are correct.

unraid-ui/src/components/common/stepper/StepperIndicator.vue (1)

23-31: LGTM — order-only change.

No behavior change; states and slots unaffected.

unraid-ui/src/components/form/switch/Switch.vue (2)

30-31: LGTM: class reordering is non-functional.

No conflicting utilities; merging via cn remains safe.


38-39: LGTM: thumb classes unchanged functionally.

Order swap does not affect behavior.

unraid-ui/src/components/form/combobox/ComboboxInput.vue (1)

33-34: LGTM: reorder only.

No precedence conflicts; same utility set.

unraid-ui/src/components/form/combobox/ComboboxList.vue (1)

36-41: Remove outline-hidden availability check — it’s a built-in Tailwind CSS v4 utility.
No custom definition or plugin is required; continue using outline-hidden as intended.

Likely an incorrect or invalid review comment.

unraid-ui/src/forms/ComboBoxField.vue (3)

93-94: LGTM: cosmetic reorder.

No behavioral change.


102-103: LGTM; ensure outline-hidden exists.

Same note as elsewhere; otherwise swap to outline-none.


116-117: LGTM; consistency with the above item.

Mirrors the same class set/order.

unraid-ui/src/components/brand/BrandButton.vue (2)

80-83: LGTM — outline gradient block reorder is non-functional.


100-103: LGTM — iconRight hover/focus reveal unchanged; order-only.

unraid-ui/src/components/common/sheet/SheetContent.vue (3)

49-50: LGTM — overlay classes reordered; behavior intact.


55-55: LGTM — close button class order only.


56-56: LGTM — icon classes reorder only.

unraid-ui/src/forms/PreconditionsLabel.vue (1)

35-36: LGTM — purely class order changes.

unraid-ui/src/components/common/scroll-area/ScrollBar.vue (2)

26-31: LGTM — scrollbar container class order change only.


33-33: LGTM — thumb classes reordered; no functional impact.

unraid-ui/src/components/common/tabs/TabsContent.vue (1)

19-21: LGTM — TabsContent class list reordered; semantics unchanged.

unraid-ui/src/forms/AccordionLayout.vue (1)

8-8: Order-only Tailwind changes look good

Utility reordering preserves the same set of classes; no behavior change expected.

Also applies to: 10-10, 15-15, 20-20

unraid-ui/src/components/form/combobox/ComboboxGroup.vue (1)

26-26: LGTM on class reordering

No functional differences; descendant selector tokens remain intact.

Also applies to: 31-31

unraid-ui/src/components/ui/dialog/DialogScrollContent.vue (1)

35-35: Dialog class reordering: OK

Overlay/content/close-button class moves are cosmetic; behavior and a11y remain unchanged.

Also applies to: 40-41, 63-65

unraid-ui/src/components/common/loading/Error.vue (2)

37-37: Class reordering is fine.


46-46: Icon class reordering is fine.

unraid-ui/src/forms/SteppedLayout.vue (2)

145-145: Class reordering on StepperDescription is fine.


150-151: Class reordering on StepperSeparator is fine.

unraid-ui/src/components/ui/select/SelectTrigger.vue (2)

20-21: Root class reordering is fine.


27-27: Icon class reordering is fine.

unraid-ui/src/components/common/tooltip/TooltipContent.vue (1)

41-41: Tooltip class reordering is fine.

unraid-ui/src/components/layout/CardWrapper.vue (2)

22-22: Root class reordering is fine.


27-29: Variant class reordering is fine.

unraid-ui/src/components/ui/dialog/DialogContent.vue (2)

36-36: LGTM on class reordering and icon sizing.

Overlay/close button class reorders are safe; no behavioral impact.

Also applies to: 57-60


42-49: No object/array class bindings found on DialogContent; fullscreen detection change isn’t required.

Likely an incorrect or invalid review comment.

unraid-ui/src/forms/ObjectArrayField.vue (1)

171-171: LGTM: stylistic Tailwind reordering only.

No logic changes. Visuals and interactions remain intact.

Also applies to: 199-201, 209-209, 217-224, 243-247

unraid-ui/src/forms/MultiSelect.vue (1)

103-103: LGTM: class-order tweaks only.

All adjustments are presentational; selection behavior unchanged.

Also applies to: 122-122, 143-143, 175-176, 182-182, 206-206, 214-214

unraid-ui/src/components/form/number/NumberField.vue (1)

23-23: LGTM: non-functional class order change.

No impact on layout or behavior.

unraid-ui/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue (1)

28-28: LGTM: ordering of utilities only.

Focus/spacing semantics preserved; no API or behavior change.

unraid-ui/src/components/ui/dropdown-menu/DropdownMenuContent.vue (1)

35-35: LGTM: class reordering only

Utility order change is non-functional; tokens unchanged. Safe.

unraid-ui/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue (3)

27-27: LGTM: reordered utilities

Focus and spacing utilities reordered only; no behavior change.


34-34: LGTM: icon size class swap is a no-op

Swapping h-4 and w-4 order doesn’t affect rendering.


27-27: Remove utility check—outline-hidden is a built-in Tailwind CSS v4 class, no custom plugin required.

unraid-ui/src/components/form/number/NumberFieldIncrement.vue (1)

25-25: LGTM: class order change only

No functional/visual change expected; explicit computed import satisfies test env guideline.

unraid-ui/src/components/ui/dropdown-menu/DropdownMenuItem.vue (2)

21-21: LGTM: utility sort

Reordering only; tokens unchanged. Safe.


21-21: Confirm Tailwind’s custom outline-hidden utility is available
No local tailwind.config.* found—ensure outline-hidden is defined in your Tailwind config or plugin (e.g., at the monorepo root).

:class="
cn(
'relative flex cursor-default select-none items-center rounded-sm gap-2 px-2 py-1.5 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0',
'focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden transition-colors select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0',
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Prevent leaking the local inset prop to the underlying Reka component

Currently inset is forwarded via v-bind and may render as an unknown DOM attribute. Omit it from forwarded props.

Outside this line, update the setup block:

// in <script setup>
const delegatedProps = reactiveOmit(props, 'class', 'inset');
🤖 Prompt for AI Agents
In unraid-ui/src/components/ui/dropdown-menu/DropdownMenuItem.vue around line
21, the local prop "inset" is being forwarded to the underlying Reka component
and may become an unknown DOM attribute; omit it from forwarded props by
creating a delegatedProps reactive object that excludes 'class' and 'inset'
(e.g., use reactiveOmit(props, 'class', 'inset')) in the <script setup> and use
that delegatedProps for v-bind on the Reka component so "inset" is not passed
through.

@elibosley elibosley merged commit 6356f9c into main Aug 29, 2025
15 checks passed
@elibosley elibosley deleted the fix/lint-unraid-ui branch August 29, 2025 18:48
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