mirror of
https://github.com/Raghu-Ch/angular-challenges.git
synced 2026-02-10 12:53:03 -05:00
feat(challenge13): create challenge 13 about styling
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
import { Component } from '@angular/core';
|
||||
import { NxWelcomeComponent } from './nx-welcome.component';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -11,3 +11,5 @@ import { Component } from '@angular/core';
|
||||
export class AppComponent {
|
||||
title = 'rxjs-race-condition';
|
||||
}
|
||||
|
||||
// faire une app qui fonctionne mais pas dans les tests e2e à cause du délai de la requete http.
|
||||
|
||||
36
apps/styling/.eslintrc.json
Normal file
36
apps/styling/.eslintrc.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"extends": ["../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts"],
|
||||
"rules": {
|
||||
"@angular-eslint/directive-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "attribute",
|
||||
"prefix": "app",
|
||||
"style": "camelCase"
|
||||
}
|
||||
],
|
||||
"@angular-eslint/component-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "element",
|
||||
"prefix": "app",
|
||||
"style": "kebab-case"
|
||||
}
|
||||
]
|
||||
},
|
||||
"extends": [
|
||||
"plugin:@nrwl/nx/angular",
|
||||
"plugin:@angular-eslint/template/process-inline-templates"
|
||||
]
|
||||
},
|
||||
{
|
||||
"files": ["*.html"],
|
||||
"extends": ["plugin:@nrwl/nx/angular-template"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
33
apps/styling/README.md
Normal file
33
apps/styling/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
<h1>Customizable style</h1>
|
||||
|
||||
> Author: Thomas Laforge
|
||||
|
||||
Styling is an important part of a day job of a frontend developer often underestimated. In Angular application, I often see people use `@Input()` to customize the style of their component. But `@Input()` should be used only for the logic and we should use other technique for styling. We can take advantage of css variable and host-context.
|
||||
|
||||
In this challenge, you will need to use both to delete all `@Input()` from your code.
|
||||
|
||||
Styling is an important aspect of a frontend developer's day job, but it is often underestimated. In Angular applications, I frequently see people using `@Input()` to customize the style of their components. However, `@Input()` should only be used for logic; and other techniques, such as CSS variables and host-context, should be used for styling.
|
||||
|
||||
In this challenge, you will need to use both CSS variables and :host-context to remove all `@Input()` from your code.
|
||||
|
||||
### Constraints:
|
||||
|
||||
- In your final submission, your component should not contain any lines of code. All styling should be handled within the decorator _(or external css files if you prefer)_
|
||||
|
||||
### Submitting your work
|
||||
|
||||
1. Fork the project
|
||||
2. clone it
|
||||
3. npm install
|
||||
4. **nx serve styling**
|
||||
5. _...work on it_
|
||||
6. Commit your work
|
||||
7. Submit a PR with a title beginning with **Answer:13** that I will review and other dev can review.
|
||||
|
||||
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A13+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="styling"/></a>
|
||||
|
||||
<!-- TODO: uncomment when done late -->
|
||||
<!-- <a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A13+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="styling solution author"/></a>
|
||||
<a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="styling blog article"/></a> -->
|
||||
|
||||
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>
|
||||
76
apps/styling/project.json
Normal file
76
apps/styling/project.json
Normal file
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"name": "styling",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"projectType": "application",
|
||||
"sourceRoot": "apps/styling/src",
|
||||
"prefix": "app",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@angular-devkit/build-angular:browser",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"options": {
|
||||
"outputPath": "dist/apps/styling",
|
||||
"index": "apps/styling/src/index.html",
|
||||
"main": "apps/styling/src/main.ts",
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "apps/styling/tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": ["apps/styling/src/favicon.ico", "apps/styling/src/assets"],
|
||||
"styles": ["apps/styling/src/styles.scss"],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "500kb",
|
||||
"maximumError": "1mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "2kb",
|
||||
"maximumError": "4kb"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"development": {
|
||||
"buildOptimizer": false,
|
||||
"optimization": false,
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"executor": "@angular-devkit/build-angular:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "styling:build:production"
|
||||
},
|
||||
"development": {
|
||||
"browserTarget": "styling:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"executor": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "styling:build"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/styling/**/*.ts", "apps/styling/**/*.html"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
17
apps/styling/src/app/page.component.ts
Normal file
17
apps/styling/src/app/page.component.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
import { Component } from '@angular/core';
|
||||
import { TextStaticComponent } from './static-text.component';
|
||||
import { TextComponent } from './text.component';
|
||||
|
||||
@Component({
|
||||
selector: 'page',
|
||||
standalone: true,
|
||||
imports: [TextStaticComponent, TextComponent],
|
||||
template: `
|
||||
<static-text></static-text>
|
||||
<static-text type="error"></static-text>
|
||||
<static-text type="warning"></static-text>
|
||||
<text [font]="15" color="blue">This a a blue text</text>
|
||||
`,
|
||||
})
|
||||
export class PageComponent {}
|
||||
33
apps/styling/src/app/static-text.component.ts
Normal file
33
apps/styling/src/app/static-text.component.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { TextComponent } from './text.component';
|
||||
|
||||
export type StaticTextType = 'normal' | 'warning' | 'error';
|
||||
|
||||
@Component({
|
||||
selector: 'static-text',
|
||||
standalone: true,
|
||||
imports: [TextComponent],
|
||||
template: `
|
||||
<text [font]="font" [color]="color">This is a static text</text>
|
||||
`,
|
||||
})
|
||||
export class TextStaticComponent {
|
||||
@Input() set type(type: StaticTextType) {
|
||||
switch (type) {
|
||||
case 'error': {
|
||||
this.font = 30;
|
||||
this.color = 'red';
|
||||
break;
|
||||
}
|
||||
case 'warning': {
|
||||
this.font = 25;
|
||||
this.color = 'orange';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
font = 10;
|
||||
color = 'black';
|
||||
}
|
||||
16
apps/styling/src/app/text.component.ts
Normal file
16
apps/styling/src/app/text.component.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'text',
|
||||
standalone: true,
|
||||
template: `
|
||||
<p style="font-size: {{ font }}px; color: {{ color }}">
|
||||
<ng-content></ng-content>
|
||||
</p>
|
||||
`,
|
||||
})
|
||||
export class TextComponent {
|
||||
@Input() font = 10;
|
||||
@Input() color = 'black';
|
||||
}
|
||||
0
apps/styling/src/assets/.gitkeep
Normal file
0
apps/styling/src/assets/.gitkeep
Normal file
BIN
apps/styling/src/favicon.ico
Normal file
BIN
apps/styling/src/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
13
apps/styling/src/index.html
Normal file
13
apps/styling/src/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Styling</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
</head>
|
||||
<body>
|
||||
<page></page>
|
||||
</body>
|
||||
</html>
|
||||
4
apps/styling/src/main.ts
Normal file
4
apps/styling/src/main.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { bootstrapApplication } from '@angular/platform-browser';
|
||||
import { PageComponent } from './app/page.component';
|
||||
|
||||
bootstrapApplication(PageComponent).catch((err) => console.error(err));
|
||||
1
apps/styling/src/styles.scss
Normal file
1
apps/styling/src/styles.scss
Normal file
@@ -0,0 +1 @@
|
||||
/* You can add global styles to this file, and also import other style files */
|
||||
10
apps/styling/tsconfig.app.json
Normal file
10
apps/styling/tsconfig.app.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": []
|
||||
},
|
||||
"files": ["src/main.ts"],
|
||||
"include": ["src/**/*.d.ts"],
|
||||
"exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
|
||||
}
|
||||
7
apps/styling/tsconfig.editor.json
Normal file
7
apps/styling/tsconfig.editor.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"types": []
|
||||
}
|
||||
}
|
||||
29
apps/styling/tsconfig.json
Normal file
29
apps/styling/tsconfig.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2022",
|
||||
"useDefineForClassFields": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.editor.json"
|
||||
}
|
||||
],
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"strictTemplates": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user