├── .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 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Home
11 |
12 |
13 |
14 |
15 |
16 | Add Tasks
17 |
18 |
19 |
20 |
21 |
22 |
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 |
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 | To-do List |
13 | |
14 | |
15 | |
16 |
17 |
18 |
19 |
20 | |
21 |
22 |
23 | |
24 |
25 |
26 | |
27 | |
28 |
29 |
30 |
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 |
--------------------------------------------------------------------------------