ما يستطيع render-ui رسمه: شجرة من الأنماط المسجّلة مرتبطة بالكيان.
يرسم render-ui شجرة من الأنماط في خانة. كل عقدة كائن يسمّي type فيه نمطًا مسجّلًا، وبجانبه خصائص النمط. السجل مغلق: النوع أو الخاصية غير المعروفة خطأ تحقق، فلا يمكن أن يختلف البرنامج والشاشة.
1(render-ui main { type: stack, direction: vertical, gap: md, children: [
2 { type: typography, content: "Orders", variant: h2 },
3 { type: data-list, entity: ?data, fields: [{ name: "title", label: "Order", variant: h4 }] },
4 { type: button, label: "New order", action: CREATE, variant: primary }
5] })| العائلة | الأنماط |
|---|---|
| التخطيط | stack وbox وcontainer وsimple-grid وsplit وcard وdivider |
| النص والوسائط | typography وmarkdown-content وcode-block وimage وicon وbadge وavatar |
| البيانات | data-list وdata-grid وtable-view وcard-grid وstat-display وchart |
| الإدخال | button وinput وform-section وsearch-input وtabs وmenu |
| التنبيه | alert وskeleton وempty-state وprogress-bar |
| المخططات واللوحات | avl-state-machine وavl-transition-explainer وmath-canvas وgraph-canvas |
يمكن ربط الخصائص: content: @entity.count يُعاد رسمه حين يتغير الحقل، وentity: ?data يأخذ الصفوف التي سلّمها fetch، و(if …) أو (str/concat …) يحسبان خاصية من الكيان. خاصية action: EVENT في الزر ترسل ذلك الحدث إلى سمته، وhref: "/path" تجعله رابطًا.
تعرض السمة شاشات مختلفة بإعادة الرسم في كل انتقال. هنا ترسل علامات التبويب أحداثًا، وكل انتقال يرسم الجسم المقابل:
Dashboard
on Board · states: 2 · transitions: 3One order is past its delivery date.
1app std-orb-docex-dashboard "1.0.0"
2"std-orb-docex-dashboard — UI patterns: a render-ui tree of layout, display and action patterns, with tabs that switch what the main slot shows."
3orbital DashboardOrbital {
4 entity Board [runtime] {
5 id : string!
6 tab : "overview" | "team" = overview
7 }
8
9 trait Dashboard -> Board [interaction, instance] {
10 initial: overview
11
12 state overview {
13 INIT -> overview
14 (render-ui main { type: stack, direction: vertical, gap: md, children: [
15 { type: tabs, items: [{ id: "overview", label: "Overview", event: SHOW_OVERVIEW }, { id: "team", label: "Team", event: SHOW_TEAM }], activeTab: "overview" },
16 { type: simple-grid, cols: 3, gap: md, children: [
17 { type: stat-display, label: "Open orders", value: 18 },
18 { type: stat-display, label: "Shipped today", value: 7 },
19 { type: stat-display, label: "Late", value: 1 }
20 ] },
21 { type: alert, variant: warning, message: "One order is past its delivery date." }
22 ] })
23 SHOW_TEAM -> team
24 (emit MOVED { event: "SHOW_TEAM" })
25 (set @entity.tab team)
26 (render-ui main { type: stack, direction: vertical, gap: md, children: [
27 { type: tabs, items: [{ id: "overview", label: "Overview", event: SHOW_OVERVIEW }, { id: "team", label: "Team", event: SHOW_TEAM }], activeTab: "team" },
28 { type: stack, direction: horizontal, gap: md, align: center, children: [
29 { type: avatar, name: "Huda", size: md },
30 { type: typography, content: "Huda · warehouse lead", variant: body }
31 ] },
32 { type: stack, direction: horizontal, gap: md, align: center, children: [
33 { type: avatar, name: "Luka", size: md },
34 { type: typography, content: "Luka · dispatch", variant: body }
35 ] }
36 ] })
37 }
38
39 state team {
40 SHOW_OVERVIEW -> overview
41 (emit MOVED { event: "SHOW_OVERVIEW" })
42 (set @entity.tab overview)
43 (render-ui main { type: stack, direction: vertical, gap: md, children: [
44 { type: tabs, items: [{ id: "overview", label: "Overview", event: SHOW_OVERVIEW }, { id: "team", label: "Team", event: SHOW_TEAM }], activeTab: "overview" },
45 { type: simple-grid, cols: 3, gap: md, children: [
46 { type: stat-display, label: "Open orders", value: 18 },
47 { type: stat-display, label: "Shipped today", value: 7 },
48 { type: stat-display, label: "Late", value: 1 }
49 ] },
50 { type: alert, variant: warning, message: "One order is past its delivery date." }
51 ] })
52 }
53
54 emits {
55 MOVED -> external {
56 event : string!
57 }
58 @description "Each move names the event it took, so the diagram beside the demo can follow it."
59 }
60 }
61
62 page "/dashboard" -> Dashboard
63}ما الذي يحدث عندما يقع الحدث SHOW_TEAM:
(set @entity.tab "team")كل نمط يحتاج إلى اسم يجب أن يكون له اسم: تسمية، أو alt، أو aria-label. الزر المكوّن من أيقونة فقط دون اسم هو الخطأ ORB_A11Y_UNNAMED. تُكتب سمات ARIA (aria-label وaria-live وrole وdir…) كخصائص كما تُهجّأ تمامًا.
يبني درس أنماط الواجهة شاشة خطوة بخطوة.