mitlist/fe/src/components/valerie/VSpinner.vue
google-labs-jules[bot] 272e5abe41 refactor: Integrate Valerie UI components into Group and List pages
This commit refactors parts of `GroupsPage.vue`, `ListsPage.vue`, and the shared `CreateListModal.vue` to use the newly created Valerie UI components.

Key changes include:

1.  **Modals:**
    *   The "Create Group Dialog" in `GroupsPage.vue` now uses `VModal`, `VFormField`, `VInput`, `VButton`, and `VSpinner`.
    *   The `CreateListModal.vue` component (used by both pages) has been internally refactored to use `VModal`, `VFormField`, `VInput`, `VTextarea`, `VSelect`, `VButton`, and `VSpinner`.

2.  **Forms:**
    *   The "Join Group" form in `GroupsPage.vue` now uses `VFormField`, `VInput`, `VButton`, and `VSpinner`.

3.  **Alerts:**
    *   Error alerts in both `GroupsPage.vue` and `ListsPage.vue` now use the `VAlert` component, with retry buttons placed in the `actions` slot.

4.  **Empty States:**
    *   The empty state displays (e.g., "No Groups Yet", "No lists found") in both pages now use the `VCard` component with `variant="empty-state"`, mapping content to the relevant props and slots.

5.  **Buttons:**
    *   Various standalone buttons (e.g., "Create New Group", "Create New List", "List" button on group cards) have been updated to use the `VButton` component with appropriate props for variants, sizes, and icons.

**Scope of this Refactor:**
*   The focus was on replacing direct usages of custom-styled modal dialogs, form elements, alerts, and buttons with their Valerie UI component counterparts.
*   Highly custom card-like structures such as `neo-group-card` (in `GroupsPage.vue`) and `neo-list-card` (in `ListsPage.vue`), along with their specific "create" card variants, have been kept with their existing custom styling for this phase. This is due to their unique layouts and styling not directly mapping to the current generic `VCard` component without significant effort or potential introduction of overly specific props to `VCard`. Only buttons within these custom cards were refactored.
*   The internal item rendering within `neo-list-card` (custom checkboxes, add item input) also remains custom for now.

This refactoring improves consistency by leveraging the standardized Valerie UI components for common UI patterns like modals, forms, alerts, and buttons on these pages.
2025-06-01 14:26:37 +02:00

96 lines
2.9 KiB
Vue

<template>
<div
role="status"
:aria-label="label"
class="spinner-dots"
:class="sizeClass"
>
<span></span>
<span></span>
<span></span>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
const props = defineProps({
size: {
type: String, // 'sm', 'md'
default: 'md',
validator: (value: string) => ['sm', 'md'].includes(value),
},
label: {
type: String,
default: 'Loading...',
},
});
const sizeClass = computed(() => {
// Based on valerie-ui.scss, 'spinner-dots' is the medium size.
// Only 'sm' size needs an additional specific class.
return props.size === 'sm' ? 'spinner-dots-sm' : null;
});
</script>
<style lang="scss" scoped>
// Styles for .spinner-dots and .spinner-dots-sm are assumed to be globally available
// from valerie-ui.scss or a similar imported stylesheet.
// For completeness in a standalone component context, they would be defined here.
// Example (from valerie-ui.scss structure):
// .spinner-dots {
// display: inline-flex; // Changed from inline-block for better flex alignment if needed
// align-items: center; // Align dots vertically if their heights differ (should not with this CSS)
// justify-content: space-around; // Distribute dots if container has more space (width affects this)
// // Default (medium) size variables from valerie-ui.scss
// // --spinner-dot-size: 8px;
// // --spinner-spacing: 2px;
// // width: calc(var(--spinner-dot-size) * 3 + var(--spinner-spacing) * 2);
// // height: var(--spinner-dot-size);
// span {
// display: inline-block;
// width: var(--spinner-dot-size, 8px);
// height: var(--spinner-dot-size, 8px);
// margin: 0 var(--spinner-spacing, 2px); // Replaces justify-content if width is tight
// border-radius: 50%;
// background-color: var(--spinner-color, #007bff); // Use a CSS variable for color
// animation: spinner-dots-bounce 1.4s infinite ease-in-out both;
// &:first-child { margin-left: 0; }
// &:last-child { margin-right: 0; }
// &:nth-child(1) {
// animation-delay: -0.32s;
// }
// &:nth-child(2) {
// animation-delay: -0.16s;
// }
// // nth-child(3) has no delay by default in the animation
// }
// }
// .spinner-dots-sm {
// // Override CSS variables for small size
// --spinner-dot-size: 6px;
// --spinner-spacing: 1px;
// // Width and height will adjust based on the new variable values if .spinner-dots uses them.
// }
// @keyframes spinner-dots-bounce {
// 0%, 80%, 100% {
// transform: scale(0);
// }
// 40% {
// transform: scale(1.0);
// }
// }
// Since this component relies on styles from valerie-ui.scss,
// ensure that valerie-ui.scss is imported in the application's global styles
// or in a higher-level component. If these styles are not present globally,
// the spinner will not render correctly.
// For Storybook, this means valerie-ui.scss needs to be imported in .storybook/preview.js or similar.
</style>