Skip to content

Styling Guide

Styling conventions and patterns for IONFLOW Frontend using Tailwind CSS and PrimeVue.

IONFLOW uses:

  • Tailwind CSS 4 - Utility-first CSS framework
  • PrimeVue 4 (Unstyled) - UI components with Volt theme
  • CSS Variables - Theme customization

Tailwind is configured in tailwind.config.js:

module.exports = {
content: [
'./index.html',
'./src/**/*.{vue,js,ts,jsx,tsx}',
],
theme: {
extend: {
colors: {
primary: 'var(--primary-color)',
surface: 'var(--surface-card)',
},
},
},
plugins: [],
};
<!-- Flex layout -->
<div class="flex items-center justify-between gap-4">
<span>Left</span>
<span>Right</span>
</div>
<!-- Grid layout -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<Card v-for="item in items" :key="item.id" />
</div>
<!-- Container with padding -->
<div class="container mx-auto px-4 py-6">
<!-- Content -->
</div>
<!-- Margin and padding -->
<div class="m-4 p-4">Margin and padding</div>
<div class="mx-auto my-2">Horizontal auto, vertical 2</div>
<div class="space-y-4">Vertical spacing between children</div>
<!-- Mobile-first approach -->
<div class="w-full md:w-1/2 lg:w-1/3">
Responsive width
</div>
<!-- Hide/show on breakpoints -->
<div class="hidden md:block">Desktop only</div>
<div class="block md:hidden">Mobile only</div>

PrimeVue is configured in unstyled mode with Volt presets in src/assets/primevue/.

<template>
<!-- Basic button -->
<Button label="Save" />
<!-- Button variants -->
<Button label="Primary" />
<Button label="Secondary" severity="secondary" />
<Button label="Success" severity="success" />
<Button label="Danger" severity="danger" />
<!-- With icons -->
<Button icon="pi pi-check" />
<Button label="Save" icon="pi pi-save" />
<!-- Sizes -->
<Button label="Small" size="small" />
<Button label="Large" size="large" />
</template>
<!-- Add custom classes -->
<Button
label="Custom"
class="w-full mt-4"
/>
<!-- Override with pt (Pass Through) -->
<InputText
:pt="{
root: { class: 'custom-input-class' }
}"
/>
:root {
/* Primary colors */
--primary-color: #3B82F6;
--primary-color-text: #ffffff;
/* Surface colors */
--surface-ground: #f8f9fa;
--surface-card: #ffffff;
--surface-border: #dee2e6;
/* Text colors */
--text-color: #495057;
--text-color-secondary: #6c757d;
/* Focus */
--focus-ring: 0 0 0 2px #ffffff, 0 0 0 4px var(--primary-color);
}
.dark {
--surface-ground: #121212;
--surface-card: #1e1e1e;
--surface-border: #383838;
--text-color: #ffffff;
--text-color-secondary: #b3b3b3;
}
<div class="bg-[var(--surface-card)] text-[var(--text-color)]">
Using CSS variables
</div>
<template>
<div class="bg-surface-card rounded-lg shadow-sm border border-surface-border p-4">
<h3 class="text-lg font-semibold text-surface-900">Title</h3>
<p class="text-surface-600 mt-2">Content</p>
</div>
</template>
<template>
<form class="space-y-4">
<div class="flex flex-col gap-2">
<label class="text-sm font-medium">Label</label>
<InputText v-model="value" class="w-full" />
<small class="text-red-500">Error message</small>
</div>
<div class="flex justify-end gap-2">
<Button label="Cancel" severity="secondary" />
<Button label="Save" />
</div>
</form>
</template>
<template>
<ul class="divide-y divide-surface-border">
<li
v-for="item in items"
:key="item.id"
class="py-3 px-4 hover:bg-surface-hover cursor-pointer"
>
{{ item.name }}
</li>
</ul>
</template>
<!-- Icon classes -->
<i class="pi pi-check"></i>
<i class="pi pi-times"></i>
<i class="pi pi-user"></i>
<!-- With size -->
<i class="pi pi-check text-xl"></i>
<i class="pi pi-check text-2xl"></i>
<!-- In buttons -->
<Button icon="pi pi-save" />
<Button icon="pi pi-trash" severity="danger" />

Common icons:

IconClassUsage
pi-checkSuccess, confirm
pi-timesClose, cancel
+pi-plusAdd, create
pi-pencilEdit
🗑pi-trashDelete
🔍pi-searchSearch
pi-cogSettings
👤pi-userUser
BreakpointSizeClass Prefix
sm640pxsm:
md768pxmd:
lg1024pxlg:
xl1280pxxl:
2xl1536px2xl:
<template>
<!-- Stack on mobile, side by side on desktop -->
<div class="flex flex-col md:flex-row gap-4">
<aside class="w-full md:w-64">Sidebar</aside>
<main class="flex-1">Content</main>
</div>
</template>
  • Use PrimeVue components for UI elements
  • Use Tailwind utilities for layout
  • Use CSS variables for theming
  • Follow mobile-first approach
  • Keep custom CSS minimal
  • Don’t create custom buttons/inputs
  • Don’t use inline styles
  • Don’t hardcode colors
  • Don’t skip responsive design
  • Don’t override PrimeVue heavily