| name | dashboard-design |
| description | Web and App implementation guide for Dashboard Design. Trigger when user wants analytics-focused layouts, data visualization, and modular overview screens. |
| date_added | 2026-06-17 |
| risk | safe |
| source | self |
| source_type | self |
Dashboard Design
"Data at a glance. Organized, scannable, and highly functional."
When to Use
Use this sub-style when the user's request matches the aesthetic described above. This is a child reference of the design-it skill and is not meant to be triggered directly.
Core Principles
- Modular Grid: The screen is broken down into functional "widgets" or cards. Usually a sidebar on the left and a top nav.
- Data Hierarchy: The most important numbers (KPIs) are large and usually at the top. Charts take up the middle, and lists/tables are at the bottom.
- Muted Backgrounds: A soft grey or off-white background so the white data cards stand out clearly.
Visual DNA
- Colors: Minimalist Slate or Earth-Grounded Elegance. Avoid too many colors. Use red/green strictly for positive/negative trends.
- Typography: Clean, tabular sans-serifs (
Inter, Roboto Mono for numbers).
- Styling: Very subtle shadows or 1px borders to separate cards.
Web Implementation
- Use CSS Grid for the macro layout (Sidebar, Header, Main).
- CSS Example:
body {
background-color: #F8F9FA;
color: #212529;
font-family: 'Inter', sans-serif;
margin: 0;
}
.dashboard-layout {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 70px 1fr;
height: 100vh;
}
.sidebar {
grid-row: 1 / 3;
background-color: #ffffff;
border-right: 1px solid #e9ecef;
padding: 20px;
}
.header {
background-color: #ffffff;
border-bottom: 1px solid #e9ecef;
padding: 0 30px;
display: flex;
align-items: center;
}
.main-content {
padding: 30px;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
overflow-y: auto;
}
{
: ;
: ;
: ;
: solid ;
: (,,,);
}
{ : ; : ; }
{ : ; : ; : ; }
{ : ; }
App Implementation
SwiftUI
struct DashboardView: View {
let columns = [
GridItem(.adaptive(minimum: 150), spacing: 16)
]
var body: some View {
NavigationView {
ScrollView {
LazyVGrid(columns: columns, spacing: 16) {
KPICard(title: "Revenue", value: "$45,231", trend: "+12.5%", isPositive: true)
KPICard(title: "Active Users", value: "2,405", trend: "+4.1%", isPositive: true)
KPICard(title: "Churn Rate", value: "1.2%", trend: "-0.4%", isPositive: false)
KPICard(title: "Avg. Session", value: "4m 12s", trend: "+0.1%", isPositive: true)
}
.padding()
RoundedRectangle(cornerRadius: 12)
.fill(Color.white)
.frame(height: 250)
.overlay(Text("Chart Area").foregroundColor(.gray))
.padding(.horizontal)
}
.background((.systemGroupedBackground))
.navigationTitle()
}
}
}
: {
title:
value:
trend:
isPositive:
body: {
(alignment: .leading, spacing: ) {
(title).font(.subheadline).foregroundColor(.secondary)
(value).font(.title2).fontWeight(.bold)
(trend)
.font(.caption)
.fontWeight(.semibold)
.foregroundColor(isPositive .green : .red)
}
.padding()
.frame(maxWidth: .infinity, alignment: .leading)
.background(.white)
.cornerRadius()
.shadow(color: .black.opacity(), radius: , y: )
}
}
- Dashboards require
.adaptive grids. LazyVGrid handles rearranging 4 cards in a row on iPad down to 2 cards on iPhone automatically.
- Use
Color(UIColor.systemGroupedBackground) to provide that subtle off-white contrast against stark white cards.
Flutter
class DashboardScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF8F9FA),
appBar: AppBar(
title: const Text('Overview', style: TextStyle(color: Colors.black)),
backgroundColor: Colors.white,
elevation: 1,
),
// On tablets, use a Row with NavigationRail. On mobile, use Drawer.
drawer: const Drawer(),
body: CustomScrollView(
slivers: [
SliverPadding(
padding: const EdgeInsets.all(16),
sliver: SliverGrid.extent(
maxCrossAxisExtent: 200, // Adapts layout based on width
mainAxisSpacing: 16,
crossAxisSpacing: 16,
childAspectRatio: 1.5,
children: [
_buildKPI('Revenue', '\$45,231', '+12.5%', true),
_buildKPI('Active Users', '2,405', '+4.1%', true),
_buildKPI('Churn Rate', '1.2%', '-0.4%', false),
_buildKPI('Avg. Session', '4m 12s', '+0.1%', true),
],
),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 16),
sliver: SliverToBoxAdapter(
child: Container(
height: 250,
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12)),
child: const Center(child: Text('Chart Area', style: TextStyle(color: Colors.grey))),
),
),
),
],
),
);
}
Widget _buildKPI(String title, String value, String trend, bool isPositive) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey[200]!),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(title, style: const TextStyle(color: Colors.grey, fontSize: 14)),
const SizedBox(height: 8),
Text(value, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
Text(trend, style: TextStyle(color: isPositive ? Colors.green : Colors.red, fontWeight: FontWeight.w600)),
],
),
);
}
}
SliverGrid.extent with a maxCrossAxisExtent is the responsive magic bullet for Flutter dashboards. It handles varying screen widths flawlessly.
- For charts, the
fl_chart package is the gold standard in Flutter.
React Native
const DashboardScreen = () => {
return (
<ScrollView style={{ flex: 1, backgroundColor: '#F8F9FA' }}>
<View style={{ padding: 16, flexDirection: 'row', flexWrap: 'wrap', gap: 16 }}>
<KPICard title="Revenue" value="$45,231" trend="+12.5%" isPositive={true} />
<KPICard title="Users" value="2,405" trend="+4.1%" isPositive={true} />
<KPICard title="Churn" value="1.2%" trend="-0.4%" isPositive={false} />
<KPICard title="Session" value="4m 12s" = = />
Chart Area
);
};
= () => (
);
- To make responsive flex grids in React Native, use
flexDirection: 'row', flexWrap: 'wrap', and set the children to flexBasis: '47%'.
- For heavy data visualization, look into
victory-native or @shopify/react-native-skia.
Jetpack Compose
@Composable
fun DashboardScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFFF8F9FA))
.verticalScroll(rememberScrollState())
) {
Text(
text = "Overview",
style = MaterialTheme.typography.headlineSmall,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(16.dp)
)
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 150.dp),
contentPadding = PaddingValues(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
modifier = Modifier.heightIn(max = 400.dp)
) {
item { KPICard("Revenue", "$45,231", "+12.5%", true) }
item { KPICard("Active Users", "2,405", "+4.1%", true) }
item { KPICard("Churn Rate", "1.2%", "-0.4%", false) }
item { KPICard("Avg. Session", "4m 12s", "+0.1%", true) }
}
Spacer(Modifier.height(16.dp))
Box(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
.height(250.dp)
.background(Color.White, RoundedCornerShape(12.dp))
.border(dp, Color(), RoundedCornerShape(dp)),
contentAlignment = Alignment.Center
) {
Text(, color = Color.Gray)
}
Spacer(Modifier.height(dp))
}
}
{
Column(
modifier = Modifier
.background(Color.White, RoundedCornerShape(dp))
.border(dp, Color(), RoundedCornerShape(dp))
.padding(dp)
) {
Text(title, color = Color.Gray, fontSize = sp)
Spacer(Modifier.height(dp))
Text(value, fontSize = sp, fontWeight = FontWeight.Bold)
Spacer(Modifier.height(dp))
Text(trend, color = (isPositive) Color() Color(), fontWeight = FontWeight.SemiBold, fontSize = sp)
}
}
GridCells.Adaptive(minSize = 150.dp) creates the responsive card layout automatically.
- Warning: Nesting
LazyVerticalGrid inside a Column with .verticalScroll can cause height calculation issues. You must use .heightIn(max=...) on the grid, or completely convert the entire layout to a single LazyVerticalGrid where the chart is just a GridItemSpan(maxLineSpan) element.
Do's and Don'ts
- DO: Right-align numbers in tables so they are easier to scan and compare.
- DON'T: Clutter cards with unnecessary decorative images. The data is the decoration.
Limitations
- This is a styling reference and does not replace enprojectnment-specific validation, accessibility testing, or expert review.
- Ensure appropriate contrast ratios and responsive behaviors are verified separately.