[refactor] Replace PrimeVue ProgressSpinner with Lucide loader icon (#9372)

## Summary
- Replace PrimeVue `ProgressSpinner` with Lucide `loader-circle` icon in
App.vue and WorkspaceAuthGate.vue
- Use white color for loading spinner for better visibility on dark
backgrounds
- Remove `primevue/progressspinner` imports and update related test

## Changes
- **App.vue**: Replace `ProgressSpinner` with
`icon-[lucide--loader-circle]`
- **WorkspaceAuthGate.vue**: Same replacement
- **WorkspaceAuthGate.test.ts**: Remove ProgressSpinner mock, use
`.animate-spin` selector

## Review Focus
- Visual consistency of white spinner on dark background during initial
load

<img width="1596" height="1189" alt="스크린샷 2026-03-04 오후 6 28 27"
src="https://github.com/user-attachments/assets/d703db74-4123-4328-912a-45ac45cf6eeb"
/>
<img width="1680" height="1304" alt="스크린샷 2026-03-04 오후 6 28 24"
src="https://github.com/user-attachments/assets/8026d10a-7e06-4f95-849c-bc891756823c"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9372-refactor-Replace-PrimeVue-ProgressSpinner-with-Lucide-loader-icon-3196d73d3650815bb1d1d4554f7f744e)
by [Unito](https://www.unito.io)
This commit is contained in:
Jin Yi
2026-03-05 16:23:22 +09:00
committed by GitHub
parent c2fc0c0f03
commit 706060a2bf
12 changed files with 111 additions and 40 deletions

View File

@@ -0,0 +1,50 @@
import type { Meta, StoryObj } from '@storybook/vue3-vite'
import Loader from './Loader.vue'
const meta: Meta<typeof Loader> = {
title: 'Components/Common/Loader',
component: Loader,
tags: ['autodocs'],
parameters: {
layout: 'centered'
},
argTypes: {
size: {
control: 'select',
options: ['sm', 'md', 'lg'],
description: 'Spinner size: sm (16px), md (32px), lg (48px)'
}
}
}
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {}
export const Small: Story = {
args: { size: 'sm' }
}
export const Medium: Story = {
args: { size: 'md' }
}
export const Large: Story = {
args: { size: 'lg' }
}
export const CustomColor: Story = {
render: (args) => ({
components: { Loader },
setup() {
return { args }
},
template:
'<div class="flex gap-4 items-center"><Loader size="lg" class="text-white" /><Loader size="md" class="text-muted-foreground" /><Loader size="sm" class="text-base-foreground" /></div>'
}),
parameters: {
backgrounds: { default: 'dark' }
}
}

View File

@@ -0,0 +1,29 @@
<template>
<span role="status" class="inline-flex">
<i
aria-hidden="true"
:class="cn('icon-[lucide--loader-circle] animate-spin', sizeClass)"
/>
<span class="sr-only">{{ t('g.loading') }}</span>
</span>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { cn } from '@/utils/tailwindUtil'
const { size } = defineProps<{
size?: 'sm' | 'md' | 'lg'
}>()
const { t } = useI18n()
const sizeMap = {
sm: 'size-4',
md: 'size-8',
lg: 'size-12'
} as const
const sizeClass = size ? sizeMap[size] : ''
</script>