diff --git a/src/components/dialog/content/manager/ManagerDialogContent.vue b/src/components/dialog/content/manager/ManagerDialogContent.vue
index 83ac3bbca..de7f82293 100644
--- a/src/components/dialog/content/manager/ManagerDialogContent.vue
+++ b/src/components/dialog/content/manager/ManagerDialogContent.vue
@@ -35,9 +35,9 @@
@@ -97,7 +92,6 @@
diff --git a/src/components/dialog/content/manager/skeleton/PackCardSkeleton.vue b/src/components/dialog/content/manager/skeleton/PackCardSkeleton.vue
new file mode 100644
index 000000000..abd52a7d5
--- /dev/null
+++ b/src/components/dialog/content/manager/skeleton/PackCardSkeleton.vue
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/dialog/content/manager/skeleton/__tests__/PackCardGridSkeleton.test.ts b/src/components/dialog/content/manager/skeleton/__tests__/PackCardGridSkeleton.test.ts
new file mode 100644
index 000000000..5baeff958
--- /dev/null
+++ b/src/components/dialog/content/manager/skeleton/__tests__/PackCardGridSkeleton.test.ts
@@ -0,0 +1,79 @@
+import { VueWrapper, mount } from '@vue/test-utils'
+import { createPinia } from 'pinia'
+import PrimeVue from 'primevue/config'
+import { describe, expect, it } from 'vitest'
+import { nextTick } from 'vue'
+import { createI18n } from 'vue-i18n'
+
+import enMessages from '@/locales/en/main.json'
+
+import GridSkeleton from '../GridSkeleton.vue'
+import PackCardSkeleton from '../PackCardSkeleton.vue'
+
+describe('GridSkeleton', () => {
+ const mountComponent = ({
+ props = {}
+ }: Record = {}): VueWrapper => {
+ const i18n = createI18n({
+ legacy: false,
+ locale: 'en',
+ messages: { en: enMessages }
+ })
+
+ return mount(GridSkeleton, {
+ props: {
+ gridStyle: {
+ display: 'grid',
+ gridTemplateColumns: 'repeat(auto-fill, minmax(19rem, 1fr))',
+ padding: '0.5rem',
+ gap: '1.5rem'
+ },
+ ...props
+ },
+ global: {
+ plugins: [PrimeVue, createPinia(), i18n],
+ stubs: {
+ PackCardSkeleton: true
+ }
+ }
+ })
+ }
+
+ it('renders with default props', () => {
+ const wrapper = mountComponent()
+ expect(wrapper.exists()).toBe(true)
+ })
+
+ it('applies the provided grid style', () => {
+ const customGridStyle = {
+ display: 'grid',
+ gridTemplateColumns: 'repeat(auto-fill, minmax(15rem, 1fr))',
+ padding: '1rem',
+ gap: '1rem'
+ }
+
+ const wrapper = mountComponent({
+ props: { gridStyle: customGridStyle }
+ })
+
+ const gridElement = wrapper.element
+ expect(gridElement.style.display).toBe('grid')
+ expect(gridElement.style.gridTemplateColumns).toBe(
+ 'repeat(auto-fill, minmax(15rem, 1fr))'
+ )
+ expect(gridElement.style.padding).toBe('1rem')
+ expect(gridElement.style.gap).toBe('1rem')
+ })
+
+ it('renders the specified number of skeleton cards', async () => {
+ const cardCount = 5
+ const wrapper = mountComponent({
+ props: { skeletonCardCount: cardCount }
+ })
+
+ await nextTick()
+
+ const skeletonCards = wrapper.findAllComponents(PackCardSkeleton)
+ expect(skeletonCards.length).toBe(5)
+ })
+})
diff --git a/tailwind.config.js b/tailwind.config.js
index ad0b42818..dc2a69710 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -217,6 +217,22 @@ export default {
plugins: [
function ({ addVariant }) {
addVariant('dark-theme', '.dark-theme &')
+ },
+ function ({ addUtilities }) {
+ const newUtilities = {
+ '.scrollbar-hide': {
+ /* Firefox */
+ 'scrollbar-width': 'none',
+ /* Webkit-based browsers */
+ '&::-webkit-scrollbar': {
+ width: '1px'
+ },
+ '&::-webkit-scrollbar-thumb': {
+ 'background-color': 'transparent'
+ }
+ }
+ }
+ addUtilities(newUtilities)
}
]
}