Files
api/unraid-ui
github-actions[bot] 9624ca5c39 chore(main): release 4.9.0 (#1378)
🤖 I have created a release *beep* *boop*
---


## [4.9.0](https://github.com/unraid/api/compare/v4.8.0...v4.9.0)
(2025-07-08)


### Features

* add graphql resource for API plugins
([#1420](https://github.com/unraid/api/issues/1420))
([642a220](642a220c3a))
* add management page for API keys
([#1408](https://github.com/unraid/api/issues/1408))
([0788756](0788756b91))
* add rclone ([#1362](https://github.com/unraid/api/issues/1362))
([5517e75](5517e7506b))
* API key management
([#1407](https://github.com/unraid/api/issues/1407))
([d37dc3b](d37dc3bce2))
* api plugin management via CLI
([#1416](https://github.com/unraid/api/issues/1416))
([3dcbfbe](3dcbfbe489))
* build out docker components
([#1427](https://github.com/unraid/api/issues/1427))
([711cc9a](711cc9ac92))
* docker and info resolver issues
([#1423](https://github.com/unraid/api/issues/1423))
([9901039](9901039a38))
* fix shading in UPC to be less severe
([#1438](https://github.com/unraid/api/issues/1438))
([b7c2407](b7c2407840))
* info resolver cleanup
([#1425](https://github.com/unraid/api/issues/1425))
([1b279bb](1b279bbab3))
* initial codeql setup
([#1390](https://github.com/unraid/api/issues/1390))
([2ade7eb](2ade7eb527))
* initialize claude code in codebse
([#1418](https://github.com/unraid/api/issues/1418))
([b6c4ee6](b6c4ee6eb4))
* move api key fetching to use api key service
([#1439](https://github.com/unraid/api/issues/1439))
([86bea56](86bea56272))
* move to cron v4 ([#1428](https://github.com/unraid/api/issues/1428))
([b8035c2](b8035c207a))
* move to iframe for changelog
([#1388](https://github.com/unraid/api/issues/1388))
([fcd6fbc](fcd6fbcdd4))
* native slackware package
([#1381](https://github.com/unraid/api/issues/1381))
([4f63b4c](4f63b4cf3b))
* send active unraid theme to docs
([#1400](https://github.com/unraid/api/issues/1400))
([f71943b](f71943b62b))
* slightly better watch mode
([#1398](https://github.com/unraid/api/issues/1398))
([881f1e0](881f1e0960))
* upgrade nuxt-custom-elements
([#1461](https://github.com/unraid/api/issues/1461))
([345e83b](345e83bfb0))
* use bigint instead of long
([#1403](https://github.com/unraid/api/issues/1403))
([574d572](574d572d65))


### Bug Fixes

* activation indicator removed
([5edfd82](5edfd823b8))
* alignment of settings on ManagementAccess settings page
([#1421](https://github.com/unraid/api/issues/1421))
([70c790f](70c790ff89))
* allow rclone to fail to initialize
([#1453](https://github.com/unraid/api/issues/1453))
([7c6f02a](7c6f02a5cb))
* always download 7.1 versioned files for patching
([edc0d15](edc0d1578b))
* api `pnpm type-check`
([#1442](https://github.com/unraid/api/issues/1442))
([3122bdb](3122bdb953))
* **api:** connect config `email` validation
([#1454](https://github.com/unraid/api/issues/1454))
([b9a1b9b](b9a1b9b087))
* backport
unraid/webgui[#2269](https://github.com/unraid/api/issues/2269) rc.nginx
update ([#1436](https://github.com/unraid/api/issues/1436))
([a7ef06e](a7ef06ea25))
* bigint
([e54d27a](e54d27aede))
* config migration from `myservers.cfg`
([#1440](https://github.com/unraid/api/issues/1440))
([c4c9984](c4c99843c7))
* **connect:** fatal race-condition in websocket disposal
([#1462](https://github.com/unraid/api/issues/1462))
([0ec0de9](0ec0de982f))
* **connect:** mothership connection
([#1464](https://github.com/unraid/api/issues/1464))
([7be8bc8](7be8bc84d3))
* console hidden
([9b85e00](9b85e009b8))
* debounce is too long
([#1426](https://github.com/unraid/api/issues/1426))
([f12d231](f12d231e63))
* delete legacy connect keys and ensure description
([22fe91c](22fe91cd56))
* **deps:** pin dependencies
([#1465](https://github.com/unraid/api/issues/1465))
([ba75a40](ba75a409a4))
* **deps:** pin dependencies
([#1470](https://github.com/unraid/api/issues/1470))
([412b329](412b32996d))
* **deps:** storybook v9
([#1476](https://github.com/unraid/api/issues/1476))
([45bb49b](45bb49bcd6))
* **deps:** update all non-major dependencies
([#1366](https://github.com/unraid/api/issues/1366))
([291ee47](291ee475fb))
* **deps:** update all non-major dependencies
([#1379](https://github.com/unraid/api/issues/1379))
([8f70326](8f70326d0f))
* **deps:** update all non-major dependencies
([#1389](https://github.com/unraid/api/issues/1389))
([cb43f95](cb43f95233))
* **deps:** update all non-major dependencies
([#1399](https://github.com/unraid/api/issues/1399))
([68df344](68df344a4b))
* **deps:** update dependency @types/diff to v8
([#1393](https://github.com/unraid/api/issues/1393))
([00da27d](00da27d04f))
* **deps:** update dependency cache-manager to v7
([#1413](https://github.com/unraid/api/issues/1413))
([9492c2a](9492c2ae6a))
* **deps:** update dependency commander to v14
([#1394](https://github.com/unraid/api/issues/1394))
([106ea09](106ea09399))
* **deps:** update dependency diff to v8
([#1386](https://github.com/unraid/api/issues/1386))
([e580f64](e580f646a5))
* **deps:** update dependency dotenv to v17
([#1474](https://github.com/unraid/api/issues/1474))
([d613bfa](d613bfa041))
* **deps:** update dependency lucide-vue-next to ^0.509.0
([#1383](https://github.com/unraid/api/issues/1383))
([469333a](469333acd4))
* **deps:** update dependency marked to v16
([#1444](https://github.com/unraid/api/issues/1444))
([453a5b2](453a5b2c95))
* **deps:** update dependency shadcn-vue to v2
([#1302](https://github.com/unraid/api/issues/1302))
([26ecf77](26ecf779e6))
* **deps:** update dependency vue-sonner to v2
([#1401](https://github.com/unraid/api/issues/1401))
([53ca414](53ca41404f))
* disable file changes on Unraid 7.2
([#1382](https://github.com/unraid/api/issues/1382))
([02de89d](02de89d130))
* do not start API with doinst.sh
([7d88b33](7d88b3393c))
* do not uninstall fully on 7.2
([#1484](https://github.com/unraid/api/issues/1484))
([2263881](22638811a9))
* drop console with terser
([a87d455](a87d455bac))
* error logs from `cloud` query when connect is not installed
([#1450](https://github.com/unraid/api/issues/1450))
([719f460](719f460016))
* flash backup integration with Unraid Connect config
([#1448](https://github.com/unraid/api/issues/1448))
([038c582](038c582aed))
* header padding regression
([#1477](https://github.com/unraid/api/issues/1477))
([e791cc6](e791cc680d))
* incorrect state merging in redux store
([#1437](https://github.com/unraid/api/issues/1437))
([17b7428](17b7428779))
* lanip copy button not present
([#1459](https://github.com/unraid/api/issues/1459))
([a280786](a2807864ac))
* move to bigint scalar
([b625227](b625227913))
* node_modules dir removed on plugin update
([#1406](https://github.com/unraid/api/issues/1406))
([7b005cb](7b005cbbf6))
* omit Connect actions in UPC when plugin is not installed
([#1417](https://github.com/unraid/api/issues/1417))
([8c8a527](8c8a5276b4))
* parsing of `ssoEnabled` in state.php
([#1455](https://github.com/unraid/api/issues/1455))
([f542c8e](f542c8e0bd))
* pin ranges ([#1460](https://github.com/unraid/api/issues/1460))
([f88400e](f88400eea8))
* pr plugin promotion workflow
([#1456](https://github.com/unraid/api/issues/1456))
([13bd9bb](13bd9bb567))
* proper fallback if missing paths config modules
([7067e9e](7067e9e3dd))
* rc.unraid-api now cleans up older dependencies
([#1404](https://github.com/unraid/api/issues/1404))
([83076bb](83076bb940))
* remote access lifecycle during boot & shutdown
([#1422](https://github.com/unraid/api/issues/1422))
([7bc583b](7bc583b186))
* sign out correctly on error
([#1452](https://github.com/unraid/api/issues/1452))
([d08fc94](d08fc94afb))
* simplify usb listing
([#1402](https://github.com/unraid/api/issues/1402))
([5355115](5355115af2))
* theme issues when sent from graph
([#1424](https://github.com/unraid/api/issues/1424))
([75ad838](75ad8381bd))
* **ui:** notifications positioning regression
([#1445](https://github.com/unraid/api/issues/1445))
([f73e5e0](f73e5e0058))
* use some instead of every for connect detection
([9ce2fee](9ce2fee380))


### Reverts

* revert package.json dependency updates from commit 711cc9a for api and
packages/*
([94420e4](94420e4d45))

---
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>
2025-07-08 15:45:49 -04:00
..
2025-05-27 07:52:25 -04:00
2025-05-27 07:52:25 -04:00
2025-05-27 07:52:25 -04:00
2025-07-08 13:00:20 -04:00

Unraid UI

A Vue 3 component library providing a set of reusable, accessible UI components for Unraid development.

Features

  • Built with Vue 3 and TypeScript
  • 🎭 Storybook documentation
  • Tested components
  • 🎪 Built on top of TailwindCSS and Shadcn/UI

Installation

Make sure you have the peer dependencies installed:

npm install vue@^3.3.0 tailwindcss@^3.0.0

Setup

1. Add CSS

Import the component library styles in your main entry file:

import '@unraid/ui/style.css';

2. Configure TailwindCSS

Create a tailwind.config.ts file with the following configuration:

import tailwindConfig from '@unraid/ui/tailwind.config.ts';
import type { Config } from 'tailwindcss';

export default {
  presets: [tailwindConfig],
  content: [
    // ... your content paths
    './components/**/*.{js,vue,ts}',
    './layouts/**/*.vue',
    './pages/**/*.vue',
  ],
  theme: {
    extend: {
      // your theme extensions
    },
  },
} satisfies Partial<Config>;

This configuration:

  • Uses the Unraid UI library's Tailwind config as a preset
  • Properly types your configuration with TypeScript
  • Allows you to extend the base theme while maintaining all Unraid UI defaults

Usage

<script setup lang="ts">
import { Button } from '@unraid/ui';
</script>

<template>
  <Button variant="primary"> Click me </Button>
</template>

Development

Local Development

Install dependencies:

npm install

Start Storybook development server:

npm run storybook

This will start Storybook at http://localhost:6006

Building

npm run build

Testing

Run tests:

npm run test

Run tests with UI:

npm run test:ui

Generate coverage report:

npm run coverage

Type Checking

npm run typecheck

Scripts

  • dev: Start development server
  • build: Build for production
  • preview: Preview production build
  • test: Run tests
  • test:ui: Run tests with UI
  • coverage: Generate test coverage
  • clean: Remove build artifacts
  • typecheck: Run type checking
  • storybook: Start Storybook development server
  • build-storybook: Build Storybook for production

License

Component Development

Installing Shadcn Components

  1. Install a new component using the Shadcn CLI:
npx shadcn-vue@latest add [component-name]
  1. The component will be installed in the root components folder. Move it to the appropriate subfolder based on its type:

    • Form components → src/components/form/
    • Layout components → src/components/layout/
    • Common components → src/components/common/
    • Brand components → src/components/brand/
  2. Update any imports in your codebase to reflect the new component location.

Component Variants Pattern

We use the class-variance-authority (CVA) package to manage component variants. Each component that supports variants should follow this pattern:

  1. Create a variants file (e.g., button.variants.ts):
import { cva } from 'class-variance-authority';

export const buttonVariants = cva('base-classes-here', {
  variants: {
    variant: {
      primary: 'variant-specific-classes',
      secondary: 'variant-specific-classes',
      // ... other variants
    },
    size: {
      sm: 'size-specific-classes',
      md: 'size-specific-classes',
      lg: 'size-specific-classes',
    },
  },
  defaultVariants: {
    variant: 'primary',
    size: 'md',
  },
});
  1. Use the variants in your component (e.g., Button.vue):
<script setup lang="ts">



import { computed } from "vue";
import { buttonVariants } from "./button.variants";
import { cn } from "@/lib/utils";

export interface ButtonProps {
  variant?: "primary" | "secondary" | /* other variants */;
  size?: "sm" | "md" | "lg";
  class?: string;
}

const props = withDefaults(defineProps<ButtonProps>(), {
  variant: "primary",
  size: "md",
});

const buttonClass = computed(() => {
  return cn(
    buttonVariants({ variant: props.variant, size: props.size }),
    props.class
  );
});
</script>

<template>
  <button :class="buttonClass">
    <slot />
  </button>
</template>

Storybook Development

We use Storybook for component development and documentation. To start the Storybook development server:

npm run storybook

This will start Storybook at http://localhost:6006

When creating stories for your components:

  1. Place story files in the stories directory
  2. Name your story files as ComponentName.stories.ts
  3. Include examples of all variants and states
  4. Add documentation using JSDoc comments

Example story file:

import type { Meta, StoryObj } from '@storybook/vue3';
import { Button } from '../src/components/common/button';

const meta = {
  title: 'Components/Button',
  component: Button,
  tags: ['autodocs'],
  argTypes: {
    variant: {
      control: 'select',
      options: ['primary', 'secondary', 'outline'],
    },
    size: {
      control: 'select',
      options: ['sm', 'md', 'lg'],
    },
  },
} satisfies Meta<typeof Button>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Primary: Story = {
  args: {
    variant: 'primary',
    size: 'md',
  },
};

export const Secondary: Story = {
  args: {
    variant: 'secondary',
    size: 'md',
  },
};