Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Web and App implementation guide for Bento UI. Trigger when user wants modular grid cards, Apple-like dashboard style, or sections arranged like a bento box.
.claude/skills/lingxling-bento-ui/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 137% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 14% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 142% | 0% |
| case-08 | ✓→✗ | ▼ Worse | 93% | 0% |
| case-21 | ✓→✗ | ▼ Worse | 151% | 0% |
> "Everything in its right place. A highly structured, modular grid of distinct compartments."
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.
SF Pro, Inter). Headlines are usually bold and placed at the top-left or bottom-left of each compartment.css.bento-container { display: grid; grid-template-columns: repeat(4, 1fr); grid-auto-rows: 200px; gap: 24px; padding: 24px; background-color: var(--bg-primary); /* Slightly darker than cards */ } .bento-card { background-color: #fff; border-radius: 32px; /* Very large border radius */ padding: 32px; box-shadow: 0 4px 24px rgba(0,0,0,0.04); /* Optional: subtle 1px border for crispness */ border: 1px solid rgba(0,0,0,0.05); display: flex; flex-direction: column; justify-content: space-between; } /* Creating spans for different bento sizes */ .bento-span-2 { grid-column: span 2; } .bento-span-2-row { grid-row: span 2; } .bento-large { grid-column: span 2; grid-row: span 2; }
swiftstruct BentoGrid: View { let columns = [ GridItem(.flexible(), spacing: 16), GridItem(.flexible(), spacing: 16) ] var body: some View { ScrollView { LazyVGrid(columns: columns, spacing: 16) { // 2x1 Span (Full width) BentoCard(title: "Hero", color: .blue) .frame(height: 180) // 1x1 Spans BentoCard(title: "Stats", color: .green) .frame(height: 180) BentoCard(title: "Graph", color: .purple) .frame(height: 180) // 1x2 Span (Tall) BentoCard(title: "Activity", color: .orange) .frame(height: 376) // (180 * 2) + 16 spacing // 1x1 Spans next to the tall one VStack(spacing: 16) { BentoCard(title: "A", color: .pink).frame(height: 180) BentoCard(title: "B", color: .cyan).frame(height: 180) } } .padding(16) } .background(Color(.systemGroupedBackground)) } } struct BentoCard: View { let title: String let color: Color var body: some View { RoundedRectangle(cornerRadius: 24) .fill(Color(.secondarySystemGroupedBackground)) .overlay( Text(title).font(.headline).foregroundColor(color), alignment: .topLeading ) .padding(16) // Soft bento shadow .shadow(color: .black.opacity(0.04), radius: 12, x: 0, y: 4) } }
LazyVGrid for uniform grids.VStack and HStack inside the grid cells to fake the spans.cornerRadius (usually 24-32pt) and spacing (usually 16pt).dartimport 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; class BentoScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[100], body: SingleChildScrollView( padding: const EdgeInsets.all(16), child: StaggeredGrid.count( crossAxisCount: 4, // 4 columns total mainAxisSpacing: 16, crossAxisSpacing: 16, children: const [ // 2x1 (Full width in a 2-col layout, spans 4) StaggeredGridTile.count( crossAxisCellCount: 4, mainAxisCellCount: 2, child: BentoCard(title: 'Hero'), ), // 1x1 StaggeredGridTile.count( crossAxisCellCount: 2, mainAxisCellCount: 2, child: BentoCard(title: 'Stats'), ), // 1x1 StaggeredGridTile.count( crossAxisCellCount: 2, mainAxisCellCount: 2, child: BentoCard(title: 'Graph'), ), // 1x2 (Tall) StaggeredGridTile.count( crossAxisCellCount: 2, mainAxisCellCount: 4, child: BentoCard(title: 'Activity'), ), ], ), ), ); } } class BentoCard extends StatelessWidget { final String title; const BentoCard({required this.title}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(24), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.04), blurRadius: 12, offset: const Offset(0, 4), ), ], ), alignment: Alignment.topLeft, child: Text(title, style: const TextStyle(fontWeight: FontWeight.bold)), ); } }
flutter_staggered_grid_view package is practically mandatory for complex Bento grids in Flutter.StaggeredGridTile.count to explicitly declare the crossAxis and mainAxis span of each compartment.jsxconst BentoScreen = () => { return ( <ScrollView style={{ flex: 1, backgroundColor: '#F2F2F7' }} contentContainerStyle={{ padding: 16 }} > {/* 2x1 Span */} <View style={[styles.bentoCard, { height: 180, marginBottom: 16 }]}> <Text style={styles.title}>Hero</Text> </View> <View style={{ flexDirection: 'row', gap: 16, marginBottom: 16 }}> {/* 1x1 Spans */} <View style={[styles.bentoCard, { flex: 1, height: 180 }]}> <Text style={styles.title}>Stats</Text> </View> <View style={[styles.bentoCard, { flex: 1, height: 180 }]}> <Text style={styles.title}>Graph</Text> </View> </View> <View style={{ flexDirection: 'row', gap: 16 }}> {/* 1x2 Span (Tall) */} <View style={[styles.bentoCard, { flex: 1, height: 376 }]}> <Text style={styles.title}>Activity</Text> </View> <View style={{ flex: 1, gap: 16 }}> {/* Stacked 1x1s */} <View style={[styles.bentoCard, { height: 180 }]}> <Text style={styles.title}>A</Text> </View> <View style={[styles.bentoCard, { height: 180 }]}> <Text style={styles.title}>B</Text> </View> </View> </View> </ScrollView> ); }; const styles = StyleSheet.create({ bentoCard: { backgroundColor: '#FFFFFF', borderRadius: 24, padding: 24, shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.04, shadowRadius: 12, elevation: 2, }, title: { fontWeight: '700', fontSize: 18, } });
flexDirection: 'row' and vertical stacks.gap property in React Native flexbox makes this significantly easier than using margins.kotlin@Composable fun BentoGrid() { Column( modifier = Modifier .fillMaxSize() .background(Color(0xFFF2F2F7)) .verticalScroll(rememberScrollState()) .padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { // Full width BentoCard(title = "Hero", modifier = Modifier.fillMaxWidth().height(180.dp)) // Two columns Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) { BentoCard(title = "Stats", modifier = Modifier.weight(1f).height(180.dp)) BentoCard(title = "Graph", modifier = Modifier.weight(1f).height(180.dp)) } // Complex span: 1x2 left, two 1x1s right Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) { BentoCard(title = "Activity", modifier = Modifier.weight(1f).height(376.dp)) Column( modifier = Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(16.dp) ) { BentoCard(title = "A", modifier = Modifier.fillMaxWidth().height(180.dp)) BentoCard(title = "B", modifier = Modifier.fillMaxWidth().height(180.dp)) } } } } @Composable fun BentoCard(title: String, modifier: Modifier = Modifier) { Card( modifier = modifier, shape = RoundedCornerShape(24.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) ) { Text(title, fontWeight = FontWeight.Bold, modifier = Modifier.padding(24.dp)) } }
LazyVerticalGrid exists, for highly specific irregular bento layouts, manually building rows and columns with weight(1f) is often much more reliable.Arrangement.spacedBy(16.dp) on both Columns and Rows to ensure mathematically perfect gutters.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 48,453 | 54,592 | +13% | 1 | 1 | 0% | 8,244 | 11,320 | +37% | 0 | 0 | — |
case-02 | pass→pass | 15,826 | 17,630 | +11% | 1 | 1 | 0% | 3,092 | 7,096 | +129% | 0 | 0 | — |
case-03 | fail→pass | 13,282 | 8,855 | -33% | 1 | 1 | 0% | 1,972 | 4,674 | +137% | 0 | 0 | — |
case-04 | pass→pass | 39,089 | 35,755 | -9% | 1 | 1 | 0% | 8,223 | 9,053 | +10% | 0 | 0 | — |
case-05 | pass→pass | 35,443 | 29,640 | -16% | 1 | 1 | 0% | 5,932 | 8,187 | +38% | 0 | 0 | — |
case-06 | pass→pass | 43,972 | 38,492 | -12% | 1 | 1 | 0% | 8,138 | 9,563 | +18% | 0 | 0 | — |
case-07 | fail→pass | 48,247 | 28,381 | -41% | 1 | 1 | 0% | 8,225 | 9,338 | +14% | 0 | 0 | — |
case-08 | pass→fail | 15,895 | 18,714 | +18% | 1 | 1 | 0% | 3,066 | 5,910 | +93% | 0 | 0 | — |
case-09 | pass→pass | 16,882 | 15,583 | -8% | 1 | 1 | 0% | 2,648 | 5,618 | +112% | 0 | 0 | — |
case-10 | pass→pass | 16,172 | 15,726 | -3% | 1 | 1 | 0% | 2,640 | 5,487 | +108% | 0 | 0 | — |
case-11 | pass→pass | 15,040 | 10,098 | -33% | 1 | 1 | 0% | 3,079 | 5,196 | +69% | 0 | 0 | — |
case-12 | fail→pass | 11,175 | 9,912 | -11% | 1 | 1 | 0% | 2,129 | 5,145 | +142% | 0 | 0 | — |
case-13 | pass→pass | 21,224 | 18,212 | -14% | 1 | 1 | 0% | 3,291 | 5,997 | +82% | 0 | 0 | — |
case-14 | pass→pass | 13,835 | 14,543 | +5% | 1 | 1 | 0% | 2,211 | 6,103 | +176% | 0 | 0 | — |
case-15 | pass→pass | 45,869 | 37,050 | -19% | 1 | 1 | 0% | 8,081 | 11,316 | +40% | 0 | 0 | — |
case-16 | pass→pass | 14,974 | 15,817 | +6% | 1 | 1 | 0% | 2,245 | 5,844 | +160% | 0 | 0 | — |
case-17 | fail→fail | 49,600 | 30,015 | -39% | 1 | 1 | 0% | 8,226 | 10,079 | +23% | 0 | 0 | — |
case-18 | pass→pass | 24,186 | 14,598 | -40% | 1 | 1 | 0% | 3,654 | 5,866 | +61% | 0 | 0 | — |
case-19 | pass→pass | 4,063 | 4,226 | +4% | 1 | 1 | 0% | 711 | 3,694 | +420% | 0 | 0 | — |
case-20 | pass→pass | 25,088 | 38,817 | +55% | 1 | 1 | 0% | 4,143 | 9,805 | +137% | 0 | 0 | — |
case-21 | pass→fail | 16,142 | 31,461 | +95% | 1 | 1 | 0% | 3,399 | 8,541 | +151% | 0 | 0 | — |
case-22 | pass→pass | 17,196 | 19,104 | +11% | 1 | 1 | 0% | 2,927 | 7,177 | +145% | 0 | 0 | — |
case-23 | pass→pass | 22,064 | 23,260 | +5% | 1 | 1 | 0% | 3,799 | 7,673 | +102% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +4 percentage points is the difference between those two pass rates over the 23 comparable cases. 2 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.