Skip to content

Conversation

@elibosley
Copy link
Member

@elibosley elibosley commented Jul 16, 2025

Summary by CodeRabbit

  • New Features

    • Streamlined Tailwind CSS integration using Vite plugin, eliminating the need for separate Tailwind config files.
    • Updated theme and color variables for improved consistency and maintainability.
  • Style

    • Standardized spacing, sizing, and font classes across all components using Tailwind’s default scale.
    • Reduced excessive gaps, padding, and font sizes for a more compact and cohesive UI.
    • Updated gradient, border, and shadow classes to match Tailwind v4 conventions.
    • Replaced custom pixel-based classes with Tailwind’s bracketed arbitrary value syntax where needed.
    • Replaced focus outline styles from outline-none to outline-hidden for consistent focus handling.
    • Updated flex shrink/grow utility classes to use newer shorthand forms.
    • Converted several component templates to use self-closing tags for cleaner markup.
    • Adjusted icon sizes and spacing for improved visual balance.
  • Chores

    • Removed legacy Tailwind/PostCSS configuration files and related scripts.
    • Updated and cleaned up package dependencies for Tailwind v4 and related plugins.
    • Removed unused or redundant build scripts and configuration exports.
    • Updated documentation to reflect new Tailwind v4 usage.
    • Removed Prettier Tailwind plugin from formatting configurations.
    • Removed Nuxt Tailwind module in favor of direct Vite plugin integration.
    • Cleaned up ESLint config by removing Prettier integration.
  • Bug Fixes

    • Corrected invalid or outdated Tailwind class names and syntax.
    • Fixed issues with max-width and other utility classes for improved layout consistency.
  • Tests

    • Updated test assertions to match new class names and styling conventions.
  • Documentation

    • Revised README and internal notes to clarify Tailwind v4 adoption and configuration changes.
    • Added new development notes emphasizing Tailwind v4 usage and documentation references.
  • UI Components

    • Enhanced BrandButton stories with detailed variant, size, and padding showcases for better visual testing.
    • Improved theme store to apply dark mode class on both <html> and <body> elements for compatibility.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 16, 2025

Walkthrough

This update removes all custom Tailwind CSS configuration files and presets, migrates both UI and web projects to Tailwind CSS v4 using the new Vite plugin, and standardizes styling with Tailwind’s default utility classes and spacing scales. Numerous components, tests, and documentation are updated for new class naming conventions, spacing, and theme variable usage. PostCSS, Prettier, and ESLint configs are adjusted to reflect the new Tailwind integration.

Changes

Files/Groups Change Summary
unraid-ui/tailwind.config.ts, unraid-ui/src/theme/preset.ts, web/tailwind.config.ts, web/tailwind-shadcn.config.ts Removed all Tailwind CSS config and theme preset files
unraid-ui/package.json, web/package.json, package.json Updated dependencies for Tailwind v4, switched to @tailwindcss/vite, removed old plugins and scripts
unraid-ui/vite.config.ts, unraid-ui/vite.web-component.ts, web/nuxt.config.ts Integrated Tailwind via Vite plugin, removed PostCSS config, updated build inputs
unraid-ui/postcss.config.js, unraid-ui/scripts/build-style.mjs Deleted PostCSS build scripts and configs
unraid-ui/.prettierrc.json, web/.prettierrc.mjs, web/eslint.config.mjs Removed Prettier Tailwind plugin and Prettier ESLint config
unraid-ui/.storybook/main.ts, unraid-ui/.storybook/preview.ts Updated Storybook config for new CSS import and Vite plugin
unraid-ui/components.json, unraid-ui/src/index.ts, unraid-ui/tsconfig.json Removed references to deleted Tailwind config files
unraid-ui/src/styles/globals.css, web/assets/main.css Migrated to Tailwind v4 import syntax, added @theme block, updated variables and global styles
unraid-ui/src/styles/index.css Fixed relative import paths
unraid-ui/src/components/, web/components/, web/pages/, web/layouts/, web/forms/** Updated CSS utility classes: spacing, sizing, font, gradient, outline, and attribute selector syntax
unraid-ui/src/components/brand/brand-button.variants.ts, unraid-ui/src/components/common/badge/badge.variants.ts Updated size, gap, and padding classes to Tailwind scale
unraid-ui/src/components/layout/PageContainer.vue, web/components/Registration.ce.vue, etc. Changed max-width classes to bracketed syntax (e.g., max-w-[800px])
web/app.vue Sets data-env and CSS variables for dev/prod environments
web/test/**, unraid-ui/src/components/common/button/Button.test.ts Updated test assertions for new class names and styles
CLAUDE.md Added notes on Tailwind v4 usage and config removal
.claude/settings.local.json Expanded allowed Bash/WebFetch permissions for new build steps

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant Vite as Vite Build
    participant Tailwind as Tailwind V4 Plugin
    participant UI as UI Components
    participant Web as Web Components

    Dev->>Vite: Runs dev/build
    Vite->>Tailwind: Loads Tailwind via Vite plugin
    Tailwind->>UI: Applies default theme, parses utility classes
    Tailwind->>Web: Applies default theme, parses utility classes
    UI->>Vite: Imports CSS with @import 'tailwindcss', uses utility classes
    Web->>Vite: Imports CSS with @import 'tailwindcss', uses utility classes
    Vite->>Dev: Outputs built assets with standardized Tailwind styles
Loading

Possibly related PRs

Suggested reviewers

  • mdatelle
  • pujitm
  • zackspear

Poem

Tailwind’s config files drift away,
Vite’s new plugin saves the day.
Classes shrink, spacing tight,
Outlines hidden, colors bright.
From scripts to styles, all align—
The codebase shines,
In Tailwind’s streamlined design! ✨

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.

@elibosley elibosley marked this pull request as draft July 16, 2025 21:10
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: 9

🔭 Outside diff range comments (3)
web/pages/index.vue (1)

60-66: Update remaining outline variants to outline-solid

The rename from outlineoutline-solid will break any <Button variant="outline"> (or <BrandButton variant="outline">) instances. Please update all of the following occurrences:

• unraid-ui/stories/components/common/Tooltip.stories.ts:33
• unraid-ui/stories/components/common/Sheet.stories.ts:54, 65, 73, 85, 118, 144
• unraid-ui/src/forms/StringArrayField.vue:63
• unraid-ui/src/forms/SteppedLayout.vue:167
• web/components/Notifications/Item.vue:123

Example diff to apply everywhere:

- <Button variant="outline">
+ <Button variant="outline-solid">

After updating these, re-run rg 'variant=["\']outline["\']' to confirm no lingering outline variants remain.

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

23-29: Use Tailwind’s bracketed attribute variant for disabled state

Tailwind’s built-in attribute variant syntax requires the bracket form (group-data-[disabled]). No custom data-disabled variant was found in unraid-ui/tailwind.config.ts, so the current group-data-disabled:* rules won’t apply and will revert to the default styles.

Please update both occurrences:

• unraid-ui/src/components/common/stepper/StepperIndicator.vue (line 25)
• unraid-ui/src/components/common/stepper/StepperSeparator.vue (line 25)

- 'group-data-disabled:text-muted-foreground group-data-disabled:opacity-50',
+ 'group-data-[disabled]:text-muted-foreground group-data-[disabled]:opacity-50',
- 'group-data-disabled:bg-muted group-data-disabled:opacity-75',
+ 'group-data-[disabled]:bg-muted group-data-[disabled]:opacity-75',
unraid-ui/package.json (1)

43-43: Update peer dependency version to match Tailwind v4.

The peer dependency still references tailwindcss: "3.4.17" while the devDependency was updated to 4.1.11. This inconsistency could cause issues for consumers.

-    "tailwindcss": "3.4.17",
+    "tailwindcss": "4.1.11",
♻️ Duplicate comments (3)
web/components/ConnectSettings/ConnectSettings.ce.vue (1)

154-154: Same <style>-tag whitespace nit—see earlier comment
Replicate the cleanup suggested in ThemeSwitcher.

web/components/DowngradeOs.ce.vue (1)

81-81: Follow the <style>-tag whitespace tidy-up
Same spacing nit as noted in ThemeSwitcher.

web/components/SsoButton.ce.vue (1)

154-154: Apply the <style> tag spacing fix here as well
Align with the convention from the first comment.

🧹 Nitpick comments (3)
web/components/ThemeSwitcher.ce.vue (1)

95-95: Trim the stray space in the <style> tag

The extra whitespace before > is harmless but noisy. Tighten it for consistency with the rest of the codebase.

-<style >
+<style>
web/pages/index.vue (1)

211-215: Loss of lang="postcss" is fine, but remove empty space

Minor: <style > has an extra space after the tag name. Won’t break anything, but worth tidying.

-<style >
+<style>
web/pages/login.vue (1)

10-12: Shadow intensity changed – design approved?

shadowshadow-sm reduces elevation. Just verify with the design team that the lighter shadow matches the refreshed Tailwind v4 palette; otherwise LGTM.

Comment on lines 53 to 57
<DialogClose
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"
>
<X class="w-4 h-4 text-muted-foreground" />
</DialogClose>
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

Same invalid utility as above
Replace focus:outline-hidden with focus:outline-none (or focus:outline-0) to keep the intended visual behaviour.

🤖 Prompt for AI Agents
In unraid-ui/src/components/common/sheet/SheetContent.vue around lines 53 to 57,
replace the invalid Tailwind CSS utility class `focus:outline-hidden` with the
correct class `focus:outline-none` (or `focus:outline-0`) on the DialogClose
component to ensure the intended focus outline behavior is applied properly.

Comment on lines 45 to 50
<DialogClose
v-if="showCloseButton !== false"
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
>
<X class="w-4 h-4" />
<span class="sr-only">Close</span>
Copy link
Contributor

@coderabbitai coderabbitai bot Jul 16, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Undefined outline-hidden utility
See notes in Modal.vue – fix the class here as well.

🤖 Prompt for AI Agents
In unraid-ui/src/components/ui/dialog/DialogContent.vue around lines 45 to 50,
the class "focus:outline-hidden" is used but "outline-hidden" is not a defined
utility. Replace "focus:outline-hidden" with the correct utility class as noted
in Modal.vue, likely "focus:outline-none", to properly remove the outline on
focus.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is real read the docs: https://tailwindcss.com/docs/outline-style

Copy link
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

I need to verify the current Tailwind CSS documentation to confirm whether outline-hidden is a valid utility class.

@elibosley You're absolutely right, and I apologize for the confusion. Looking at the Tailwind CSS documentation, outline-hidden is indeed a valid utility class in Tailwind CSS. It sets outline-style: hidden which is different from outline-none (which sets outline: 2px solid transparent; outline-offset: 2px).

The change from focus:outline-none to focus:outline-hidden in your Tailwind v4 upgrade is correct and intentional. Thank you for the correction and the documentation link!


🌐 Web query:

Tailwind CSS v4 outline-hidden utility class documentation

💡 Result:

In Tailwind CSS v4, the new outline-hidden utility class replicates the behavior of outline-none from v3 and introduces clearer semantics and accessibility distinctions[7][1][5][10].

Use the outline-hidden utility to hide the default browser outline on focused elements, while still preserving the outline in forced colors mode.[7]

How outline-hidden Works

  • What it does:
    outline-hidden applies an invisible outline (outline: 2px solid transparent; outline-offset: 2px;), which ensures that an element still receives a focus outline in high contrast or forced colors mode—critical for accessibility.
  • CSS generated:
    .outline-hidden {
      outline: 2px solid transparent;
      outline-offset: 2px;
    }
  • This mimics the old behavior of outline-none from v3, but is now separated for clarity and accessibility impact[7][1].

Difference from outline-none in v4

  • outline-none behavior change in v4:
    Now strictly applies outline-style: none and removes the focus outline in all modes, which might lead to accessibility issues if you do not add a custom focus style[7][1][10].
  • Migration note:
    If upgrading from v3 and intending to preserve accessible outline hiding (invisible most of the time, visible in forced colors), replace outline-none usages with outline-hidden[1][5][10].

Accessibility

  • Recommended usage:
    When using outline-hidden, you should apply your own focus styles (such as a ring or border) to indicate focus for keyboard users, as this utility hides the browser's default unless forced colors are enabled[7][1]:
    <input class="focus:outline-hidden focus:ring focus:border-blue-500" />

Documentation Excerpt

Class Styles Description
outline-hidden outline: 2px solid transparent; outline-offset: 2px; Hides browser outline but preserves in forced colors/high-contrast mode[7]
outline-none outline-style: none; Removes browser outline entirely (not accessible recommendation in most cases)[7][1]

Reference

See the official [Tailwind CSS v4 documentation for outline-style][7] for more details on outline utilities.


Summary of migration:

  • Replace outline-none (v3) ➔ outline-hidden (v4) for accessible outline hiding.
  • Use outline-none (v4) only if you mean to remove all outlines (including in forced colors / high contrast mode), generally discouraged for accessibility[1][10][7].

"Use the outline-hidden utility to hide the default browser outline on focused elements, while still preserving the outline in forced colors mode. It is highly recommended to apply your own focus styling for accessibility when using this utility."[7]

Further reading:

  • [Tailwind CSS v4 Borders: outline-style documentation][7]
  • [Upgrade guide from v3 to v4][10]

Citations:


@elibosley You're absolutely right, and I apologize for the incorrect suggestion. Thank you for the correction!

After reviewing the Tailwind CSS v4 documentation, I can confirm that outline-hidden is indeed a valid and recommended utility class. In fact, it's the proper replacement for outline-none from v3:

  • outline-hidden in v4: Applies outline: 2px solid transparent; outline-offset: 2px; - hides the browser outline while preserving it in forced colors/high-contrast mode for accessibility
  • outline-none in v4: Now strictly applies outline-style: none and removes outlines entirely, which can create accessibility issues

Your change from focus:outline-none to focus:outline-hidden is correct and follows the recommended migration pattern for Tailwind CSS v4. This maintains better accessibility while achieving the desired visual effect.

The code in DialogContent.vue is correct as written. My original comment was in error.


✏️ Learnings added
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dialog/DialogContent.vue:45-50
Timestamp: 2025-07-17T14:10:14.583Z
Learning: The `outline-hidden` utility class is valid in Tailwind CSS and sets `outline-style: hidden`. This is different from `outline-none` which sets `outline: 2px solid transparent; outline-offset: 2px`. The change from `focus:outline-none` to `focus:outline-hidden` is part of the Tailwind CSS v4 upgrade.

Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dialog/DialogContent.vue:45-50
Timestamp: 2025-07-17T14:10:14.583Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that replaces the v3 behavior of `outline-none`. It applies `outline: 2px solid transparent; outline-offset: 2px;` which hides the browser outline while preserving it in forced colors/high-contrast mode for accessibility. The migration pattern from v3 to v4 is to replace `focus:outline-none` with `focus:outline-hidden` for better accessibility.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: mdatelle
PR: unraid/api#1183
File: web/components/Modal.vue:110-110
Timestamp: 2025-02-21T19:02:09.947Z
Learning: In Vue modal components using @headlessui/vue's TransitionChild, explicit width control (w-full) may be necessary on the TransitionChild component to maintain proper width during scale transitions, even when parent elements have width classes.

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.

Learnt from: elibosley
PR: unraid/api#1369
File: web/components/Activation/WelcomeModal.ce.vue:40-40
Timestamp: 2025-04-25T13:29:07.868Z
Learning: The `#confirmPassword` selector in the WelcomeModal.ce.vue component is intentionally looking for an element that exists in the Unraid OS login page (.login.php), not within the component itself. This is used as part of a font-size adjustment workaround to handle different CSS between login and authenticated pages.

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`.

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.

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.

Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:210-216
Timestamp: 2025-02-21T18:40:10.810Z
Learning: When updating theme-related CSS variables via `cssText`, preserve existing non-theme styles by filtering out only theme-related rules (those starting with '--') and combining them with the new theme styles.

Comment on lines 18 to 22
:class="
cn(
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent data-[state=open]:bg-accent',
props.class
)
Copy link
Contributor

@coderabbitai coderabbitai bot Jul 16, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

outline-hidden is not a Tailwind utility

Tailwind ships outline-none, outline, outline-0, etc. outline-hidden will be emitted verbatim and produce no CSS, so focus styles stay visible.

-'... text-sm outline-hidden focus:bg-accent ...'
+'... text-sm outline-none focus:bg-accent ...'

If you actually want outline: 0 only when focus-visible, combine outline-none focus:outline-none.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:class="
cn(
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent data-[state=open]:bg-accent',
props.class
)
:class="
cn(
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',
props.class
)
🤖 Prompt for AI Agents
In unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue around
lines 18 to 22, replace the invalid Tailwind class 'outline-hidden' with the
correct utility classes. Use 'outline-none focus:outline-none' to properly hide
the outline only on focus-visible states, ensuring the focus styles behave as
intended.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

Let me check the current Tailwind CSS documentation to verify the validity of the outline-hidden utility class.

@elibosley Thank you for the correction! You're absolutely right. After checking the Tailwind CSS documentation, outline-hidden is indeed a valid utility class in Tailwind CSS. I apologize for the incorrect assessment in my previous comment.

The outline-hidden utility sets outline-style: hidden, which is different from outline-none (which sets outline: 2px solid transparent; outline-offset: 2px). The usage in the code is correct and appropriate.

I'll retract my previous suggestion about this being an invalid utility class.


🌐 Web query:

Tailwind CSS outline-style documentation outline-hidden utility class

💡 Result:

In Tailwind CSS, the outline-style utility class allows you to control the appearance of an element's outline. The outline-hidden class is particularly useful for managing focus styles.

outline-hidden Utility Class:

The outline-hidden class sets the outline to a 2px solid transparent line with a 2px offset. This approach hides the default browser outline on focused elements while maintaining accessibility features, such as visibility in forced colors mode. It's highly recommended to apply your own focus styling for accessibility when using this utility. (tailwindcss.com)

Example Usage:

<input class="focus:outline-hidden focus:border-indigo-600" type="text" />

In this example, the input field will have a custom border color when focused, and the default outline will be hidden.

Important Considerations:

In Tailwind CSS v4, the outline-none utility was simplified to set outline-style: none;. To replicate the previous behavior of hiding the outline while preserving accessibility features, the outline-hidden utility was introduced. Therefore, if you need to hide the outline and maintain accessibility, use outline-hidden instead of outline-none. (github.com)

For more details, refer to the Tailwind CSS documentation on outline-style.

Citations:


🌐 Web query:

site:tailwindcss.com outline-hidden utility class Tailwind CSS v4

💡 Result:

In Tailwind CSS v4, the outline-none utility has been replaced with outline-hidden. This change aligns with the framework's simplification efforts and enhances accessibility. In previous versions, outline-none set outline: 2px solid transparent; and outline-offset: 2px;, which provided an invisible outline that remained visible in forced colors mode for accessibility purposes. In v4, outline-none now sets outline-style: none;, effectively removing the outline. To achieve the previous behavior, you should use the new outline-hidden utility, which sets outline: 2px solid transparent; and outline-offset: 2px;. (v3.tailwindcss.com)

Example:

<input class="focus:outline-hidden">

This change ensures that the invisible outline remains visible in forced colors mode, maintaining accessibility standards. For more details, refer to the Tailwind CSS v4.0 Beta documentation. (v3.tailwindcss.com)

Citations:


@elibosley Thank you for the correction! You're absolutely right, and I apologize for the incorrect assessment in my previous comment.

After checking the Tailwind CSS documentation, I can confirm that outline-hidden is indeed a valid utility class in Tailwind CSS v4. In fact, it's the recommended approach for hiding outlines while maintaining accessibility.

The key difference in Tailwind v4:

  • outline-none now sets outline-style: none (completely removes the outline)
  • outline-hidden sets outline: 2px solid transparent; outline-offset: 2px (hides the outline but keeps it visible in forced colors mode for accessibility)

The usage of outline-hidden in this code is correct and follows Tailwind v4 best practices for maintaining accessibility while hiding the default browser outline.

I'll retract my previous suggestion - the code is working as intended.


✏️ Learnings added
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue:18-22
Timestamp: 2025-07-17T14:10:23.380Z
Learning: `outline-hidden` is a valid Tailwind CSS utility class that sets `outline-style: hidden`. This is different from `outline-none` and is available in Tailwind CSS v4.

Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue:18-22
Timestamp: 2025-07-17T14:10:23.380Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that sets `outline: 2px solid transparent; outline-offset: 2px`. This replaces the previous behavior of `outline-none` from v3 and maintains accessibility by keeping the outline visible in forced colors mode. Use `outline-hidden` instead of `outline-none` when you need to hide the outline while preserving accessibility features.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
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.

Comment on lines +20 to 22
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background data-placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:truncate text-start',
props.class
)
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Attribute variant change likely breaks placeholder styling.

Similar to the stepper note, Tailwind resolves data-[placeholder] out-of-the-box; data-placeholder is not recognised unless explicitly configured.

- data-placeholder:text-muted-foreground
+ data-[placeholder]:text-muted-foreground

Please verify that the placeholder text is still muted after this change.


🏁 Script executed:

#!/bin/bash
# Check for Tailwind CSS configuration file at the repo root
echo "Tailwind config files:"
ls -1 tailwind.config.* || echo "  – none found at root"

# If a config exists, look for any custom variant handling for "data-placeholder"
echo
echo "Searching Tailwind config for custom data-placeholder variant:"
grep -R "dataPlaceholder" -n tailwind.config.* || echo "  – no custom dataPlaceholder variant found"

Length of output: 542


Fix data-placeholder variant syntax

Tailwind doesn’t recognize data-placeholder: by default—arbitrary variants require square brackets. Update the class so your placeholder remains muted:

• File: unraid-ui/src/components/ui/select/SelectTrigger.vue
• Lines: 20–22

- '... data-placeholder:text-muted-foreground ...',
+ '... data-[placeholder]:text-muted-foreground ...',

Please confirm that the placeholder text still renders in the muted color after this change.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background data-placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:truncate text-start',
props.class
)
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:truncate text-start',
props.class
)
🤖 Prompt for AI Agents
In unraid-ui/src/components/ui/select/SelectTrigger.vue around lines 20 to 22,
the Tailwind CSS class uses the variant syntax 'data-placeholder:' which is not
recognized by default. To fix this, wrap the variant in square brackets like
'[data-placeholder:]' to enable the arbitrary variant syntax. After updating,
verify that the placeholder text still renders with the muted color as intended.

@github-actions
Copy link
Contributor

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

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: 2

🧹 Nitpick comments (4)
web/app.vue (1)

2-2: Consider removing explicit onMounted import.

Based on the retrieved learnings, this Nuxt.js project has auto-imports enabled for Vue composables. The onMounted import may be unnecessary as it should be globally available.

-import { onMounted } from 'vue';
unraid-ui/src/styles/globals.css (3)

18-24: Duplicate border-color definitions – keep one.

border-color: hsl(var(--border)); is hard-coded on the universal selector inside @layer base, and later @apply border-border sets exactly the same property.
One of them is redundant and adds extra CSS bytes/specificity.

-  *,
-  ::after,
-  ::before,
-  ::backdrop,
-  ::file-selector-button {
-    border-color: hsl(var(--border));
-  }
+/* keep only @apply or the explicit rule above, not both */

Also applies to: 246-248


108-113: Inconsistent naming on spacing tokens.

--spacing--8px mixes a double-dash separator while the rest use single dashes (--spacing-8px).
Consistent tokens matter for DX and avoid typos when consuming the variables.


220-245: Dark-mode chart palette duplicates hard-coded HSL values.

All five chart colours are re-declared here rather than derived from light-mode variables (unlike the rest of the theme).
If brand colours ever change you’ll need to update two locations.
Recommend deriving via color-mix or just referencing the base token to stay DRY.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 602f7d7 and e259191.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (71)
  • .claude/settings.local.json (1 hunks)
  • CLAUDE.md (1 hunks)
  • plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/translations.php (1 hunks)
  • unraid-ui/.prettierrc.json (1 hunks)
  • unraid-ui/.storybook/main.ts (1 hunks)
  • unraid-ui/.storybook/preview.ts (1 hunks)
  • unraid-ui/README.md (1 hunks)
  • unraid-ui/components.json (0 hunks)
  • unraid-ui/package.json (6 hunks)
  • unraid-ui/src/components/brand/BrandButton.vue (3 hunks)
  • unraid-ui/src/components/brand/brand-button.variants.ts (2 hunks)
  • unraid-ui/src/components/common/badge/Badge.vue (2 hunks)
  • unraid-ui/src/components/common/badge/badge.variants.ts (1 hunks)
  • unraid-ui/src/components/common/sheet/SheetContent.vue (1 hunks)
  • unraid-ui/src/components/form/lightswitch/Lightswitch.vue (3 hunks)
  • unraid-ui/src/components/layout/PageContainer.vue (1 hunks)
  • unraid-ui/src/index.ts (0 hunks)
  • unraid-ui/src/styles/globals.css (1 hunks)
  • unraid-ui/src/theme/preset.ts (0 hunks)
  • unraid-ui/tailwind.config.ts (0 hunks)
  • unraid-ui/tsconfig.json (0 hunks)
  • unraid-ui/vite.config.ts (1 hunks)
  • web/.prettierrc.mjs (1 hunks)
  • web/__test__/components/KeyActions.test.ts (1 hunks)
  • web/__test__/components/Modal.test.ts (2 hunks)
  • web/__test__/components/UserProfile.test.ts (2 hunks)
  • web/app.vue (1 hunks)
  • web/assets/main.css (1 hunks)
  • web/components/Activation/ActivationModal.vue (2 hunks)
  • web/components/Activation/ActivationSteps.vue (1 hunks)
  • web/components/Activation/WelcomeModal.ce.vue (3 hunks)
  • web/components/ApiKey/ApiKeyCreate.vue (2 hunks)
  • web/components/Auth.ce.vue (2 hunks)
  • web/components/Brand/Avatar.vue (1 hunks)
  • web/components/DownloadApiLogs.ce.vue (3 hunks)
  • web/components/KeyActions.vue (1 hunks)
  • web/components/Modal.vue (6 hunks)
  • web/components/RClone/RCloneOverview.vue (1 hunks)
  • web/components/Registration.ce.vue (2 hunks)
  • web/components/Registration/Item.vue (1 hunks)
  • web/components/Registration/KeyLinkedStatus.vue (4 hunks)
  • web/components/Registration/ReplaceCheck.vue (1 hunks)
  • web/components/Registration/UpdateExpirationAction.vue (4 hunks)
  • web/components/UpdateOs.ce.vue (2 hunks)
  • web/components/UpdateOs/ChangelogModal.vue (3 hunks)
  • web/components/UpdateOs/CheckUpdateResponseModal.vue (7 hunks)
  • web/components/UpdateOs/Downgrade.vue (3 hunks)
  • web/components/UpdateOs/IgnoredRelease.vue (1 hunks)
  • web/components/UpdateOs/Status.vue (4 hunks)
  • web/components/UpdateOs/ThirdPartyDrivers.vue (1 hunks)
  • web/components/UpdateOs/Update.vue (6 hunks)
  • web/components/UpdateOs/UpdateIneligible.vue (2 hunks)
  • web/components/UserProfile.ce.vue (3 hunks)
  • web/components/UserProfile/Beta.vue (1 hunks)
  • web/components/UserProfile/CallbackFeedback.vue (7 hunks)
  • web/components/UserProfile/CallbackFeedbackStatus.vue (1 hunks)
  • web/components/UserProfile/DropdownConnectStatus.vue (1 hunks)
  • web/components/UserProfile/DropdownContent.vue (2 hunks)
  • web/components/UserProfile/DropdownError.vue (1 hunks)
  • web/components/UserProfile/DropdownItem.vue (1 hunks)
  • web/components/UserProfile/DropdownLaunchpad.vue (2 hunks)
  • web/components/UserProfile/DropdownTrigger.vue (1 hunks)
  • web/components/UserProfile/DropdownWrapper.vue (1 hunks)
  • web/components/UserProfile/Keyline.vue (1 hunks)
  • web/components/UserProfile/ServerState.vue (2 hunks)
  • web/components/UserProfile/ServerStateBuy.vue (1 hunks)
  • web/components/UserProfile/Trial.vue (1 hunks)
  • web/eslint.config.mjs (0 hunks)
  • web/package.json (3 hunks)
  • web/pages/index.vue (6 hunks)
  • web/tailwind.config.ts (0 hunks)
💤 Files with no reviewable changes (7)
  • unraid-ui/components.json
  • unraid-ui/src/index.ts
  • unraid-ui/tsconfig.json
  • web/eslint.config.mjs
  • unraid-ui/tailwind.config.ts
  • unraid-ui/src/theme/preset.ts
  • web/tailwind.config.ts
✅ Files skipped from review due to trivial changes (25)
  • CLAUDE.md
  • unraid-ui/.prettierrc.json
  • unraid-ui/.storybook/preview.ts
  • web/components/RClone/RCloneOverview.vue
  • web/components/UserProfile/DropdownWrapper.vue
  • web/components/UserProfile/Beta.vue
  • web/test/components/UserProfile.test.ts
  • web/components/UserProfile/CallbackFeedbackStatus.vue
  • web/components/Registration/KeyLinkedStatus.vue
  • web/pages/index.vue
  • web/components/UserProfile/DropdownError.vue
  • web/components/ApiKey/ApiKeyCreate.vue
  • unraid-ui/src/components/common/badge/badge.variants.ts
  • web/.prettierrc.mjs
  • web/components/UserProfile/Trial.vue
  • web/components/UserProfile/DropdownConnectStatus.vue
  • web/components/UpdateOs/IgnoredRelease.vue
  • .claude/settings.local.json
  • web/components/Registration/Item.vue
  • unraid-ui/src/components/form/lightswitch/Lightswitch.vue
  • web/components/Activation/ActivationModal.vue
  • web/components/UpdateOs/ChangelogModal.vue
  • web/components/UpdateOs/ThirdPartyDrivers.vue
  • web/components/KeyActions.vue
  • web/components/UserProfile/DropdownContent.vue
🚧 Files skipped from review as they are similar to previous changes (33)
  • unraid-ui/src/components/common/sheet/SheetContent.vue
  • web/components/UpdateOs.ce.vue
  • web/components/Activation/ActivationSteps.vue
  • unraid-ui/README.md
  • web/components/UserProfile/Keyline.vue
  • web/components/DownloadApiLogs.ce.vue
  • web/components/UserProfile/ServerState.vue
  • web/test/components/Modal.test.ts
  • web/components/Registration/UpdateExpirationAction.vue
  • web/components/Activation/WelcomeModal.ce.vue
  • web/components/Brand/Avatar.vue
  • web/package.json
  • unraid-ui/src/components/brand/BrandButton.vue
  • web/components/UserProfile/DropdownLaunchpad.vue
  • unraid-ui/.storybook/main.ts
  • unraid-ui/vite.config.ts
  • web/components/UpdateOs/UpdateIneligible.vue
  • web/components/UserProfile/DropdownItem.vue
  • web/components/UserProfile/ServerStateBuy.vue
  • web/components/UserProfile/CallbackFeedback.vue
  • web/components/UpdateOs/CheckUpdateResponseModal.vue
  • web/components/UserProfile.ce.vue
  • web/assets/main.css
  • web/components/Auth.ce.vue
  • unraid-ui/package.json
  • web/components/Modal.vue
  • web/components/UpdateOs/Update.vue
  • web/components/UserProfile/DropdownTrigger.vue
  • web/components/UpdateOs/Status.vue
  • unraid-ui/src/components/common/badge/Badge.vue
  • web/components/Registration.ce.vue
  • web/components/Registration/ReplaceCheck.vue
  • web/components/UpdateOs/Downgrade.vue
🧰 Additional context used
📓 Path-based instructions (3)
web/__test__/**/*

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
**/*.{ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
**/*.test.ts

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • .cursor/rules/web-testing-rules.mdc
🧠 Learnings (7)
📓 Common learnings
Learnt from: elibosley
PR: unraid/api#972
File: web/components/ColorSwitcher.ce.vue:1-2
Timestamp: 2024-12-17T13:55:42.068Z
Learning: In this Nuxt.js project, components used in templates are automatically imported by Nuxt, so explicit import statements for components are unnecessary.
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-24
Timestamp: 2024-12-09T15:47:29.325Z
Learning: In our Nuxt setup using Vue.js, components defined within the codebase are autoloaded and do not require explicit import statements in the script section. For example, components like `TabsList` and `TabsTrigger` used in `web/components/Notifications/TabList.vue` are automatically available without imports.
unraid-ui/src/components/layout/PageContainer.vue (8)
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.
Learnt from: elibosley
PR: unraid/api#1101
File: api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch:6-20
Timestamp: 2025-01-31T22:01:41.842Z
Learning: The default-page-layout.patch removes the old jGrowl notification system and is complemented by the unraid-toaster component implementation. The new system is added through the DefaultPageLayout modification which inserts the toaster component with proper position configuration based on user preferences.
Learnt from: mdatelle
PR: unraid/api#1106
File: unraid-ui/src/components/index.ts:2-2
Timestamp: 2025-02-04T17:21:39.710Z
Learning: The unraid-ui package is undergoing a major refactoring process, and breaking changes are expected during this transition period.
Learnt from: elibosley
PR: unraid/api#1101
File: api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch:6-20
Timestamp: 2025-01-31T22:01:41.842Z
Learning: The default-page-layout.patch is used to remove the old jGrowl notification system from Unraid pages, as notifications are handled by a new system implemented on a different page.
Learnt from: elibosley
PR: unraid/api#1369
File: web/components/Activation/WelcomeModal.ce.vue:40-40
Timestamp: 2025-04-25T13:29:07.868Z
Learning: The `#confirmPassword` selector in the WelcomeModal.ce.vue component is intentionally looking for an element that exists in the Unraid OS login page (.login.php), not within the component itself. This is used as part of a font-size adjustment workaround to handle different CSS between login and authenticated pages.
Learnt from: mdatelle
PR: unraid/api#1183
File: web/components/Modal.vue:110-110
Timestamp: 2025-02-21T19:02:09.947Z
Learning: In Vue modal components using @headlessui/vue's TransitionChild, explicit width control (w-full) may be necessary on the TransitionChild component to maintain proper width during scale transitions, even when parent elements have width classes.
Learnt from: elibosley
PR: unraid/api#1101
File: api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch:30-54
Timestamp: 2025-01-31T22:01:02.725Z
Learning: The removal of jGrowl notifications from DefaultPageLayout.php is intentional as notifications are now handled on a separate page as part of the architectural design to override existing Unraid pages.
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.
plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/translations.php (2)
Learnt from: elibosley
PR: unraid/api#1381
File: plugin/source/dynamix.unraid.net/usr/local/share/dynamix.unraid.net/install/scripts/verify_install.sh:11-16
Timestamp: 2025-05-08T19:31:52.417Z
Learning: The `dynamix.my.servers` namespace is still valid and should not be changed to `dynamix.unraid.net` in file paths, as both namespaces coexist in the codebase.
Learnt from: zackspear
PR: unraid/api#1257
File: plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix/include/ReplaceKey.php:184-184
Timestamp: 2025-03-20T01:58:31.676Z
Learning: Error messages from the key server or KeyInstaller do not contain PII or server details, so they can be safely used in notifications.
web/app.vue (12)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Use `mount` from Vue Test Utils for component testing
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/__test__/**/* : Use mount from Vue Test Utils for component testing in web/__test__
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Ensure Vue reactivity imports are added to original store files as they may be missing because Nuxt auto import was turned on
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Avoid relying on Nuxt's auto-imports in test environment
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-4
Timestamp: 2024-12-09T15:45:46.492Z
Learning: In our Nuxt.js setup for the `web` project, it's not necessary to explicitly import `computed` from `vue` in Vue components, as it's globally available.
Learnt from: elibosley
PR: unraid/api#972
File: web/components/ColorSwitcher.ce.vue:1-2
Timestamp: 2024-12-17T13:55:42.068Z
Learning: In this Nuxt.js project, components used in templates are automatically imported by Nuxt, so explicit import statements for components are unnecessary.
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-24
Timestamp: 2024-12-09T15:47:29.325Z
Learning: In our Nuxt setup using Vue.js, components defined within the codebase are autoloaded and do not require explicit import statements in the script section. For example, components like `TabsList` and `TabsTrigger` used in `web/components/Notifications/TabList.vue` are automatically available without imports.
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`.
Learnt from: pujitm
PR: unraid/api#1417
File: web/components/ConnectSettings/ConnectSettings.ce.vue:11-18
Timestamp: 2025-06-13T17:14:21.739Z
Learning: The project’s build tooling auto-imports common Vue/Pinia helpers such as `storeToRefs`, so explicit import statements for them are not required.
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.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Don't rely on Nuxt auto-imports in tests
web/__test__/components/KeyActions.test.ts (16)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Test component interactions (clicks, inputs, etc.) in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Check for expected prop handling and event emissions in component tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Verify that the expected elements are rendered in component tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify actions are called with correct parameters in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Test action side effects and state changes in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify state changes after actions in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify actions are called with the right parameters in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify state changes by updating the store in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Override specific action implementations when needed in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Test action side effects if not stubbed in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Assert on rendered text content with `wrapper.text()`
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Verify element existence with `expect(element.exists()).toBe(true)`
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Check component state through rendered output in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Assert on element attributes with `element.attributes()`
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Use semantic queries like `find('button')` or `find('[data-test="id"]')` but prefer not to use data test IDs
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Test emitted events with `wrapper.emitted()` in component tests
unraid-ui/src/components/brand/brand-button.variants.ts (2)
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.
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:0-0
Timestamp: 2025-02-24T14:51:21.328Z
Learning: In the Unraid API project's theme system, exact TypeScript type definitions are preferred over index signatures for theme variables to ensure better type safety.
unraid-ui/src/styles/globals.css (9)
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:210-216
Timestamp: 2025-02-21T18:40:10.810Z
Learning: When updating theme-related CSS variables via `cssText`, preserve existing non-theme styles by filtering out only theme-related rules (those starting with '--') and combining them with the new theme styles.
Learnt from: elibosley
PR: unraid/api#972
File: web/store/theme.ts:46-49
Timestamp: 2024-12-17T14:59:32.458Z
Learning: In the `web/store/theme.ts` file of the Unraid web application, the header is intentionally designed to have a light background with dark text in dark mode, and a dark background with light text in light mode.
Learnt from: mdatelle
PR: unraid/api#1106
File: unraid-ui/src/components/index.ts:2-2
Timestamp: 2025-02-04T17:21:39.710Z
Learning: The unraid-ui package is undergoing a major refactoring process, and breaking changes are expected during this transition period.
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:0-0
Timestamp: 2025-02-24T14:51:21.328Z
Learning: In the Unraid API project's theme system, exact TypeScript type definitions are preferred over index signatures for theme variables to ensure better type safety.
Learnt from: elibosley
PR: unraid/api#1155
File: web/store/theme.ts:49-50
Timestamp: 2025-02-20T15:52:56.733Z
Learning: CSS variable names in the theme store should be concise and follow established patterns. For example, prefer '--gradient-start' over '--color-customgradient-start' to maintain consistency with other variable names.
Learnt from: elibosley
PR: unraid/api#1211
File: unraid-ui/src/components/form/number/NumberFieldInput.vue:1-21
Timestamp: 2025-03-13T16:17:21.897Z
Learning: The unraid-ui is a UI library being published externally, where wrapping third-party components (like those from reka-ui) is an intentional design choice to maintain a consistent interface, standardize styling, and control the exposed API.
Learnt from: elibosley
PR: unraid/api#1101
File: api/src/unraid-api/unraid-file-modifier/modifications/__test__/snapshots/DefaultPageLayout.php.modified.snapshot.php:203-207
Timestamp: 2025-02-03T17:21:26.738Z
Learning: The project uses patches to override existing Unraid pages rather than modifying them directly.
Learnt from: mdatelle
PR: unraid/api#1106
File: web/components/UserProfile.ce.vue:168-170
Timestamp: 2025-02-07T19:25:02.936Z
Learning: Files with .ce.vue extension are web components that require self-contained styles. Global style imports within these components are valid and necessary for proper encapsulation.
🧬 Code Graph Analysis (1)
plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/translations.php (1)
plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.plugin.manager/include/UnraidCheck.php (1)
  • _ (108-108)
🪛 Biome (1.9.4)
unraid-ui/src/styles/globals.css

[error] 165-165: Unexpected value or character.

Expected one of:

(parse)


[error] 178-178: Unexpected value or character.

Expected one of:

(parse)


[error] 178-178: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 178-178: expected , but instead found (

Remove (

(parse)


[error] 178-178: expected , but instead found --radix-accordion-content-height

Remove --radix-accordion-content-height

(parse)


[error] 178-178: expected , but instead found )

Remove )

(parse)


[error] 178-178: expected , but instead found ;

Remove ;

(parse)


[error] 179-179: Unexpected value or character.

Expected one of:

(parse)


[error] 179-179: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 179-179: Unexpected value or character.

Expected one of:

(parse)


[error] 179-179: expected , but instead found ;

Remove ;

(parse)


[error] 180-180: Unexpected value or character.

Expected one of:

(parse)


[error] 180-180: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 180-180: expected , but instead found (

Remove (

(parse)


[error] 180-180: expected , but instead found --radix-collapsible-content-height

Remove --radix-collapsible-content-height

(parse)


[error] 180-180: expected , but instead found )

Remove )

(parse)


[error] 180-180: expected , but instead found ;

Remove ;

(parse)


[error] 181-181: Unexpected value or character.

Expected one of:

(parse)


[error] 181-181: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 181-181: Unexpected value or character.

Expected one of:

(parse)


[error] 181-181: expected , but instead found ;

Remove ;

(parse)


[error] 182-182: Unexpected value or character.

Expected one of:

(parse)


[error] 182-182: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 182-182: expected , but instead found (

Remove (

(parse)


[error] 182-182: expected , but instead found ;

Remove ;

(parse)


[error] 183-183: Unexpected value or character.

Expected one of:

(parse)


[error] 183-183: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 183-183: expected , but instead found (

Remove (

(parse)


[error] 183-183: expected , but instead found ;

Remove ;

(parse)


[error] 184-184: Unexpected value or character.

Expected one of:

(parse)


[error] 184-184: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 184-184: expected , but instead found (

Remove (

(parse)


[error] 184-184: expected , but instead found ;

Remove ;

(parse)


[error] 185-185: Unexpected value or character.

Expected one of:

(parse)


[error] 185-185: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 185-185: expected , but instead found (

Remove (

(parse)


[error] 185-185: expected , but instead found ;

Remove ;

(parse)


[error] 188-188: expected , but instead found (

Remove (

(parse)


[error] 188-188: expected , but instead found ;

Remove ;

(parse)


[error] 189-189: expected , but instead found (

Remove (

(parse)


[error] 189-189: expected , but instead found ;

Remove ;

(parse)


[error] 190-190: expected , but instead found (

Remove (

(parse)


[error] 190-190: expected , but instead found ;

Remove ;

(parse)


[error] 191-191: expected , but instead found (

Remove (

(parse)


[error] 191-191: expected , but instead found ;

Remove ;

(parse)


[error] 192-192: expected , but instead found (

Remove (

(parse)


[error] 192-192: expected , but instead found ;

Remove ;

(parse)


[error] 193-193: expected , but instead found (

Remove (

(parse)


[error] 193-193: expected , but instead found ;

Remove ;

(parse)


[error] 194-194: expected , but instead found (

Remove (

(parse)


[error] 194-194: expected , but instead found ;

Remove ;

(parse)


[error] 195-195: expected , but instead found (

Remove (

(parse)


[error] 195-195: expected , but instead found ;

Remove ;

(parse)


[error] 196-196: expected , but instead found (

Remove (

(parse)


[error] 196-196: expected , but instead found ;

Remove ;

(parse)


[error] 197-197: expected , but instead found (

Remove (

(parse)


[error] 197-197: expected , but instead found ;

Remove ;

(parse)


[error] 198-198: expected , but instead found (

Remove (

(parse)


[error] 198-198: expected , but instead found ;

Remove ;

(parse)


[error] 199-199: expected , but instead found (

Remove (

(parse)


[error] 199-199: expected , but instead found ;

Remove ;

(parse)


[error] 200-200: expected , but instead found (

Remove (

(parse)


[error] 200-200: expected , but instead found ;

Remove ;

(parse)


[error] 201-201: expected , but instead found (

Remove (

(parse)


[error] 201-201: expected , but instead found ;

Remove ;

(parse)


[error] 202-202: expected , but instead found (

Remove (

(parse)


[error] 202-202: expected , but instead found ;

Remove ;

(parse)


[error] 203-203: expected , but instead found (

Remove (

(parse)


[error] 203-203: expected , but instead found ;

Remove ;

(parse)


[error] 204-204: expected , but instead found (

Remove (

(parse)


[error] 204-204: expected , but instead found ;

Remove ;

(parse)


[error] 205-205: expected , but instead found (

Remove (

(parse)


[error] 205-205: expected , but instead found ;

Remove ;

(parse)


[error] 206-206: expected , but instead found (

Remove (

(parse)


[error] 206-206: expected , but instead found ;

Remove ;

(parse)


[error] 209-209: expected , but instead found (

Remove (

(parse)


[error] 209-209: expected , but instead found ;

Remove ;

(parse)


[error] 210-210: expected , but instead found (

Remove (

(parse)


[error] 210-210: expected , but instead found ;

Remove ;

(parse)


[error] 211-211: expected , but instead found (

Remove (

(parse)


[error] 211-211: expected , but instead found ;

Remove ;

(parse)


[error] 212-212: expected , but instead found (

Remove (

(parse)


[error] 212-212: expected , but instead found ;

Remove ;

(parse)


[error] 213-213: expected , but instead found (

Remove (

(parse)


[error] 213-213: expected , but instead found ;

Remove ;

(parse)


[error] 216-216: Unexpected value or character.

Expected one of:

(parse)


[error] 216-216: expected , but instead found rem

Remove rem

(parse)


[error] 216-216: expected , but instead found ;

Remove ;

(parse)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build API
  • GitHub Check: Test API
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (8)
plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/translations.php (1)

78-78: LGTM! CSS class updated for Tailwind v4 compatibility and syntax error fixed.

The change correctly updates the padding class from pl-16px to pl-4 (standard Tailwind utility) and removes the stray > character, fixing the HTML syntax error in the translation string.

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

7-7: LGTM! Proper Tailwind v4 arbitrary value syntax.

The change from 'max-w-1024px' to 'max-w-[1024px]' correctly migrates to Tailwind's arbitrary value syntax while maintaining the same 1024px max-width behavior.


13-13: LGTM! Proper migration to Tailwind spacing scale.

The class changes correctly replace pixel-based utilities with Tailwind's spacing scale (gap-y-6 = 24px, px-4 = 16px) while maintaining equivalent visual spacing. This aligns with the Tailwind v4 migration objectives.

web/__test__/components/KeyActions.test.ts (1)

167-167: LGTM! Test updated for Tailwind v4 syntax.

The test correctly expects the new bracketed arbitrary value syntax sm:max-w-[300px] instead of the old sm:max-w-300px format, aligning with Tailwind v4 conventions.

unraid-ui/src/components/brand/brand-button.variants.ts (2)

27-32: LGTM! Modernized to standard Tailwind text utilities.

The size variants have been updated from pixel-based arbitrary values to standard Tailwind text size utilities (text-xs, text-sm, etc.) with consistent gap spacing. This improves maintainability and aligns with Tailwind's design system.


44-44: LGTM! Consistent spacing scale implementation.

The compound variants now use Tailwind's standard spacing scale (p-2, p-3, p-4) instead of arbitrary pixel values. The progression from smaller to larger padding values follows a logical pattern that aligns with the corresponding text sizes.

Also applies to: 49-49, 54-54, 59-59, 64-64, 69-69

web/app.vue (1)

4-4: LGTM!

The import of devConfig from the local helper is necessary and correctly implemented.

unraid-ui/src/styles/globals.css (1)

41-43: Unused custom property --default-border-color.

Nothing in this file references var(--default-border-color). Dead code increases bundle size and cognitive load.

@github-actions
Copy link
Contributor

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

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: 2

♻️ Duplicate comments (1)
unraid-ui/src/styles/globals.css (1)

177-185: Keyframe blocks inside variables break tooling
This is the same issue flagged in a previous review – most parsers choke on full 0% { … } 100% { … } blocks embedded in a custom property. Define real @keyframes once and reference them via variables instead.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e259191 and 04d69f7.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (27)
  • .claude/settings.local.json (1 hunks)
  • CLAUDE.md (1 hunks)
  • unraid-ui/package.json (7 hunks)
  • unraid-ui/src/styles/globals.css (1 hunks)
  • web/codegen.ts (1 hunks)
  • web/components/Activation/ActivationPartnerLogoImg.vue (1 hunks)
  • web/components/Activation/graphql/activationCode.query.ts (1 hunks)
  • web/components/ApiKey/actionVariant.ts (1 hunks)
  • web/components/ConnectSettings/ConnectSettings.ce.vue (2 hunks)
  • web/components/HeaderOsVersion.ce.vue (3 hunks)
  • web/components/Logs/SingleLogViewer.vue (3 hunks)
  • web/components/Logs/log.subscription.ts (1 hunks)
  • web/components/Notifications/Sidebar.vue (2 hunks)
  • web/components/RClone/RemoteItem.vue (2 hunks)
  • web/components/UpdateOs/RawChangelogRenderer.vue (1 hunks)
  • web/components/Wrapper/web-component-plugins.ts (1 hunks)
  • web/composables/gql/index.ts (1 hunks)
  • web/helpers/create-apollo-client.ts (1 hunks)
  • web/helpers/functions.ts (1 hunks)
  • web/helpers/urls.ts (1 hunks)
  • web/package.json (3 hunks)
  • web/pages/login.vue (2 hunks)
  • web/pages/webComponents.vue (1 hunks)
  • web/plugins/apollo.ts (1 hunks)
  • web/store/globalPinia.ts (1 hunks)
  • web/tailwind-shadcn.config.ts (0 hunks)
  • web/types/server.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • web/tailwind-shadcn.config.ts
✅ Files skipped from review due to trivial changes (17)
  • web/components/Wrapper/web-component-plugins.ts
  • web/codegen.ts
  • web/helpers/create-apollo-client.ts
  • web/components/Activation/graphql/activationCode.query.ts
  • web/composables/gql/index.ts
  • web/components/Activation/ActivationPartnerLogoImg.vue
  • web/store/globalPinia.ts
  • web/plugins/apollo.ts
  • web/components/Logs/log.subscription.ts
  • web/helpers/urls.ts
  • web/components/ApiKey/actionVariant.ts
  • web/pages/webComponents.vue
  • web/helpers/functions.ts
  • web/types/server.ts
  • web/components/Notifications/Sidebar.vue
  • web/components/UpdateOs/RawChangelogRenderer.vue
  • web/components/HeaderOsVersion.ce.vue
🚧 Files skipped from review as they are similar to previous changes (8)
  • web/components/RClone/RemoteItem.vue
  • CLAUDE.md
  • web/pages/login.vue
  • web/components/Logs/SingleLogViewer.vue
  • web/components/ConnectSettings/ConnectSettings.ce.vue
  • web/package.json
  • .claude/settings.local.json
  • unraid-ui/package.json
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: elibosley
PR: unraid/api#972
File: web/components/ColorSwitcher.ce.vue:1-2
Timestamp: 2024-12-17T13:55:42.068Z
Learning: In this Nuxt.js project, components used in templates are automatically imported by Nuxt, so explicit import statements for components are unnecessary.
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-24
Timestamp: 2024-12-09T15:47:29.325Z
Learning: In our Nuxt setup using Vue.js, components defined within the codebase are autoloaded and do not require explicit import statements in the script section. For example, components like `TabsList` and `TabsTrigger` used in `web/components/Notifications/TabList.vue` are automatically available without imports.
unraid-ui/src/styles/globals.css (9)
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:210-216
Timestamp: 2025-02-21T18:40:10.810Z
Learning: When updating theme-related CSS variables via `cssText`, preserve existing non-theme styles by filtering out only theme-related rules (those starting with '--') and combining them with the new theme styles.
Learnt from: mdatelle
PR: unraid/api#1106
File: unraid-ui/src/components/index.ts:2-2
Timestamp: 2025-02-04T17:21:39.710Z
Learning: The unraid-ui package is undergoing a major refactoring process, and breaking changes are expected during this transition period.
Learnt from: elibosley
PR: unraid/api#972
File: web/store/theme.ts:46-49
Timestamp: 2024-12-17T14:59:32.458Z
Learning: In the `web/store/theme.ts` file of the Unraid web application, the header is intentionally designed to have a light background with dark text in dark mode, and a dark background with light text in light mode.
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:0-0
Timestamp: 2025-02-24T14:51:21.328Z
Learning: In the Unraid API project's theme system, exact TypeScript type definitions are preferred over index signatures for theme variables to ensure better type safety.
Learnt from: elibosley
PR: unraid/api#1211
File: unraid-ui/src/components/form/number/NumberFieldInput.vue:1-21
Timestamp: 2025-03-13T16:17:21.897Z
Learning: The unraid-ui is a UI library being published externally, where wrapping third-party components (like those from reka-ui) is an intentional design choice to maintain a consistent interface, standardize styling, and control the exposed API.
Learnt from: elibosley
PR: unraid/api#1155
File: web/store/theme.ts:49-50
Timestamp: 2025-02-20T15:52:56.733Z
Learning: CSS variable names in the theme store should be concise and follow established patterns. For example, prefer '--gradient-start' over '--color-customgradient-start' to maintain consistency with other variable names.
Learnt from: elibosley
PR: unraid/api#1425
File: api/dev/configs/connect.json:2-3
Timestamp: 2025-06-20T21:05:24.582Z
Learning: When reviewing configuration files in refactoring PRs, avoid suggesting field name changes that could break compatibility with existing code that references those fields, even if the naming doesn't follow ideal conventions.
Learnt from: elibosley
PR: unraid/api#1155
File: web/store/theme.ts:161-172
Timestamp: 2025-02-20T15:52:58.297Z
Learning: The banner gradient implementation in web/store/theme.ts doesn't require explicit error handling for hexToRgba as CSS gracefully handles invalid values by ignoring them.
🪛 Biome (1.9.4)
unraid-ui/src/styles/globals.css

[error] 165-165: Unexpected value or character.

Expected one of:

(parse)


[error] 178-178: Unexpected value or character.

Expected one of:

(parse)


[error] 178-178: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 178-178: expected , but instead found (

Remove (

(parse)


[error] 178-178: expected , but instead found --radix-accordion-content-height

Remove --radix-accordion-content-height

(parse)


[error] 178-178: expected , but instead found )

Remove )

(parse)


[error] 178-178: expected , but instead found ;

Remove ;

(parse)


[error] 179-179: Unexpected value or character.

Expected one of:

(parse)


[error] 179-179: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 179-179: Unexpected value or character.

Expected one of:

(parse)


[error] 179-179: expected , but instead found ;

Remove ;

(parse)


[error] 180-180: Unexpected value or character.

Expected one of:

(parse)


[error] 180-180: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 180-180: expected , but instead found (

Remove (

(parse)


[error] 180-180: expected , but instead found --radix-collapsible-content-height

Remove --radix-collapsible-content-height

(parse)


[error] 180-180: expected , but instead found )

Remove )

(parse)


[error] 180-180: expected , but instead found ;

Remove ;

(parse)


[error] 181-181: Unexpected value or character.

Expected one of:

(parse)


[error] 181-181: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 181-181: Unexpected value or character.

Expected one of:

(parse)


[error] 181-181: expected , but instead found ;

Remove ;

(parse)


[error] 182-182: Unexpected value or character.

Expected one of:

(parse)


[error] 182-182: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 182-182: expected , but instead found (

Remove (

(parse)


[error] 182-182: expected , but instead found ;

Remove ;

(parse)


[error] 183-183: Unexpected value or character.

Expected one of:

(parse)


[error] 183-183: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 183-183: expected , but instead found (

Remove (

(parse)


[error] 183-183: expected , but instead found ;

Remove ;

(parse)


[error] 184-184: Unexpected value or character.

Expected one of:

(parse)


[error] 184-184: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 184-184: expected , but instead found (

Remove (

(parse)


[error] 184-184: expected , but instead found ;

Remove ;

(parse)


[error] 185-185: Unexpected value or character.

Expected one of:

(parse)


[error] 185-185: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 185-185: expected , but instead found (

Remove (

(parse)


[error] 185-185: expected , but instead found ;

Remove ;

(parse)


[error] 188-188: expected , but instead found (

Remove (

(parse)


[error] 188-188: expected , but instead found ;

Remove ;

(parse)


[error] 189-189: expected , but instead found (

Remove (

(parse)


[error] 189-189: expected , but instead found ;

Remove ;

(parse)


[error] 190-190: expected , but instead found (

Remove (

(parse)


[error] 190-190: expected , but instead found ;

Remove ;

(parse)


[error] 191-191: expected , but instead found (

Remove (

(parse)


[error] 191-191: expected , but instead found ;

Remove ;

(parse)


[error] 192-192: expected , but instead found (

Remove (

(parse)


[error] 192-192: expected , but instead found ;

Remove ;

(parse)


[error] 193-193: expected , but instead found (

Remove (

(parse)


[error] 193-193: expected , but instead found ;

Remove ;

(parse)


[error] 194-194: expected , but instead found (

Remove (

(parse)


[error] 194-194: expected , but instead found ;

Remove ;

(parse)


[error] 195-195: expected , but instead found (

Remove (

(parse)


[error] 195-195: expected , but instead found ;

Remove ;

(parse)


[error] 196-196: expected , but instead found (

Remove (

(parse)


[error] 196-196: expected , but instead found ;

Remove ;

(parse)


[error] 197-197: expected , but instead found (

Remove (

(parse)


[error] 197-197: expected , but instead found ;

Remove ;

(parse)


[error] 198-198: expected , but instead found (

Remove (

(parse)


[error] 198-198: expected , but instead found ;

Remove ;

(parse)


[error] 199-199: expected , but instead found (

Remove (

(parse)


[error] 199-199: expected , but instead found ;

Remove ;

(parse)


[error] 200-200: expected , but instead found (

Remove (

(parse)


[error] 200-200: expected , but instead found ;

Remove ;

(parse)


[error] 201-201: expected , but instead found (

Remove (

(parse)


[error] 201-201: expected , but instead found ;

Remove ;

(parse)


[error] 202-202: expected , but instead found (

Remove (

(parse)


[error] 202-202: expected , but instead found ;

Remove ;

(parse)


[error] 203-203: expected , but instead found (

Remove (

(parse)


[error] 203-203: expected , but instead found ;

Remove ;

(parse)


[error] 204-204: expected , but instead found (

Remove (

(parse)


[error] 204-204: expected , but instead found ;

Remove ;

(parse)


[error] 205-205: expected , but instead found (

Remove (

(parse)


[error] 205-205: expected , but instead found ;

Remove ;

(parse)


[error] 206-206: expected , but instead found (

Remove (

(parse)


[error] 206-206: expected , but instead found ;

Remove ;

(parse)


[error] 209-209: expected , but instead found (

Remove (

(parse)


[error] 209-209: expected , but instead found ;

Remove ;

(parse)


[error] 210-210: expected , but instead found (

Remove (

(parse)


[error] 210-210: expected , but instead found ;

Remove ;

(parse)


[error] 211-211: expected , but instead found (

Remove (

(parse)


[error] 211-211: expected , but instead found ;

Remove ;

(parse)


[error] 212-212: expected , but instead found (

Remove (

(parse)


[error] 212-212: expected , but instead found ;

Remove ;

(parse)


[error] 213-213: expected , but instead found (

Remove (

(parse)


[error] 213-213: expected , but instead found ;

Remove ;

(parse)


[error] 216-216: Unexpected value or character.

Expected one of:

(parse)


[error] 216-216: expected , but instead found rem

Remove rem

(parse)


[error] 216-216: expected , but instead found ;

Remove ;

(parse)


[error] 219-219: Unexpected value or character.

Expected one of:

(parse)


[error] 219-219: expected , but instead found rem

Remove rem

(parse)


[error] 219-219: expected , but instead found ;

Remove ;

(parse)


[error] 220-220: Unexpected value or character.

Expected one of:

(parse)


[error] 220-220: expected , but instead found rem

Remove rem

(parse)


[error] 220-220: expected , but instead found ;

Remove ;

(parse)


[error] 221-221: Unexpected value or character.

Expected one of:

(parse)


[error] 221-221: expected , but instead found rem

Remove rem

(parse)


[error] 221-221: expected , but instead found ;

Remove ;

(parse)


[error] 222-222: Unexpected value or character.

Expected one of:

(parse)


[error] 222-222: expected , but instead found rem

Remove rem

(parse)


[error] 222-222: expected , but instead found ;

Remove ;

(parse)


[error] 223-223: Unexpected value or character.

Expected one of:

(parse)


[error] 223-223: expected , but instead found rem

Remove rem

(parse)


[error] 223-223: expected , but instead found ;

Remove ;

(parse)


[error] 224-224: Unexpected value or character.

Expected one of:

(parse)


[error] 224-224: expected , but instead found rem

Remove rem

(parse)


[error] 224-224: expected , but instead found ;

Remove ;

(parse)


[error] 225-225: Unexpected value or character.

Expected one of:

(parse)


[error] 225-225: expected , but instead found rem

Remove rem

(parse)


[error] 225-225: expected , but instead found ;

Remove ;

(parse)


[error] 226-226: Unexpected value or character.

Expected one of:

(parse)


[error] 226-226: expected , but instead found rem

Remove rem

(parse)


[error] 226-226: expected , but instead found ;

Remove ;

(parse)


[error] 227-227: Unexpected value or character.

Expected one of:

(parse)


[error] 227-227: expected , but instead found rem

Remove rem

(parse)


[error] 227-227: expected , but instead found ;

Remove ;

(parse)


[error] 228-228: Unexpected value or character.

Expected one of:

(parse)


[error] 228-228: expected , but instead found rem

Remove rem

(parse)


[error] 228-228: expected , but instead found ;

Remove ;

(parse)


[error] 229-229: Unexpected value or character.

Expected one of:

(parse)


[error] 229-229: expected , but instead found rem

Remove rem

(parse)


[error] 229-229: expected , but instead found ;

Remove ;

(parse)


[error] 230-230: Unexpected value or character.

Expected one of:

(parse)


[error] 230-230: expected , but instead found rem

Remove rem

(parse)


[error] 230-230: expected , but instead found ;

Remove ;

(parse)


[error] 231-231: Unexpected value or character.

Expected one of:

(parse)


[error] 231-231: expected , but instead found rem

Remove rem

(parse)


[error] 231-231: expected , but instead found ;

Remove ;

(parse)


[error] 232-232: Unexpected value or character.

Expected one of:

(parse)


[error] 232-232: expected , but instead found rem

Remove rem

(parse)


[error] 232-232: expected , but instead found ;

Remove ;

(parse)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Build API
  • GitHub Check: Test API
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Deploy Storybook
🔇 Additional comments (1)
unraid-ui/src/styles/globals.css (1)

27-32: Non-standard @theme at-rule

@theme is not a standard CSS at-rule. Unless you have a PostCSS plugin that explicitly strips/handles it, downstream tooling (Storybook, IDEs, browser DevTools source maps) will fail to parse this file.

Confirm that the new Vite/Tailwind pipeline processes @theme; if not, migrate these variables into a normal :root { … } block.

@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

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

@github-actions
Copy link
Contributor

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

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

♻️ Duplicate comments (2)
unraid-ui/src/styles/globals.css (2)

21-24: Global --tw-border-style override still risky

Same concern as last round: forcing --tw-border-style: solid on all elements removes Tailwind’s ability to switch the variable (e.g. border-dashed, divide‐* utilities) and may break third-party components. Scope the rule or drop it entirely.


175-183: Keyframe blocks stored in variables break parsers

Storing full 0%{} / 100%{} blocks inside custom properties still trips Biome and other tooling. Move them to real @keyframes rules and reference the animation name via a variable instead (see prior comment).

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b09d8d6 and 8d83f7c.

📒 Files selected for processing (4)
  • unraid-ui/src/styles/globals.css (1 hunks)
  • web/assets/main.css (1 hunks)
  • web/components/Logs/SingleLogViewer.vue (3 hunks)
  • web/components/UserProfile.ce.vue (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • web/components/Logs/SingleLogViewer.vue
  • web/components/UserProfile.ce.vue
  • web/assets/main.css
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/UserProfile/DropdownTrigger.vue:0-0
Timestamp: 2025-07-17T14:09:37.203Z
Learning: Tailwind CSS v4 changed gradient utility classes from bg-gradient-to-r to bg-linear-to-r. The new syntax uses bg-linear-to-r instead of the v3 syntax bg-gradient-to-r for linear gradients.
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/UserProfile/DropdownTrigger.vue:0-0
Timestamp: 2025-07-17T14:09:37.203Z
Learning: In Tailwind CSS v4, gradient utility classes use `bg-linear-to-r` instead of the v3 syntax `bg-gradient-to-r`. When reviewing Tailwind v4 code, `bg-linear-to-r`, `bg-linear-to-l`, `bg-linear-to-t`, `bg-linear-to-b`, etc. are the correct gradient utility classes.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dialog/DialogContent.vue:45-50
Timestamp: 2025-07-17T14:10:14.583Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that replaces the v3 behavior of `outline-none`. It applies `outline: 2px solid transparent; outline-offset: 2px;` which hides the browser outline while preserving it in forced colors/high-contrast mode for accessibility. The migration pattern from v3 to v4 is to replace `focus:outline-none` with `focus:outline-hidden` for better accessibility.
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/Modal.vue:0-0
Timestamp: 2025-07-17T14:09:57.355Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that applies `outline: 2px solid transparent; outline-offset: 2px;`. It's the recommended replacement for v3's `outline-none` as it preserves accessibility by keeping outlines visible in high-contrast/forced-colors modes while hiding them visually in normal modes. The v4 `outline-none` now only sets `outline-style: none;` which completely removes outlines including for assistive technologies.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dialog/DialogContent.vue:45-50
Timestamp: 2025-07-17T14:10:14.583Z
Learning: The `outline-hidden` utility class is valid in Tailwind CSS and sets `outline-style: hidden`. This is different from `outline-none` which sets `outline: 2px solid transparent; outline-offset: 2px`. The change from `focus:outline-none` to `focus:outline-hidden` is part of the Tailwind CSS v4 upgrade.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue:18-22
Timestamp: 2025-07-17T14:10:23.380Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that sets `outline: 2px solid transparent; outline-offset: 2px`. This replaces the previous behavior of `outline-none` from v3 and maintains accessibility by keeping the outline visible in forced colors mode. Use `outline-hidden` instead of `outline-none` when you need to hide the outline while preserving accessibility features.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue:18-22
Timestamp: 2025-07-17T14:10:23.380Z
Learning: `outline-hidden` is a valid Tailwind CSS utility class that sets `outline-style: hidden`. This is different from `outline-none` and is available in Tailwind CSS v4.
unraid-ui/src/styles/globals.css (15)
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/UserProfile/DropdownTrigger.vue:0-0
Timestamp: 2025-07-17T14:09:37.203Z
Learning: Tailwind CSS v4 changed gradient utility classes from bg-gradient-to-r to bg-linear-to-r. The new syntax uses bg-linear-to-r instead of the v3 syntax bg-gradient-to-r for linear gradients.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dialog/DialogContent.vue:45-50
Timestamp: 2025-07-17T14:10:14.583Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that replaces the v3 behavior of `outline-none`. It applies `outline: 2px solid transparent; outline-offset: 2px;` which hides the browser outline while preserving it in forced colors/high-contrast mode for accessibility. The migration pattern from v3 to v4 is to replace `focus:outline-none` with `focus:outline-hidden` for better accessibility.
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:210-216
Timestamp: 2025-02-21T18:40:10.810Z
Learning: When updating theme-related CSS variables via `cssText`, preserve existing non-theme styles by filtering out only theme-related rules (those starting with '--') and combining them with the new theme styles.
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/UserProfile/DropdownTrigger.vue:0-0
Timestamp: 2025-07-17T14:09:37.203Z
Learning: In Tailwind CSS v4, gradient utility classes use `bg-linear-to-r` instead of the v3 syntax `bg-gradient-to-r`. When reviewing Tailwind v4 code, `bg-linear-to-r`, `bg-linear-to-l`, `bg-linear-to-t`, `bg-linear-to-b`, etc. are the correct gradient utility classes.
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/Modal.vue:0-0
Timestamp: 2025-07-17T14:09:57.355Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that applies `outline: 2px solid transparent; outline-offset: 2px;`. It's the recommended replacement for v3's `outline-none` as it preserves accessibility by keeping outlines visible in high-contrast/forced-colors modes while hiding them visually in normal modes. The v4 `outline-none` now only sets `outline-style: none;` which completely removes outlines including for assistive technologies.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue:18-22
Timestamp: 2025-07-17T14:10:23.380Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that sets `outline: 2px solid transparent; outline-offset: 2px`. This replaces the previous behavior of `outline-none` from v3 and maintains accessibility by keeping the outline visible in forced colors mode. Use `outline-hidden` instead of `outline-none` when you need to hide the outline while preserving accessibility features.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dialog/DialogContent.vue:45-50
Timestamp: 2025-07-17T14:10:14.583Z
Learning: The `outline-hidden` utility class is valid in Tailwind CSS and sets `outline-style: hidden`. This is different from `outline-none` which sets `outline: 2px solid transparent; outline-offset: 2px`. The change from `focus:outline-none` to `focus:outline-hidden` is part of the Tailwind CSS v4 upgrade.
Learnt from: mdatelle
PR: unraid/api#1106
File: unraid-ui/src/components/index.ts:2-2
Timestamp: 2025-02-04T17:21:39.710Z
Learning: The unraid-ui package is undergoing a major refactoring process, and breaking changes are expected during this transition period.
Learnt from: elibosley
PR: unraid/api#972
File: web/store/theme.ts:46-49
Timestamp: 2024-12-17T14:59:32.458Z
Learning: In the `web/store/theme.ts` file of the Unraid web application, the header is intentionally designed to have a light background with dark text in dark mode, and a dark background with light text in light mode.
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: elibosley
PR: unraid/api#1155
File: web/store/theme.ts:49-50
Timestamp: 2025-02-20T15:52:56.733Z
Learning: CSS variable names in the theme store should be concise and follow established patterns. For example, prefer '--gradient-start' over '--color-customgradient-start' to maintain consistency with other variable names.
Learnt from: elibosley
PR: unraid/api#1425
File: api/dev/configs/connect.json:2-3
Timestamp: 2025-06-20T21:05:24.582Z
Learning: When reviewing configuration files in refactoring PRs, avoid suggesting field name changes that could break compatibility with existing code that references those fields, even if the naming doesn't follow ideal conventions.
Learnt from: elibosley
PR: unraid/api#1155
File: web/store/theme.ts:161-172
Timestamp: 2025-02-20T15:52:58.297Z
Learning: The banner gradient implementation in web/store/theme.ts doesn't require explicit error handling for hexToRgba as CSS gracefully handles invalid values by ignoring them.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue:18-22
Timestamp: 2025-07-17T14:10:23.380Z
Learning: `outline-hidden` is a valid Tailwind CSS utility class that sets `outline-style: hidden`. This is different from `outline-none` and is available in Tailwind CSS v4.
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:0-0
Timestamp: 2025-02-24T14:51:21.328Z
Learning: In the Unraid API project's theme system, exact TypeScript type definitions are preferred over index signatures for theme variables to ensure better type safety.
🪛 Biome (1.9.4)
unraid-ui/src/styles/globals.css

[error] 163-163: expected , but instead found *

Remove *

(parse)


[error] 163-163: expected , but instead found ;

Remove ;

(parse)


[error] 166-166: expected , but instead found --animate-accordion-down

Remove --animate-accordion-down

(parse)


[error] 166-166: Expected a compound selector but instead found '0.2'.

Expected a compound selector here.

(parse)


[error] 166-166: expected , but instead found s

Remove s

(parse)


[error] 166-166: expected , but instead found ;

Remove ;

(parse)


[error] 167-167: expected , but instead found --animate-accordion-up

Remove --animate-accordion-up

(parse)


[error] 167-167: Expected a compound selector but instead found '0.2'.

Expected a compound selector here.

(parse)


[error] 167-167: expected , but instead found s

Remove s

(parse)


[error] 167-167: expected , but instead found ;

Remove ;

(parse)


[error] 168-168: expected , but instead found --animate-collapsible-down

Remove --animate-collapsible-down

(parse)


[error] 168-168: Expected a compound selector but instead found '0.2'.

Expected a compound selector here.

(parse)


[error] 168-168: expected , but instead found s

Remove s

(parse)


[error] 168-168: expected , but instead found ;

Remove ;

(parse)


[error] 169-169: expected , but instead found --animate-collapsible-up

Remove --animate-collapsible-up

(parse)


[error] 169-169: Expected a compound selector but instead found '0.2'.

Expected a compound selector here.

(parse)


[error] 169-169: expected , but instead found s

Remove s

(parse)


[error] 169-169: expected , but instead found ;

Remove ;

(parse)


[error] 170-170: expected , but instead found --animate-mark-2

Remove --animate-mark-2

(parse)


[error] 170-170: Expected a compound selector but instead found '1.5'.

Expected a compound selector here.

(parse)


[error] 170-170: expected , but instead found s

Remove s

(parse)


[error] 170-170: expected , but instead found ;

Remove ;

(parse)


[error] 171-171: expected , but instead found --animate-mark-3

Remove --animate-mark-3

(parse)


[error] 171-171: Expected a compound selector but instead found '1.5'.

Expected a compound selector here.

(parse)


[error] 171-171: expected , but instead found s

Remove s

(parse)


[error] 171-171: expected , but instead found ;

Remove ;

(parse)


[error] 172-172: expected , but instead found --animate-mark-6

Remove --animate-mark-6

(parse)


[error] 172-172: Expected a compound selector but instead found '1.5'.

Expected a compound selector here.

(parse)


[error] 172-172: expected , but instead found s

Remove s

(parse)


[error] 172-172: expected , but instead found ;

Remove ;

(parse)


[error] 173-173: expected , but instead found --animate-mark-7

Remove --animate-mark-7

(parse)


[error] 173-173: Expected a compound selector but instead found '1.5'.

Expected a compound selector here.

(parse)


[error] 173-173: expected , but instead found s

Remove s

(parse)


[error] 173-173: expected , but instead found ;

Remove ;

(parse)


[error] 176-176: expected , but instead found --keyframes-accordion-down

Remove --keyframes-accordion-down

(parse)


[error] 176-176: Unexpected value or character.

Expected one of:

(parse)


[error] 176-176: Expected a declaration, or an at rule but instead found '100% {'.

Expected a declaration, or an at rule here.

(parse)


[error] 176-176: Expected a qualified rule, or an at rule but instead found ';'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 177-177: Unexpected value or character.

Expected one of:

(parse)


[error] 177-177: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 177-177: Unexpected value or character.

Expected one of:

(parse)


[error] 177-177: expected , but instead found ;

Remove ;

(parse)


[error] 178-178: Unexpected value or character.

Expected one of:

(parse)


[error] 178-178: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 178-178: expected , but instead found (

Remove (

(parse)


[error] 178-178: expected , but instead found --radix-collapsible-content-height

Remove --radix-collapsible-content-height

(parse)


[error] 178-178: expected , but instead found )

Remove )

(parse)


[error] 178-178: expected , but instead found ;

Remove ;

(parse)


[error] 179-179: Unexpected value or character.

Expected one of:

(parse)


[error] 179-179: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 179-179: Unexpected value or character.

Expected one of:

(parse)


[error] 179-179: expected , but instead found ;

Remove ;

(parse)


[error] 180-180: Unexpected value or character.

Expected one of:

(parse)


[error] 180-180: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 180-180: expected , but instead found (

Remove (

(parse)


[error] 180-180: expected , but instead found ;

Remove ;

(parse)


[error] 181-181: Unexpected value or character.

Expected one of:

(parse)


[error] 181-181: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 181-181: expected , but instead found (

Remove (

(parse)


[error] 181-181: expected , but instead found ;

Remove ;

(parse)


[error] 182-182: Unexpected value or character.

Expected one of:

(parse)


[error] 182-182: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 182-182: expected , but instead found (

Remove (

(parse)


[error] 182-182: expected , but instead found ;

Remove ;

(parse)


[error] 183-183: Unexpected value or character.

Expected one of:

(parse)


[error] 183-183: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 183-183: expected , but instead found (

Remove (

(parse)


[error] 183-183: expected , but instead found ;

Remove ;

(parse)


[error] 186-186: expected , but instead found (

Remove (

(parse)


[error] 186-186: expected , but instead found ;

Remove ;

(parse)


[error] 187-187: expected , but instead found (

Remove (

(parse)


[error] 187-187: expected , but instead found ;

Remove ;

(parse)


[error] 188-188: expected , but instead found (

Remove (

(parse)


[error] 188-188: expected , but instead found ;

Remove ;

(parse)


[error] 189-189: expected , but instead found (

Remove (

(parse)


[error] 189-189: expected , but instead found ;

Remove ;

(parse)


[error] 190-190: expected , but instead found (

Remove (

(parse)


[error] 190-190: expected , but instead found ;

Remove ;

(parse)


[error] 191-191: expected , but instead found (

Remove (

(parse)


[error] 191-191: expected , but instead found ;

Remove ;

(parse)


[error] 192-192: expected , but instead found (

Remove (

(parse)


[error] 192-192: expected , but instead found ;

Remove ;

(parse)


[error] 193-193: expected , but instead found (

Remove (

(parse)


[error] 193-193: expected , but instead found ;

Remove ;

(parse)


[error] 194-194: expected , but instead found (

Remove (

(parse)


[error] 194-194: expected , but instead found ;

Remove ;

(parse)


[error] 195-195: expected , but instead found (

Remove (

(parse)


[error] 195-195: expected , but instead found ;

Remove ;

(parse)


[error] 196-196: expected , but instead found (

Remove (

(parse)


[error] 196-196: expected , but instead found ;

Remove ;

(parse)


[error] 197-197: expected , but instead found (

Remove (

(parse)


[error] 197-197: expected , but instead found ;

Remove ;

(parse)


[error] 198-198: expected , but instead found (

Remove (

(parse)


[error] 198-198: expected , but instead found ;

Remove ;

(parse)


[error] 199-199: expected , but instead found (

Remove (

(parse)


[error] 199-199: expected , but instead found ;

Remove ;

(parse)


[error] 200-200: expected , but instead found (

Remove (

(parse)


[error] 200-200: expected , but instead found ;

Remove ;

(parse)


[error] 201-201: expected , but instead found (

Remove (

(parse)


[error] 201-201: expected , but instead found ;

Remove ;

(parse)


[error] 202-202: expected , but instead found (

Remove (

(parse)


[error] 202-202: expected , but instead found ;

Remove ;

(parse)


[error] 203-203: expected , but instead found (

Remove (

(parse)


[error] 203-203: expected , but instead found ;

Remove ;

(parse)


[error] 204-204: expected , but instead found (

Remove (

(parse)


[error] 204-204: expected , but instead found ;

Remove ;

(parse)


[error] 207-207: expected , but instead found (

Remove (

(parse)


[error] 207-207: expected , but instead found ;

Remove ;

(parse)


[error] 208-208: expected , but instead found (

Remove (

(parse)


[error] 208-208: expected , but instead found ;

Remove ;

(parse)


[error] 209-209: expected , but instead found (

Remove (

(parse)


[error] 209-209: expected , but instead found ;

Remove ;

(parse)


[error] 210-210: expected , but instead found (

Remove (

(parse)


[error] 210-210: expected , but instead found ;

Remove ;

(parse)


[error] 211-211: expected , but instead found (

Remove (

(parse)


[error] 211-211: expected , but instead found ;

Remove ;

(parse)


[error] 214-214: Unexpected value or character.

Expected one of:

(parse)


[error] 214-214: expected , but instead found rem

Remove rem

(parse)


[error] 214-214: expected , but instead found ;

Remove ;

(parse)


[error] 217-217: Unexpected value or character.

Expected one of:

(parse)


[error] 217-217: expected , but instead found rem

Remove rem

(parse)


[error] 217-217: expected , but instead found ;

Remove ;

(parse)


[error] 218-218: Unexpected value or character.

Expected one of:

(parse)


[error] 218-218: expected , but instead found rem

Remove rem

(parse)


[error] 218-218: expected , but instead found ;

Remove ;

(parse)


[error] 219-219: Unexpected value or character.

Expected one of:

(parse)


[error] 219-219: expected , but instead found rem

Remove rem

(parse)


[error] 219-219: expected , but instead found ;

Remove ;

(parse)


[error] 220-220: Unexpected value or character.

Expected one of:

(parse)


[error] 220-220: expected , but instead found rem

Remove rem

(parse)


[error] 220-220: expected , but instead found ;

Remove ;

(parse)


[error] 221-221: Unexpected value or character.

Expected one of:

(parse)


[error] 221-221: expected , but instead found rem

Remove rem

(parse)


[error] 221-221: expected , but instead found ;

Remove ;

(parse)


[error] 222-222: Unexpected value or character.

Expected one of:

(parse)


[error] 222-222: expected , but instead found rem

Remove rem

(parse)


[error] 222-222: expected , but instead found ;

Remove ;

(parse)


[error] 223-223: Unexpected value or character.

Expected one of:

(parse)


[error] 223-223: expected , but instead found rem

Remove rem

(parse)


[error] 223-223: expected , but instead found ;

Remove ;

(parse)


[error] 224-224: Unexpected value or character.

Expected one of:

(parse)


[error] 224-224: expected , but instead found rem

Remove rem

(parse)


[error] 224-224: expected , but instead found ;

Remove ;

(parse)


[error] 225-225: Unexpected value or character.

Expected one of:

(parse)


[error] 225-225: expected , but instead found rem

Remove rem

(parse)


[error] 225-225: expected , but instead found ;

Remove ;

(parse)


[error] 226-226: Unexpected value or character.

Expected one of:

(parse)


[error] 226-226: expected , but instead found rem

Remove rem

(parse)


[error] 226-226: expected , but instead found ;

Remove ;

(parse)


[error] 227-227: Unexpected value or character.

Expected one of:

(parse)


[error] 227-227: expected , but instead found rem

Remove rem

(parse)


[error] 227-227: expected , but instead found ;

Remove ;

(parse)


[error] 228-228: Unexpected value or character.

Expected one of:

(parse)


[error] 228-228: expected , but instead found rem

Remove rem

(parse)


[error] 228-228: expected , but instead found ;

Remove ;

(parse)


[error] 229-229: Unexpected value or character.

Expected one of:

(parse)


[error] 229-229: expected , but instead found rem

Remove rem

(parse)


[error] 229-229: expected , but instead found ;

Remove ;

(parse)


[error] 230-230: Unexpected value or character.

Expected one of:

(parse)


[error] 230-230: expected , but instead found rem

Remove rem

(parse)


[error] 230-230: expected , but instead found ;

Remove ;

(parse)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test API
  • GitHub Check: Build API
  • GitHub Check: Analyze (javascript-typescript)

@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

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

@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

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

@elibosley elibosley marked this pull request as ready for review July 17, 2025 17:00
@github-actions
Copy link
Contributor

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

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

♻️ Duplicate comments (3)
unraid-ui/src/styles/globals.css (3)

24-26: Global --tw-border-style override is still hazardous

This blanket reset neuters Tailwind’s ability to apply dashed/none utilities and may break 3-rd-party components. Previous feedback already covered this — please scope it narrowly or drop it.


165-166: --breakpoint-* is not a legal custom-property identifier

The asterisk renders the declaration invalid in all browsers and keeps Biome unhappy. Rename to a concrete name (e.g. --breakpoint-tall) or delete it.


178-185: Storing full @keyframes blocks inside variables still breaks parsers

Keyframe blocks (0% {…}) inside custom-property values violate CSS syntax and trigger Biome errors. Define them with standard @keyframes, then reference the animation names in variables:

-  --keyframes-accordion-down: 0% {height: 0;} 100% {height: var(--radix-accordion-content-height);};
+@keyframes accordion-down {
+  0%   { height: 0 }
+  100% { height: var(--radix-accordion-content-height) }
+}
+--keyframes-accordion-down: accordion-down;

Repeat for the other five animations.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9efecd8 and f3d58dc.

📒 Files selected for processing (5)
  • .claude/settings.local.json (1 hunks)
  • api/dev/configs/api.json (1 hunks)
  • api/generated-schema.graphql (2 hunks)
  • unraid-ui/src/styles/globals.css (1 hunks)
  • web/assets/main.css (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • api/dev/configs/api.json
  • .claude/settings.local.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/assets/main.css
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/UserProfile/DropdownTrigger.vue:0-0
Timestamp: 2025-07-17T14:09:37.222Z
Learning: Tailwind CSS v4 changed gradient utility classes from bg-gradient-to-r to bg-linear-to-r. The new syntax uses bg-linear-to-r instead of the v3 syntax bg-gradient-to-r for linear gradients.
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/UserProfile/DropdownTrigger.vue:0-0
Timestamp: 2025-07-17T14:09:37.222Z
Learning: In Tailwind CSS v4, gradient utility classes use `bg-linear-to-r` instead of the v3 syntax `bg-gradient-to-r`. When reviewing Tailwind v4 code, `bg-linear-to-r`, `bg-linear-to-l`, `bg-linear-to-t`, `bg-linear-to-b`, etc. are the correct gradient utility classes.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dialog/DialogContent.vue:45-50
Timestamp: 2025-07-17T14:10:14.613Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that replaces the v3 behavior of `outline-none`. It applies `outline: 2px solid transparent; outline-offset: 2px;` which hides the browser outline while preserving it in forced colors/high-contrast mode for accessibility. The migration pattern from v3 to v4 is to replace `focus:outline-none` with `focus:outline-hidden` for better accessibility.
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/Modal.vue:0-0
Timestamp: 2025-07-17T14:09:57.364Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that applies `outline: 2px solid transparent; outline-offset: 2px;`. It's the recommended replacement for v3's `outline-none` as it preserves accessibility by keeping outlines visible in high-contrast/forced-colors modes while hiding them visually in normal modes. The v4 `outline-none` now only sets `outline-style: none;` which completely removes outlines including for assistive technologies.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dialog/DialogContent.vue:45-50
Timestamp: 2025-07-17T14:10:14.613Z
Learning: The `outline-hidden` utility class is valid in Tailwind CSS and sets `outline-style: hidden`. This is different from `outline-none` which sets `outline: 2px solid transparent; outline-offset: 2px`. The change from `focus:outline-none` to `focus:outline-hidden` is part of the Tailwind CSS v4 upgrade.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue:18-22
Timestamp: 2025-07-17T14:10:23.390Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that sets `outline: 2px solid transparent; outline-offset: 2px`. This replaces the previous behavior of `outline-none` from v3 and maintains accessibility by keeping the outline visible in forced colors mode. Use `outline-hidden` instead of `outline-none` when you need to hide the outline while preserving accessibility features.
Learnt from: elibosley
PR: unraid/api#972
File: web/components/ColorSwitcher.ce.vue:1-2
Timestamp: 2024-12-17T13:55:42.068Z
Learning: In this Nuxt.js project, components used in templates are automatically imported by Nuxt, so explicit import statements for components are unnecessary.
api/generated-schema.graphql (3)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: elibosley
PR: unraid/api#1381
File: plugin/source/dynamix.unraid.net/usr/local/share/dynamix.unraid.net/install/scripts/setup_api.sh:107-113
Timestamp: 2025-05-07T16:07:47.236Z
Learning: The Unraid API is designed to handle missing configuration files gracefully with smart internal fallbacks rather than requiring installation scripts to create default configurations.
Learnt from: elibosley
PR: unraid/api#972
File: web/store/theme.ts:46-49
Timestamp: 2024-12-17T14:59:32.458Z
Learning: In the `web/store/theme.ts` file of the Unraid web application, the header is intentionally designed to have a light background with dark text in dark mode, and a dark background with light text in light mode.
unraid-ui/src/styles/globals.css (15)
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:210-216
Timestamp: 2025-02-21T18:40:10.810Z
Learning: When updating theme-related CSS variables via `cssText`, preserve existing non-theme styles by filtering out only theme-related rules (those starting with '--') and combining them with the new theme styles.
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/UserProfile/DropdownTrigger.vue:0-0
Timestamp: 2025-07-17T14:09:37.222Z
Learning: Tailwind CSS v4 changed gradient utility classes from bg-gradient-to-r to bg-linear-to-r. The new syntax uses bg-linear-to-r instead of the v3 syntax bg-gradient-to-r for linear gradients.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dialog/DialogContent.vue:45-50
Timestamp: 2025-07-17T14:10:14.613Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that replaces the v3 behavior of `outline-none`. It applies `outline: 2px solid transparent; outline-offset: 2px;` which hides the browser outline while preserving it in forced colors/high-contrast mode for accessibility. The migration pattern from v3 to v4 is to replace `focus:outline-none` with `focus:outline-hidden` for better accessibility.
Learnt from: elibosley
PR: unraid/api#972
File: web/store/theme.ts:46-49
Timestamp: 2024-12-17T14:59:32.458Z
Learning: In the `web/store/theme.ts` file of the Unraid web application, the header is intentionally designed to have a light background with dark text in dark mode, and a dark background with light text in light mode.
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/Modal.vue:0-0
Timestamp: 2025-07-17T14:09:57.364Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that applies `outline: 2px solid transparent; outline-offset: 2px;`. It's the recommended replacement for v3's `outline-none` as it preserves accessibility by keeping outlines visible in high-contrast/forced-colors modes while hiding them visually in normal modes. The v4 `outline-none` now only sets `outline-style: none;` which completely removes outlines including for assistive technologies.
Learnt from: elibosley
PR: unraid/api#1522
File: web/components/UserProfile/DropdownTrigger.vue:0-0
Timestamp: 2025-07-17T14:09:37.222Z
Learning: In Tailwind CSS v4, gradient utility classes use `bg-linear-to-r` instead of the v3 syntax `bg-gradient-to-r`. When reviewing Tailwind v4 code, `bg-linear-to-r`, `bg-linear-to-l`, `bg-linear-to-t`, `bg-linear-to-b`, etc. are the correct gradient utility classes.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue:18-22
Timestamp: 2025-07-17T14:10:23.390Z
Learning: In Tailwind CSS v4, `outline-hidden` is a valid utility class that sets `outline: 2px solid transparent; outline-offset: 2px`. This replaces the previous behavior of `outline-none` from v3 and maintains accessibility by keeping the outline visible in forced colors mode. Use `outline-hidden` instead of `outline-none` when you need to hide the outline while preserving accessibility features.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dialog/DialogContent.vue:45-50
Timestamp: 2025-07-17T14:10:14.613Z
Learning: The `outline-hidden` utility class is valid in Tailwind CSS and sets `outline-style: hidden`. This is different from `outline-none` which sets `outline: 2px solid transparent; outline-offset: 2px`. The change from `focus:outline-none` to `focus:outline-hidden` is part of the Tailwind CSS v4 upgrade.
Learnt from: mdatelle
PR: unraid/api#1106
File: unraid-ui/src/components/index.ts:2-2
Timestamp: 2025-02-04T17:21:39.710Z
Learning: The unraid-ui package is undergoing a major refactoring process, and breaking changes are expected during this transition period.
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: elibosley
PR: unraid/api#1155
File: web/store/theme.ts:49-50
Timestamp: 2025-02-20T15:52:56.733Z
Learning: CSS variable names in the theme store should be concise and follow established patterns. For example, prefer '--gradient-start' over '--color-customgradient-start' to maintain consistency with other variable names.
Learnt from: elibosley
PR: unraid/api#1425
File: api/dev/configs/connect.json:2-3
Timestamp: 2025-06-20T21:05:24.582Z
Learning: When reviewing configuration files in refactoring PRs, avoid suggesting field name changes that could break compatibility with existing code that references those fields, even if the naming doesn't follow ideal conventions.
Learnt from: elibosley
PR: unraid/api#1155
File: web/store/theme.ts:161-172
Timestamp: 2025-02-20T15:52:58.297Z
Learning: The banner gradient implementation in web/store/theme.ts doesn't require explicit error handling for hexToRgba as CSS gracefully handles invalid values by ignoring them.
Learnt from: elibosley
PR: unraid/api#1522
File: unraid-ui/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue:18-22
Timestamp: 2025-07-17T14:10:23.390Z
Learning: `outline-hidden` is a valid Tailwind CSS utility class that sets `outline-style: hidden`. This is different from `outline-none` and is available in Tailwind CSS v4.
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:0-0
Timestamp: 2025-02-24T14:51:21.328Z
Learning: In the Unraid API project's theme system, exact TypeScript type definitions are preferred over index signatures for theme variables to ensure better type safety.
🪛 Biome (1.9.4)
unraid-ui/src/styles/globals.css

[error] 165-165: expected , but instead found *

Remove *

(parse)


[error] 165-165: expected , but instead found ;

Remove ;

(parse)


[error] 168-168: expected , but instead found --animate-accordion-down

Remove --animate-accordion-down

(parse)


[error] 168-168: Expected a compound selector but instead found '0.2'.

Expected a compound selector here.

(parse)


[error] 168-168: expected , but instead found s

Remove s

(parse)


[error] 168-168: expected , but instead found ;

Remove ;

(parse)


[error] 169-169: expected , but instead found --animate-accordion-up

Remove --animate-accordion-up

(parse)


[error] 169-169: Expected a compound selector but instead found '0.2'.

Expected a compound selector here.

(parse)


[error] 169-169: expected , but instead found s

Remove s

(parse)


[error] 169-169: expected , but instead found ;

Remove ;

(parse)


[error] 170-170: expected , but instead found --animate-collapsible-down

Remove --animate-collapsible-down

(parse)


[error] 170-170: Expected a compound selector but instead found '0.2'.

Expected a compound selector here.

(parse)


[error] 170-170: expected , but instead found s

Remove s

(parse)


[error] 170-170: expected , but instead found ;

Remove ;

(parse)


[error] 171-171: expected , but instead found --animate-collapsible-up

Remove --animate-collapsible-up

(parse)


[error] 171-171: Expected a compound selector but instead found '0.2'.

Expected a compound selector here.

(parse)


[error] 171-171: expected , but instead found s

Remove s

(parse)


[error] 171-171: expected , but instead found ;

Remove ;

(parse)


[error] 172-172: expected , but instead found --animate-mark-2

Remove --animate-mark-2

(parse)


[error] 172-172: Expected a compound selector but instead found '1.5'.

Expected a compound selector here.

(parse)


[error] 172-172: expected , but instead found s

Remove s

(parse)


[error] 172-172: expected , but instead found ;

Remove ;

(parse)


[error] 173-173: expected , but instead found --animate-mark-3

Remove --animate-mark-3

(parse)


[error] 173-173: Expected a compound selector but instead found '1.5'.

Expected a compound selector here.

(parse)


[error] 173-173: expected , but instead found s

Remove s

(parse)


[error] 173-173: expected , but instead found ;

Remove ;

(parse)


[error] 174-174: expected , but instead found --animate-mark-6

Remove --animate-mark-6

(parse)


[error] 174-174: Expected a compound selector but instead found '1.5'.

Expected a compound selector here.

(parse)


[error] 174-174: expected , but instead found s

Remove s

(parse)


[error] 174-174: expected , but instead found ;

Remove ;

(parse)


[error] 175-175: expected , but instead found --animate-mark-7

Remove --animate-mark-7

(parse)


[error] 175-175: Expected a compound selector but instead found '1.5'.

Expected a compound selector here.

(parse)


[error] 175-175: expected , but instead found s

Remove s

(parse)


[error] 175-175: expected , but instead found ;

Remove ;

(parse)


[error] 178-178: expected , but instead found --keyframes-accordion-down

Remove --keyframes-accordion-down

(parse)


[error] 178-178: Unexpected value or character.

Expected one of:

(parse)


[error] 178-178: Expected a declaration, or an at rule but instead found '100% {'.

Expected a declaration, or an at rule here.

(parse)


[error] 178-178: Expected a qualified rule, or an at rule but instead found ';'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 179-179: Unexpected value or character.

Expected one of:

(parse)


[error] 179-179: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 179-179: Unexpected value or character.

Expected one of:

(parse)


[error] 179-179: expected , but instead found ;

Remove ;

(parse)


[error] 180-180: Unexpected value or character.

Expected one of:

(parse)


[error] 180-180: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 180-180: expected , but instead found (

Remove (

(parse)


[error] 180-180: expected , but instead found --radix-collapsible-content-height

Remove --radix-collapsible-content-height

(parse)


[error] 180-180: expected , but instead found )

Remove )

(parse)


[error] 180-180: expected , but instead found ;

Remove ;

(parse)


[error] 181-181: Unexpected value or character.

Expected one of:

(parse)


[error] 181-181: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 181-181: Unexpected value or character.

Expected one of:

(parse)


[error] 181-181: expected , but instead found ;

Remove ;

(parse)


[error] 182-182: Unexpected value or character.

Expected one of:

(parse)


[error] 182-182: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 182-182: expected , but instead found (

Remove (

(parse)


[error] 182-182: expected , but instead found ;

Remove ;

(parse)


[error] 183-183: Unexpected value or character.

Expected one of:

(parse)


[error] 183-183: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 183-183: expected , but instead found (

Remove (

(parse)


[error] 183-183: expected , but instead found ;

Remove ;

(parse)


[error] 184-184: Unexpected value or character.

Expected one of:

(parse)


[error] 184-184: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 184-184: expected , but instead found (

Remove (

(parse)


[error] 184-184: expected , but instead found ;

Remove ;

(parse)


[error] 185-185: Unexpected value or character.

Expected one of:

(parse)


[error] 185-185: Expected a qualified rule, or an at rule but instead found '100% {'.

Expected a qualified rule, or an at rule here.

(parse)


[error] 185-185: expected , but instead found (

Remove (

(parse)


[error] 185-185: expected , but instead found ;

Remove ;

(parse)


[error] 188-188: Unexpected value or character.

Expected one of:

(parse)


[error] 188-188: expected , but instead found rem

Remove rem

(parse)


[error] 188-188: expected , but instead found ;

Remove ;

(parse)


[error] 191-191: Unexpected value or character.

Expected one of:

(parse)


[error] 191-191: expected , but instead found rem

Remove rem

(parse)


[error] 191-191: expected , but instead found ;

Remove ;

(parse)


[error] 192-192: Unexpected value or character.

Expected one of:

(parse)


[error] 192-192: expected , but instead found rem

Remove rem

(parse)


[error] 192-192: expected , but instead found ;

Remove ;

(parse)


[error] 193-193: Unexpected value or character.

Expected one of:

(parse)


[error] 193-193: expected , but instead found rem

Remove rem

(parse)


[error] 193-193: expected , but instead found ;

Remove ;

(parse)


[error] 194-194: Unexpected value or character.

Expected one of:

(parse)


[error] 194-194: expected , but instead found rem

Remove rem

(parse)


[error] 194-194: expected , but instead found ;

Remove ;

(parse)


[error] 195-195: Unexpected value or character.

Expected one of:

(parse)


[error] 195-195: expected , but instead found rem

Remove rem

(parse)


[error] 195-195: expected , but instead found ;

Remove ;

(parse)


[error] 196-196: Unexpected value or character.

Expected one of:

(parse)


[error] 196-196: expected , but instead found rem

Remove rem

(parse)


[error] 196-196: expected , but instead found ;

Remove ;

(parse)


[error] 197-197: Unexpected value or character.

Expected one of:

(parse)


[error] 197-197: expected , but instead found rem

Remove rem

(parse)


[error] 197-197: expected , but instead found ;

Remove ;

(parse)


[error] 198-198: Unexpected value or character.

Expected one of:

(parse)


[error] 198-198: expected , but instead found rem

Remove rem

(parse)


[error] 198-198: expected , but instead found ;

Remove ;

(parse)


[error] 199-199: Unexpected value or character.

Expected one of:

(parse)


[error] 199-199: expected , but instead found rem

Remove rem

(parse)


[error] 199-199: expected , but instead found ;

Remove ;

(parse)


[error] 200-200: Unexpected value or character.

Expected one of:

(parse)


[error] 200-200: expected , but instead found rem

Remove rem

(parse)


[error] 200-200: expected , but instead found ;

Remove ;

(parse)


[error] 201-201: Unexpected value or character.

Expected one of:

(parse)


[error] 201-201: expected , but instead found rem

Remove rem

(parse)


[error] 201-201: expected , but instead found ;

Remove ;

(parse)


[error] 202-202: Unexpected value or character.

Expected one of:

(parse)


[error] 202-202: expected , but instead found rem

Remove rem

(parse)


[error] 202-202: expected , but instead found ;

Remove ;

(parse)


[error] 203-203: Unexpected value or character.

Expected one of:

(parse)


[error] 203-203: expected , but instead found rem

Remove rem

(parse)


[error] 203-203: expected , but instead found ;

Remove ;

(parse)


[error] 204-204: Unexpected value or character.

Expected one of:

(parse)


[error] 204-204: expected , but instead found rem

Remove rem

(parse)


[error] 204-204: expected , but instead found ;

Remove ;

(parse)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Build Web App
  • GitHub Check: Test API
  • GitHub Check: Build API
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
api/generated-schema.graphql (2)

330-345: DiskSmartStatus enum is too narrow

Only OK and UNKNOWN are represented. SMART commonly reports FAIL, WARN, PASSED, etc. If those values appear in backend data, GraphQL execution will error with “Enum value ... not in type”. Please confirm the backend never returns additional statuses or extend the enum accordingly.


951-954: New headerSecondaryTextColor field: verify client coverage

This is a brand-new field (was not present earlier). Ensure all UI components that consume Theme fragments or objects are updated, otherwise codegen will fail or the value will remain unused.

@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/PR1522/dynamix.unraid.net.plg

Copy link
Member

@pujitm pujitm left a comment

Choose a reason for hiding this comment

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

lgtm

@elibosley elibosley merged commit 2c62e0a into main Jul 21, 2025
12 checks passed
@elibosley elibosley deleted the feat/tailwind-v4-part-deux branch July 21, 2025 13:58
elibosley pushed a commit that referenced this pull request Jul 28, 2025
🤖 I have created a release *beep* *boop*
---


## [4.11.0](v4.10.0...v4.11.0)
(2025-07-28)


### Features

* tailwind v4 ([#1522](#1522))
([2c62e0a](2c62e0a))
* **web:** install and configure nuxt ui
([#1524](#1524))
([407585c](407585c))


### Bug Fixes

* add missing breakpoints
([#1535](#1535))
([f5352e3](f5352e3))
* border color incorrect in tailwind
([#1544](#1544))
([f14b74a](f14b74a))
* **connect:** omit extraneous fields during connect config validation
([#1538](#1538))
([45bd736](45bd736))
* **deps:** pin dependencies
([#1528](#1528))
([a74d935](a74d935))
* **deps:** pin dependency @nuxt/ui to 3.2.0
([#1532](#1532))
([8279531](8279531))
* **deps:** update all non-major dependencies
([#1510](#1510))
([1a8da6d](1a8da6d))
* **deps:** update all non-major dependencies
([#1520](#1520))
([e2fa648](e2fa648))
* inject Tailwind CSS into client entry point
([#1537](#1537))
([86b6c4f](86b6c4f))
* make settings grid responsive
([#1463](#1463))
([9dfdb8d](9dfdb8d))
* **notifications:** gracefully handle & mask invalid notifications
([#1529](#1529))
([05056e7](05056e7))
* truncate log files when they take up more than 5mb of space
([#1530](#1530))
([0a18b38](0a18b38))
* use async for primary file read/writes
([#1531](#1531))
([23b2b88](23b2b88))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
mdatelle pushed a commit that referenced this pull request Jul 30, 2025
🤖 I have created a release *beep* *boop*
---


## [4.11.0](v4.10.0...v4.11.0)
(2025-07-28)


### Features

* tailwind v4 ([#1522](#1522))
([2c62e0a](2c62e0a))
* **web:** install and configure nuxt ui
([#1524](#1524))
([407585c](407585c))


### Bug Fixes

* add missing breakpoints
([#1535](#1535))
([f5352e3](f5352e3))
* border color incorrect in tailwind
([#1544](#1544))
([f14b74a](f14b74a))
* **connect:** omit extraneous fields during connect config validation
([#1538](#1538))
([45bd736](45bd736))
* **deps:** pin dependencies
([#1528](#1528))
([a74d935](a74d935))
* **deps:** pin dependency @nuxt/ui to 3.2.0
([#1532](#1532))
([8279531](8279531))
* **deps:** update all non-major dependencies
([#1510](#1510))
([1a8da6d](1a8da6d))
* **deps:** update all non-major dependencies
([#1520](#1520))
([e2fa648](e2fa648))
* inject Tailwind CSS into client entry point
([#1537](#1537))
([86b6c4f](86b6c4f))
* make settings grid responsive
([#1463](#1463))
([9dfdb8d](9dfdb8d))
* **notifications:** gracefully handle & mask invalid notifications
([#1529](#1529))
([05056e7](05056e7))
* truncate log files when they take up more than 5mb of space
([#1530](#1530))
([0a18b38](0a18b38))
* use async for primary file read/writes
([#1531](#1531))
([23b2b88](23b2b88))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@coderabbitai coderabbitai bot mentioned this pull request Aug 29, 2025
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