Skip to content

Commit

Permalink
feat(tasks): Make tasks panel responsive (#200)
Browse files Browse the repository at this point in the history
* refactor: Format class name order in taskItem

* feat(taskItem): Tasks are bigger on mobile

* refactor(controls): Remove bottom margin

* refactor(timerSwitch): Remove width and height modifiers

* feat: Add task display component

* refactor(tasks): Make task list more mobile friendly

* feat(tasks): Show task list on the right on desktop

* refactor(timer): Todo manager button is now consistently on the right

* feat(todoItem): Make checkbox bigger on mobile

* feat(todoDisplay): Make displayed tasks fixed width

* feat(tasks): Increase bottom padding on desktop

* feat(taskDisplay): Add transitions for displayed tasks

* refactor(timer): Remove todoDisplay for now

* fix(timer): Make todo manager fixed
This mitigates some layout issues caused by scroll bars appearing during absolute positioning

* fix(timer): Hide todo manager by default
  • Loading branch information
Hanziness committed Apr 12, 2022
1 parent 81c85f7 commit 55996a5
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 30 deletions.
2 changes: 1 addition & 1 deletion components/timer/controls/contolsBasic.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="w-max dark:text-gray-100 z-10 flex flex-row items-center p-2 mb-4 text-gray-900 bg-transparent">
<div class="w-max dark:text-gray-100 z-10 flex flex-row items-center p-2 text-gray-900 bg-transparent">
<!-- Reset -->
<div
role="button"
Expand Down
2 changes: 1 addition & 1 deletion components/timer/display/_timerSwitch.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="w-full h-full relative flex flex-col justify-center text-center text-black dark:text-gray-100 transition-opacity duration-500 select-none" :class="[{ 'opacity-70': !running, 'opacity-100': running }]">
<div class="dark:text-gray-100 relative flex flex-col justify-center text-center text-black transition-opacity duration-500 select-none" :class="[{ 'opacity-70': !running, 'opacity-100': running }]">
<Transition name="timer-switch" mode="out-in">
<CompleteMarker v-if="$store.getters['schedule/getCurrentTimerState'] === 3" :key="'complete'" />
<TimerTraditional v-else-if="timerWidget === 'traditional'" v-bind="timerInfo" :key="'traditional'" @tick="$emit('tick', $event)" />
Expand Down
35 changes: 35 additions & 0 deletions components/todoList/display.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<template>
<transition-group class="flex flex-col w-full max-w-sm gap-2 px-4" enter-class="translate-y-2 opacity-0" enter-active-class="transition" leave-to-class="-translate-y-2 opacity-0" leave-active-class="transition">
<TaskItem
v-for="task in tasks"
:key="task.section + '-' + task.title"
:manage="false"
:draggable="false"
:item="task"
class="!border-l-0"
@input="$store.commit('tasklist/toggleComplete', { item: task })"
@delete="$store.commit('tasklist/delete', { item: task })"
/>
</transition-group>
</template>

<script>
import Item from './item.vue'
export default {
components: { TaskItem: Item },
computed: {
tasks: {
get () {
let tasks = this.$store.getters['tasklist/sortedTasks']
.filter(task => task.section === this.$store.getters['schedule/getCurrentItem'].type)
if (this.$store.state.settings.tasks.maxActiveTasks > 0) {
tasks = tasks.slice(0, this.$store.state.settings.tasks.maxActiveTasks)
}
return tasks
}
}
}
}
</script>
16 changes: 10 additions & 6 deletions components/todoList/item.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div
:class="['relative bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 hover:shadow-sm rounded-md border-l-8 themed-border px-2 py-2 transition-all duration-200 flex flex-row items-center', { 'opacity-50 line-through italic': item.state === 2, 'cursor-move': showReorder, 'ring themed-ring': dragged || droptarget }]"
:class="['relative bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 hover:shadow-sm rounded-md border-l-8 themed-border px-2 py-3 md:py-2 transition-all duration-200 flex flex-row items-center', { 'opacity-50 line-through italic': item.state === 2, 'cursor-move': showReorder, 'ring themed-ring': dragged || droptarget }]"
:style="{ '--theme': $store.state.settings.visuals[item.section].colour }"
draggable
@mouseenter="hovering = true"
Expand All @@ -10,25 +10,25 @@
@dragend="dragged = false, $emit('dropfinish', item)"
@dragenter="$emit('droptarget', item)"
>
<div :class="['absolute left-0 h-full -my-2 mr-2 self-stretch themed-bg transition-all duration-75 text-white flex flex-row items-center flex-shrink-0', showReorder ? 'w-6' : 'w-0']">
<div :class="['absolute left-0 top-0 h-full self-stretch themed-bg transition-all duration-75 text-white flex flex-row items-center flex-shrink-0', showReorder ? 'w-6' : 'w-0']">
<span v-show="showReorder">
<IconMenu size="16" />
</span>
</div>
<div class="flex flex-col select-none mr-7 transition-all duration-75 min-w-0" :class="[showReorder ? 'translate-x-6' : 'translate-x-0']">
<div class="mr-7 flex flex-col min-w-0 transition-all duration-75 select-none" :class="[showReorder ? 'translate-x-6' : 'translate-x-0']">
<span class="break-words">{{ item.title }}</span>
<!-- <span class="text-sm">Description</span> -->
</div>

<span class="flex-grow" />

<div class="flex-shrink-0 flex flex-row items-center space-x-1">
<div class="flex flex-row items-center flex-shrink-0 space-x-1">
<transition name="slidein">
<button v-show="manage" class="transition-all duration-100" @click="$emit('delete')">
<IconDelete size="18" class="mr-1" />
</button>
</transition>
<input :checked="checked" type="checkbox" class="rounded w-5 h-5 mr-1 themed-checkbox" @input="checked = !checked">
<input :checked="checked" type="checkbox" class="themed-checkbox md:w-5 md:h-5 w-6 h-6 mr-1 rounded" @input="checked = !checked">
</div>
</div>
</template>
Expand All @@ -52,6 +52,10 @@ export default {
droptarget: {
type: Boolean,
default: false
},
moveable: {
type: Boolean,
default: false
}
},
data () {
Expand All @@ -71,7 +75,7 @@ export default {
},
showReorder: {
get () {
return this.hovering
return this.moveable && this.hovering
}
}
},
Expand Down
26 changes: 16 additions & 10 deletions components/todoList/main.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
<template>
<div class="px-4 py-3 rounded-xl bg-gray-50 dark:bg-gray-800 shadow-lg border border-gray-400 border-opacity-20 w-96" @keyup.stop="">
<div class="flex flex-row items-center">
<p class="uppercase text-xl text-gray-800 dark:text-gray-100 font-bold tracking-tighter" v-text="$i18n.t('tasks.title')" />
<div class="flex-grow" />
<button v-show="!$store.getters['schedule/isRunning']" :class="['px-2 py-1 text-xs rounded-lg border border-yellow-300 dark:border-opacity-50 dark:text-yellow-100 text-yellow-800 transition-colors', { 'bg-yellow-200 dark:bg-opacity-40': manageMode, 'bg-yellow-50 dark:bg-opacity-10': !manageMode }]" @click="manageMode = !manageMode">
<div class="bg-gray-50 dark:bg-gray-800 border-opacity-20 md:border md:py-3 px-4 py-4 border-gray-400 shadow-lg" @keyup.stop="">
<div class="relative flex flex-row items-center justify-center h-10">
<p class="dark:text-gray-100 text-xl font-bold tracking-tighter text-gray-800 uppercase" v-text="$i18n.t('tasks.title')" />
<!-- <div class="flex-grow" /> -->
<!-- <button v-show="!$store.getters['schedule/isRunning']" :class="['px-2 py-1 text-xs rounded-lg border border-yellow-300 dark:border-opacity-50 dark:text-yellow-100 text-yellow-800 transition-colors', { 'bg-yellow-200 dark:bg-opacity-40': manageMode, 'bg-yellow-50 dark:bg-opacity-10': !manageMode }]" @click="manageMode = !manageMode">
<IconManage class="inline translate-y-[-0.1rem]" size="16" />
<span v-text="$i18n.t('tasks.manage')" />
</button> -->
<button class="hover:bg-gray-300 active:bg-gray-400 absolute right-0 float-right p-2 transition-all rounded-full" @click="$emit('hide')">
<XIcon />
</button>
</div>
<div v-show="displayedTasks.length < 1" key="notask" class="italic text-black dark:text-gray-200 text-opacity-70 mt-3" v-text="$i18n.t('tasks.empty')" />
<div v-show="displayedTasks.length < 1" key="notask" class="dark:text-gray-200 text-opacity-70 mt-3 italic text-black" v-text="$i18n.t('tasks.empty')" />
<transition-group
tag="div"
name="transition-item"
class="flex flex-col space-y-2 mt-2 py-1 -mx-2 px-2 max-h-64 overflow-y-auto overflow-x-hidden"
class="max-h-64 flex flex-col px-2 py-1 mt-2 -mx-2 space-y-2 overflow-x-hidden overflow-y-auto"
@drop.prevent="itemDropped($event, 1)"
>
<TaskItem
Expand All @@ -21,6 +24,7 @@
:manage="!$store.getters['schedule/isRunning'] && manageMode"
:item="task"
:droptarget="task === dropTarget"
moveable
@input="$store.commit('tasklist/toggleComplete', { item: task })"
@delete="$store.commit('tasklist/delete', { item: task })"
@dropstart="draggedItem = task, dragging = true"
Expand All @@ -33,15 +37,17 @@
</template>

<script>
import { EditIcon } from 'vue-tabler-icons'
// import { EditIcon } from 'vue-tabler-icons'
import { XIcon } from 'vue-tabler-icons'
import TaskItem from '@/components/todoList/item.vue'
import TaskAdd from '@/components/todoList/addTask.vue'
export default {
components: { TaskItem, TaskAdd, IconManage: EditIcon },
components: { TaskItem, TaskAdd, XIcon /* IconManage: EditIcon */ },
data () {
return {
manageMode: false,
manageMode: true,
/** Is a task being dragged to another place? */
dragging: false,
Expand Down
38 changes: 26 additions & 12 deletions pages/timer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,24 +54,36 @@
/>
</TransitionGroup>

<TimerSwitch
:time-elapsed="timeElapsed"
:time-original="timeOriginal"
:timer-state="timerState"
:timer-widget="$store.state.settings.currentTimer"
class="place-items-center absolute grid"
@tick="timeString = $event"
/>
<TimerControls class="mb-4" :class="[{ 'pointer-events-none': preview }]" :can-use-keyboard="!preview && !showSettings" />
<TodoList v-show="$store.state.settings.tasks.enabled" class="absolute z-10" style="right: 24px; bottom: 24px;" :editing="[0].includes($store.state.schedule.timerState)" />
<div class="flex flex-col items-center justify-center w-full h-full gap-2">
<TimerSwitch
key="timerswitch"
:time-elapsed="timeElapsed"
:time-original="timeOriginal"
:timer-state="timerState"
:timer-widget="$store.state.settings.currentTimer"
class="place-items-center absolute grid"
@tick="timeString = $event"
/>
</div>

<div class="relative flex flex-row items-center justify-center w-full gap-2 mb-4">
<TimerControls :class="[{ 'pointer-events-none': preview }]" :can-use-keyboard="!preview && !showSettings" />

<button v-show="$store.state.settings.tasks.enabled" class="right-4 dark:bg-gray-700 sm:absolute p-4 transition-all bg-gray-200 rounded-full shadow-md" :class="{'scale-0': showTodoManager}" @click="showTodoManager = true">
<ListCheckIcon />
</button>
</div>
<transition enter-class="translate-y-full" enter-active-class="duration-300 ease-out" leave-to-class="translate-y-full" leave-active-class="duration-150 ease-in">
<TodoList v-show="$store.state.settings.tasks.enabled && showTodoManager" class="rounded-t-xl xl:right-4 xl:pb-8 fixed bottom-0 z-10 w-full max-w-lg transition-all" :editing="[0].includes($store.state.schedule.timerState)" @hide="showTodoManager = false" />
</transition>
</div>
</Ticker>
</NotificationController>
</section>
</template>

<script>
import { SettingsIcon } from 'vue-tabler-icons'
import { SettingsIcon, ListCheckIcon } from 'vue-tabler-icons'
// Static imports:
Expand All @@ -87,7 +99,8 @@ export default {
SettingsPanel: () => import(/* webpackChunkName: "settings" */ '@/components/settings/settingsPanel.vue'),
UiOverlay: () => import(/* webpackChunkName: "uibase", webpackPrefetch: true */ '@/components/base/overlay.vue'),
TodoList: () => import(/* webpackChunkName: "todo" */ '@/components/todoList/main.vue'),
CogIcon: SettingsIcon
CogIcon: SettingsIcon,
ListCheckIcon
},
layout: 'timer',
Expand All @@ -102,6 +115,7 @@ export default {
data () {
return {
showSettings: false,
showTodoManager: false,
timeString: ''
}
},
Expand Down

0 comments on commit 55996a5

Please sign in to comment.