Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 5 additions & 155 deletions apps/demo/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,162 +1,12 @@
<header>
<h1>{{ title() }}</h1>
<nav>
<a routerLink="/buttons" routerLinkActive="active">Buttons</a>
<a routerLink="/i18n" routerLinkActive="active">Translations</a>
</nav>
<demo-color-scheme-switch></demo-color-scheme-switch>
</header>

<main>
<aside class="card">
<form>
<fieldset class="control-group">
<legend>State</legend>
<label>
<input
#disabledControl
type="checkbox"
(change)="disabled.set(disabledControl.checked); oldButton.disabled = disabledControl.checked"
/>
Disabled
</label>
<label>
<input
#loadingControl
type="checkbox"
(change)="loading.set(loadingControl.checked); oldButton.loading = loadingControl.checked"
/>
Loading
</label>
</fieldset>

<fieldset>
<legend>Type</legend>
<label>
<input
type="radio"
name="type"
[checked]="button.type() === 'button'"
(change)="button.type.set('button'); oldButton.type = 'button'"
/>
Button
</label>
<label>
<input
type="radio"
name="type"
[checked]="button.type() === 'submit'"
(change)="button.type.set('submit'); oldButton.type = 'submit'"
/>
Submit
</label>
</fieldset>

<fieldset>
<legend>Appearance</legend>
<label>
<input
type="radio"
name="appearance"
[checked]="!appearance()"
(change)="appearance.set(undefined); oldButton.appearance = undefined"
/>
Default
</label>
<label>
<input
type="radio"
name="appearance"
[checked]="appearance() === 'outline'"
(change)="appearance.set('outline'); oldButton.appearance = 'outline'"
/>
Outline
</label>
<label>
<input
type="radio"
name="appearance"
[checked]="appearance() === 'solid'"
(change)="appearance.set('solid'); oldButton.appearance = 'solid'"
/>
Solid
</label>
</fieldset>

<fieldset>
<legend>Color</legend>
<label>
<input
type="radio"
name="appearance"
[checked]="!color()"
(change)="color.set(undefined); oldButton.color = undefined"
/>
Default
</label>
<label>
<input
type="radio"
name="appearance"
[checked]="color() === 'red'"
(change)="color.set('red'); oldButton.color = 'red'"
/>
Red
</label>
<label>
<input
type="radio"
name="appearance"
[checked]="color() === 'green'"
(change)="color.set('green'); oldButton.color = 'green'"
/>
Green
</label>
</fieldset>
</form>
</aside>

<div class="card output">
<header>
<h2>Old</h2>
<p>
Using plain Angular APIs (<a
href="https://github.com/homj/angular-extensions/blob/main/apps/demo/src/app/components/old-button/old-button.component.ts"
target="_blank"
>code</a
>)
</p>
</header>
<demo-old-button
#oldButton
type="submit"
[disabled]="disabled()"
[loading]="loading()"
[appearance]="appearance()"
[color]="color()"
(click)="incrementCounter()"
>
Button
</demo-old-button>
</div>

<div class="card output">
<header>
<h2>New</h2>
<p>
Using <strong>&#64;homj/composables</strong> (<a
href="https://github.com/homj/angular-extensions/blob/main/apps/demo/src/app/components/button/button.component.ts"
target="_blank"
>code</a
>)
</p>
</header>
<demo-button
#button
type="submit"
[disabled]="disabled()"
[loading]="loading()"
[appearance]="appearance()"
[color]="color()"
(click)="incrementCounter()"
>
Button
</demo-button>
</div>
<router-outlet></router-outlet>
</main>
93 changes: 32 additions & 61 deletions apps/demo/src/app/app.component.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
:host {
display: flex;
flex-direction: column;
height: 100dvh;
min-height: 100dvh;
background-color: var(--surface-1);

@media (prefers-reduced-motion: no-preference) {
Expand All @@ -11,85 +11,56 @@
header {
align-items: center;
display: flex;
gap: 1.5rem;
justify-content: space-between;
margin: 2rem;
padding: 1rem 2rem;
border-bottom: var(--border-size-1) solid var(--surface-3);

@media (prefers-reduced-motion: no-preference) {
transition: border-color 0.3s var(--ease-1);
}

h1 {
max-inline-size: unset;
font-size: var(--font-size-fluid-1);

@media (prefers-reduced-motion: no-preference) {
transition: color 0.3s var(--ease-1);
}
}
}

main {
align-items: stretch;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 2rem;
justify-content: center;
margin-block: auto;
padding: 4rem;

aside {
background-color: white;
border-radius: 1rem;
padding: 0.5rem 1rem 1rem;

form {
align-items: stretch;
display: flex;
flex-direction: column;
gap: 1rem;
justify-content: center;
}
nav {
display: flex;
gap: 0.25rem;
flex: 1;

fieldset {
display: grid;
gap: 1rem;
min-width: 10rem;
a {
border-radius: var(--radius-2);
color: var(--text-2);
font-weight: var(--font-weight-5);
padding: 0.375rem 0.75rem;
text-decoration: none;

@media (prefers-reduced-motion: no-preference) {
transition: color 0.3s var(--ease-1), border-color 0.3s var(--ease-1);
&:hover {
color: var(--text-1);
background-color: var(--surface-3);
}
}
}

.output {
align-items: center;
display: flex;
justify-content: center;
min-height: 15rem;
width: 25rem;
max-width: 100%;
position: relative;

header {
display: flex;
flex-direction: column;
inset: 1rem 0.5rem auto 1rem;
position: absolute;

h2 {
font-size: var(--font-size-fluid-1);
&.active {
color: var(--brand);
background-color: var(--surface-2);
}

p {
color: var(--text-2);
@media (prefers-reduced-motion: no-preference) {
transition: color 0.2s var(--ease-1), background-color 0.2s var(--ease-1);
}
}
}
}

.card {
background-color: var(--surface-2);
border: var(--border-size-1) solid var(--surface-3);
border-radius: var(--radius-conditional-3);

@media (prefers-reduced-motion: no-preference) {
transition: background-color 0.3s var(--ease-1), border-color 0.3s var(--ease-1);
}
}
main {
display: flex;
flex: 1;
flex-direction: column;
}
}
22 changes: 0 additions & 22 deletions apps/demo/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,6 @@ describe('AppComponent', () => {
fixture.detectChanges();
});

describe('counter', () => {
it('should initially be 0', () => {
expect(fixture.componentInstance.counter()).toBe(0);
});

it('should be incremented by 1 after calling incrementCounter', () => {
fixture.componentInstance.incrementCounter();

expect(fixture.componentInstance.counter()).toBe(1);

fixture.componentInstance.incrementCounter();

expect(fixture.componentInstance.counter()).toBe(2);
});
});

describe('title', () => {
it(`should have the correct title`, () => {
expect(fixture.componentInstance.title()).toEqual('@homj/composables');
Expand All @@ -47,12 +31,6 @@ describe('AppComponent', () => {
it('should bind the title to the document', () => {
expect(document.title).toContain('@homj/composables');
});

it('should include the click counter after the first click', () => {
fixture.componentInstance.incrementCounter();

expect(fixture.componentInstance.title()).toEqual('@homj/composables - Clicks: 1');
});
});

it('should render the color-scheme-switch component', () => {
Expand Down
24 changes: 6 additions & 18 deletions apps/demo/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
import { Component, computed, signal } from '@angular/core';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterModule } from '@angular/router';
import { bindTitle } from '@homj/composables/title';
import { signal } from '@angular/core';

import { ButtonAppearance, ButtonColor, ButtonComponent } from './components/button/button.component';
import { ColorSchemeSwitchComponent } from './components/color-scheme-switch/color-scheme-switch.component';
import { OldButtonComponent } from './components/old-button/old-button.component';

@Component({
imports: [RouterModule, ButtonComponent, ColorSchemeSwitchComponent, OldButtonComponent],
imports: [RouterModule, ColorSchemeSwitchComponent],
selector: 'demo-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
styleUrls: ['./app.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
readonly counter = signal(0);
readonly title = bindTitle(
computed(() => (this.counter() ? `@homj/composables - Clicks: ${this.counter()}` : '@homj/composables'))
);

readonly disabled = signal(false);
readonly loading = signal(false);
readonly appearance = signal<ButtonAppearance>('solid');
readonly color = signal<ButtonColor>(undefined);

incrementCounter() {
this.counter.update((value) => value + 1);
}
readonly title = bindTitle(signal('@homj/composables'));
}
6 changes: 5 additions & 1 deletion apps/demo/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { ApplicationConfig } from '@angular/core';
import { provideRouter, withEnabledBlockingInitialNavigation } from '@angular/router';
import { Language, provideTranslation } from '@homj/composables/i18n';

import { appRoutes } from './app.routes';

export const appConfig: ApplicationConfig = {
providers: [ provideRouter(appRoutes, withEnabledBlockingInitialNavigation()) ]
providers: [
provideRouter(appRoutes, withEnabledBlockingInitialNavigation()),
provideTranslation((lang) => import(`./i18n/${lang}.json`).then((m) => m.default), 'en' as Language)
]
};
12 changes: 11 additions & 1 deletion apps/demo/src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
import { Route } from '@angular/router';

export const appRoutes: Route[] = [];
export const appRoutes: Route[] = [
{ path: '', redirectTo: 'buttons', pathMatch: 'full' },
{
path: 'buttons',
loadComponent: () => import('./pages/buttons/buttons-demo.component').then((m) => m.ButtonsDemoComponent)
},
{
path: 'i18n',
loadComponent: () => import('./pages/i18n-demo/i18n-demo.component').then((m) => m.I18nDemoComponent)
}
];
Loading
Loading