diff --git a/.eslintrc.js b/.eslintrc.js
index 04081bc90..e02011018 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -53,6 +53,21 @@ module.exports = {
asyncArrow: 'always'
}],
'spaced-comment': 'off',
+ 'vue/attributes-order': ['error', {
+ order: [
+ 'DEFINITION',
+ 'LIST_RENDERING',
+ 'CONDITIONALS',
+ 'RENDER_MODIFIERS',
+ 'GLOBAL',
+ ['UNIQUE', 'SLOT'],
+ 'TWO_WAY_BINDING',
+ ['OTHER_DIRECTIVES', 'OTHER_ATTR'],
+ 'EVENTS',
+ 'CONTENT'
+ ],
+ alphabetical: false
+ }],
'vue/first-attribute-linebreak': 'off',
'vue/html-closing-bracket-newline': ['error', {
singleline: 'never',
diff --git a/package-lock.json b/package-lock.json
index 12ccaca3e..be11944ac 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
"name": "odk-central-frontend",
"version": "0.1.0",
"dependencies": {
+ "@floating-ui/dom": "^1.1.0",
"axios": "^0.22.0",
"bootstrap": "~3",
"dompurify": "~2",
@@ -507,6 +508,19 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/@floating-ui/core": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.1.0.tgz",
+ "integrity": "sha512-zbsLwtnHo84w1Kc8rScAo5GMk1GdecSlrflIbfnEBJwvTSj1SL6kkOYV+nHraMCPEy+RNZZUaZyL8JosDGCtGQ=="
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.1.0.tgz",
+ "integrity": "sha512-TSogMPVxbRe77QCj1dt8NmRiJasPvuc+eT5jnJ6YpLqgOD2zXc5UA3S1qwybN+GVCDNdKfpKy1oj8RpzLJvh6A==",
+ "dependencies": {
+ "@floating-ui/core": "^1.0.5"
+ }
+ },
"node_modules/@hapi/hoek": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
@@ -13029,6 +13043,19 @@
}
}
},
+ "@floating-ui/core": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.1.0.tgz",
+ "integrity": "sha512-zbsLwtnHo84w1Kc8rScAo5GMk1GdecSlrflIbfnEBJwvTSj1SL6kkOYV+nHraMCPEy+RNZZUaZyL8JosDGCtGQ=="
+ },
+ "@floating-ui/dom": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.1.0.tgz",
+ "integrity": "sha512-TSogMPVxbRe77QCj1dt8NmRiJasPvuc+eT5jnJ6YpLqgOD2zXc5UA3S1qwybN+GVCDNdKfpKy1oj8RpzLJvh6A==",
+ "requires": {
+ "@floating-ui/core": "^1.0.5"
+ }
+ },
"@hapi/hoek": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
diff --git a/package.json b/package.json
index 32312205b..0c7ce8cbc 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"pre-commit": "node bin/transifex/restructure.js && git diff --exit-code -- transifex/strings_en.json"
},
"dependencies": {
+ "@floating-ui/dom": "^1.1.0",
"axios": "^0.22.0",
"bootstrap": "~3",
"dompurify": "~2",
diff --git a/src/assets/scss/app.scss b/src/assets/scss/app.scss
index d1cfae79f..8c1ec7e72 100644
--- a/src/assets/scss/app.scss
+++ b/src/assets/scss/app.scss
@@ -74,6 +74,23 @@ em:lang(ja) {
font-weight: bold;
}
+.tooltip {
+ /* v-tooltip.aria-describedby tooltips are rendered before they are shown
+ on-screen. `display` is not set to `none` for those tooltips. Instead, they
+ are transparent. However, we do need to position them: otherwise, they would
+ result in extra space at the bottom of the page. I tried using the sr-only
+ class, but that resulted in Floating UI miscalculating the position of the
+ tooltip. Instead, tooltips will be positioned at the top of the page. */
+ top: 0;
+ // Move the tooltip to the left so that it doesn't obstruct the navbar.
+ left: -1000px;
+}
+.tooltip-inner {
+ overflow-wrap: break-word;
+ // Allow the text to have line breaks.
+ white-space: pre-line;
+}
+
////////////////////////////////////////////////////////////////////////////////
@@ -198,8 +215,8 @@ a, .btn-link {
a {
&.disabled, fieldset[disabled] & {
- // Not specifying pointer-events so that the cursor and any title attribute
- // is shown.
+ // Not specifying pointer-events so that the cursor and any tooltip is
+ // shown.
&.btn { color: #fff; }
}
diff --git a/src/components/actor-link.vue b/src/components/actor-link.vue
index 3bc09fc79..a7cbea94a 100644
--- a/src/components/actor-link.vue
+++ b/src/components/actor-link.vue
@@ -10,8 +10,8 @@ including this file, may be copied, modified, propagated, or distributed
except according to the terms contained in the LICENSE file.
-->
-