@origostudio/origo-design 0.0.46 → 0.0.48

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 (77) hide show
  1. package/CHANGELOG.md +5 -2
  2. package/bmad-resolved-config.json +226 -0
  3. package/bmad_prd_workflow.json +17 -0
  4. package/config_output.json +226 -0
  5. package/dist/packages/angular-renderer/CHANGELOG.md +15 -0
  6. package/dist/packages/angular-renderer/package.json +3 -3
  7. package/dist/packages/angular-renderer/src/components/primitives/button/button.component.d.ts +26 -0
  8. package/dist/packages/angular-renderer/src/components/primitives/button/button.component.js +29 -3
  9. package/dist/packages/angular-renderer/src/components/primitives/button/button.component.js.map +1 -1
  10. package/dist/packages/angular-renderer/src/components/primitives/button-group/button-group.component.d.ts +23 -0
  11. package/dist/packages/angular-renderer/src/components/primitives/button-group/button-group.component.js +73 -0
  12. package/dist/packages/angular-renderer/src/components/primitives/button-group/button-group.component.js.map +1 -0
  13. package/dist/packages/angular-renderer/src/components/primitives/floating-action-button/floating-action-button.component.d.ts +41 -0
  14. package/dist/packages/angular-renderer/src/components/primitives/floating-action-button/floating-action-button.component.js +87 -0
  15. package/dist/packages/angular-renderer/src/components/primitives/floating-action-button/floating-action-button.component.js.map +1 -0
  16. package/dist/packages/angular-renderer/src/components/primitives/icon-button/icon-button.component.d.ts +44 -0
  17. package/dist/packages/angular-renderer/src/components/primitives/icon-button/icon-button.component.js +93 -0
  18. package/dist/packages/angular-renderer/src/components/primitives/icon-button/icon-button.component.js.map +1 -0
  19. package/dist/packages/angular-renderer/src/index.d.ts +3 -0
  20. package/dist/packages/angular-renderer/src/index.js +3 -0
  21. package/dist/packages/angular-renderer/src/index.js.map +1 -1
  22. package/dist/packages/angular-renderer/src/lib/primitives.provider.js +6 -0
  23. package/dist/packages/angular-renderer/src/lib/primitives.provider.js.map +1 -1
  24. package/dist/packages/cli/CHANGELOG.md +8 -0
  25. package/dist/packages/cli/package.json +2 -2
  26. package/dist/packages/cli/package.json.bak +2 -2
  27. package/dist/packages/core/CHANGELOG.md +8 -0
  28. package/dist/packages/core/package.json +1 -1
  29. package/dist/packages/core/package.json.bak +1 -1
  30. package/dist/packages/design-tokens/CHANGELOG.md +8 -0
  31. package/dist/packages/design-tokens/package.json +1 -1
  32. package/dist/packages/playground/browser/{chunk-NvAbwArG.js → chunk-4MD_GCgA.js} +1 -1
  33. package/dist/packages/playground/browser/{chunk-D8xCSUn8.js → chunk-B8F7hD0p.js} +1 -1
  34. package/dist/packages/playground/browser/{chunk-KjK48aB_.js → chunk-BQfPUVzZ.js} +1 -1
  35. package/dist/packages/playground/browser/{chunk-Vi7LKue9.js → chunk-COjGAm8R.js} +1 -1
  36. package/dist/packages/playground/browser/{chunk-hQe37O_T.js → chunk-CQQHYSEg.js} +1 -1
  37. package/dist/packages/playground/browser/{chunk-M-QQ6mOa.js → chunk-CdNbNqNV.js} +1 -1
  38. package/dist/packages/playground/browser/{chunk-Ds2pJNq1.js → chunk-ChP61sze.js} +1 -1
  39. package/dist/packages/playground/browser/{chunk-D8NS9RS7.js → chunk-ClmlG9ZJ.js} +1 -1
  40. package/dist/packages/playground/browser/{chunk-DOh0X2ps.js → chunk-CtaS4wCa.js} +1 -1
  41. package/dist/packages/playground/browser/{chunk-CoC5zYQK.js → chunk-DRRJiw3L.js} +1 -1
  42. package/dist/packages/playground/browser/{chunk-Bnpjwr-7.js → chunk-DvVvDpcg.js} +1 -1
  43. package/dist/packages/playground/browser/{chunk-pi5vOCVu.js → chunk-DyfobgsU.js} +1 -1
  44. package/dist/packages/playground/browser/{chunk-DQXI3hQ7.js → chunk-PT1eAqp3.js} +1 -1
  45. package/dist/packages/playground/browser/{chunk-iW-WwSbU.js → chunk-cI3o8oNy.js} +1 -1
  46. package/dist/packages/playground/browser/{chunk-7aXhMYht.js → chunk-zkDXJCJr.js} +1 -1
  47. package/dist/packages/playground/browser/index.html +2 -2
  48. package/dist/packages/playground/browser/main-DTJJSNK4.js +733 -0
  49. package/package.json +1 -1
  50. package/packages/angular-renderer/CHANGELOG.md +15 -0
  51. package/packages/angular-renderer/package.json +3 -3
  52. package/packages/angular-renderer/src/components/primitives/button/button.component.html +16 -1
  53. package/packages/angular-renderer/src/components/primitives/button/button.component.ts +41 -3
  54. package/packages/angular-renderer/src/components/primitives/button-group/button-group.component.html +8 -0
  55. package/packages/angular-renderer/src/components/primitives/button-group/button-group.component.scss +18 -0
  56. package/packages/angular-renderer/src/components/primitives/button-group/button-group.component.ts +71 -0
  57. package/packages/angular-renderer/src/components/primitives/floating-action-button/floating-action-button.component.html +18 -0
  58. package/packages/angular-renderer/src/components/primitives/floating-action-button/floating-action-button.component.scss +47 -0
  59. package/packages/angular-renderer/src/components/primitives/floating-action-button/floating-action-button.component.ts +94 -0
  60. package/packages/angular-renderer/src/components/primitives/icon-button/icon-button.component.html +18 -0
  61. package/packages/angular-renderer/src/components/primitives/icon-button/icon-button.component.scss +34 -0
  62. package/packages/angular-renderer/src/components/primitives/icon-button/icon-button.component.ts +102 -0
  63. package/packages/angular-renderer/src/index.ts +3 -0
  64. package/packages/angular-renderer/src/lib/primitives.provider.ts +6 -0
  65. package/packages/cli/CHANGELOG.md +8 -0
  66. package/packages/cli/package.json +2 -2
  67. package/packages/core/CHANGELOG.md +8 -0
  68. package/packages/core/package.json +1 -1
  69. package/packages/design-tokens/CHANGELOG.md +8 -0
  70. package/packages/design-tokens/package.json +1 -1
  71. package/packages/devtools/CHANGELOG.md +8 -0
  72. package/packages/devtools/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  73. package/packages/devtools/package.json +3 -3
  74. package/packages/playground/CHANGELOG.md +8 -0
  75. package/packages/playground/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  76. package/packages/playground/package.json +3 -3
  77. package/dist/packages/playground/browser/main-HYTU6AQS.js +0 -731
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@origostudio/origo-design",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,3 +1,18 @@
1
+ ## 0.0.48 (2026-10-07)
2
+
3
+ ### 🚀 Features
4
+
5
+ - add core primitives, buttons, and review artifacts for Angular renderer ([f0cbc46](https://github.com/OrigoStudio/origo-design/commit/f0cbc46))
6
+ - add core button and action primitive components to angular-renderer ([2f7d926](https://github.com/OrigoStudio/origo-design/commit/2f7d926))
7
+
8
+ ### ❤️ Thank You
9
+
10
+ - Hardik Patel @hardikpatelse
11
+
12
+ ## 0.0.47 (2026-10-07)
13
+
14
+ This was a version bump only for angular-renderer to align it with other projects, there were no code changes.
15
+
1
16
  ## 0.0.46 (2026-10-02)
2
17
 
3
18
  This was a version bump only for angular-renderer to align it with other projects, there were no code changes.
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@origostudio/angular-renderer",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
4
4
  "private": false,
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "dependencies": {
9
- "@origostudio/core": "0.0.46",
10
- "@origostudio/design-tokens": "0.0.46",
9
+ "@origostudio/core": "0.0.48",
10
+ "@origostudio/design-tokens": "0.0.48",
11
11
  "tslib": "^2.3.0",
12
12
  "@analogjs/vite-plugin-angular": "^2.7.1",
13
13
  "zone.js": "^0.16.3",
@@ -3,7 +3,22 @@
3
3
  [disabled]="computedDisabled()"
4
4
  [attr.aria-label]="computedAriaLabel()"
5
5
  [attr.aria-describedby]="computedAriaDescribedBy()"
6
+ [attr.aria-busy]="computedLoading() ? 'true' : null"
6
7
  (click)="onClick()"
7
8
  >
8
- {{ computedLabel() }}
9
+ @if (computedLoading()) {
10
+ <span class="origo-spinner"></span>
11
+ }
12
+ @if (computedIcon() && computedIconPosition() !== 'right') {
13
+ <span [class]="'origo-icon origo-icon-' + computedIcon()"></span>
14
+ }
15
+ <span class="origo-button-label">{{ computedLabel() }}</span>
16
+ @if (computedBadge()) {
17
+ <span [class]="'origo-badge origo-badge-' + computedBadgeSeverity()">{{
18
+ computedBadge()
19
+ }}</span>
20
+ }
21
+ @if (computedIcon() && computedIconPosition() === 'right') {
22
+ <span [class]="'origo-icon origo-icon-' + computedIcon()"></span>
23
+ }
9
24
  </button>
@@ -17,6 +17,16 @@ export interface ButtonProps {
17
17
  type?: 'button' | 'submit' | 'reset';
18
18
  'aria-label'?: string;
19
19
  'aria-describedby'?: string;
20
+ loading?: boolean;
21
+ severity?: string;
22
+ variant?: string;
23
+ icon?: string;
24
+ iconPosition?: string;
25
+ badge?: string;
26
+ badgeSeverity?: string;
27
+ permissions?: any;
28
+ rules?: any;
29
+ metadata?: any;
20
30
  }
21
31
 
22
32
  @Component({
@@ -27,7 +37,7 @@ export interface ButtonProps {
27
37
  changeDetection: ChangeDetectionStrategy.OnPush,
28
38
  encapsulation: ViewEncapsulation.ShadowDom,
29
39
  host: {
30
- '[class.origo-button]': 'true',
40
+ '[class]': 'computedHostClasses()',
31
41
  '[attr.data-testid]': 'contract().id ?? ""',
32
42
  },
33
43
  })
@@ -36,13 +46,41 @@ export class ButtonComponent implements OrigoAdapter<ButtonProps> {
36
46
  label: 'string',
37
47
  disabled: 'boolean',
38
48
  type: 'string',
49
+ loading: 'boolean',
50
+ severity: 'string',
51
+ variant: 'string',
52
+ icon: 'string',
53
+ iconPosition: 'string',
54
+ badge: 'string',
55
+ badgeSeverity: 'string',
56
+ permissions: 'object',
57
+ rules: 'object',
58
+ metadata: 'object',
39
59
  };
40
60
  static readonly strictContract = false;
41
61
 
42
62
  contract = input.required<InteractionContract<ButtonProps>>();
43
63
 
44
64
  computedLabel = computed(() => this.contract().props?.label ?? 'Button');
45
- computedDisabled = computed(() => !!this.contract().props?.disabled);
65
+ computedLoading = computed(() => !!this.contract().props?.loading);
66
+ computedDisabled = computed(() => {
67
+ const props = this.contract().props;
68
+ const rulesDisable = props?.rules?.disable === true || props?.permissions?.allow === false;
69
+ return !!props?.disabled || this.computedLoading() || rulesDisable;
70
+ });
71
+
72
+ computedIcon = computed(() => this.contract().props?.icon);
73
+ computedIconPosition = computed(() => this.contract().props?.iconPosition ?? 'left');
74
+ computedBadge = computed(() => this.contract().props?.badge);
75
+ computedBadgeSeverity = computed(() => this.contract().props?.badgeSeverity ?? 'info');
76
+
77
+ computedHostClasses = computed(() => {
78
+ const s = this.contract().props?.severity;
79
+ const v = this.contract().props?.variant;
80
+ return ['origo-button', s ? `origo-severity-${s}` : '', v ? `origo-variant-${v}` : '']
81
+ .filter(Boolean)
82
+ .join(' ');
83
+ });
46
84
  computedType = computed(() => {
47
85
  const type = this.contract().props?.type;
48
86
  return type === 'button' || type === 'submit' || type === 'reset' ? type : 'button';
@@ -65,7 +103,7 @@ export class ButtonComponent implements OrigoAdapter<ButtonProps> {
65
103
  private experienceAdapter = inject(WebExperienceAdapterService);
66
104
 
67
105
  onClick() {
68
- if (this.computedDisabled()) return;
106
+ if (this.computedDisabled() || this.computedLoading()) return;
69
107
 
70
108
  const id = this.contract().id;
71
109
  if (!id) return;
@@ -0,0 +1,8 @@
1
+ <div
2
+ class="origo-button-group-content"
3
+ role="group"
4
+ [attr.aria-label]="computedAriaLabel()"
5
+ [attr.aria-describedby]="computedAriaDescribedBy()"
6
+ >
7
+ <ng-content></ng-content>
8
+ </div>
@@ -0,0 +1,18 @@
1
+ :host {
2
+ display: inline-flex;
3
+ }
4
+ .origo-button-group-content {
5
+ display: flex;
6
+ flex-direction: row;
7
+ gap: var(--origo-spacing-container-padding);
8
+ }
9
+ :host(.origo-orientation-column) .origo-button-group-content {
10
+ flex-direction: column;
11
+ }
12
+ :host(.origo-attached) .origo-button-group-content {
13
+ gap: 0;
14
+ }
15
+ /* Note: attached styling across shadow DOM requires passing CSS custom properties to children, which relies on children consuming them. */
16
+ :host(.origo-attached) {
17
+ --origo-button-radius: 0;
18
+ }
@@ -0,0 +1,71 @@
1
+ import {
2
+ Component,
3
+ input,
4
+ ChangeDetectionStrategy,
5
+ computed,
6
+ ViewEncapsulation,
7
+ } from '@angular/core';
8
+ import { InteractionContract } from '@origostudio/core';
9
+ import { OrigoAdapter } from '../../../adapters/web/adapter';
10
+
11
+ export interface ButtonGroupProps {
12
+ orientation?: 'row' | 'column';
13
+ attached?: boolean;
14
+ size?: 'small' | 'medium' | 'large';
15
+ 'aria-label'?: string;
16
+ 'aria-describedby'?: string;
17
+ }
18
+
19
+ @Component({
20
+ selector: 'origo-button-group',
21
+ standalone: true,
22
+ templateUrl: './button-group.component.html',
23
+ styleUrls: ['./button-group.component.scss'],
24
+ changeDetection: ChangeDetectionStrategy.OnPush,
25
+ encapsulation: ViewEncapsulation.ShadowDom,
26
+ host: {
27
+ '[class]': 'computedHostClasses()',
28
+ '[attr.data-testid]': 'contract().id ?? ""',
29
+ },
30
+ })
31
+ export class ButtonGroupComponent implements OrigoAdapter<ButtonGroupProps> {
32
+ static readonly contractSchema = {
33
+ orientation: 'string',
34
+ attached: 'boolean',
35
+ size: 'string',
36
+ 'aria-label': 'string',
37
+ 'aria-describedby': 'string',
38
+ };
39
+ static readonly strictContract = false;
40
+
41
+ contract = input.required<InteractionContract<ButtonGroupProps>>();
42
+
43
+ computedHostClasses = computed(() => {
44
+ const rawO = this.contract().props?.orientation;
45
+ const o = rawO === 'column' ? 'column' : 'row';
46
+ const attached = this.contract().props?.attached;
47
+ const rawSize = this.contract().props?.size;
48
+ const size = ['small', 'medium', 'large'].includes(rawSize as string) ? rawSize : undefined;
49
+ return [
50
+ 'origo-button-group',
51
+ `origo-orientation-${o}`,
52
+ attached ? 'origo-attached' : '',
53
+ size ? `origo-size-${size}` : '',
54
+ ]
55
+ .filter(Boolean)
56
+ .join(' ');
57
+ });
58
+
59
+ computedAriaLabel = computed(() => {
60
+ const label = this.contract().props?.['aria-label'];
61
+ return label !== undefined && label !== null && String(label).trim() !== ''
62
+ ? String(label)
63
+ : undefined;
64
+ });
65
+ computedAriaDescribedBy = computed(() => {
66
+ const desc = this.contract().props?.['aria-describedby'];
67
+ return desc !== undefined && desc !== null && String(desc).trim() !== ''
68
+ ? String(desc)
69
+ : undefined;
70
+ });
71
+ }
@@ -0,0 +1,18 @@
1
+ <button
2
+ type="button"
3
+ [disabled]="computedDisabled()"
4
+ [attr.aria-label]="computedAriaLabel()"
5
+ [attr.aria-describedby]="computedAriaDescribedBy()"
6
+ (click)="onClick()"
7
+ >
8
+ @if (computedLoading()) {
9
+ <span class="origo-spinner"></span>
10
+ } @else {
11
+ @if (computedIcon()) {
12
+ <span [class]="'origo-icon origo-icon-' + computedIcon()"></span>
13
+ }
14
+ }
15
+ @if (computedLabel()) {
16
+ <span class="origo-fab-label">{{ computedLabel() }}</span>
17
+ }
18
+ </button>
@@ -0,0 +1,47 @@
1
+ :host {
2
+ display: inline-flex;
3
+ position: fixed;
4
+ z-index: 1000;
5
+ }
6
+ :host(.origo-position-bottom-right) {
7
+ bottom: var(--origo-spacing-container-padding);
8
+ right: var(--origo-spacing-container-padding);
9
+ }
10
+ :host(.origo-position-bottom-left) {
11
+ bottom: var(--origo-spacing-container-padding);
12
+ left: var(--origo-spacing-container-padding);
13
+ }
14
+ button {
15
+ cursor: pointer;
16
+ background-color: var(--origo-color-surface-primary);
17
+ color: var(--origo-color-text-inverse);
18
+ border: none;
19
+ border-radius: var(--origo-radius-xl);
20
+ box-shadow: var(--origo-shadow-md);
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ gap: var(--origo-spacing-sm, 8px);
25
+ min-width: 48px;
26
+ min-height: 48px;
27
+ padding: 0 var(--origo-spacing-container-padding);
28
+ transition: var(--origo-transition-all);
29
+ }
30
+ button:empty {
31
+ padding: 0;
32
+ }
33
+ button:hover:not(:disabled) {
34
+ background-color: var(--origo-color-surface-primary-hover);
35
+ box-shadow: var(--origo-shadow-lg);
36
+ }
37
+ button:active:not(:disabled) {
38
+ background-color: var(--origo-color-surface-primary-active);
39
+ }
40
+ button:focus-visible {
41
+ outline: var(--origo-outline-width, 2px) solid var(--origo-color-focus);
42
+ outline-offset: var(--origo-outline-width, 2px);
43
+ }
44
+ button:disabled {
45
+ cursor: not-allowed;
46
+ opacity: var(--origo-opacity-disabled);
47
+ }
@@ -0,0 +1,94 @@
1
+ import {
2
+ Component,
3
+ input,
4
+ ChangeDetectionStrategy,
5
+ computed,
6
+ ViewEncapsulation,
7
+ inject,
8
+ } from '@angular/core';
9
+ import { InteractionContract } from '@origostudio/core';
10
+ import { OrigoAdapter } from '../../../adapters/web/adapter';
11
+ import { WebExperienceAdapterService } from '../../../adapters/web/experience-adapter.service';
12
+
13
+ export interface FabProps {
14
+ icon?: string;
15
+ label?: string;
16
+ severity?: string;
17
+ loading?: boolean;
18
+ disabled?: boolean;
19
+ position?: 'bottom-right' | 'bottom-left';
20
+ 'aria-label'?: string;
21
+ 'aria-describedby'?: string;
22
+ permissions?: any;
23
+ rules?: any;
24
+ metadata?: any;
25
+ }
26
+
27
+ @Component({
28
+ selector: 'origo-fab',
29
+ standalone: true,
30
+ templateUrl: './floating-action-button.component.html',
31
+ styleUrls: ['./floating-action-button.component.scss'],
32
+ changeDetection: ChangeDetectionStrategy.OnPush,
33
+ encapsulation: ViewEncapsulation.ShadowDom,
34
+ host: {
35
+ '[class]': 'computedHostClasses()',
36
+ '[attr.data-testid]': 'contract().id ?? ""',
37
+ },
38
+ })
39
+ export class FloatingActionButtonComponent implements OrigoAdapter<FabProps> {
40
+ static readonly contractSchema = {
41
+ icon: 'string',
42
+ label: 'string',
43
+ severity: 'string',
44
+ loading: 'boolean',
45
+ disabled: 'boolean',
46
+ position: 'string',
47
+ 'aria-label': 'string',
48
+ 'aria-describedby': 'string',
49
+ permissions: 'object',
50
+ rules: 'object',
51
+ metadata: 'object',
52
+ };
53
+ static readonly strictContract = false;
54
+
55
+ contract = input.required<InteractionContract<FabProps>>();
56
+
57
+ computedIcon = computed(() => this.contract().props?.icon ?? '');
58
+ computedLabel = computed(() => this.contract().props?.label ?? '');
59
+ computedLoading = computed(() => !!this.contract().props?.loading);
60
+ computedDisabled = computed(() => {
61
+ const props = this.contract().props;
62
+ const rulesDisable = props?.rules?.disable === true || props?.permissions?.allow === false;
63
+ return !!props?.disabled || this.computedLoading() || rulesDisable;
64
+ });
65
+
66
+ computedAriaLabel = computed(() => {
67
+ const p = this.contract().props;
68
+ const v = p?.['aria-label'] || p?.label;
69
+ return v ? String(v) : undefined;
70
+ });
71
+
72
+ computedAriaDescribedBy = computed(() => {
73
+ const v = this.contract().props?.['aria-describedby'];
74
+ return v ? String(v) : undefined;
75
+ });
76
+
77
+ computedHostClasses = computed(() => {
78
+ const s = this.contract().props?.severity;
79
+ const rawP = this.contract().props?.position;
80
+ const p = ['bottom-left', 'bottom-right'].includes(rawP as string) ? rawP : 'bottom-right';
81
+ return ['origo-fab', s ? `origo-severity-${s}` : '', `origo-position-${p}`]
82
+ .filter(Boolean)
83
+ .join(' ');
84
+ });
85
+
86
+ private experienceAdapter = inject(WebExperienceAdapterService);
87
+
88
+ onClick() {
89
+ if (this.computedDisabled() || this.computedLoading()) return;
90
+ const id = this.contract().id;
91
+ if (!id) return;
92
+ this.experienceAdapter.dispatchCapability(id, 'click');
93
+ }
94
+ }
@@ -0,0 +1,18 @@
1
+ <button
2
+ type="button"
3
+ [disabled]="computedDisabled()"
4
+ [attr.aria-label]="computedAriaLabel()"
5
+ [attr.aria-describedby]="computedAriaDescribedBy()"
6
+ [title]="contract().props?.tooltip || null"
7
+ (click)="onClick()"
8
+ >
9
+ @if (computedLoading()) {
10
+ <span class="origo-spinner"></span>
11
+ } @else {
12
+ @if (computedIcon()) {
13
+ <span [class]="'origo-icon origo-icon-' + computedIcon()"></span>
14
+ } @else {
15
+ <span class="origo-icon origo-icon-default"></span>
16
+ }
17
+ }
18
+ </button>
@@ -0,0 +1,34 @@
1
+ :host {
2
+ display: inline-flex;
3
+ }
4
+ button {
5
+ cursor: pointer;
6
+ background-color: var(--origo-color-surface-primary);
7
+ color: var(--origo-color-text-inverse);
8
+ padding: var(--origo-spacing-container-padding);
9
+ border: none;
10
+ border-radius: var(--origo-radius-sm);
11
+ box-shadow: var(--origo-shadow-sm, none);
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+ transition: var(--origo-transition-all);
16
+ }
17
+ button:hover:not(:disabled) {
18
+ background-color: var(--origo-color-surface-primary-hover);
19
+ }
20
+ button:active:not(:disabled) {
21
+ background-color: var(--origo-color-surface-primary-active);
22
+ }
23
+ button:focus-visible {
24
+ outline: var(--origo-outline-width, 2px) solid var(--origo-color-focus);
25
+ outline-offset: var(--origo-outline-width, 2px);
26
+ }
27
+ button:disabled {
28
+ cursor: not-allowed;
29
+ opacity: var(--origo-opacity-disabled);
30
+ }
31
+ :host(.origo-rounded) button {
32
+ border-radius: var(--origo-radius-round, 50%);
33
+ aspect-ratio: 1;
34
+ }
@@ -0,0 +1,102 @@
1
+ import {
2
+ Component,
3
+ input,
4
+ ChangeDetectionStrategy,
5
+ computed,
6
+ ViewEncapsulation,
7
+ inject,
8
+ } from '@angular/core';
9
+ import { InteractionContract } from '@origostudio/core';
10
+ import { OrigoAdapter } from '../../../adapters/web/adapter';
11
+ import { WebExperienceAdapterService } from '../../../adapters/web/experience-adapter.service';
12
+
13
+ export interface IconButtonProps {
14
+ icon?: string;
15
+ label?: string;
16
+ tooltip?: string;
17
+ severity?: string;
18
+ variant?: string;
19
+ rounded?: boolean;
20
+ loading?: boolean;
21
+ disabled?: boolean;
22
+ 'aria-label'?: string;
23
+ 'aria-describedby'?: string;
24
+ permissions?: any;
25
+ rules?: any;
26
+ metadata?: any;
27
+ }
28
+
29
+ @Component({
30
+ selector: 'origo-icon-button',
31
+ standalone: true,
32
+ templateUrl: './icon-button.component.html',
33
+ styleUrls: ['./icon-button.component.scss'],
34
+ changeDetection: ChangeDetectionStrategy.OnPush,
35
+ encapsulation: ViewEncapsulation.ShadowDom,
36
+ host: {
37
+ '[class]': 'computedHostClasses()',
38
+ '[attr.data-testid]': 'contract().id ?? ""',
39
+ },
40
+ })
41
+ export class IconButtonComponent implements OrigoAdapter<IconButtonProps> {
42
+ static readonly contractSchema = {
43
+ icon: 'string',
44
+ label: 'string',
45
+ tooltip: 'string',
46
+ severity: 'string',
47
+ variant: 'string',
48
+ rounded: 'boolean',
49
+ loading: 'boolean',
50
+ disabled: 'boolean',
51
+ 'aria-label': 'string',
52
+ 'aria-describedby': 'string',
53
+ permissions: 'object',
54
+ rules: 'object',
55
+ metadata: 'object',
56
+ };
57
+ static readonly strictContract = false;
58
+
59
+ contract = input.required<InteractionContract<IconButtonProps>>();
60
+
61
+ computedIcon = computed(() => this.contract().props?.icon ?? '');
62
+ computedLoading = computed(() => !!this.contract().props?.loading);
63
+ computedDisabled = computed(() => {
64
+ const props = this.contract().props;
65
+ const rulesDisable = props?.rules?.disable === true || props?.permissions?.allow === false;
66
+ return !!props?.disabled || this.computedLoading() || rulesDisable;
67
+ });
68
+
69
+ computedAriaLabel = computed(() => {
70
+ const p = this.contract().props;
71
+ const v = p?.['aria-label'] || p?.label;
72
+ return v ? String(v) : undefined;
73
+ });
74
+
75
+ computedAriaDescribedBy = computed(() => {
76
+ const v = this.contract().props?.['aria-describedby'];
77
+ return v ? String(v) : undefined;
78
+ });
79
+
80
+ computedHostClasses = computed(() => {
81
+ const s = this.contract().props?.severity;
82
+ const v = this.contract().props?.variant;
83
+ const rounded = this.contract().props?.rounded;
84
+ return [
85
+ 'origo-icon-button',
86
+ s ? `origo-severity-${s}` : '',
87
+ v ? `origo-variant-${v}` : '',
88
+ rounded ? 'origo-rounded' : '',
89
+ ]
90
+ .filter(Boolean)
91
+ .join(' ');
92
+ });
93
+
94
+ private experienceAdapter = inject(WebExperienceAdapterService);
95
+
96
+ onClick() {
97
+ if (this.computedDisabled() || this.computedLoading()) return;
98
+ const id = this.contract().id;
99
+ if (!id) return;
100
+ this.experienceAdapter.dispatchCapability(id, 'click');
101
+ }
102
+ }
@@ -5,6 +5,9 @@ export * from './adapters/web/adapter';
5
5
  export * from './components/primitives/vbox/vbox.component';
6
6
  export * from './components/primitives/text-input/text-input.component';
7
7
  export * from './components/primitives/button/button.component';
8
+ export * from './components/primitives/icon-button/icon-button.component';
9
+ export * from './components/primitives/button-group/button-group.component';
10
+ export * from './components/primitives/floating-action-button/floating-action-button.component';
8
11
  export * from './devtools';
9
12
  export * from './components/primitives/select/select.component';
10
13
  export * from './components/primitives/checkbox/checkbox.component';
@@ -1,5 +1,8 @@
1
1
  import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';
2
2
  import { RENDERER_REGISTRY } from './renderer.tokens';
3
+ import { IconButtonComponent } from '../components/primitives/icon-button/icon-button.component';
4
+ import { ButtonGroupComponent } from '../components/primitives/button-group/button-group.component';
5
+ import { FloatingActionButtonComponent } from '../components/primitives/floating-action-button/floating-action-button.component';
3
6
  import { SelectComponent } from '../components/primitives/select/select.component';
4
7
  import { CheckboxComponent } from '../components/primitives/checkbox/checkbox.component';
5
8
  import { RadioGroupComponent } from '../components/primitives/radio-group/radio-group.component';
@@ -21,6 +24,9 @@ import { VBoxComponent } from '../components/primitives/vbox/vbox.component';
21
24
 
22
25
  export function provideOrigo9Primitives(): EnvironmentProviders {
23
26
  const registryMap = new Map<string, unknown>([
27
+ ['IconButton', IconButtonComponent],
28
+ ['ButtonGroup', ButtonGroupComponent],
29
+ ['FloatingActionButton', FloatingActionButtonComponent],
24
30
  ['Select', SelectComponent],
25
31
  ['Checkbox', CheckboxComponent],
26
32
  ['RadioGroup', RadioGroupComponent],
@@ -1,3 +1,11 @@
1
+ ## 0.0.48 (2026-10-07)
2
+
3
+ This was a version bump only for cli to align it with other projects, there were no code changes.
4
+
5
+ ## 0.0.47 (2026-10-07)
6
+
7
+ This was a version bump only for cli to align it with other projects, there were no code changes.
8
+
1
9
  ## 0.0.46 (2026-10-02)
2
10
 
3
11
  This was a version bump only for cli to align it with other projects, there were no code changes.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@origostudio/cli",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
4
4
  "private": false,
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -9,7 +9,7 @@
9
9
  "origo": "./src/main.js"
10
10
  },
11
11
  "dependencies": {
12
- "@origostudio/core": "0.0.46",
12
+ "@origostudio/core": "0.0.48",
13
13
  "commander": "^15.0.0",
14
14
  "tslib": "^2.3.0"
15
15
  },
@@ -1,3 +1,11 @@
1
+ ## 0.0.48 (2026-10-07)
2
+
3
+ This was a version bump only for core to align it with other projects, there were no code changes.
4
+
5
+ ## 0.0.47 (2026-10-07)
6
+
7
+ This was a version bump only for core to align it with other projects, there were no code changes.
8
+
1
9
  ## 0.0.46 (2026-10-02)
2
10
 
3
11
  This was a version bump only for core to align it with other projects, there were no code changes.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@origostudio/core",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
4
4
  "private": false,
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -1,3 +1,11 @@
1
+ ## 0.0.48 (2026-10-07)
2
+
3
+ This was a version bump only for design-tokens to align it with other projects, there were no code changes.
4
+
5
+ ## 0.0.47 (2026-10-07)
6
+
7
+ This was a version bump only for design-tokens to align it with other projects, there were no code changes.
8
+
1
9
  ## 0.0.46 (2026-10-02)
2
10
 
3
11
  This was a version bump only for design-tokens to align it with other projects, there were no code changes.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@origostudio/design-tokens",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
4
4
  "private": false,
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",