Skip to content

Commit

Permalink
refactor: update button component and base layout
Browse files Browse the repository at this point in the history
- Update button component to include new styles and options
- Update base layout to fix flexbox alignment issue
  • Loading branch information
valerymelou committed May 20, 2024
1 parent 463674f commit be0f060
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 25 deletions.
6 changes: 5 additions & 1 deletion apps/portfolio/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
<html lang="en" class="dark scroll-smooth">
<head>
<meta charset="utf-8" />
<title>portfolio</title>
<title>Valery Melou</title>
<base href="/" />
<meta
name="description"
content="Web developer from Yaounde Cameroon. Crafting beautiful, interactive and accessible experiences for the web and the mobile."
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
Expand Down
5 changes: 2 additions & 3 deletions apps/portfolio/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ module.exports = {
colors: {
...colors,
dark: colors.slate[900],
primary: {
dark: '#5eead4',
light: colors.teal[700],
accent: {
base: '#068477',
},
},
fontFamily: {
Expand Down
18 changes: 17 additions & 1 deletion libs/pages/about/src/lib/about.component.html
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
<p>about works!</p>
<div class="flex flex-col flex-1 justify-center">
<div class="container max-w-3xl space-y-10">
<h1
class="md:text-6xl text-5xl leading-[3rem] font-bold dark:text-white text-black"
>
Hey, I'm Valery Melou
</h1>
<h2 class="text-2xl leading-10">
I'm a web developer from Yaounde, Cameroon.<br />
I build beautiful, interactive and accessible experiences for the web and
the mobile.
</h2>
<div>
<a href="/work" ui-flat-button color="accent" large>Check my work</a>
</div>
</div>
</div>
4 changes: 3 additions & 1 deletion libs/pages/about/src/lib/about.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ButtonComponent } from '@valerymelou/shared/ui';

@Component({
selector: 'app-about',
standalone: true,
imports: [CommonModule],
imports: [CommonModule, ButtonComponent],
templateUrl: './about.component.html',
styles: ':host {display: flex; flex-direction: column; flex: 1;}',
})
export class AboutComponent {}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="flex min-h-screen flex-col">
<app-navbar></app-navbar>
<main class="flex-1 flex flex-col pt-[72px]">
<div class="container max-w-[1024px] mx-auto px-4">
<div class="container max-w-[1024px] mx-auto px-4 flex flex-col flex-1">
<router-outlet></router-outlet>
</div>
</main>
Expand Down
10 changes: 5 additions & 5 deletions libs/shared/layout/src/lib/footer/footer.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,30 @@
Coded in
<a
href="https://code.visualstudio.com/"
class="dark:text-white hover:text-primary-dark transition-all duration-300 ease-in-out text-primary-light font-normal"
class="dark:text-white hover:text-accent-base transition-all duration-300 ease-in-out text-accent-light font-normal"
target="_blank"
rel="noopener"
>Visual Studio Code</a
>
by yours truly. Built with
<a
href="https://angular.dev"
class="dark:text-white hover:text-primary-dark transition-all duration-300 ease-in-out text-primary-light font-normal"
class="dark:text-white hover:text-accent-base transition-all duration-300 ease-in-out text-accent-light font-normal"
target="_blank"
rel="noopener"
>Angular</a
>
and
<a
href="https://tailwindcss.com/"
class="dark:text-white hover:text-primary-dark transition-all duration-300 ease-in-out text-primary-light font-normal"
class="dark:text-white hover:text-accent-base transition-all duration-300 ease-in-out text-accent-light font-normal"
target="_blank"
rel="noopener"
>Tailwind CSS</a
>, deployed by
<a
href="https://hostme.space/"
class="dark:text-white hover:text-primary-dark transition-all duration-300 ease-in-out text-primary-light font-normal"
class="dark:text-white hover:text-accent-base transition-all duration-300 ease-in-out text-accent-light font-normal"
target="_blank"
rel="noopener"
>Hostme</a
Expand All @@ -41,7 +41,7 @@
You can edit this website on
<a
href="https://github.com/valerymelou/valerymelou.com"
class="dark:text-white hover:text-primary-dark transition-all duration-300 ease-in-out text-primary-light font-normal"
class="dark:text-white hover:text-accent-base transition-all duration-300 ease-in-out text-accent-light font-normal"
target="_blank"
rel="noopener"
>GitHub</a
Expand Down
20 changes: 9 additions & 11 deletions libs/shared/layout/src/lib/navbar/navbar.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,24 @@
class="fixed top-0 left-0 right-0 mx-auto text-dark dark:bg-dark bg-white dark:text-white border-b dark:border-slate-700 border-slate-200"
>
<div class="container max-w-[1024px] mx-auto flex flex-col px-4">
<div class="flex justify-between w-full items-center mt-4 md:mb-0 mb-4">
<a href="/" class="flex items-center">
<div class="flex w-full mt-4 md:mb-0 mb-4">
<a href="/" class="flex items-center md:mb-2 mr-10">
<img
src="/assets/images/valerymelou.jpg"
class="rounded-full dark:border-white border-dark border-2"
alt="Valery Melou"
width="40"
height="40"
/>
<h1 class="mx-4 space-x-2 font-bold md:text-base text-sm">
Valery MELOU
</h1>
</a>
@if(showNavigation) {
<div
class="fixed top-[72px] bottom-0 left-0 right-0 backdrop-blur-lg dark:bg-dark bg-white bg-opacity-20"
class="fixed top-[72px] bottom-0 left-0 right-0 backdrop-blur-sm dark:bg-dark bg-white bg-opacity-20 dark:bg-opacity-20"
(click)="toggleNavigation()"
></div>
}
<nav
class="flex md:space-x-4 mx-auto font-display text-xs dark:text-slate-400 text-slate-700 md:relative fixed md:top-0 top-[72px] bottom-0 right-0 flex-col md:flex-row md:w-full w-3/5 py-8 px-8 md:p-0 md:translate-x-0 translate-x-full transition-all will-change-transform duration-300 ease-in-out shadow-lg md:shadow-none flex-1"
class="flex md:space-x-5 mr-auto font-display text-xs dark:bg-dark bg-white dark:text-slate-400 text-slate-700 md:relative fixed md:top-0 top-[72px] bottom-0 right-0 flex-col md:flex-row md:w-full w-3/5 py-8 px-8 md:p-0 md:translate-x-0 translate-x-full transition-all will-change-transform duration-300 ease-in-out shadow-lg md:shadow-none flex-1"
[ngClass]="{ 'translate-x-full': !showNavigation }"
>
@for (link of links; track link.label; let first = $first, last =
Expand All @@ -31,7 +28,7 @@ <h1 class="mx-4 space-x-2 font-bold md:text-base text-sm">
[routerLink]="link.path"
class="py-4 md:px-4 md:text-left text-right rounded-t-lg font-medium uppercase md:border -mb-[1px] border-transparent transition-all duration-300 ease-in-out dark:text-white dark:hover:text-white hover:text-black"
routerLinkActive="dark:text-white text-black dark:border-b-dark border-b-white dark:border-t-slate-700 dark:border-l-slate-700 dark:border-r-slate-700 border-t-slate-200 border-l-slate-200 border-r-slate-200"
[ngClass]="{ 'md:ml-auto': first, 'md:!mr-auto': last }"
[ngClass]="{ 'md:!mr-auto': last }"
>{{ link.label }}</a
>
} @for (link of socialLinks; track link.path) {
Expand All @@ -47,12 +44,12 @@ <h1 class="mx-4 space-x-2 font-bold md:text-base text-sm">
</a>
}
</nav>
<div class="flex ml-4 dark:text-slate-400 text-slate-700">
<div class="flex md:ml-5 dark:text-slate-400 text-slate-700 ml-auto">
<button
class="flex items-center"
class="flex items-center dark:text-slate-400 hover:text-black focus:text-black active:text-black dark:hover:text-white dark:active:text-white dark:focus:text-white transition-all duration-300 ease-in-out"
[uiMenuTriggerFor]="themeMenu"
[yOffset]="20"
[xPosition]="'after'"
aria-label="Change theme"
>
<ng-icon
[name]="theme === 'dark' ? 'matDarkModeRound' : 'matLightModeRound'"
Expand All @@ -62,6 +59,7 @@ <h1 class="mx-4 space-x-2 font-bold md:text-base text-sm">
<button
class="md:hidden flex items-center ml-4 dark:text-white text-black"
(click)="toggleNavigation()"
aria-label="Toggle navigation"
>
@if(showNavigation) {
<ng-icon name="matCloseRound" size="32"></ng-icon>
Expand Down
3 changes: 2 additions & 1 deletion libs/shared/layout/src/lib/navbar/navbar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ interface SocialLink {
})
export class NavbarComponent {
links: NavbarLink[] = [
{ label: 'About', path: '/' },
{ label: 'Home', path: '/' },
{ label: 'About', path: '/about' },
{ label: 'Experience', path: '/experience' },
{ label: 'Projects', path: '/projects' },
{ label: 'Blog', path: '/blog' },
Expand Down
2 changes: 1 addition & 1 deletion libs/shared/ui/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"type": ["element", "attribute"],
"prefix": "ui",
"style": "kebab-case"
}
Expand Down
2 changes: 2 additions & 0 deletions libs/shared/ui/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from './lib/button/button.component';

export * from './lib/menu/menu.component';

export * from './lib/menu/menu-trigger-for.directive';
1 change: 1 addition & 0 deletions libs/shared/ui/src/lib/button/button.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ng-content></ng-content>
35 changes: 35 additions & 0 deletions libs/shared/ui/src/lib/button/button.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Component } from '@angular/core';

import { ButtonComponent } from './button.component';

@Component({
template: `
<button ui-flat-button>Test</button>
<button ui-flat-button full>Test</button>
<button ui-flat-button large>Test</button>
<button ui-flat-button disabled>Test</button>
`,
selector: 'ui-button-test',
})
class ButtonTestComponent {}

describe('ButtonComponent', () => {
let component: ButtonTestComponent;
let fixture: ComponentFixture<ButtonTestComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ButtonTestComponent],
imports: [ButtonComponent],
}).compileComponents();

fixture = TestBed.createComponent(ButtonTestComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
110 changes: 110 additions & 0 deletions libs/shared/ui/src/lib/button/button.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import {
AfterViewInit,
Component,
ElementRef,
HostBinding,
Input,
booleanAttribute,
} from '@angular/core';
import { CommonModule } from '@angular/common';

/**
* List of attributes that can be used to add ButtonComponent instances on
* host attributes to style different variants.
*/
const BUTTON_HOST_ATTRIBUTES: string[] = ['ui-flat-button'];

/**
* Classes that can be added on host attribute per variant and per host attribute.
*/
const BUTTON_STYLE_CLASSES: { [name: string]: { [name: string]: string } } = {
'ui-flat-button': {
default:
'bg-white text-black disabled:text-black disabled:text-opacity-50 disabled:bg-white disabled:bg-opacity-50 disabled:cursor-default',
accent:
'bg-accent-base text-white disabled:text-white disabled:text-opacity-50 disabled:bg-accent-base disabled:bg-opacity-50 disabled:cursor-default',
},
};

/**
* Button component.
* Provides a standard button with different variants.
*/
@Component({
selector: 'button[ui-flat-button], a[ui-flat-button]',
standalone: true,
imports: [CommonModule],
templateUrl: './button.component.html',
})
export class ButtonComponent implements AfterViewInit {
@Input() color: 'default' | 'primary' | 'accent' | 'secondary' = 'default';
@Input({ transform: booleanAttribute }) disabled = false;
@Input({ transform: booleanAttribute }) large = false;
@Input({ transform: booleanAttribute }) full = false;
@HostBinding('attr.disabled') get valid() {
return this.disabled ? 'disabled' : null;
}

constructor(private _elementRef: ElementRef<HTMLElement>) {
// Button base classes:
this.getHostElement().classList.add(
'inline-flex',
'items-center',
'justify-center',
'leading-8',
'rounded-full',
'transition-all',
'duration-300',
'font-semibold'
);
}

ngAfterViewInit(): void {
// Add classes for button variant:
BUTTON_HOST_ATTRIBUTES.forEach((hostAttribute) => {
if (this.hasHostAttributes(hostAttribute)) {
this.addToClassList(BUTTON_STYLE_CLASSES[hostAttribute][this.color]);
}
});

// Add classes for button size:
if (this.large) {
this.addToClassList('px-8 py-4 text-lg');
} else {
this.addToClassList('px-4 py-3 text-sm leading-[18px]');
}

// Add classes for button width:
if (this.full) {
this.addToClassList('w-full');
}
}

/**
* Returns the host element.
* @returns The host element.
*/
private getHostElement(): HTMLElement {
return this._elementRef.nativeElement;
}

/**
* Checks if the host element has one of the given attributes.
* @param attributes
* @returns boolean
*/
private hasHostAttributes(...attributes: string[]): boolean {
return attributes.some((attribute) =>
this.getHostElement().hasAttribute(attribute)
);
}

/**
* Adds the given classes to the host element.
* @param className
*/
private addToClassList(className: string): void {
const classes = className.split(' ');
this.getHostElement().classList.add(...classes);
}
}

0 comments on commit be0f060

Please sign in to comment.