Card Component
Overview
A flexible card container component with optional header, toolbar, footer, and color customization.
Location: resources/components/card.vue
Type: Simple Component
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
title | String | Yes | - | Card header title |
color | String | No | - | Bootstrap color class for header (e.g., cyan-2, green-10) |
Computed
| Property | Description |
|---|---|
headerClass | Builds CSS classes for header including color |
whiteTitle | Auto-determines if title should be white based on color darkness |
Slots
| Slot | Description |
|---|---|
| Default | Main card body content |
toolbar | Toolbar buttons in header (right-aligned) |
footer | Card footer content |
Usage
Basic Card
vue
<card title="User Information">
<p>Card content goes here...</p>
</card>Card with Color
vue
<card title="Dashboard Statistics" color="teal-2">
<p>Statistics content...</p>
</card>Card with Toolbar
vue
<card title="Staff" color="teal-2">
<template #toolbar>
<div class="btn btn-sm btn-success" @click="addContact">
<i class="fa fas fa-plus"></i> New
</div>
</template>
<!-- Main content -->
<vue-datatable>...</vue-datatable>
</card>Card with Footer
vue
<card title="Report">
<p>Report content...</p>
<template #footer>
<div class="btn btn-primary">Download PDF</div>
</template>
</card>Card with Multiple Toolbar Buttons
vue
<card title="Employees" color="blue-3">
<template #toolbar>
<div class="btn btn-sm btn-primary mr-1" @click="exportData">
<i class="fas fa-download"></i> Export
</div>
<div class="btn btn-sm btn-success" @click="addEmployee">
<i class="fas fa-plus"></i> Add
</div>
</template>
<p>Employee list content...</p>
</card>Real Examples from OATERS
blade
<card title="{{trans('ruby::words.staff')}}" color="teal-2">
<template #toolbar>
<div class="btn btn-sm btn-success" title="{{trans('ruby::contacts.new')}}" @click="addContact"><i class="fa fas fa-plus align-middle"></i><span class="d-none d-sm-inline-block ml-2">{{trans('ruby::contacts.new')}}</span></div>
</template>
<vue-datafilter :cols="4" datatable-ref="contactsTable">
<!-- filters -->
</vue-datafilter>
<x-ruby::tables.contacts/>
</card>blade
<card title="{{trans('sapphire::admin.tenants.new')}}" color="green-10">
<vue-table id="latest-tenants" class="table-striped table-hover mb-0">
<!-- table content -->
</vue-table>
</card>Component Registration
javascript
import {createApp} from "vue";
import Card from "@/components/card.vue";
let app = createApp({
methods: {
addItem() {
console.log('Add item clicked');
}
}
});
app.component('Card', Card);
app.mount('#app');Features
- ✅ Automatic white text for dark colors (colors 1-5)
- ✅ Flexible layout with slots
- ✅ Bootstrap 4 card structure
- ✅ Toolbar with max-height constraint (28px)
- ✅ Optional header, body, and footer sections
Color System
The component uses a numeric color naming convention:
| Color Range | Text Color | Use Case |
|---|---|---|
color-1 to color-5 | White | Dark backgrounds |
color-6 to color-10 | Black (default) | Light backgrounds |
Examples
vue
<!-- Dark header with white text -->
<card title="Dark Card" color="blue-2">...</card>
<!-- Light header with default text -->
<card title="Light Card" color="blue-8">...</card>Available Colors
Common Bootstrap color variants (with numeric suffixes 1-10):
grey-1throughgrey-10red-1throughred-10orange-1throughorange-10yellow-1throughyellow-10green-1throughgreen-10teal-1throughteal-10cyan-1throughcyan-10blue-1throughblue-10purple-1throughpurple-10pink-1throughpink-10
Styling
Component Styles
css
.btn-toolbar {
max-height: 28px;
}Custom Styling
Override card styles in your application:
css
.card {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.card-header {
font-weight: bold;
border-bottom: 2px solid;
}
.card-body {
padding: 1.5rem;
}Best Practices
Use toolbar slot for actions: Keep header clean with toolbar slot
vue<card title="Data"> <template #toolbar> <button @click="refresh">Refresh</button> </template> </card>Color naming: Use numeric suffixes (1-10) where lower = darker
vue<card title="Important" color="red-3">...</card>Footer for actions: Use footer slot for form buttons or actions
vue<card title="Form"> <form>...</form> <template #footer> <button type="submit">Save</button> </template> </card>Semantic titles: Use descriptive, user-friendly titles
vue<card title="Recent Activity">...</card>Consistent colors: Maintain color consistency across similar card types
vue<!-- All data tables use teal --> <card title="Users" color="teal-2">...</card> <card title="Products" color="teal-2">...</card>
Common Patterns
Data Table Card
vue
<card title="Employees" color="blue-3">
<template #toolbar>
<div class="btn btn-sm btn-success" @click="addEmployee">
<i class="fas fa-plus"></i> Add Employee
</div>
</template>
<vue-datatable ref="employeeTable">
<dt-column name="name" data="name">Name</dt-column>
<dt-column name="email" data="email">Email</dt-column>
<dt-column name="department" data="department">Department</dt-column>
</vue-datatable>
</card>Form Card
vue
<card title="Edit Profile" color="green-3">
<form @submit.prevent="saveProfile">
<div class="form-group">
<label>Name</label>
<input v-model="profile.name" class="form-control">
</div>
<div class="form-group">
<label>Email</label>
<input v-model="profile.email" class="form-control">
</div>
</form>
<template #footer>
<button type="button" class="btn btn-secondary" @click="cancel">
Cancel
</button>
<button type="submit" class="btn btn-primary" @click="saveProfile">
Save Changes
</button>
</template>
</card>Statistics Card
vue
<card title="Total Sales" color="cyan-2">
<h2 class="text-center mb-0">${{ totalSales }}</h2>
<p class="text-center text-muted">This Month</p>
</card>Collapsible Card
vue
<card title="Advanced Settings" color="grey-8">
<template #toolbar>
<div class="btn btn-sm btn-outline-secondary" @click="toggleCollapse">
<i :class="collapsed ? 'fas fa-chevron-down' : 'fas fa-chevron-up'"></i>
</div>
</template>
<div v-show="!collapsed">
<p>Advanced settings content...</p>
</div>
</card>Loading State Card
vue
<card title="Dashboard Data" color="purple-3">
<div v-if="loading" class="text-center py-5">
<i class="fas fa-spinner fa-spin fa-3x"></i>
<p class="mt-3">Loading...</p>
</div>
<div v-else>
<p>{{ data }}</p>
</div>
</card>Multi-section Card
vue
<card title="User Profile" color="blue-4">
<div class="card-section">
<h5>Personal Information</h5>
<p>Name: {{ user.name }}</p>
<p>Email: {{ user.email }}</p>
</div>
<hr>
<div class="card-section">
<h5>Account Settings</h5>
<p>Status: {{ user.status }}</p>
<p>Role: {{ user.role }}</p>
</div>
<template #footer>
<div class="btn btn-primary" @click="editProfile">Edit Profile</div>
</template>
</card>Layout Patterns
Card Grid
vue
<div class="row">
<div class="col-md-6">
<card title="Card 1" color="blue-3">
<p>Content 1</p>
</card>
</div>
<div class="col-md-6">
<card title="Card 2" color="green-3">
<p>Content 2</p>
</card>
</div>
</div>Full Width Card
vue
<div class="container-fluid">
<card title="Full Width Dashboard" color="grey-8">
<p>Full width content...</p>
</card>
</div>Stacked Cards
vue
<div class="card-stack">
<card title="Recent Activity" color="cyan-8">
<p>Activity feed...</p>
</card>
<card title="Notifications" color="orange-8" class="mt-3">
<p>Notification list...</p>
</card>
<card title="Tasks" color="green-8" class="mt-3">
<p>Task list...</p>
</card>
</div>Troubleshooting
Header styles not applying
- Confirm color class exists in your CSS (e.g.,
bg-cyan-2) - Check if custom CSS is overriding card styles
- Verify Bootstrap 4 is loaded
White title not showing
- Verify you're using colors 1-5 (darker colors)
- Check that color naming follows the pattern:
color-1tocolor-10 - Ensure no CSS is overriding text color
Toolbar buttons overflowing
- Check
max-height: 28pxconstraint on.btn-toolbar - Use
btn-smclass for toolbar buttons - Consider reducing number of toolbar buttons
Footer not displaying
- Verify you're using the
#footerslot - Check that slot content is not empty
- Ensure no CSS is hiding the footer
Card not responsive
- Wrap cards in Bootstrap grid columns
- Use responsive column classes (e.g.,
col-md-6) - Test on different screen sizes