├── .browserslistrc ├── .eslintrc.js ├── .gitignore ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── assets │ └── scss │ │ ├── app.scss │ │ └── settings.scss ├── main.ts ├── models │ ├── BaseModel.ts │ └── Task.ts ├── router │ └── index.ts ├── shims-vue.d.ts ├── shims-vuex.d.ts ├── store │ └── index.ts └── views │ ├── AddTask │ ├── AddTask.html │ ├── AddTask.scss │ ├── AddTask.ts │ └── AddTask.vue │ └── Home │ ├── Home.html │ ├── Home.scss │ ├── Home.ts │ └── Home.vue └── tsconfig.json /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: [ 7 | "plugin:vue/vue3-essential", 8 | "eslint:recommended", 9 | "@vue/typescript/recommended", 10 | "@vue/prettier", 11 | "@vue/prettier/@typescript-eslint" 12 | ], 13 | parserOptions: { 14 | ecmaVersion: 2020 15 | }, 16 | rules: { 17 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", 18 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off" 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # todo-app2 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | npm run lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@vue/cli-plugin-babel/preset"] 3 | }; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "todo-app2", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@types/lodash": "^4.14.168", 12 | "core-js": "^3.6.5", 13 | "font-awesome": "^4.7.0", 14 | "font-awesome-sass": "^4.7.0", 15 | "foundation-sites": "^6.6.3", 16 | "lodash": "^4.17.21", 17 | "vue": "^3.0.0", 18 | "vue-class-component": "^8.0.0-0", 19 | "vue-router": "^4.0.0-0", 20 | "vuex": "^4.0.0-0" 21 | }, 22 | "devDependencies": { 23 | "@typescript-eslint/eslint-plugin": "^2.33.0", 24 | "@typescript-eslint/parser": "^2.33.0", 25 | "@vue/cli-plugin-babel": "~4.5.0", 26 | "@vue/cli-plugin-eslint": "~4.5.0", 27 | "@vue/cli-plugin-router": "~4.5.0", 28 | "@vue/cli-plugin-typescript": "~4.5.0", 29 | "@vue/cli-plugin-vuex": "~4.5.0", 30 | "@vue/cli-service": "~4.5.0", 31 | "@vue/compiler-sfc": "^3.0.0", 32 | "@vue/eslint-config-prettier": "^6.0.0", 33 | "@vue/eslint-config-typescript": "^5.0.2", 34 | "eslint": "^6.7.2", 35 | "eslint-plugin-prettier": "^3.1.3", 36 | "eslint-plugin-vue": "^7.0.0-0", 37 | "node-sass": "^4.12.0", 38 | "prettier": "^1.19.1", 39 | "sass-loader": "^8.0.2", 40 | "typescript": "~3.9.3" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/architanayak/vue3-typescript-todo-app/f849a4d153637e53337d792258ba901aa0484d26/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/assets/scss/app.scss: -------------------------------------------------------------------------------- 1 | $fa-font-path: "../../../node_modules/font-awesome-sass/assets/fonts/font-awesome/"; 2 | @import "../../../node_modules/font-awesome-sass/assets/stylesheets/font-awesome"; 3 | @import "~foundation-sites/scss/foundation"; 4 | @import "settings"; 5 | @include foundation-flex-classes; 6 | @include foundation-flex-grid; 7 | @include foundation-everything(true); 8 | 9 | body{ 10 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 11 | color: #4d4d4d; 12 | font-size: 18px; 13 | line-height: 1.4em; 14 | } 15 | .text-line-through { 16 | text-decoration: line-through; 17 | } 18 | 19 | .button { 20 | margin: 0; 21 | } 22 | 23 | .bottom_bar { 24 | background-color: #0000002e; 25 | font-size: 1.5rem; 26 | position: fixed; 27 | width: 100%; 28 | bottom: 0; 29 | padding: 1.5rem; 30 | 31 | a { 32 | color: #0b0a0ab0; 33 | 34 | 35 | &.router-link-exact-active { 36 | color: #0b0a0a; 37 | } 38 | 39 | i{ 40 | margin-right: 10px 41 | } 42 | } 43 | } 44 | 45 | .fade-enter-active, .fade-leave-active { 46 | transition: all .2s ease; 47 | } 48 | 49 | .fade-enter, .fade-leave-active { 50 | opacity: 0; 51 | } 52 | -------------------------------------------------------------------------------- /src/assets/scss/settings.scss: -------------------------------------------------------------------------------- 1 | // Foundation for Sites Settings 2 | // ----------------------------- 3 | // 4 | // Table of Contents: 5 | // 6 | // 1. Global 7 | // 2. Breakpoints 8 | // 3. The Grid 9 | // 4. Base Typography 10 | // 5. Typography Helpers 11 | // 6. Abide 12 | // 7. Accordion 13 | // 8. Accordion Menu 14 | // 9. Badge 15 | // 10. Breadcrumbs 16 | // 11. Button 17 | // 12. Button Group 18 | // 13. Callout 19 | // 14. Card 20 | // 15. Close Button 21 | // 16. Drilldown 22 | // 17. Dropdown 23 | // 18. Dropdown Menu 24 | // 19. Flexbox Utilities 25 | // 20. Forms 26 | // 21. Label 27 | // 22. Media Object 28 | // 23. Menu 29 | // 24. Meter 30 | // 25. Off-canvas 31 | // 26. Orbit 32 | // 27. Pagination 33 | // 28. Progress Bar 34 | // 29. Prototype Arrow 35 | // 30. Prototype Border-Box 36 | // 31. Prototype Border-None 37 | // 32. Prototype Bordered 38 | // 33. Prototype Display 39 | // 34. Prototype Font-Styling 40 | // 35. Prototype List-Style-Type 41 | // 36. Prototype Overflow 42 | // 37. Prototype Position 43 | // 38. Prototype Rounded 44 | // 39. Prototype Separator 45 | // 40. Prototype Shadow 46 | // 41. Prototype Sizing 47 | // 42. Prototype Spacing 48 | // 43. Prototype Text-Decoration 49 | // 44. Prototype Text-Transformation 50 | // 45. Prototype Text-Utilities 51 | // 46. Responsive Embed 52 | // 47. Reveal 53 | // 48. Slider 54 | // 49. Switch 55 | // 50. Table 56 | // 51. Tabs 57 | // 52. Thumbnail 58 | // 53. Title Bar 59 | // 54. Tooltip 60 | // 55. Top Bar 61 | // 56. Xy Grid 62 | 63 | @import '~foundation-sites/scss/util/util'; 64 | 65 | // 1. Global 66 | // --------- 67 | 68 | $global-font-size: 100%; 69 | $global-width: rem-calc(1200); 70 | $global-lineheight: 1.5; 71 | $foundation-palette: ( 72 | primary: #1779ba, 73 | secondary: #767676, 74 | success: #3adb76, 75 | warning: #ffae00, 76 | alert: #cc4b37, 77 | ); 78 | $light-gray: #e6e6e6; 79 | $medium-gray: #cacaca; 80 | $dark-gray: #8a8a8a; 81 | $black: #0a0a0a; 82 | $white: #fefefe; 83 | $body-background: $white; 84 | $body-font-color: $black; 85 | $body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; 86 | $body-antialiased: true; 87 | $global-margin: 1rem; 88 | $global-padding: 1rem; 89 | $global-position: 1rem; 90 | $global-weight-normal: normal; 91 | $global-weight-bold: bold; 92 | $global-radius: 0; 93 | $global-menu-padding: 0.7rem 1rem; 94 | $global-menu-nested-margin: 1rem; 95 | $global-text-direction: ltr; 96 | $global-flexbox: true; 97 | $global-prototype-breakpoints: false; 98 | $global-button-cursor: auto; 99 | $global-color-pick-contrast-tolerance: 0; 100 | $print-transparent-backgrounds: true; 101 | 102 | @include add-foundation-colors; 103 | 104 | // 2. Breakpoints 105 | // -------------- 106 | 107 | $breakpoints: ( 108 | small: 0, 109 | medium: 640px, 110 | large: 1024px, 111 | xlarge: 1200px, 112 | xxlarge: 1440px, 113 | ); 114 | $print-breakpoint: large; 115 | $breakpoint-classes: (small medium large); 116 | 117 | // 3. The Grid 118 | // ----------- 119 | 120 | $grid-row-width: $global-width; 121 | $grid-column-count: 12; 122 | $grid-column-gutter: ( 123 | small: 20px, 124 | medium: 30px, 125 | ); 126 | $grid-column-align-edge: true; 127 | $grid-column-alias: 'columns'; 128 | $block-grid-max: 8; 129 | 130 | // 4. Base Typography 131 | // ------------------ 132 | 133 | $header-font-family: $body-font-family; 134 | $header-font-weight: $global-weight-normal; 135 | $header-font-style: normal; 136 | $font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace; 137 | $header-color: inherit; 138 | $header-lineheight: 1.4; 139 | $header-margin-bottom: 0.5rem; 140 | $header-styles: ( 141 | small: ( 142 | 'h1': ('font-size': 24), 143 | 'h2': ('font-size': 20), 144 | 'h3': ('font-size': 19), 145 | 'h4': ('font-size': 18), 146 | 'h5': ('font-size': 17), 147 | 'h6': ('font-size': 16), 148 | ), 149 | medium: ( 150 | 'h1': ('font-size': 48), 151 | 'h2': ('font-size': 40), 152 | 'h3': ('font-size': 31), 153 | 'h4': ('font-size': 25), 154 | 'h5': ('font-size': 20), 155 | 'h6': ('font-size': 16), 156 | ), 157 | ); 158 | $header-text-rendering: optimizeLegibility; 159 | $small-font-size: 80%; 160 | $header-small-font-color: $medium-gray; 161 | $paragraph-lineheight: 1.6; 162 | $paragraph-margin-bottom: 1rem; 163 | $paragraph-text-rendering: optimizeLegibility; 164 | $code-color: $black; 165 | $code-font-family: $font-family-monospace; 166 | $code-font-weight: $global-weight-normal; 167 | $code-background: $light-gray; 168 | $code-border: 1px solid $medium-gray; 169 | $code-padding: rem-calc(2 5 1); 170 | $anchor-color: $primary-color; 171 | $anchor-color-hover: scale-color($anchor-color, $lightness: -14%); 172 | $anchor-text-decoration: none; 173 | $anchor-text-decoration-hover: none; 174 | $hr-width: $global-width; 175 | $hr-border: 1px solid $medium-gray; 176 | $hr-margin: rem-calc(20) auto; 177 | $list-lineheight: $paragraph-lineheight; 178 | $list-margin-bottom: $paragraph-margin-bottom; 179 | $list-style-type: disc; 180 | $list-style-position: outside; 181 | $list-side-margin: 1.25rem; 182 | $list-nested-side-margin: 1.25rem; 183 | $defnlist-margin-bottom: 1rem; 184 | $defnlist-term-weight: $global-weight-bold; 185 | $defnlist-term-margin-bottom: 0.3rem; 186 | $blockquote-color: $dark-gray; 187 | $blockquote-padding: rem-calc(9 20 0 19); 188 | $blockquote-border: 1px solid $medium-gray; 189 | $cite-font-size: rem-calc(13); 190 | $cite-color: $dark-gray; 191 | $cite-pseudo-content: '\2014 \0020'; 192 | $keystroke-font: $font-family-monospace; 193 | $keystroke-color: $black; 194 | $keystroke-background: $light-gray; 195 | $keystroke-padding: rem-calc(2 4 0); 196 | $keystroke-radius: $global-radius; 197 | $abbr-underline: 1px dotted $black; 198 | 199 | // 5. Typography Helpers 200 | // --------------------- 201 | 202 | $lead-font-size: $global-font-size * 1.25; 203 | $lead-lineheight: 1.6; 204 | $subheader-lineheight: 1.4; 205 | $subheader-color: $dark-gray; 206 | $subheader-font-weight: $global-weight-normal; 207 | $subheader-margin-top: 0.2rem; 208 | $subheader-margin-bottom: 0.5rem; 209 | $stat-font-size: 2.5rem; 210 | 211 | // 6. Abide 212 | // -------- 213 | 214 | $abide-inputs: true; 215 | $abide-labels: true; 216 | $input-background-invalid: get-color(alert); 217 | $form-label-color-invalid: get-color(alert); 218 | $input-error-color: get-color(alert); 219 | $input-error-font-size: rem-calc(12); 220 | $input-error-font-weight: $global-weight-bold; 221 | 222 | // 7. Accordion 223 | // ------------ 224 | 225 | $accordion-background: $white; 226 | $accordion-plusminus: true; 227 | $accordion-title-font-size: rem-calc(12); 228 | $accordion-item-color: $primary-color; 229 | $accordion-item-background-hover: $light-gray; 230 | $accordion-item-padding: 1.25rem 1rem; 231 | $accordion-content-background: $white; 232 | $accordion-content-border: 1px solid $light-gray; 233 | $accordion-content-color: $body-font-color; 234 | $accordion-content-padding: 1rem; 235 | 236 | // 8. Accordion Menu 237 | // ----------------- 238 | 239 | $accordionmenu-padding: $global-menu-padding; 240 | $accordionmenu-nested-margin: $global-menu-nested-margin; 241 | $accordionmenu-submenu-padding: $accordionmenu-padding; 242 | $accordionmenu-arrows: true; 243 | $accordionmenu-arrow-color: $primary-color; 244 | $accordionmenu-item-background: null; 245 | $accordionmenu-border: null; 246 | $accordionmenu-submenu-toggle-background: null; 247 | $accordion-submenu-toggle-border: $accordionmenu-border; 248 | $accordionmenu-submenu-toggle-width: 40px; 249 | $accordionmenu-submenu-toggle-height: $accordionmenu-submenu-toggle-width; 250 | $accordionmenu-arrow-size: 6px; 251 | 252 | // 9. Badge 253 | // -------- 254 | 255 | $badge-background: $primary-color; 256 | $badge-color: $white; 257 | $badge-color-alt: $black; 258 | $badge-palette: $foundation-palette; 259 | $badge-padding: 0.3em; 260 | $badge-minwidth: 2.1em; 261 | $badge-font-size: 0.6rem; 262 | 263 | // 10. Breadcrumbs 264 | // --------------- 265 | 266 | $breadcrumbs-margin: 0 0 $global-margin 0; 267 | $breadcrumbs-item-font-size: rem-calc(11); 268 | $breadcrumbs-item-color: $primary-color; 269 | $breadcrumbs-item-color-current: $black; 270 | $breadcrumbs-item-color-disabled: $medium-gray; 271 | $breadcrumbs-item-margin: 0.75rem; 272 | $breadcrumbs-item-uppercase: true; 273 | $breadcrumbs-item-separator: true; 274 | $breadcrumbs-item-separator-item: '/'; 275 | $breadcrumbs-item-separator-item-rtl: '\\'; 276 | $breadcrumbs-item-separator-color: $medium-gray; 277 | 278 | // 11. Button 279 | // ---------- 280 | 281 | $button-font-family: inherit; 282 | $button-padding: 0.85em 1em; 283 | $button-margin: 0 0 $global-margin 0; 284 | $button-fill: solid; 285 | $button-background: $primary-color; 286 | $button-background-hover: scale-color($button-background, $lightness: -15%); 287 | $button-color: $white; 288 | $button-color-alt: $black; 289 | $button-radius: $global-radius; 290 | $button-hollow-border-width: 1px; 291 | $button-sizes: ( 292 | tiny: 0.6rem, 293 | small: 0.75rem, 294 | default: 0.9rem, 295 | large: 1.25rem, 296 | ); 297 | $button-palette: $foundation-palette; 298 | $button-opacity-disabled: 0.25; 299 | $button-background-hover-lightness: -20%; 300 | $button-hollow-hover-lightness: -50%; 301 | $button-transition: background-color 0.25s ease-out, color 0.25s ease-out; 302 | $button-responsive-expanded: false; 303 | 304 | // 12. Button Group 305 | // ---------------- 306 | 307 | $buttongroup-margin: 1rem; 308 | $buttongroup-spacing: 1px; 309 | $buttongroup-child-selector: '.button'; 310 | $buttongroup-expand-max: 6; 311 | $buttongroup-radius-on-each: true; 312 | 313 | // 13. Callout 314 | // ----------- 315 | 316 | $callout-background: $white; 317 | $callout-background-fade: 85%; 318 | $callout-border: 1px solid rgba($black, 0.25); 319 | $callout-margin: 0 0 1rem 0; 320 | $callout-padding: 1rem; 321 | $callout-font-color: $body-font-color; 322 | $callout-font-color-alt: $body-background; 323 | $callout-radius: $global-radius; 324 | $callout-link-tint: 30%; 325 | 326 | // 14. Card 327 | // -------- 328 | 329 | $card-background: $white; 330 | $card-font-color: $body-font-color; 331 | $card-divider-background: $light-gray; 332 | $card-border: 1px solid $light-gray; 333 | $card-shadow: none; 334 | $card-border-radius: $global-radius; 335 | $card-padding: $global-padding; 336 | $card-margin-bottom: $global-margin; 337 | 338 | // 15. Close Button 339 | // ---------------- 340 | 341 | $closebutton-position: right top; 342 | $closebutton-offset-horizontal: ( 343 | small: 0.66rem, 344 | medium: 1rem, 345 | ); 346 | $closebutton-offset-vertical: ( 347 | small: 0.33em, 348 | medium: 0.5rem, 349 | ); 350 | $closebutton-size: ( 351 | small: 1.5em, 352 | medium: 2em, 353 | ); 354 | $closebutton-lineheight: 1; 355 | $closebutton-color: $dark-gray; 356 | $closebutton-color-hover: $black; 357 | 358 | // 16. Drilldown 359 | // ------------- 360 | 361 | $drilldown-transition: transform 0.15s linear; 362 | $drilldown-arrows: true; 363 | $drilldown-padding: $global-menu-padding; 364 | $drilldown-nested-margin: 0; 365 | $drilldown-background: $white; 366 | $drilldown-submenu-padding: $drilldown-padding; 367 | $drilldown-submenu-background: $white; 368 | $drilldown-arrow-color: $primary-color; 369 | $drilldown-arrow-size: 6px; 370 | 371 | // 17. Dropdown 372 | // ------------ 373 | 374 | $dropdown-padding: 1rem; 375 | $dropdown-background: $body-background; 376 | $dropdown-border: 1px solid $medium-gray; 377 | $dropdown-font-size: 1rem; 378 | $dropdown-width: 300px; 379 | $dropdown-radius: $global-radius; 380 | $dropdown-sizes: ( 381 | tiny: 100px, 382 | small: 200px, 383 | large: 400px, 384 | ); 385 | 386 | // 18. Dropdown Menu 387 | // ----------------- 388 | 389 | $dropdownmenu-arrows: true; 390 | $dropdownmenu-arrow-color: $anchor-color; 391 | $dropdownmenu-arrow-size: 6px; 392 | $dropdownmenu-arrow-padding: 1.5rem; 393 | $dropdownmenu-min-width: 200px; 394 | $dropdownmenu-background: $white; 395 | $dropdownmenu-submenu-background: $dropdownmenu-background; 396 | $dropdownmenu-padding: $global-menu-padding; 397 | $dropdownmenu-nested-margin: 0; 398 | $dropdownmenu-submenu-padding: $dropdownmenu-padding; 399 | $dropdownmenu-border: 1px solid $medium-gray; 400 | $dropdown-menu-item-color-active: get-color(primary); 401 | $dropdown-menu-item-background-active: transparent; 402 | 403 | // 19. Flexbox Utilities 404 | // --------------------- 405 | 406 | $flex-source-ordering-count: 6; 407 | $flexbox-responsive-breakpoints: true; 408 | 409 | // 20. Forms 410 | // --------- 411 | 412 | $fieldset-border: 1px solid $medium-gray; 413 | $fieldset-padding: rem-calc(20); 414 | $fieldset-margin: rem-calc(18 0); 415 | $legend-padding: rem-calc(0 3); 416 | $form-spacing: rem-calc(16); 417 | $helptext-color: $black; 418 | $helptext-font-size: rem-calc(13); 419 | $helptext-font-style: italic; 420 | $input-prefix-color: $black; 421 | $input-prefix-background: $light-gray; 422 | $input-prefix-border: 1px solid $medium-gray; 423 | $input-prefix-padding: 1rem; 424 | $form-label-color: $black; 425 | $form-label-font-size: rem-calc(14); 426 | $form-label-font-weight: $global-weight-normal; 427 | $form-label-line-height: 1.8; 428 | $select-background: $white; 429 | $select-triangle-color: $dark-gray; 430 | $select-radius: $global-radius; 431 | $input-color: $black; 432 | $input-placeholder-color: $medium-gray; 433 | $input-font-family: inherit; 434 | $input-font-size: rem-calc(16); 435 | $input-font-weight: $global-weight-normal; 436 | $input-line-height: $global-lineheight; 437 | $input-background: $white; 438 | $input-background-focus: $white; 439 | $input-background-disabled: $light-gray; 440 | $input-border: 1px solid $medium-gray; 441 | $input-border-focus: 1px solid $dark-gray; 442 | $input-padding: $form-spacing / 2; 443 | $input-shadow: inset 0 1px 2px rgba($black, 0.1); 444 | $input-shadow-focus: 0 0 5px $medium-gray; 445 | $input-cursor-disabled: not-allowed; 446 | $input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out; 447 | $input-number-spinners: true; 448 | $input-radius: $global-radius; 449 | $form-button-radius: $global-radius; 450 | 451 | // 21. Label 452 | // --------- 453 | 454 | $label-background: $primary-color; 455 | $label-color: $white; 456 | $label-color-alt: $black; 457 | $label-palette: $foundation-palette; 458 | $label-font-size: 0.8rem; 459 | $label-padding: 0.33333rem 0.5rem; 460 | $label-radius: $global-radius; 461 | 462 | // 22. Media Object 463 | // ---------------- 464 | 465 | $mediaobject-margin-bottom: $global-margin; 466 | $mediaobject-section-padding: $global-padding; 467 | $mediaobject-image-width-stacked: 100%; 468 | 469 | // 23. Menu 470 | // -------- 471 | 472 | $menu-margin: 0; 473 | $menu-nested-margin: $global-menu-nested-margin; 474 | $menu-items-padding: $global-menu-padding; 475 | $menu-simple-margin: 1rem; 476 | $menu-item-color-active: $white; 477 | $menu-item-background-active: get-color(primary); 478 | $menu-icon-spacing: 0.25rem; 479 | $menu-item-background-hover: $light-gray; 480 | $menu-state-back-compat: true; 481 | $menu-centered-back-compat: true; 482 | $menu-icons-back-compat: true; 483 | 484 | // 24. Meter 485 | // --------- 486 | 487 | $meter-height: 1rem; 488 | $meter-radius: $global-radius; 489 | $meter-background: $medium-gray; 490 | $meter-fill-good: $success-color; 491 | $meter-fill-medium: $warning-color; 492 | $meter-fill-bad: $alert-color; 493 | 494 | // 25. Off-canvas 495 | // -------------- 496 | 497 | $offcanvas-sizes: ( 498 | small: 250px, 499 | ); 500 | $offcanvas-vertical-sizes: ( 501 | small: 250px, 502 | ); 503 | $offcanvas-background: $light-gray; 504 | $offcanvas-shadow: 0 0 10px rgba($black, 0.7); 505 | $offcanvas-inner-shadow-size: 20px; 506 | $offcanvas-inner-shadow-color: rgba($black, 0.25); 507 | $offcanvas-overlay-zindex: 11; 508 | $offcanvas-push-zindex: 12; 509 | $offcanvas-overlap-zindex: 13; 510 | $offcanvas-reveal-zindex: 12; 511 | $offcanvas-transition-length: 0.5s; 512 | $offcanvas-transition-timing: ease; 513 | $offcanvas-fixed-reveal: true; 514 | $offcanvas-exit-background: rgba($white, 0.25); 515 | $maincontent-class: 'off-canvas-content'; 516 | 517 | // 26. Orbit 518 | // --------- 519 | 520 | $orbit-bullet-background: $medium-gray; 521 | $orbit-bullet-background-active: $dark-gray; 522 | $orbit-bullet-diameter: 1.2rem; 523 | $orbit-bullet-margin: 0.1rem; 524 | $orbit-bullet-margin-top: 0.8rem; 525 | $orbit-bullet-margin-bottom: 0.8rem; 526 | $orbit-caption-background: rgba($black, 0.5); 527 | $orbit-caption-padding: 1rem; 528 | $orbit-control-background-hover: rgba($black, 0.5); 529 | $orbit-control-padding: 1rem; 530 | $orbit-control-zindex: 10; 531 | 532 | // 27. Pagination 533 | // -------------- 534 | 535 | $pagination-font-size: rem-calc(14); 536 | $pagination-margin-bottom: $global-margin; 537 | $pagination-item-color: $black; 538 | $pagination-item-padding: rem-calc(3 10); 539 | $pagination-item-spacing: rem-calc(1); 540 | $pagination-radius: $global-radius; 541 | $pagination-item-background-hover: $light-gray; 542 | $pagination-item-background-current: $primary-color; 543 | $pagination-item-color-current: $white; 544 | $pagination-item-color-disabled: $medium-gray; 545 | $pagination-ellipsis-color: $black; 546 | $pagination-mobile-items: false; 547 | $pagination-mobile-current-item: false; 548 | $pagination-arrows: true; 549 | 550 | // 28. Progress Bar 551 | // ---------------- 552 | 553 | $progress-height: 1rem; 554 | $progress-background: $medium-gray; 555 | $progress-margin-bottom: $global-margin; 556 | $progress-meter-background: $primary-color; 557 | $progress-radius: $global-radius; 558 | 559 | // 29. Prototype Arrow 560 | // ------------------- 561 | 562 | $prototype-arrow-directions: ( 563 | down, 564 | up, 565 | right, 566 | left 567 | ); 568 | $prototype-arrow-size: 0.4375rem; 569 | $prototype-arrow-color: $black; 570 | 571 | // 30. Prototype Border-Box 572 | // ------------------------ 573 | 574 | $prototype-border-box-breakpoints: $global-prototype-breakpoints; 575 | 576 | // 31. Prototype Border-None 577 | // ------------------------- 578 | 579 | $prototype-border-none-breakpoints: $global-prototype-breakpoints; 580 | 581 | // 32. Prototype Bordered 582 | // ---------------------- 583 | 584 | $prototype-bordered-breakpoints: $global-prototype-breakpoints; 585 | $prototype-border-width: rem-calc(1); 586 | $prototype-border-type: solid; 587 | $prototype-border-color: $medium-gray; 588 | 589 | // 33. Prototype Display 590 | // --------------------- 591 | 592 | $prototype-display-breakpoints: $global-prototype-breakpoints; 593 | $prototype-display: ( 594 | inline, 595 | inline-block, 596 | block, 597 | table, 598 | table-cell 599 | ); 600 | 601 | // 34. Prototype Font-Styling 602 | // -------------------------- 603 | 604 | $prototype-font-breakpoints: $global-prototype-breakpoints; 605 | $prototype-wide-letter-spacing: rem-calc(4); 606 | $prototype-font-normal: $global-weight-normal; 607 | $prototype-font-bold: $global-weight-bold; 608 | 609 | // 35. Prototype List-Style-Type 610 | // ----------------------------- 611 | 612 | $prototype-list-breakpoints: $global-prototype-breakpoints; 613 | $prototype-style-type-unordered: ( 614 | disc, 615 | circle, 616 | square 617 | ); 618 | $prototype-style-type-ordered: ( 619 | decimal, 620 | lower-alpha, 621 | lower-latin, 622 | lower-roman, 623 | upper-alpha, 624 | upper-latin, 625 | upper-roman 626 | ); 627 | 628 | // 36. Prototype Overflow 629 | // ---------------------- 630 | 631 | $prototype-overflow-breakpoints: $global-prototype-breakpoints; 632 | $prototype-overflow: ( 633 | visible, 634 | hidden, 635 | scroll 636 | ); 637 | 638 | // 37. Prototype Position 639 | // ---------------------- 640 | 641 | $prototype-position-breakpoints: $global-prototype-breakpoints; 642 | $prototype-position: ( 643 | static, 644 | relative, 645 | absolute, 646 | fixed 647 | ); 648 | $prototype-position-z-index: 975; 649 | 650 | // 38. Prototype Rounded 651 | // --------------------- 652 | 653 | $prototype-rounded-breakpoints: $global-prototype-breakpoints; 654 | $prototype-border-radius: rem-calc(3); 655 | 656 | // 39. Prototype Separator 657 | // ----------------------- 658 | 659 | $prototype-separator-breakpoints: $global-prototype-breakpoints; 660 | $prototype-separator-align: center; 661 | $prototype-separator-height: rem-calc(2); 662 | $prototype-separator-width: 3rem; 663 | $prototype-separator-background: $primary-color; 664 | $prototype-separator-margin-top: $global-margin; 665 | 666 | // 40. Prototype Shadow 667 | // -------------------- 668 | 669 | $prototype-shadow-breakpoints: $global-prototype-breakpoints; 670 | $prototype-box-shadow: 0 2px 5px 0 rgba(0,0,0,.16), 671 | 0 2px 10px 0 rgba(0,0,0,.12); 672 | 673 | // 41. Prototype Sizing 674 | // -------------------- 675 | 676 | $prototype-sizing-breakpoints: $global-prototype-breakpoints; 677 | $prototype-sizing: ( 678 | width, 679 | height 680 | ); 681 | $prototype-sizes: ( 682 | 25: 25%, 683 | 50: 50%, 684 | 75: 75%, 685 | 100: 100% 686 | ); 687 | 688 | // 42. Prototype Spacing 689 | // --------------------- 690 | 691 | $prototype-spacing-breakpoints: $global-prototype-breakpoints; 692 | $prototype-spacers-count: 3; 693 | 694 | // 43. Prototype Text-Decoration 695 | // ----------------------------- 696 | 697 | $prototype-decoration-breakpoints: $global-prototype-breakpoints; 698 | $prototype-text-decoration: ( 699 | overline, 700 | underline, 701 | line-through, 702 | ); 703 | 704 | // 44. Prototype Text-Transformation 705 | // --------------------------------- 706 | 707 | $prototype-transformation-breakpoints: $global-prototype-breakpoints; 708 | $prototype-text-transformation: ( 709 | lowercase, 710 | uppercase, 711 | capitalize 712 | ); 713 | 714 | // 45. Prototype Text-Utilities 715 | // ---------------------------- 716 | 717 | $prototype-utilities-breakpoints: $global-prototype-breakpoints; 718 | $prototype-text-overflow: ellipsis; 719 | 720 | // 46. Responsive Embed 721 | // -------------------- 722 | 723 | $responsive-embed-margin-bottom: rem-calc(16); 724 | $responsive-embed-ratios: ( 725 | default: 4 by 3, 726 | widescreen: 16 by 9, 727 | ); 728 | 729 | // 47. Reveal 730 | // ---------- 731 | 732 | $reveal-background: $white; 733 | $reveal-width: 600px; 734 | $reveal-max-width: $global-width; 735 | $reveal-padding: $global-padding; 736 | $reveal-border: 1px solid $medium-gray; 737 | $reveal-radius: $global-radius; 738 | $reveal-zindex: 1005; 739 | $reveal-overlay-background: rgba($black, 0.45); 740 | 741 | // 48. Slider 742 | // ---------- 743 | 744 | $slider-width-vertical: 0.5rem; 745 | $slider-transition: all 0.2s ease-in-out; 746 | $slider-height: 0.5rem; 747 | $slider-background: $light-gray; 748 | $slider-fill-background: $medium-gray; 749 | $slider-handle-height: 1.4rem; 750 | $slider-handle-width: 1.4rem; 751 | $slider-handle-background: $primary-color; 752 | $slider-opacity-disabled: 0.25; 753 | $slider-radius: $global-radius; 754 | 755 | // 49. Switch 756 | // ---------- 757 | 758 | $switch-background: $medium-gray; 759 | $switch-background-active: $primary-color; 760 | $switch-height: 2rem; 761 | $switch-height-tiny: 1.5rem; 762 | $switch-height-small: 1.75rem; 763 | $switch-height-large: 2.5rem; 764 | $switch-radius: $global-radius; 765 | $switch-margin: $global-margin; 766 | $switch-paddle-background: $white; 767 | $switch-paddle-offset: 0.25rem; 768 | $switch-paddle-radius: $global-radius; 769 | $switch-paddle-transition: all 0.25s ease-out; 770 | 771 | // 50. Table 772 | // --------- 773 | 774 | $table-background: $white; 775 | $table-color-scale: 5%; 776 | $table-border: 1px solid smart-scale($table-background, $table-color-scale); 777 | $table-padding: rem-calc(8 10 10); 778 | $table-hover-scale: 2%; 779 | $table-row-hover: darken($table-background, $table-hover-scale); 780 | $table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale); 781 | $table-is-striped: true; 782 | $table-striped-background: smart-scale($table-background, $table-color-scale); 783 | $table-stripe: even; 784 | $table-head-background: smart-scale($table-background, $table-color-scale / 2); 785 | $table-head-row-hover: darken($table-head-background, $table-hover-scale); 786 | $table-foot-background: smart-scale($table-background, $table-color-scale); 787 | $table-foot-row-hover: darken($table-foot-background, $table-hover-scale); 788 | $table-head-font-color: $body-font-color; 789 | $table-foot-font-color: $body-font-color; 790 | $show-header-for-stacked: false; 791 | $table-stack-breakpoint: medium; 792 | 793 | // 51. Tabs 794 | // -------- 795 | 796 | $tab-margin: 0; 797 | $tab-background: $white; 798 | $tab-color: $primary-color; 799 | $tab-background-active: $light-gray; 800 | $tab-active-color: $primary-color; 801 | $tab-item-font-size: rem-calc(12); 802 | $tab-item-background-hover: $white; 803 | $tab-item-padding: 1.25rem 1.5rem; 804 | $tab-expand-max: 6; 805 | $tab-content-background: $white; 806 | $tab-content-border: $light-gray; 807 | $tab-content-color: $body-font-color; 808 | $tab-content-padding: 1rem; 809 | 810 | // 52. Thumbnail 811 | // ------------- 812 | 813 | $thumbnail-border: solid 4px $white; 814 | $thumbnail-margin-bottom: $global-margin; 815 | $thumbnail-shadow: 0 0 0 1px rgba($black, 0.2); 816 | $thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5); 817 | $thumbnail-transition: box-shadow 200ms ease-out; 818 | $thumbnail-radius: $global-radius; 819 | 820 | // 53. Title Bar 821 | // ------------- 822 | 823 | $titlebar-background: $black; 824 | $titlebar-color: $white; 825 | $titlebar-padding: 0.5rem; 826 | $titlebar-text-font-weight: bold; 827 | $titlebar-icon-color: $white; 828 | $titlebar-icon-color-hover: $medium-gray; 829 | $titlebar-icon-spacing: 0.25rem; 830 | 831 | // 54. Tooltip 832 | // ----------- 833 | 834 | $has-tip-cursor: help; 835 | $has-tip-font-weight: $global-weight-bold; 836 | $has-tip-border-bottom: dotted 1px $dark-gray; 837 | $tooltip-background-color: $black; 838 | $tooltip-color: $white; 839 | $tooltip-padding: 0.75rem; 840 | $tooltip-max-width: 10rem; 841 | $tooltip-font-size: $small-font-size; 842 | $tooltip-pip-width: 0.75rem; 843 | $tooltip-pip-height: $tooltip-pip-width * 0.866; 844 | $tooltip-radius: $global-radius; 845 | 846 | // 55. Top Bar 847 | // ----------- 848 | 849 | $topbar-padding: 0.5rem; 850 | $topbar-background: $light-gray; 851 | $topbar-submenu-background: $topbar-background; 852 | $topbar-title-spacing: 0.5rem 1rem 0.5rem 0; 853 | $topbar-input-width: 200px; 854 | $topbar-unstack-breakpoint: medium; 855 | 856 | // 56. Xy Grid 857 | // ----------- 858 | 859 | $xy-grid: true; 860 | $grid-container: $global-width; 861 | $grid-columns: 12; 862 | $grid-margin-gutters: ( 863 | small: 20px, 864 | medium: 30px 865 | ); 866 | $grid-padding-gutters: $grid-margin-gutters; 867 | $grid-container-padding: $grid-padding-gutters; 868 | $grid-container-max: $global-width; 869 | $xy-block-grid-max: 8; 870 | 871 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from "vue"; 2 | import App from "./App.vue"; 3 | import router from "./router"; 4 | import store from "./store"; 5 | 6 | createApp(App) 7 | .use(store) 8 | .use(router) 9 | .mount("#app"); 10 | -------------------------------------------------------------------------------- /src/models/BaseModel.ts: -------------------------------------------------------------------------------- 1 | export class BaseModel { 2 | constructor() { 3 | this.createdAt = new Date(); 4 | this.updatedAt = new Date(); 5 | this.deletedAt = new Date(); 6 | } 7 | createdAt: Date; 8 | updatedAt: Date; 9 | deletedAt: Date; 10 | } 11 | 12 | export default BaseModel; 13 | -------------------------------------------------------------------------------- /src/models/Task.ts: -------------------------------------------------------------------------------- 1 | import { BaseModel } from "./BaseModel"; 2 | 3 | export class Task extends BaseModel { 4 | name: string; 5 | completed: boolean; 6 | 7 | constructor(name: string) { 8 | super(); 9 | this.name = name; 10 | this.completed = false; 11 | } 12 | } 13 | 14 | export default Task; 15 | -------------------------------------------------------------------------------- /src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"; 2 | import Home from "@/views/Home/Home.vue"; 3 | import AddTask from "@/views/AddTask/AddTask.vue"; 4 | 5 | const routes: Array = [ 6 | { 7 | path: "/", 8 | name: "Home", 9 | component: Home 10 | }, 11 | { 12 | path: "/add_task", 13 | name: "AddTask", 14 | component: AddTask 15 | } 16 | ]; 17 | 18 | const router = createRouter({ 19 | history: createWebHistory(process.env.BASE_URL), 20 | routes 21 | }); 22 | 23 | console.log("history", process.env.BASE_URL) 24 | 25 | export default router; 26 | -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | declare module '*.vue' { 3 | import type { DefineComponent } from 'vue' 4 | const component: DefineComponent<{}, {}, any> 5 | export default component 6 | } 7 | -------------------------------------------------------------------------------- /src/shims-vuex.d.ts: -------------------------------------------------------------------------------- 1 | import { Store } from "@/store"; // path to store file 2 | 3 | declare module "@vue/runtime-core" { 4 | interface ComponentCustomProperties { 5 | $store: Store; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createStore } from "vuex"; 2 | import Task from "../models/Task"; 3 | import { findIndex } from "lodash"; 4 | 5 | export default createStore({ 6 | state: { 7 | tasks: [ 8 | { 9 | name: "Demo for VueJS and TS", 10 | createdAt: new Date(), 11 | updatedAt: new Date(), 12 | completed: false 13 | }, 14 | { 15 | name: "UI design", 16 | createdAt: new Date(), 17 | updatedAt: new Date(), 18 | completed: false 19 | } 20 | ] as Task[] 21 | }, 22 | mutations: { 23 | setTask: (state, task) => state.tasks.push(task), 24 | deleteTask(state, task) { 25 | let taskIndex = findIndex(state.tasks, task); 26 | state.tasks.splice(taskIndex, ++taskIndex); 27 | }, 28 | completeTask(state, task) { 29 | const taskIndex = findIndex(state.tasks, task); 30 | state.tasks[taskIndex].completed = true; 31 | } 32 | }, 33 | actions: {}, 34 | modules: {} 35 | }); 36 | -------------------------------------------------------------------------------- /src/views/AddTask/AddTask.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Add Tasks

5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Add your next task- 14 | 16 |
17 |
18 |
19 |
20 | 23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /src/views/AddTask/AddTask.scss: -------------------------------------------------------------------------------- 1 | .create_task { 2 | margin-top: 2rem; 3 | h4 { 4 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 5 | margin: 2rem 0; 6 | } 7 | .card { 8 | background-color: #8080800d; 9 | } 10 | .card-section { 11 | padding: 1.5rem; 12 | legend { 13 | font-size: 20px; 14 | } 15 | input { 16 | border-radius: 5px; 17 | } 18 | button { 19 | border-radius: 5px; 20 | font-size: 18px; 21 | padding: 10px 20px; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/views/AddTask/AddTask.ts: -------------------------------------------------------------------------------- 1 | import { defineComponent } from "vue"; 2 | import Task from "../../models/Task"; 3 | 4 | export default defineComponent({ 5 | name: "AddTask", 6 | data() { 7 | return { 8 | taskName: "" 9 | }; 10 | }, 11 | methods: { 12 | addTask(): void { 13 | if (this.taskName !== "") { 14 | const newTask = new Task(this.taskName); 15 | this.$store.commit("setTask", newTask); 16 | this.taskName = ""; 17 | this.$router.push("/"); 18 | } 19 | } 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /src/views/AddTask/AddTask.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/views/Home/Home.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Vue 3 + TypeScript Todo Application

5 |
6 |
7 |
8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 27 | 28 | 29 | 30 |
To-do List
22 | 23 | 25 | 26 |
31 |
32 |
33 |
34 | -------------------------------------------------------------------------------- /src/views/Home/Home.scss: -------------------------------------------------------------------------------- 1 | .home { 2 | margin-top: 2rem; 3 | h4 { 4 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 5 | margin: 2rem 0; 6 | } 7 | tbody { 8 | background-color: #8080800d; 9 | } 10 | thead { 11 | background-color: #0000002e; 12 | } 13 | th { 14 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 15 | color: #0b0a0a; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/views/Home/Home.ts: -------------------------------------------------------------------------------- 1 | import { defineComponent } from "vue"; 2 | import Task from "../../models/Task"; 3 | 4 | export default defineComponent({ 5 | name: "Home", 6 | data() { 7 | return { 8 | tasks: [] as Task[] 9 | }; 10 | }, 11 | methods: { 12 | setTaskComplete(task: Task): void { 13 | this.$store.commit("completeTask", task); 14 | }, 15 | deleteTask(task: Task) { 16 | this.$store.commit("deleteTask", task); 17 | } 18 | }, 19 | mounted() { 20 | this.tasks = this.$store.state.tasks; 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /src/views/Home/Home.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "experimentalDecorators": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "sourceMap": true, 14 | "baseUrl": ".", 15 | "types": [ 16 | "webpack-env" 17 | ], 18 | "paths": { 19 | "@/*": [ 20 | "src/*" 21 | ] 22 | }, 23 | "lib": [ 24 | "esnext", 25 | "dom", 26 | "dom.iterable", 27 | "scripthost" 28 | ] 29 | }, 30 | "include": [ 31 | "src/**/*.ts", 32 | "src/**/*.tsx", 33 | "src/**/*.vue", 34 | "tests/**/*.ts", 35 | "tests/**/*.tsx" 36 | ], 37 | "exclude": [ 38 | "node_modules" 39 | ] 40 | } 41 | --------------------------------------------------------------------------------