mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-13 02:32:15 +01:00
improve focus state styling
This commit is contained in:
@@ -23,6 +23,7 @@ import {
|
||||
import TimeEntryRow from '@/packages/ui/src/TimeEntry/TimeEntryRow.vue';
|
||||
import GroupedItemsCountButton from '@/packages/ui/src/GroupedItemsCountButton.vue';
|
||||
import type { TimeEntriesGroupedByType } from '@/types/time-entries';
|
||||
import { Checkbox } from '@/packages/ui/src';
|
||||
|
||||
const props = defineProps<{
|
||||
timeEntry: TimeEntriesGroupedByType;
|
||||
@@ -76,6 +77,7 @@ function updateProjectAndTask(projectId: string, taskId: string) {
|
||||
}
|
||||
|
||||
const expanded = ref(false);
|
||||
|
||||
function onSelectChange(event: Event) {
|
||||
const target = event.target as HTMLInputElement;
|
||||
if (target.checked) {
|
||||
@@ -92,10 +94,10 @@ function onSelectChange(event: Event) {
|
||||
data-testid="time_entry_row">
|
||||
<MainContainer class="min-w-0">
|
||||
<div
|
||||
class="sm:flex py-0.5 items-center min-w-0 justify-between group">
|
||||
class="sm:flex py-2 items-center min-w-0 justify-between group">
|
||||
<div class="flex space-x-3 items-center min-w-0">
|
||||
<input
|
||||
@change="onSelectChange"
|
||||
<Checkbox
|
||||
@update:checked="onSelectChange"
|
||||
:checked="
|
||||
timeEntry.timeEntries.every(
|
||||
(aggregateTimeEntry: TimeEntry) =>
|
||||
@@ -103,9 +105,7 @@ function onSelectChange(event: Event) {
|
||||
aggregateTimeEntry
|
||||
)
|
||||
)
|
||||
"
|
||||
type="checkbox"
|
||||
class="h-4 w-4 rounded bg-card-background border-input-border text-accent-500/80 focus:ring-accent-500/80" />
|
||||
" />
|
||||
<div class="flex items-center min-w-0">
|
||||
<GroupedItemsCountButton
|
||||
:expanded="expanded"
|
||||
@@ -113,7 +113,7 @@ function onSelectChange(event: Event) {
|
||||
{{ timeEntry?.timeEntries?.length }}
|
||||
</GroupedItemsCountButton>
|
||||
<TimeEntryDescriptionInput
|
||||
class="min-w-0"
|
||||
class="min-w-0 mr-4"
|
||||
@changed="updateTimeEntryDescription"
|
||||
:modelValue="
|
||||
timeEntry.description
|
||||
@@ -130,6 +130,7 @@ function onSelectChange(event: Event) {
|
||||
:project="timeEntry.project_id"
|
||||
:enableEstimatedTime
|
||||
:currency="currency"
|
||||
class="border border-border-primary"
|
||||
:task="
|
||||
timeEntry.task_id
|
||||
"></TimeTrackerProjectTaskDropdown>
|
||||
@@ -143,6 +144,7 @@ function onSelectChange(event: Event) {
|
||||
:modelValue="timeEntry.tags"></TimeEntryRowTagDropdown>
|
||||
<BillableToggleButton
|
||||
:modelValue="timeEntry.billable"
|
||||
class="opacity-50 focus-visible:opacity-100 group-hover:opacity-100"
|
||||
size="small"
|
||||
@changed="
|
||||
updateTimeEntryBillable
|
||||
@@ -150,13 +152,13 @@ function onSelectChange(event: Event) {
|
||||
<div class="flex-1">
|
||||
<button
|
||||
@click="expanded = !expanded"
|
||||
class="hidden lg:block text-muted w-[110px] px-2 py-2 bg-transparent text-center hover:bg-card-background rounded-lg border border-transparent hover:border-card-border text-sm font-medium">
|
||||
class="hidden lg:block text-muted w-[105px] px-1 py-1.5 bg-transparent text-center hover:bg-card-background rounded-lg border border-transparent hover:border-card-border text-sm font-medium focus-visible:outline-none focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:bg-tertiary">
|
||||
{{ formatStartEnd(timeEntry.start, timeEntry.end) }}
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
@click="expanded = !expanded"
|
||||
class="text-white w-[100px] px-3 py-2 bg-transparent text-center hover:bg-card-background rounded-lg border border-transparent hover:border-card-border text-sm font-semibold">
|
||||
class="text-white min-w-[90px] px-2 py-1.5 bg-transparent text-center hover:bg-card-background rounded-lg border border-transparent hover:border-card-border text-sm font-semibold focus-visible:outline-none focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:bg-tertiary">
|
||||
{{
|
||||
formatHumanReadableDuration(timeEntry.duration ?? 0)
|
||||
}}
|
||||
@@ -165,7 +167,7 @@ function onSelectChange(event: Event) {
|
||||
<TimeTrackerStartStop
|
||||
@changed="onStartStopClick(timeEntry)"
|
||||
:active="!!(timeEntry.start && !timeEntry.end)"
|
||||
class="opacity-20 hidden sm:flex group-hover:opacity-100"></TimeTrackerStartStop>
|
||||
class="opacity-20 hidden sm:flex group-hover:opacity-100 focus-visible:opacity-100"></TimeTrackerStartStop>
|
||||
<TimeEntryMoreOptionsDropdown
|
||||
@delete="
|
||||
deleteTimeEntries(timeEntry?.timeEntries ?? [])
|
||||
|
||||
@@ -36,7 +36,7 @@ const displaysPlaceholder = computed(() => {
|
||||
<div class="relative text-sm font-medium min-w-0">
|
||||
<div
|
||||
:class="[
|
||||
'opacity-0 py-2 text-sm whitespace-pre min-w-0 pl-3 pr-1',
|
||||
'opacity-0 h-4 text-sm whitespace-pre font-medium min-w-0 pl-3 pr-1',
|
||||
{ 'min-w-[130px]': displaysPlaceholder },
|
||||
]">
|
||||
{{ liveDataValue }}
|
||||
|
||||
@@ -88,14 +88,14 @@ const showMassUpdateModal = ref(false);
|
||||
>Select All</InputLabel
|
||||
>
|
||||
<button
|
||||
class="text-text-tertiary flex space-x-1 items-center hover:text-text-secondary transition focus-visible:ring-2 outline-0 focus-visible:text-text-primary focus-visible:ring-white/80 rounded h-full px-2"
|
||||
class="text-text-tertiary flex space-x-1 items-center hover:text-text-secondary transition focus-visible:ring-2 outline-0 focus-visible:text-text-primary focus-visible:ring-ring rounded h-full px-2"
|
||||
@click="showMassUpdateModal = true"
|
||||
v-if="selectedTimeEntries.length">
|
||||
<PencilSquareIcon class="w-4"></PencilSquareIcon>
|
||||
<span> Edit </span>
|
||||
</button>
|
||||
<button
|
||||
class="text-red-400 h-full px-2 space-x-1 items-center flex hover:text-red-500 transition focus-visible:ring-2 outline-0 focus-visible:text-red-500 focus-visible:ring-white/80 rounded"
|
||||
class="text-red-400 h-full px-2 space-x-1 items-center flex hover:text-red-500 transition focus-visible:ring-2 outline-0 focus-visible:text-red-500 focus-visible:ring-ring rounded"
|
||||
@click="deleteSelected"
|
||||
v-if="selectedTimeEntries.length">
|
||||
<TrashIcon class="w-3.5"></TrashIcon>
|
||||
|
||||
@@ -33,10 +33,10 @@ const open = ref(false);
|
||||
data-testid="time_entry_range_selector"
|
||||
:class="
|
||||
twMerge(
|
||||
'text-muted w-[110px] px-2 bg-transparent text-center hover:bg-card-background rounded-lg border border-transparent hover:border-card-border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80',
|
||||
'text-muted w-[105px] px-2 bg-transparent text-center hover:bg-card-background rounded-lg border border-transparent hover:border-card-border focus-visible:outline-none focus:outline-none focus-visible:ring-2 focus-visible:text-text-primary focus-visible:ring-ring focus-visible:bg-tertiary',
|
||||
showDate
|
||||
? 'text-xs py-1.5 font-semibold'
|
||||
: 'text-sm py-2 font-medium',
|
||||
: 'text-sm py-1.5 font-medium',
|
||||
open && 'border-card-border bg-card-background'
|
||||
)
|
||||
">
|
||||
|
||||
@@ -19,6 +19,7 @@ import TimeEntryMoreOptionsDropdown from '@/packages/ui/src/TimeEntry/TimeEntryM
|
||||
import BillableToggleButton from '@/packages/ui/src/Input/BillableToggleButton.vue';
|
||||
import { computed } from 'vue';
|
||||
import TimeTrackerProjectTaskDropdown from '@/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue';
|
||||
import { Checkbox } from '@/packages/ui/src';
|
||||
|
||||
const props = defineProps<{
|
||||
timeEntry: TimeEntry;
|
||||
@@ -96,16 +97,15 @@ function onSelectChange(event: Event) {
|
||||
data-testid="time_entry_row">
|
||||
<MainContainer class="min-w-0">
|
||||
<div
|
||||
class="sm:flex py-0.5 min-w-0 items-center justify-between group">
|
||||
<div class="flex space-x-1 items-center min-w-0">
|
||||
<input
|
||||
@change="onSelectChange"
|
||||
:checked="selected"
|
||||
type="checkbox"
|
||||
class="h-4 w-4 rounded bg-card-background border-input-border text-accent-500/80 focus:ring-accent-500/80" />
|
||||
<div class="w-7 h-7" v-if="indent === true"></div>
|
||||
class="sm:flex py-2 min-w-0 items-center justify-between group">
|
||||
<div class="flex items-center min-w-0">
|
||||
<Checkbox
|
||||
@update:checked="onSelectChange"
|
||||
:checked="selected" />
|
||||
<div class="w-10 h-7" v-if="indent === true"></div>
|
||||
<TimeEntryDescriptionInput
|
||||
@changed="updateTimeEntryDescription"
|
||||
class="min-w-0 mr-4"
|
||||
:modelValue="
|
||||
timeEntry.description
|
||||
"></TimeEntryDescriptionInput>
|
||||
@@ -120,12 +120,14 @@ function onSelectChange(event: Event) {
|
||||
@changed="updateProjectAndTask"
|
||||
:project="timeEntry.project_id"
|
||||
:currency="currency"
|
||||
class="border border-border-primary"
|
||||
:enableEstimatedTime
|
||||
:task="
|
||||
timeEntry.task_id
|
||||
"></TimeTrackerProjectTaskDropdown>
|
||||
</div>
|
||||
<div class="flex items-center font-medium lg:space-x-2">
|
||||
<div
|
||||
class="flex items-center font-medium space-x-1 lg:space-x-2">
|
||||
<div class="text-sm px-2" v-if="showMember && members">
|
||||
{{ memberName }}
|
||||
</div>
|
||||
@@ -136,6 +138,7 @@ function onSelectChange(event: Event) {
|
||||
:modelValue="timeEntry.tags"></TimeEntryRowTagDropdown>
|
||||
<BillableToggleButton
|
||||
:modelValue="timeEntry.billable"
|
||||
class="opacity-50 group-hover:opacity-100 focus-visible:opacity-100"
|
||||
size="small"
|
||||
@changed="
|
||||
updateTimeEntryBillable
|
||||
@@ -159,7 +162,7 @@ function onSelectChange(event: Event) {
|
||||
<TimeTrackerStartStop
|
||||
@changed="onStartStopClick"
|
||||
:active="!!(timeEntry.start && !timeEntry.end)"
|
||||
class="opacity-20 hidden sm:flex group-hover:opacity-100"></TimeTrackerStartStop>
|
||||
class="opacity-20 hidden sm:flex focus-visible:opacity-100 group-hover:opacity-100"></TimeTrackerStartStop>
|
||||
<TimeEntryMoreOptionsDropdown
|
||||
@delete="
|
||||
deleteTimeEntry
|
||||
|
||||
@@ -71,7 +71,7 @@ function selectInput(event: Event) {
|
||||
<template #trigger>
|
||||
<input
|
||||
data-testid="time_entry_duration_input"
|
||||
class="text-white w-[100px] px-3 py-2 bg-transparent text-center hover:bg-card-background rounded-lg border border-transparent hover:border-card-border text-sm font-semibold focus-visible:border-transparent focus-visible:ring-2 focus-visible:ring-white/80"
|
||||
class="text-white w-[90px] px-2 py-1.5 bg-transparent text-center hover:bg-card-background rounded-lg border border-transparent hover:border-card-border text-sm font-semibold focus-visible:bg-tertiary focus-visible:border-transparent focus-visible:ring-2 focus-visible:ring-ring"
|
||||
@focus="selectInput"
|
||||
@keydown.tab="open = false"
|
||||
@blur="updateTimerAndStartLiveTimerUpdate"
|
||||
|
||||
@@ -56,7 +56,7 @@ function selectUnselectAll(value: boolean) {
|
||||
{{ formatDate(date) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-muted pr-[90px] lg:pr-[108px]">
|
||||
<div class="text-muted pr-[90px] lg:pr-[92px]">
|
||||
<span class="font-semibold">
|
||||
{{ formatHumanReadableDuration(duration) }}
|
||||
</span>
|
||||
|
||||
@@ -31,11 +31,11 @@ const timeEntryTags = computed<Tag[]>(() => {
|
||||
<template #trigger>
|
||||
<button
|
||||
data-testid="time_entry_tag_dropdown"
|
||||
class="opacity-50 group-hover:opacity-100 transition">
|
||||
class="opacity-50 group-hover:opacity-100 group/dropdown focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:opacity-100 transition focus:bg-card-background-separator hover:bg-card-background-separator rounded-full flex items-center justify-center">
|
||||
<TagBadge
|
||||
:border="false"
|
||||
size="large"
|
||||
class="border-0"
|
||||
class="border-0 sm:px-1.5 text-icon-default group-focus-within/dropdown:text-text-primary"
|
||||
:name="
|
||||
timeEntryTags.map((tag: Tag) => tag.name).join(', ')
|
||||
"></TagBadge>
|
||||
|
||||
Reference in New Issue
Block a user