├── .gitignore ├── README.md ├── babel.config.js ├── docs └── images │ └── screenshot.jpg ├── package-lock.json ├── package.json ├── prettier.config.js ├── public ├── favicon.ico └── index.html └── src ├── App.vue ├── assets ├── img │ └── bg.svg └── styles │ └── main.css ├── components ├── ComponentTypes.js ├── FormConfigProvider.vue ├── FormElements │ ├── FieldError.vue │ ├── FieldGroup.vue │ ├── FieldLabel.vue │ ├── Fields │ │ ├── CheckBox.vue │ │ ├── InputBox.vue │ │ ├── RadioButton.vue │ │ └── TextArea.vue │ ├── FormNav.vue │ ├── FormProgress.vue │ └── FormResult.vue ├── FormTemplate.vue └── Transitions │ ├── DataDrivenTransition.vue │ └── TypeBasedTransition.vue ├── config └── formConfig.json ├── directives └── index.js ├── main.js ├── mixins └── formMixin.js └── store ├── form └── lead.js └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This repository has been archived. 2 | 3 | ## Visit **[Advanced Vue 3 Form](https://github.com/Krutie/advanced-vue3-form)** repo for the latest implementation of the similar form. 4 | 5 | ----- 6 | 7 | ### An Interactive and Distraction-free Form with Vue 8 | 9 | This is a supporting GitHub repository for **[Building an Interactive and Distraction-free Form with Vue](https://medium.com/vue-mastery/building-an-interactive-and-distraction-free-form-with-vue-bfe23907e981)** article. 10 | 11 | Learn how to build an interactive and distraction-free form using advanced concepts of the Vue.js framework and other supporting libraries for form validation and animations. 12 | 13 | ### Take a look at the [Demo](http://distraction-free-vue-form.surge.sh/). 14 | 15 | ![Project Image](/docs/images/screenshot.jpg) 16 | 17 | ## Project setup 18 | 19 | ```bash 20 | npm install 21 | ``` 22 | 23 | ### Compiles and hot-reloads for development 24 | 25 | ``` 26 | npm run serve 27 | ``` 28 | 29 | ### Compiles and minifies for production 30 | 31 | ``` 32 | npm run build 33 | ``` 34 | 35 | ### Run your tests 36 | 37 | ``` 38 | npm run test 39 | ``` 40 | 41 | ### Lints and fixes files 42 | 43 | ``` 44 | npm run lint 45 | ``` 46 | 47 | ### Customize configuration 48 | 49 | See [Configuration Reference](https://cli.vuejs.org/config/). 50 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /docs/images/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krutie/distraction-free-vue-form/a6a25a0f9270958d5fb2fb588c9d79b6a61fc226/docs/images/screenshot.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "distraction-free-vue-form", 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 | "core-js": "^2.6.5", 12 | "gsap": "^2.1.3", 13 | "vee-validate": "^2.2.11", 14 | "vue": "^2.6.10", 15 | "vuex": "^3.1.1" 16 | }, 17 | "devDependencies": { 18 | "@vue/cli-plugin-babel": "^3.8.0", 19 | "@vue/cli-plugin-eslint": "^3.8.0", 20 | "@vue/cli-service": "^3.8.0", 21 | "babel-eslint": "^10.0.1", 22 | "eslint": "^5.16.0", 23 | "eslint-plugin-vue": "^5.0.0", 24 | "vue-template-compiler": "^2.6.10" 25 | }, 26 | "eslintConfig": { 27 | "root": true, 28 | "env": { 29 | "node": true 30 | }, 31 | "extends": [ 32 | "plugin:vue/essential", 33 | "eslint:recommended" 34 | ], 35 | "rules": {}, 36 | "parserOptions": { 37 | "parser": "babel-eslint" 38 | } 39 | }, 40 | "postcss": { 41 | "plugins": { 42 | "autoprefixer": {} 43 | } 44 | }, 45 | "browserslist": [ 46 | "> 1%", 47 | "last 2 versions" 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 120, 3 | tabWidth: 2, 4 | semi: false 5 | } 6 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Krutie/distraction-free-vue-form/a6a25a0f9270958d5fb2fb588c9d79b6a61fc226/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | advanced-vue-form 11 | 12 | 13 | 19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 18 | 22 | -------------------------------------------------------------------------------- /src/assets/img/bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/assets/styles/main.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css?family=Rubik:300,400,500,700&display=swap"); 2 | body { 3 | margin: 0; 4 | } 5 | #app { 6 | font-family: "Rubik", sans-serif; 7 | -webkit-font-smoothing: antialiased; 8 | -moz-osx-font-smoothing: grayscale; 9 | color: #2c3e50; 10 | background-image: url("../img/bg.svg"); 11 | background-position: bottom; 12 | background-size: cover; 13 | height: 100vh; 14 | background-repeat: no-repeat; 15 | } 16 | 17 | /* Logo Title - Advanced Vue.js Form */ 18 | .logo { 19 | position: fixed; 20 | left: 0; 21 | right: 0; 22 | } 23 | .logo h1 { 24 | font-weight: 500; 25 | font-size: 1.7em; 26 | text-align: center; 27 | user-select: none; 28 | } 29 | 30 | /* HTML Tags */ 31 | h1 { 32 | margin: 15px; 33 | font-weight: 300; 34 | } 35 | h2 { 36 | font-size: 2em; 37 | margin-bottom: 0.75em; 38 | } 39 | 40 | h2:not(:first-child) { 41 | margin-top: 0.75em; 42 | } 43 | input[type="checkbox"] { 44 | } 45 | 46 | *:focus { 47 | outline: none; 48 | } 49 | 50 | input[type="text"], 51 | textarea { 52 | border-color: transparent; 53 | border-bottom: 1px dashed #95c3c4 !important; 54 | height: 30px; 55 | width: 75%; 56 | font-size: 1.5em; 57 | border-radius: 3px; 58 | background-color: transparent; 59 | } 60 | textarea { 61 | height: 120px; 62 | width: 100%; 63 | } 64 | 65 | /* Form */ 66 | .field-group { 67 | position: absolute; 68 | top: Calc(25% - 100px); 69 | width: 100%; 70 | } 71 | .field-label { 72 | display: block; 73 | font-size: 1.7em; 74 | padding-bottom: 15px; 75 | } 76 | .field-area { 77 | padding: 3em; 78 | background-color: #d6f1ef; 79 | box-shadow: 1px 1px 1px 1px rgba(106, 145, 146, 0.4); 80 | border-radius: 10px; 81 | margin: 5% 10%; 82 | } 83 | .form-error-message { 84 | font-size: smaller; 85 | margin: 1em; 86 | font-size: 1.3em; 87 | font-weight: 300; 88 | color: #ef6574; 89 | text-align: center; 90 | font-weight: 400; 91 | } 92 | .form-complete { 93 | padding-top: 5%; 94 | font-size: 1.2em; 95 | } 96 | .form-complete h1 { 97 | text-align: center; 98 | font-size: 1.5em; 99 | } 100 | .form-complete p { 101 | padding-left: 100px; 102 | } 103 | 104 | /* Navigation and Progress Bar */ 105 | .nav { 106 | position: fixed; 107 | bottom: 0; 108 | left: 0; 109 | right: 0; 110 | background-color: inherit; 111 | padding: 5px; 112 | z-index: 10; 113 | display: flex; 114 | justify-content: center; 115 | transition: background-color 0.5s ease; 116 | } 117 | 118 | .form-button { 119 | border: 2px solid white; 120 | margin: 5px; 121 | border-radius: 5px; 122 | font-size: 1.2em; 123 | left: Calc(50% - 25px); 124 | box-shadow: 1px 1px 1px 1px rgba(106, 145, 146, 0.4); 125 | cursor: pointer; 126 | } 127 | 128 | .nav .form-button { 129 | font-weight: 500; 130 | padding: 10px; 131 | background-color: rgba(96, 125, 139, 0.25); 132 | } 133 | .form-error-message .form-button { 134 | font-weight: 700; 135 | padding: 10px; 136 | position: inherit; 137 | } 138 | 139 | .bar { 140 | height: 7px; 141 | width: 0px; 142 | background-color: #fefaa1; 143 | border-radius: 2px; 144 | position: fixed; 145 | bottom: 66px; 146 | } 147 | 148 | ::-webkit-scrollbar { 149 | width: 0px; 150 | } 151 | /* Generic media query for portrait mode */ 152 | @media only screen and (orientation: portrait) { 153 | input[type="text"] { 154 | font-size: 1.4em; 155 | } 156 | textarea { 157 | font-size: 1.2em; 158 | } 159 | .field-label { 160 | font-size: 1.5em; 161 | } 162 | .field-group { 163 | top: Calc(40% - 100px) !important; 164 | } 165 | .field-area { 166 | padding: 2em 1em !important; 167 | } 168 | .form-error-message .form-button { 169 | display: none; 170 | } 171 | .form-complete { 172 | padding-top: 35%; 173 | pading-bottom: 35%; 174 | } 175 | 176 | .form-complete p { 177 | padding-left: 30px !important; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/components/ComponentTypes.js: -------------------------------------------------------------------------------- 1 | import FormTemplate from "./FormTemplate.vue" 2 | import InputBox from "./FormElements/Fields/InputBox.vue" 3 | import TextArea from "./FormElements/Fields/TextArea.vue" 4 | import RadioButton from "./FormElements/Fields/RadioButton.vue" 5 | import CheckBox from "./FormElements/Fields/CheckBox.vue" 6 | 7 | const COMPONENT_MAP = { 8 | formTemplate: FormTemplate, 9 | text: InputBox, 10 | textarea: TextArea, 11 | radio: RadioButton, 12 | check: CheckBox 13 | } 14 | 15 | export function getComponent(type) { 16 | return COMPONENT_MAP[type] 17 | } 18 | -------------------------------------------------------------------------------- /src/components/FormConfigProvider.vue: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /src/components/FormElements/FieldError.vue: -------------------------------------------------------------------------------- 1 | 9 | 20 | -------------------------------------------------------------------------------- /src/components/FormElements/FieldGroup.vue: -------------------------------------------------------------------------------- 1 | 8 | 28 | -------------------------------------------------------------------------------- /src/components/FormElements/FieldLabel.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/components/FormElements/Fields/CheckBox.vue: -------------------------------------------------------------------------------- 1 | 16 | 47 | 52 | -------------------------------------------------------------------------------- /src/components/FormElements/Fields/InputBox.vue: -------------------------------------------------------------------------------- 1 | 4 | 9 | -------------------------------------------------------------------------------- /src/components/FormElements/Fields/RadioButton.vue: -------------------------------------------------------------------------------- 1 | 9 | 14 | -------------------------------------------------------------------------------- /src/components/FormElements/Fields/TextArea.vue: -------------------------------------------------------------------------------- 1 |