├── .browserslistrc ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── angular.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── src ├── app │ ├── about │ │ ├── about.component.html │ │ ├── about.component.scss │ │ └── about.component.ts │ ├── app-routing.module.ts │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.ts │ ├── app.module.ts │ ├── location │ │ ├── location.component.html │ │ ├── location.component.scss │ │ └── location.component.ts │ ├── navigation │ │ ├── navigation.component.html │ │ ├── navigation.component.scss │ │ └── navigation.component.ts │ └── shop │ │ ├── color-picker │ │ ├── color-picker-dialog │ │ │ ├── color-picker-dialog.component.html │ │ │ ├── color-picker-dialog.component.scss │ │ │ └── color-picker-dialog.component.ts │ │ ├── color-picker.component.html │ │ ├── color-picker.component.scss │ │ └── color-picker.component.ts │ │ ├── dumpling │ │ ├── dumpling.component.html │ │ ├── dumpling.component.scss │ │ ├── dumpling.component.spec.ts │ │ └── dumpling.component.ts │ │ ├── shop.component.html │ │ ├── shop.component.scss │ │ └── shop.component.ts ├── assets │ ├── .gitkeep │ ├── blue-demo-screenshot.png │ └── pink-demo-screenshot.png ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── styles.scss └── test.ts ├── tsconfig.app.json ├── tsconfig.json └── tsconfig.spec.json /.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": [ 4 | "projects/**/*" 5 | ], 6 | "overrides": [ 7 | { 8 | "files": [ 9 | "*.ts" 10 | ], 11 | "parserOptions": { 12 | "project": [ 13 | "tsconfig.json", 14 | "e2e/tsconfig.json" 15 | ], 16 | "createDefaultProgram": true 17 | }, 18 | "extends": [ 19 | "plugin:@angular-eslint/ng-cli-compat", 20 | "plugin:@angular-eslint/ng-cli-compat--formatting-add-on", 21 | "plugin:@angular-eslint/template/process-inline-templates" 22 | ], 23 | "rules": { 24 | "@angular-eslint/component-selector": [ 25 | "error", 26 | { 27 | "type": "element", 28 | "prefix": "app", 29 | "style": "kebab-case" 30 | } 31 | ], 32 | "@angular-eslint/directive-selector": [ 33 | "error", 34 | { 35 | "type": "attribute", 36 | "prefix": "app", 37 | "style": "camelCase" 38 | } 39 | ], 40 | "@typescript-eslint/explicit-member-accessibility": [ 41 | "off", 42 | { 43 | "accessibility": "explicit" 44 | } 45 | ], 46 | "@typescript-eslint/no-unused-vars": "error", 47 | "arrow-parens": [ 48 | "off", 49 | "always" 50 | ], 51 | "id-blacklist": "error", 52 | "import/order": "off", 53 | "no-bitwise": "off", 54 | "space-before-function-paren": "off" 55 | } 56 | }, 57 | { 58 | "files": [ 59 | "*.html" 60 | ], 61 | "extends": [ 62 | "plugin:@angular-eslint/template/recommended" 63 | ], 64 | "rules": { 65 | "@angular-eslint/template/accessibility-alt-text": 2, 66 | "@angular-eslint/template/accessibility-elements-content": 2, 67 | "@angular-eslint/template/accessibility-label-for": 2, 68 | "@angular-eslint/template/no-positive-tabindex": 2, 69 | "@angular-eslint/template/accessibility-table-scope": 2, 70 | "@angular-eslint/template/accessibility-valid-aria": 2, 71 | "@angular-eslint/template/click-events-have-key-events": 2, 72 | "@angular-eslint/template/mouse-events-have-key-events": 2, 73 | "@angular-eslint/template/no-autofocus": 2, 74 | "@angular-eslint/template/no-distracting-elements": 2 75 | } 76 | } 77 | ] 78 | } 79 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.angular 36 | /.sass-cache 37 | /connect.lock 38 | /coverage 39 | /libpeerconnection.log 40 | npm-debug.log 41 | yarn-error.log 42 | testem.log 43 | /typings 44 | *.package-lock.json 45 | 46 | # System Files 47 | .DS_Store 48 | Thumbs.db 49 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement (CLA). You (or your employer) retain the copyright to your 10 | contribution; this simply gives us permission to use and redistribute your 11 | contributions as part of the project. Head over to 12 | to see your current agreements on file or 13 | to sign a new one. 14 | 15 | You generally only need to submit a CLA once, so if you've already submitted one 16 | (even if it was for a different project), you probably don't need to do it 17 | again. 18 | 19 | ## Code Reviews 20 | 21 | All submissions, including submissions by project members, require review. We 22 | use GitHub pull requests for this purpose. Consult 23 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 24 | information on using pull requests. 25 | 26 | ## Community Guidelines 27 | 28 | This project follows 29 | [Google's Open Source Community Guidelines](https://opensource.google/conduct/). 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build more accessible Angular apps : Dumpling Shop demo 2 | 3 | Demo for the [Build more accessible Angular apps](https://codelabs.developers.google.com/angular-a11y) codelab. 4 | 5 | 6 | ## Get set up 7 | 8 | Run `npm install` to install the dependencies required to run the server. 9 | 10 | Run `git checkout get-started` to use the `get-started` branch for the codelab. All solutions can be found in the `main` branch. 11 | 12 | Run `ng serve --hmr` to run the server. 13 | 14 | Open a browser tab to [http://localhost:4200](http://localhost:4200). The app will automatically reload if you change any of the source files. 15 | 16 | 17 | ## Disclaimer 18 | 19 | This is a demo from [@twerske](https://twitter.com/twerske) and the Angular team, and not an officially supported Google product. -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "cli": { 4 | "analytics": false 5 | }, 6 | "version": 1, 7 | "newProjectRoot": "projects", 8 | "projects": { 9 | "angular-a11y": { 10 | "projectType": "application", 11 | "schematics": { 12 | "@schematics/angular:component": { 13 | "style": "scss" 14 | }, 15 | "@schematics/angular:application": { 16 | "strict": true 17 | } 18 | }, 19 | "root": "", 20 | "sourceRoot": "src", 21 | "prefix": "app", 22 | "architect": { 23 | "build": { 24 | "builder": "@angular-devkit/build-angular:browser", 25 | "options": { 26 | "outputPath": "dist/angular-a11y", 27 | "index": "src/index.html", 28 | "main": "src/main.ts", 29 | "polyfills": "src/polyfills.ts", 30 | "tsConfig": "tsconfig.app.json", 31 | "assets": [ 32 | "src/favicon.ico", 33 | "src/assets" 34 | ], 35 | "styles": [ 36 | "src/styles.scss" 37 | ], 38 | "inlineStyleLanguage": "scss", 39 | "scripts": [], 40 | "vendorChunk": true, 41 | "extractLicenses": false, 42 | "buildOptimizer": false, 43 | "sourceMap": true, 44 | "optimization": false, 45 | "namedChunks": true, 46 | "aot": false 47 | }, 48 | "configurations": { 49 | "production": { 50 | "fileReplacements": [ 51 | { 52 | "replace": "src/environments/environment.ts", 53 | "with": "src/environments/environment.prod.ts" 54 | } 55 | ], 56 | "optimization": true, 57 | "outputHashing": "all", 58 | "sourceMap": false, 59 | "namedChunks": false, 60 | "extractLicenses": true, 61 | "vendorChunk": false, 62 | "buildOptimizer": true, 63 | "budgets": [ 64 | { 65 | "type": "initial", 66 | "maximumWarning": "500kb", 67 | "maximumError": "1mb" 68 | }, 69 | { 70 | "type": "anyComponentStyle", 71 | "maximumWarning": "2kb", 72 | "maximumError": "4kb" 73 | } 74 | ] 75 | } 76 | } 77 | }, 78 | "serve": { 79 | "builder": "@angular-devkit/build-angular:dev-server", 80 | "options": { 81 | "browserTarget": "angular-a11y:build" 82 | }, 83 | "configurations": { 84 | "production": { 85 | "browserTarget": "angular-a11y:build:production" 86 | } 87 | } 88 | }, 89 | "extract-i18n": { 90 | "builder": "@angular-devkit/build-angular:extract-i18n", 91 | "options": { 92 | "browserTarget": "angular-a11y:build" 93 | } 94 | }, 95 | "test": { 96 | "builder": "@angular-devkit/build-angular:karma", 97 | "options": { 98 | "main": "src/test.ts", 99 | "polyfills": "src/polyfills.ts", 100 | "tsConfig": "tsconfig.spec.json", 101 | "karmaConfig": "karma.conf.js", 102 | "assets": [ 103 | "src/favicon.ico", 104 | "src/assets" 105 | ], 106 | "styles": [ 107 | "src/styles.scss" 108 | ], 109 | "scripts": [] 110 | } 111 | }, 112 | "lint": { 113 | "builder": "@angular-eslint/builder:lint", 114 | "options": { 115 | "lintFilePatterns": [ 116 | "src/**/*.ts", 117 | "src/**/*.html" 118 | ] 119 | } 120 | }, 121 | "e2e": { 122 | "builder": "@angular-devkit/build-angular:protractor", 123 | "options": { 124 | "protractorConfig": "e2e/protractor.conf.js", 125 | "devServerTarget": "angular-a11y:serve" 126 | }, 127 | "configurations": { 128 | "production": { 129 | "devServerTarget": "angular-a11y:serve:production" 130 | } 131 | } 132 | } 133 | } 134 | } 135 | }, 136 | "defaultProject": "angular-a11y" 137 | } 138 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | // Karma configuration file, see link for more information 17 | // https://karma-runner.github.io/1.0/config/configuration-file.html 18 | 19 | module.exports = function (config) { 20 | config.set({ 21 | basePath: '', 22 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 23 | plugins: [ 24 | require('karma-jasmine'), 25 | require('karma-chrome-launcher'), 26 | require('karma-jasmine-html-reporter'), 27 | require('karma-coverage'), 28 | require('@angular-devkit/build-angular/plugins/karma') 29 | ], 30 | client: { 31 | jasmine: { 32 | // you can add configuration options for Jasmine here 33 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 34 | // for example, you can disable the random execution with `random: false` 35 | // or set a specific seed with `seed: 4321` 36 | }, 37 | clearContext: false // leave Jasmine Spec Runner output visible in browser 38 | }, 39 | jasmineHtmlReporter: { 40 | suppressAll: true // removes the duplicated traces 41 | }, 42 | coverageReporter: { 43 | dir: require('path').join(__dirname, './coverage/angular-a11y'), 44 | subdir: '.', 45 | reporters: [ 46 | { type: 'html' }, 47 | { type: 'text-summary' } 48 | ] 49 | }, 50 | reporters: ['progress', 'kjhtml'], 51 | port: 9876, 52 | colors: true, 53 | logLevel: config.LOG_INFO, 54 | autoWatch: true, 55 | browsers: ['Chrome'], 56 | singleRun: false, 57 | restartOnFileChange: true 58 | }); 59 | }; 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-a11y", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "test": "ng test", 9 | "lint": "eslint -c .eslintrc.js --ext .ts ./src/", 10 | "e2e": "ng e2e" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular/animations": "~14.0.0-rc.0", 15 | "@angular/cdk": "^14.0.0-rc.0", 16 | "@angular/common": "^14.0.0-rc.0", 17 | "@angular/compiler": "^14.0.0-rc.0", 18 | "@angular/core": "^14.0.0-rc.0", 19 | "@angular/forms": "^14.0.0-rc.0", 20 | "@angular/google-maps": "^14.0.0-rc.0", 21 | "@angular/material": "^14.0.0-rc.0", 22 | "@angular/platform-browser": "^14.0.0-rc.0", 23 | "@angular/platform-browser-dynamic": "^14.0.0-rc.0", 24 | "@angular/router": "~14.0.0-rc.0", 25 | "rxjs": "^7.4.0", 26 | "tslib": "^2.0.0", 27 | "zone.js": "~0.11.4" 28 | }, 29 | "devDependencies": { 30 | "@angular-devkit/build-angular": "~14.0.0-rc.0", 31 | "@angular-eslint/builder": "13.0.0-alpha.0", 32 | "@angular-eslint/eslint-plugin": "13.0.0-alpha.0", 33 | "@angular-eslint/eslint-plugin-template": "13.0.0-alpha.0", 34 | "@angular-eslint/schematics": "13.0.0-alpha.0", 35 | "@angular-eslint/template-parser": "13.0.0-alpha.0", 36 | "@angular/cli": "~14.0.0-rc.0", 37 | "@angular/compiler-cli": "~14.0.0-rc.0", 38 | "@types/jasmine": "~3.6.0", 39 | "@types/node": "^12.11.1", 40 | "@typescript-eslint/eslint-plugin": "5.4.0", 41 | "@typescript-eslint/parser": "5.4.0", 42 | "eslint": "^7.6.0", 43 | "eslint-plugin-import": "2.22.1", 44 | "eslint-plugin-jsdoc": "30.7.6", 45 | "eslint-plugin-prefer-arrow": "1.2.2", 46 | "jasmine-core": "~3.6.0", 47 | "jasmine-spec-reporter": "~5.0.0", 48 | "karma": "^6.3.19", 49 | "karma-chrome-launcher": "~3.1.0", 50 | "karma-coverage": "~2.0.3", 51 | "karma-jasmine": "~4.0.0", 52 | "karma-jasmine-html-reporter": "^1.5.0", 53 | "protractor": "~7.0.0", 54 | "ts-node": "~8.3.0", 55 | "tslint": "~6.1.0", 56 | "typescript": "~4.4.4" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/app/about/about.component.html: -------------------------------------------------------------------------------- 1 | 16 |
17 | 18 |

Who are we?

19 |

Have you ever thought, “wow, I love dumplings”?

20 |

Who hasn't.

21 |

We took it one step further and created Dumpling Dumpling,

22 |

double the dumpling, double the fun.

23 |
24 |

How are we different?

25 |

Handmade in San Francisco, California, we craft fully customizable dumplings. Glitter? Rainbows? Vegan? We do it all.

26 |

This shop is concept only.

27 |
28 | -------------------------------------------------------------------------------- /src/app/about/about.component.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | :host { 17 | display: flex; 18 | justify-content: center; 19 | } 20 | 21 | .about { 22 | width: 50%; 23 | padding: 5%; 24 | 25 | .center { 26 | text-align: center; 27 | } 28 | 29 | .right { 30 | text-align: right; 31 | } 32 | 33 | .spacer { 34 | height: 10%; 35 | } 36 | } 37 | 38 | :host-context(.dark-theme) { 39 | .about { 40 | color: #fff; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/app/about/about.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { Component } from '@angular/core'; 17 | 18 | @Component({ 19 | selector: 'app-about', 20 | templateUrl: './about.component.html', 21 | styleUrls: ['./about.component.scss'] 22 | }) 23 | export class AboutComponent { } 24 | -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { NgModule } from '@angular/core'; 17 | import { RouterModule, Routes } from '@angular/router'; 18 | import { AboutComponent } from './about/about.component'; 19 | import { LocationComponent } from './location/location.component'; 20 | import { ShopComponent } from './shop/shop.component'; 21 | 22 | // TODO: #4. Define unique page titles 23 | const routes: Routes = [ 24 | { path: 'shop', component: ShopComponent, title: 'Our Shop – a11y in Angular' }, 25 | { path: 'about', component: AboutComponent, title: 'Our Story - a11y in Angular' }, 26 | { path: 'locate', component: LocationComponent, title: 'Find Us - a11y in Angular' }, 27 | { path: '', redirectTo: '/shop', pathMatch: 'full' }, 28 | { path: '**', component: ShopComponent }, 29 | ]; 30 | 31 | @NgModule({ 32 | imports: [RouterModule.forRoot(routes)], 33 | exports: [RouterModule] 34 | }) 35 | export class AppRoutingModule { } 36 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { Component } from '@angular/core'; 17 | 18 | @Component({ 19 | selector: 'app-root', 20 | templateUrl: './app.component.html', 21 | styleUrls: ['./app.component.scss'] 22 | }) 23 | export class AppComponent { 24 | title = 'a11y in Angular'; 25 | isDark: boolean | undefined; 26 | bodyStyles: CSSStyleDeclaration | undefined; 27 | } 28 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { NgModule } from '@angular/core'; 17 | import { BrowserModule, Title } from '@angular/platform-browser'; 18 | import { FormsModule } from '@angular/forms'; 19 | 20 | import { AppRoutingModule } from './app-routing.module'; 21 | import { AppComponent } from './app.component'; 22 | 23 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 24 | import { MatButtonModule } from '@angular/material/button'; 25 | import { MatCardModule } from '@angular/material/card'; 26 | import { MatDialogModule } from '@angular/material/dialog'; 27 | import { MatIconModule } from '@angular/material/icon'; 28 | import { MatListModule } from '@angular/material/list'; 29 | import { MatSliderModule } from '@angular/material/slider'; 30 | import { MatToolbarModule } from '@angular/material/toolbar'; 31 | import { GoogleMapsModule } from '@angular/google-maps'; 32 | 33 | import { AboutComponent } from './about/about.component'; 34 | import { ColorPickerComponent } from './shop/color-picker/color-picker.component'; 35 | import { ColorPickerDialogComponent } from './shop/color-picker/color-picker-dialog/color-picker-dialog.component'; 36 | import { DumplingComponent } from './shop/dumpling/dumpling.component'; 37 | import { LocationComponent } from './location/location.component'; 38 | import { NavigationComponent } from './navigation/navigation.component'; 39 | import { ShopComponent } from './shop/shop.component'; 40 | 41 | // TODO: #9. Add the power of @angular/cdk/a11y 42 | import { A11yModule } from '@angular/cdk/a11y'; 43 | 44 | @NgModule({ 45 | declarations: [ 46 | AppComponent, 47 | NavigationComponent, 48 | ShopComponent, 49 | AboutComponent, 50 | LocationComponent, 51 | DumplingComponent, 52 | ColorPickerComponent, 53 | ColorPickerDialogComponent, 54 | ], 55 | imports: [ 56 | BrowserModule, 57 | AppRoutingModule, 58 | FormsModule, 59 | BrowserAnimationsModule, 60 | MatButtonModule, 61 | MatCardModule, 62 | MatDialogModule, 63 | MatIconModule, 64 | MatListModule, 65 | MatSliderModule, 66 | MatToolbarModule, 67 | GoogleMapsModule, 68 | A11yModule, 69 | ], 70 | providers: [Title], 71 | bootstrap: [AppComponent] 72 | }) 73 | export class AppModule { } 74 | -------------------------------------------------------------------------------- /src/app/location/location.component.html: -------------------------------------------------------------------------------- 1 | 16 |
17 | 22 | 24 | 25 |
26 |

Find Us

27 |
28 |
123 Dolores Street
29 |
San Francisco, CA 94114
30 |
31 |
32 |

Pickup Hours

33 |

Monday to Friday, 10am to 6pm

34 |
35 |
36 |
37 | -------------------------------------------------------------------------------- /src/app/location/location.component.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | .location-map { 17 | height: 100%; 18 | text-align: -webkit-center; 19 | padding: 5%; 20 | 21 | .map-container { 22 | border: #f0f8ff 2px solid; 23 | } 24 | 25 | .details { 26 | margin: 5%; 27 | 28 | .typography { 29 | margin: .1rem; 30 | } 31 | 32 | .hours { 33 | margin-top: 1rem; 34 | 35 | h3 { 36 | margin: 0; 37 | } 38 | } 39 | } 40 | } 41 | 42 | :host-context(.dark-theme) { 43 | .details { 44 | color: #fff; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/app/location/location.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { Component } from '@angular/core'; 17 | 18 | @Component({ 19 | selector: 'app-location', 20 | templateUrl: './location.component.html', 21 | styleUrls: ['./location.component.scss'] 22 | }) 23 | export class LocationComponent { 24 | center: google.maps.LatLngLiteral = { 25 | lat: 37.759767, 26 | lng: -122.427121, 27 | }; 28 | 29 | options: google.maps.MapOptions = { 30 | center: this.center, 31 | zoom: 20, 32 | mapTypeId: 'hybrid', 33 | zoomControl: false, 34 | scrollwheel: false, 35 | disableDoubleClickZoom: true, 36 | maxZoom: 15, 37 | minZoom: 8, 38 | styles: [ 39 | { 40 | featureType: 'all', 41 | stylers: [ 42 | { color: '#C0C0C0' } 43 | ] 44 | }, { 45 | featureType: 'road.arterial', 46 | elementType: 'geometry', 47 | stylers: [ 48 | { color: '#CCFFFF' } 49 | ] 50 | }, { 51 | featureType: 'landscape', 52 | elementType: 'labels', 53 | stylers: [ 54 | { visibility: 'off' } 55 | ] 56 | } 57 | ] 58 | }; 59 | 60 | markerPosition: google.maps.LatLngLiteral = this.center; 61 | markerOptions: google.maps.MarkerOptions = {draggable: false}; 62 | } 63 | -------------------------------------------------------------------------------- /src/app/navigation/navigation.component.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 20 | home 21 | 22 |

Dumpling Shop

23 | 30 |
31 | 32 | 33 |
34 | Our Shop 35 | Our Story 36 | Find Us 37 |
38 |
39 |
40 | -------------------------------------------------------------------------------- /src/app/navigation/navigation.component.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | .title-header { 17 | justify-content: space-between; 18 | 19 | h1 { 20 | align-self: flex-end; 21 | } 22 | } 23 | 24 | .navigation-links { 25 | place-content: center center; 26 | } 27 | -------------------------------------------------------------------------------- /src/app/navigation/navigation.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { OverlayContainer } from '@angular/cdk/overlay'; 17 | import { Component, OnInit } from '@angular/core'; 18 | 19 | @Component({ 20 | selector: 'app-navigation', 21 | templateUrl: './navigation.component.html', 22 | styleUrls: ['./navigation.component.scss'] 23 | }) 24 | export class NavigationComponent implements OnInit { 25 | isDark: boolean | undefined; 26 | 27 | constructor(private overlayContainer: OverlayContainer) {} 28 | 29 | ngOnInit(): void { 30 | this.isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; 31 | this.setTheme(); 32 | } 33 | 34 | toggleTheme(): void { 35 | this.isDark = !this.isDark; 36 | this.setTheme(); 37 | } 38 | 39 | setTheme(): void { 40 | document.documentElement.classList.toggle('dark-theme', this.isDark); 41 | this.overlayContainer.getContainerElement().classList.toggle('dark-theme', this.isDark); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/app/shop/color-picker/color-picker-dialog/color-picker-dialog.component.html: -------------------------------------------------------------------------------- 1 | 16 |
17 | 18 | 19 | 20 |
21 |
22 |

{{ paint }}

23 |
24 |
25 |
26 |
27 |
28 | 31 | 34 |
35 | -------------------------------------------------------------------------------- /src/app/shop/color-picker/color-picker-dialog/color-picker-dialog.component.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | .color-option { 17 | display: flex; 18 | flex-direction: row; 19 | align-items: center; 20 | text-transform: uppercase; 21 | 22 | p { 23 | margin: 0; 24 | } 25 | } 26 | 27 | .circle { 28 | height: 40px; 29 | width: 40px; 30 | margin: 10px; 31 | margin-left: 0; 32 | box-sizing: border-box; 33 | border-radius: 100%; 34 | border: 1px solid #dadada; 35 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.14); 36 | } 37 | 38 | button { 39 | text-transform: uppercase; 40 | } 41 | -------------------------------------------------------------------------------- /src/app/shop/color-picker/color-picker-dialog/color-picker-dialog.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { LiveAnnouncer } from '@angular/cdk/a11y'; 17 | import { Component, EventEmitter, OnInit, Output } from '@angular/core'; 18 | import { MatDialogRef } from '@angular/material/dialog'; 19 | 20 | export interface ColorDialogData { 21 | color: string; 22 | } 23 | 24 | @Component({ 25 | selector: 'app-color-picker-dialog', 26 | templateUrl: './color-picker-dialog.component.html', 27 | styleUrls: ['./color-picker-dialog.component.scss'] 28 | }) 29 | export class ColorPickerDialogComponent implements OnInit { 30 | @Output() recolor = new EventEmitter(); 31 | color = '#fff'; 32 | 33 | public defaultColors: string[] = [ 34 | 'white', 35 | 'tomato', 36 | 'hotpink', 37 | 'coral', 38 | 'gold', 39 | 'greenyellow', 40 | 'lightgreen', 41 | 'turquoise', 42 | 'skyblue', 43 | 'royalblue', 44 | 'plum', 45 | ]; 46 | 47 | // TODO: #11. Announce changes with LiveAnnouncer 48 | constructor(public dialogRef: MatDialogRef, 49 | private liveAnnouncer: LiveAnnouncer) { } 50 | 51 | ngOnInit(): void { } 52 | 53 | public changeColor(color: string): void { 54 | if (color) { 55 | this.recolor.emit(color); 56 | } 57 | 58 | // TODO: #11. Announce changes with LiveAnnouncer 59 | this.liveAnnouncer.announce(`Select color: ${color}`); 60 | this.dialogRef.close(); 61 | } 62 | 63 | public closeDialog(): void { 64 | this.dialogRef.close(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/app/shop/color-picker/color-picker.component.html: -------------------------------------------------------------------------------- 1 | 16 | 30 | -------------------------------------------------------------------------------- /src/app/shop/color-picker/color-picker.component.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | :host { 17 | width: 100%; 18 | height: 100%; 19 | } 20 | 21 | .wrapper-color { 22 | width: 100%; 23 | height: 100%; 24 | display: flex; 25 | box-sizing: border-box; 26 | border-radius: 5px; 27 | 28 | .color-info { 29 | display: flex; 30 | width: 120%; 31 | align-items: center; 32 | padding: 10px 0; 33 | 34 | .text { 35 | width: calc(100% - 40px); 36 | text-align: left; 37 | 38 | p.style { 39 | margin-bottom: 0; 40 | } 41 | 42 | span.style-value { 43 | display: block; 44 | margin: 0; 45 | text-transform: uppercase; 46 | font-size: 14px; 47 | letter-spacing: 1.5px; 48 | line-height: normal; 49 | } 50 | } 51 | 52 | .circle { 53 | height: 40px; 54 | width: 40px; 55 | box-sizing: border-box; 56 | border-radius: 100%; 57 | border: 1px solid #dadada; 58 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.14); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/app/shop/color-picker/color-picker.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { Component, EventEmitter, Input, Output } from '@angular/core'; 17 | import { MatDialog } from '@angular/material/dialog'; 18 | import { ColorPickerDialogComponent } from './color-picker-dialog/color-picker-dialog.component'; 19 | 20 | @Component({ 21 | selector: 'app-color-picker', 22 | templateUrl: './color-picker.component.html', 23 | styleUrls: ['./color-picker.component.scss'] 24 | }) 25 | export class ColorPickerComponent { 26 | @Input() color = 'gold'; 27 | @Output() recolor = new EventEmitter(); 28 | 29 | constructor(public dialog: MatDialog) {} 30 | 31 | openDialog(): void { 32 | const dialogRef = this.dialog.open(ColorPickerDialogComponent, { 33 | data: {color: this.color}, 34 | }); 35 | 36 | dialogRef.componentInstance.recolor.subscribe((color) => { 37 | this.color = color; 38 | this.recolor.emit(this.color); 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/app/shop/dumpling/dumpling.component.html: -------------------------------------------------------------------------------- 1 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /src/app/shop/dumpling/dumpling.component.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Adapted from https://codepen.io/osermay/pen/wrKQOd 18 | 19 | @use 'sass:math'; 20 | 21 | $dumpling-light: #efd7b8; 22 | $dumpling-dark: darken(#efd7b8, 15%); 23 | $dumpling-size: 100px; 24 | $dumpling-inner: 70px; 25 | $fold-size: 20px; 26 | 27 | @mixin center ($margin: auto, $left: 0, $right: 0) { 28 | margin: $margin; 29 | left: $left; 30 | right: $right; 31 | } 32 | 33 | .container { 34 | position: relative; 35 | width: 200px; 36 | height: 200px; 37 | margin: auto; 38 | margin-bottom: -200px; 39 | } 40 | 41 | .dumpling-body { 42 | @include center; 43 | background-color: $dumpling-light; 44 | width: $dumpling-size; 45 | height: math.div($dumpling-size, 2); 46 | border-top-left-radius: $dumpling-size; 47 | border-top-right-radius: $dumpling-size; 48 | border: #ffe9e9 solid 2px; 49 | } 50 | 51 | .shadow { 52 | @include center; 53 | opacity: 10%; 54 | background-color: #ffebcd; 55 | width: $dumpling-size * .9; 56 | height: $dumpling-inner - $fold-size; 57 | border-top-left-radius: $dumpling-size; 58 | border-top-right-radius: $dumpling-size; 59 | z-index: 100; 60 | } 61 | 62 | .fold-class { 63 | position: absolute; 64 | top: 0; 65 | right: 60%; 66 | border: #ffe9e9 solid 2px; 67 | border-radius: 50%; 68 | background-color: $dumpling-light; 69 | width: $fold-size; 70 | height: $fold-size; 71 | z-index: -1; 72 | } 73 | 74 | .fold { 75 | @extend .fold-class; 76 | right: 68%; 77 | top: 15.5%; 78 | } 79 | 80 | .fold2 { 81 | @extend .fold-class; 82 | right: 66%; 83 | top: 7%; 84 | } 85 | 86 | .fold3 { 87 | @extend .fold-class 88 | } 89 | 90 | .fold4 { 91 | @include center; 92 | @extend .fold-class; 93 | right: 15%; 94 | top: -4%; 95 | } 96 | 97 | .fold5 { 98 | @include center; 99 | @extend .fold-class; 100 | top: -5%; 101 | } 102 | 103 | .fold6 { 104 | @extend .fold5; 105 | top: -4%; 106 | left: 15%; 107 | } 108 | 109 | .fold7 { 110 | @extend .fold; 111 | left: 60%; 112 | top: 0; 113 | } 114 | 115 | .fold8 { 116 | @extend .fold; 117 | left: 66%; 118 | top: 7%; 119 | } 120 | 121 | .fold9 { 122 | @extend .fold; 123 | left: 68%; 124 | top: 15.5%; 125 | } 126 | -------------------------------------------------------------------------------- /src/app/shop/dumpling/dumpling.component.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 17 | 18 | import { DumplingComponent } from './dumpling.component'; 19 | 20 | describe('DumplingComponent', () => { 21 | let component: DumplingComponent; 22 | let fixture: ComponentFixture; 23 | 24 | beforeEach(async () => { 25 | await TestBed.configureTestingModule({ 26 | declarations: [ DumplingComponent ] 27 | }) 28 | .compileComponents(); 29 | }); 30 | 31 | beforeEach(() => { 32 | fixture = TestBed.createComponent(DumplingComponent); 33 | component = fixture.componentInstance; 34 | fixture.detectChanges(); 35 | }); 36 | 37 | it('should create', () => { 38 | expect(component).toBeTruthy(); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /src/app/shop/dumpling/dumpling.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { Component, Input } from '@angular/core'; 17 | 18 | @Component({ 19 | selector: 'app-dumpling', 20 | templateUrl: './dumpling.component.html', 21 | styleUrls: ['./dumpling.component.scss'] 22 | }) 23 | export class DumplingComponent { 24 | @Input() color = '#efd7b8'; 25 | } 26 | -------------------------------------------------------------------------------- /src/app/shop/shop.component.html: -------------------------------------------------------------------------------- 1 | 16 |
17 |
18 | 19 |
20 |
21 | 22 | Fillings 23 | 24 | 25 | 26 | 27 | {{ flavor }} 28 | 29 | 30 | 31 | 32 | 33 | Quantity 34 | 35 | 36 | 48 | 49 | 50 | 51 | 52 | Color 53 | 54 | 55 | 56 | 57 |
58 | 59 | 65 |
-------------------------------------------------------------------------------- /src/app/shop/shop.component.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | @use '@angular/material' as mat; 17 | 18 | // TODO: #12. Enable HighContrast mode 19 | @use '@angular/cdk'; 20 | 21 | :host { 22 | display: flex; 23 | justify-content: center; 24 | } 25 | 26 | .shop { 27 | width: 75%; 28 | padding: 5%; 29 | padding-top: 0; 30 | display: flex; 31 | flex-direction: column; 32 | 33 | .dumpling-container { 34 | display: flex; 35 | flex-wrap: wrap; 36 | height: 45vh; 37 | overflow: hidden; 38 | place-content: space-evenly center; 39 | } 40 | 41 | .dumpling-customizations { 42 | display: flex; 43 | justify-content: space-between; 44 | flex-wrap: wrap; 45 | 46 | .selection-card { 47 | margin: 0 10px 10px 0; 48 | display: flex; 49 | flex-direction: column; 50 | background-color: mat.get-color-from-palette(mat.$pink-palette, 100); 51 | 52 | .mat-card-content { 53 | display: flex; 54 | flex-direction: column; 55 | } 56 | } 57 | 58 | .quantity-slider { 59 | width: 100%; 60 | } 61 | 62 | .fillings { 63 | flex-grow: 1; 64 | 65 | // TODO: #7. Create selectable controls with Angular Material 66 | } 67 | 68 | .quantity { 69 | flex-grow: 3; 70 | } 71 | 72 | .color { 73 | flex-grow: 2; 74 | margin: 0 0 10px 0; 75 | } 76 | } 77 | 78 | .purchase-button { 79 | width: 100%; 80 | padding: 10px 0; 81 | border-radius: 5px; 82 | background-color: mat.get-color-from-palette(mat.$pink-palette, A100); 83 | 84 | // TODO: #12. Enable HighContrast mode 85 | @include cdk.high-contrast() { 86 | outline: solid 1px; 87 | background-color: mat.get-color-from-palette(mat.$pink-palette, 50); 88 | } 89 | 90 | text-align: center; 91 | text-transform: uppercase; 92 | letter-spacing: 12px; 93 | 94 | h3 { 95 | margin: 16px 0 16px; 96 | } 97 | } 98 | } 99 | 100 | :host-context(.dark-theme) { 101 | .dumpling-customizations .selection-card { 102 | background-color: mat.get-color-from-palette(mat.$indigo-palette, 400); 103 | } 104 | 105 | .purchase-button { 106 | background-color: mat.get-color-from-palette(mat.$light-green-palette, A100); 107 | 108 | // TODO: #12. Enable HighContrast mode 109 | @include cdk.high-contrast() { 110 | // outline: solid 1px; 111 | // background-color: mat.get-color-from-palette(mat.$light-green-palette, 50); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/app/shop/shop.component.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { LiveAnnouncer } from '@angular/cdk/a11y'; 17 | import { Component, OnInit } from '@angular/core'; 18 | 19 | @Component({ 20 | selector: 'app-shop', 21 | templateUrl: './shop.component.html', 22 | styleUrls: ['./shop.component.scss'] 23 | }) 24 | export class ShopComponent implements OnInit { 25 | quantity = 11; 26 | color = 'gold'; 27 | 28 | // TODO: #7. Create selectable controls with Angular Material 29 | fillings: string[] = ['Bok Choy & Chili Crunch', 'Tofu & Mushroom', 'Chicken & Ginger', 'Impossible Meat & Spinach']; 30 | selectedFillings: string[] = []; 31 | 32 | // TODO: #11. Announce changes with LiveAnnouncer 33 | constructor(private liveAnnouncer: LiveAnnouncer) { } 34 | 35 | ngOnInit(): void { } 36 | 37 | counter(i: number): Array { 38 | return new Array(i); 39 | } 40 | 41 | public changeColor(color: string): void { 42 | this.color = color; 43 | } 44 | 45 | fauxPurchase(): void { 46 | let flavor = ''; 47 | 48 | // TODO: #7. Create selectable controls with Angular Material 49 | this.selectedFillings.forEach(filling => { 50 | flavor = flavor + ' ' + filling; 51 | }); 52 | 53 | const fakePurchase = `Purchase ${this.quantity} ${flavor}dumplings in the color ${this.color}!`; 54 | console.log(fakePurchase); 55 | 56 | // TODO: #11. Announce changes with LiveAnnouncer 57 | this.liveAnnouncer.announce(fakePurchase); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/angular-accessibility/709fc82883b9873a654697c15a2c2d45b0e409ff/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/assets/blue-demo-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/angular-accessibility/709fc82883b9873a654697c15a2c2d45b0e409ff/src/assets/blue-demo-screenshot.png -------------------------------------------------------------------------------- /src/assets/pink-demo-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/angular-accessibility/709fc82883b9873a654697c15a2c2d45b0e409ff/src/assets/pink-demo-screenshot.png -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | export const environment = { 17 | production: true 18 | }; 19 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | // This file can be replaced during build by using the `fileReplacements` array. 17 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 18 | // The list of file replacements can be found in `angular.json`. 19 | 20 | export const environment = { 21 | production: false 22 | }; 23 | 24 | /* 25 | * For easier debugging in development mode, you can import the following file 26 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 27 | * 28 | * This import should be commented out in production mode because it will have a negative impact 29 | * on performance if an error is thrown. 30 | */ 31 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 32 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/angular-accessibility/709fc82883b9873a654697c15a2c2d45b0e409ff/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | a11y in Angular 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { enableProdMode } from '@angular/core'; 17 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 18 | 19 | import { AppModule } from './app/app.module'; 20 | import { environment } from './environments/environment'; 21 | 22 | if (environment.production) { 23 | enableProdMode(); 24 | } 25 | 26 | platformBrowserDynamic().bootstrapModule(AppModule) 27 | .catch(err => console.error(err)); 28 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | /** 17 | * This file includes polyfills needed by Angular and is loaded before the app. 18 | * You can add your own extra polyfills to this file. 19 | * 20 | * This file is divided into 2 sections: 21 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 22 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 23 | * file. 24 | * 25 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 26 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 27 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 28 | * 29 | * Learn more in https://angular.io/guide/browser-support 30 | */ 31 | 32 | /*************************************************************************************************** 33 | * BROWSER POLYFILLS 34 | */ 35 | 36 | /** 37 | * By default, zone.js will patch all possible macroTask and DomEvents 38 | * user can disable parts of macroTask/DomEvents patch by setting following flags 39 | * because those flags need to be set before `zone.js` being loaded, and webpack 40 | * will put import in the top of bundle, so user need to create a separate file 41 | * in this directory (for example: zone-flags.ts), and put the following flags 42 | * into that file, and then add the following code before importing zone.js. 43 | * import './zone-flags'; 44 | * 45 | * The flags allowed in zone-flags.ts are listed here. 46 | * 47 | * The following flags will work for all browsers. 48 | * 49 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 50 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 51 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 52 | * 53 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 54 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 55 | * 56 | * (window as any).__Zone_enable_cross_context_check = true; 57 | * 58 | */ 59 | 60 | /*************************************************************************************************** 61 | * Zone JS is required by default for Angular itself. 62 | */ 63 | import 'zone.js'; // Included with Angular CLI. 64 | 65 | 66 | /*************************************************************************************************** 67 | * APPLICATION IMPORTS 68 | */ 69 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | @use '@angular/material' as mat; 17 | 18 | @import url('https://fonts.googleapis.com/css2?family=Vollkorn:ital,wght@1,700&Lato:wght@400;700;900&display=swap'); 19 | $vollkorn-font-family: 'Vollkorn', serif; 20 | $lato-font-family: 'Lato', sans-serif; 21 | 22 | // TODO: #5. Ensure adequate color contrast 23 | $light-primary: mat.define-palette(mat.$pink-palette, $default: A100, $lighter: 100, $text: 900); 24 | $light-accent: mat.define-palette(mat.$red-palette, $default: A400, $lighter: 100); 25 | 26 | $dark-primary: mat.define-palette(mat.$light-green-palette, $default: A100, $lighter: 50, $text: 900); 27 | $dark-accent: mat.define-palette(mat.$indigo-palette, $default: 600, $lighter: 500); 28 | 29 | $custom-typography: mat.define-typography-config( 30 | $font-family: $lato-font-family, 31 | $display-4: mat.define-typography-level(112px, 112px, 700, $letter-spacing: -0.05em, $font-family: $vollkorn-font-family), 32 | $display-3: mat.define-typography-level(56px, 56px, 700, $letter-spacing: -0.02em, $font-family: $vollkorn-font-family), 33 | $display-2: mat.define-typography-level(45px, 48px, 700, $letter-spacing: -0.005em, $font-family: $vollkorn-font-family), 34 | $display-1: mat.define-typography-level(34px, 40px, 700, $font-family: $vollkorn-font-family), 35 | $headline: mat.define-typography-level(18px, 32px, 700, $font-family: $vollkorn-font-family), 36 | $title: mat.define-typography-level(50px, 32px, 700, $font-family: $vollkorn-font-family), 37 | $subheading-2: mat.define-typography-level(18px, 28px, 700, $letter-spacing: .2em, $font-family: $lato-font-family), 38 | $subheading-1: mat.define-typography-level(18px, 24px, 700, $font-family: $lato-font-family), 39 | $body-2: mat.define-typography-level(18px, 24px, 700, $font-family: $lato-font-family), 40 | $body-1: mat.define-typography-level(16px, 20px, 700, $font-family: $lato-font-family), 41 | $caption: mat.define-typography-level(16px, 20px, 700, $font-family: $lato-font-family), 42 | $button: mat.define-typography-level(18px, 28px, 700, $font-family: $lato-font-family), 43 | $input: mat.define-typography-level(inherit, 1.125, 700, $font-family: $lato-font-family) 44 | ); 45 | 46 | $light-theme: mat.define-light-theme(( 47 | color: ( 48 | primary: $light-primary, 49 | accent: $light-accent, 50 | ), 51 | typography: $custom-typography 52 | )); 53 | 54 | $dark-theme: mat.define-dark-theme(( 55 | color: ( 56 | primary: $dark-primary, 57 | accent: $dark-accent 58 | ) 59 | )); 60 | 61 | @include mat.core(); 62 | @include mat.core-theme($light-theme); 63 | @include mat.all-component-themes($light-theme); 64 | @include mat.all-component-typographies($light-theme); 65 | 66 | .dark-theme { 67 | @include mat.core-color($dark-theme); 68 | @include mat.all-component-themes($dark-theme); 69 | } 70 | 71 | /* Global styles */ 72 | html, body { 73 | height: 100%; 74 | } 75 | 76 | body { 77 | margin: 0; 78 | -webkit-appearance: none; 79 | background-color: mat.get-color-from-palette($light-accent, default); 80 | color: mat.get-contrast-color-from-palette($light-accent, default); 81 | } 82 | 83 | .dark-theme body { 84 | background-color: mat.get-color-from-palette($dark-accent, default); 85 | color: mat.get-contrast-color-from-palette($dark-accent, default); 86 | } 87 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 17 | 18 | import 'zone.js/testing'; 19 | import { getTestBed } from '@angular/core/testing'; 20 | import { 21 | BrowserDynamicTestingModule, 22 | platformBrowserDynamicTesting 23 | } from '@angular/platform-browser-dynamic/testing'; 24 | 25 | declare const require: { 26 | context(path: string, deep?: boolean, filter?: RegExp): { 27 | (id: string): T; 28 | keys(): string[]; 29 | }; 30 | }; 31 | 32 | // First, initialize the Angular testing environment. 33 | getTestBed().initTestEnvironment( 34 | BrowserDynamicTestingModule, 35 | platformBrowserDynamicTesting(), { 36 | teardown: { destroyAfterEach: false } 37 | } 38 | ); 39 | // Then we find all the tests. 40 | const context = require.context('./', true, /\.spec\.ts$/); 41 | // And load the modules. 42 | context.keys().map(context); 43 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "sourceMap": true, 12 | "declaration": false, 13 | "downlevelIteration": true, 14 | "experimentalDecorators": true, 15 | "moduleResolution": "node", 16 | "importHelpers": true, 17 | "target": "es2015", 18 | "module": "es2020", 19 | "lib": [ 20 | "es2018", 21 | "dom" 22 | ] 23 | }, 24 | "angularCompilerOptions": { 25 | "enableI18nLegacyMessageIdFormat": false, 26 | "strictInjectionParameters": true, 27 | "strictInputAccessModifiers": true, 28 | "strictTemplates": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | --------------------------------------------------------------------------------