widget-based-design – skill Thiết kế & UI cho agent AI
Hướng dẫn triển khai Widget-Based Design cho Web và App. Kích hoạt khi người dùng muốn các khối module hóa, thẩm mỹ màn hình chính iOS và các mini-app tùy chỉnh.
Cài skill widget-based-design bằng một lệnh
Chọn công cụ bạn đang dùng, copy lệnh và dán vào terminal. Skill sẽ nằm trong thư mục skills của công cụ đó và sẵn sàng dùng ở phiên làm việc tiếp theo.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/widget-based-design-8d68c.tgz | tar xz -C ~/.claude/skills
Gọi trong Claude Code: /widget-based-design – rồi mô tả công việc bạn muốn làm.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/widget-based-design-8d68c.tgz | tar xz -C ~/.codex/skills
Gọi trong Codex: $widget-based-design – rồi mô tả công việc bạn muốn làm.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/widget-based-design-8d68c.tgz | tar xz -C ~/.hermes/skills
Gọi trong Hermes Agent: /widget-based-design – rồi mô tả công việc bạn muốn làm.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/widget-based-design-8d68c.tgz | tar xz -C ~/.deepcode/skills
Gọi trong DeepSeek: /widget-based-design – rồi mô tả công việc bạn muốn làm.
Nội dung SKILL.md
Nội dung SKILL.md gốc bằng tiếng Anh.
Widget-Based Design
> "Miniature applications. Small, highly functional blocks of UI designed to be rearranged."
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
1. Strict Aspect Ratios: Widgets usually follow strict sizes (1x1 square, 2x1 rectangle, 2x2 large square).
2. Glanceability: Widgets show the most important piece of data instantly. Deep interaction usually requires opening the full app.
3. Corner Radius Match: The inner content's border radius should perfectly nest within the widget's outer border radius.
Visual DNA
- Colors: Widgets often use bright, solid color backgrounds or full-bleed photos to differentiate themselves.
- Typography: Large, bold numbers (like a clock or weather temp) paired with tiny sub-labels.
- Layout: Similar to Bento UI, but specifically focused on functional app-lets rather than just content layout.
Web Implementation
- CSS Example:
.widget-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
grid-auto-rows: 160px; /* Force squares */
gap: 16px;
padding: 32px;
}
.widget {
background-color: #ffffff;
border-radius: 24px; /* Classic iOS widget radius */
box-shadow: 0 8px 24px rgba(0,0,0,0.08);
padding: 16px;
display: flex;
flex-direction: column;
justify-content: space-between;
overflow: hidden;
position: relative;
}
/* Specific Sizes */
.widget-small { grid-column: span 1; grid-row: span 1; }
.widget-medium { grid-column: span 2; grid-row: span 1; }
.widget-large { grid-column: span 2; grid-row: span 2; }
/* Weather Widget Example */
.widget.weather {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: #12313a;
}
.weather-temp { font-size: 3rem; font-weight: 300; }
.weather-icon { position: absolute; top: 16px; right: 16px; font-size: 2rem; }App Implementation
SwiftUI
struct WidgetDesignView: View {
let columns = [GridItem(.flexible(), spacing: 16), GridItem(.flexible(), spacing: 16)]
var body: some View {
ScrollView {
LazyVGrid(columns: columns, spacing: 16) {
// One column: LazyVGrid does not span WeatherWidget across two columns.
WeatherWidget()
.frame(height: 160) // Base unit height
// 1x1 Widget
Text("Fitness") // Replace with a defined widget component.
.frame(height: 160)
// 1x1 Widget
Text("Music") // Replace with a defined widget component.
.frame(height: 160)
}
.padding(24)
}
.background(Color(white: 0.95))
}
}
struct WeatherWidget: View {
var body: some View {
ZStack(alignment: .topTrailing) {
LinearGradient(colors: [Color(hex: "4facfe"), Color(hex: "00f2fe")], startPoint: .topLeading, endPoint: .bottomTrailing)
Image(systemName: "cloud.sun.fill")
.foregroundColor(Color(red: 0.07, green: 0.19, blue: 0.23))
.font(.system(size: 40))
.padding()
VStack(alignment: .leading) {
Spacer()
Text("72°")
.font(.system(size: 48, weight: .thin))
.foregroundColor(Color(red: 0.07, green: 0.19, blue: 0.23))
Text("San Francisco")
.font(.subheadline)
.foregroundColor(Color(red: 0.07, green: 0.19, blue: 0.23))
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
}
.cornerRadius(24) // Classic iOS widget radius
.shadow(color: .black.opacity(0.1), radius: 10, y: 5)
}
}- SwiftUI is perfect for this. The
LazyVGridhandles the layout, andcornerRadius(24)matches Apple's default widget styling perfectly. - Use
ZStackas the root of the widget to easily overlay content on top of complex gradients or images.
Flutter
class WidgetDesignScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF2F2F2),
body: GridView.count(
crossAxisCount: 2, // 2 columns for a typical phone
padding: const EdgeInsets.all(24),
mainAxisSpacing: 16,
crossAxisSpacing: 16,
childAspectRatio: 1.0, // 1x1 squares
children: [
// Note: Flutter GridView doesn't easily span rows/cols out of the box.
// flutter_staggered_grid_view is highly recommended for real widget layouts.
_buildWeatherWidget(),
const Center(child: Text("Fitness")),
const Center(child: Text("Music")),
],
),
);
}
Widget _buildWeatherWidget() {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
gradient: const LinearGradient(colors: [Color(0xFF4FACFE), Color(0xFF00F2FE)]),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 5))],
),
padding: const EdgeInsets.all(16),
child: Stack(
children: [
const Align(
alignment: Alignment.topRight,
child: Icon(Icons.cloud, color: const Color(0xFF12313A), size: 40),
),
Align(
alignment: Alignment.bottomLeft,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('72°', style: TextStyle(color: const Color(0xFF12313A), fontSize: 48, fontWeight: FontWeight.w300)),
Text('San Francisco', style: TextStyle(color: const Color(0xFF12313A), fontSize: 14)),
],
),
)
],
),
);
}
}- A
Stackinside aContainerwithBorderRadius.circular(24)is the blueprint for every widget. - Standard
GridViewis too rigid for mixed 2x1 and 1x1 widgets. Use theflutter_staggered_grid_viewpackage for production apps.
React Native
const WidgetDesignScreen = () => {
return (
<ScrollView style={{ flex: 1, backgroundColor: '#F2F2F2' }} contentContainerStyle={{ padding: 24 }}>
<View style={{ flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-between', gap: 16 }}>
{/* 2x1 Widget (Full width minus padding) */}
<View style={[styles.widget, { width: '100%' }]}>
<LinearGradient colors={['#4facfe', '#00f2fe']} style={styles.widgetBg} />
<Text style={styles.temp}>72°</Text>
<Text style={styles.sub}>San Francisco</Text>
</View>
{/* 1x1 Widgets (Half width minus half gap) */}
<View style={[styles.widget, { width: '47%' }]}><Text>Fitness</Text></View>
<View style={[styles.widget, { width: '47%' }]}><Text>Music</Text></View>
</View>
</ScrollView>
);
};
const styles = StyleSheet.create({
widget: {
height: 160, // Fixed height forces square/rectangular aspect ratios
borderRadius: 24,
backgroundColor: '#FFF',
padding: 16,
justifyContent: 'flex-end',
shadowColor: '#000', shadowOffset: { width: 0, height: 5 }, shadowOpacity: 0.1, shadowRadius: 10, elevation: 5,
overflow: 'hidden'
},
widgetBg: {
...StyleSheet.absoluteFillObject,
borderRadius: 24,
},
temp: { fontSize: 48, fontWeight: '300', color: '#12313a' },
sub: { fontSize: 14, color: '#12313a' }
});- In React Native,
flexWrap: 'wrap'combined with percentage widths (e.g.,47%for 2 columns with a gap) is the cleanest way to build a responsive widget layout. - If using
LinearGradientfromexpo-linear-gradientorreact-native-linear-gradient, applyStyleSheet.absoluteFillObjectso it sits behind the text.
Jetpack Compose
@Composable
fun WidgetDesignScreen() {
LazyVerticalGrid(
columns = GridCells.Fixed(2),
modifier = Modifier.fillMaxSize().background(Color(0xFFF2F2F2)).padding(24.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// 2x1 Widget (Spans both columns)
item(span = { GridItemSpan(2) }) {
WeatherWidget(Modifier.height(160.dp))
}
// 1x1 Widgets
item { Box(Modifier.height(160.dp).background(Color.White, RoundedCornerShape(24.dp))) }
item { Box(Modifier.height(160.dp).background(Color.White, RoundedCornerShape(24.dp))) }
}
}
@Composable
fun WeatherWidget(modifier: Modifier = Modifier) {
Box(
modifier = modifier
.fillMaxWidth()
.shadow(10.dp, RoundedCornerShape(24.dp))
… (nội dung đầy đủ có trong gói tải về)
Skill liên quan
- wordpress – Quy trình phát triển WordPress gồm phát triển theme, tạo plugin, tích hợp WooCommerce…
- wordpress-theme-development – Quy trình phát triển theme WordPress gồm kiến trúc theme, template hierarchy, custom…
- write-design-md – Viết hoặc cập nhật DESIGN.md của dự án dựa trên màu sắc, kiểu chữ, khoảng cách và thành…
- y2k-design – Hướng dẫn triển khai web và ứng dụng cho Y2K Design. Kích hoạt khi người dùng muốn hiệu…
- api-and-interface-design – Hướng dẫn thiết kế API và giao diện ổn định. Dùng khi thiết kế API, ranh giới module…
- 20-andruia-niche-intelligence – Dùng sau khi xác định lĩnh vực của dự án: chuẩn bị hồ sơ tổng hợp bằng tiếng Tây Ban Nha…
- 2d-games – Nguyên tắc phát triển game 2D. Sprite, atlas, tilemap, vật lý, camera và các mẫu thể…
- 3d-ui – Hướng dẫn triển khai web và ứng dụng cho giao diện 3D. Kích hoạt khi người dùng muốn đối…