openuispec 0.1.18 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -34
- package/cli/index.ts +1 -1
- package/docs/stress-test-maturity-report.md +97 -0
- package/examples/todo-orbit/AGENTS.md +127 -0
- package/examples/todo-orbit/CLAUDE.md +127 -0
- package/examples/todo-orbit/README.md +62 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/README.md +14 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/build.gradle.kts +58 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/proguard-rules.pro +1 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/AndroidManifest.xml +20 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/MainActivity.kt +14 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/TodoOrbitApp.kt +345 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/AppLogic.kt +231 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/Models.kt +169 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/Strings.kt +8 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/components/CommonComponents.kt +185 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/AnalyticsScreen.kt +193 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/SettingsScreen.kt +102 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/TasksScreen.kt +342 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/sheets/EditorSheets.kt +344 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/theme/TodoOrbitTheme.kt +59 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values/strings.xml +148 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values-ru/strings.xml +154 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/build.gradle.kts +4 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/gradle.properties +4 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/gradlew +248 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/gradlew.bat +93 -0
- package/examples/todo-orbit/generated/android/Todo Orbit/settings.gradle.kts +18 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/README.md +29 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/en.lproj/Localizable.strings +118 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/ru.lproj/Localizable.strings +118 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/App/TodoOrbitApp.swift +50 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/OrbitChrome.swift +204 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/SchedulePreviewView.swift +126 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/TrendChartView.swift +70 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/RecurringRuleSheet.swift +123 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/TaskEditorSheet.swift +60 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Models/DomainModels.swift +238 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/AnalyticsView.swift +94 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/SettingsView.swift +74 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/TasksHomeView.swift +363 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Support/AppModel.swift +324 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/TodoOrbit.xcodeproj/project.pbxproj +408 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/TodoOrbit.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/TodoOrbit.xcodeproj/xcshareddata/xcschemes/TodoOrbit.xcscheme +79 -0
- package/examples/todo-orbit/generated/ios/Todo Orbit/project.yml +24 -0
- package/examples/todo-orbit/generated/web/Todo Orbit/index.html +16 -0
- package/examples/todo-orbit/generated/web/Todo Orbit/package-lock.json +1087 -0
- package/examples/todo-orbit/generated/web/Todo Orbit/package.json +24 -0
- package/examples/todo-orbit/generated/web/Todo Orbit/src/App.tsx +2114 -0
- package/examples/todo-orbit/generated/web/Todo Orbit/src/main.tsx +13 -0
- package/examples/todo-orbit/generated/web/Todo Orbit/src/styles.css +886 -0
- package/examples/todo-orbit/generated/web/Todo Orbit/tsconfig.json +19 -0
- package/examples/todo-orbit/generated/web/Todo Orbit/vite.config.ts +6 -0
- package/examples/todo-orbit/openuispec/README.md +158 -0
- package/examples/todo-orbit/openuispec/contracts/.gitkeep +0 -0
- package/examples/todo-orbit/openuispec/contracts/action_trigger.yaml +28 -0
- package/examples/todo-orbit/openuispec/contracts/collection.yaml +32 -0
- package/examples/todo-orbit/openuispec/contracts/data_display.yaml +38 -0
- package/examples/todo-orbit/openuispec/contracts/feedback.yaml +32 -0
- package/examples/todo-orbit/openuispec/contracts/input_field.yaml +52 -0
- package/examples/todo-orbit/openuispec/contracts/nav_container.yaml +47 -0
- package/examples/todo-orbit/openuispec/contracts/surface.yaml +28 -0
- package/examples/todo-orbit/openuispec/contracts/x_schedule_preview.yaml +134 -0
- package/examples/todo-orbit/openuispec/contracts/x_task_trend_chart.yaml +139 -0
- package/examples/todo-orbit/openuispec/flows/.gitkeep +0 -0
- package/examples/todo-orbit/openuispec/flows/create_recurring_rule.yaml +253 -0
- package/examples/todo-orbit/openuispec/flows/create_task.yaml +118 -0
- package/examples/todo-orbit/openuispec/flows/edit_task.yaml +126 -0
- package/examples/todo-orbit/openuispec/locales/.gitkeep +0 -0
- package/examples/todo-orbit/openuispec/locales/en.json +150 -0
- package/examples/todo-orbit/openuispec/locales/ru.json +150 -0
- package/examples/todo-orbit/openuispec/openuispec.yaml +122 -0
- package/examples/todo-orbit/openuispec/platform/.gitkeep +0 -0
- package/examples/todo-orbit/openuispec/platform/android.yaml +19 -0
- package/examples/todo-orbit/openuispec/platform/ios.yaml +20 -0
- package/examples/todo-orbit/openuispec/platform/web.yaml +22 -0
- package/examples/todo-orbit/openuispec/screens/.gitkeep +0 -0
- package/examples/todo-orbit/openuispec/screens/analytics.yaml +139 -0
- package/examples/todo-orbit/openuispec/screens/home.yaml +172 -0
- package/examples/todo-orbit/openuispec/screens/settings.yaml +148 -0
- package/examples/todo-orbit/openuispec/screens/task_detail.yaml +223 -0
- package/examples/todo-orbit/openuispec/tokens/.gitkeep +0 -0
- package/examples/todo-orbit/openuispec/tokens/color.yaml +93 -0
- package/examples/todo-orbit/openuispec/tokens/elevation.yaml +25 -0
- package/examples/todo-orbit/openuispec/tokens/icons.yaml +92 -0
- package/examples/todo-orbit/openuispec/tokens/layout.yaml +107 -0
- package/examples/todo-orbit/openuispec/tokens/motion.yaml +39 -0
- package/examples/todo-orbit/openuispec/tokens/spacing.yaml +18 -0
- package/examples/todo-orbit/openuispec/tokens/themes.yaml +23 -0
- package/examples/todo-orbit/openuispec/tokens/typography.yaml +52 -0
- package/package.json +1 -1
- package/schema/validate.ts +0 -2
- package/spec/openuispec-v0.1.md +76 -12
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
icons:
|
|
2
|
+
sizes:
|
|
3
|
+
sm:
|
|
4
|
+
semantic: "Small inline icon size"
|
|
5
|
+
value: 16
|
|
6
|
+
md:
|
|
7
|
+
semantic: "Default icon size for actions and list items"
|
|
8
|
+
value: 20
|
|
9
|
+
lg:
|
|
10
|
+
semantic: "Prominent icon size for empty states and hero elements"
|
|
11
|
+
value: 24
|
|
12
|
+
|
|
13
|
+
variants:
|
|
14
|
+
default: "outline"
|
|
15
|
+
suffixes:
|
|
16
|
+
_fill: "Filled variant for active or completed states"
|
|
17
|
+
|
|
18
|
+
fallback:
|
|
19
|
+
strategy: "name_passthrough"
|
|
20
|
+
missing_icon: "questionmark_circle"
|
|
21
|
+
|
|
22
|
+
registry:
|
|
23
|
+
actions:
|
|
24
|
+
plus:
|
|
25
|
+
semantic: "Create a new task or item"
|
|
26
|
+
platform:
|
|
27
|
+
ios: "plus"
|
|
28
|
+
android: "add"
|
|
29
|
+
web: "plus"
|
|
30
|
+
search:
|
|
31
|
+
semantic: "Search tasks"
|
|
32
|
+
platform:
|
|
33
|
+
ios: "magnifyingglass"
|
|
34
|
+
android: "search"
|
|
35
|
+
web: "search"
|
|
36
|
+
trash:
|
|
37
|
+
semantic: "Delete a task"
|
|
38
|
+
platform:
|
|
39
|
+
ios: "trash"
|
|
40
|
+
android: "delete"
|
|
41
|
+
web: "trash-2"
|
|
42
|
+
checkmark:
|
|
43
|
+
semantic: "Confirm completion"
|
|
44
|
+
variants: ["circle", "circle_fill", "list"]
|
|
45
|
+
platform:
|
|
46
|
+
ios: "checkmark"
|
|
47
|
+
android: "check"
|
|
48
|
+
web: "check"
|
|
49
|
+
|
|
50
|
+
objects:
|
|
51
|
+
calendar:
|
|
52
|
+
semantic: "Date and scheduling"
|
|
53
|
+
platform:
|
|
54
|
+
ios: "calendar"
|
|
55
|
+
android: "calendar_today"
|
|
56
|
+
web: "calendar"
|
|
57
|
+
gear:
|
|
58
|
+
semantic: "Settings and preferences"
|
|
59
|
+
variants: ["fill"]
|
|
60
|
+
platform:
|
|
61
|
+
ios: "gear"
|
|
62
|
+
android: "settings"
|
|
63
|
+
web: "settings"
|
|
64
|
+
globe:
|
|
65
|
+
semantic: "Language and locale selection"
|
|
66
|
+
platform:
|
|
67
|
+
ios: "globe"
|
|
68
|
+
android: "language"
|
|
69
|
+
web: "languages"
|
|
70
|
+
flag:
|
|
71
|
+
semantic: "Priority marker"
|
|
72
|
+
variants: ["fill"]
|
|
73
|
+
platform:
|
|
74
|
+
ios: "flag"
|
|
75
|
+
android: "flag"
|
|
76
|
+
web: "flag"
|
|
77
|
+
|
|
78
|
+
custom:
|
|
79
|
+
todo_orbit:
|
|
80
|
+
checkmark_list:
|
|
81
|
+
semantic: "Todo list navigation icon"
|
|
82
|
+
platform:
|
|
83
|
+
ios: "checklist"
|
|
84
|
+
android: "checklist"
|
|
85
|
+
web: "list-checks"
|
|
86
|
+
chart_line:
|
|
87
|
+
semantic: "Analytics and trend visualization icon"
|
|
88
|
+
variants: ["fill"]
|
|
89
|
+
platform:
|
|
90
|
+
ios: "chart.line.uptrend.xyaxis"
|
|
91
|
+
android: "insert_chart"
|
|
92
|
+
web: "chart-line"
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
layout:
|
|
2
|
+
size_classes:
|
|
3
|
+
compact:
|
|
4
|
+
semantic: "Phone-first single-column layouts"
|
|
5
|
+
width: { max: 640 }
|
|
6
|
+
columns: 4
|
|
7
|
+
margin: "spacing.md"
|
|
8
|
+
content_max_width: null
|
|
9
|
+
examples: "Phones in portrait, narrow browser windows"
|
|
10
|
+
regular:
|
|
11
|
+
semantic: "Tablet portrait and large phone landscape layouts"
|
|
12
|
+
width: { min: 641, max: 1024 }
|
|
13
|
+
columns: 8
|
|
14
|
+
margin: "spacing.lg"
|
|
15
|
+
content_max_width: 860
|
|
16
|
+
examples: "Tablets in portrait, wide phones in landscape"
|
|
17
|
+
expanded:
|
|
18
|
+
semantic: "Desktop and large-tablet multi-column layouts"
|
|
19
|
+
width: { min: 1025 }
|
|
20
|
+
columns: 12
|
|
21
|
+
margin: "spacing.xl"
|
|
22
|
+
content_max_width: 1240
|
|
23
|
+
examples: "Desktop browsers, tablets in landscape"
|
|
24
|
+
|
|
25
|
+
platform_mapping:
|
|
26
|
+
ios:
|
|
27
|
+
uses: "UIUserInterfaceSizeClass"
|
|
28
|
+
compact: ".compact horizontal"
|
|
29
|
+
regular: ".regular horizontal"
|
|
30
|
+
expanded: ".regular horizontal + width > 1024"
|
|
31
|
+
android:
|
|
32
|
+
uses: "WindowSizeClass"
|
|
33
|
+
compact: "WindowWidthSizeClass.Compact"
|
|
34
|
+
regular: "WindowWidthSizeClass.Medium"
|
|
35
|
+
expanded: "WindowWidthSizeClass.Expanded"
|
|
36
|
+
web:
|
|
37
|
+
uses: "media queries"
|
|
38
|
+
compact: "@media (max-width: 640px)"
|
|
39
|
+
regular: "@media (min-width: 641px) and (max-width: 1024px)"
|
|
40
|
+
expanded: "@media (min-width: 1025px)"
|
|
41
|
+
|
|
42
|
+
primitives:
|
|
43
|
+
stack:
|
|
44
|
+
semantic: "Vertical content flow"
|
|
45
|
+
props:
|
|
46
|
+
spacing: { type: token_ref, default: "spacing.md" }
|
|
47
|
+
align: { type: enum, values: [leading, center, trailing, stretch], default: stretch }
|
|
48
|
+
padding: { type: token_ref, required: false }
|
|
49
|
+
platform_mapping:
|
|
50
|
+
ios: "VStack"
|
|
51
|
+
android: "Column"
|
|
52
|
+
web: "flex-direction: column"
|
|
53
|
+
row:
|
|
54
|
+
semantic: "Horizontal content flow"
|
|
55
|
+
props:
|
|
56
|
+
spacing: { type: token_ref, default: "spacing.sm" }
|
|
57
|
+
align: { type: enum, values: [top, center, bottom, baseline, stretch], default: center }
|
|
58
|
+
justify: { type: enum, values: [start, center, end, space-between, space-around], default: start }
|
|
59
|
+
wrap: { type: bool, default: false }
|
|
60
|
+
platform_mapping:
|
|
61
|
+
ios: "HStack"
|
|
62
|
+
android: "Row"
|
|
63
|
+
web: "flex-direction: row"
|
|
64
|
+
grid:
|
|
65
|
+
semantic: "Responsive 2D arrangement"
|
|
66
|
+
props:
|
|
67
|
+
columns: { type: "int or adaptive_map", default: 2 }
|
|
68
|
+
gap: { type: token_ref, default: "spacing.md" }
|
|
69
|
+
platform_mapping:
|
|
70
|
+
ios: "LazyVGrid"
|
|
71
|
+
android: "LazyVerticalGrid"
|
|
72
|
+
web: "display: grid"
|
|
73
|
+
scroll_vertical:
|
|
74
|
+
semantic: "Scrollable vertical canvas"
|
|
75
|
+
props:
|
|
76
|
+
safe_area: { type: bool, default: true }
|
|
77
|
+
padding: { type: token_ref, required: false }
|
|
78
|
+
platform_mapping:
|
|
79
|
+
ios: "ScrollView(.vertical)"
|
|
80
|
+
android: "LazyColumn or verticalScroll"
|
|
81
|
+
web: "overflow-y: auto"
|
|
82
|
+
split_view:
|
|
83
|
+
semantic: "Master-detail two-pane layout"
|
|
84
|
+
props:
|
|
85
|
+
primary_width: { type: "fraction or token_ref", default: 0.36 }
|
|
86
|
+
divider: { type: bool, default: true }
|
|
87
|
+
collapse_at: { type: size_class, default: "compact" }
|
|
88
|
+
platform_mapping:
|
|
89
|
+
ios: "NavigationSplitView"
|
|
90
|
+
android: "ListDetailPaneScaffold"
|
|
91
|
+
web: "CSS Grid with two columns"
|
|
92
|
+
|
|
93
|
+
reflow_rules:
|
|
94
|
+
action_trigger:
|
|
95
|
+
compact: { full_width: true }
|
|
96
|
+
regular: { full_width: false }
|
|
97
|
+
nav_container:
|
|
98
|
+
compact: { variant: "tab_bar" }
|
|
99
|
+
regular: { variant: "rail" }
|
|
100
|
+
expanded: { variant: "sidebar" }
|
|
101
|
+
task_actions:
|
|
102
|
+
compact: { layout: stack }
|
|
103
|
+
regular: { layout: row }
|
|
104
|
+
stat_group:
|
|
105
|
+
compact: { layout: grid, columns: 2 }
|
|
106
|
+
regular: { layout: row }
|
|
107
|
+
expanded: { layout: row }
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
motion:
|
|
2
|
+
duration:
|
|
3
|
+
instant: 100
|
|
4
|
+
quick: 180
|
|
5
|
+
normal: 280
|
|
6
|
+
slow: 420
|
|
7
|
+
|
|
8
|
+
easing:
|
|
9
|
+
default: "ease-out"
|
|
10
|
+
enter: "ease-out"
|
|
11
|
+
exit: "ease-in"
|
|
12
|
+
emphasis: "cubic-bezier(0.2, 0, 0, 1)"
|
|
13
|
+
|
|
14
|
+
reduced_motion: "remove-animation"
|
|
15
|
+
|
|
16
|
+
patterns:
|
|
17
|
+
press_feedback:
|
|
18
|
+
duration: "instant"
|
|
19
|
+
property: "scale"
|
|
20
|
+
value: 0.98
|
|
21
|
+
state_change:
|
|
22
|
+
duration: "quick"
|
|
23
|
+
property: "opacity, border-color, background"
|
|
24
|
+
screen_enter:
|
|
25
|
+
duration: "normal"
|
|
26
|
+
easing: "enter"
|
|
27
|
+
pattern: "slide-from-trailing"
|
|
28
|
+
screen_exit:
|
|
29
|
+
duration: "quick"
|
|
30
|
+
easing: "exit"
|
|
31
|
+
pattern: "slide-to-leading"
|
|
32
|
+
checkbox_check:
|
|
33
|
+
duration: "quick"
|
|
34
|
+
easing: "emphasis"
|
|
35
|
+
pattern: "scale-bounce"
|
|
36
|
+
modal_present:
|
|
37
|
+
duration: "normal"
|
|
38
|
+
easing: "enter"
|
|
39
|
+
pattern: "fade-and-lift"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
spacing:
|
|
2
|
+
base_unit: 4
|
|
3
|
+
platform_flex: 0.15
|
|
4
|
+
|
|
5
|
+
scale:
|
|
6
|
+
none: 0
|
|
7
|
+
xs: 4
|
|
8
|
+
sm: 8
|
|
9
|
+
md: { base: 16, range: [12, 16] }
|
|
10
|
+
lg: { base: 24, range: [20, 24] }
|
|
11
|
+
xl: 32
|
|
12
|
+
xxl: 40
|
|
13
|
+
|
|
14
|
+
aliases:
|
|
15
|
+
page_margin: { horizontal: md, vertical: md }
|
|
16
|
+
card_padding: { all: md }
|
|
17
|
+
section_gap: lg
|
|
18
|
+
inline_gap: sm
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
themes:
|
|
2
|
+
default: "light"
|
|
3
|
+
|
|
4
|
+
variants:
|
|
5
|
+
light:
|
|
6
|
+
surface.primary: { lightness: [97, 100] }
|
|
7
|
+
surface.secondary: { lightness: [93, 97] }
|
|
8
|
+
surface.tertiary: { lightness: [89, 94] }
|
|
9
|
+
text.primary: { lightness: [8, 14] }
|
|
10
|
+
text.secondary: { lightness: [36, 46] }
|
|
11
|
+
border.default: { opacity: 0.22 }
|
|
12
|
+
dark:
|
|
13
|
+
surface.primary: { lightness: [10, 14] }
|
|
14
|
+
surface.secondary: { lightness: [14, 18] }
|
|
15
|
+
surface.tertiary: { lightness: [18, 24] }
|
|
16
|
+
text.primary: { lightness: [90, 95] }
|
|
17
|
+
text.secondary: { lightness: [62, 70] }
|
|
18
|
+
border.default: { opacity: 0.18 }
|
|
19
|
+
|
|
20
|
+
platform:
|
|
21
|
+
ios: { supports_dynamic: true }
|
|
22
|
+
android: { dynamic_color: true }
|
|
23
|
+
web: { prefers_color_scheme: true, css_custom_properties: true }
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
typography:
|
|
2
|
+
font_family:
|
|
3
|
+
primary:
|
|
4
|
+
semantic: "Main UI typeface for the todo app"
|
|
5
|
+
value: "Manrope"
|
|
6
|
+
fallback_strategy: "modern-sans"
|
|
7
|
+
platform:
|
|
8
|
+
ios: { system_alternative: "SF Pro" }
|
|
9
|
+
android: { system_alternative: "Google Sans" }
|
|
10
|
+
web: { load_strategy: "swap", source: "google_fonts" }
|
|
11
|
+
|
|
12
|
+
scale:
|
|
13
|
+
display:
|
|
14
|
+
semantic: "Large empty-state and hero copy"
|
|
15
|
+
size: { base: 30, range: [28, 34] }
|
|
16
|
+
weight: 700
|
|
17
|
+
tracking: -0.02
|
|
18
|
+
line_height: 1.15
|
|
19
|
+
heading_lg:
|
|
20
|
+
semantic: "Primary screen titles"
|
|
21
|
+
size: { base: 24, range: [22, 28] }
|
|
22
|
+
weight: 700
|
|
23
|
+
tracking: -0.02
|
|
24
|
+
line_height: 1.2
|
|
25
|
+
heading:
|
|
26
|
+
semantic: "Section headings and modal titles"
|
|
27
|
+
size: { base: 18, range: [17, 20] }
|
|
28
|
+
weight: 600
|
|
29
|
+
tracking: -0.01
|
|
30
|
+
line_height: 1.3
|
|
31
|
+
heading_sm:
|
|
32
|
+
semantic: "Compact emphasized labels"
|
|
33
|
+
size: { base: 15, range: [14, 17] }
|
|
34
|
+
weight: 600
|
|
35
|
+
line_height: 1.35
|
|
36
|
+
body:
|
|
37
|
+
semantic: "Primary body copy"
|
|
38
|
+
size: { base: 16, range: [15, 17] }
|
|
39
|
+
weight: 400
|
|
40
|
+
line_height: 1.5
|
|
41
|
+
body_sm:
|
|
42
|
+
semantic: "Supporting text and subtitles"
|
|
43
|
+
size: { base: 14, range: [13, 15] }
|
|
44
|
+
weight: 400
|
|
45
|
+
tracking: 0.004
|
|
46
|
+
line_height: 1.45
|
|
47
|
+
caption:
|
|
48
|
+
semantic: "Tiny labels and metadata"
|
|
49
|
+
size: { base: 12, range: [11, 13] }
|
|
50
|
+
weight: 500
|
|
51
|
+
tracking: 0.015
|
|
52
|
+
line_height: 1.35
|
package/package.json
CHANGED
package/schema/validate.ts
CHANGED
package/spec/openuispec-v0.1.md
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
OpenUISpec is not a cross-platform framework. It is a **semantic design language specification** from which AI generates native platform code. The spec describes *what* UI does and *how it should feel* — never *which widget to use*.
|
|
15
15
|
|
|
16
|
+
OpenUISpec is a shared UI sync language for native products, optimized for solo developers but also intended for teams that need a durable synchronization layer between product intent and platform code. It is not a pixel-perfect design description and it does not aim to erase platform differences. Its goal is semantic consistency with bounded native variation.
|
|
17
|
+
|
|
16
18
|
### Core principles
|
|
17
19
|
|
|
18
20
|
1. **Semantic over visual.** The spec defines behavioral intent, not pixel layouts. A "primary action trigger" maps to `Button` in SwiftUI, `Button` in Compose, and `<button>` in HTML — the spec never says "button."
|
|
@@ -1720,6 +1722,8 @@ Layout primitives are the building blocks for arranging content. They replace th
|
|
|
1720
1722
|
| `split_view` | Side-by-side master-detail | `NavigationSplitView` | `ListDetailPaneScaffold` | CSS Grid |
|
|
1721
1723
|
| `adaptive` | Changes layout per size class | — | — | — |
|
|
1722
1724
|
|
|
1725
|
+
Layout primitives must remain usable across the size classes they are generated for. Multi-pane or master-detail patterns require an explicit compact fallback rather than assuming large-screen behavior will degrade correctly.
|
|
1726
|
+
|
|
1723
1727
|
Each primitive has typed props:
|
|
1724
1728
|
|
|
1725
1729
|
```yaml
|
|
@@ -2022,17 +2026,21 @@ This section defines the rules any AI code generator must follow when producing
|
|
|
2022
2026
|
Every AI generator, regardless of platform target, MUST:
|
|
2023
2027
|
|
|
2024
2028
|
1. Produce **compilable code** that builds without errors on the target platform.
|
|
2025
|
-
2.
|
|
2026
|
-
3.
|
|
2027
|
-
4.
|
|
2028
|
-
5.
|
|
2029
|
-
6.
|
|
2030
|
-
7.
|
|
2031
|
-
8.
|
|
2032
|
-
9.
|
|
2033
|
-
10.
|
|
2034
|
-
11.
|
|
2035
|
-
12.
|
|
2029
|
+
2. Refresh its knowledge of the current target platform implementation model before generation when the output depends on toolchain-specific conventions, project formats, packaging rules, resource wiring, or fast-moving framework APIs.
|
|
2030
|
+
3. Map every `contract` reference to the correct native widget per `platform_mapping`.
|
|
2031
|
+
4. Apply all `tokens` values within their declared `range` constraints.
|
|
2032
|
+
5. Implement every `state` declared in each used contract, including transitions.
|
|
2033
|
+
6. Set correct `a11y.role` and `a11y.label` for every component instance. For contextual containers such as `collection`, derive the label from the visible heading/header via `aria-labelledby` or the platform equivalent when possible instead of requiring a dedicated prop.
|
|
2034
|
+
7. Respect `themes` by generating light/dark mode support.
|
|
2035
|
+
8. Handle `empty`, `loading`, and `error` states for `collection` contracts.
|
|
2036
|
+
9. Wire all `action.navigate` declarations to the platform's navigation system.
|
|
2037
|
+
10. Apply `motion.reduced_motion` preferences globally.
|
|
2038
|
+
11. Implement all three size classes (`compact`, `regular`, `expanded`) and apply `adaptive` overrides from screen files.
|
|
2039
|
+
12. Validate all `props` types and report spec errors before generating code.
|
|
2040
|
+
13. Generate platform-native localization resources from JSON locale files when `i18n` config is present (see Section 11).
|
|
2041
|
+
14. Emit a valid native project or target configuration that bundles every generated runtime resource, including localization files, assets, and generated metadata. A generated resource file that is not connected to the runnable target is non-compliant.
|
|
2042
|
+
15. Adapt navigation and container patterns for every supported size class and form factor. A generator may not assume that a large-screen or multi-pane layout will remain usable on compact layouts without an explicit fallback.
|
|
2043
|
+
16. Preserve required contract semantics when mapping to native widgets. A platform-native substitution may change the implementation primitive, but it may not drop required token-driven shapes, borders, visual states, or interaction semantics declared by the contract.
|
|
2036
2044
|
|
|
2037
2045
|
### 8.3 Validation
|
|
2038
2046
|
|
|
@@ -2975,7 +2983,7 @@ Generators produce platform-native localization resources from the JSON source:
|
|
|
2975
2983
|
|
|
2976
2984
|
| Platform | Output format | Plurals | Notes |
|
|
2977
2985
|
|----------|--------------|---------|-------|
|
|
2978
|
-
| **iOS** | `.xcstrings` (Xcode 15+) | Built-in plural rules | ICU plurals map to `.stringsdict` entries within `.xcstrings
|
|
2986
|
+
| **iOS** | `.xcstrings` (Xcode 15+) or correctly bundled `.strings` resources | Built-in plural rules | ICU plurals map to `.stringsdict` entries within `.xcstrings`; generated locale resources must be attached to the runnable target and resolvable at runtime |
|
|
2979
2987
|
| **Android** | `res/values-{locale}/strings.xml` + `plurals.xml` | `<plurals>` element | ICU selects map to conditional logic in generated code |
|
|
2980
2988
|
| **Web** | JSON bundles per locale | `react-intl` / `i18next` ICU plugin | Direct ICU MessageFormat — no conversion needed |
|
|
2981
2989
|
|
|
@@ -2993,6 +3001,7 @@ i18n:
|
|
|
2993
3001
|
**MUST:**
|
|
2994
3002
|
- Resolve every `$t:key` reference to the corresponding locale string
|
|
2995
3003
|
- Generate platform-native locale files from JSON sources for each supported locale
|
|
3004
|
+
- Ensure generated locale files are actually bundled by the runnable platform target and available at runtime
|
|
2996
3005
|
- Pass `t_params` data paths to ICU placeholders at runtime
|
|
2997
3006
|
- Apply `$direction` from the active locale to layout direction
|
|
2998
3007
|
- Use the `fallback_strategy` for missing keys (default: fall back to `default_locale`)
|
|
@@ -3201,6 +3210,61 @@ ios:
|
|
|
3201
3210
|
- Generate test code based on `test_cases`
|
|
3202
3211
|
- Add platform-specific enhancements beyond what the contract specifies
|
|
3203
3212
|
|
|
3213
|
+
### 12.8 Extending standard contracts
|
|
3214
|
+
|
|
3215
|
+
The 7 built-in contract families (Section 4) can be extended per-project using `contracts/<name>.yaml` files. Extensions add project-specific **variants**, **token overrides**, **platform mapping**, and **generation hints** without redefining the base contract. The base definition (props, states, a11y) remains authoritative from the spec.
|
|
3216
|
+
|
|
3217
|
+
```yaml
|
|
3218
|
+
# contracts/input_field.yaml
|
|
3219
|
+
input_field:
|
|
3220
|
+
variants:
|
|
3221
|
+
cut_corner:
|
|
3222
|
+
semantic: "Angled corner input for branded forms"
|
|
3223
|
+
tokens:
|
|
3224
|
+
cut_size: "spacing.sm"
|
|
3225
|
+
border: { color: "color.semantic.border", width: 1 }
|
|
3226
|
+
platform_mapping:
|
|
3227
|
+
ios: { shape: "CutCornerShape", clip: true }
|
|
3228
|
+
android: { shape: "CutCornerShape" }
|
|
3229
|
+
web: { style: "clip-path" }
|
|
3230
|
+
generation:
|
|
3231
|
+
must_handle:
|
|
3232
|
+
- "Cut top-right and bottom-left corners by cut_size"
|
|
3233
|
+
- "Maintain focus ring that follows the cut shape"
|
|
3234
|
+
should_handle:
|
|
3235
|
+
- "Animate corner cut on focus"
|
|
3236
|
+
```
|
|
3237
|
+
|
|
3238
|
+
**Root key:** The contract family name (e.g. `input_field`, `action_trigger`). Not `x_` prefixed — that is reserved for fully custom contracts.
|
|
3239
|
+
|
|
3240
|
+
**Available extension fields** (all optional):
|
|
3241
|
+
|
|
3242
|
+
| Field | Purpose |
|
|
3243
|
+
|-------|---------|
|
|
3244
|
+
| `variants` | Named style/behavior presets with their own tokens, platform_mapping, and generation hints |
|
|
3245
|
+
| `additional_props` | Props beyond what the spec defines for this contract |
|
|
3246
|
+
| `tokens` | Contract-level token overrides |
|
|
3247
|
+
| `platform_mapping` | Per-platform implementation hints |
|
|
3248
|
+
| `generation` | AI generation hints (must_handle, should_handle, may_handle) |
|
|
3249
|
+
| `test_cases` | Behavioral verification scenarios |
|
|
3250
|
+
|
|
3251
|
+
**Usage in screens:** Reference a variant by name in the `variant` field of a contract instance:
|
|
3252
|
+
|
|
3253
|
+
```yaml
|
|
3254
|
+
- contract: input_field
|
|
3255
|
+
variant: cut_corner
|
|
3256
|
+
props:
|
|
3257
|
+
label: "Email"
|
|
3258
|
+
input_type: email
|
|
3259
|
+
```
|
|
3260
|
+
|
|
3261
|
+
**Key differences from custom contracts (Section 12.1–12.7):**
|
|
3262
|
+
|
|
3263
|
+
- Standard extensions do **not** redefine `semantic`, `props`, `states`, or `a11y` — these come from the spec
|
|
3264
|
+
- Required props from the base contract still apply (e.g. `input_field` always requires `props.label`)
|
|
3265
|
+
- An empty extension (`input_field: {}`) is valid and means "use the spec definition as-is"
|
|
3266
|
+
- Validated against `contract.schema.json`, not `custom-contract.schema.json`
|
|
3267
|
+
|
|
3204
3268
|
---
|
|
3205
3269
|
|
|
3206
3270
|
## 13. Form validation and field dependencies
|