feat: improved checkbox #1800
|
@ -120,7 +120,7 @@ describe('Namepaces', () => {
|
|||
.should('not.contain', 'Archived')
|
||||
|
||||
// Show archived
|
||||
cy.get('[data-cy="show-archived-check"] label.check span')
|
||||
cy.get('[data-cy="show-archived-check"] .fancycheckbox__content')
|
||||
.should('be.visible')
|
||||
.click()
|
||||
cy.get('[data-cy="show-archived-check"] input')
|
||||
|
@ -129,7 +129,7 @@ describe('Namepaces', () => {
|
|||
.should('contain', 'Archived')
|
||||
|
||||
// Don't show archived
|
||||
cy.get('[data-cy="show-archived-check"] label.check span')
|
||||
cy.get('[data-cy="show-archived-check"] .fancycheckbox__content')
|
||||
.should('be.visible')
|
||||
.click()
|
||||
cy.get('[data-cy="show-archived-check"] input')
|
||||
|
|
|
@ -22,10 +22,10 @@ describe('Project View Table', () => {
|
|||
cy.get('.project-table .filter-container .items .button')
|
||||
.contains('Columns')
|
||||
.click()
|
||||
cy.get('.project-table .filter-container .card.columns-filter .card-content .fancycheckbox .check')
|
||||
cy.get('.project-table .filter-container .card.columns-filter .card-content .fancycheckbox')
|
||||
.contains('Priority')
|
||||
.click()
|
||||
cy.get('.project-table .filter-container .card.columns-filter .card-content .fancycheckbox .check')
|
||||
cy.get('.project-table .filter-container .card.columns-filter .card-content .fancycheckbox')
|
||||
.contains('Done')
|
||||
.click()
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ describe('Task', () => {
|
|||
TaskFactory.create(1)
|
||||
|
||||
cy.visit('/projects/1/list')
|
||||
cy.get('.tasks .task .fancycheckbox label.check')
|
||||
cy.get('.tasks .task .fancycheckbox')
|
||||
.first()
|
||||
.click()
|
||||
cy.get('.global-notification')
|
||||
|
|
|
@ -3,6 +3,16 @@
|
|||
/// <reference types="cypress" />
|
||||
/// <reference types="@histoire/plugin-vue/components" />
|
||||
|
||||
declare module 'postcss-focus-within/browser' {
|
||||
import focusWithinInit from 'postcss-focus-within/browser'
|
||||
export default focusWithinInit
|
||||
}
|
||||
|
||||
declare module 'css-has-pseudo/browser' {
|
||||
import cssHasPseudo from 'css-has-pseudo/browser'
|
||||
export default cssHasPseudo
|
||||
}
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_IS_ONLINE: boolean
|
||||
}
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
"flatpickr": "4.6.13",
|
||||
"flexsearch": "0.7.31",
|
||||
"floating-vue": "2.0.0-beta.20",
|
||||
"focus-within": "3.0.2",
|
||||
"highlight.js": "11.7.0",
|
||||
"is-touch-device": "1.0.1",
|
||||
"klona": "2.0.6",
|
||||
|
@ -102,7 +101,6 @@
|
|||
"@types/codemirror": "5.60.7",
|
||||
"@types/dompurify": "3.0.0",
|
||||
"@types/flexsearch": "0.7.3",
|
||||
"@types/focus-within": "1.0.1",
|
||||
"@types/lodash.debounce": "4.0.7",
|
||||
"@types/marked": "4.0.8",
|
||||
"@types/node": "18.15.11",
|
||||
|
@ -117,6 +115,7 @@
|
|||
"autoprefixer": "10.4.14",
|
||||
"browserslist": "4.21.5",
|
||||
"caniuse-lite": "1.0.30001470",
|
||||
"css-has-pseudo": "5.0.2",
|
||||
"csstype": "3.1.1",
|
||||
"cypress": "12.9.0",
|
||||
"esbuild": "0.17.14",
|
||||
|
@ -128,6 +127,7 @@
|
|||
"postcss": "8.4.21",
|
||||
"postcss-easing-gradients": "3.0.1",
|
||||
"postcss-easings": "3.0.1",
|
||||
"postcss-focus-within": "7.0.2",
|
||||
"postcss-preset-env": "8.2.0",
|
||||
"rollup": "3.20.2",
|
||||
"rollup-plugin-visualizer": "5.9.0",
|
||||
|
|
|
@ -87,9 +87,6 @@ dependencies:
|
|||
floating-vue:
|
||||
specifier: 2.0.0-beta.20
|
||||
version: 2.0.0-beta.20(vue@3.2.47)
|
||||
focus-within:
|
||||
specifier: 3.0.2
|
||||
version: 3.0.2
|
||||
highlight.js:
|
||||
specifier: 11.7.0
|
||||
version: 11.7.0
|
||||
|
@ -173,9 +170,6 @@ devDependencies:
|
|||
'@types/flexsearch':
|
||||
specifier: 0.7.3
|
||||
version: 0.7.3
|
||||
'@types/focus-within':
|
||||
specifier: 1.0.1
|
||||
version: 1.0.1
|
||||
'@types/lodash.debounce':
|
||||
specifier: 4.0.7
|
||||
version: 4.0.7
|
||||
|
@ -218,6 +212,9 @@ devDependencies:
|
|||
caniuse-lite:
|
||||
specifier: 1.0.30001470
|
||||
version: 1.0.30001470
|
||||
css-has-pseudo:
|
||||
specifier: 5.0.2
|
||||
version: 5.0.2(postcss@8.4.21)
|
||||
csstype:
|
||||
specifier: 3.1.1
|
||||
version: 3.1.1
|
||||
|
@ -251,6 +248,9 @@ devDependencies:
|
|||
postcss-easings:
|
||||
specifier: 3.0.1
|
||||
version: 3.0.1(postcss@8.4.21)
|
||||
postcss-focus-within:
|
||||
specifier: 7.0.2
|
||||
version: 7.0.2(postcss@8.4.21)
|
||||
postcss-preset-env:
|
||||
specifier: 8.2.0
|
||||
version: 8.2.0(postcss@8.4.21)
|
||||
|
@ -2245,7 +2245,7 @@ packages:
|
|||
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
|
||||
dependencies:
|
||||
eslint: 8.37.0
|
||||
eslint-visitor-keys: 3.3.0
|
||||
eslint-visitor-keys: 3.4.0
|
||||
dev: true
|
||||
|
||||
/@eslint-community/regexpp@4.4.0:
|
||||
|
@ -3900,10 +3900,6 @@ packages:
|
|||
resolution: {integrity: sha512-HXwADeHEP4exXkCIwy2n1+i0f1ilP1ETQOH5KDOugjkTFZPntWo0Gr8stZOaebkxsdx+k0X/K6obU/+it07ocg==}
|
||||
dev: true
|
||||
|
||||
/@types/focus-within@1.0.1:
|
||||
resolution: {integrity: sha512-ClIiYA9fOJUcZzb8nQXlvwta5obDHd5aQw4I2L/b1lvFSPXXImgiN7ueRVfMlIEkpAvc22hMjbu3g3RiPzZEUQ==}
|
||||
dev: true
|
||||
|
||||
/@types/fs-extra@9.0.13:
|
||||
resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==}
|
||||
dependencies:
|
||||
|
@ -4224,7 +4220,7 @@ packages:
|
|||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 5.57.0
|
||||
eslint-visitor-keys: 3.3.0
|
||||
eslint-visitor-keys: 3.4.0
|
||||
dev: true
|
||||
|
||||
/@vercel/nft@0.22.1(supports-color@9.2.1):
|
||||
|
@ -5977,7 +5973,7 @@ packages:
|
|||
dev: true
|
||||
|
||||
/concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
||||
dev: true
|
||||
|
||||
/concordance@5.0.4:
|
||||
|
@ -7255,11 +7251,6 @@ packages:
|
|||
engines: {node: '>=4'}
|
||||
dev: false
|
||||
|
||||
/eslint-visitor-keys@3.3.0:
|
||||
resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
/eslint-visitor-keys@3.4.0:
|
||||
resolution: {integrity: sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
@ -7323,15 +7314,6 @@ packages:
|
|||
eslint-visitor-keys: 1.3.0
|
||||
dev: false
|
||||
|
||||
/espree@9.4.0:
|
||||
resolution: {integrity: sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn-jsx: 5.3.2(acorn@8.8.2)
|
||||
eslint-visitor-keys: 3.3.0
|
||||
dev: true
|
||||
|
||||
/espree@9.5.1:
|
||||
resolution: {integrity: sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
@ -7346,13 +7328,6 @@ packages:
|
|||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
|
||||
/esquery@1.4.0:
|
||||
resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==}
|
||||
engines: {node: '>=0.10'}
|
||||
dependencies:
|
||||
estraverse: 5.3.0
|
||||
dev: true
|
||||
|
||||
/esquery@1.4.2:
|
||||
resolution: {integrity: sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
@ -7990,14 +7965,6 @@ packages:
|
|||
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
|
||||
dev: true
|
||||
|
||||
/focus-within@3.0.2:
|
||||
resolution: {integrity: sha512-TMn2sLUwi02dSPElXFPyzBkiQN+Xo1oYta5Jd2zC54MQoBOCMht6xar7gJgw5a9+GtFxkG9c2k4ptI6cU37soA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
postcss: 7.0.39
|
||||
dev: false
|
||||
|
||||
/folder-walker@3.2.0:
|
||||
resolution: {integrity: sha512-VjAQdSLsl6AkpZNyrQJfO7BXLo4chnStqb055bumZMbRUPpVuPN3a4ktsnRCmrFZjtMlYLkyXiR5rAs4WOpC4Q==}
|
||||
dependencies:
|
||||
|
@ -11627,6 +11594,7 @@ packages:
|
|||
|
||||
/picocolors@0.2.1:
|
||||
resolution: {integrity: sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==}
|
||||
dev: true
|
||||
|
||||
/picocolors@1.0.0:
|
||||
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
|
||||
|
@ -12126,6 +12094,7 @@ packages:
|
|||
dependencies:
|
||||
picocolors: 0.2.1
|
||||
source-map: 0.6.1
|
||||
dev: true
|
||||
|
||||
/postcss@8.4.21:
|
||||
resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==}
|
||||
|
@ -14666,9 +14635,9 @@ packages:
|
|||
debug: 4.3.4(supports-color@9.2.1)
|
||||
eslint: 8.37.0
|
||||
eslint-scope: 7.1.1
|
||||
eslint-visitor-keys: 3.3.0
|
||||
espree: 9.4.0
|
||||
esquery: 1.4.0
|
||||
eslint-visitor-keys: 3.4.0
|
||||
espree: 9.5.1
|
||||
esquery: 1.4.2
|
||||
lodash: 4.17.21
|
||||
semver: 7.3.8
|
||||
transitivePeerDependencies:
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 18 18" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5">
|
||||
<path d="M1,9 L1,3.5 C1,2 2,1 3.5,1 L14.5,1 C16,1 17,2 17,3.5 L17,14.5 C17,16 16,17 14.5,17 L3.5,17 C2,17 1,16 1,14.5 L1,9 Z" stroke-dasharray="60"></path>
|
||||
<polyline points="1 9 7 14 15 4" stroke-dasharray="22" stroke-dashoffset="66"></polyline>
|
||||
</svg>
|
After Width: | Height: | Size: 420 B |
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<div class="base-checkbox" v-cy="'checkbox'">
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="checkboxId"
|
||||
class="is-sr-only"
|
||||
:checked="modelValue"
|
||||
@change="(event) => emit('update:modelValue', (event.target as HTMLInputElement).checked)"
|
||||
:disabled="disabled || undefined"
|
||||
/>
|
||||
|
||||
<slot name="label" :checkboxId="checkboxId">
|
||||
<label :for="checkboxId" class="base-checkbox__label">
|
||||
<slot/>
|
||||
</label>
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref} from 'vue'
|
||||
import {createRandomID} from '@/helpers/randomId'
|
||||
|
||||
defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'update:modelValue', value: boolean): void
|
||||
}>()
|
||||
|
||||
const checkboxId = ref(`fancycheckbox_${createRandomID()}`)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.base-checkbox__label {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.base-checkbox:has(input:disabled) .base-checkbox__label {
|
||||
cursor:not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,71 @@
|
|||
<script lang="ts" setup>
|
||||
import {ref} from 'vue'
|
||||
import {logEvent} from 'histoire/client'
|
||||
import FancyCheckbox from './fancycheckbox.vue'
|
||||
|
||||
const isDisabled = ref<boolean | undefined>()
|
||||
|
||||
const isChecked = ref(false)
|
||||
|
||||
const isCheckedInitiallyEnabled = ref(true)
|
||||
|
||||
const isCheckedDisabled = ref(false)
|
||||
|
||||
const withoutInitialState = ref<boolean | undefined>()
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<Story :layout="{ type: 'grid', width: '200px' }">
|
||||
<Variant title="Default">
|
||||
<FancyCheckbox
|
||||
v-model="isChecked"
|
||||
:disabled="isDisabled"
|
||||
>
|
||||
This is probably not important
|
||||
</FancyCheckbox>
|
||||
|
||||
Visualisation
|
||||
<input type="checkbox" v-model="isChecked">
|
||||
{{ isChecked }}
|
||||
</Variant>
|
||||
<Variant title="Enabled Initially">
|
||||
<FancyCheckbox
|
||||
:disabled="isDisabled"
|
||||
v-model="isCheckedInitiallyEnabled"
|
||||
>
|
||||
We want you to use this option
|
||||
</FancyCheckbox>
|
||||
|
||||
Visualisation
|
||||
<input type="checkbox" v-model="isCheckedInitiallyEnabled">
|
||||
{{ isCheckedInitiallyEnabled }}
|
||||
</Variant>
|
||||
<Variant title="Disabled">
|
||||
<FancyCheckbox
|
||||
disabled
|
||||
:modelValue="isCheckedDisabled"
|
||||
@update:model-value="logEvent('Setting disabled: This should never happen', $event)"
|
||||
>
|
||||
You can't change this
|
||||
</FancyCheckbox>
|
||||
|
||||
Visualisation
|
||||
<input type="checkbox" v-model="isCheckedDisabled" disabled>
|
||||
{{ isCheckedDisabled }}
|
||||
</Variant>
|
||||
|
||||
<Variant title="Undefined initial State">
|
||||
<FancyCheckbox
|
||||
v-model="withoutInitialState"
|
||||
:disabled="isDisabled"
|
||||
>
|
||||
Not sure what the value should be
|
||||
</FancyCheckbox>
|
||||
|
||||
Visualisation
|
||||
<input type="checkbox" v-model="withoutInitialState" disabled>
|
||||
{{ withoutInitialState }}
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
|
@ -1,66 +1,42 @@
|
|||
<template>
|
||||
<div :class="{'is-disabled': disabled}" class="fancycheckbox">
|
||||
<input
|
||||
:checked="checked"
|
||||
:disabled="disabled || undefined"
|
||||
:id="checkBoxId"
|
||||
@change="(event: Event) => updateData((event.target as HTMLInputElement).checked)"
|
||||
type="checkbox"
|
||||
/>
|
||||
<label :for="checkBoxId" class="check" @click.prevent="check">
|
||||
<svg height="18px" viewBox="0 0 18 18" width="18px">
|
||||
<path
|
||||
d="M1,9 L1,3.5 C1,2 2,1 3.5,1 L14.5,1 C16,1 17,2 17,3.5 L17,14.5 C17,16 16,17 14.5,17 L3.5,17 C2,17 1,16 1,14.5 L1,9 Z"></path>
|
||||
<polyline points="1 9 7 14 15 4"></polyline>
|
||||
</svg>
|
||||
<span>
|
||||
<slot></slot>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<BaseCheckbox
|
||||
class="fancycheckbox"
|
||||
:class="{
|
||||
'is-disabled': disabled,
|
||||
'is-block': isBlock,
|
||||
}"
|
||||
:disabled="disabled"
|
||||
:model-value="modelValue"
|
||||
@update:model-value="value => emit('update:modelValue', value)"
|
||||
>
|
||||
<CheckboxIcon class="fancycheckbox__icon" />
|
||||
<span v-if="$slots.default" class="fancycheckbox__content">
|
||||
<slot/>
|
||||
</span>
|
||||
</BaseCheckbox>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref, toRef, watch} from 'vue'
|
||||
import CheckboxIcon from '@/assets/checkbox.svg?component'
|
||||
dpschen marked this conversation as resolved
Outdated
|
||||
|
||||
import {createRandomID} from '@/helpers/randomId'
|
||||
import BaseCheckbox from '@/components/base/BaseCheckbox.vue'
|
||||
|
||||
const checked = ref(false)
|
||||
const checkBoxId = `fancycheckbox_${createRandomID()}`
|
||||
|
||||
const props = defineProps({
|
||||
defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
isBlock: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue', 'change'])
|
||||
|
||||
const modelValue = toRef(props, 'modelValue')
|
||||
|
||||
watch(
|
||||
modelValue,
|
||||
newValue => {
|
||||
checked.value = newValue
|
||||
},
|
||||
{immediate: true},
|
||||
)
|
||||
|
||||
function updateData(newChecked: boolean) {
|
||||
checked.value = newChecked
|
||||
emit('update:modelValue', newChecked)
|
||||
emit('change', newChecked)
|
||||
}
|
||||
|
||||
function check() {
|
||||
checked.value = !checked.value
|
||||
updateData(checked.value)
|
||||
}
|
||||
const emit = defineEmits<{
|
||||
(event: 'update:modelValue', value: boolean): void
|
||||
}>()
|
||||
</script>
|
||||
|
||||
|
||||
|
@ -70,75 +46,54 @@ function check() {
|
|||
padding-right: 5px;
|
||||
padding-top: 3px;
|
||||
|
||||
// FIXME: should be a prop
|
||||
&.is-block {
|
||||
display: block;
|
||||
margin: .5rem .2rem;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=checkbox] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.check {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
margin: auto;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
span {
|
||||
.fancycheckbox__content {
|
||||
font-size: 0.8rem;
|
||||
vertical-align: top;
|
||||
padding-left: .5rem;
|
||||
}
|
||||
|
||||
svg {
|
||||
.fancycheckbox__icon:deep() {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
fill: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke: #c8ccd4;
|
||||
stroke-width: 1.5;
|
||||
stroke: var(--stroke-color, #c8ccd4);
|
||||
transform: translate3d(0, 0, 0);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.check:hover svg {
|
||||
stroke: var(--primary);
|
||||
}
|
||||
|
||||
.is-disabled .check:hover svg {
|
||||
stroke: #c8ccd4;
|
||||
}
|
||||
|
||||
path {
|
||||
stroke-dasharray: 60;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
|
||||
polyline {
|
||||
stroke-dasharray: 22;
|
||||
stroke-dashoffset: 66;
|
||||
}
|
||||
|
||||
input[type=checkbox]:checked + .check {
|
||||
svg {
|
||||
stroke: var(--primary);
|
||||
path,
|
||||
polyline {
|
||||
transition: all 0.2s linear, color 0.2s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.fancycheckbox:not(:has(input:disabled)):hover .fancycheckbox__icon,
|
||||
.fancycheckbox:has(input:checked) .fancycheckbox__icon {
|
||||
--stroke-color: var(--primary);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
// Since css-has-pseudo doesn't work with deep classes,
|
||||
// the following rules can't be scoped
|
||||
|
||||
.fancycheckbox:has(:not(input:checked)) .fancycheckbox__icon {
|
||||
path {
|
||||
transition-delay: 0.05s;
|
||||
}
|
||||
}
|
||||
|
||||
.fancycheckbox:has(input:checked) .fancycheckbox__icon {
|
||||
path {
|
||||
stroke-dashoffset: 60;
|
||||
transition: all 0.3s linear;
|
||||
}
|
||||
|
||||
polyline {
|
||||
stroke-dashoffset: 42;
|
||||
transition: all 0.2s linear;
|
||||
transition-delay: 0.15s;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
<template>
|
||||
<router-link
|
||||
:to="taskDetailRoute"
|
||||
:class="{'is-loading': taskService.loading}"
|
||||
class="task loader-container"
|
||||
>
|
||||
<div :class="{'is-loading': taskService.loading}" class="task loader-container">
|
||||
<fancycheckbox
|
||||
:disabled="(isArchived || disabled) && !canMarkAsDone"
|
||||
@change="markAsDone"
|
||||
@update:model-value="markAsDone"
|
||||
v-model="task.done"
|
||||
/>
|
||||
|
||||
|
@ -16,7 +12,8 @@
|
|||
class="mr-1"
|
||||
/>
|
||||
|
||||
<div
|
||||
<router-link
|
||||
:to="taskDetailRoute"
|
||||
:class="{ 'done': task.done, 'show-project': showProject && project !== null}"
|
||||
class="tasktext"
|
||||
>
|
||||
|
@ -96,7 +93,7 @@
|
|||
</span>
|
||||
|
||||
<checklist-summary :task="task"/>
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
<progress
|
||||
class="progress is-small"
|
||||
|
@ -117,14 +114,14 @@
|
|||
|
||||
<BaseButton
|
||||
:class="{'is-favorite': task.isFavorite}"
|
||||
@click.prevent="toggleFavorite"
|
||||
@click="toggleFavorite"
|
||||
class="favorite"
|
||||
>
|
||||
<icon icon="star" v-if="task.isFavorite"/>
|
||||
<icon :icon="['far', 'star']" v-else/>
|
||||
</BaseButton>
|
||||
<slot />
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -288,11 +285,7 @@ function hideDeferDueDatePopup(e) {
|
|||
border-radius: $radius;
|
||||
border: 2px solid transparent;
|
||||
|
||||
color: var(--text);
|
||||
transition: color ease $transition-duration;
|
||||
|
||||
&:hover {
|
||||
color: var(--grey-900);
|
||||
background-color: var(--grey-100);
|
||||
}
|
||||
|
||||
|
@ -338,6 +331,15 @@ function hideDeferDueDatePopup(e) {
|
|||
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--text);
|
||||
transition: color ease $transition-duration;
|
||||
|
||||
&:hover {
|
||||
color: var(--grey-900);
|
||||
}
|
||||
}
|
||||
|
||||
.favorite {
|
||||
opacity: 1;
|
||||
text-align: center;
|
||||
|
|
|
@ -6,13 +6,11 @@ declare global {
|
|||
}
|
||||
}
|
||||
|
||||
const cypressDirective: Directive = {
|
||||
mounted(el, {value}) {
|
||||
if (
|
||||
(window.Cypress || import.meta.env.DEV) &&
|
||||
value
|
||||
) {
|
||||
el.setAttribute('data-cy', value)
|
||||
const cypressDirective = <Directive<HTMLElement,string>>{
|
||||
mounted(el, {arg, value}) {
|
||||
const testingId = arg || value
|
||||
if ((window.Cypress || import.meta.env.DEV) && testingId) {
|
||||
el.setAttribute('data-cy', testingId)
|
||||
}
|
||||
},
|
||||
beforeUnmount(el) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { defineSetupVue3 } from '@histoire/plugin-vue'
|
||||
import './polyfills'
|
||||
import {defineSetupVue3} from '@histoire/plugin-vue'
|
||||
import {i18n} from './i18n'
|
||||
|
||||
// import './histoire.css' // Import global CSS
|
||||
|
@ -6,18 +7,21 @@ import './styles/global.scss'
|
|||
|
||||
import {createPinia} from 'pinia'
|
||||
|
||||
import cypress from '@/directives/cypress'
|
||||
|
||||
import FontAwesomeIcon from '@/components/misc/Icon'
|
||||
import XButton from '@/components/input/button.vue'
|
||||
import Modal from '@/components/misc/modal.vue'
|
||||
import Card from '@/components/misc/card.vue'
|
||||
|
||||
|
||||
export const setupVue3 = defineSetupVue3(({ app }) => {
|
||||
// Add Pinia store
|
||||
const pinia = createPinia()
|
||||
app.use(pinia)
|
||||
app.use(i18n)
|
||||
|
||||
app.directive('cy', cypress)
|
||||
|
||||
app.component('icon', FontAwesomeIcon)
|
||||
app.component('XButton', XButton)
|
||||
app.component('modal', Modal)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// in order to use postcss-preset-env correctly we need some client side plugins
|
||||
import focusWithin from 'focus-within'
|
||||
import focusWithinInit from 'postcss-focus-within/browser'
|
||||
import cssHasPseudo from 'css-has-pseudo/browser'
|
||||
|
||||
focusWithin(document)
|
||||
focusWithinInit()
|
||||
cssHasPseudo(document)
|
|
@ -22,7 +22,7 @@
|
|||
<x-button @click="setDefaultFilters">Reset</x-button>
|
||||
</div>
|
||||
</div>
|
||||
<fancycheckbox class="is-block" v-model="filters.showTasksWithoutDates">
|
||||
<fancycheckbox is-block v-model="filters.showTasksWithoutDates">
|
||||
{{ $t('project.gantt.showTasksWithoutDates') }}
|
||||
</fancycheckbox>
|
||||
</div>
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
</x-button>
|
||||
</template>
|
||||
</datepicker-with-range>
|
||||
<fancycheckbox @change="setShowNulls" class="mr-2">
|
||||
<fancycheckbox @update:model-value="setShowNulls" class="mr-2">
|
||||
{{ $t('task.show.noDates') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="setShowOverdue">
|
||||
<fancycheckbox @update:model-value="setShowOverdue">
|
||||
{{ $t('task.show.overdue') }}
|
||||
</fancycheckbox>
|
||||
</p>
|
||||
|
|
|
@ -81,6 +81,7 @@ export default defineConfig(({mode}) => {
|
|||
// See also './src/polyfills.ts'
|
||||
features: {
|
||||
'focus-within-pseudo-class': true,
|
||||
'has-pseudo-class': true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
|
|
Reference in New Issue
Nit-picking, but can we call this something other than "Img"? That makes me thing of a css-sprite png image from 2000...
Done!