# Component Styling Guidelines - ROA2WEB

**Last Updated:** 2025-11-18
**Phase:** 3 - PrimeVue Centralization

---

## 🎯 Core Principles

### 1. **NEVER Use `:deep()` in Components**

❌ **NEVER Do This:**
```vue
<style scoped>
:deep(.p-inputtext) {
  border: 2px solid #3b82f6 !important;
}
</style>
```

✅ **Always Do This:**
PrimeVue components are styled globally in `assets/css/vendor/primevue-overrides.css`.

Use classes, not deep overrides:
```vue
<template>
  <InputText class="form-input" />
</template>

<style scoped>
.form-input {
  /* Component-specific spacing/layout only */
  margin-bottom: var(--space-md);
}
</style>
```

---

### 2. **Use Design Tokens, Not Hardcoded Values**

❌ **NEVER Do This:**
```vue
<style scoped>
.my-button {
  background: #3b82f6;
  color: #ffffff;
  border: 1px solid #e5e7eb;
}
</style>
```

✅ **Always Do This:**
```vue
<style scoped>
.my-button {
  background: var(--color-primary);
  color: var(--color-text-inverse);
  border: 1px solid var(--color-border);
}
</style>
```

**Available Design Tokens:** See `assets/css/core/variables.css`

---

### 3. **Minimize `!important` Usage**

#### ✅ **Acceptable Use Cases:**

1. **Global PrimeVue Overrides** (`primevue-overrides.css`):
```css
.p-inputtext {
  border: 2px solid var(--color-border) !important;
}
```

2. **Print Styles** (`@media print`):
```css
@media print {
  .dashboard-table th {
    background: var(--color-bg-muted) !important;
    color: #000 !important;
  }
}
```

3. **Critical PrimeVue Component Overrides** (rare):
```vue
<style scoped>
.login-button {
  /* Overriding PrimeVue Button defaults intentionally */
  background: var(--color-primary-light) !important;
}
</style>
```

#### ❌ **NEVER Do This:**
```vue
<style scoped>
.my-text {
  color: red !important;  /* No justification for !important */
  font-size: 16px !important;
}
</style>
```

---

## 📁 File Organization

### Where to Put Styles

1. **Component-Specific Styles** → `<style scoped>` in component
   - Layout (flexbox, grid)
   - Component-specific spacing
   - Custom animations

2. **Global Patterns** → `assets/css/patterns/`
   - Reusable UI patterns
   - Interactive states
   - Dashboard metrics

3. **PrimeVue Overrides** → `assets/css/vendor/primevue-overrides.css`
   - ALL PrimeVue component styling
   - Global theme customization

4. **App-Wide Row Styling** → `App.vue` (unscoped)
   - DataTable row classes (`.invoice-paid`, `.bank-row`, etc.)
   - Status badges
   - Global utilities

---

## 🎨 PrimeVue Styling Strategy

### Global Override File

**Location:** `src/assets/css/vendor/primevue-overrides.css`

**Purpose:** Single source of truth for all PrimeVue component styling

**Example:**
```css
/* Input Components */
.p-inputtext,
.p-password input {
  border: 2px solid var(--color-border) !important;
  border-radius: var(--radius-md) !important;
}

/* Focus States */
.p-inputtext:focus {
  border-color: var(--color-primary) !important;
  box-shadow: var(--focus-ring) !important;
}
```

### Component Usage

```vue
<template>
  <!-- PrimeVue components automatically styled by global overrides -->
  <InputText v-model="username" placeholder="Username" />

  <!-- Add component-specific classes for layout/spacing only -->
  <InputText v-model="email" class="email-input" />
</template>

<style scoped>
/* Component-specific layout ONLY - no PrimeVue overrides */
.email-input {
  margin-top: var(--space-md);
  width: 100%;
}
</style>
```

---

## 🔄 DataTable Row Styling

### Global Row Classes (App.vue)

Custom row classes for DataTables are defined globally in `App.vue`:

```css
/* src/App.vue - unscoped styles */
.p-datatable .p-datatable-tbody > tr.invoice-paid {
  background-color: var(--green-50);
  color: var(--green-900);
}

.p-datatable .p-datatable-tbody > tr.invoice-overdue {
  background-color: var(--red-50);
  color: var(--red-900);
}

.p-datatable .p-datatable-tbody > tr.bank-row {
  background-color: var(--blue-50);
}

.p-datatable .p-datatable-tbody > tr.cash-row {
  background-color: var(--yellow-50);
}
```

### Component Usage

```vue
<script setup>
const getRowClass = (data) => {
  if (data.status === 'paid') return 'invoice-paid';
  if (data.status === 'overdue') return 'invoice-overdue';
  return '';
};
</script>

<template>
  <DataTable :value="invoices" :rowClass="getRowClass">
    <!-- columns -->
  </DataTable>
</template>

<style scoped>
/* NO :deep() overrides needed! Row classes defined in App.vue */
</style>
```

---

## 📐 Design Tokens Reference

### Colors

```css
/* Primary */
--color-primary: #2563eb
--color-primary-light: #3b82f6
--color-primary-dark: #1d4ed8

/* Semantic */
--color-success: #059669
--color-warning: #d97706
--color-error: #dc2626
--color-info: #0891b2

/* Text */
--color-text: #111827
--color-text-secondary: #6b7280
--color-text-muted: #9ca3af
--color-text-inverse: #ffffff

/* Backgrounds */
--color-bg: #ffffff
--color-bg-secondary: #f9fafb
--color-bg-muted: #f3f4f6

/* Borders */
--color-border: #e5e7eb
--color-border-light: #f3f4f6
--color-border-dark: #d1d5db
```

### Spacing

```css
--space-xs: 0.25rem   /* 4px */
--space-sm: 0.5rem    /* 8px */
--space-md: 1rem      /* 16px */
--space-lg: 1.5rem    /* 24px */
--space-xl: 2rem      /* 32px */
--space-2xl: 3rem     /* 48px */
```

### Border Radius

```css
--radius-sm: 0.25rem  /* 4px */
--radius-md: 0.5rem   /* 8px */
--radius-lg: 0.75rem  /* 12px */
--radius-xl: 1rem     /* 16px */
--radius-full: 9999px
```

### Transitions

```css
--transition-fast: 150ms ease
--transition-normal: 250ms ease
--transition-slow: 350ms ease
```

**Full Reference:** `src/assets/css/core/variables.css`

---

## ✅ Phase 3 Achievements

- ✅ **Zero `:deep()` in Components** - All migrated to global CSS
- ✅ **Zero Hardcoded CSS Colors** - All use design tokens
- ✅ **Centralized PrimeVue Styling** - Single source in `primevue-overrides.css`
- ✅ **Documented `!important` Usage** - Clear acceptable use cases
- ✅ **Build Successful** - Zero breaking changes

---

## 🚫 Common Mistakes to Avoid

### 1. Duplicating Global Styles

❌ **Wrong:**
```vue
<!-- InvoicesView.vue -->
<style scoped>
:deep(.p-datatable .p-datatable-tbody > tr.invoice-paid) {
  background-color: var(--green-50); /* Already in App.vue! */
}
</style>
```

✅ **Correct:**
```vue
<!-- InvoicesView.vue -->
<style scoped>
/* Row styling defined globally in App.vue */
</style>
```

### 2. Overriding PrimeVue in Components

❌ **Wrong:**
```vue
<style scoped>
:deep(.p-button) {
  padding: 12px 24px;
}
</style>
```

✅ **Correct:**
Add to `assets/css/vendor/primevue-overrides.css` instead.

### 3. Using Hardcoded Colors

❌ **Wrong:**
```vue
<style scoped>
.card {
  background: #ffffff;
  border: 1px solid #e5e7eb;
}
</style>
```

✅ **Correct:**
```vue
<style scoped>
.card {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
}
</style>
```

---

## 📚 Related Documentation

- **Form Patterns:** `docs/FORM_TEMPLATE.md`
- **Design Tokens:** `src/assets/css/core/variables.css`
- **PrimeVue Overrides:** `src/assets/css/vendor/primevue-overrides.css`
- **Phase 3 Plan:** `features/phases/phase-3-primevue.md`

---

**Questions?** Check the CSS Refactoring documentation in `features/`
