├── .editorconfig ├── .github ├── FUNDING.yml └── dependabot.yml ├── .gitignore ├── .npmrc ├── .prettierrc ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── eslint.config.mjs ├── nuxt-tour.png ├── package-lock.json ├── package.json ├── playground ├── .gitignore ├── .prettierrc ├── app.vue ├── assets │ └── css │ │ └── tailwind.css ├── components │ ├── Docs │ │ ├── Footer.vue │ │ ├── Navbar.vue │ │ ├── Navlink.vue │ │ └── Toc.vue │ ├── Ui │ │ ├── Avatar │ │ │ ├── Avatar.vue │ │ │ ├── Fallback.vue │ │ │ └── Image.vue │ │ ├── Button.vue │ │ ├── Container.vue │ │ ├── Divider.vue │ │ ├── Navbar.vue │ │ ├── ScrollArea │ │ │ ├── Corner.vue │ │ │ ├── ScrollArea.vue │ │ │ ├── Scrollbar.vue │ │ │ ├── Thumb.vue │ │ │ └── Viewport.vue │ │ ├── Sheet │ │ │ ├── Close.vue │ │ │ ├── Content.vue │ │ │ ├── Description.vue │ │ │ ├── Footer.vue │ │ │ ├── Header.vue │ │ │ ├── Overlay.vue │ │ │ ├── Portal.vue │ │ │ ├── Sheet.vue │ │ │ ├── Title.vue │ │ │ ├── Trigger.vue │ │ │ └── X.vue │ │ └── VueSonner.client.vue │ └── content │ │ ├── Showcase.vue │ │ ├── docs │ │ └── CreateTourExample.vue │ │ ├── examples │ │ ├── ExAutoStart.vue │ │ ├── ExCallbackEmits.vue │ │ ├── ExCustomButton.vue │ │ ├── ExHighlight.vue │ │ └── ExHtmlElement.vue │ │ └── prose │ │ ├── ProsePre.vue │ │ └── ProseTable.vue ├── content │ ├── 0.index.md │ ├── 1.getting-started.md │ ├── 3.create-tour.md │ ├── 4.props.md │ ├── 5.methods.md │ ├── 6.slots.md │ ├── 7.emits.md │ ├── 8.styles.md │ └── 9.examples │ │ ├── autostart.md │ │ ├── button.md │ │ ├── callbacks-emits.md │ │ ├── highlight.md │ │ └── html-elements.md ├── layouts │ └── default.vue ├── nuxt.config.ts ├── package-lock.json ├── package.json ├── public │ └── nuxt-tour.png ├── server │ └── tsconfig.json ├── tailwind.config.js ├── tsconfig.json ├── ui-thing.config.ts └── utils │ └── shared.styles.ts ├── src ├── module.ts └── runtime │ ├── components │ └── Tour.vue │ ├── props.ts │ └── scss │ ├── _variables.scss │ └── tour.scss ├── test ├── basic.test.ts └── fixtures │ └── basic │ ├── app.vue │ ├── nuxt.config.ts │ └── package.json └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_size = 2 5 | indent_style = space 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: llehXIrI8g 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Please see the documentation for all configuration options: 2 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 3 | 4 | version: 2 5 | updates: 6 | - package-ecosystem: "npm" 7 | directories: 8 | - "/" 9 | - "/playground" 10 | schedule: 11 | interval: "weekly" 12 | day: "sunday" 13 | time: "06:00" 14 | timezone: "America/Jamaica" 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules 3 | 4 | # Logs 5 | *.log* 6 | 7 | # Temp directories 8 | .temp 9 | .tmp 10 | .cache 11 | 12 | # Yarn 13 | **/.yarn/cache 14 | **/.yarn/*state* 15 | 16 | # Generated dirs 17 | dist 18 | 19 | # Nuxt 20 | .nuxt 21 | .output 22 | .data 23 | .vercel_build_output 24 | .build-* 25 | .netlify 26 | 27 | # Env 28 | .env 29 | 30 | # Testing 31 | reports 32 | coverage 33 | *.lcov 34 | .nyc_output 35 | 36 | # VSCode 37 | .vscode/* 38 | !.vscode/settings.json 39 | !.vscode/tasks.json 40 | !.vscode/launch.json 41 | !.vscode/extensions.json 42 | !.vscode/*.code-snippets 43 | 44 | # Intellij idea 45 | *.iml 46 | .idea 47 | 48 | # OSX 49 | .DS_Store 50 | .AppleDouble 51 | .LSOverride 52 | .AppleDB 53 | .AppleDesktop 54 | Network Trash Folder 55 | Temporary Items 56 | .apdisk 57 | 58 | # Logs 59 | logs 60 | *.log 61 | npm-debug.log* 62 | yarn-debug.log* 63 | yarn-error.log* 64 | lerna-debug.log* 65 | .pnpm-debug.log* 66 | 67 | # Diagnostic reports (https://nodejs.org/api/report.html) 68 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 69 | 70 | # Runtime data 71 | pids 72 | *.pid 73 | *.seed 74 | *.pid.lock 75 | 76 | # Directory for instrumented libs generated by jscoverage/JSCover 77 | lib-cov 78 | 79 | # Coverage directory used by tools like istanbul 80 | coverage 81 | *.lcov 82 | 83 | # nyc test coverage 84 | .nyc_output 85 | 86 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 87 | .grunt 88 | 89 | # Bower dependency directory (https://bower.io/) 90 | bower_components 91 | 92 | # node-waf configuration 93 | .lock-wscript 94 | 95 | # Compiled binary addons (https://nodejs.org/api/addons.html) 96 | build/Release 97 | 98 | # Dependency directories 99 | node_modules/ 100 | jspm_packages/ 101 | 102 | # Snowpack dependency directory (https://snowpack.dev/) 103 | web_modules/ 104 | 105 | # TypeScript cache 106 | *.tsbuildinfo 107 | 108 | # Optional npm cache directory 109 | .npm 110 | 111 | # Optional eslint cache 112 | .eslintcache 113 | 114 | # Optional stylelint cache 115 | .stylelintcache 116 | 117 | # Microbundle cache 118 | .rpt2_cache/ 119 | .rts2_cache_cjs/ 120 | .rts2_cache_es/ 121 | .rts2_cache_umd/ 122 | 123 | # Optional REPL history 124 | .node_repl_history 125 | 126 | # Output of 'npm pack' 127 | *.tgz 128 | 129 | # Yarn Integrity file 130 | .yarn-integrity 131 | 132 | # dotenv environment variable files 133 | .env 134 | .env.development.local 135 | .env.test.local 136 | .env.production.local 137 | .env.local 138 | 139 | # parcel-bundler cache (https://parceljs.org/) 140 | .cache 141 | .parcel-cache 142 | 143 | # Next.js build output 144 | .next 145 | out 146 | 147 | # Nuxt.js build / generate output 148 | .nuxt 149 | dist 150 | 151 | # Gatsby files 152 | .cache/ 153 | # Comment in the public line in if your project uses Gatsby and not Next.js 154 | # https://nextjs.org/blog/next-9-1#public-directory-support 155 | # public 156 | 157 | # vuepress build output 158 | .vuepress/dist 159 | 160 | # vuepress v2.x temp and cache directory 161 | .temp 162 | .cache 163 | 164 | # Docusaurus cache and generated files 165 | .docusaurus 166 | 167 | # Serverless directories 168 | .serverless/ 169 | 170 | # FuseBox cache 171 | .fusebox/ 172 | 173 | # DynamoDB Local files 174 | .dynamodb/ 175 | 176 | # TernJS port file 177 | .tern-port 178 | 179 | # Stores VSCode versions used for testing VSCode extensions 180 | .vscode-test 181 | 182 | # yarn v2 183 | .yarn/cache 184 | .yarn/unplugged 185 | .yarn/build-state.yml 186 | .yarn/install-state.gz 187 | .pnp.* 188 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "endOfLine": "lf", 4 | "printWidth": 100, 5 | "semi": true, 6 | "singleQuote": false, 7 | "tabWidth": 2, 8 | "trailingComma": "es5", 9 | "useTabs": false, 10 | "vueIndentScriptAndStyle": true, 11 | "plugins": ["@ianvs/prettier-plugin-sort-imports"], 12 | "importOrder": ["", "", "", "^[.]"] 13 | } 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v0.0.40 4 | 5 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.39...v0.0.40) 6 | 7 | ### 🏡 Chore 8 | 9 | - Bump deps ([fc3c70d](https://github.com/BayBreezy/nuxt-tour/commit/fc3c70d)) 10 | 11 | ### ❤️ Contributors 12 | 13 | - Behon Baker ([@BayBreezy](https://github.com/BayBreezy)) 14 | 15 | ## v0.0.39 16 | 17 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.38...v0.0.39) 18 | 19 | ### 🏡 Chore 20 | 21 | - Bump deps ([05318cd](https://github.com/BayBreezy/nuxt-tour/commit/05318cd)) 22 | - Optimize deps during development ([2ce4621](https://github.com/BayBreezy/nuxt-tour/commit/2ce4621)) 23 | - Remove small offset from clip path values ([1dd6fa2](https://github.com/BayBreezy/nuxt-tour/commit/1dd6fa2)) 24 | - Update logic used to determine dev mode ([758de92](https://github.com/BayBreezy/nuxt-tour/commit/758de92)) 25 | 26 | ### ❤️ Contributors 27 | 28 | - Behon Baker ([@BayBreezy](https://github.com/BayBreezy)) 29 | 30 | ## v0.0.38 31 | 32 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.37...v0.0.38) 33 | 34 | ### 📖 Documentation 35 | 36 | - Update markup for html example ([9fe6fdf](https://github.com/BayBreezy/nuxt-tour/commit/9fe6fdf)) 37 | 38 | ### 🏡 Chore 39 | 40 | - Update test ([dcc7110](https://github.com/BayBreezy/nuxt-tour/commit/dcc7110)) 41 | - Bump deps ([3aad744](https://github.com/BayBreezy/nuxt-tour/commit/3aad744)) 42 | 43 | ### 🎨 Styles 44 | 45 | - Lint and format ([fdfc89d](https://github.com/BayBreezy/nuxt-tour/commit/fdfc89d)) 46 | 47 | ### ❤️ Contributors 48 | 49 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 50 | 51 | ## v0.0.37 52 | 53 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.36...v0.0.37) 54 | 55 | ### 🚀 Enhancements 56 | 57 | - Add `backdrop` & transition styles to css ([1a56f3b](https://github.com/BayBreezy/nuxt-tour/commit/1a56f3b)) 58 | - Add `backdrop` prop to tour & tour steps. Also extracted the tour emit types ([85f0d13](https://github.com/BayBreezy/nuxt-tour/commit/85f0d13)) 59 | - Add `backdrop` functionality along with transition & update default values ([4c0c81e](https://github.com/BayBreezy/nuxt-tour/commit/4c0c81e)) 60 | 61 | ### 📖 Documentation 62 | 63 | - Fix twoslash error in docs ([1ede335](https://github.com/BayBreezy/nuxt-tour/commit/1ede335)) 64 | - Update examples ([0fe5e42](https://github.com/BayBreezy/nuxt-tour/commit/0fe5e42)) 65 | - Update the code snippets ([838029b](https://github.com/BayBreezy/nuxt-tour/commit/838029b)) 66 | 67 | ### ❤️ Contributors 68 | 69 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 70 | 71 | ## v0.0.36 72 | 73 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.35...v0.0.36) 74 | 75 | ### 🏡 Chore 76 | 77 | - **release:** V0.0.35 ([5193f44](https://github.com/BayBreezy/nuxt-tour/commit/5193f44)) 78 | - Bump deps ([2e9481b](https://github.com/BayBreezy/nuxt-tour/commit/2e9481b)) 79 | 80 | ### ❤️ Contributors 81 | 82 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 83 | 84 | ## v0.0.35 85 | 86 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.34...v0.0.35) 87 | 88 | ### 🏡 Chore 89 | 90 | - Bump deps ([091828e](https://github.com/BayBreezy/nuxt-tour/commit/091828e)) 91 | 92 | ### ❤️ Contributors 93 | 94 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 95 | 96 | ## v0.0.34 97 | 98 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.33...v0.0.34) 99 | 100 | ### 🩹 Fixes 101 | 102 | - Change how lodash merge is imported(for pnpm's sake) ([74adfd8](https://github.com/BayBreezy/nuxt-tour/commit/74adfd8)) 103 | 104 | ### 🏡 Chore 105 | 106 | - Bump deps ([4edd4b4](https://github.com/BayBreezy/nuxt-tour/commit/4edd4b4)) 107 | - Swap out lodash for lodash-es ([431b4ca](https://github.com/BayBreezy/nuxt-tour/commit/431b4ca)) 108 | 109 | ### ❤️ Contributors 110 | 111 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 112 | 113 | ## v0.0.33 114 | 115 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.32...v0.0.33) 116 | 117 | ### 🏡 Chore 118 | 119 | - **release:** V0.0.32 ([19fc9fd](https://github.com/BayBreezy/nuxt-tour/commit/19fc9fd)) 120 | - Move `@types/lodash` to being a dependency ([af7312e](https://github.com/BayBreezy/nuxt-tour/commit/af7312e)) 121 | 122 | ### ❤️ Contributors 123 | 124 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 125 | 126 | ## v0.0.32 127 | 128 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.31...v0.0.32) 129 | 130 | ### 🏡 Chore 131 | 132 | - Bump deps ([190eee6](https://github.com/BayBreezy/nuxt-tour/commit/190eee6)) 133 | 134 | ### ❤️ Contributors 135 | 136 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 137 | 138 | ## v0.0.31 139 | 140 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.30...v0.0.31) 141 | 142 | ### 🏡 Chore 143 | 144 | - **release:** V0.0.30 ([294e642](https://github.com/BayBreezy/nuxt-tour/commit/294e642)) 145 | - Bump deps ([6816556](https://github.com/BayBreezy/nuxt-tour/commit/6816556)) 146 | 147 | ### ❤️ Contributors 148 | 149 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 150 | 151 | ## v0.0.30 152 | 153 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.29...v0.0.30) 154 | 155 | ### 🏡 Chore 156 | 157 | - Bump deps ([86611fd](https://github.com/BayBreezy/nuxt-tour/commit/86611fd)) 158 | 159 | ### ❤️ Contributors 160 | 161 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 162 | 163 | ## v0.0.29 164 | 165 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.28...v0.0.29) 166 | 167 | ### 🩹 Fixes 168 | 169 | - Replace defu with lodash `merge`. Allows user config to get merged with defaults properly. closes Custom popperConfig properties are being overriden by defaults. #120 ([#120](https://github.com/BayBreezy/nuxt-tour/issues/120)) 170 | 171 | ### 🏡 Chore 172 | 173 | - Bump deps ([46959e8](https://github.com/BayBreezy/nuxt-tour/commit/46959e8)) 174 | 175 | ### ❤️ Contributors 176 | 177 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 178 | 179 | ## v0.0.28 180 | 181 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.27...v0.0.28) 182 | 183 | ### 📖 Documentation 184 | 185 | - Update u-thing config ([9cbe4c1](https://github.com/BayBreezy/nuxt-tour/commit/9cbe4c1)) 186 | 187 | ### 🏡 Chore 188 | 189 | - Bump deps ([2a42f43](https://github.com/BayBreezy/nuxt-tour/commit/2a42f43)) 190 | 191 | ### 🤖 CI 192 | 193 | - Update dependabot config ([784f38b](https://github.com/BayBreezy/nuxt-tour/commit/784f38b)) 194 | 195 | ### ❤️ Contributors 196 | 197 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 198 | 199 | ## v0.0.27 200 | 201 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.26...v0.0.27) 202 | 203 | ### 🏡 Chore 204 | 205 | - **release:** V0.0.26 ([c7b85d1](https://github.com/BayBreezy/nuxt-tour/commit/c7b85d1)) 206 | - Update deps ([8feab55](https://github.com/BayBreezy/nuxt-tour/commit/8feab55)) 207 | 208 | ### ❤️ Contributors 209 | 210 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 211 | 212 | ## v0.0.26 213 | 214 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.25...v0.0.26) 215 | 216 | ### 🏡 Chore 217 | 218 | - Bump deps ([5c25367](https://github.com/BayBreezy/nuxt-tour/commit/5c25367)) 219 | - **deps-dev:** Bump @nuxt/icon from 1.5.8 to 1.6.0 in /playground ([90ee092](https://github.com/BayBreezy/nuxt-tour/commit/90ee092)) 220 | - **deps-dev:** Bump vitest from 2.1.3 to 2.1.4 ([174abca](https://github.com/BayBreezy/nuxt-tour/commit/174abca)) 221 | - **deps-dev:** Bump @nuxt/eslint-config from 0.6.0 to 0.6.1 ([7e64eac](https://github.com/BayBreezy/nuxt-tour/commit/7e64eac)) 222 | - Bump deps ([b19b8e6](https://github.com/BayBreezy/nuxt-tour/commit/b19b8e6)) 223 | 224 | ### ❤️ Contributors 225 | 226 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 227 | 228 | ## v0.0.25 229 | 230 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.24...v0.0.25) 231 | 232 | ### 🩹 Fixes 233 | 234 | - **sass:** Update sass to 1.8 and fix breaking changes ([543c5a7](https://github.com/BayBreezy/nuxt-tour/commit/543c5a7)) 235 | 236 | ### 🏡 Chore 237 | 238 | - **release:** V0.0.24 ([957868f](https://github.com/BayBreezy/nuxt-tour/commit/957868f)) 239 | - Bump deps ([b919521](https://github.com/BayBreezy/nuxt-tour/commit/b919521)) 240 | 241 | ### ❤️ Contributors 242 | 243 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 244 | 245 | ## v0.0.24 246 | 247 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.23...v0.0.24) 248 | 249 | ### 🏡 Chore 250 | 251 | - **release:** V0.0.23 ([407386e](https://github.com/BayBreezy/nuxt-tour/commit/407386e)) 252 | - Bump deps ([7d51358](https://github.com/BayBreezy/nuxt-tour/commit/7d51358)) 253 | - Bump deps ([7b9f877](https://github.com/BayBreezy/nuxt-tour/commit/7b9f877)) 254 | 255 | ### ❤️ Contributors 256 | 257 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 258 | 259 | ## v0.0.23 260 | 261 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.22...v0.0.23) 262 | 263 | ### 🏡 Chore 264 | 265 | - Bump deps ([d66256c](https://github.com/BayBreezy/nuxt-tour/commit/d66256c)) 266 | 267 | ### ❤️ Contributors 268 | 269 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 270 | 271 | ## v0.0.22 272 | 273 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.21...v0.0.22) 274 | 275 | ### 🏡 Chore 276 | 277 | - Bump deps ([b11eab8](https://github.com/BayBreezy/nuxt-tour/commit/b11eab8)) 278 | 279 | ### ❤️ Contributors 280 | 281 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 282 | 283 | ## v0.0.21 284 | 285 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.20...v0.0.21) 286 | 287 | ### 🏡 Chore 288 | 289 | - **release:** V0.0.20 ([91725e0](https://github.com/BayBreezy/nuxt-tour/commit/91725e0)) 290 | - Bump deps ([29d8176](https://github.com/BayBreezy/nuxt-tour/commit/29d8176)) 291 | 292 | ### ❤️ Contributors 293 | 294 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 295 | 296 | ## v0.0.20 297 | 298 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.19...v0.0.20) 299 | 300 | ### 🏡 Chore 301 | 302 | - Bump deps ([a65b2a2](https://github.com/BayBreezy/nuxt-tour/commit/a65b2a2)) 303 | - Add license to root of product ([261b678](https://github.com/BayBreezy/nuxt-tour/commit/261b678)) 304 | 305 | ### ❤️ Contributors 306 | 307 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 308 | 309 | ## v0.0.19 310 | 311 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.18...v0.0.19) 312 | 313 | ### 🏡 Chore 314 | 315 | - Bump deps ([852191d](https://github.com/BayBreezy/nuxt-tour/commit/852191d)) 316 | - Bump deps ([e65322a](https://github.com/BayBreezy/nuxt-tour/commit/e65322a)) 317 | 318 | ### ❤️ Contributors 319 | 320 | - Behon Baker 321 | 322 | ## v0.0.18 323 | 324 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.17...v0.0.18) 325 | 326 | ### 🏡 Chore 327 | 328 | - Bump deps ([43dba2f](https://github.com/BayBreezy/nuxt-tour/commit/43dba2f)) 329 | - Bump deps ([a9b0fa1](https://github.com/BayBreezy/nuxt-tour/commit/a9b0fa1)) 330 | 331 | ### 🎨 Styles 332 | 333 | - Lint tour component ([39d2e1c](https://github.com/BayBreezy/nuxt-tour/commit/39d2e1c)) 334 | 335 | ### ❤️ Contributors 336 | 337 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 338 | 339 | ## v0.0.17 340 | 341 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.16...v0.0.17) 342 | 343 | ### 🩹 Fixes 344 | 345 | - Bump deps and make icon module a dependency instead of a devDep. Closes Cannot find module '@nuxt/icon' #44 ([#44](https://github.com/BayBreezy/nuxt-tour/issues/44)) 346 | 347 | ### ❤️ Contributors 348 | 349 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 350 | 351 | ## v0.0.16 352 | 353 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.15...v0.0.16) 354 | 355 | ### 🏡 Chore 356 | 357 | - Bump deps ([0ae6cf2](https://github.com/BayBreezy/nuxt-tour/commit/0ae6cf2)) 358 | 359 | ### ❤️ Contributors 360 | 361 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 362 | 363 | ## v0.0.15 364 | 365 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.14...v0.0.15) 366 | 367 | ### 🏡 Chore 368 | 369 | - Bump deps ([ea4916a](https://github.com/BayBreezy/nuxt-tour/commit/ea4916a)) 370 | 371 | ### ❤️ Contributors 372 | 373 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 374 | 375 | ## v0.0.14 376 | 377 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.13...v0.0.14) 378 | 379 | ### 📖 Documentation 380 | 381 | - **readme:** Remove iconPrefix from readme ([9083a8c](https://github.com/BayBreezy/nuxt-tour/commit/9083a8c)) 382 | - **config:** Change icon package, update tw config & transpile deps ([416a712](https://github.com/BayBreezy/nuxt-tour/commit/416a712)) 383 | - **component:** Update sonner component ([e1aa316](https://github.com/BayBreezy/nuxt-tour/commit/e1aa316)) 384 | - Remove iconPrefix from getting started page ([06d12a0](https://github.com/BayBreezy/nuxt-tour/commit/06d12a0)) 385 | 386 | ### 🏡 Chore 387 | 388 | - **module:** Removed the `iconPrefix` option & change the icon module that is used ([8c8f932](https://github.com/BayBreezy/nuxt-tour/commit/8c8f932)) 389 | - Bump deps ([7a29d86](https://github.com/BayBreezy/nuxt-tour/commit/7a29d86)) 390 | 391 | ### ❤️ Contributors 392 | 393 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 394 | 395 | ## v0.0.13 396 | 397 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.12...v0.0.13) 398 | 399 | ### 🏡 Chore 400 | 401 | - Update deps ([68db5a8](https://github.com/BayBreezy/nuxt-tour/commit/68db5a8)) 402 | 403 | ### ❤️ Contributors 404 | 405 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 406 | 407 | ## v0.0.12 408 | 409 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.11...v0.0.12) 410 | 411 | ### 🏡 Chore 412 | 413 | - Bump deps ([b1f2960](https://github.com/BayBreezy/nuxt-tour/commit/b1f2960)) 414 | 415 | ### ❤️ Contributors 416 | 417 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 418 | 419 | ## v0.0.11 420 | 421 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.10...v0.0.11) 422 | 423 | ## v0.0.10 424 | 425 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.9...v0.0.10) 426 | 427 | ### 📖 Documentation 428 | 429 | - **github link:** Added a link to the github repo in the navigation docs ([cc2f465](https://github.com/BayBreezy/nuxt-tour/commit/cc2f465)) 430 | 431 | ### 🏡 Chore 432 | 433 | - **release:** V0.0.9 ([2ea13ec](https://github.com/BayBreezy/nuxt-tour/commit/2ea13ec)) 434 | - Clean install of packages for docs ([614d7b7](https://github.com/BayBreezy/nuxt-tour/commit/614d7b7)) 435 | 436 | ### ❤️ Contributors 437 | 438 | - Behon Baker ([@BayBreezy](http://github.com/BayBreezy)) 439 | - BayBreezy 440 | 441 | ## v0.0.9 442 | 443 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.8...v0.0.9) 444 | 445 | ### 🏡 Chore 446 | 447 | - Bump deps ([5d07ab7](https://github.com/BayBreezy/nuxt-tour/commit/5d07ab7)) 448 | 449 | ### ❤️ Contributors 450 | 451 | - BayBreezy 452 | 453 | ## v0.0.8 454 | 455 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.7...v0.0.8) 456 | 457 | ### 🏡 Chore 458 | 459 | - Update deps ([11101ce](https://github.com/BayBreezy/nuxt-tour/commit/11101ce)) 460 | - Update docs deps ([ce5cf49](https://github.com/BayBreezy/nuxt-tour/commit/ce5cf49)) 461 | 462 | ### 🎨 Styles 463 | 464 | - **lint:** Use `@ts-expect-error` instead of `@ts-ignore` ([994ffbf](https://github.com/BayBreezy/nuxt-tour/commit/994ffbf)) 465 | 466 | ### ❤️ Contributors 467 | 468 | - Behon Baker 469 | 470 | ## v0.0.7 471 | 472 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.6...v0.0.7) 473 | 474 | ### 🏡 Chore 475 | 476 | - **dev deps:** Bump dev dep ([fba0d0c](https://github.com/BayBreezy/nuxt-tour/commit/fba0d0c)) 477 | - Update deps ([c99cac9](https://github.com/BayBreezy/nuxt-tour/commit/c99cac9)) 478 | - Update eslint config ([3bf676a](https://github.com/BayBreezy/nuxt-tour/commit/3bf676a)) 479 | 480 | ### ❤️ Contributors 481 | 482 | - Behon Baker 483 | 484 | ## v0.0.6 485 | 486 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.5...v0.0.6) 487 | 488 | ### 📖 Documentation 489 | 490 | - Install latest module version ([6b66464](https://github.com/BayBreezy/nuxt-tour/commit/6b66464)) 491 | - Update deps ([7de30bc](https://github.com/BayBreezy/nuxt-tour/commit/7de30bc)) 492 | 493 | ### 🏡 Chore 494 | 495 | - Update deps ([0e00c03](https://github.com/BayBreezy/nuxt-tour/commit/0e00c03)) 496 | - Bump deps ([635ae90](https://github.com/BayBreezy/nuxt-tour/commit/635ae90)) 497 | - Bump deps ([edf4ce6](https://github.com/BayBreezy/nuxt-tour/commit/edf4ce6)) 498 | 499 | ### ❤️ Contributors 500 | 501 | - Behon Baker 502 | - BayBreezy 503 | 504 | ## v0.0.5 505 | 506 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.4...v0.0.5) 507 | 508 | ### 🏡 Chore 509 | 510 | - **tour:** Perform jump before updating the popper instance ([b654165](https://github.com/BayBreezy/nuxt-tour/commit/b654165)) 511 | 512 | ### ❤️ Contributors 513 | 514 | - BayBreezy 515 | 516 | ## v0.0.4 517 | 518 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.3...v0.0.4) 519 | 520 | ### 📖 Documentation 521 | 522 | - Installed newer version of the module ([142c911](https://github.com/BayBreezy/nuxt-tour/commit/142c911)) 523 | - Update deps ([9f9fc23](https://github.com/BayBreezy/nuxt-tour/commit/9f9fc23)) 524 | 525 | ### 🏡 Chore 526 | 527 | - Bumps deps ([8ddc34a](https://github.com/BayBreezy/nuxt-tour/commit/8ddc34a)) 528 | 529 | ### ❤️ Contributors 530 | 531 | - BayBreezy 532 | - Behon Baker 533 | 534 | ## v0.0.3 535 | 536 | [compare changes](https://github.com/BayBreezy/nuxt-tour/compare/v0.0.2...v0.0.3) 537 | 538 | ### 🚀 Enhancements 539 | 540 | - Add autostart example ([dd8456f](https://github.com/BayBreezy/nuxt-tour/commit/dd8456f)) 541 | 542 | ### 📖 Documentation 543 | 544 | - **cover:** Update docs and readme ([052743e](https://github.com/BayBreezy/nuxt-tour/commit/052743e)) 545 | - Add icon option to module interface ([3e855dd](https://github.com/BayBreezy/nuxt-tour/commit/3e855dd)) 546 | - Add the code example ([c9f2e68](https://github.com/BayBreezy/nuxt-tour/commit/c9f2e68)) 547 | - Add highlight example ([2d89f7f](https://github.com/BayBreezy/nuxt-tour/commit/2d89f7f)) 548 | 549 | ### 🏡 Chore 550 | 551 | - Update test and fix package ([94a0b55](https://github.com/BayBreezy/nuxt-tour/commit/94a0b55)) 552 | - Update docs with css ([25c9c04](https://github.com/BayBreezy/nuxt-tour/commit/25c9c04)) 553 | - Add jump types for twoslash in production ([261c4f1](https://github.com/BayBreezy/nuxt-tour/commit/261c4f1)) 554 | - Update responsiveness in default layout and navbar ([a3be6c7](https://github.com/BayBreezy/nuxt-tour/commit/a3be6c7)) 555 | - Install vue & vue-router ([2e804d8](https://github.com/BayBreezy/nuxt-tour/commit/2e804d8)) 556 | - Show nested navigation links ([08d0c19](https://github.com/BayBreezy/nuxt-tour/commit/08d0c19)) 557 | - Render title, body and subtext in v-html attribute ([5afa227](https://github.com/BayBreezy/nuxt-tour/commit/5afa227)) 558 | - Add callback example ([2d16ef4](https://github.com/BayBreezy/nuxt-tour/commit/2d16ef4)) 559 | - Add nuxt-icon-tw module for displaying icons ([dd1ba67](https://github.com/BayBreezy/nuxt-tour/commit/dd1ba67)) 560 | - Install nuxt-icon-tw ([a39f620](https://github.com/BayBreezy/nuxt-tour/commit/a39f620)) 561 | - Remove classes from from button props ([3bc8f45](https://github.com/BayBreezy/nuxt-tour/commit/3bc8f45)) 562 | - Update the gap between the button and icon ([84b772f](https://github.com/BayBreezy/nuxt-tour/commit/84b772f)) 563 | - Change the icon props name ([08fc5d9](https://github.com/BayBreezy/nuxt-tour/commit/08fc5d9)) 564 | - Give finish button its own slot and display icons ([d539c88](https://github.com/BayBreezy/nuxt-tour/commit/d539c88)) 565 | - Display button icons in Tour component. Add default icon styles ([b59d3de](https://github.com/BayBreezy/nuxt-tour/commit/b59d3de)) 566 | - Add white-space set to nowrap for buttons in scss file ([175a114](https://github.com/BayBreezy/nuxt-tour/commit/175a114)) 567 | - Add custom button example ([fc6390a](https://github.com/BayBreezy/nuxt-tour/commit/fc6390a)) 568 | - Comment out local module path ([6b85c9d](https://github.com/BayBreezy/nuxt-tour/commit/6b85c9d)) 569 | 570 | ### 🎨 Styles 571 | 572 | - **lint:** Run lint fix ([a8272cc](https://github.com/BayBreezy/nuxt-tour/commit/a8272cc)) 573 | 574 | ### ❤️ Contributors 575 | 576 | - Behon Baker 577 | - BayBreezy 578 | 579 | ## v0.0.2 580 | 581 | ### 📖 Documentation 582 | 583 | - **readme:** Update readme ([f19f966](https://github.com/your-org/nuxt-tour/commit/f19f966)) 584 | - Start docs ([f218485](https://github.com/your-org/nuxt-tour/commit/f218485)) 585 | 586 | ### 🏡 Chore 587 | 588 | - **module:** Add check for prefix before registering component ([e58535e](https://github.com/your-org/nuxt-tour/commit/e58535e)) 589 | - Update package description ([da90649](https://github.com/your-org/nuxt-tour/commit/da90649)) 590 | - Update docs ([de5180f](https://github.com/your-org/nuxt-tour/commit/de5180f)) 591 | 592 | ### 🎨 Styles 593 | 594 | - **lint:** Run lint fix ([61558b8](https://github.com/your-org/nuxt-tour/commit/61558b8)) 595 | 596 | ### ❤️ Contributors 597 | 598 | - BayBreezy 599 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Behon Baker. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 9 | 10 | # Nuxt Tour 11 | 12 | [![npm version][npm-version-src]][npm-version-href] 13 | [![npm downloads][npm-downloads-src]][npm-downloads-href] 14 | [![License][license-src]][license-href] 15 | [![Nuxt][nuxt-src]][nuxt-href] 16 | 17 | Docs Cover 18 | 19 |
20 | 21 | Empower your users with interactive guided tours of your Nuxt 3 applications using the `nuxt-tour` module. 22 | 23 | With this module, developers can seamlessly integrate step-by-step tooltips into their applications, providing clear instructions and highlighting key features. 24 | 25 | Special thanks to [Vue Tour](https://github.com/GlobalHive/vuejs-tour/tree/master) for doing the heavy lifting. I basically just ported it to Nuxt 3(with a few changes here and there). 26 | 27 | Thank you https://github.com/GlobalHive 28 | 29 | - [📖  Documentation](https://nuxt-tour.behonbaker.com/) 30 | - [✨  Release Notes](/CHANGELOG.md) 31 | 32 | 33 | ## Features 34 | 35 | 36 | 37 | - **Easy Integration**: Quickly add guided tours to your Nuxt 3 projects with minimal setup. 38 | - **Customizable**: Tailor the appearance of steps to match your application's design and user experience. 39 | - **Step-by-Step Navigation**: Guide users through workflows and features with sequential tooltips and intuitive navigation controls. 40 | - **Rich Content Support**: Enhance tooltips with text, images, videos, and interactive elements through the provided slots. 41 | - **Responsive Design**: Ensure a consistent experience across devices with responsive tooltips that adapt to different screen sizes. 42 | 43 | ## Quick Setup 44 | 45 | Install the module to your Nuxt application with one command: 46 | 47 | ```bash 48 | npm install nuxt-tour 49 | ``` 50 | 51 | Then, add the module to your `nuxt.config` file: 52 | 53 | ```ts 54 | export default defineNuxtConfig({ 55 | modules: ["nuxt-tour"], 56 | }); 57 | ``` 58 | 59 | You can then pass a `prefix` to the module via the `tour` key in your `nuxt.config` file. You can also pass the `injectSass` key to inject the default styles into your application: 60 | 61 | ```ts 62 | export default defineNuxtConfig({ 63 | modules: ["nuxt-tour"], 64 | tour: { 65 | prefix: "tour", 66 | }, 67 | }); 68 | ``` 69 | 70 | ## Configure the module 71 | 72 | You can configure the module by passing the following options to the `tour` key in your `nuxt.config` file: 73 | 74 | ```ts 75 | export interface TourOptions { 76 | /** 77 | * The prefix to use for the component name 78 | * 79 | * @default "V" 80 | */ 81 | prefix?: string; 82 | /** 83 | * Inject the default sass file 84 | * 85 | * Feel free to create your own 🙂. Just get the class names correct 86 | * 87 | * @default true 88 | */ 89 | injectSass?: boolean; 90 | } 91 | ``` 92 | 93 | That's it! You can now use Nuxt Tour in your Nuxt app ✨ 94 | 95 | ## Contribution 96 | 97 |
98 | Local development 99 | 100 | ```bash 101 | # Install dependencies 102 | npm install 103 | 104 | # Generate type stubs 105 | npm run dev:prepare 106 | 107 | # Develop with the playground 108 | npm run dev 109 | 110 | # Build the playground 111 | npm run dev:build 112 | 113 | # Run ESLint 114 | npm run lint 115 | 116 | # Run Vitest 117 | npm run test 118 | npm run test:watch 119 | 120 | # Release new version 121 | npm run release 122 | ``` 123 | 124 |
125 | 126 | 127 | 128 | [npm-version-src]: https://img.shields.io/npm/v/nuxt-tour/latest.svg?style=flat&colorA=020420&colorB=00DC82 129 | [npm-version-href]: https://npmjs.com/package/nuxt-tour 130 | [npm-downloads-src]: https://img.shields.io/npm/dm/nuxt-tour.svg?style=flat&colorA=020420&colorB=00DC82 131 | [npm-downloads-href]: https://npmjs.com/package/nuxt-tour 132 | [license-src]: https://img.shields.io/npm/l/nuxt-tour.svg?style=flat&colorA=020420&colorB=00DC82 133 | [license-href]: https://npmjs.com/package/nuxt-tour 134 | [nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js 135 | [nuxt-href]: https://nuxt.com 136 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { createConfigForNuxt } from "@nuxt/eslint-config/flat"; 2 | 3 | export default createConfigForNuxt({ 4 | features: { 5 | tooling: true, 6 | }, 7 | // options here 8 | }) 9 | .override("nuxt/vue/rules", { 10 | rules: { 11 | "vue/multi-word-component-names": "off", 12 | "vue/require-default-prop": "off", 13 | "vue/no-v-html": "off", 14 | }, 15 | ignores: ["dist", "node_modules", ".nuxt"], 16 | }) 17 | .override("nuxt/typescript/rules", { 18 | rules: { 19 | "@typescript-eslint/no-unused-vars": "off", 20 | "@typescript-eslint/no-explicit-any": "off", 21 | "@typescript-eslint/no-invalid-void-type": "off", 22 | }, 23 | }); 24 | -------------------------------------------------------------------------------- /nuxt-tour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BayBreezy/nuxt-tour/5df61fef7fdb73b47dd773ae60d2147d5498b76b/nuxt-tour.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-tour", 3 | "version": "0.0.40", 4 | "description": "Empower your users with interactive guided tours of your Nuxt 3 applications using the nuxt-tour module. With this module, developers can seamlessly integrate step-by-step tooltips into their applications, providing clear instructions and highlighting key features.", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/BayBreezy/nuxt-tour.git" 8 | }, 9 | "license": "MIT", 10 | "author": { 11 | "name": "Behon Baker", 12 | "email": "behon.baker@yahoo.com", 13 | "url": "https://behonbaker.com/" 14 | }, 15 | "type": "module", 16 | "exports": { 17 | ".": { 18 | "types": "./dist/types.d.mts", 19 | "import": "./dist/module.mjs", 20 | "require": "./dist/module.mjs" 21 | } 22 | }, 23 | "main": "./dist/module.mjs", 24 | "files": [ 25 | "dist", 26 | "src/**/*" 27 | ], 28 | "scripts": { 29 | "afterClone": "npm i && cd playground && npm i && cd .. && npm run dev:prepare", 30 | "dev": "nuxi dev playground", 31 | "dev:build": "nuxi build playground", 32 | "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground", 33 | "lint": "eslint .", 34 | "lint:fix": "eslint . --fix", 35 | "netlify": "npm run afterClone && npm run prepack && npm run dev:build", 36 | "prepack": "nuxt-module-build build", 37 | "prepare": "nuxt-module-build prepare && nuxt-module-build build", 38 | "release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags", 39 | "rm:lock": "rm -rf package-lock.json playground/package-lock.json", 40 | "test": "vitest run", 41 | "test:watch": "vitest watch" 42 | }, 43 | "dependencies": { 44 | "@nuxt/icon": "^1.12.0", 45 | "@nuxt/kit": "^3.17.2", 46 | "@popperjs/core": "^2.11.8", 47 | "@types/jump.js": "^1.0.6", 48 | "@types/lodash-es": "^4.17.12", 49 | "@vueuse/core": "^13.1.0", 50 | "@vueuse/integrations": "^13.1.0", 51 | "focus-trap": "^7.6.4", 52 | "jump.js": "^1.0.2", 53 | "lodash-es": "^4.17.21", 54 | "sass": "^1.87.0" 55 | }, 56 | "devDependencies": { 57 | "@ianvs/prettier-plugin-sort-imports": "^4.4.1", 58 | "@nuxt/eslint-config": "^1.3.0", 59 | "@nuxt/module-builder": "1.0.1", 60 | "@nuxt/schema": "^3.17.2", 61 | "@nuxt/test-utils": "^3.18.0", 62 | "@types/node": "^22.15.17", 63 | "changelogen": "^0.6.1", 64 | "eslint": "^9.26.0", 65 | "nuxt": "^3.17.2", 66 | "prettier": "^3.5.3", 67 | "vitest": "^3.1.3", 68 | "vue-tsc": "^2.2.10" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /playground/.gitignore: -------------------------------------------------------------------------------- 1 | .nuxt 2 | .output 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | lerna-debug.log* 10 | .pnpm-debug.log* 11 | 12 | # Diagnostic reports (https://nodejs.org/api/report.html) 13 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 14 | 15 | # Runtime data 16 | pids 17 | *.pid 18 | *.seed 19 | *.pid.lock 20 | 21 | # Directory for instrumented libs generated by jscoverage/JSCover 22 | lib-cov 23 | 24 | # Coverage directory used by tools like istanbul 25 | coverage 26 | *.lcov 27 | 28 | # nyc test coverage 29 | .nyc_output 30 | 31 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 32 | .grunt 33 | 34 | # Bower dependency directory (https://bower.io/) 35 | bower_components 36 | 37 | # node-waf configuration 38 | .lock-wscript 39 | 40 | # Compiled binary addons (https://nodejs.org/api/addons.html) 41 | build/Release 42 | 43 | # Dependency directories 44 | node_modules/ 45 | jspm_packages/ 46 | 47 | # Snowpack dependency directory (https://snowpack.dev/) 48 | web_modules/ 49 | 50 | # TypeScript cache 51 | *.tsbuildinfo 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Optional stylelint cache 60 | .stylelintcache 61 | 62 | # Microbundle cache 63 | .rpt2_cache/ 64 | .rts2_cache_cjs/ 65 | .rts2_cache_es/ 66 | .rts2_cache_umd/ 67 | 68 | # Optional REPL history 69 | .node_repl_history 70 | 71 | # Output of 'npm pack' 72 | *.tgz 73 | 74 | # Yarn Integrity file 75 | .yarn-integrity 76 | 77 | # dotenv environment variable files 78 | .env 79 | .env.development.local 80 | .env.test.local 81 | .env.production.local 82 | .env.local 83 | 84 | # parcel-bundler cache (https://parceljs.org/) 85 | .cache 86 | .parcel-cache 87 | 88 | # Next.js build output 89 | .next 90 | out 91 | 92 | # Nuxt.js build / generate output 93 | .nuxt 94 | dist 95 | 96 | # Gatsby files 97 | .cache/ 98 | # Comment in the public line in if your project uses Gatsby and not Next.js 99 | # https://nextjs.org/blog/next-9-1#public-directory-support 100 | # public 101 | 102 | # vuepress build output 103 | .vuepress/dist 104 | 105 | # vuepress v2.x temp and cache directory 106 | .temp 107 | .cache 108 | 109 | # Docusaurus cache and generated files 110 | .docusaurus 111 | 112 | # Serverless directories 113 | .serverless/ 114 | 115 | # FuseBox cache 116 | .fusebox/ 117 | 118 | # DynamoDB Local files 119 | .dynamodb/ 120 | 121 | # TernJS port file 122 | .tern-port 123 | 124 | # Stores VSCode versions used for testing VSCode extensions 125 | .vscode-test 126 | 127 | # yarn v2 128 | .yarn/cache 129 | .yarn/unplugged 130 | .yarn/build-state.yml 131 | .yarn/install-state.gz 132 | .pnp.* 133 | -------------------------------------------------------------------------------- /playground/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "endOfLine": "lf", 4 | "plugins": ["@ianvs/prettier-plugin-sort-imports", "prettier-plugin-tailwindcss"], 5 | "printWidth": 100, 6 | "semi": true, 7 | "singleQuote": false, 8 | "tabWidth": 2, 9 | "trailingComma": "es5", 10 | "useTabs": false, 11 | "vueIndentScriptAndStyle": true, 12 | "tailwindFunctions": ["tv"], 13 | "importOrder": ["", "", "", "", "^[.]"] 14 | } 15 | -------------------------------------------------------------------------------- /playground/app.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /playground/assets/css/tailwind.css: -------------------------------------------------------------------------------- 1 | @import url("https://rsms.me/inter/inter.css"); 2 | @import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap"); 3 | 4 | @tailwind base; 5 | @tailwind components; 6 | @tailwind utilities; 7 | 8 | @layer base { 9 | :root { 10 | --background: 0 0% 100%; 11 | --foreground: 240 10% 3.9%; 12 | --card: 0 0% 100%; 13 | --card-foreground: 240 10% 3.9%; 14 | --popover: 0 0% 100%; 15 | --popover-foreground: 240 10% 3.9%; 16 | --primary: 240 5.9% 10%; 17 | --primary-foreground: 0 0% 98%; 18 | --secondary: 240 4.8% 95.9%; 19 | --secondary-foreground: 240 5.9% 10%; 20 | --muted: 240 4.8% 95.9%; 21 | --muted-foreground: 240 3.8% 46.1%; 22 | --accent: 240 4.8% 95.9%; 23 | --accent-foreground: 240 5.9% 10%; 24 | --destructive: 0 84.2% 60.2%; 25 | --destructive-foreground: 0 0% 98%; 26 | --border: 240 5.9% 90%; 27 | --input: 240 5.9% 90%; 28 | --ring: 240 5.9% 10%; 29 | --radius: 0.5rem; 30 | /* Twoslash stuff */ 31 | --vp-c-border: theme("colors.foreground / 30%"); 32 | --vp-code-font-size: theme("fontSize.sm"); 33 | --twoslash-error-color: theme("colors.destructive.DEFAULT"); 34 | --vp-c-bg: theme("colors.background"); 35 | } 36 | 37 | .dark { 38 | --background: 240 10% 3.9%; 39 | --foreground: 0 0% 98%; 40 | --card: 240 10% 3.9%; 41 | --card-foreground: 0 0% 98%; 42 | --popover: 240 10% 3.9%; 43 | --popover-foreground: 0 0% 98%; 44 | --primary: 0 0% 98%; 45 | --primary-foreground: 240 5.9% 10%; 46 | --secondary: 240 3.7% 15.9%; 47 | --secondary-foreground: 0 0% 98%; 48 | --muted: 240 3.7% 15.9%; 49 | --muted-foreground: 240 5% 64.9%; 50 | --accent: 240 3.7% 15.9%; 51 | --accent-foreground: 0 0% 98%; 52 | --destructive: 0 62.8% 30.6%; 53 | --destructive-foreground: 0 0% 98%; 54 | --border: 240 3.7% 15.9%; 55 | --input: 240 3.7% 15.9%; 56 | --ring: 240 4.9% 83.9%; 57 | --vp-c-bg: theme("colors.muted.DEFAULT"); 58 | } 59 | } 60 | 61 | .v-popper__arrow-inner { 62 | color: theme("colors.foreground / 7%"); 63 | } 64 | 65 | @layer base { 66 | * { 67 | @apply border-border; 68 | } 69 | body { 70 | @apply bg-background text-foreground; 71 | font-feature-settings: 72 | "rlig" 1, 73 | "calt" 1; 74 | } 75 | } 76 | 77 | h1 > a, 78 | h2 > a, 79 | h3 > a, 80 | h4 > a, 81 | h5 > a, 82 | h6 > a { 83 | @apply !font-bold !no-underline hover:!text-foreground hover:!decoration-wavy; 84 | } 85 | 86 | code { 87 | @apply inline-block rounded bg-muted px-1 py-px font-mono; 88 | } 89 | 90 | a > code { 91 | @apply inline-block border border-dashed border-primary/40 bg-primary/5 px-1 transition hover:border-primary; 92 | } 93 | -------------------------------------------------------------------------------- /playground/components/Docs/Footer.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 45 | -------------------------------------------------------------------------------- /playground/components/Docs/Navbar.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 60 | -------------------------------------------------------------------------------- /playground/components/Docs/Navlink.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 42 | -------------------------------------------------------------------------------- /playground/components/Docs/Toc.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 61 | -------------------------------------------------------------------------------- /playground/components/Ui/Avatar/Avatar.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 44 | -------------------------------------------------------------------------------- /playground/components/Ui/Avatar/Fallback.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 28 | -------------------------------------------------------------------------------- /playground/components/Ui/Avatar/Image.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 23 | -------------------------------------------------------------------------------- /playground/components/Ui/Button.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 62 | -------------------------------------------------------------------------------- /playground/components/Ui/Container.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 26 | -------------------------------------------------------------------------------- /playground/components/Ui/Divider.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 78 | -------------------------------------------------------------------------------- /playground/components/Ui/Navbar.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 32 | -------------------------------------------------------------------------------- /playground/components/Ui/ScrollArea/Corner.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | -------------------------------------------------------------------------------- /playground/components/Ui/ScrollArea/ScrollArea.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 33 | -------------------------------------------------------------------------------- /playground/components/Ui/ScrollArea/Scrollbar.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 37 | -------------------------------------------------------------------------------- /playground/components/Ui/ScrollArea/Thumb.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 37 | -------------------------------------------------------------------------------- /playground/components/Ui/ScrollArea/Viewport.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 22 | -------------------------------------------------------------------------------- /playground/components/Ui/Sheet/Close.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | -------------------------------------------------------------------------------- /playground/components/Ui/Sheet/Content.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 70 | -------------------------------------------------------------------------------- /playground/components/Ui/Sheet/Description.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 27 | -------------------------------------------------------------------------------- /playground/components/Ui/Sheet/Footer.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 27 | -------------------------------------------------------------------------------- /playground/components/Ui/Sheet/Header.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 27 | -------------------------------------------------------------------------------- /playground/components/Ui/Sheet/Overlay.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 20 | -------------------------------------------------------------------------------- /playground/components/Ui/Sheet/Portal.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | -------------------------------------------------------------------------------- /playground/components/Ui/Sheet/Sheet.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /playground/components/Ui/Sheet/Title.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 27 | -------------------------------------------------------------------------------- /playground/components/Ui/Sheet/Trigger.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | -------------------------------------------------------------------------------- /playground/components/Ui/Sheet/X.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 38 | -------------------------------------------------------------------------------- /playground/components/Ui/VueSonner.client.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 15 | 48 | -------------------------------------------------------------------------------- /playground/components/content/Showcase.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /playground/components/content/docs/CreateTourExample.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 102 | 103 | 108 | -------------------------------------------------------------------------------- /playground/components/content/examples/ExAutoStart.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 51 | -------------------------------------------------------------------------------- /playground/components/content/examples/ExCallbackEmits.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 75 | -------------------------------------------------------------------------------- /playground/components/content/examples/ExCustomButton.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 93 | 94 | 102 | -------------------------------------------------------------------------------- /playground/components/content/examples/ExHighlight.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 46 | -------------------------------------------------------------------------------- /playground/components/content/examples/ExHtmlElement.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 77 | -------------------------------------------------------------------------------- /playground/components/content/prose/ProsePre.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 67 | -------------------------------------------------------------------------------- /playground/components/content/prose/ProseTable.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /playground/content/0.index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introducing Nuxt Tour" 3 | icon: "iconoir:tournament" 4 | --- 5 | 6 | Empower your users with interactive guided tours of your Nuxt 3 applications using the `nuxt-tour` module. 7 | 8 | With this versatile module, developers can seamlessly integrate step-by-step guide into their applications, providing clear instructions and highlighting key features. 9 | 10 | ## Features 11 | 12 | - **Easy Integration**: Quickly add guided tours to your Nuxt 3 projects with minimal setup. 13 | - **Customizable**: Tailor the appearance and behavior of tooltips to match your application's design and user experience. 14 | - **Step-by-Step Navigation**: Guide users through workflows and features with sequential tooltips and intuitive navigation controls. 15 | - **Rich Content Support**: Enhance guides with text, images, videos, and interactive elements via the available slots. 16 | - **Responsive Design**: Ensure a consistent experience across devices with responsive guides that adapt to different screen sizes. 17 | 18 | Whether you're onboarding new users, showcasing product features, or providing contextual assistance, nuxt-tour empowers developers to create immersive and user-friendly experiences within their Nuxt 3 applications. 19 | 20 | Get started today and elevate your user experience with `nuxt-tour`. 21 | 22 | ## Credits Beating Heart 23 | 24 | Special thanks to [Vue Tour](https://github.com/GlobalHive/vuejs-tour/tree/master) for doing the heavy lifting. I basically just ported it to Nuxt 3(with a few changes here and there). 25 | 26 | Thank you https://github.com/GlobalHive 27 | -------------------------------------------------------------------------------- /playground/content/1.getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Getting started" 3 | description: "Learn how to install and configure the nuxt-tour module in your Nuxt 3 project." 4 | icon: "heroicons:rocket-launch" 5 | --- 6 | 7 | ## Prerequisites 8 | 9 | Before you begin, ensure you have the following: 10 | 11 | - A Nuxt 3 project set up and running. 12 | - Basic knowledge of Vue.js and Nuxt 3. 13 | - Node.js installed on your machine. (Use NVM for managing multiple Node.js versions.) 14 | 15 | ## Installation 16 | 17 | To get started with `nuxt-tour`, install the package with your favorite package manager: 18 | 19 | ```bash [Terminal] 20 | npm install nuxt-tour 21 | ``` 22 | 23 | After installing, go ahead and add the module to your Nuxt 3 project by updating the `nuxt.config` file: 24 | 25 | ```ts twoslash [nuxt.config.ts] 26 | export default defineNuxtConfig({ 27 | modules: ["nuxt-tour"], 28 | }); 29 | ``` 30 | 31 | ## Module options 32 | 33 | The module currently supports the following options: 34 | 35 | - `prefix`: The prefix for the module's Tour component. Default: `V`. 36 | - `injectSass`: Whether to inject the module's Sass file. Default: `true`. 37 | 38 | This is the interface for the module options: 39 | 40 | ```ts twoslash [Module Options] 41 | export interface TourOptions { 42 | /** 43 | * The prefix to use for the component name 44 | * 45 | * @default "V" 46 | */ 47 | prefix?: string; 48 | /** 49 | * Inject the default sass file 50 | * 51 | * Feel free to create your own 🙂. Just get the class names correct 52 | * 53 | * @default `true` 54 | */ 55 | injectSass?: boolean; 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /playground/content/3.create-tour.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Create a tour" 3 | description: "Learn how to create a tour in your Nuxt 3 project using the nuxt-tour module." 4 | icon: "heroicons:sparkles" 5 | --- 6 | 7 | :CreateTourExample 8 | 9 | ## Add the component 10 | 11 | Add the `VTour` component to your page. 12 | 13 | I use `VTour` here because the default prefix for the component is `V`. Ensure that you change the component name to match your prefix. 14 | 15 | Ensure that you pass an array of steps to the `steps` prop. 16 | 17 | ```vue 18 | 23 | 24 | 45 | ``` 46 | 47 | ### Limitations 48 | 49 | - :icon{name="heroicons:exclamation-triangle" .text-amber-500.mr-2} Only one `VTour` component can be used per page. 50 | - :icon{name="heroicons:exclamation-triangle" .text-amber-500.mr-2} The `target` prop must be a valid CSS selector. If the target cannot be found, the tour will try to render the step in the middle of the page. 51 | - :icon{name="heroicons:exclamation-triangle" .text-amber-500.mr-2} Ensure that the target element is rendered before the tour is initialized. 52 | 53 | ## Start the tour 54 | 55 | There are two ways to start the tour: 56 | 57 | - Automatically start the tour when the component is mounted by passing the `autoStart` prop. 58 | - Manually start the tour by calling the `startTour` method on the `VTour` component. 59 | 60 | ### Automatically start the tour 61 | 62 | To automatically start the tour when the component is mounted, pass the `autoStart` prop. 63 | 64 | ```vue [Auto start] 65 | 68 | 69 | 75 | ``` 76 | 77 | ### Manually start the tour 78 | 79 | To manually start the tour, call the `startTour` method on the `VTour` component. 80 | 81 | ```vue [Manual start] 82 | 85 | 86 | 99 | ``` 100 | 101 | ## Multiple tours 102 | 103 | If you need to create multiple tours within your application, you need to pass a `name` prop to the `VTour` component. 104 | 105 | The component will use the name `default` if no name is provided. 106 | 107 | The `name` prop is used to store which tour has been completed in the browser's local storage. 108 | 109 | Try to make each tour unique to avoid conflicts. 110 | 111 | ```vue [Named tour] 112 | 115 | 116 | 122 | ``` 123 | -------------------------------------------------------------------------------- /playground/content/4.props.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Props" 3 | description: "Learn about the props available in the nuxt-tour module." 4 | icon: "heroicons:adjustments-vertical" 5 | --- 6 | 7 | ## Tour Props 8 | 9 | Below are all the props that the `VTour` component accepts. 10 | 11 | ```ts twoslash 12 | import type { Modifier, OptionsGeneric } from "@popperjs/core"; 13 | import type { Options } from "jump.js"; 14 | import type { ComputedRef, MaybeRefOrGetter, Ref } from "vue"; 15 | 16 | type HTMLElement = any; 17 | 18 | export type ButtonProp = { 19 | /** 20 | * The label of the button 21 | */ 22 | label?: string; 23 | /** 24 | * The icon displayed to the right of the button 25 | * 26 | * Any icon from the [Icones](https://icones.netlify.app/) website can be used here 27 | */ 28 | rightIcon?: string; 29 | /** 30 | * The icon displayed to the left of the button 31 | * 32 | * Any icon from the [Icones](https://icones.netlify.app/) website can be used here 33 | */ 34 | leftIcon?: string; 35 | }; 36 | 37 | export type TourStep = { 38 | /** 39 | * The element that the step should target 40 | * 41 | * This can be a CSS selector, a ref of type string 42 | * 43 | * If this is not passed, the step will be positioned in the center of the screen 44 | */ 45 | target?: string | undefined | null | MaybeRefOrGetter | ComputedRef; 46 | 47 | /** 48 | * The title of the step 49 | */ 50 | title?: string | HTMLElement | Ref | Ref | undefined | null; 51 | /** 52 | * The subtext of the step 53 | */ 54 | subText?: string | HTMLElement | Ref | Ref | undefined | null; 55 | /** 56 | * The content of the step 57 | */ 58 | body?: string | HTMLElement | Ref | Ref | undefined | null; 59 | /** 60 | * The configuration to pass to popperjs 61 | */ 62 | popperConfig?: Partial>>> | undefined; 63 | /** 64 | * The function that should be called when `Next` button is clicked 65 | */ 66 | onNext?: () => void | (() => Promise); 67 | /** 68 | * The function that should be called when `Prev` button is clicked 69 | */ 70 | onPrev?: () => void | (() => Promise); 71 | /** 72 | * The function that should be called when the step is displayed 73 | */ 74 | onShow?: () => void | (() => Promise); 75 | /** 76 | * The prefix that will be added to the slot name 77 | */ 78 | slot?: string; 79 | /** 80 | * Determines if the step should show a backdrop or not 81 | * 82 | * @default false 83 | */ 84 | backdrop?: boolean; 85 | }; 86 | // ---cut--- 87 | export type TourProps = { 88 | /** 89 | * The name of the tour 90 | * @default "default" 91 | */ 92 | name?: string; 93 | /** 94 | * The steps of the tour 95 | */ 96 | steps: TourStep[]; 97 | /** 98 | * The function that should be called when the tour is completed 99 | */ 100 | onComplete?: () => void | (() => Promise); 101 | /** 102 | * The function that should be called when the tour is skipped 103 | */ 104 | onSkip?: () => void | (() => Promise); 105 | /** 106 | * Determines if the tour should be started automatically 107 | * @default false 108 | */ 109 | autoStart?: boolean; 110 | /** 111 | * The delay before the tour starts. This will only work if `autoStart` is `true` 112 | * @default 0 113 | */ 114 | startDelay?: number | string | null; 115 | /** 116 | * When this is `true`, the target element will be highlighted 117 | */ 118 | highlight?: boolean; 119 | /** 120 | * The configuration of the `Next` button 121 | */ 122 | nextButton?: ButtonProp; 123 | /** 124 | * The configuration of the `Skip` button 125 | */ 126 | skipButton?: ButtonProp; 127 | /** 128 | * The configuration of the `Prev` button 129 | */ 130 | prevButton?: ButtonProp; 131 | /** 132 | * The configuration of the `Finish` button 133 | */ 134 | finishButton?: ButtonProp; 135 | /** 136 | * Prop used to determine if the arrow should be shown or not 137 | * @default true 138 | */ 139 | showArrow?: boolean; 140 | /** 141 | * The configuration to pass to jump.js 142 | * 143 | * @default { duration: 300, offset: -100 } 144 | */ 145 | jumpOptions?: Options; 146 | /** 147 | * Determines if focus should be trapped within the tour 148 | * 149 | * @default true 150 | */ 151 | trapFocus?: boolean; 152 | /** 153 | * Determines if the scroll should be locked when the tour is active 154 | * 155 | * @default true 156 | */ 157 | lockScroll?: boolean; 158 | /** 159 | * Determines if the tour should show a backdrop or not 160 | * 161 | * @default false 162 | */ 163 | backdrop?: boolean; 164 | }; 165 | ``` 166 | 167 | ## Step Props 168 | 169 | These are the options that can be added to the objects in the `steps` array. 170 | 171 | ```ts twoslash 172 | import type { Modifier, OptionsGeneric } from "@popperjs/core"; 173 | import type { Options } from "jump.js"; 174 | import type { ComputedRef, MaybeRefOrGetter, Ref } from "vue"; 175 | 176 | type HTMLElement = any; 177 | 178 | // ---cut--- 179 | export type TourStep = { 180 | /** 181 | * The element that the step should target 182 | * 183 | * This can be a CSS selector, a ref of type string 184 | * 185 | * If this is not passed, the step will be positioned in the center of the screen 186 | */ 187 | target?: string | undefined | null | MaybeRefOrGetter | ComputedRef; 188 | 189 | /** 190 | * The title of the step 191 | */ 192 | title?: string | HTMLElement | Ref | Ref | undefined | null; 193 | /** 194 | * The subtext of the step 195 | */ 196 | subText?: string | HTMLElement | Ref | Ref | undefined | null; 197 | /** 198 | * The content of the step 199 | */ 200 | body?: string | HTMLElement | Ref | Ref | undefined | null; 201 | /** 202 | * The configuration to pass to popperjs 203 | */ 204 | popperConfig?: Partial>>> | undefined; 205 | /** 206 | * The function that should be called when `Next` button is clicked 207 | */ 208 | onNext?: () => void | (() => Promise); 209 | /** 210 | * The function that should be called when `Prev` button is clicked 211 | */ 212 | onPrev?: () => void | (() => Promise); 213 | /** 214 | * The function that should be called when the step is displayed 215 | */ 216 | onShow?: () => void | (() => Promise); 217 | /** 218 | * The prefix that will be added to the slot name 219 | */ 220 | slot?: string; 221 | /** 222 | * Determines if the step should show a backdrop or not 223 | * 224 | * @default false 225 | */ 226 | backdrop?: boolean; 227 | }; 228 | ``` 229 | 230 | ## Button Prop 231 | 232 | These are the options that can be added to the objects in the `nextButton`, `skipButton`, `prevButton`, and `finishButton` props. 233 | 234 | ```ts twoslash 235 | export type ButtonProp = { 236 | /** 237 | * The label of the button 238 | */ 239 | label?: string; 240 | /** 241 | * The icon displayed to the right of the button 242 | * 243 | * Any icon from the [Icones](https://icones.netlify.app/) website can be used here 244 | */ 245 | rightIcon?: string; 246 | /** 247 | * The icon displayed to the left of the button 248 | * 249 | * Any icon from the [Icones](https://icones.netlify.app/) website can be used here 250 | */ 251 | leftIcon?: string; 252 | }; 253 | ``` 254 | -------------------------------------------------------------------------------- /playground/content/5.methods.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Methods 3 | description: Learn about the methods available on the nuxt-tour module. 4 | icon: fluent:math-formula-24-filled 5 | --- 6 | 7 | ## Getting the Tour Instance 8 | 9 | To get the tour instance, you can add a ref to the `VTour` component and then access the different methods on the instance. 10 | 11 | ```vue 12 | 15 | 16 | 27 | ``` 28 | 29 | ## Methods 30 | 31 | Below are all the methods that the `VTour` component exposes. 32 | 33 | ### `startTour` 34 | 35 | Starts the tour from the first step. This 36 | 37 | If the `steps` prop is empty, the tour won't start 38 | 39 | If the name of the tour in local storage is found and it's value is `true`, the tour won't start 40 | 41 | ### `endTour` 42 | 43 | Ends the tour and set the the `name` of the tour in local storage to `true` 44 | 45 | ### `nextStep` 46 | 47 | Moves to the next step in the tour 48 | 49 | ### `prevStep` 50 | 51 | Moves to the previous step in the tour 52 | 53 | ### `goToStep` 54 | 55 | Moves to a specific step in the tour. A number **MUST** be passed to this method. 56 | 57 | ### `resetTour` 58 | 59 | This method removes the `name` of the tour from local storage and then calls the `startTour` method. 60 | 61 | ### `recalculatePopper` 62 | 63 | This method recalculates the position of the popper element. This is useful when the target element changes position. 64 | 65 | ### `activateFocusTrap` 66 | 67 | This method activates the focus trap. This is useful when you want to prevent the user from interacting with elements outside the tour. 68 | 69 | ### `deActivateFocusTrap` 70 | 71 | This method deactivates the focus trap. This is useful when you want to allow the user to interact with elements outside the tour. 72 | -------------------------------------------------------------------------------- /playground/content/6.slots.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Slots 3 | description: Learn about the slots available on the nuxt-tour module. 4 | icon: heroicons:cube-transparent 5 | --- 6 | 7 | ## Slot names 8 | 9 | In order to render a usable slot, you **MUST** add the name of your slot to the `slot` property within the step object. 10 | 11 | ```ts 12 | const steps = [ 13 | { 14 | target: "#start-the-tour>a", 15 | title: "Start the tour", 16 | subText: "Two ways to start the tour", 17 | slot: "startTour", 18 | }, 19 | ]; 20 | ``` 21 | 22 | The step above would prepend `startTour-` to all of the slots that are available in the `VTour` component. 23 | 24 | ## Available Slots 25 | 26 | Below are all the slots that the `VTour` component exposes. Remember to add the `slot` property to the step object to render the slot. 27 | 28 | ### header 29 | 30 | This slot is used to render the header of the step. The header slot also holds the title and sub-text slots. 31 | 32 | The available slot props are: 33 | 34 | ```vue 35 | 49 | ``` 50 | 51 | ### title 52 | 53 | This slot is used to render the title of the step. 54 | 55 | The available slot props are: 56 | 57 | ```vue 58 | 72 | ``` 73 | 74 | ### sub-text 75 | 76 | This slot is used to render the sub-text of the step. 77 | 78 | ```vue 79 | 93 | ``` 94 | 95 | ### body 96 | 97 | This slot is used to render the body of the step. 98 | 99 | ```vue 100 | 114 | ``` 115 | 116 | ### actions 117 | 118 | This slot is used to render the actions of the step. The actions slot also holds the next, previous and skip slots 119 | 120 | ```vue 121 | 135 | ``` 136 | 137 | ### skip-button 138 | 139 | This slot is used to render the skip button of the step. 140 | 141 | ```vue 142 | 159 | ``` 160 | 161 | ### next-button 162 | 163 | This slot is used to render the next button of the step. 164 | 165 | ```vue 166 | 183 | ``` 184 | 185 | ### prev-button 186 | 187 | This slot is used to render the previous button of the step. 188 | 189 | ```vue 190 | 207 | ``` 208 | 209 | ### arrow 210 | 211 | This slot is used to render the arrow of the step. 212 | 213 | ```vue 214 | 231 | ``` 232 | -------------------------------------------------------------------------------- /playground/content/7.emits.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Emits 3 | description: Learn about the events emitted by the nuxt-tour module. 4 | icon: heroicons:rss 5 | --- 6 | 7 | ## Event Emissions 8 | 9 | Below are all the events that the `VTour` component emits. 10 | 11 | ```vue 12 | 15 | 16 | 29 | ``` 30 | 31 | ### `onTourStart` 32 | 33 | Emitted when the tour starts. 34 | 35 | ### `onTourEnd` 36 | 37 | Emitted when the tour ends. 38 | -------------------------------------------------------------------------------- /playground/content/8.styles.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Styles 3 | description: Learn about the styles available on the nuxt-tour module. 4 | icon: heroicons:swatch 5 | --- 6 | 7 | ## Default styles 8 | 9 | The `VTour` component comes with a default set of styles that can be overridden by adding your own styles to your project. 10 | 11 | If you don't want to use the default styles, you can disable them by setting the `injectSass` prop to `false` in your `nuxt.config` 12 | 13 | ```ts 14 | export default defineNuxtConfig({ 15 | tour: { injectSass: false }, 16 | }); 17 | ``` 18 | 19 | ## Sass variables 20 | 21 | Below are the default Sass variables that are used in the `VTour` component. 22 | 23 | ```scss [_variables.scss] 24 | $ntBorderColor: #e2e8f0 !default; 25 | $ntWhite: #ffffff !default; 26 | $ntTextColor: #0f172a !default; 27 | $ntSubTextColor: #64748b !default; 28 | $ntHighlightColor: #0ea5e9 !default; 29 | 30 | // Tooltip base 31 | $ntTooltipPosition: relative !default; 32 | $ntTooltipBackgroundColor: $ntWhite !default; 33 | $ntTooltipBorder: 1px solid $ntBorderColor !default; 34 | $ntTooltipPadding: 10px 15px !default; 35 | $ntTooltipBoxShadow: 36 | 0 2px 10px 0 rgba(0, 0, 0, 0.05), 37 | 0 2px 5px 0 rgba(0, 0, 0, 0.06) !default; 38 | $ntTooltipBorderRadius: 6px !default; 39 | $ntTooltipZIndex: 9999 !default; 40 | $ntTooltipMaxWidth: 370px !default; 41 | $ntTooltipDisplay: flex !default; 42 | $ntTooltipFlexDirection: column !default; 43 | $ntTooltipGap: 5px !default; 44 | 45 | // Tooltip Header 46 | $ntTooltipHeaderDisplay: flex !default; 47 | $ntTooltipHeaderFlexDirection: column !default; 48 | $ntTooltipHeaderGap: 6px !default; 49 | 50 | // Tooltip Title 51 | $ntTooltipTitleFontSize: 16px !default; 52 | $ntTooltipTitleLineHeight: normal !default; 53 | $ntTooltipTitleFontWeight: 600 !default; 54 | $ntTooltipTitleColor: $ntTextColor !default; 55 | 56 | // Tooltip subtext 57 | $ntTooltipSubTextFontSize: 14px !default; 58 | $ntTooltipSubTextLineHeight: normal !default; 59 | $ntTooltipSubTextColor: $ntSubTextColor !default; 60 | 61 | // Tooltip body 62 | $ntTooltipBodyFontSize: 14px !default; 63 | $ntTooltipBodyColor: $ntTextColor !default; 64 | 65 | // Tooltip arrow 66 | $ntTooltipArrowSize: 12px !default; 67 | $ntTooltipArrowBorder: 1px solid $ntBorderColor !default; 68 | $ntTooltipArrowBackgroundColor: $ntWhite !default; 69 | 70 | // Highlight 71 | $ntHighlightOffset: 8px !default; 72 | $ntHighlightOutlineRadius: 4px !default; 73 | $ntHighlightOutline: 1px solid $ntHighlightColor !default; 74 | 75 | // Action - Button container 76 | $ntActionDisplay: flex !default; 77 | $ntActionGap: 8px !default; 78 | $ntActionAlignItems: center !default; 79 | $ntActionGap: 8px !default; 80 | $ntActionMarginTop: 14px !default; 81 | 82 | // Action - Button 83 | $ntButtonDisplay: inline-flex !default; 84 | $ntButtonAlignItems: center !default; 85 | $ntButtonJustifyContent: center !default; 86 | $ntButtonLineHeight: 0 !default; 87 | $ntButtonGap: 8px !default; 88 | $ntButtonHeight: 32px !default; 89 | $ntButtonPadding: 4px 14px !default; 90 | $ntButtonBorderRadius: 5px !default; 91 | $ntButtonFontSize: 14px !default; 92 | $ntButtonFontWeight: 500 !default; 93 | $ntButtonTransition: all 0.2s ease-in-out !default; 94 | 95 | // Next - Finish button 96 | $ntButtonBackgroundColor: #020617 !default; 97 | $ntButtonColor: $ntWhite !default; 98 | 99 | // Skip button 100 | $ntButtonSkipBackgroundColor: transparent !default; 101 | $ntButtonSkipColor: $ntButtonBackgroundColor !default; 102 | $ntButtonSkipBorder: 1px solid $ntButtonSkipBackgroundColor !default; 103 | $ntButtonSkipHoverBackgroundColor: $ntBorderColor !default; 104 | 105 | // Prev button 106 | $ntButtonPrevBackgroundColor: $ntBorderColor !default; 107 | $ntButtonPrevColor: $ntButtonBackgroundColor !default; 108 | $ntButtonPrevBorder: 1px solid $ntBorderColor !default; 109 | $ntButtonPrevHoverBackgroundColor: $ntButtonBackgroundColor !default; 110 | $ntButtonPrevHoverBorderColor: $ntButtonPrevBackgroundColor !default; 111 | $ntButtonPrevHoverColor: $ntWhite !default; 112 | 113 | // Backdrop 114 | $ntBackdropZIndex: 9998 !default; 115 | $ntBackdropBackground: rgba(0, 0, 0, 0.5) !default; 116 | ``` 117 | 118 | ## Classes 119 | 120 | Here is the `scss` file that is injected. Feel free to override the variables to match your project's theme. 121 | 122 | ```scss [tour.scss] 123 | @use "sass:math"; 124 | @use "variables"; 125 | 126 | [data-hidden] { 127 | display: none !important; 128 | } 129 | 130 | .fade-nt-tooltip-enter-active, 131 | .fade-nt-tooltip-leave-active { 132 | transition: all 0.2s; 133 | } 134 | 135 | .fade-nt-tooltip-enter-from, 136 | .fade-nt-tooltip-leave-to { 137 | opacity: 0; 138 | } 139 | 140 | #nt-backdrop { 141 | position: fixed; 142 | top: 0; 143 | left: 0; 144 | width: 100%; 145 | height: 100%; 146 | background-color: variables.$ntBackdropBackground; 147 | z-index: variables.$ntBackdropZIndex; 148 | } 149 | 150 | #nt-tooltip { 151 | position: variables.$ntTooltipPosition; 152 | background-color: variables.$ntTooltipBackgroundColor; 153 | border: variables.$ntTooltipBorder; 154 | padding: variables.$ntTooltipPadding; 155 | box-shadow: variables.$ntTooltipBoxShadow; 156 | border-radius: variables.$ntTooltipBorderRadius; 157 | z-index: variables.$ntTooltipZIndex; 158 | max-width: variables.$ntTooltipMaxWidth; 159 | display: variables.$ntTooltipDisplay; 160 | flex-direction: variables.$ntTooltipFlexDirection; 161 | gap: variables.$ntTooltipGap; 162 | } 163 | 164 | .nt-center { 165 | position: absolute !important; 166 | top: 50% !important; 167 | left: 50% !important; 168 | transform: translate(-50%, -50%) !important; 169 | } 170 | 171 | #nt-tooltip-header { 172 | display: variables.$ntTooltipHeaderDisplay; 173 | flex-direction: variables.$ntTooltipHeaderFlexDirection; 174 | gap: variables.$ntTooltipHeaderGap; 175 | 176 | #nt-tooltip-title { 177 | font-size: variables.$ntTooltipTitleFontSize; 178 | line-height: variables.$ntTooltipTitleLineHeight; 179 | font-weight: variables.$ntTooltipTitleFontWeight; 180 | color: variables.$ntTooltipTitleColor; 181 | } 182 | 183 | #nt-tooltip-sub-text { 184 | line-height: variables.$ntTooltipSubTextLineHeight; 185 | font-size: variables.$ntTooltipSubTextFontSize; 186 | color: variables.$ntTooltipSubTextColor; 187 | } 188 | } 189 | 190 | #nt-tooltip-body { 191 | font-size: variables.$ntTooltipBodyFontSize; 192 | color: variables.$ntTooltipBodyColor; 193 | } 194 | 195 | #nt-tooltip[data-popper-placement^="top"] { 196 | #nt-arrow { 197 | bottom: math.div(-(variables.$ntTooltipArrowSize), 2); 198 | &::before { 199 | content: ""; 200 | border-bottom: variables.$ntTooltipArrowBorder; 201 | border-right: variables.$ntTooltipArrowBorder; 202 | } 203 | } 204 | } 205 | 206 | #nt-tooltip[data-popper-placement^="bottom"] { 207 | #nt-arrow { 208 | top: math.div(-(variables.$ntTooltipArrowSize), 2); 209 | &::before { 210 | content: ""; 211 | border-top: variables.$ntTooltipArrowBorder; 212 | border-left: variables.$ntTooltipArrowBorder; 213 | } 214 | } 215 | } 216 | 217 | #nt-tooltip[data-popper-placement^="left"] { 218 | #nt-arrow { 219 | right: math.div(-(variables.$ntTooltipArrowSize), 2); 220 | &::before { 221 | content: ""; 222 | border-top: variables.$ntTooltipArrowBorder; 223 | border-right: variables.$ntTooltipArrowBorder; 224 | } 225 | } 226 | } 227 | 228 | #nt-tooltip[data-popper-placement^="right"] { 229 | #nt-arrow { 230 | left: math.div(-(variables.$ntTooltipArrowSize), 2); 231 | &::before { 232 | content: ""; 233 | border-bottom: variables.$ntTooltipArrowBorder; 234 | border-left: variables.$ntTooltipArrowBorder; 235 | } 236 | } 237 | } 238 | 239 | #nt-arrow { 240 | width: variables.$ntTooltipArrowSize; 241 | height: variables.$ntTooltipArrowSize; 242 | position: absolute; 243 | z-index: -99; 244 | 245 | &::before { 246 | content: ""; 247 | width: variables.$ntTooltipArrowSize; 248 | height: variables.$ntTooltipArrowSize; 249 | background-color: variables.$ntTooltipArrowBackgroundColor; 250 | transform: rotate(45deg); 251 | position: absolute; 252 | } 253 | } 254 | 255 | .nt-highlight { 256 | outline: variables.$ntHighlightOutline; 257 | outline-offset: variables.$ntHighlightOffset; 258 | border-radius: variables.$ntHighlightOutlineRadius; 259 | } 260 | 261 | .nt-actions { 262 | display: variables.$ntActionDisplay; 263 | gap: variables.$ntActionGap; 264 | align-items: variables.$ntActionAlignItems; 265 | gap: variables.$ntActionGap; 266 | margin-top: variables.$ntActionMarginTop; 267 | 268 | button { 269 | display: variables.$ntButtonDisplay; 270 | align-items: variables.$ntButtonAlignItems; 271 | justify-content: variables.$ntButtonJustifyContent; 272 | line-height: variables.$ntButtonLineHeight; 273 | gap: variables.$ntButtonGap; 274 | height: variables.$ntButtonHeight; 275 | padding: variables.$ntButtonPadding; 276 | border-radius: variables.$ntButtonBorderRadius; 277 | background-color: variables.$ntButtonBackgroundColor; 278 | color: variables.$ntButtonColor; 279 | font-size: variables.$ntButtonFontSize; 280 | font-weight: variables.$ntButtonFontWeight; 281 | transition: variables.$ntButtonTransition; 282 | white-space: nowrap; 283 | cursor: pointer; 284 | 285 | &#nt-action-skip { 286 | background-color: variables.$ntButtonSkipBackgroundColor; 287 | color: variables.$ntButtonSkipColor; 288 | border: variables.$ntButtonSkipBorder; 289 | 290 | &:hover { 291 | background-color: variables.$ntButtonSkipHoverBackgroundColor; 292 | } 293 | } 294 | 295 | &#nt-action-prev { 296 | background-color: variables.$ntButtonPrevBackgroundColor; 297 | color: variables.$ntButtonPrevColor; 298 | border: variables.$ntButtonPrevBorder; 299 | 300 | &:hover { 301 | background-color: variables.$ntButtonPrevHoverBackgroundColor; 302 | border-color: variables.$ntButtonPrevHoverBorderColor; 303 | color: variables.$ntButtonPrevHoverColor; 304 | } 305 | } 306 | 307 | &:hover { 308 | opacity: 0.85; 309 | } 310 | } 311 | } 312 | ``` 313 | 314 | ## CSS 315 | 316 | Here is the CSS that is injected into the head of your document. 317 | 318 | At build time, the `scss` file is compiled to `css` and injected into the head of your document. 319 | 320 | ```css [tour.css] 321 | [data-hidden] { 322 | display: none !important; 323 | } 324 | 325 | .fade-nt-tooltip-enter-active, 326 | .fade-nt-tooltip-leave-active { 327 | transition: all 0.2s; 328 | } 329 | 330 | .fade-nt-tooltip-enter-from, 331 | .fade-nt-tooltip-leave-to { 332 | opacity: 0; 333 | } 334 | 335 | #nt-backdrop { 336 | position: fixed; 337 | top: 0; 338 | left: 0; 339 | width: 100%; 340 | height: 100%; 341 | background-color: rgba(0, 0, 0, 0.5); 342 | z-index: 9998; 343 | } 344 | 345 | #nt-tooltip { 346 | position: relative; 347 | background-color: #ffffff; 348 | border: 1px solid #e2e8f0; 349 | padding: 10px 15px; 350 | box-shadow: 351 | 0 2px 10px 0 rgba(0, 0, 0, 0.05), 352 | 0 2px 5px 0 rgba(0, 0, 0, 0.06); 353 | border-radius: 6px; 354 | z-index: 9999; 355 | max-width: 370px; 356 | display: flex; 357 | flex-direction: column; 358 | gap: 5px; 359 | } 360 | 361 | .nt-center { 362 | position: absolute !important; 363 | top: 50% !important; 364 | left: 50% !important; 365 | transform: translate(-50%, -50%) !important; 366 | } 367 | 368 | #nt-tooltip-header { 369 | display: flex; 370 | flex-direction: column; 371 | gap: 6px; 372 | } 373 | #nt-tooltip-header #nt-tooltip-title { 374 | font-size: 16px; 375 | line-height: normal; 376 | font-weight: 600; 377 | color: #0f172a; 378 | } 379 | #nt-tooltip-header #nt-tooltip-sub-text { 380 | line-height: normal; 381 | font-size: 14px; 382 | color: #64748b; 383 | } 384 | 385 | #nt-tooltip-body { 386 | font-size: 14px; 387 | color: #0f172a; 388 | } 389 | 390 | #nt-tooltip[data-popper-placement^="top"] #nt-arrow { 391 | bottom: -6px; 392 | } 393 | #nt-tooltip[data-popper-placement^="top"] #nt-arrow::before { 394 | content: ""; 395 | border-bottom: 1px solid #e2e8f0; 396 | border-right: 1px solid #e2e8f0; 397 | } 398 | 399 | #nt-tooltip[data-popper-placement^="bottom"] #nt-arrow { 400 | top: -6px; 401 | } 402 | #nt-tooltip[data-popper-placement^="bottom"] #nt-arrow::before { 403 | content: ""; 404 | border-top: 1px solid #e2e8f0; 405 | border-left: 1px solid #e2e8f0; 406 | } 407 | 408 | #nt-tooltip[data-popper-placement^="left"] #nt-arrow { 409 | right: -6px; 410 | } 411 | #nt-tooltip[data-popper-placement^="left"] #nt-arrow::before { 412 | content: ""; 413 | border-top: 1px solid #e2e8f0; 414 | border-right: 1px solid #e2e8f0; 415 | } 416 | 417 | #nt-tooltip[data-popper-placement^="right"] #nt-arrow { 418 | left: -6px; 419 | } 420 | #nt-tooltip[data-popper-placement^="right"] #nt-arrow::before { 421 | content: ""; 422 | border-bottom: 1px solid #e2e8f0; 423 | border-left: 1px solid #e2e8f0; 424 | } 425 | 426 | #nt-arrow { 427 | width: 12px; 428 | height: 12px; 429 | position: absolute; 430 | z-index: -99; 431 | } 432 | #nt-arrow::before { 433 | content: ""; 434 | width: 12px; 435 | height: 12px; 436 | background-color: #ffffff; 437 | transform: rotate(45deg); 438 | position: absolute; 439 | } 440 | 441 | .nt-highlight { 442 | outline: 1px solid #0ea5e9; 443 | outline-offset: 8px; 444 | border-radius: 4px; 445 | } 446 | 447 | .nt-actions { 448 | display: flex; 449 | gap: 8px; 450 | align-items: center; 451 | gap: 8px; 452 | margin-top: 14px; 453 | } 454 | .nt-actions button { 455 | display: inline-flex; 456 | align-items: center; 457 | justify-content: center; 458 | line-height: 0; 459 | gap: 8px; 460 | height: 32px; 461 | padding: 4px 14px; 462 | border-radius: 5px; 463 | background-color: #020617; 464 | color: #ffffff; 465 | font-size: 14px; 466 | font-weight: 500; 467 | transition: all 0.2s ease-in-out; 468 | white-space: nowrap; 469 | cursor: pointer; 470 | } 471 | .nt-actions button#nt-action-skip { 472 | background-color: transparent; 473 | color: #020617; 474 | border: 1px solid transparent; 475 | } 476 | .nt-actions button#nt-action-skip:hover { 477 | background-color: #e2e8f0; 478 | } 479 | .nt-actions button#nt-action-prev { 480 | background-color: #e2e8f0; 481 | color: #020617; 482 | border: 1px solid #e2e8f0; 483 | } 484 | .nt-actions button#nt-action-prev:hover { 485 | background-color: #020617; 486 | border-color: #e2e8f0; 487 | color: #ffffff; 488 | } 489 | .nt-actions button:hover { 490 | opacity: 0.85; 491 | } 492 | ``` 493 | -------------------------------------------------------------------------------- /playground/content/9.examples/autostart.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Autostart" 3 | description: "How start a tour automatically. Just pass the autoStart prop to the VTour component." 4 | icon: ph:shooting-star 5 | --- 6 | 7 | ## Autostart 8 | 9 | You can start a tour automatically when the page loads by passing the `autoStart` prop to the `VTour` component. 10 | 11 | :ExAutoStart 12 | 13 | ### The code 14 | 15 | ```vue 16 | 30 | 31 | 66 | ``` 67 | -------------------------------------------------------------------------------- /playground/content/9.examples/button.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Buttons 3 | description: See how you can customize the buttons in the tour. 4 | icon: ic:baseline-smart-button 5 | --- 6 | 7 | ## Custom Buttons 8 | 9 | We can change the look and feel of the buttons in the tour by passing an object to the respective button props. The props are: 10 | 11 | - nextButton 12 | - skipButton 13 | - prevButton 14 | - finishButton 15 | 16 | The color of the finish button can be changed by adding a style tag to the SFC. 17 | 18 | ```vue 19 | 27 | ``` 28 | 29 | :ExCustomButton{.mt-7} 30 | 31 | ### The code 32 | 33 | ```vue 34 | 59 | 60 | 126 | 127 | 135 | ``` 136 | -------------------------------------------------------------------------------- /playground/content/9.examples/callbacks-emits.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Callbacks & Emits" 3 | description: "See how you can use the different emits and callbacks available in the tour component." 4 | icon: gravity-ui:function 5 | --- 6 | 7 | ## Callbacks and Emits 8 | 9 | The following are functions that can be passed to the `VTour` component: 10 | 11 | - `complete`: This function is called when the tour is completed. (It should be passed as `@complete=""`) 12 | - `skip`: This function is called when the tour is skipped. (It should be passed as `@skip=""`) 13 | 14 | The following are emits that can be listened to: 15 | 16 | - `onTourStart`: This event is emitted when the tour starts. 17 | - `onTourEnd`: This event is emitted when the tour ends. 18 | 19 | :ExCallbackEmits 20 | 21 | ### The code 22 | 23 | ```vue 24 | 68 | 69 | 98 | ``` 99 | -------------------------------------------------------------------------------- /playground/content/9.examples/highlight.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Highlight 3 | description: Highlight elements on a page to guide users through a tour. 4 | icon: heroicons:camera 5 | --- 6 | 7 | ## Highlight 8 | 9 | Passing the `highlight` prop to the `VTour` component will allow you to highlight elements on the page as the tour progresses. 10 | 11 | Feel free to update the css classes to match your project's design system. 12 | 13 | :ExHighlight 14 | 15 | ### The code 16 | 17 | ```vue 18 | 33 | 34 | 63 | ``` 64 | -------------------------------------------------------------------------------- /playground/content/9.examples/html-elements.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "HTML elements" 3 | description: "How to provide HTML elements directly as target for TourStep" 4 | icon: ph:shooting-star 5 | --- 6 | 7 | ## HTML elements 8 | 9 | How to provide HTML elements directly as target for TourStep. This allows for greater flexibility in targeting elements. 10 | 11 | :ExHtmlElement 12 | 13 | ### The code 14 | 15 | ```vue [ExHtmlElement.vue] 16 | 41 | 42 | 92 | ``` 93 | -------------------------------------------------------------------------------- /playground/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 67 | -------------------------------------------------------------------------------- /playground/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | import Tour from "../src/module"; 2 | 3 | export default defineNuxtConfig({ 4 | $development: { 5 | vite: { 6 | optimizeDeps: { 7 | include: ["radix-vue", "vue-use-active-scroll", "tailwind-variants"], 8 | }, 9 | }, 10 | }, 11 | modules: [ 12 | Tour, 13 | "nuxt-content-twoslash", 14 | "@nuxtjs/tailwindcss", 15 | "@nuxtjs/color-mode", 16 | "@vueuse/nuxt", 17 | "@nuxt/content", 18 | "@nuxt/icon", 19 | ], 20 | 21 | tour: { prefix: "V" }, 22 | devtools: { enabled: true, componentInspector: false }, 23 | 24 | tailwindcss: { 25 | exposeConfig: true, 26 | cssPath: ["~/assets/css/tailwind.css", { injectPosition: "last" }], 27 | }, 28 | 29 | colorMode: { classSuffix: "" }, 30 | typescript: { shim: false }, 31 | 32 | imports: { 33 | imports: [ 34 | { from: "tailwind-variants", name: "tv" }, 35 | { from: "tailwind-variants", name: "VariantProps", type: true }, 36 | { from: "vue-sonner", name: "toast", as: "useSonner" }, 37 | ], 38 | }, 39 | 40 | content: { 41 | documentDriven: true, 42 | markdown: { 43 | toc: { depth: 3 }, 44 | }, 45 | highlight: { 46 | langs: ["js", "ts", "html", "scss", "css", "json", "vue", "vue-html", "bash", "sh", "shell"], 47 | theme: { 48 | default: "min-light", 49 | dark: "night-owl", 50 | }, 51 | }, 52 | navigation: { 53 | fields: ["icon"], 54 | }, 55 | }, 56 | 57 | build: { transpile: ["vue-sonner"] }, 58 | compatibilityDate: "2024-07-19", 59 | }); 60 | -------------------------------------------------------------------------------- /playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-module-playground", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "build": "nuxi build", 7 | "dev": "nuxi dev --host", 8 | "generate": "nuxi generate", 9 | "ui": "npx --yes ui-thing@latest add" 10 | }, 11 | "dependencies": { 12 | "@nuxt/content": "2.13.4", 13 | "nuxt": "3.17.2", 14 | "nuxt-content-twoslash": "^0.1.2", 15 | "radix-vue": "1.9.17", 16 | "tailwind-variants": "^1.0.0", 17 | "vue": "latest", 18 | "vue-router": "^4.5.1", 19 | "vue-sonner": "^1.3.2", 20 | "vue-use-active-scroll": "^1.1.3" 21 | }, 22 | "devDependencies": { 23 | "@ianvs/prettier-plugin-sort-imports": "4.4.1", 24 | "@iconify-json/bi": "^1.2.3", 25 | "@iconify-json/fluent": "^1.2.20", 26 | "@iconify-json/gravity-ui": "^1.2.5", 27 | "@iconify-json/heroicons": "^1.2.2", 28 | "@iconify-json/iconoir": "^1.2.7", 29 | "@iconify-json/lucide": "^1.2.41", 30 | "@iconify-json/ph": "^1.2.2", 31 | "@nuxt/icon": "^1.12.0", 32 | "@nuxtjs/color-mode": "^3.5.2", 33 | "@nuxtjs/tailwindcss": "^6.14.0", 34 | "@tailwindcss/typography": "^0.5.16", 35 | "@types/jump.js": "^1.0.6", 36 | "@vueuse/nuxt": "^13.1.0", 37 | "prettier": "^3.5.3", 38 | "prettier-plugin-tailwindcss": "^0.6.11", 39 | "tailwindcss-animate": "^1.0.7", 40 | "typescript": "^5.8.3" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /playground/public/nuxt-tour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BayBreezy/nuxt-tour/5df61fef7fdb73b47dd773ae60d2147d5498b76b/playground/public/nuxt-tour.png -------------------------------------------------------------------------------- /playground/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.nuxt/tsconfig.server.json" 3 | } 4 | -------------------------------------------------------------------------------- /playground/tailwind.config.js: -------------------------------------------------------------------------------- 1 | const { fontFamily } = require("tailwindcss/defaultTheme"); 2 | 3 | /**@type {import('tailwindcss').Config} */ 4 | module.exports = { 5 | content: ["./content/**/*.md"], 6 | darkMode: "class", 7 | theme: { 8 | extend: { 9 | container: { 10 | center: true, 11 | padding: { 12 | DEFAULT: "1rem", 13 | sm: "2rem", 14 | lg: "4rem", 15 | }, 16 | screens: { 17 | "2xl": "1300px", 18 | }, 19 | }, 20 | fontFamily: { 21 | sans: ["Inter var", "Inter", ...fontFamily.sans], 22 | mono: ["JetBrains Mono", "ui-monospace", ...fontFamily.mono], 23 | }, 24 | borderRadius: { 25 | lg: "var(--radius)", 26 | md: "calc(var(--radius) - 2px)", 27 | sm: "calc(var(--radius) - 4px)", 28 | }, 29 | keyframes: { 30 | "accordion-down": { 31 | from: { height: "0px" }, 32 | to: { height: "var(--radix-accordion-content-height)" }, 33 | }, 34 | "accordion-up": { 35 | from: { height: "var(--radix-accordion-content-height)" }, 36 | to: { height: "0px" }, 37 | }, 38 | fadeIn: { 39 | from: { opacity: "0" }, 40 | to: { opacity: "1" }, 41 | }, 42 | fadeOut: { 43 | from: { opacity: "1" }, 44 | to: { opacity: "0" }, 45 | }, 46 | "collapse-down": { 47 | from: { height: "0px" }, 48 | to: { height: "var(--radix-collapsible-content-height)" }, 49 | }, 50 | "collapse-up": { 51 | from: { height: "var(--radix-collapsible-content-height)" }, 52 | to: { height: "0px" }, 53 | }, 54 | }, 55 | animation: { 56 | "accordion-down": "accordion-down 0.2s ease-out", 57 | "accordion-up": "accordion-up 0.2s ease-out", 58 | fadeIn: "fadeIn 0.2s ease-out", 59 | fadeOut: "fadeOut 0.2s ease-out", 60 | "collapse-down": "collapse-down 0.2s ease-out", 61 | "collapse-up": "collapse-up 0.2s ease-out", 62 | }, 63 | colors: { 64 | border: "hsl(var(--border))", 65 | input: "hsl(var(--input))", 66 | ring: "hsl(var(--ring))", 67 | background: "hsl(var(--background))", 68 | foreground: "hsl(var(--foreground))", 69 | primary: { 70 | DEFAULT: "hsl(var(--primary))", 71 | foreground: "hsl(var(--primary-foreground))", 72 | }, 73 | secondary: { 74 | DEFAULT: "hsl(var(--secondary))", 75 | foreground: "hsl(var(--secondary-foreground))", 76 | }, 77 | destructive: { 78 | DEFAULT: "hsl(var(--destructive))", 79 | foreground: "hsl(var(--destructive-foreground))", 80 | }, 81 | muted: { 82 | DEFAULT: "hsl(var(--muted))", 83 | foreground: "hsl(var(--muted-foreground))", 84 | }, 85 | accent: { 86 | DEFAULT: "hsl(var(--accent))", 87 | foreground: "hsl(var(--accent-foreground))", 88 | }, 89 | popover: { 90 | DEFAULT: "hsl(var(--popover))", 91 | foreground: "hsl(var(--popover-foreground))", 92 | }, 93 | card: { 94 | DEFAULT: "hsl(var(--card))", 95 | foreground: "hsl(var(--card-foreground))", 96 | }, 97 | }, 98 | typography: ({ theme }) => ({ 99 | DEFAULT: { 100 | css: { 101 | "--tw-prose-body": theme("colors.foreground"), 102 | "--tw-prose-headings": theme("colors.foreground"), 103 | "--tw-prose-lead": theme("colors.muted.foreground"), 104 | "--tw-prose-links": theme("colors.foreground"), 105 | "--tw-prose-bold": theme("colors.foreground"), 106 | "--tw-prose-counters": theme("colors.muted.foreground"), 107 | "--tw-prose-bullets": theme("colors.primary.DEFAULT / 50%"), 108 | "--tw-prose-hr": theme("colors.border"), 109 | "--tw-prose-quotes": theme("colors.foreground"), 110 | "--tw-prose-quote-borders": theme("colors.border"), 111 | "--tw-prose-captions": theme("colors.muted.foreground"), 112 | "--tw-prose-kbd": theme("colors.foreground"), 113 | "--tw-prose-kbd-shadows": theme("colors.foreground"), 114 | "--tw-prose-pre-bg": theme("colors.background"), 115 | "--tw-prose-th-borders": theme("colors.border"), 116 | "--tw-prose-td-borders": theme("colors.border"), 117 | "--tw-prose-invert-body": theme("colors.foreground"), 118 | "--tw-prose-invert-headings": theme("colors.foreground"), 119 | "--tw-prose-invert-lead": theme("colors.muted.foreground"), 120 | "--tw-prose-invert-links": theme("colors.foreground"), 121 | "--tw-prose-invert-bold": theme("colors.foreground"), 122 | "--tw-prose-invert-counters": theme("colors.muted.foreground"), 123 | "--tw-prose-invert-bullets": theme("colors.primary.DEFAULT / 50%"), 124 | "--tw-prose-invert-hr": theme("colors.border"), 125 | "--tw-prose-invert-quotes": theme("colors.foreground"), 126 | "--tw-prose-invert-quote-borders": theme("colors.border"), 127 | "--tw-prose-invert-captions": theme("colors.muted.foreground"), 128 | "--tw-prose-invert-kbd": theme("colors.foreground"), 129 | "--tw-prose-invert-kbd-shadows": theme("colors.foreground"), 130 | "--tw-prose-invert-pre-bg": theme("colors.foreground / 10%"), 131 | "--tw-prose-invert-th-borders": theme("colors.border"), 132 | "--tw-prose-invert-td-borders": theme("colors.border"), 133 | "code::before": { 134 | content: "", 135 | }, 136 | "code::after": { 137 | content: "", 138 | }, 139 | }, 140 | }, 141 | }), 142 | }, 143 | }, 144 | plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography")], 145 | }; 146 | -------------------------------------------------------------------------------- /playground/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.nuxt/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /playground/ui-thing.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | nuxtVersion: 3, 3 | theme: "zinc", 4 | tailwindCSSLocation: "assets/css/tailwind.css", 5 | tailwindConfigLocation: "tailwind.config.js", 6 | componentsLocation: "components/Ui", 7 | composablesLocation: "composables", 8 | utilsLocation: "utils", 9 | force: true, 10 | useDefaultFilename: true, 11 | packageManager: "npm", 12 | }; 13 | -------------------------------------------------------------------------------- /playground/utils/shared.styles.ts: -------------------------------------------------------------------------------- 1 | // Add here because button styles are used in several components 2 | export const buttonStyles = tv({ 3 | base: "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", 4 | variants: { 5 | variant: { 6 | default: "bg-primary text-primary-foreground hover:bg-primary/90", 7 | destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", 8 | outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground", 9 | secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", 10 | ghost: "hover:bg-accent hover:text-accent-foreground", 11 | link: "text-primary underline-offset-4 hover:underline", 12 | }, 13 | size: { 14 | default: "h-10 px-4 py-2", 15 | sm: "h-9 rounded-md px-3", 16 | lg: "h-11 rounded-md px-8", 17 | "icon-sm": "h-9 w-9", 18 | icon: "h-10 w-10", 19 | }, 20 | disabled: { 21 | true: "pointer-events-none opacity-50", 22 | }, 23 | }, 24 | defaultVariants: { 25 | variant: "default", 26 | size: "default", 27 | }, 28 | }); 29 | -------------------------------------------------------------------------------- /src/module.ts: -------------------------------------------------------------------------------- 1 | import { addComponent, createResolver, defineNuxtModule, installModule } from "@nuxt/kit"; 2 | 3 | export interface TourOptions { 4 | /** 5 | * The prefix to use for the component name 6 | * 7 | * @default "V" 8 | */ 9 | prefix?: string; 10 | /** 11 | * Inject the default sass file 12 | * 13 | * Feel free to create your own 🙂. Just get the class names correct 14 | * 15 | * @default true 16 | */ 17 | injectSass?: boolean; 18 | } 19 | 20 | export default defineNuxtModule({ 21 | meta: { 22 | name: "nuxt-tour", 23 | configKey: "tour", 24 | compatibility: { 25 | nuxt: ">=3.0", 26 | }, 27 | }, 28 | // Default configuration options of the Nuxt module 29 | defaults: { 30 | prefix: "V", 31 | injectSass: true, 32 | }, 33 | async setup(options, nuxt) { 34 | const resolver = createResolver(import.meta.url); 35 | 36 | const runtimeDir = resolver.resolve("./runtime"); 37 | nuxt.options.build.transpile.push(runtimeDir); 38 | nuxt.options.build.transpile.push("@popperjs/core"); 39 | nuxt.options.alias["#nuxt-tour"] = runtimeDir; 40 | 41 | const isDevelopment = runtimeDir.endsWith("src/runtime") || runtimeDir.endsWith("src\\runtime"); 42 | 43 | const extension = isDevelopment ? "scss" : "css"; 44 | if (options.injectSass) { 45 | // add sass files to the top of the css array 46 | nuxt.options.css.unshift(resolver.resolve(`./runtime/scss/tour.${extension}`)); 47 | } 48 | 49 | // install nuxt-icon module 50 | await installModule("@nuxt/icon"); 51 | 52 | // optimize deps in dev mode 53 | if (isDevelopment) { 54 | nuxt.hook("vite:extendConfig", (config) => { 55 | config.optimizeDeps?.include?.push( 56 | "@popperjs/core", 57 | "@vueuse/integrations/useFocusTrap", 58 | "jump.js", 59 | "lodash-es" 60 | ); 61 | }); 62 | } 63 | 64 | addComponent({ 65 | filePath: resolver.resolve("./runtime/components/Tour.vue"), 66 | name: options.prefix ? `${options.prefix}Tour` : "Tour", 67 | }); 68 | }, 69 | }); 70 | -------------------------------------------------------------------------------- /src/runtime/components/Tour.vue: -------------------------------------------------------------------------------- 1 | 276 | 277 | 778 | -------------------------------------------------------------------------------- /src/runtime/props.ts: -------------------------------------------------------------------------------- 1 | import type { Modifier, OptionsGeneric } from "@popperjs/core"; 2 | import type { ComputedRef, MaybeRefOrGetter, Ref } from "#imports"; 3 | import type { Options } from "jump.js"; 4 | 5 | export type TourEmits = { 6 | /** 7 | * Emitted when the tour starts 8 | */ 9 | onTourStart: []; 10 | /** 11 | * Emitted when the tour ends 12 | */ 13 | onTourEnd: []; 14 | }; 15 | 16 | export type ButtonProp = { 17 | /** 18 | * The label of the button 19 | */ 20 | label?: string; 21 | /** 22 | * The icon displayed to the right of the button 23 | * 24 | * Any icon from the [Icones](https://icones.netlify.app/) website can be used here 25 | */ 26 | rightIcon?: string; 27 | /** 28 | * The icon displayed to the left of the button 29 | * 30 | * Any icon from the [Icones](https://icones.netlify.app/) website can be used here 31 | */ 32 | leftIcon?: string; 33 | }; 34 | 35 | export type TourStep = { 36 | /** 37 | * The element that the step should target 38 | * 39 | * This can be a CSS selector, a ref of type string 40 | * 41 | * If this is not passed, the step will be positioned in the center of the screen 42 | */ 43 | target?: string | undefined | null | MaybeRefOrGetter | ComputedRef | HTMLElement; 44 | /** 45 | * The title of the step 46 | */ 47 | title?: string | HTMLElement | Ref | Ref | undefined | null; 48 | /** 49 | * The subtext of the step 50 | */ 51 | subText?: string | HTMLElement | Ref | Ref | undefined | null; 52 | /** 53 | * The content of the step 54 | */ 55 | body?: string | HTMLElement | Ref | Ref | undefined | null; 56 | /** 57 | * The configuration to pass to popperjs 58 | */ 59 | popperConfig?: Partial>>> | undefined; 60 | /** 61 | * The function that should be called when `Next` button is clicked 62 | */ 63 | onNext?: () => void | (() => Promise); 64 | /** 65 | * The function that should be called when `Prev` button is clicked 66 | */ 67 | onPrev?: () => void | (() => Promise); 68 | /** 69 | * The function that should be called when the step is displayed 70 | */ 71 | onShow?: () => void | (() => Promise); 72 | /** 73 | * The prefix that will be added to the slot name 74 | */ 75 | slot?: string; 76 | /** 77 | * Determines if the step should show a backdrop or not 78 | * 79 | * @default false 80 | */ 81 | backdrop?: boolean; 82 | }; 83 | 84 | export type TourProps = { 85 | /** 86 | * The name of the tour 87 | * @default "default" 88 | */ 89 | name?: string; 90 | /** 91 | * The steps of the tour 92 | */ 93 | steps: TourStep[]; 94 | /** 95 | * The function that should be called when the tour is completed 96 | */ 97 | onComplete?: () => void | (() => Promise); 98 | /** 99 | * The function that should be called when the tour is skipped 100 | */ 101 | onSkip?: () => void | (() => Promise); 102 | /** 103 | * Determines if the tour should be started automatically 104 | * @default false 105 | */ 106 | autoStart?: boolean; 107 | /** 108 | * The delay before the tour starts. This will only work if `autoStart` is `true` 109 | * @default 0 110 | */ 111 | startDelay?: number | string | null; 112 | /** 113 | * When this is `true`, the target element will be highlighted 114 | */ 115 | highlight?: boolean; 116 | /** 117 | * The configuration of the `Next` button 118 | */ 119 | nextButton?: ButtonProp; 120 | /** 121 | * The configuration of the `Skip` button 122 | */ 123 | skipButton?: ButtonProp; 124 | /** 125 | * The configuration of the `Prev` button 126 | */ 127 | prevButton?: ButtonProp; 128 | /** 129 | * The configuration of the `Finish` button 130 | */ 131 | finishButton?: ButtonProp; 132 | /** 133 | * Prop used to determine if the arrow should be shown or not 134 | * @default true 135 | */ 136 | showArrow?: boolean; 137 | /** 138 | * The configuration to pass to jump.js 139 | * 140 | * @default { duration: 300, offset: -100 } 141 | */ 142 | jumpOptions?: Options; 143 | /** 144 | * Determines if focus should be trapped within the tour 145 | * 146 | * @default true 147 | */ 148 | trapFocus?: boolean; 149 | /** 150 | * Determines if the scroll should be locked when the tour is active 151 | * 152 | * @default true 153 | */ 154 | lockScroll?: boolean; 155 | /** 156 | * Determines if the tour should show a backdrop or not 157 | * 158 | * @default false 159 | */ 160 | backdrop?: boolean; 161 | }; 162 | -------------------------------------------------------------------------------- /src/runtime/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | $ntBorderColor: #e2e8f0 !default; 2 | $ntWhite: #ffffff !default; 3 | $ntTextColor: #0f172a !default; 4 | $ntSubTextColor: #64748b !default; 5 | $ntHighlightColor: #0ea5e9 !default; 6 | 7 | // Tooltip base 8 | $ntTooltipPosition: relative !default; 9 | $ntTooltipBackgroundColor: $ntWhite !default; 10 | $ntTooltipBorder: 1px solid $ntBorderColor !default; 11 | $ntTooltipPadding: 10px 15px !default; 12 | $ntTooltipBoxShadow: 13 | 0 2px 10px 0 rgba(0, 0, 0, 0.05), 14 | 0 2px 5px 0 rgba(0, 0, 0, 0.06) !default; 15 | $ntTooltipBorderRadius: 6px !default; 16 | $ntTooltipZIndex: 9999 !default; 17 | $ntTooltipMaxWidth: 370px !default; 18 | $ntTooltipDisplay: flex !default; 19 | $ntTooltipFlexDirection: column !default; 20 | $ntTooltipGap: 5px !default; 21 | 22 | // Tooltip Header 23 | $ntTooltipHeaderDisplay: flex !default; 24 | $ntTooltipHeaderFlexDirection: column !default; 25 | $ntTooltipHeaderGap: 6px !default; 26 | 27 | // Tooltip Title 28 | $ntTooltipTitleFontSize: 16px !default; 29 | $ntTooltipTitleLineHeight: normal !default; 30 | $ntTooltipTitleFontWeight: 600 !default; 31 | $ntTooltipTitleColor: $ntTextColor !default; 32 | 33 | // Tooltip subtext 34 | $ntTooltipSubTextFontSize: 14px !default; 35 | $ntTooltipSubTextLineHeight: normal !default; 36 | $ntTooltipSubTextColor: $ntSubTextColor !default; 37 | 38 | // Tooltip body 39 | $ntTooltipBodyFontSize: 14px !default; 40 | $ntTooltipBodyColor: $ntTextColor !default; 41 | 42 | // Tooltip arrow 43 | $ntTooltipArrowSize: 12px !default; 44 | $ntTooltipArrowBorder: 1px solid $ntBorderColor !default; 45 | $ntTooltipArrowBackgroundColor: $ntWhite !default; 46 | 47 | // Highlight 48 | $ntHighlightOffset: 8px !default; 49 | $ntHighlightOutlineRadius: 4px !default; 50 | $ntHighlightOutline: 1px solid $ntHighlightColor !default; 51 | 52 | // Action - Button container 53 | $ntActionDisplay: flex !default; 54 | $ntActionGap: 8px !default; 55 | $ntActionAlignItems: center !default; 56 | $ntActionGap: 8px !default; 57 | $ntActionMarginTop: 14px !default; 58 | 59 | // Action - Button 60 | $ntButtonDisplay: inline-flex !default; 61 | $ntButtonAlignItems: center !default; 62 | $ntButtonJustifyContent: center !default; 63 | $ntButtonLineHeight: 0 !default; 64 | $ntButtonGap: 8px !default; 65 | $ntButtonHeight: 32px !default; 66 | $ntButtonPadding: 4px 14px !default; 67 | $ntButtonBorderRadius: 5px !default; 68 | $ntButtonFontSize: 14px !default; 69 | $ntButtonFontWeight: 500 !default; 70 | $ntButtonTransition: all 0.2s ease-in-out !default; 71 | 72 | // Next - Finish button 73 | $ntButtonBackgroundColor: #020617 !default; 74 | $ntButtonColor: $ntWhite !default; 75 | 76 | // Skip button 77 | $ntButtonSkipBackgroundColor: transparent !default; 78 | $ntButtonSkipColor: $ntButtonBackgroundColor !default; 79 | $ntButtonSkipBorder: 1px solid $ntButtonSkipBackgroundColor !default; 80 | $ntButtonSkipHoverBackgroundColor: $ntBorderColor !default; 81 | 82 | // Prev button 83 | $ntButtonPrevBackgroundColor: $ntBorderColor !default; 84 | $ntButtonPrevColor: $ntButtonBackgroundColor !default; 85 | $ntButtonPrevBorder: 1px solid $ntBorderColor !default; 86 | $ntButtonPrevHoverBackgroundColor: $ntButtonBackgroundColor !default; 87 | $ntButtonPrevHoverBorderColor: $ntButtonPrevBackgroundColor !default; 88 | $ntButtonPrevHoverColor: $ntWhite !default; 89 | 90 | // Backdrop 91 | $ntBackdropZIndex: 9998 !default; 92 | $ntBackdropBackground: rgba(0, 0, 0, 0.5) !default; 93 | -------------------------------------------------------------------------------- /src/runtime/scss/tour.scss: -------------------------------------------------------------------------------- 1 | @use "sass:math"; 2 | @use "variables"; 3 | 4 | [data-hidden] { 5 | display: none !important; 6 | } 7 | 8 | .fade-nt-tooltip-enter-active, 9 | .fade-nt-tooltip-leave-active { 10 | transition: all 0.2s; 11 | } 12 | 13 | .fade-nt-tooltip-enter-from, 14 | .fade-nt-tooltip-leave-to { 15 | opacity: 0; 16 | } 17 | 18 | #nt-backdrop { 19 | position: fixed; 20 | top: 0; 21 | left: 0; 22 | width: 100%; 23 | height: 100%; 24 | background-color: variables.$ntBackdropBackground; 25 | z-index: variables.$ntBackdropZIndex; 26 | } 27 | 28 | #nt-tooltip { 29 | position: variables.$ntTooltipPosition; 30 | background-color: variables.$ntTooltipBackgroundColor; 31 | border: variables.$ntTooltipBorder; 32 | padding: variables.$ntTooltipPadding; 33 | box-shadow: variables.$ntTooltipBoxShadow; 34 | border-radius: variables.$ntTooltipBorderRadius; 35 | z-index: variables.$ntTooltipZIndex; 36 | max-width: variables.$ntTooltipMaxWidth; 37 | display: variables.$ntTooltipDisplay; 38 | flex-direction: variables.$ntTooltipFlexDirection; 39 | gap: variables.$ntTooltipGap; 40 | } 41 | 42 | .nt-center { 43 | position: absolute !important; 44 | top: 50% !important; 45 | left: 50% !important; 46 | transform: translate(-50%, -50%) !important; 47 | } 48 | 49 | #nt-tooltip-header { 50 | display: variables.$ntTooltipHeaderDisplay; 51 | flex-direction: variables.$ntTooltipHeaderFlexDirection; 52 | gap: variables.$ntTooltipHeaderGap; 53 | 54 | #nt-tooltip-title { 55 | font-size: variables.$ntTooltipTitleFontSize; 56 | line-height: variables.$ntTooltipTitleLineHeight; 57 | font-weight: variables.$ntTooltipTitleFontWeight; 58 | color: variables.$ntTooltipTitleColor; 59 | } 60 | 61 | #nt-tooltip-sub-text { 62 | line-height: variables.$ntTooltipSubTextLineHeight; 63 | font-size: variables.$ntTooltipSubTextFontSize; 64 | color: variables.$ntTooltipSubTextColor; 65 | } 66 | } 67 | 68 | #nt-tooltip-body { 69 | font-size: variables.$ntTooltipBodyFontSize; 70 | color: variables.$ntTooltipBodyColor; 71 | } 72 | 73 | #nt-tooltip[data-popper-placement^="top"] { 74 | #nt-arrow { 75 | bottom: math.div(-(variables.$ntTooltipArrowSize), 2); 76 | &::before { 77 | content: ""; 78 | border-bottom: variables.$ntTooltipArrowBorder; 79 | border-right: variables.$ntTooltipArrowBorder; 80 | } 81 | } 82 | } 83 | 84 | #nt-tooltip[data-popper-placement^="bottom"] { 85 | #nt-arrow { 86 | top: math.div(-(variables.$ntTooltipArrowSize), 2); 87 | &::before { 88 | content: ""; 89 | border-top: variables.$ntTooltipArrowBorder; 90 | border-left: variables.$ntTooltipArrowBorder; 91 | } 92 | } 93 | } 94 | 95 | #nt-tooltip[data-popper-placement^="left"] { 96 | #nt-arrow { 97 | right: math.div(-(variables.$ntTooltipArrowSize), 2); 98 | &::before { 99 | content: ""; 100 | border-top: variables.$ntTooltipArrowBorder; 101 | border-right: variables.$ntTooltipArrowBorder; 102 | } 103 | } 104 | } 105 | 106 | #nt-tooltip[data-popper-placement^="right"] { 107 | #nt-arrow { 108 | left: math.div(-(variables.$ntTooltipArrowSize), 2); 109 | &::before { 110 | content: ""; 111 | border-bottom: variables.$ntTooltipArrowBorder; 112 | border-left: variables.$ntTooltipArrowBorder; 113 | } 114 | } 115 | } 116 | 117 | #nt-arrow { 118 | width: variables.$ntTooltipArrowSize; 119 | height: variables.$ntTooltipArrowSize; 120 | position: absolute; 121 | z-index: -99; 122 | 123 | &::before { 124 | content: ""; 125 | width: variables.$ntTooltipArrowSize; 126 | height: variables.$ntTooltipArrowSize; 127 | background-color: variables.$ntTooltipArrowBackgroundColor; 128 | transform: rotate(45deg); 129 | position: absolute; 130 | } 131 | } 132 | 133 | .nt-highlight { 134 | outline: variables.$ntHighlightOutline; 135 | outline-offset: variables.$ntHighlightOffset; 136 | border-radius: variables.$ntHighlightOutlineRadius; 137 | } 138 | 139 | .nt-actions { 140 | display: variables.$ntActionDisplay; 141 | gap: variables.$ntActionGap; 142 | align-items: variables.$ntActionAlignItems; 143 | gap: variables.$ntActionGap; 144 | margin-top: variables.$ntActionMarginTop; 145 | 146 | button { 147 | display: variables.$ntButtonDisplay; 148 | align-items: variables.$ntButtonAlignItems; 149 | justify-content: variables.$ntButtonJustifyContent; 150 | line-height: variables.$ntButtonLineHeight; 151 | gap: variables.$ntButtonGap; 152 | height: variables.$ntButtonHeight; 153 | padding: variables.$ntButtonPadding; 154 | border-radius: variables.$ntButtonBorderRadius; 155 | background-color: variables.$ntButtonBackgroundColor; 156 | color: variables.$ntButtonColor; 157 | font-size: variables.$ntButtonFontSize; 158 | font-weight: variables.$ntButtonFontWeight; 159 | transition: variables.$ntButtonTransition; 160 | white-space: nowrap; 161 | cursor: pointer; 162 | 163 | &#nt-action-skip { 164 | background-color: variables.$ntButtonSkipBackgroundColor; 165 | color: variables.$ntButtonSkipColor; 166 | border: variables.$ntButtonSkipBorder; 167 | 168 | &:hover { 169 | background-color: variables.$ntButtonSkipHoverBackgroundColor; 170 | } 171 | } 172 | 173 | &#nt-action-prev { 174 | background-color: variables.$ntButtonPrevBackgroundColor; 175 | color: variables.$ntButtonPrevColor; 176 | border: variables.$ntButtonPrevBorder; 177 | 178 | &:hover { 179 | background-color: variables.$ntButtonPrevHoverBackgroundColor; 180 | border-color: variables.$ntButtonPrevHoverBorderColor; 181 | color: variables.$ntButtonPrevHoverColor; 182 | } 183 | } 184 | 185 | &:hover { 186 | opacity: 0.85; 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /test/basic.test.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from "node:url"; 2 | import { $fetch, setup } from "@nuxt/test-utils/e2e"; 3 | import { describe, expect, it } from "vitest"; 4 | 5 | describe("Display Tour To User", async () => { 6 | await setup({ 7 | rootDir: fileURLToPath(new URL("./fixtures/basic", import.meta.url)), 8 | }); 9 | 10 | it("loads the page properly", async () => { 11 | // Get response to a server-rendered page with `$fetch`. 12 | const html: string = await $fetch("/"); 13 | // Expect it to have the nt-tooltip id in the DOM 14 | expect(html).toContain("
"); 15 | }); 16 | 17 | it("has the target class on the h1 element", async () => { 18 | const html: string = await $fetch("/"); 19 | // Expect it to have the target class on the h1 element 20 | expect(html).toContain('class="target"'); 21 | }); 22 | 23 | it( 24 | "automatically starts the tour", 25 | async () => { 26 | const html: string = await $fetch("/"); 27 | expect(html).toContain('role="tooltip"'); 28 | }, 29 | { timeout: 20000 } 30 | ); 31 | 32 | it("has correct content inside the step", async () => { 33 | const html: string = await $fetch("/"); 34 | // Expect it to have the nt-tooltip id in the DOM 35 | expect(html).toContain("Welcome to the tour"); 36 | expect(html).toContain("This is the subtext"); 37 | expect(html).toContain("This is the first step"); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/fixtures/basic/app.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | 23 | 31 | -------------------------------------------------------------------------------- /test/fixtures/basic/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | import MyModule from "../../../src/module"; 2 | 3 | export default defineNuxtConfig({ 4 | modules: [MyModule], 5 | tour: { prefix: "V", injectSass: true }, 6 | }); 7 | -------------------------------------------------------------------------------- /test/fixtures/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "basic", 4 | "type": "module" 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.nuxt/tsconfig.json" 3 | } 4 | --------------------------------------------------------------------------------