openuispec 0.2.1 → 0.2.2

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.
Files changed (33) hide show
  1. package/README.md +15 -0
  2. package/examples/social-app/AGENTS.md +1 -1
  3. package/examples/social-app/CLAUDE.md +1 -1
  4. package/examples/social-app/generated/web/social-app/src/components/Shell.tsx +24 -24
  5. package/examples/social-app/generated/web/social-app/src/components/ui.tsx +1 -1
  6. package/examples/social-app/generated/web/social-app/src/styles.css +1 -0
  7. package/examples/social-app/openuispec/contracts/action_trigger.yaml +21 -0
  8. package/examples/social-app/openuispec/contracts/nav_container.yaml +21 -0
  9. package/examples/todo-orbit/openuispec/contracts/action_trigger.yaml +10 -0
  10. package/examples/todo-orbit/openuispec/contracts/nav_container.yaml +25 -5
  11. package/package.json +1 -1
  12. package/schema/contract.schema.json +57 -7
  13. package/schema/custom-contract.schema.json +59 -8
  14. package/schema/defs/action.schema.json +1 -1
  15. package/schema/defs/adaptive.schema.json +1 -1
  16. package/schema/defs/common.schema.json +8 -8
  17. package/schema/defs/data-binding.schema.json +3 -3
  18. package/schema/defs/validation.schema.json +1 -1
  19. package/schema/flow.schema.json +14 -14
  20. package/schema/locale.schema.json +1 -1
  21. package/schema/openuispec.schema.json +5 -5
  22. package/schema/platform.schema.json +2 -2
  23. package/schema/screen.schema.json +23 -23
  24. package/schema/tokens/color.schema.json +9 -9
  25. package/schema/tokens/elevation.schema.json +2 -2
  26. package/schema/tokens/icons.schema.json +1 -1
  27. package/schema/tokens/layout.schema.json +9 -9
  28. package/schema/tokens/motion.schema.json +2 -2
  29. package/schema/tokens/spacing.schema.json +4 -4
  30. package/schema/tokens/themes.schema.json +2 -2
  31. package/schema/tokens/typography.schema.json +4 -4
  32. package/schema/validate.ts +1 -1
  33. package/spec/openuispec-v0.1.md +83 -4
@@ -568,6 +568,57 @@ Any token value can be suffixed with `!exact` to override the range system and f
568
568
  logo_width: { value: 120, modifier: "!exact" }
569
569
  ```
570
570
 
571
+ ### Shared Interactive State Roles
572
+
573
+ Interactive contracts may optionally encode **state-specific visual roles** inside their token maps using a nested `states:` object. This gives generators an explicit source of truth for foreground/background changes instead of forcing them to infer state styling from parent container colors or platform defaults.
574
+
575
+ This pattern is optional. If a contract or variant does not declare `states:`, generators fall back to the token values defined at that level plus the base contract semantics.
576
+
577
+ Recommended state keys:
578
+
579
+ - `default`
580
+ - `active`
581
+ - `selected`
582
+ - `pressed`
583
+ - `focused`
584
+ - `disabled`
585
+ - `loading`
586
+ - `error`
587
+
588
+ Allowed visual role keys (no others are permitted):
589
+
590
+ - `background`
591
+ - `text`
592
+ - `icon`
593
+ - `border`
594
+ - `badge_background`
595
+ - `badge_text`
596
+
597
+ Rules:
598
+
599
+ - State keys should correspond to declared contract states where possible. `active` and `selected` may also be used for per-item selection semantics such as navigation items, chips, tabs, and segmented controls.
600
+ - Omitted roles inherit from the parent token block for that variant or element.
601
+ - Top-level token values remain the default/fallback values unless overridden inside `states:`.
602
+ - Generators and audits should prefer explicit state-role tokens over inferred color inheritance when both are present.
603
+
604
+ Example:
605
+
606
+ ```yaml
607
+ sidebar:
608
+ item_height: [44, 48]
609
+ item_radius: "spacing.sm"
610
+ states:
611
+ default:
612
+ text: "color.text.secondary"
613
+ icon: "color.text.secondary"
614
+ active:
615
+ background: "color.brand.primary"
616
+ text: "color.brand.primary.on_color"
617
+ icon: "color.brand.primary.on_color"
618
+ badge_background: "color.brand.accent"
619
+ badge_text: "color.brand.accent.on_color"
620
+ ```
621
+
571
622
  ---
572
623
 
573
624
  ### 4.1 `action_trigger`
@@ -629,6 +680,12 @@ action_trigger:
629
680
  min_height: { sm: 32, md: [44, 48], lg: 56 }
630
681
  padding_h: { sm: "spacing.sm", md: "spacing.md", lg: "spacing.lg" }
631
682
  radius: "spacing.sm"
683
+ states:
684
+ disabled:
685
+ background: "color.surface.tertiary"
686
+ text: "color.text.tertiary"
687
+ loading:
688
+ text: "color.brand.primary.on_color"
632
689
  secondary:
633
690
  background: "color.surface.secondary"
634
691
  text: "color.text.primary"
@@ -636,6 +693,11 @@ action_trigger:
636
693
  min_height: { sm: 32, md: [44, 48], lg: 56 }
637
694
  padding_h: "spacing.md"
638
695
  radius: "spacing.sm"
696
+ states:
697
+ disabled:
698
+ background: "color.surface.tertiary"
699
+ text: "color.text.tertiary"
700
+ border: { width: 1, color: "color.border.default" }
639
701
  tertiary:
640
702
  background: transparent
641
703
  text: "color.brand.primary"
@@ -1017,18 +1079,35 @@ nav_container:
1017
1079
  border_top: { width: 0.5, color: "color.border.default" }
1018
1080
  icon_size: 24
1019
1081
  label_style: "typography.caption"
1020
- active_color: "color.brand.primary"
1021
- inactive_color: "color.text.tertiary"
1082
+ item:
1083
+ states:
1084
+ default:
1085
+ text: "color.text.tertiary"
1086
+ icon: "color.text.tertiary"
1087
+ active:
1088
+ text: "color.brand.primary"
1089
+ icon: "color.brand.primary"
1090
+ badge_background: "color.brand.accent"
1091
+ badge_text: "color.brand.accent.on_color"
1022
1092
  sidebar:
1023
1093
  width: { collapsed: [64, 72], expanded: [220, 280] }
1024
1094
  background: "color.surface.secondary"
1025
1095
  item_height: [44, 48]
1026
1096
  item_radius: "spacing.sm"
1027
1097
  item_padding_h: "spacing.md"
1028
- active_background: "color.brand.primary"
1029
- active_text: "color.brand.primary.on_color"
1030
1098
  icon_size: 20
1031
1099
  label_style: "typography.body_sm"
1100
+ item:
1101
+ states:
1102
+ default:
1103
+ text: "color.text.secondary"
1104
+ icon: "color.text.secondary"
1105
+ active:
1106
+ background: "color.brand.primary"
1107
+ text: "color.brand.primary.on_color"
1108
+ icon: "color.brand.primary.on_color"
1109
+ badge_background: "color.brand.accent"
1110
+ badge_text: "color.brand.accent.on_color"
1032
1111
  drawer:
1033
1112
  width: { range: [280, 320] }
1034
1113
  overlay_opacity: 0.5