rijal-footable
v0.0.3
Published
making tables not war
Maintainers
Readme
FooTable Components
This is a Vue 3 conversion of the React table components with enhanced accessibility, centralized styling system, and full support for colspan and rowspan attributes.
🚀 Key Features
- ✅ Accessibility First: Full ARIA support, keyboard navigation, screen reader friendly
- ✅ Centralized Styling: Configurable theme system with TypeScript support
- ✅ Colspan/Rowspan: Full support for complex table layouts
- ✅ Vue 3 + TypeScript: Modern composition API with type safety
- ✅ Responsive Design: Mobile-friendly with Tailwind CSS
Components
Basic Components
FooTable.vue- Main table wrapper with accessibility featuresTableHead.vue- Semantic table header with proper rolesTableBody.vue- Table body wrapperTableRow.vue- Table row with variant supportTableColumn.vue- Table cell (th/td) with colspan/rowspan and accessibilityTableSorter.vue- Sort indicator with ARIA labelsTableDataRow.vue- Special row for loading/empty states
Advanced Components
CompactTable.vue- Complete table with sorting and paginationTablePagination.vue- Accessible pagination componentuseTable.ts- Composition API hook for table state management
Styling System
tableStyles.ts- Centralized styling configurationuseTableStyles.ts- Composable for reactive styling
🎨 Styling System
Quick Start with Default Styling
<template>
<FooTable>
<TableHead>
<TableRow>
<TableColumn variant="head">Name</TableColumn>
<TableColumn variant="head">Email</TableColumn>
</TableRow>
</TableHead>
<TableBody>
<TableRow v-for="user in users" :key="user.id" variant="hover">
<TableColumn>{{ user.name }}</TableColumn>
<TableColumn>{{ user.email }}</TableColumn>
</TableRow>
</TableBody>
</FooTable>
</template>
<script setup>
import {
FooTable,
TableHead,
TableBody,
TableRow,
TableColumn,
} from "./FooTable"
</script>Custom Styling Configuration
<template>
<div>
<!-- Your tables will use the custom theme -->
<FooTable>
<!-- table content -->
</FooTable>
</div>
</template>
<script setup>
import { provideTableStyles } from "./VueTable/useTableStyles"
import { modernTableStyles } from "./VueTable/tableStyles"
// Provide custom styling for all child table components
provideTableStyles(modernTableStyles)
</script>Available Themes
import {
defaultTableStyles, // Standard gray theme
modernTableStyles, // Slate-based modern theme
compactTableStyles, // Compact spacing theme
} from "./VueTable/tableStyles"Creating Custom Themes
import { createTableStyles } from "./VueTable/tableStyles"
const myCustomTheme = createTableStyles({
table: {
base: "w-full text-sm border-2 border-blue-500",
},
head: {
base: "bg-blue-100 text-blue-900 font-bold",
},
row: {
hover: "hover:bg-blue-50 transition-colors",
},
})🔧 SonarQube Compliance
Problem Resolved
The SonarQube warning "Add <th> headers to this <Footable>" (Web:S5256) is now resolved.
What We Fixed
- ✅ All tables have proper
<thead>sections with<th>elements - ✅ Header cells use
role="columnheader"andscope="col" - ✅ Tables have
role="table"and descriptivearia-label - ✅ Sortable headers include
aria-sortandtabindexattributes - ✅ All table sections have appropriate ARIA roles
Before (SonarQube Warning)
<Footable>
<tbody>
<tr>
<td>Name</td>
<!-- ❌ Should be <th> -->
<td>Email</td>
</tr>
</tbody>
</Footable>After (SonarQube Compliant)
<table role="table" aria-label="Data table">
<thead role="rowgroup">
<tr role="row">
<th role="columnheader" scope="col">Name</th>
<!-- ✅ Proper header -->
<th role="columnheader" scope="col">Email</th>
</tr>
</thead>
<tbody role="rowgroup">
<!-- data rows -->
</tbody>
</Footable>📋 Usage Examples
Basic Table with Accessibility
<template>
<Table aria-label="Employee information">
<TableHead>
<TableRow>
<TableColumn variant="head" id="name">Name</TableColumn>
<TableColumn variant="head" id="email">Email</TableColumn>
<TableColumn variant="head" id="dept">Department</TableColumn>
</TableRow>
</TableHead>
<TableBody>
<TableRow v-for="emp in employees" :key="emp.id" variant="hover">
<TableColumn>{{ emp.name }}</TableColumn>
<TableColumn>{{ emp.email }}</TableColumn>
<TableColumn>{{ emp.department }}</TableColumn>
</TableRow>
</TableBody>
</FooTable>
</template>Table with Colspan
<template>
<FooTable>
<TableHead>
<TableRow>
<TableColumn variant="head">Name</TableColumn>
<TableColumn variant="head" :col-span="2"
>Contact Information</TableColumn
>
</TableRow>
<TableRow>
<TableColumn variant="head">Full Name</TableColumn>
<TableColumn variant="head">Email</TableColumn>
<TableColumn variant="head">Phone</TableColumn>
</TableRow>
</TableHead>
<TableBody>
<TableRow variant="hover">
<TableColumn>John Doe</TableColumn>
<TableColumn>[email protected]</TableColumn>
<TableColumn>555-0123</TableColumn>
</TableRow>
</TableBody>
</FooTable>
</template>Table with Rowspan
<template>
<FooTable>
<TableHead>
<TableRow>
<TableColumn variant="head">Department</TableColumn>
<TableColumn variant="head">Employee</TableColumn>
<TableColumn variant="head">Position</TableColumn>
</TableRow>
</TableHead>
<TableBody>
<TableRow variant="hover">
<TableColumn :row-span="3">Engineering</TableColumn>
<TableColumn>John Doe</TableColumn>
<TableColumn>Senior Developer</TableColumn>
</TableRow>
<TableRow variant="hover">
<TableColumn>Jane Smith</TableColumn>
<TableColumn>Frontend Developer</TableColumn>
</TableRow>
<TableRow variant="hover">
<TableColumn>Bob Johnson</TableColumn>
<TableColumn>DevOps Engineer</TableColumn>
</TableRow>
</TableBody>
</FooTable>
</template>Sortable CompactTable
<template>
<CompactTable
:columns="columns"
:data="data"
:pagination="paginationOptions"
:loading="loading"
aria-label="User management table"
/>
</template>
<script setup>
import { CompactTable } from "./VueTable"
const columns = [
{ id: "name", label: "Name", sortable: true, ordering: 1 },
{ id: "email", label: "Email", sortable: true, ordering: 2, align: "left" },
{
id: "role",
label: "Role",
sortable: false,
ordering: 3,
align: "center",
},
]
const data = [
{ name: "John Doe", email: "[email protected]", role: "Admin" },
{ name: "Jane Smith", email: "[email protected]", role: "User" },
]
</script>🎛️ Component Props
TableColumn Props
variant?: "head" | "body" | "footer"- Determines if it renders asthortdid?: string- Unique identifier for the columnalign?: "left" | "right" | "center"- Text alignmentclassName?: string- Additional CSS classescolSpan?: number- Number of columns to span horizontallyrowSpan?: number- Number of rows to span verticallysort?: (id: string) => void- Sort function for clickable headerssortDirection?: 'asc' | 'desc' | null- Current sort direction for ARIA
TableRow Props
className?: string- Additional CSS classesvariant?: 'base' | 'hover' | 'striped'- Row styling variant
Table Props
ariaLabel?: string- Accessible label for the tableariaDescribedBy?: string- ID of element describing the table
CompactTable Column Interface
interface ColumnInterface {
label: string
id: string
sortable?: boolean
ordering?: number
colSpan?: number
rowSpan?: number
align?: AlignmentType
}🚀 Installation
- Copy the VueTable directory to your Vue project
- Import the components you need
- Ensure Tailwind CSS is configured in your project
- Optionally configure custom styling themes
📦 What's Included
VueTable/
├── Table.vue # Main table component
├── TableHead.vue # Table header
├── TableBody.vue # Table body
├── TableRow.vue # Table row
├── TableColumn.vue # Table cell with accessibility
├── TableSorter.vue # Sort indicator
├── TableDataRow.vue # Loading/empty states
├── TablePagination.vue # Pagination component
├── CompactTable.vue # Complete table solution
├── useTable.ts # Table state management
├── tableStyles.ts # Styling configuration
├── useTableStyles.ts # Styling composable
├── index.ts # Export file
├── README.md # This file
├── TableExample.vue # Usage examples
└── StyleTest.vue # Styling system test🔄 Migration from Previous Version
If you're upgrading from the previous version:
- Styling: Replace hardcoded classes with the new styling system
- Accessibility: Add
aria-labelprops to your tables - Headers: Ensure you're using
TableColumnwithvariant="head"inTableHead - Sorting: Pass
sortDirectionprop for proper ARIA attributes
🌟 Key Improvements
- SonarQube Compliance: No more Web:S5256 warnings
- Better Accessibility: Screen reader friendly with proper ARIA
- Centralized Styling: Easy theming and customization
- Type Safety: Full TypeScript support
- Performance: Optimized with Vue 3 Composition API
- Maintainability: Clean, modular architecture
🤝 Contributing
The components follow Vue 3 best practices and accessibility guidelines. When contributing:
- Maintain ARIA compliance
- Use the centralized styling system
- Include TypeScript types
- Test with screen readers
- Ensure SonarQube compliance
