From 9d1023935ebec47454b357fd6404257145909616 Mon Sep 17 00:00:00 2001 From: FORESTIER Fabien <fabien.forestier@soprasteria.com> Date: Fri, 23 Mar 2018 13:38:59 +0100 Subject: [PATCH] Add bootstrap-grid, create core module, dive the app in three main component header, main, footer, add base of theming --- webapp/.angular-cli.json | 3 +- webapp/package-lock.json | 6 + webapp/package.json | 1 + webapp/src/app/app-routing.module.ts | 12 + webapp/src/app/app.component.html | 20 +- webapp/src/app/app.module.ts | 7 +- .../components/footer/footer.component.html | 3 + .../components/footer/footer.component.scss | 0 .../footer/footer.component.spec.ts | 25 + .../components/footer/footer.component.ts | 15 + .../components/header/header.component.html | 3 + .../components/header/header.component.scss | 0 .../header/header.component.spec.ts | 25 + .../components/header/header.component.ts | 15 + .../core/components/main/main.component.html | 9 + .../core/components/main/main.component.scss | 0 .../components/main/main.component.spec.ts | 25 + .../core/components/main/main.component.ts | 15 + webapp/src/app/core/core-routing.module.ts | 13 + webapp/src/app/core/core.module.ts | 18 + .../src/assets/img/android-chrome-192x192.png | Bin 0 -> 5193 bytes .../src/assets/img/android-chrome-512x512.png | Bin 0 -> 15280 bytes webapp/src/assets/img/apple-touch-icon.png | Bin 0 -> 4823 bytes webapp/src/assets/img/favicon-16x16.png | Bin 0 -> 727 bytes webapp/src/assets/img/favicon-32x32.png | Bin 0 -> 1354 bytes webapp/src/assets/img/favicon.ico | Bin 0 -> 15086 bytes webapp/src/assets/img/logo.svg | 5 + webapp/src/scss/_functions.scss | 86 ++ webapp/src/scss/_grid.scss | 52 + webapp/src/scss/_variables.scss | 894 ++++++++++++++++++ webapp/src/scss/bootstrap-grid.scss | 32 + webapp/src/scss/mixins/_breakpoints.scss | 123 +++ webapp/src/scss/mixins/_grid-framework.scss | 67 ++ webapp/src/scss/mixins/_grid.scss | 52 + webapp/src/scss/utilities/_display.scss | 38 + webapp/src/scss/utilities/_flex.scss | 46 + webapp/src/styles.scss | 18 + webapp/src/theme.scss | 17 + webapp/src/theming/_all-theme.scss | 29 + webapp/src/theming/_theming.scss | 11 + .../theming/grandlyon/config/_palette.scss | 89 ++ .../theming/grandlyon/config/_variables.scss | 9 + webapp/src/theming/grandlyon/grandlyon.scss | 10 + 43 files changed, 1771 insertions(+), 22 deletions(-) create mode 100644 webapp/src/app/app-routing.module.ts create mode 100644 webapp/src/app/core/components/footer/footer.component.html create mode 100644 webapp/src/app/core/components/footer/footer.component.scss create mode 100644 webapp/src/app/core/components/footer/footer.component.spec.ts create mode 100644 webapp/src/app/core/components/footer/footer.component.ts create mode 100644 webapp/src/app/core/components/header/header.component.html create mode 100644 webapp/src/app/core/components/header/header.component.scss create mode 100644 webapp/src/app/core/components/header/header.component.spec.ts create mode 100644 webapp/src/app/core/components/header/header.component.ts create mode 100644 webapp/src/app/core/components/main/main.component.html create mode 100644 webapp/src/app/core/components/main/main.component.scss create mode 100644 webapp/src/app/core/components/main/main.component.spec.ts create mode 100644 webapp/src/app/core/components/main/main.component.ts create mode 100644 webapp/src/app/core/core-routing.module.ts create mode 100644 webapp/src/app/core/core.module.ts create mode 100644 webapp/src/assets/img/android-chrome-192x192.png create mode 100644 webapp/src/assets/img/android-chrome-512x512.png create mode 100644 webapp/src/assets/img/apple-touch-icon.png create mode 100644 webapp/src/assets/img/favicon-16x16.png create mode 100644 webapp/src/assets/img/favicon-32x32.png create mode 100644 webapp/src/assets/img/favicon.ico create mode 100644 webapp/src/assets/img/logo.svg create mode 100644 webapp/src/scss/_functions.scss create mode 100644 webapp/src/scss/_grid.scss create mode 100644 webapp/src/scss/_variables.scss create mode 100644 webapp/src/scss/bootstrap-grid.scss create mode 100644 webapp/src/scss/mixins/_breakpoints.scss create mode 100644 webapp/src/scss/mixins/_grid-framework.scss create mode 100644 webapp/src/scss/mixins/_grid.scss create mode 100644 webapp/src/scss/utilities/_display.scss create mode 100644 webapp/src/scss/utilities/_flex.scss create mode 100644 webapp/src/theme.scss create mode 100644 webapp/src/theming/_all-theme.scss create mode 100644 webapp/src/theming/_theming.scss create mode 100644 webapp/src/theming/grandlyon/config/_palette.scss create mode 100644 webapp/src/theming/grandlyon/config/_variables.scss create mode 100644 webapp/src/theming/grandlyon/grandlyon.scss diff --git a/webapp/.angular-cli.json b/webapp/.angular-cli.json index 862071be..8310aa96 100644 --- a/webapp/.angular-cli.json +++ b/webapp/.angular-cli.json @@ -19,7 +19,8 @@ "testTsconfig": "tsconfig.spec.json", "prefix": "app", "styles": [ - "styles.scss" + "styles.scss", + "theme.scss" ], "scripts": [], "environmentSource": "environments/environment.ts", diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 9ba90098..090f6bca 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -9167,6 +9167,12 @@ "pify": "3.0.0" } }, + "sass-recursive-map-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sass-recursive-map-merge/-/sass-recursive-map-merge-1.0.1.tgz", + "integrity": "sha512-OuDTGVGx2o2sPeaSgGob5s2Qf6LxoMU4LG7n6vCzNgfXyBz/y8tKzcEYdmvgyhjvGQVcGA1g2UJnP7WMmahuVg==", + "dev": true + }, "saucelabs": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.3.0.tgz", diff --git a/webapp/package.json b/webapp/package.json index 20789ef7..01a56507 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -45,6 +45,7 @@ "protractor": "~5.1.2", "ts-node": "~4.1.0", "tslint": "~5.9.1", + "sass-recursive-map-merge": "^1.0.1", "typescript": "~2.5.3" } } diff --git a/webapp/src/app/app-routing.module.ts b/webapp/src/app/app-routing.module.ts new file mode 100644 index 00000000..5c38405b --- /dev/null +++ b/webapp/src/app/app-routing.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +const routes: Routes = [ + { path: '', redirectTo: 'app', pathMatch: 'full' } +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] +}) +export class AppRoutingModule { } diff --git a/webapp/src/app/app.component.html b/webapp/src/app/app.component.html index fa2706a4..6a164d69 100644 --- a/webapp/src/app/app.component.html +++ b/webapp/src/app/app.component.html @@ -1,20 +1,2 @@ -<!--The content below is only a placeholder and can be replaced.--> -<div style="text-align:center"> - <h1> - Welcome to {{ title }}! - </h1> - <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="> -</div> -<h2>Here are some links to help you start: </h2> -<ul> - <li> - <h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2> - </li> - <li> - <h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2> - </li> - <li> - <h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2> - </li> -</ul> +<router-outlet></router-outlet> diff --git a/webapp/src/app/app.module.ts b/webapp/src/app/app.module.ts index f4b848b8..2d9e72fb 100644 --- a/webapp/src/app/app.module.ts +++ b/webapp/src/app/app.module.ts @@ -4,8 +4,9 @@ import { NgModule } from '@angular/core'; import { AppMaterialModule } from './app.material.module'; - import { AppComponent } from './app.component'; +import { AppRoutingModule } from './app-routing.module'; +import { CoreModule } from './core/core.module'; @NgModule({ @@ -15,7 +16,9 @@ import { AppComponent } from './app.component'; imports: [ BrowserModule, BrowserAnimationsModule, - AppMaterialModule + AppMaterialModule, + CoreModule, + AppRoutingModule ], providers: [], bootstrap: [AppComponent] diff --git a/webapp/src/app/core/components/footer/footer.component.html b/webapp/src/app/core/components/footer/footer.component.html new file mode 100644 index 00000000..6800e0eb --- /dev/null +++ b/webapp/src/app/core/components/footer/footer.component.html @@ -0,0 +1,3 @@ +<p> + footer works! +</p> diff --git a/webapp/src/app/core/components/footer/footer.component.scss b/webapp/src/app/core/components/footer/footer.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/webapp/src/app/core/components/footer/footer.component.spec.ts b/webapp/src/app/core/components/footer/footer.component.spec.ts new file mode 100644 index 00000000..2ca6c454 --- /dev/null +++ b/webapp/src/app/core/components/footer/footer.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FooterComponent } from './footer.component'; + +describe('FooterComponent', () => { + let component: FooterComponent; + let fixture: ComponentFixture<FooterComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ FooterComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FooterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/webapp/src/app/core/components/footer/footer.component.ts b/webapp/src/app/core/components/footer/footer.component.ts new file mode 100644 index 00000000..da17d824 --- /dev/null +++ b/webapp/src/app/core/components/footer/footer.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-footer', + templateUrl: './footer.component.html', + styleUrls: ['./footer.component.scss'] +}) +export class FooterComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/webapp/src/app/core/components/header/header.component.html b/webapp/src/app/core/components/header/header.component.html new file mode 100644 index 00000000..c3dba658 --- /dev/null +++ b/webapp/src/app/core/components/header/header.component.html @@ -0,0 +1,3 @@ +<mat-toolbar color="primary"> + <span>OpenData</span> +</mat-toolbar> \ No newline at end of file diff --git a/webapp/src/app/core/components/header/header.component.scss b/webapp/src/app/core/components/header/header.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/webapp/src/app/core/components/header/header.component.spec.ts b/webapp/src/app/core/components/header/header.component.spec.ts new file mode 100644 index 00000000..2d0479d7 --- /dev/null +++ b/webapp/src/app/core/components/header/header.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HeaderComponent } from './header.component'; + +describe('HeaderComponent', () => { + let component: HeaderComponent; + let fixture: ComponentFixture<HeaderComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ HeaderComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(HeaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/webapp/src/app/core/components/header/header.component.ts b/webapp/src/app/core/components/header/header.component.ts new file mode 100644 index 00000000..591e148a --- /dev/null +++ b/webapp/src/app/core/components/header/header.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-header', + templateUrl: './header.component.html', + styleUrls: ['./header.component.scss'] +}) +export class HeaderComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/webapp/src/app/core/components/main/main.component.html b/webapp/src/app/core/components/main/main.component.html new file mode 100644 index 00000000..bfa5088f --- /dev/null +++ b/webapp/src/app/core/components/main/main.component.html @@ -0,0 +1,9 @@ +<app-header></app-header> + +<div class="container-fluid"> + <p> + main works! + </p> +</div> + +<app-footer></app-footer> diff --git a/webapp/src/app/core/components/main/main.component.scss b/webapp/src/app/core/components/main/main.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/webapp/src/app/core/components/main/main.component.spec.ts b/webapp/src/app/core/components/main/main.component.spec.ts new file mode 100644 index 00000000..0878044a --- /dev/null +++ b/webapp/src/app/core/components/main/main.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MainComponent } from './main.component'; + +describe('MainComponent', () => { + let component: MainComponent; + let fixture: ComponentFixture<MainComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MainComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MainComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/webapp/src/app/core/components/main/main.component.ts b/webapp/src/app/core/components/main/main.component.ts new file mode 100644 index 00000000..8b899ba8 --- /dev/null +++ b/webapp/src/app/core/components/main/main.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-main', + templateUrl: './main.component.html', + styleUrls: ['./main.component.scss'] +}) +export class MainComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/webapp/src/app/core/core-routing.module.ts b/webapp/src/app/core/core-routing.module.ts new file mode 100644 index 00000000..90928dee --- /dev/null +++ b/webapp/src/app/core/core-routing.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { MainComponent } from './components/main/main.component'; + +const routes: Routes = [ + { path: 'app', component: MainComponent } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class CoreRoutingModule { } diff --git a/webapp/src/app/core/core.module.ts b/webapp/src/app/core/core.module.ts new file mode 100644 index 00000000..e7e45744 --- /dev/null +++ b/webapp/src/app/core/core.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { CoreRoutingModule } from './core-routing.module'; +import { HeaderComponent } from './components/header/header.component'; +import { MainComponent } from './components/main/main.component'; +import { FooterComponent } from './components/footer/footer.component'; +import { AppMaterialModule } from '../app.material.module'; + +@NgModule({ + imports: [ + CommonModule, + CoreRoutingModule, + AppMaterialModule + ], + declarations: [HeaderComponent, MainComponent, FooterComponent] +}) +export class CoreModule { } diff --git a/webapp/src/assets/img/android-chrome-192x192.png b/webapp/src/assets/img/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..27c7e19579c49567b1de0625ddf670927b0718e7 GIT binary patch literal 5193 zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Bd2>3_*8t*cliYSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7}%1$-CY>| zgW!U_%O^81FtC?+`ns||Vq)U5HdN1gD8|4b^vcu4F{I+w+qu<yVnR!g?>GJ~n&-sA z%v8kNcqgbwz~GakjzSO%OZJMTp&TJwG%j>Si5_)gSR0YEw9Dga(Aqsb2^;?k+-nhA z>A<Pq$ta|t!pO{Wl9j3Q?(;AG_wCH9&&`=>X*_ebi~auh&yD2|ow2Nbzxn&E?Dc!E z-Fn_+cuXR>XK)bPl(?dIF{Yiqc=2ZFxBtz|f1_O^XHWk2M84K`?@4>>#>@ka2j)4L zZ;+}G+96*dB{649lIK;Y#hdQ2zv1l(sNFQR;p+je1i=qX20^R;NPYEX{%5h}vtonI z)0W@m?0tN1cd$yFy4_arKjlI5fuslPO71?K#rMGZK=k3_@YnsO2lAcfuU~Ur-tosW z#&*}IVouicRw(z(J>Zk@yzkt)i7R+NH>gH_Z~L|D(B?Ni$F{%O*YlcDjqyFxH|8p* z`aOc{>IEv8UbMgA6gj2IB+u}T<Ez+2pL5J^S$D3B9V_>`66f1sV8NQe_F;RXf;v-n zqho^12Hp)^KlC3w+Bfgs(U*?r62v}eChR!Ypw4f~W5XW9U$cMx^6xuko*oxzIM1-0 z*`B|Y|H)p-8|*t+DtIjzXI#I2`L@U3%MIR*_3AziJi8k7nd(Cp`*SU{XKPGvlx{fv ztEy`Ly36wHt-q4}T%AI@9TVywthw@iI@A2uFWzVgukx6Y&S3B2H1~r@fqRU{j(yTU zI6hoIP@>{*sJeiEhwu-+4+-w+;VVxa(Pdh`&~x?&n*tew{fjrRzV+%dTaA?Oyue${ zAGRwt{$x+6e&D9^!e8;Njo=OO9~uQ*1qKCdAG)oaCT09x&&1zSwQ1eV4wetj2c|p! zT+ZZgqR=wA@$ljO{7m1N>gGN_cE!Pm=^U$=(pzh>FUpP4J!~e+WP1<ZJ0N&Kydk;a zJahS#7yUu!-n&W4yjZ??^J<ouK9-X2FP<k)Y_OkKm@W9j`&6s^1Fi>>8nZR5nZy~? zm02gaGTvackn8<xdBES=YIj@ltf1XY_3Sk~6?-Q(diX4OJmFh3Zw*uCT*e8<I43`G zd|<UC@jP=~gW8exuQ^_F7`eY&QRb`hKk7le)6M0K_c{2#xUFUPm>He#9Q7pO!3vq& z(~IOYUz}%n{_X1*vy{H43mAA9zccZtPL;L2+;<?JG2Zb|h0O;C;qxK=M-TWn-n>|z z&;51o?1iEC9e1*^&0JrcP?FRra(nv)i)VN9zcJi*Eh;YM?Va~*M!@-{ymy=hU${!~ zo4okX$m0{WF=fl-#r69cYovDw{5Wi2@VMw|Nb`z6;uqfR*S5J(z0gNt)kV%fno(~0 zEYlV<&bpBh+?Bzk%kqz{qW;{k*$Y=WxcvQSB(z}j#Dp5wnZmltLQ}LoZ@ya+*6Oi( ze#4eLr%hct{;}mo1xc?W-JNW&Glwg>ZqN&TUv}X71+5v=`L=lZ`EOmQ=K4V2$@Tie zv+<#Ch4#t2-FhLHvPouxCi4Wx_zZ9Lf{b(3-<+cUPk;E?{)F4yiwSpKx3t6yyt3!d z{j`l^;ePiC1@|~*I^TTV_#pGat1IQzO0N~fR;=_$OOj(>*SLvutFh7a+lybfHPpK< zyZbStNv8K(=lP|l?lAwTSoN;zjbpRdqK++h1PY7|<`ievvU0v;Ny*yc;_X(d@1%A^ zL@W16;3BJjr?Ss6TUPFtEd4Xz<l;6ZBgXX()t%>=jv7X>e%fTVCDW$BL->5iWRHyX zPV<(}h@7I`Xzw28?8Nzl^HbE(GY(yv&(u^FoMvbL)y~fT%lpKt8O>+b^R9f|?~s<D zTq7~_*-kY-!Ly&jSH}D^>TLNUwnS5Y`PYvvj9V^kd8$#ZWK=$FVJPR8hjA@iyp5%5 zIA+RmPk8=_L&7+Cg<4>}zQeLZC7b4Qu1(O4%1v4(EW%lIf8K;&wTwY+8{hJ8(n{i# z;k!OHH)!$6a$zIeWHsj9rayQdH|Q%0?|rAD!IaO}dunerpV=#;E#)(uW%Hed-^j?N zq`ue@rLydt&6C6IJG1k-=N1^4sO~v^BZF%$_nS+P(sQOvJ>mL0ENa7hFJaC{GN)pf z=bm_MEa=;ELr>l@@BVY+t~Z{4|4W}Zvuc}TEpP6zWVM#(xl^_?rw84AZQ><Z`mD-{ zVUggZvr&5z?};=`P)mzsoDu&#>Vn-8*~|$QO82_LCM9RaC7*Mhz59qr*6pTc7pz1S zW_PGPjo2tNv%WB1uEFGg=albH*I!68)4js_z*q9^`lTt}A-m=ZPcN|bayhv60B6RV z>>!@`im$S78LFyY*xcZL;n@0XPj0cYn#sAR`PaN%oYBDNEWJHVf<e#e^q-eKYr|K_ zHJ@;Mx1=Wd<}NNXu8*b%k}vu{4$ygi_hR|s1O1KS#$8$gmY(b@*QacbxmOvsJM_T+ zW&5Q2lbD0E?#{?DXkR(UaqSZB7q4Ewl#PG7*_NwiE_aNW)$7$KbfX+q8rT($pI^Jc zX}J3E_uZQ^n|Aa3u#(>E6n#oWitlew%A4XHb<JkmK5A_+eyVo#u*M_5-j3W|e`gwr z-JLJG^Stp*a|PF_eO2$<jigsioA@Un@v!?LBVpafNNpF!n|H&Rq>W5UHA{}PhP2%h zcDs->w`bZ}_X!{FbD3_fmyUXLZF13lw}ZQHPt>&#o@w+tqhZCIogNByy*>+X*4pl^ zv`t%^#Ip8EveuuAZr{>1Hf)JMmg;<<zv2Eh4XwN9guZ_7QnoyGa#6<|x%*CfzbY2h z$wUfmPrW<Cry**p3~P;%P06lHg&L=-WvA+`*>PuU#^lNCmJ9o?%bhU$y}fgCeABK< zhv2|Rw-29iIjLmW%jYtCJ9|+{nq;C7j}mXOz$dP|ym!pl1aDS75nL4Z(dO2JIG?3v z^$bf-<@BvNZ?mjYv1XmC+DG@r_wThZb@orZSpIe;)21C9KiePAcAxO_qw}lt7X+7F z%wJffnZ>@Zok{Kcq5>OBW8eGzHZ1oYXCKzNws6J)L5)p&G&5OFPYi$ImBOW~aQmOE zHdn?~>Cc`5YniSuzA~fS&7NQJc75pFq)WMHl6R%f)T$Jg;`ZRI7k(SM%w@l9N7#F= zbdR7!>6MXkoF_MZkW}SJw4b`#$+WHU(h^Z`w%}BrMJFEkm~hth87aKJ*n4JvXv>?! zTLRplovvTJ^jCAnrms(Pio+s{Cx+QD|Bxy0i}!#3tVnLlLQ&(+i8*{>i$YE2F|1cM z-a74@exRmwZpg-?%JH>f(=rx&pIPjo`Oo+%*FO=J{8SaW1!*?iCwua|lwFyA8$|6| z#;ESN?(8eOjIjI8OW#|Z4Su+*mNQfOY)+eVHM{e1yRJP>?q)FopL?9EmzJ7Ld$xCF zN^h=hyJx4@WDC!g>s@a>we<OVb+1^sz_$r2H{GAKZ-ea3=Z}j`^nA^|99}K=>=iM2 z&2cM0wtd>|`GQPpnMwz3*?t}_ckm3}8YJo#V6m5Zt;zO{nQBLho`~)es$44;a5VaA z(l+Pj9W&ID%yiYxA2Z2S>UDn{+RHbkQR;I4r97!rQ?Ix6;-yTPZ%^3V;N<j-{j4ms z<?e+gl{0<iC$wq^zCNwtm{rCbT`S~OsIk!C?>@^@`U^d)EIye%HQcPFeJ_LSZpR*{ zPR$ar<o%X+nSGm<rszD4R`d@3Z!fp@!2UIp*4fOQa8mN47O&RyjQ>UUR#%D{O+TIN zdU4@|OVixxmu)l_{i&Yt;n`j85P=pO&lOR9G5PO3;>EYVzU%QK-<_#8<J|eu1M(_w z^UP+5&U6xA=x{qTW3sJU;gl6~+ZC*TJ>0lrd8kX%Uu~5GhRX%+tm?cg|Ib?P=j-nt zvHw|o*Q^Va)?57RrHzC3ff$imTe)1P)q0i}6W++bi|j2bh<eBu)04CPv$Ol$nS~Nd z8_vw|Q@K!j{;yl^yyi<4>5Dv`FS~W|yi)KBttX;h?0sf4SG)~ww0G7#{QYY6vyRLI ziL!HJzXmySdHlR`>T2ec;{jP!H3iS!F5JJ5`_BD~H?Q{VbowvQxjZBBiCDfy+2nUl zB^$D=LN|GJXE5Dq3Sv9Qv}^O0<WpaEGPt^|U+A{aFK*GnJwmxr=@VreX7=2f@7)-` z<lWlvZ#7$@WSvrH<!yeum$S0<Uh^YnUG5;)zk7veWmGTvSGTM&>6}Ayb@JTvx-XtY zYDc#3G1OnW@4ob0wLRQNgYz67&-I%-!@X=?px&bDcW&B_%ZjuXF<iZ=vEyT9iB94C zee>>p+cz(6691;}{Vv;n37*(r$GG;ZhmNb=v$+=(JGZT<oAA>}l=ZaK*2m!s8}CgN zo0E9r1J_&mUz=BkD!h8_6z`w!{-T+G@zi%MAI?lyC@;E~WIf^g(tFG2iairw+VVa} z%XeYf7R7t5Zw_mJU(8W=SnqXDS&zcZfBV;DPil{AF`IwiL9*Um`T9erDGRnJ-#Vaj zGQi&9(0`^aNB(r0&nTW?{Y5!r=N|o-ORasje2YT0w=Zx_z26fgnYQSMvorgO)gN+R zY(IUnoMm&%l#`VQPS@J*eaRao?G^am^|)ZWll>h3-0F(eRmX!%9{l5alKDqU(S1ML z-wf9ozS(CticbuGk@dtwVyUfApZY}IGM=bO_nMpBJ=Z)?O_?0qn^soOcd%acDOc`_ z^28%t4}N<%q$%YZG{vL@JKg=faAoIq0oHTNlqWx0_+mTn!gtp{iHUu^>zgt2uf)__ zdTA_`cjKJ&cIhniZL-&%C}|*m^U~|rHlL-;=Cx-`G21f#^rNX4rm6716fIi!D^W;= zJy9-ganW7br@z$K*S~aL{bH+!=UUHq>knzETsgeZS3l^epm1eto_lhM(8R-wau}2* zFW~;^Kl!kD{(?IbrcdfB%CjkF*v2cnV_)O+klf}?{OpGg_qyC)%l|gxh=|Aj%*1Gw zj%+2xcW!CNUne>g`EMxr&mxjhY0DFEt$Slvj?J6kY}VKOPuHCNJSVYX`_gUm_lmKa ze2j1GnjGs{KlM=Q;Y1%csf*_p?s+0=vAb<sSxb71<f%2kg4Tpc<~z<?yu{b};lG1c z-~ASRRGtRzZ0^s`37yw`zkJy{GuAEaH~J<V`F>{e>Fp`e36JC62PR~AZ(ZJc{z_jG zuXls#*Lmqa=cdh?wWq)Lec0VgC5uE_j;1V$U}?O?X30K})oVYqa0*kA<axE<dzYnF zFy+*BrF^MgviDxkp7_-#H4858mGwwypSV5ecfdKe6EV5F0vle)1;wq*XtfYInzD~! z&AeT=r(85^&9<5#UHav%(#rdeaZ5hB=w0bCQfo2W()#+;JX@`7ryqN~K1ik7gsV$l z^9{MKawuBMhH)FyqDD*Mr|(M^UoQK+?46nF`k7ngqe8<LRGbu=^5?sjS7GGrRrxYi z%-{Jmz7?Aml&{*iH{d}*xCy7;awE0^pC4;^=l+coxH@sm>)?zc9;W{;scV*qvxdoY zp0DRE2tKy?eQ%K8HRbC+>?avV$=otl{PJ<z!{SiG^JmjG8!%>m{2bV@?wxgRP|4zi zhpHNBn}vQ<tC&RQZ<^6}$$Vemr&VczD@~`j-hbyTcz2D-o7f92ztwKGPxf<?JpQ~T z`~K|0vpYWgv3HvI;BjZz$qb{jPK>uVU-YW9=q+UEay#!f`K^e5!`gOJ4Z#mCCAZdI zoE|SaA+45`_0c?M#=~Dz_DkfbPpSLkIwfI;Zd7YS;O0g0bH97sdpS9El4yY3&BZRy z{1?dP{+hnoaMxVBFO#NxOv?Cv>B6)xA5SRVTBGm2`oibXQ>%{ZJ)F6}C9Yt@Uf%_4 z+iL^XUAFZ25&iYw!l?SLm)kW?u9Nnil6Jl{#9DBMOO|lryLE-R>_VTmy|`Brxilnl zz3D}9{g(83{5%z`H>zGZIT^^^e7ClWG0!x-e3I{OvAxk>6E^XG?ODKcXKzDNO5c-2 ziKY4V47tmePtH~AZTZyiQr(sEv`ceg?b(SMOKaJ@9_6$w%?PcM{VO=7*@n@~zT4xk z?AilPTN-U7pPst!om@C;>WMi0h5Mgv=9$S=K56cYZ5)3Mr(B*mv&eaB(euT<&o-u1 z^Uhylvr<6g^O--<EB;T`m}#V~yR$*<k@ZBS9WyeF+*1Ft`1S<{Ub=HvGWF}?VwTAD zxs@zSkJO8;Rk&^~ux+Y<N%o(0*8*QvHh#)_s+D(?PbKHD={nD_#hbD>z4F~|8WZd= zIlUw2`!k*|?^XzNzGpvM^{guO>6^z+70(nCjtC#f32X}Rb92wB=gIjY%dt&zung^h zMwl)a{geMDah+AIKjRMr1A}UbYeY#(Vo9o1a#3nxNh*VpfuV)2fsw9(QHY^|m8qqb ziKVuIp_PF_C$GSJ6b-rgDVb@NxHbF;SP{&?zz|*)5>XPASgue|l%JNFld4csS&*ub zSx}P9z)&&g@h2XR!Y~buQ~syVcs>ncU{>bVOXe0<7WSSj!Yr)d(qM8pg;{xXh{EX` pS56!`b42C{`{@Rc1zvg#ufzpQJ~^3AWnf@n@O1TaS?83{1OTzeaGn4F literal 0 HcmV?d00001 diff --git a/webapp/src/assets/img/android-chrome-512x512.png b/webapp/src/assets/img/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..70d2e5c65b6f2d949814afaefbf7dfa0521687ea GIT binary patch literal 15280 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 SbSeV_1B0ilpUXO@geCy@HxE1j literal 0 HcmV?d00001 diff --git a/webapp/src/assets/img/apple-touch-icon.png b/webapp/src/assets/img/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f6a9f6786a18ae9941594b9731ad679fe919be15 GIT binary patch literal 4823 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 N!PC{xWt~$(6972o>Q4Xw literal 0 HcmV?d00001 diff --git a/webapp/src/assets/img/favicon-16x16.png b/webapp/src/assets/img/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..1870e1d32ea23a1106918dc041f86739f2589f61 GIT binary patch literal 727 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4rT@h1`S>QU<L*TmUKs7M+SzC{oH>NSs54@ z6p}rHd>I(3)EF2VS{N99F)%PRykKA`HDF+PmB7GYHG_dcykO3*KpO@IhQk3qA+8Jz z3~yyr{u|h_va!p^D=5n=yp>UTE2F~9#?H#d4q>B_pJi2bxOf=B3RsayG-YpPRNl#` z{FYTS<l<pqWh1Eaij2w?SrtWYUJgz!E-r2^E^ZD^E>13PPEIZvc?Csz1vMpQRRu*5 zQdCk^R8mn;R8>^^|Np;1seUs91A{|JkRK>W7#J9s7#SJ0<aMPLl~mQt)x3Q|`~pqP z>>SN)&6QKkic-2aDN71UiAjj5s#&-jXn7dBaR~5=@(YLxiTv-MSkJ(~z?kIi?&9$8 zX3Px+1_t&LPhVH|M@&py)&>E&7aJHD7?M0)977~7CnqdmO-N2pW??EbQ{(gV^Gi!( z)60{Kv#X0^bW}_f3^Xj{Wb@R_^puRWtYmdnO%+WIHDxR1_0`RljkT?1c2-Un4mM_U zGe|JpzG2IzZ5y|4Zl8IUi`k^mk|E|AN3-}Zml_5J2GtVRh?11Vl2ohYqSVBaR0bmh zLknF4BV7Zd5JLkiQ%fro3vB~KD+2@lD(Pqx4Y~O#nQ4`{HN>eee$K$a5MC7$Q4*9` zu24{vpO%@Es!&o{kgAYbP?F5RP%-E6CmxQ%Fb$1U{-@7)J`G}ER_4}A<`z~K_MR-l zEUe(tU~)KxS$T7a!s#1VP8>ONMCJ(l=?0GlUV03##05(}IhjsnU|?YIboFyt=akR{ E0L~@5od5s; literal 0 HcmV?d00001 diff --git a/webapp/src/assets/img/favicon-32x32.png b/webapp/src/assets/img/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..f6297745e4fddbc6d05d33642f5fbd858f1cbef6 GIT binary patch literal 1354 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4rT@h2A3sW#~2tGSkfJR9T^xl_H+M9WCckk zdj$D1FjT2AFf_C<F#KX*U}$*3z))(y!0;-8fx&791A}<MoLzx73=B*%0X`wF3=9l! zWmK40Se4`zl;suP%BT>DKFFvja&ob<u@giD4g4sh(kvv-OoUOaZ0vYU`y#74S44`D zkU4lvK$iL}t2#?WiiwbE_?`4#M&-SX%10TMJOL3FLPo)D-zBSDAg8oYR(XM}GOLKF zn20DJFQ2%mn3RO1sEDYlf})(1G#@XYw4{`@grumjh?1PVsEDYNyaF7lfMZjc0`mX= z|GVbQoz1|&u(>42FPH%Yq;&<j^>p|pI9X+QmGouUby;N<g*7ET<oI-q0#(d3oK#)e z;)?v8b>|3~O{~tG&_BoJw9PvE00#>>5iK_s4Z8)R%v%lSiN{@9dRQpb$j(#2-8a!j zEk#q$YOy*;M2pB`<EZI<KRnFkm4&SYO&LAyU8JYaPIFF5U06`0w33gRiCIj7i%C*U znxBu2ON5(~pI4Ys#z36STER?ON>{~5U0KG4nS+Iqos)-+)w0k&m4ShQG0EHAW%I4v z|8)!u4D2PIzOL+#n3%Y%4FYm6HZU+Sa(cQrhFF|VPLN=2X4|l7V{t)Iq4B2=pFSFM z6>xBIc6W4jdV6?zo<4EvWVfb)hL+~)6{}WeXA~7?e=Jy;vHInUS1+X{q$Fq0m^Cvx zBFZr0b3xI~8@F!Wj<UY7Ld)99a`%p1JF90@R8{_-@$=VDc7qk{Y^?1qZLRJuR&K7x zk62kAKdP>xrn-E|vZc#YQ_@n6pWJx%?5X$-QL&XG+*5C?m^y80ct}|2^(#hKubNkw znwc7Z*t%ugR>Ld{<7pP#jkawoFDWbi{^i?O{}~pUpQfz5yzIQgSE0{mA~!!jGuOQS z;GfoRG5yG0IX}CmuHcG@2wNMsx$N$&tJ&AqL~XA-e9U+CHU1Kl9wrtBhE1{Fr&pg| z+Qq=YpjzS@QIe8al4_M)l$uzQ%3x$*XrXIhq-$UlVrXDxYH4L+p>1GjWniFRB^`~T zAvZrIGp!Q0hB)=b&lwmP!mC0eN`ey06$*;-(=u~X6-p`#QWY`_N|G5ED&{=?#KTb- zrlE1l|MVHpr$G$N%G`R%+``Jj-jhX`g%w;HOb(|oD{l@_IDO;Fi6du@$Q)rm-Qcmn aOON4|xM0aAC)25*^y=yA=d#Wzp$Py0a)3zy literal 0 HcmV?d00001 diff --git a/webapp/src/assets/img/favicon.ico b/webapp/src/assets/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5619a8f1cf3db720725e00d80636e23de406e8de GIT binary patch literal 15086 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 bMpie<CO-rqW2~U@Rvh>b4sr0<ECT}oShyQF literal 0 HcmV?d00001 diff --git a/webapp/src/assets/img/logo.svg b/webapp/src/assets/img/logo.svg new file mode 100644 index 00000000..2bb541a6 --- /dev/null +++ b/webapp/src/assets/img/logo.svg @@ -0,0 +1,5 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="185.6" height="37.9" viewBox="0 0 185.6 37.9"> + <path d="M14.4 21.3C12.8 23 10.5 24 8.1 24c-2.2 0-4.4-.9-5.9-2.4C0 19.5 0 17.4 0 12c0-5.3 0-7.4 2.2-9.6C3.8.9 5.9 0 8.1 0c4.2 0 7.4 2.7 8.1 6.9h-1.8c-.7-3.3-3.1-5.3-6.3-5.3-1.7 0-3.3.6-4.5 1.8C1.9 5.1 1.8 6.9 1.8 12s.1 6.9 1.8 8.6c1.2 1.2 2.8 1.8 4.5 1.8 1.9 0 3.7-.8 4.9-2.3 1-1.3 1.4-2.7 1.4-4.7v-2.1H8.1v-1.6h8.2v3.8c0 2.6-.5 4.3-1.9 5.8zm22.2 2.5l-5.7-10.9h-6.5v10.9h-1.8V.2h9c3.9 0 6.8 2.2 6.8 6.3 0 3.5-2.1 5.8-5.5 6.4l5.7 10.9h-2zm-5.2-22h-7v9.6h7c3 0 5.2-1.5 5.2-4.8s-2.2-4.8-5.2-4.8m27 22l-2.1-5.7h-11l-2.1 5.7h-1.9L50 .2h1.6l8.7 23.6h-1.9zM50.8 2.6l-5 13.9h9.9L50.8 2.6zM80 23.8L66.3 3.3v20.5h-1.8V.2h1.8L80 20.7V.2h1.8v23.6H80zm23-2.1c-1.4 1.4-3.5 2.1-5.9 2.1h-8V.2h8c2.5 0 4.5.8 5.9 2.2 2.4 2.4 2.3 6.1 2.3 9.3 0 3.2.1 7.6-2.3 10m-1.2-18.1c-1.4-1.4-3.2-1.8-5.1-1.8H91v20.4h5.7c1.9 0 3.7-.4 5.1-1.8 1.9-1.9 1.8-6.1 1.8-8.7-.1-2.6.1-6.2-1.8-8.1z" fill="#ed1c24"/> + <path d="M110.8 23.8V.2h4.6v19.5h10.8v4.1h-15.4zm25.6-9.7v9.7h-4.6v-9.7L124.7.2h5l4.4 9.5 4.4-9.5h5l-7.1 13.9zm24 7.3c-1.7 1.7-3.7 2.6-6.4 2.6s-4.8-.9-6.4-2.6c-2.4-2.4-2.3-5.3-2.3-9.4 0-4.1-.1-7 2.3-9.4C149.3.9 151.3 0 154 0s4.7.9 6.4 2.6c2.4 2.4 2.4 5.3 2.4 9.4-.1 4.1 0 7.1-2.4 9.4m-3.5-16c-.7-.8-1.7-1.3-3-1.3s-2.3.5-3 1.3c-.9 1-1.1 2.1-1.1 6.6s.2 5.6 1.1 6.6c.7.8 1.7 1.3 3 1.3s2.3-.5 3-1.3c.9-1 1.2-2.1 1.2-6.6s-.3-5.6-1.2-6.6zm24.6 18.4l-9.4-14.5v14.5h-4.6V.2h4.1l9.4 14.5V.2h4.6v23.6h-4.1z" fill="#050607"/> + <path d="M159.4 33.2c0-.8 0-2-1.1-2s-1 1.5-1 2.3c0 .7.1 1.8 1 1.8 1 0 1.1-.7 1.1-2.1m-2-1.9c.3-.5.7-.7 1.2-.7.9 0 1.7.3 1.7 2.6 0 1.3 0 2.8-1.7 2.8-.5 0-.9-.2-1.2-.6v2.5h-.9v-7.3h.9v.7zm-61.1 3.1c0 .5.2 1 .8 1 .5 0 1.2-.3 1.1-2-.8-.1-1.9-.1-1.9 1m1.9.8c-.3.6-.7.9-1.3.9-1.1 0-1.4-.7-1.4-1.7 0-1.6 1.6-1.7 2.8-1.6 0-.7 0-1.5-.9-1.5-.6 0-.9.4-.8.9h-.9c0-1.2.7-1.6 1.8-1.6 1.4 0 1.7.7 1.7 1.6v2.5c0 .4 0 .8.1 1.3h-.9l-.2-.8zm15.4.7v-3.7c0-.5-.2-1-.8-1-.3 0-.6.2-.7.4-.2.3-.2.6-.2.8V36h-.9v-4.2c0-.4 0-.7-.1-1.1h.9v.7c.2-.6.7-.8 1.3-.8.5 0 1 .2 1.2.7.3-.6.8-.7 1.3-.7.6 0 1.4.1 1.4 1.4v4h-.9v-3.7c0-.5-.2-1-.8-1-.3 0-.4 0-.7.2-.2.2-.3.7-.3.9V36c.2-.1-.7-.1-.7-.1zm12.1-7.5l-1.4 1.5h-.7l.9-1.5h1.2zm-.2 4.5c0-1.5-.4-1.7-1.1-1.7-.6 0-1 .3-1 1.7h2.1zm-2.1.7c0 1.5.4 1.8 1.1 1.8.6 0 .9-.5.9-1h.9c0 1.2-.7 1.7-1.8 1.7s-2-.3-2-2.7c0-1.5.2-2.8 2-2.8 1.5 0 1.9.8 1.9 2.6v.4h-3zm8.8-2.9v-1l.9-.4v1.4h1.1v.6H133v3.2c0 .3 0 .8.8.8h.4v.7c-.3 0-.6.1-.9.1-.8 0-1.2-.3-1.2-.9v-3.7h-.9v-.6l1-.2zm8.4.8c.4-.8.8-.9 1.7-.9v.9h-.4c-.9 0-1.2.7-1.2 1.4V36h-.9v-5.3h.9l-.1.8zm9.7 1.5c0-1.4-.4-1.8-1.1-1.8-.7 0-1.1.3-1.1 1.8 0 1.7.2 2.3 1.1 2.3.8 0 1.1-.6 1.1-2.3m-3.1.4c0-1.5.2-2.8 2-2.8s2 1.3 2 2.8c0 2.3-.9 2.7-2 2.7-1.2-.1-2-.4-2-2.7zm21.5-.4c0-1.4-.4-1.8-1.1-1.8s-1.1.3-1.1 1.8c0 1.7.2 2.3 1.1 2.3.8 0 1.1-.6 1.1-2.3m-3.1.4c0-1.5.2-2.8 2-2.8s2 1.3 2 2.8c0 2.3-.9 2.7-2 2.7-1.2-.1-2-.4-2-2.7zm10.4 2.5h-.9v-7.5h.9v7.5zm8.4-3c0-1.5-.4-1.7-1.1-1.7-.5 0-1 .3-1 1.7h2.1zm-2.1.7c0 1.5.4 1.8 1.1 1.8.6 0 .9-.5.9-1h.9c0 1.2-.7 1.7-1.8 1.7s-2-.3-2-2.7c0-1.5.2-2.8 2-2.8 1.5 0 1.9.8 1.9 2.6v.4h-3zm-91.8 2.3h-.9v-7.5h.9v7.5z" fill="#231f20"/> +</svg> diff --git a/webapp/src/scss/_functions.scss b/webapp/src/scss/_functions.scss new file mode 100644 index 00000000..1266d34b --- /dev/null +++ b/webapp/src/scss/_functions.scss @@ -0,0 +1,86 @@ +// Bootstrap functions +// +// Utility mixins and functions for evalutating source code across our variables, maps, and mixins. + +// Ascending +// Used to evaluate Sass maps like our grid breakpoints. +@mixin _assert-ascending($map, $map-name) { + $prev-key: null; + $prev-num: null; + @each $key, $num in $map { + @if $prev-num == null { + // Do nothing + } @else if not comparable($prev-num, $num) { + @warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !"; + } @else if $prev-num >= $num { + @warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !"; + } + $prev-key: $key; + $prev-num: $num; + } +} + +// Starts at zero +// Another grid mixin that ensures the min-width of the lowest breakpoint starts at 0. +@mixin _assert-starts-at-zero($map) { + $values: map-values($map); + $first-value: nth($values, 1); + @if $first-value != 0 { + @warn "First breakpoint in `$grid-breakpoints` must start at 0, but starts at #{$first-value}."; + } +} + +// Replace `$search` with `$replace` in `$string` +// Used on our SVG icon backgrounds for custom forms. +// +// @author Hugo Giraudel +// @param {String} $string - Initial string +// @param {String} $search - Substring to replace +// @param {String} $replace ('') - New value +// @return {String} - Updated string +@function str-replace($string, $search, $replace: "") { + $index: str-index($string, $search); + + @if $index { + @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); + } + + @return $string; +} + +// Color contrast +@function color-yiq($color) { + $r: red($color); + $g: green($color); + $b: blue($color); + + $yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000; + + @if ($yiq >= $yiq-contrasted-threshold) { + @return $yiq-text-dark; + } @else { + @return $yiq-text-light; + } +} + +// Retrieve color Sass maps +@function color($key: "blue") { + @return map-get($colors, $key); +} + +@function theme-color($key: "primary") { + @return map-get($theme-colors, $key); +} + +@function gray($key: "100") { + @return map-get($grays, $key); +} + +// Request a theme color level +@function theme-color-level($color-name: "primary", $level: 0) { + $color: theme-color($color-name); + $color-base: if($level > 0, #000, #fff); + $level: abs($level); + + @return mix($color-base, $color, $level * $theme-color-interval); +} diff --git a/webapp/src/scss/_grid.scss b/webapp/src/scss/_grid.scss new file mode 100644 index 00000000..a2275153 --- /dev/null +++ b/webapp/src/scss/_grid.scss @@ -0,0 +1,52 @@ +// Container widths +// +// Set the container width, and override it for fixed navbars in media queries. + +@if $enable-grid-classes { + .container { + @include make-container(); + @include make-container-max-widths(); + } +} + +// Fluid container +// +// Utilizes the mixin meant for fixed width containers, but with 100% width for +// fluid, full width layouts. + +@if $enable-grid-classes { + .container-fluid { + @include make-container(); + } +} + +// Row +// +// Rows contain and clear the floats of your columns. + +@if $enable-grid-classes { + .row { + @include make-row(); + } + + // Remove the negative margin from default .row, then the horizontal padding + // from all immediate children columns (to prevent runaway style inheritance). + .no-gutters { + margin-right: 0; + margin-left: 0; + + > .col, + > [class*="col-"] { + padding-right: 0; + padding-left: 0; + } + } +} + +// Columns +// +// Common styles for small and large grid columns + +@if $enable-grid-classes { + @include make-grid-columns(); +} diff --git a/webapp/src/scss/_variables.scss b/webapp/src/scss/_variables.scss new file mode 100644 index 00000000..be580deb --- /dev/null +++ b/webapp/src/scss/_variables.scss @@ -0,0 +1,894 @@ +// Variables +// +// Variables should follow the `$component-state-property-size` formula for +// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs. + + +// +// Color system +// + +// stylelint-disable +$white: #fff !default; +$gray-100: #f8f9fa !default; +$gray-200: #e9ecef !default; +$gray-300: #dee2e6 !default; +$gray-400: #ced4da !default; +$gray-500: #adb5bd !default; +$gray-600: #6c757d !default; +$gray-700: #495057 !default; +$gray-800: #343a40 !default; +$gray-900: #212529 !default; +$black: #000 !default; + +$grays: () !default; +$grays: map-merge(( + "100": $gray-100, + "200": $gray-200, + "300": $gray-300, + "400": $gray-400, + "500": $gray-500, + "600": $gray-600, + "700": $gray-700, + "800": $gray-800, + "900": $gray-900 +), $grays); + +$blue: #007bff !default; +$indigo: #6610f2 !default; +$purple: #6f42c1 !default; +$pink: #e83e8c !default; +$red: #dc3545 !default; +$orange: #fd7e14 !default; +$yellow: #ffc107 !default; +$green: #28a745 !default; +$teal: #20c997 !default; +$cyan: #17a2b8 !default; + +$colors: () !default; +$colors: map-merge(( + "blue": $blue, + "indigo": $indigo, + "purple": $purple, + "pink": $pink, + "red": $red, + "orange": $orange, + "yellow": $yellow, + "green": $green, + "teal": $teal, + "cyan": $cyan, + "white": $white, + "gray": $gray-600, + "gray-dark": $gray-800 +), $colors); + +$primary: $blue !default; +$secondary: $gray-600 !default; +$success: $green !default; +$info: $cyan !default; +$warning: $yellow !default; +$danger: $red !default; +$light: $gray-100 !default; +$dark: $gray-800 !default; + +$theme-colors: () !default; +$theme-colors: map-merge(( + "primary": $primary, + "secondary": $secondary, + "success": $success, + "info": $info, + "warning": $warning, + "danger": $danger, + "light": $light, + "dark": $dark +), $theme-colors); +// stylelint-enable + +// Set a specific jump point for requesting color jumps +$theme-color-interval: 8% !default; + +// The yiq lightness value that determines when the lightness of color changes from "dark" to "light". Acceptable values are between 0 and 255. +$yiq-contrasted-threshold: 150 !default; + +// Customize the light and dark text colors for use in our YIQ color contrast function. +$yiq-text-dark: $gray-900 !default; +$yiq-text-light: $white !default; + +// Options +// +// Quickly modify global styling by enabling or disabling optional features. + +$enable-caret: true !default; +$enable-rounded: true !default; +$enable-shadows: false !default; +$enable-gradients: false !default; +$enable-transitions: true !default; +$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS +$enable-grid-classes: true !default; +$enable-print-styles: true !default; + + +// Spacing +// +// Control the default styling of most Bootstrap elements by modifying these +// variables. Mostly focused on spacing. +// You can add more entries to the $spacers map, should you need more variation. + +// stylelint-disable +$spacer: 1rem !default; +$spacers: () !default; +$spacers: map-merge(( + 0: 0, + 1: ($spacer * .25), + 2: ($spacer * .5), + 3: $spacer, + 4: ($spacer * 1.5), + 5: ($spacer * 3) +), $spacers); + +// This variable affects the `.h-*` and `.w-*` classes. +$sizes: () !default; +$sizes: map-merge(( + 25: 25%, + 50: 50%, + 75: 75%, + 100: 100% +), $sizes); +// stylelint-enable + +// Body +// +// Settings for the `<body>` element. + +$body-bg: $white !default; +$body-color: $gray-900 !default; + +// Links +// +// Style anchor elements. + +$link-color: theme-color("primary") !default; +$link-decoration: none !default; +$link-hover-color: darken($link-color, 15%) !default; +$link-hover-decoration: underline !default; + +// Paragraphs +// +// Style p element. + +$paragraph-margin-bottom: 1rem !default; + + +// Grid breakpoints +// +// Define the minimum dimensions at which your layout will change, +// adapting to different screen sizes, for use in media queries. + +$grid-breakpoints: ( + xs: 0, + sm: 576px, + md: 768px, + lg: 992px, + xl: 1200px +) !default; + +@include _assert-ascending($grid-breakpoints, "$grid-breakpoints"); +@include _assert-starts-at-zero($grid-breakpoints); + + +// Grid containers +// +// Define the maximum width of `.container` for different screen sizes. + +$container-max-widths: ( + sm: 540px, + md: 720px, + lg: 960px, + xl: 1140px +) !default; + +@include _assert-ascending($container-max-widths, "$container-max-widths"); + + +// Grid columns +// +// Set the number of columns and specify the width of the gutters. + +$grid-columns: 12 !default; +$grid-gutter-width: 30px !default; + +// Components +// +// Define common padding and border radius sizes and more. + +$line-height-lg: 1.5 !default; +$line-height-sm: 1.5 !default; + +$border-width: 1px !default; +$border-color: $gray-300 !default; + +$border-radius: .25rem !default; +$border-radius-lg: .3rem !default; +$border-radius-sm: .2rem !default; + +$component-active-color: $white !default; +$component-active-bg: theme-color("primary") !default; + +$caret-width: .3em !default; + +$transition-base: all .2s ease-in-out !default; +$transition-fade: opacity .15s linear !default; +$transition-collapse: height .35s ease !default; + + +// Fonts +// +// Font, line-height, and color for body text, headings, and more. + +// stylelint-disable value-keyword-case +$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default; +$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default; +$font-family-base: $font-family-sans-serif !default; +// stylelint-enable value-keyword-case + +$font-size-base: 1rem !default; // Assumes the browser default, typically `16px` +$font-size-lg: ($font-size-base * 1.25) !default; +$font-size-sm: ($font-size-base * .875) !default; + +$font-weight-light: 300 !default; +$font-weight-normal: 400 !default; +$font-weight-bold: 700 !default; + +$font-weight-base: $font-weight-normal !default; +$line-height-base: 1.5 !default; + +$h1-font-size: $font-size-base * 2.5 !default; +$h2-font-size: $font-size-base * 2 !default; +$h3-font-size: $font-size-base * 1.75 !default; +$h4-font-size: $font-size-base * 1.5 !default; +$h5-font-size: $font-size-base * 1.25 !default; +$h6-font-size: $font-size-base !default; + +$headings-margin-bottom: ($spacer / 2) !default; +$headings-font-family: inherit !default; +$headings-font-weight: 500 !default; +$headings-line-height: 1.2 !default; +$headings-color: inherit !default; + +$display1-size: 6rem !default; +$display2-size: 5.5rem !default; +$display3-size: 4.5rem !default; +$display4-size: 3.5rem !default; + +$display1-weight: 300 !default; +$display2-weight: 300 !default; +$display3-weight: 300 !default; +$display4-weight: 300 !default; +$display-line-height: $headings-line-height !default; + +$lead-font-size: ($font-size-base * 1.25) !default; +$lead-font-weight: 300 !default; + +$small-font-size: 80% !default; + +$text-muted: $gray-600 !default; + +$blockquote-small-color: $gray-600 !default; +$blockquote-font-size: ($font-size-base * 1.25) !default; + +$hr-border-color: rgba($black, .1) !default; +$hr-border-width: $border-width !default; + +$mark-padding: .2em !default; + +$dt-font-weight: $font-weight-bold !default; + +$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default; +$nested-kbd-font-weight: $font-weight-bold !default; + +$list-inline-padding: .5rem !default; + +$mark-bg: #fcf8e3 !default; + +$hr-margin-y: $spacer !default; + + +// Tables +// +// Customizes the `.table` component with basic values, each used across all table variations. + +$table-cell-padding: .75rem !default; +$table-cell-padding-sm: .3rem !default; + +$table-bg: transparent !default; +$table-accent-bg: rgba($black, .05) !default; +$table-hover-bg: rgba($black, .075) !default; +$table-active-bg: $table-hover-bg !default; + +$table-border-width: $border-width !default; +$table-border-color: $gray-300 !default; + +$table-head-bg: $gray-200 !default; +$table-head-color: $gray-700 !default; + +$table-dark-bg: $gray-900 !default; +$table-dark-accent-bg: rgba($white, .05) !default; +$table-dark-hover-bg: rgba($white, .075) !default; +$table-dark-border-color: lighten($gray-900, 7.5%) !default; +$table-dark-color: $body-bg !default; + + +// Buttons + Forms +// +// Shared variables that are reassigned to `$input-` and `$btn-` specific variables. + +$input-btn-padding-y: .375rem !default; +$input-btn-padding-x: .75rem !default; +$input-btn-line-height: $line-height-base !default; + +$input-btn-focus-width: .2rem !default; +$input-btn-focus-color: rgba($component-active-bg, .25) !default; +$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default; + +$input-btn-padding-y-sm: .25rem !default; +$input-btn-padding-x-sm: .5rem !default; +$input-btn-line-height-sm: $line-height-sm !default; + +$input-btn-padding-y-lg: .5rem !default; +$input-btn-padding-x-lg: 1rem !default; +$input-btn-line-height-lg: $line-height-lg !default; + +$input-btn-border-width: $border-width !default; + + +// Buttons +// +// For each of Bootstrap's buttons, define text, background, and border color. + +$btn-padding-y: $input-btn-padding-y !default; +$btn-padding-x: $input-btn-padding-x !default; +$btn-line-height: $input-btn-line-height !default; + +$btn-padding-y-sm: $input-btn-padding-y-sm !default; +$btn-padding-x-sm: $input-btn-padding-x-sm !default; +$btn-line-height-sm: $input-btn-line-height-sm !default; + +$btn-padding-y-lg: $input-btn-padding-y-lg !default; +$btn-padding-x-lg: $input-btn-padding-x-lg !default; +$btn-line-height-lg: $input-btn-line-height-lg !default; + +$btn-border-width: $input-btn-border-width !default; + +$btn-font-weight: $font-weight-normal !default; +$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default; +$btn-focus-width: $input-btn-focus-width !default; +$btn-focus-box-shadow: $input-btn-focus-box-shadow !default; +$btn-disabled-opacity: .65 !default; +$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default; + +$btn-link-disabled-color: $gray-600 !default; + +$btn-block-spacing-y: .5rem !default; + +// Allows for customizing button radius independently from global border radius +$btn-border-radius: $border-radius !default; +$btn-border-radius-lg: $border-radius-lg !default; +$btn-border-radius-sm: $border-radius-sm !default; + +$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default; + + +// Forms + +$input-padding-y: $input-btn-padding-y !default; +$input-padding-x: $input-btn-padding-x !default; +$input-line-height: $input-btn-line-height !default; + +$input-padding-y-sm: $input-btn-padding-y-sm !default; +$input-padding-x-sm: $input-btn-padding-x-sm !default; +$input-line-height-sm: $input-btn-line-height-sm !default; + +$input-padding-y-lg: $input-btn-padding-y-lg !default; +$input-padding-x-lg: $input-btn-padding-x-lg !default; +$input-line-height-lg: $input-btn-line-height-lg !default; + +$input-bg: $white !default; +$input-disabled-bg: $gray-200 !default; + +$input-color: $gray-700 !default; +$input-border-color: $gray-400 !default; +$input-border-width: $input-btn-border-width !default; +$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default; + +$input-border-radius: $border-radius !default; +$input-border-radius-lg: $border-radius-lg !default; +$input-border-radius-sm: $border-radius-sm !default; + +$input-focus-bg: $input-bg !default; +$input-focus-border-color: lighten($component-active-bg, 25%) !default; +$input-focus-color: $input-color !default; +$input-focus-width: $input-btn-focus-width !default; +$input-focus-box-shadow: $input-btn-focus-box-shadow !default; + +$input-placeholder-color: $gray-600 !default; + +$input-height-border: $input-border-width * 2 !default; + +$input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default; +$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default; + +$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default; +$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default; + +$input-height-inner-lg: ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default; +$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default; + +$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default; + +$form-text-margin-top: .25rem !default; + +$form-check-input-gutter: 1.25rem !default; +$form-check-input-margin-y: .3rem !default; +$form-check-input-margin-x: .25rem !default; + +$form-check-inline-margin-x: .75rem !default; +$form-check-inline-input-margin-x: .3125rem !default; + +$form-group-margin-bottom: 1rem !default; + +$input-group-addon-color: $input-color !default; +$input-group-addon-bg: $gray-200 !default; +$input-group-addon-border-color: $input-border-color !default; + +$custom-control-gutter: 1.5rem !default; +$custom-control-spacer-x: 1rem !default; + +$custom-control-indicator-size: 1rem !default; +$custom-control-indicator-bg: $gray-300 !default; +$custom-control-indicator-bg-size: 50% 50% !default; +$custom-control-indicator-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default; + +$custom-control-indicator-disabled-bg: $gray-200 !default; +$custom-control-label-disabled-color: $gray-600 !default; + +$custom-control-indicator-checked-color: $component-active-color !default; +$custom-control-indicator-checked-bg: $component-active-bg !default; +$custom-control-indicator-checked-disabled-bg: rgba(theme-color("primary"), .5) !default; +$custom-control-indicator-checked-box-shadow: none !default; + +$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default; + +$custom-control-indicator-active-color: $component-active-color !default; +$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default; +$custom-control-indicator-active-box-shadow: none !default; + +$custom-checkbox-indicator-border-radius: $border-radius !default; +$custom-checkbox-indicator-icon-checked: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"), "#", "%23") !default; + +$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default; +$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default; +$custom-checkbox-indicator-icon-indeterminate: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3E%3C/svg%3E"), "#", "%23") !default; +$custom-checkbox-indicator-indeterminate-box-shadow: none !default; + +$custom-radio-indicator-border-radius: 50% !default; +$custom-radio-indicator-icon-checked: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3E%3C/svg%3E"), "#", "%23") !default; + +$custom-select-padding-y: .375rem !default; +$custom-select-padding-x: .75rem !default; +$custom-select-height: $input-height !default; +$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator +$custom-select-line-height: $input-btn-line-height !default; +$custom-select-color: $input-color !default; +$custom-select-disabled-color: $gray-600 !default; +$custom-select-bg: $white !default; +$custom-select-disabled-bg: $gray-200 !default; +$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions +$custom-select-indicator-color: $gray-800 !default; +$custom-select-indicator: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E"), "#", "%23") !default; +$custom-select-border-width: $input-btn-border-width !default; +$custom-select-border-color: $input-border-color !default; +$custom-select-border-radius: $border-radius !default; + +$custom-select-focus-border-color: $input-focus-border-color !default; +$custom-select-focus-box-shadow: inset 0 1px 2px rgba($black, .075), 0 0 5px rgba($custom-select-focus-border-color, .5) !default; + +$custom-select-font-size-sm: 75% !default; +$custom-select-height-sm: $input-height-sm !default; + +$custom-select-font-size-lg: 125% !default; +$custom-select-height-lg: $input-height-lg !default; + +$custom-file-height: $input-height !default; +$custom-file-focus-border-color: $input-focus-border-color !default; +$custom-file-focus-box-shadow: $input-btn-focus-box-shadow !default; + +$custom-file-padding-y: $input-btn-padding-y !default; +$custom-file-padding-x: $input-btn-padding-x !default; +$custom-file-line-height: $input-btn-line-height !default; +$custom-file-color: $input-color !default; +$custom-file-bg: $input-bg !default; +$custom-file-border-width: $input-btn-border-width !default; +$custom-file-border-color: $input-border-color !default; +$custom-file-border-radius: $input-border-radius !default; +$custom-file-box-shadow: $input-box-shadow !default; +$custom-file-button-color: $custom-file-color !default; +$custom-file-button-bg: $input-group-addon-bg !default; +$custom-file-text: ( + en: "Browse" +) !default; + + +// Form validation +$form-feedback-margin-top: $form-text-margin-top !default; +$form-feedback-font-size: $small-font-size !default; +$form-feedback-valid-color: theme-color("success") !default; +$form-feedback-invalid-color: theme-color("danger") !default; + + +// Dropdowns +// +// Dropdown menu container and contents. + +$dropdown-min-width: 10rem !default; +$dropdown-padding-y: .5rem !default; +$dropdown-spacer: .125rem !default; +$dropdown-bg: $white !default; +$dropdown-border-color: rgba($black, .15) !default; +$dropdown-border-radius: $border-radius !default; +$dropdown-border-width: $border-width !default; +$dropdown-divider-bg: $gray-200 !default; +$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default; + +$dropdown-link-color: $gray-900 !default; +$dropdown-link-hover-color: darken($gray-900, 5%) !default; +$dropdown-link-hover-bg: $gray-100 !default; + +$dropdown-link-active-color: $component-active-color !default; +$dropdown-link-active-bg: $component-active-bg !default; + +$dropdown-link-disabled-color: $gray-600 !default; + +$dropdown-item-padding-y: .25rem !default; +$dropdown-item-padding-x: 1.5rem !default; + +$dropdown-header-color: $gray-600 !default; + + +// Z-index master list +// +// Warning: Avoid customizing these values. They're used for a bird's eye view +// of components dependent on the z-axis and are designed to all work together. + +$zindex-dropdown: 1000 !default; +$zindex-sticky: 1020 !default; +$zindex-fixed: 1030 !default; +$zindex-modal-backdrop: 1040 !default; +$zindex-modal: 1050 !default; +$zindex-popover: 1060 !default; +$zindex-tooltip: 1070 !default; + +// Navs + +$nav-link-padding-y: .5rem !default; +$nav-link-padding-x: 1rem !default; +$nav-link-disabled-color: $gray-600 !default; + +$nav-tabs-border-color: $gray-300 !default; +$nav-tabs-border-width: $border-width !default; +$nav-tabs-border-radius: $border-radius !default; +$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default; +$nav-tabs-link-active-color: $gray-700 !default; +$nav-tabs-link-active-bg: $body-bg !default; +$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default; + +$nav-pills-border-radius: $border-radius !default; +$nav-pills-link-active-color: $component-active-color !default; +$nav-pills-link-active-bg: $component-active-bg !default; + +// Navbar + +$navbar-padding-y: ($spacer / 2) !default; +$navbar-padding-x: $spacer !default; + +$navbar-nav-link-padding-x: .5rem !default; + +$navbar-brand-font-size: $font-size-lg !default; +// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link +$nav-link-height: ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default; +$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default; +$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default; + +$navbar-toggler-padding-y: .25rem !default; +$navbar-toggler-padding-x: .75rem !default; +$navbar-toggler-font-size: $font-size-lg !default; +$navbar-toggler-border-radius: $btn-border-radius !default; + +$navbar-dark-color: rgba($white, .5) !default; +$navbar-dark-hover-color: rgba($white, .75) !default; +$navbar-dark-active-color: $white !default; +$navbar-dark-disabled-color: rgba($white, .25) !default; +$navbar-dark-toggler-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"), "#", "%23") !default; +$navbar-dark-toggler-border-color: rgba($white, .1) !default; + +$navbar-light-color: rgba($black, .5) !default; +$navbar-light-hover-color: rgba($black, .7) !default; +$navbar-light-active-color: rgba($black, .9) !default; +$navbar-light-disabled-color: rgba($black, .3) !default; +$navbar-light-toggler-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"), "#", "%23") !default; +$navbar-light-toggler-border-color: rgba($black, .1) !default; + +// Pagination + +$pagination-padding-y: .5rem !default; +$pagination-padding-x: .75rem !default; +$pagination-padding-y-sm: .25rem !default; +$pagination-padding-x-sm: .5rem !default; +$pagination-padding-y-lg: .75rem !default; +$pagination-padding-x-lg: 1.5rem !default; +$pagination-line-height: 1.25 !default; + +$pagination-color: $link-color !default; +$pagination-bg: $white !default; +$pagination-border-width: $border-width !default; +$pagination-border-color: $gray-300 !default; + +$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default; + +$pagination-hover-color: $link-hover-color !default; +$pagination-hover-bg: $gray-200 !default; +$pagination-hover-border-color: $gray-300 !default; + +$pagination-active-color: $component-active-color !default; +$pagination-active-bg: $component-active-bg !default; +$pagination-active-border-color: $pagination-active-bg !default; + +$pagination-disabled-color: $gray-600 !default; +$pagination-disabled-bg: $white !default; +$pagination-disabled-border-color: $gray-300 !default; + + +// Jumbotron + +$jumbotron-padding: 2rem !default; +$jumbotron-bg: $gray-200 !default; + + +// Cards + +$card-spacer-y: .75rem !default; +$card-spacer-x: 1.25rem !default; +$card-border-width: $border-width !default; +$card-border-radius: $border-radius !default; +$card-border-color: rgba($black, .125) !default; +$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default; +$card-cap-bg: rgba($black, .03) !default; +$card-bg: $white !default; + +$card-img-overlay-padding: 1.25rem !default; + +$card-group-margin: ($grid-gutter-width / 2) !default; +$card-deck-margin: $card-group-margin !default; + +$card-columns-count: 3 !default; +$card-columns-gap: 1.25rem !default; +$card-columns-margin: $card-spacer-y !default; + + +// Tooltips + +$tooltip-font-size: $font-size-sm !default; +$tooltip-max-width: 200px !default; +$tooltip-color: $white !default; +$tooltip-bg: $black !default; +$tooltip-border-radius: $border-radius !default; +$tooltip-opacity: .9 !default; +$tooltip-padding-y: .25rem !default; +$tooltip-padding-x: .5rem !default; +$tooltip-margin: 0 !default; + +$tooltip-arrow-width: .8rem !default; +$tooltip-arrow-height: .4rem !default; +$tooltip-arrow-color: $tooltip-bg !default; + + +// Popovers + +$popover-font-size: $font-size-sm !default; +$popover-bg: $white !default; +$popover-max-width: 276px !default; +$popover-border-width: $border-width !default; +$popover-border-color: rgba($black, .2) !default; +$popover-border-radius: $border-radius-lg !default; +$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default; + +$popover-header-bg: darken($popover-bg, 3%) !default; +$popover-header-color: $headings-color !default; +$popover-header-padding-y: .5rem !default; +$popover-header-padding-x: .75rem !default; + +$popover-body-color: $body-color !default; +$popover-body-padding-y: $popover-header-padding-y !default; +$popover-body-padding-x: $popover-header-padding-x !default; + +$popover-arrow-width: 1rem !default; +$popover-arrow-height: .5rem !default; +$popover-arrow-color: $popover-bg !default; + +$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default; + + +// Badges + +$badge-font-size: 75% !default; +$badge-font-weight: $font-weight-bold !default; +$badge-padding-y: .25em !default; +$badge-padding-x: .4em !default; +$badge-border-radius: $border-radius !default; + +$badge-pill-padding-x: .6em !default; +// Use a higher than normal value to ensure completely rounded edges when +// customizing padding or font-size on labels. +$badge-pill-border-radius: 10rem !default; + + +// Modals + +// Padding applied to the modal body +$modal-inner-padding: 1rem !default; + +$modal-dialog-margin: .5rem !default; +$modal-dialog-margin-y-sm-up: 1.75rem !default; + +$modal-title-line-height: $line-height-base !default; + +$modal-content-bg: $white !default; +$modal-content-border-color: rgba($black, .2) !default; +$modal-content-border-width: $border-width !default; +$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default; +$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default; + +$modal-backdrop-bg: $black !default; +$modal-backdrop-opacity: .5 !default; +$modal-header-border-color: $gray-200 !default; +$modal-footer-border-color: $modal-header-border-color !default; +$modal-header-border-width: $modal-content-border-width !default; +$modal-footer-border-width: $modal-header-border-width !default; +$modal-header-padding: 1rem !default; + +$modal-lg: 800px !default; +$modal-md: 500px !default; +$modal-sm: 300px !default; + +$modal-transition: transform .3s ease-out !default; + + +// Alerts +// +// Define alert colors, border radius, and padding. + +$alert-padding-y: .75rem !default; +$alert-padding-x: 1.25rem !default; +$alert-margin-bottom: 1rem !default; +$alert-border-radius: $border-radius !default; +$alert-link-font-weight: $font-weight-bold !default; +$alert-border-width: $border-width !default; + +$alert-bg-level: -10 !default; +$alert-border-level: -9 !default; +$alert-color-level: 6 !default; + + +// Progress bars + +$progress-height: 1rem !default; +$progress-font-size: ($font-size-base * .75) !default; +$progress-bg: $gray-200 !default; +$progress-border-radius: $border-radius !default; +$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default; +$progress-bar-color: $white !default; +$progress-bar-bg: theme-color("primary") !default; +$progress-bar-animation-timing: 1s linear infinite !default; +$progress-bar-transition: width .6s ease !default; + +// List group + +$list-group-bg: $white !default; +$list-group-border-color: rgba($black, .125) !default; +$list-group-border-width: $border-width !default; +$list-group-border-radius: $border-radius !default; + +$list-group-item-padding-y: .75rem !default; +$list-group-item-padding-x: 1.25rem !default; + +$list-group-hover-bg: $gray-100 !default; +$list-group-active-color: $component-active-color !default; +$list-group-active-bg: $component-active-bg !default; +$list-group-active-border-color: $list-group-active-bg !default; + +$list-group-disabled-color: $gray-600 !default; +$list-group-disabled-bg: $list-group-bg !default; + +$list-group-action-color: $gray-700 !default; +$list-group-action-hover-color: $list-group-action-color !default; + +$list-group-action-active-color: $body-color !default; +$list-group-action-active-bg: $gray-200 !default; + + +// Image thumbnails + +$thumbnail-padding: .25rem !default; +$thumbnail-bg: $body-bg !default; +$thumbnail-border-width: $border-width !default; +$thumbnail-border-color: $gray-300 !default; +$thumbnail-border-radius: $border-radius !default; +$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default; + + +// Figures + +$figure-caption-font-size: 90% !default; +$figure-caption-color: $gray-600 !default; + + +// Breadcrumbs + +$breadcrumb-padding-y: .75rem !default; +$breadcrumb-padding-x: 1rem !default; +$breadcrumb-item-padding: .5rem !default; + +$breadcrumb-margin-bottom: 1rem !default; + +$breadcrumb-bg: $gray-200 !default; +$breadcrumb-divider-color: $gray-600 !default; +$breadcrumb-active-color: $gray-600 !default; +$breadcrumb-divider: "/" !default; + + +// Carousel + +$carousel-control-color: $white !default; +$carousel-control-width: 15% !default; +$carousel-control-opacity: .5 !default; + +$carousel-indicator-width: 30px !default; +$carousel-indicator-height: 3px !default; +$carousel-indicator-spacer: 3px !default; +$carousel-indicator-active-bg: $white !default; + +$carousel-caption-width: 70% !default; +$carousel-caption-color: $white !default; + +$carousel-control-icon-width: 20px !default; + +$carousel-control-prev-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"), "#", "%23") !default; +$carousel-control-next-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"), "#", "%23") !default; + +$carousel-transition: transform .6s ease !default; + + +// Close + +$close-font-size: $font-size-base * 1.5 !default; +$close-font-weight: $font-weight-bold !default; +$close-color: $black !default; +$close-text-shadow: 0 1px 0 $white !default; + +// Code + +$code-font-size: 87.5% !default; +$code-color: $pink !default; + +$kbd-padding-y: .2rem !default; +$kbd-padding-x: .4rem !default; +$kbd-font-size: $code-font-size !default; +$kbd-color: $white !default; +$kbd-bg: $gray-900 !default; + +$pre-color: $gray-900 !default; +$pre-scrollable-max-height: 340px !default; + + +// Printing +$print-page-size: a3 !default; +$print-body-min-width: map-get($grid-breakpoints, "lg") !default; diff --git a/webapp/src/scss/bootstrap-grid.scss b/webapp/src/scss/bootstrap-grid.scss new file mode 100644 index 00000000..26c0dc89 --- /dev/null +++ b/webapp/src/scss/bootstrap-grid.scss @@ -0,0 +1,32 @@ +/*! + * Bootstrap Grid v4.0.0 (https://getbootstrap.com) + * Copyright 2011-2018 The Bootstrap Authors + * Copyright 2011-2018 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +@at-root { + @-ms-viewport { width: device-width; } // stylelint-disable-line at-rule-no-vendor-prefix +} + +html { + box-sizing: border-box; + -ms-overflow-style: scrollbar; +} + +*, +*::before, +*::after { + box-sizing: inherit; +} + +@import "functions"; +@import "variables"; + +@import "mixins/breakpoints"; +@import "mixins/grid-framework"; +@import "mixins/grid"; + +@import "grid"; +@import "utilities/display"; +@import "utilities/flex"; diff --git a/webapp/src/scss/mixins/_breakpoints.scss b/webapp/src/scss/mixins/_breakpoints.scss new file mode 100644 index 00000000..d1ad684c --- /dev/null +++ b/webapp/src/scss/mixins/_breakpoints.scss @@ -0,0 +1,123 @@ +// Breakpoint viewport sizes and media queries. +// +// Breakpoints are defined as a map of (name: minimum width), order from small to large: +// +// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px) +// +// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default. + +// Name of the next breakpoint, or null for the last breakpoint. +// +// >> breakpoint-next(sm) +// md +// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)) +// md +// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl)) +// md +@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) { + $n: index($breakpoint-names, $name); + @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null); +} + +// Minimum breakpoint width. Null for the smallest (first) breakpoint. +// +// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)) +// 576px +@function breakpoint-min($name, $breakpoints: $grid-breakpoints) { + $min: map-get($breakpoints, $name); + @return if($min != 0, $min, null); +} + +// Maximum breakpoint width. Null for the largest (last) breakpoint. +// The maximum value is calculated as the minimum of the next one less 0.02px +// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths. +// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max +// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari. +// See https://bugs.webkit.org/show_bug.cgi?id=178261 +// +// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)) +// 767.98px +@function breakpoint-max($name, $breakpoints: $grid-breakpoints) { + $next: breakpoint-next($name, $breakpoints); + @return if($next, breakpoint-min($next, $breakpoints) - .02px, null); +} + +// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash infront. +// Useful for making responsive utilities. +// +// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)) +// "" (Returns a blank string) +// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)) +// "-sm" +@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) { + @return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}"); +} + +// Media of at least the minimum breakpoint width. No query for the smallest breakpoint. +// Makes the @content apply to the given breakpoint and wider. +@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) { + $min: breakpoint-min($name, $breakpoints); + @if $min { + @media (min-width: $min) { + @content; + } + } @else { + @content; + } +} + +// Media of at most the maximum breakpoint width. No query for the largest breakpoint. +// Makes the @content apply to the given breakpoint and narrower. +@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) { + $max: breakpoint-max($name, $breakpoints); + @if $max { + @media (max-width: $max) { + @content; + } + } @else { + @content; + } +} + +// Media that spans multiple breakpoint widths. +// Makes the @content apply between the min and max breakpoints +@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) { + $min: breakpoint-min($lower, $breakpoints); + $max: breakpoint-max($upper, $breakpoints); + + @if $min != null and $max != null { + @media (min-width: $min) and (max-width: $max) { + @content; + } + } @else if $max == null { + @include media-breakpoint-up($lower, $breakpoints) { + @content; + } + } @else if $min == null { + @include media-breakpoint-down($upper, $breakpoints) { + @content; + } + } +} + +// Media between the breakpoint's minimum and maximum widths. +// No minimum for the smallest breakpoint, and no maximum for the largest one. +// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower. +@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) { + $min: breakpoint-min($name, $breakpoints); + $max: breakpoint-max($name, $breakpoints); + + @if $min != null and $max != null { + @media (min-width: $min) and (max-width: $max) { + @content; + } + } @else if $max == null { + @include media-breakpoint-up($name, $breakpoints) { + @content; + } + } @else if $min == null { + @include media-breakpoint-down($name, $breakpoints) { + @content; + } + } +} diff --git a/webapp/src/scss/mixins/_grid-framework.scss b/webapp/src/scss/mixins/_grid-framework.scss new file mode 100644 index 00000000..7b37f868 --- /dev/null +++ b/webapp/src/scss/mixins/_grid-framework.scss @@ -0,0 +1,67 @@ +// Framework grid generation +// +// Used only by Bootstrap to generate the correct number of grid classes given +// any value of `$grid-columns`. + +@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) { + // Common properties for all breakpoints + %grid-column { + position: relative; + width: 100%; + min-height: 1px; // Prevent columns from collapsing when empty + padding-right: ($gutter / 2); + padding-left: ($gutter / 2); + } + + @each $breakpoint in map-keys($breakpoints) { + $infix: breakpoint-infix($breakpoint, $breakpoints); + + // Allow columns to stretch full width below their breakpoints + @for $i from 1 through $columns { + .col#{$infix}-#{$i} { + @extend %grid-column; + } + } + .col#{$infix}, + .col#{$infix}-auto { + @extend %grid-column; + } + + @include media-breakpoint-up($breakpoint, $breakpoints) { + // Provide basic `.col-{bp}` classes for equal-width flexbox columns + .col#{$infix} { + flex-basis: 0; + flex-grow: 1; + max-width: 100%; + } + .col#{$infix}-auto { + flex: 0 0 auto; + width: auto; + max-width: none; // Reset earlier grid tiers + } + + @for $i from 1 through $columns { + .col#{$infix}-#{$i} { + @include make-col($i, $columns); + } + } + + .order#{$infix}-first { order: -1; } + + .order#{$infix}-last { order: $columns + 1; } + + @for $i from 0 through $columns { + .order#{$infix}-#{$i} { order: $i; } + } + + // `$columns - 1` because offsetting by the width of an entire row isn't possible + @for $i from 0 through ($columns - 1) { + @if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0 + .offset#{$infix}-#{$i} { + @include make-col-offset($i, $columns); + } + } + } + } + } +} diff --git a/webapp/src/scss/mixins/_grid.scss b/webapp/src/scss/mixins/_grid.scss new file mode 100644 index 00000000..b75ebcbc --- /dev/null +++ b/webapp/src/scss/mixins/_grid.scss @@ -0,0 +1,52 @@ +/// Grid system +// +// Generate semantic grid columns with these mixins. + +@mixin make-container() { + width: 100%; + padding-right: ($grid-gutter-width / 2); + padding-left: ($grid-gutter-width / 2); + margin-right: auto; + margin-left: auto; +} + + +// For each breakpoint, define the maximum width of the container in a media query +@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) { + @each $breakpoint, $container-max-width in $max-widths { + @include media-breakpoint-up($breakpoint, $breakpoints) { + max-width: $container-max-width; + } + } +} + +@mixin make-row() { + display: flex; + flex-wrap: wrap; + margin-right: ($grid-gutter-width / -2); + margin-left: ($grid-gutter-width / -2); +} + +@mixin make-col-ready() { + position: relative; + // Prevent columns from becoming too narrow when at smaller grid tiers by + // always setting `width: 100%;`. This works because we use `flex` values + // later on to override this initial width. + width: 100%; + min-height: 1px; // Prevent collapsing + padding-right: ($grid-gutter-width / 2); + padding-left: ($grid-gutter-width / 2); +} + +@mixin make-col($size, $columns: $grid-columns) { + flex: 0 0 percentage($size / $columns); + // Add a `max-width` to ensure content within each column does not blow out + // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari + // do not appear to require this. + max-width: percentage($size / $columns); +} + +@mixin make-col-offset($size, $columns: $grid-columns) { + $num: $size / $columns; + margin-left: if($num == 0, 0, percentage($num)); +} diff --git a/webapp/src/scss/utilities/_display.scss b/webapp/src/scss/utilities/_display.scss new file mode 100644 index 00000000..20aeeb5f --- /dev/null +++ b/webapp/src/scss/utilities/_display.scss @@ -0,0 +1,38 @@ +// stylelint-disable declaration-no-important + +// +// Utilities for common `display` values +// + +@each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + .d#{$infix}-none { display: none !important; } + .d#{$infix}-inline { display: inline !important; } + .d#{$infix}-inline-block { display: inline-block !important; } + .d#{$infix}-block { display: block !important; } + .d#{$infix}-table { display: table !important; } + .d#{$infix}-table-row { display: table-row !important; } + .d#{$infix}-table-cell { display: table-cell !important; } + .d#{$infix}-flex { display: flex !important; } + .d#{$infix}-inline-flex { display: inline-flex !important; } + } +} + + +// +// Utilities for toggling `display` in print +// + +@media print { + .d-print-none { display: none !important; } + .d-print-inline { display: inline !important; } + .d-print-inline-block { display: inline-block !important; } + .d-print-block { display: block !important; } + .d-print-table { display: table !important; } + .d-print-table-row { display: table-row !important; } + .d-print-table-cell { display: table-cell !important; } + .d-print-flex { display: flex !important; } + .d-print-inline-flex { display: inline-flex !important; } +} diff --git a/webapp/src/scss/utilities/_flex.scss b/webapp/src/scss/utilities/_flex.scss new file mode 100644 index 00000000..8e470384 --- /dev/null +++ b/webapp/src/scss/utilities/_flex.scss @@ -0,0 +1,46 @@ +// stylelint-disable declaration-no-important + +// Flex variation +// +// Custom styles for additional flex alignment options. + +@each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + .flex#{$infix}-row { flex-direction: row !important; } + .flex#{$infix}-column { flex-direction: column !important; } + .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; } + .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; } + + .flex#{$infix}-wrap { flex-wrap: wrap !important; } + .flex#{$infix}-nowrap { flex-wrap: nowrap !important; } + .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; } + + .justify-content#{$infix}-start { justify-content: flex-start !important; } + .justify-content#{$infix}-end { justify-content: flex-end !important; } + .justify-content#{$infix}-center { justify-content: center !important; } + .justify-content#{$infix}-between { justify-content: space-between !important; } + .justify-content#{$infix}-around { justify-content: space-around !important; } + + .align-items#{$infix}-start { align-items: flex-start !important; } + .align-items#{$infix}-end { align-items: flex-end !important; } + .align-items#{$infix}-center { align-items: center !important; } + .align-items#{$infix}-baseline { align-items: baseline !important; } + .align-items#{$infix}-stretch { align-items: stretch !important; } + + .align-content#{$infix}-start { align-content: flex-start !important; } + .align-content#{$infix}-end { align-content: flex-end !important; } + .align-content#{$infix}-center { align-content: center !important; } + .align-content#{$infix}-between { align-content: space-between !important; } + .align-content#{$infix}-around { align-content: space-around !important; } + .align-content#{$infix}-stretch { align-content: stretch !important; } + + .align-self#{$infix}-auto { align-self: auto !important; } + .align-self#{$infix}-start { align-self: flex-start !important; } + .align-self#{$infix}-end { align-self: flex-end !important; } + .align-self#{$infix}-center { align-self: center !important; } + .align-self#{$infix}-baseline { align-self: baseline !important; } + .align-self#{$infix}-stretch { align-self: stretch !important; } + } +} diff --git a/webapp/src/styles.scss b/webapp/src/styles.scss index 90d4ee00..df64f3c4 100644 --- a/webapp/src/styles.scss +++ b/webapp/src/styles.scss @@ -1 +1,19 @@ /* You can add global styles to this file, and also import other style files */ + +@import '~scss/bootstrap-grid.scss'; + +html, +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + margin: 0; + padding: 0; + height: 100%; +} + +h1, h2, h3 { + font-size: 2em; + font-weight: 700; + padding-left: 0.5em; + margin: 0; + flex: 1; +} \ No newline at end of file diff --git a/webapp/src/theme.scss b/webapp/src/theme.scss new file mode 100644 index 00000000..9feaf1a1 --- /dev/null +++ b/webapp/src/theme.scss @@ -0,0 +1,17 @@ +// Charger les outils Material Design +@import '~@angular/material/theming'; + +// Charger les mixins de theming des composants +@import 'theming/all-theme'; + +// Charger le thème principal +@import 'theming/grandlyon/grandlyon'; + +// Le mixin `mat-core()` ne doit être appélé qu'une seule fois puisqu'il génère +// des styles CSS. +// TODO: passer en argument la configuration typographique. +@include mat-core(); + +@include angular-material-theme($gl-theme); +@include app-theme($gl-theme); + diff --git a/webapp/src/theming/_all-theme.scss b/webapp/src/theming/_all-theme.scss new file mode 100644 index 00000000..50310d03 --- /dev/null +++ b/webapp/src/theming/_all-theme.scss @@ -0,0 +1,29 @@ +@mixin app-theme($theme) { + // @include app-shared-theme($theme); + // @include app-components-theme($theme); +} + +// Theming des éléments transverses + +// @import "shared/form-theme"; +// @import "shared/loader-theme"; +// @import "shared/table-theme"; + +// @mixin app-shared-theme($theme) { +// @include app-shared-form-theme($theme); +// @include app-shared-loader-theme($theme); +// @include app-shared-table-theme($theme); +// } + +// // Theming des composants Angular + +// @import "~app/app-theme.component"; +// @import "~app/components/menu/menu-theme.component"; +// @import "~app/components/federal/welcome/welcome-theme.component"; + +// @mixin app-components-theme($theme) { +// @include app-app-theme($theme); +// @include app-menu-theme($theme); +// @include app-welcome-theme($theme); +// } + diff --git a/webapp/src/theming/_theming.scss b/webapp/src/theming/_theming.scss new file mode 100644 index 00000000..b09f09c5 --- /dev/null +++ b/webapp/src/theming/_theming.scss @@ -0,0 +1,11 @@ +@import "~sass-recursive-map-merge/recursive-map-merge"; + +@function app-override-theme($mat-theme, $foreground: null, $background: null) { + $theme: ( + foreground: $foreground, + background: $background, + ); + + @return recursive-map-merge($mat-theme, $theme); +} + diff --git a/webapp/src/theming/grandlyon/config/_palette.scss b/webapp/src/theming/grandlyon/config/_palette.scss new file mode 100644 index 00000000..eb2416e0 --- /dev/null +++ b/webapp/src/theming/grandlyon/config/_palette.scss @@ -0,0 +1,89 @@ +// Color palettes for Grand Lyon, la Métropole +// +// Generator: +// http://mcg.mbitson.com/#!?vermilion=%23e10000&woodsmoke=%23050707&themename=grandlyon + +$gl-dark-primary-text: black; +$gl-light-primary-text: white; + +$gl-vermilion: ( + 50: #ffebeb, + 100: #ff9f9f, + 200: #ff6767, + 300: #ff1f1f, + 400: #ff0101, + 500: #e10000, + 600: #c20000, + 700: #a40000, + 800: #850000, + 900: #670000, + A100: #ffe1e1, + A200: #ff7b7b, + A400: #ff1515, + A700: #fa0000, + contrast: ( + 50: $gl-dark-primary-text, + 100: $gl-dark-primary-text, + 200: $gl-dark-primary-text, + 300: $gl-light-primary-text, + 400: $gl-light-primary-text, + 500: $gl-light-primary-text, + 600: $gl-light-primary-text, + 700: $gl-light-primary-text, + 800: $gl-light-primary-text, + 900: $gl-light-primary-text, + A100: $gl-dark-primary-text, + A200: $gl-dark-primary-text, + A400: $gl-light-primary-text, + A700: $gl-light-primary-text, + ) +); + +$gl-woodsmoke: ( + 50: #e1e1e1, + 100: #b4b5b5, + 200: #828383, + 300: #505151, + 400: #2b2c2c, + 500: #050707, + 600: #040606, + 700: #040505, + 800: #030404, + 900: #010202, + A100: #a6a6a6, + A200: #8c8c8c, + A400: #737373, + A700: #666666, + contrast: ( + 50: $gl-dark-primary-text, + 100: $gl-dark-primary-text, + 200: $gl-dark-primary-text, + 300: $gl-light-primary-text, + 400: $gl-light-primary-text, + 500: $gl-light-primary-text, + 600: $gl-light-primary-text, + 700: $gl-light-primary-text, + 800: $gl-light-primary-text, + 900: $gl-light-primary-text, + A100: $gl-dark-primary-text, + A200: $gl-dark-primary-text, + A400: $gl-light-primary-text, + A700: $gl-light-primary-text, + ) +); + +// Palette des couleurs d'arrière plan spécifique au thème clair. +$gl-light-theme-background: ( + // spécifiques + actived-navigation: #f0f0f0, + form: rgba(220, 220, 220, 0.4), + table-header: #d3d3d3, +); + +// Palette des couleurs de premier plan spécifique au thème clair. +$gl-light-theme-foreground: ( + // spécifiques + valid: #4caf50, + invalid: #d32f2f, +); + diff --git a/webapp/src/theming/grandlyon/config/_variables.scss b/webapp/src/theming/grandlyon/config/_variables.scss new file mode 100644 index 00000000..2ac14af9 --- /dev/null +++ b/webapp/src/theming/grandlyon/config/_variables.scss @@ -0,0 +1,9 @@ +@import "palette"; + +// Palettes +// -------- + +$gl-theme-primary: mat-palette($gl-vermilion); +$gl-theme-accent: mat-palette($gl-woodsmoke); +$gl-theme-warn: mat-palette($gl-woodsmoke); + diff --git a/webapp/src/theming/grandlyon/grandlyon.scss b/webapp/src/theming/grandlyon/grandlyon.scss new file mode 100644 index 00000000..73837988 --- /dev/null +++ b/webapp/src/theming/grandlyon/grandlyon.scss @@ -0,0 +1,10 @@ +@import '../theming'; + +@import "config/variables"; + +$gl-theme: app-override-theme( + mat-light-theme($gl-theme-primary, $gl-theme-accent, $gl-theme-warn), + $foreground: $gl-light-theme-foreground, + $background: $gl-light-theme-background +); + -- GitLab