Skip to content

Commit 0d39080

Browse files
authored
Merge branch 'main' into lmendoza/PD-5410
2 parents 092198c + e340845 commit 0d39080

27 files changed

Lines changed: 1096 additions & 336 deletions

projects/orcid-ui-docs/src/app/app.routes.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ export const routes: Routes = [
9393
(m) => m.SkeletonPlaceholderPageComponent
9494
),
9595
},
96+
{
97+
path: 'step-view',
98+
loadComponent: () =>
99+
import('./pages/orcid-ui/step-view-page.component').then(
100+
(m) => m.StepViewPageComponent
101+
),
102+
},
96103
{
97104
path: 'auth-challenge',
98105
loadComponent: () =>

projects/orcid-ui-docs/src/app/docs-shell.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ <h1 class="docs-logo">Orcid UI</h1>
3434
<a routerLink="/skeleton-placeholder" routerLinkActive="active">
3535
Skeleton Placeholder
3636
</a>
37+
<a routerLink="/step-view" routerLinkActive="active"> Step View </a>
3738
<a routerLink="/material-buttons-directives" routerLinkActive="active">
3839
Material Buttons Directives
3940
</a>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<app-documentation-page
2+
i18n-title="@@orcidUiDocs.stepView.title"
3+
i18n-description="@@orcidUiDocs.stepView.description"
4+
title="Step View"
5+
description="A reusable step shell for guided flows with title/subtitle, projected body content, optional footer projection, and a primary action output."
6+
>
7+
<div controls>
8+
<p>Change these values to preview `orcid-step-view` behavior:</p>
9+
<div class="controls-grid">
10+
<mat-form-field appearance="outline">
11+
<mat-label>Title</mat-label>
12+
<input matInput [(ngModel)]="config.title" />
13+
</mat-form-field>
14+
15+
<mat-form-field appearance="outline">
16+
<mat-label>Subtitle</mat-label>
17+
<input matInput [(ngModel)]="config.subtitle" />
18+
</mat-form-field>
19+
20+
<mat-form-field appearance="outline">
21+
<mat-label>Primary action label</mat-label>
22+
<input matInput [(ngModel)]="config.primaryLabel" />
23+
</mat-form-field>
24+
25+
<mat-checkbox [(ngModel)]="config.primaryDisabled">
26+
Disable primary action
27+
</mat-checkbox>
28+
29+
<mat-checkbox [(ngModel)]="config.fullWidthActions">
30+
Full width actions
31+
</mat-checkbox>
32+
</div>
33+
</div>
34+
35+
<div examples>
36+
<div class="example-container">
37+
<orcid-step-view
38+
[title]="config.title"
39+
[subtitle]="config.subtitle"
40+
[primaryLabel]="config.primaryLabel"
41+
[primaryDisabled]="config.primaryDisabled"
42+
[fullWidthActions]="config.fullWidthActions"
43+
>
44+
<p class="orc-ui-font-body body-copy">
45+
Use this projected body region for form controls and explanatory text.
46+
</p>
47+
<p class="orc-ui-font-body-small body-copy">
48+
The parent flow controls step transitions and handles output events.
49+
</p>
50+
51+
<div orcidStepViewFooter class="preview-footer">
52+
<button mat-button type="button">Projected footer action</button>
53+
</div>
54+
</orcid-step-view>
55+
</div>
56+
</div>
57+
58+
<div usage>
59+
<pre><code class="language-html">&lt;orcid-step-view
60+
[title]="title"
61+
[subtitle]="subtitle"
62+
[primaryLabel]="primaryLabel"
63+
[primaryDisabled]="isPrimaryDisabled"
64+
(primaryAction)="onPrimary()"
65+
&gt;
66+
&lt;div&gt;Step content goes here&lt;/div&gt;
67+
68+
&lt;div orcidStepViewFooter&gt;
69+
&lt;button mat-button type="button"&gt;Extra footer control&lt;/button&gt;
70+
&lt;/div&gt;
71+
&lt;/orcid-step-view&gt;</code></pre>
72+
</div>
73+
74+
<div inputs>
75+
<h4>Inputs</h4>
76+
<ul>
77+
<li><code>title</code>: Main step title.</li>
78+
<li>
79+
<code>subtitle</code>: Optional secondary line (for step count copy).
80+
</li>
81+
<li><code>primaryLabel</code>: Optional primary button label.</li>
82+
<li><code>primaryDisabled</code>: Disables primary action.</li>
83+
<li>
84+
<code>fullWidthActions</code>: Makes action buttons stretch to width.
85+
</li>
86+
</ul>
87+
88+
<h4>Outputs</h4>
89+
<ul>
90+
<li>
91+
<code>primaryAction</code>: Emitted when primary action is clicked.
92+
</li>
93+
</ul>
94+
95+
<h4>Slots</h4>
96+
<ul>
97+
<li>Default slot: Main step body content.</li>
98+
<li>
99+
<code>[orcidStepViewFooter]</code>: Optional projected footer area.
100+
</li>
101+
</ul>
102+
</div>
103+
</app-documentation-page>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.controls-grid {
2+
display: grid;
3+
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
4+
gap: 16px;
5+
margin-top: 16px;
6+
}
7+
8+
.example-container {
9+
max-width: 680px;
10+
}
11+
12+
.body-copy {
13+
margin: 0;
14+
}
15+
16+
.preview-footer {
17+
display: flex;
18+
justify-content: flex-end;
19+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { CommonModule } from '@angular/common'
2+
import { Component } from '@angular/core'
3+
import { FormsModule } from '@angular/forms'
4+
import { MatButtonModule } from '@angular/material/button'
5+
import { MatCheckboxModule } from '@angular/material/checkbox'
6+
import { MatFormFieldModule } from '@angular/material/form-field'
7+
import { MatInputModule } from '@angular/material/input'
8+
import { OrcidStepViewComponent } from '@orcid/ui'
9+
import { DocumentationPageComponent } from '../../components/documentation-page/documentation-page.component'
10+
11+
@Component({
12+
selector: 'orcid-step-view-page',
13+
standalone: true,
14+
imports: [
15+
CommonModule,
16+
FormsModule,
17+
MatButtonModule,
18+
MatCheckboxModule,
19+
MatFormFieldModule,
20+
MatInputModule,
21+
OrcidStepViewComponent,
22+
DocumentationPageComponent,
23+
],
24+
templateUrl: './step-view-page.component.html',
25+
styleUrls: ['./step-view-page.component.scss'],
26+
})
27+
export class StepViewPageComponent {
28+
config = {
29+
title: 'Enable two-factor authentication',
30+
subtitle: 'Step 1 of 2 - Authentication app',
31+
primaryLabel: 'Next step - 2FA recovery codes',
32+
primaryDisabled: false,
33+
fullWidthActions: true,
34+
}
35+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<section class="orcid-step-view">
2+
<header class="orcid-step-view__header">
3+
<img
4+
*ngIf="showHeaderIcon"
5+
class="orcid-step-view__icon"
6+
[src]="headerIconSrc"
7+
[alt]="headerIconAlt"
8+
/>
9+
<h2 class="orcid-step-view__title">{{ title }}</h2>
10+
<p *ngIf="subtitle" class="orcid-step-view__subtitle">{{ subtitle }}</p>
11+
</header>
12+
13+
<div class="orcid-step-view__body">
14+
<ng-content></ng-content>
15+
</div>
16+
17+
<footer class="orcid-step-view__footer">
18+
<ng-content select="[orcidStepViewFooter]"></ng-content>
19+
<div class="orcid-step-view__footer-divider"></div>
20+
<div
21+
class="orcid-step-view__actions"
22+
[class.orcid-step-view__actions--full]="fullWidthActions"
23+
>
24+
<button
25+
*ngIf="primaryLabel"
26+
mat-flat-button
27+
class="orcid-step-view__primary-action"
28+
type="button"
29+
[disabled]="primaryDisabled"
30+
(click)="primaryAction.emit()"
31+
>
32+
{{ primaryLabel }}
33+
</button>
34+
</div>
35+
</footer>
36+
</section>
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
:host {
2+
display: block;
3+
}
4+
5+
.orcid-step-view {
6+
background: var(--orcid-surface, #ffffff);
7+
border: 1px solid var(--orcid-ui-background, #bdbdbd);
8+
border-radius: var(--orcid-space-2, 8px);
9+
padding: var(--orcid-space-xl, 64px);
10+
display: flex;
11+
flex-direction: column;
12+
gap: var(--orcid-space-8, 32px);
13+
}
14+
15+
.orcid-step-view__header {
16+
display: flex;
17+
flex-direction: column;
18+
gap: var(--orcid-space-2, 8px);
19+
text-align: center;
20+
}
21+
22+
.orcid-step-view__icon {
23+
width: 64px;
24+
height: 64px;
25+
margin: 0 auto;
26+
margin-bottom: var(--orcid-space-m, 24px);
27+
}
28+
29+
.orcid-step-view__title {
30+
margin: 0;
31+
color: var(--orcid-color-text-dark-high, #000000);
32+
font-family: var(--orcid-font-family-sans, 'Noto Sans', sans-serif);
33+
font-size: var(--orcid-font-size-heading-small, 24px);
34+
font-weight: var(--orcid-font-weight-medium, 500);
35+
line-height: 1.5;
36+
}
37+
38+
.orcid-step-view__subtitle {
39+
margin: 0;
40+
color: rgba(0, 0, 0, 0.6);
41+
font-family: var(--orcid-font-family-sans, 'Noto Sans', sans-serif);
42+
font-size: var(--orcid-font-size-body-small, 14px);
43+
font-weight: var(--orcid-font-weight-regular, 400);
44+
line-height: 1.5;
45+
}
46+
47+
.orcid-step-view__body {
48+
display: flex;
49+
flex-direction: column;
50+
}
51+
52+
.orcid-step-view__footer {
53+
display: flex;
54+
flex-direction: column;
55+
gap: var(--orcid-space-8, 32px);
56+
}
57+
58+
.orcid-step-view__footer-divider {
59+
width: 100%;
60+
border-top: 1px solid var(--orcid-color-border-subtle, #dddddd);
61+
}
62+
63+
.orcid-step-view__actions {
64+
display: flex;
65+
gap: var(--orcid-space-4, 16px);
66+
justify-content: center;
67+
}
68+
69+
.orcid-step-view__actions--full {
70+
width: 100%;
71+
}
72+
73+
.orcid-step-view__actions--full button {
74+
flex: 1 1 auto;
75+
}
76+
77+
.orcid-step-view__primary-action {
78+
background-color: var(--orcid-color-brand-secondary-dark, #085c77) !important;
79+
color: var(--orcid-color-text-light-high, #ffffff) !important;
80+
}
81+
82+
.orcid-step-view__primary-action[disabled] {
83+
opacity: 0.6;
84+
}
85+
86+
@media (max-width: 767px) {
87+
.orcid-step-view {
88+
padding: var(--orcid-space-4, 16px);
89+
border: 0;
90+
border-radius: 0;
91+
}
92+
93+
.orcid-step-view__icon {
94+
margin-bottom: var(--orcid-space-s, 8px);
95+
}
96+
97+
.orcid-step-view__actions {
98+
flex-direction: column;
99+
width: 100%;
100+
}
101+
102+
.orcid-step-view__actions button {
103+
width: 100%;
104+
}
105+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Component, EventEmitter, Input, Output } from '@angular/core'
2+
import { NgIf } from '@angular/common'
3+
import { MatButtonModule } from '@angular/material/button'
4+
5+
@Component({
6+
selector: 'orcid-step-view',
7+
standalone: true,
8+
imports: [NgIf, MatButtonModule],
9+
templateUrl: './step-view.component.html',
10+
styleUrls: ['./step-view.component.scss'],
11+
})
12+
export class OrcidStepViewComponent {
13+
/** Main title displayed at the top of the step view. */
14+
@Input() title = ''
15+
16+
/** Optional subtitle shown below title (e.g. Step 1 of 2). */
17+
@Input() subtitle = ''
18+
19+
/** Show ORCID icon block in header. */
20+
@Input() showHeaderIcon = true
21+
22+
/** Header icon source path. */
23+
@Input() headerIconSrc = 'assets/vectors/orcid.logo.icon.svg'
24+
25+
/** Header icon alt text. */
26+
@Input() headerIconAlt = 'orcid logo'
27+
28+
/** Optional text for the primary action button. */
29+
@Input() primaryLabel = ''
30+
31+
/** Disables the primary action button when true. */
32+
@Input() primaryDisabled = false
33+
34+
/** Whether footer buttons should fill the container width. */
35+
@Input() fullWidthActions = true
36+
37+
@Output() primaryAction = new EventEmitter<void>()
38+
}

projects/orcid-ui/src/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ export * from './lib/components/action-surface-container/action-surface-containe
1515
export * from './lib/components/panel/panel.component'
1616
export * from './lib/components/skeleton-placeholder/skeleton-placeholder.component'
1717
export * from './lib/components/modal/modal.component'
18+
export * from './lib/components/step-view/step-view.component'

0 commit comments

Comments
 (0)