mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-17 04:32:15 +01:00
add responsiveness for the dashboard and menu
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
|
|
||||||
:root{
|
:root{
|
||||||
|
--theme-color-default-background: #040618;
|
||||||
--theme-color-icon-default: #42466C;
|
--theme-color-icon-default: #42466C;
|
||||||
--theme-color-card-background: #13152B;
|
--theme-color-card-background: #13152B;
|
||||||
--theme-color-card-background-active: #1C1E34;
|
--theme-color-card-background-active: #1C1E34;
|
||||||
@@ -29,6 +30,11 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body{
|
||||||
|
background-color: var(--theme-color-default-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Outfit';
|
font-family: 'Outfit';
|
||||||
src: url('/fonts/Outfit-VariableFont_wght.ttf');
|
src: url('/fonts/Outfit-VariableFont_wght.ttf');
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const props = withDefaults(
|
|||||||
|
|
||||||
const badgeClasses = {
|
const badgeClasses = {
|
||||||
base: 'py-1 px-2 space-x-1.5 text-xs',
|
base: 'py-1 px-2 space-x-1.5 text-xs',
|
||||||
large: 'py-1.5 px-3 space-x-2 text-sm text-muted',
|
large: 'py-1 sm:py-1.5 px-2 sm:px-3 space-x-1.5 sm:space-x-2 text-xs sm:text-sm text-muted',
|
||||||
};
|
};
|
||||||
|
|
||||||
const borderClasses = computed(() => {
|
const borderClasses = computed(() => {
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ const iconColorClasses = computed(() => {
|
|||||||
:class="
|
:class="
|
||||||
twMerge(
|
twMerge(
|
||||||
iconColorClasses,
|
iconColorClasses,
|
||||||
'flex-shrink-0 ring-0 focus:outline-none focus:ring-0 transition focus:bg-card-background-separator hover:bg-card-background-separator rounded-full w-11 h-11 flex items-center justify-center'
|
'flex-shrink-0 ring-0 focus:outline-none focus:ring-0 transition focus:bg-card-background-separator hover:bg-card-background-separator rounded-full w-7 sm:w-11 h-7 sm:h-11 flex items-center justify-center'
|
||||||
)
|
)
|
||||||
">
|
">
|
||||||
<svg
|
<svg
|
||||||
class="h-7"
|
class="w-5 sm:w-7 h-5 sm:h-7"
|
||||||
viewBox="0 0 8 14"
|
viewBox="0 0 8 14"
|
||||||
fill="none"
|
fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const props = withDefaults(
|
|||||||
|
|
||||||
const indicatorClasses = {
|
const indicatorClasses = {
|
||||||
base: 'w-2.5 h-2.5',
|
base: 'w-2.5 h-2.5',
|
||||||
large: 'w-3 h-3',
|
large: 'w-2 sm:w-3 h-2 sm:h-3',
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ const iconColorClasses = computed(() => {
|
|||||||
:class="
|
:class="
|
||||||
twMerge(
|
twMerge(
|
||||||
iconColorClasses,
|
iconColorClasses,
|
||||||
'flex-shrink-0 ring-0 focus:outline-none focus:ring-0 transition focus:bg-card-background-separator hover:bg-card-background-separator rounded-full w-11 h-11 flex items-center justify-center'
|
'flex-shrink-0 ring-0 focus:outline-none focus:ring-0 transition focus:bg-card-background-separator hover:bg-card-background-separator rounded-full w-7 sm:w-11 h-7 sm:h-11 flex items-center justify-center'
|
||||||
)
|
)
|
||||||
">
|
">
|
||||||
<TagIcon class="w-7 h-7"></TagIcon>
|
<TagIcon class="w-5 sm:w-7 h-5 sm:h-7"></TagIcon>
|
||||||
<span
|
<span
|
||||||
v-if="model.length > 1"
|
v-if="model.length > 1"
|
||||||
class="font-extrabold absolute rounded-full text-xs w-3 h-3 block top-[15px] rotate-[45deg] right-[14px] text-card-background">
|
class="font-extrabold absolute rounded-full text-xs w-3 h-3 block top-[15px] rotate-[45deg] right-[14px] text-card-background">
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ const props = withDefaults(
|
|||||||
);
|
);
|
||||||
const buttonSizeClasses = {
|
const buttonSizeClasses = {
|
||||||
base: 'w-8 h-8 bg-accent-200/40 hover:scale-110 hover:bg-accent-300/70 ring-accent-200/10 focus:ring-accent-200/10 hover:ring-4',
|
base: 'w-8 h-8 bg-accent-200/40 hover:scale-110 hover:bg-accent-300/70 ring-accent-200/10 focus:ring-accent-200/10 hover:ring-4',
|
||||||
large: 'w-11 h-11 ring-accent-200/10 focus:ring-accent-200/20 ring-8 hover:scale-110',
|
large: 'w-8 sm:w-11 h-8 sm:h-11 ring-accent-200/10 focus:ring-accent-200/20 ring-4 sm:ring-8 hover:scale-110',
|
||||||
};
|
};
|
||||||
const iconClass = {
|
const iconClass = {
|
||||||
base: 'w-3.5 h-3.5',
|
base: 'w-3.5 h-3.5',
|
||||||
large: 'w-4 h-4',
|
large: 'w-3.5 h-3.5 sm:w-4 sm:h-4',
|
||||||
};
|
};
|
||||||
|
|
||||||
const buttonColorClasses = computed(() => {
|
const buttonColorClasses = computed(() => {
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="px-3.5 py-2 flex @container">
|
<div class="px-3.5 py-2 flex justify-between @container">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<p class="font-semibold text-sm text-white">
|
<p class="font-semibold text-sm text-white">
|
||||||
{{ formatHumanReadableDate(date) }}
|
{{ formatHumanReadableDate(date) }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="items-center justify-center flex-1 flex">
|
<div class="items-center justify-center flex-1 hidden @2xs:flex">
|
||||||
<svg
|
<svg
|
||||||
class="w-20 opacity-70 transition hover:opacity-100"
|
class="w-20 opacity-70 transition hover:opacity-100"
|
||||||
viewBox="0 0 42 10"
|
viewBox="0 0 42 10"
|
||||||
|
|||||||
@@ -130,8 +130,9 @@ const option = ref({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="grid gap-x-6 xl:gap-x-6 grid-cols-4">
|
<div
|
||||||
<div class="col-span-3">
|
class="grid space-y-5 sm:space-y-0 sm:gap-x-6 xl:gap-x-6 grid-cols-1 lg:grid-cols-3 xl:grid-cols-4">
|
||||||
|
<div class="col-span-2 xl:col-span-3">
|
||||||
<CardTitle
|
<CardTitle
|
||||||
title="This Week"
|
title="This Week"
|
||||||
class="pb-8"
|
class="pb-8"
|
||||||
|
|||||||
@@ -152,9 +152,9 @@ function onTimeEntryEnterPress() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardTitle title="Time Tracker" :icon="ClockIcon"></CardTitle>
|
<CardTitle title="Time Tracker" :icon="ClockIcon"></CardTitle>
|
||||||
<div class="flex items-center" data-testid="dashboard_timer">
|
<div class="flex items-center relative" data-testid="dashboard_timer">
|
||||||
<div
|
<div
|
||||||
class="flex w-full rounded-lg bg-card-background border-card-border border transition">
|
class="flex flex-col sm:flex-row w-full rounded-lg bg-card-background border-card-border border transition">
|
||||||
<div class="flex-1 flex items-center pr-6">
|
<div class="flex-1 flex items-center pr-6">
|
||||||
<input
|
<input
|
||||||
placeholder="What are you working on?"
|
placeholder="What are you working on?"
|
||||||
@@ -162,36 +162,40 @@ function onTimeEntryEnterPress() {
|
|||||||
v-model="currentTimeEntry.description"
|
v-model="currentTimeEntry.description"
|
||||||
@keydown.enter="startTimerIfNotActive"
|
@keydown.enter="startTimerIfNotActive"
|
||||||
@blur="updateTimeEntry"
|
@blur="updateTimeEntry"
|
||||||
class="w-full rounded-l-lg py-3 px-5 text-lg text-white focus:bg-card-background-active font-medium bg-transparent border-none placeholder-muted focus:ring-0 transition"
|
class="w-full rounded-l-lg py-2.5 px-3 border-b border-b-card-background-separator sm:px-4 text-sm sm:text-lg text-white focus:bg-card-background-active font-medium bg-transparent border-none placeholder-muted focus:ring-0 transition"
|
||||||
type="text" />
|
type="text" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center justify-between pl-2">
|
||||||
<TimeTrackerProjectTaskDropdown
|
<div class="flex items-center w-[130px]">
|
||||||
@changed="updateTimeEntry"
|
<TimeTrackerProjectTaskDropdown
|
||||||
v-model:project="currentTimeEntry.project_id"
|
@changed="updateTimeEntry"
|
||||||
v-model:task="
|
v-model:project="currentTimeEntry.project_id"
|
||||||
currentTimeEntry.task_id
|
v-model:task="
|
||||||
"></TimeTrackerProjectTaskDropdown>
|
currentTimeEntry.task_id
|
||||||
</div>
|
"></TimeTrackerProjectTaskDropdown>
|
||||||
<div class="flex items-center space-x-2 px-4">
|
</div>
|
||||||
<TimeTrackerTagDropdown
|
<div class="flex items-center space-x-2 px-4">
|
||||||
@changed="updateTimeEntry"
|
<TimeTrackerTagDropdown
|
||||||
v-model="currentTimeEntry.tags"></TimeTrackerTagDropdown>
|
@changed="updateTimeEntry"
|
||||||
<BillableToggleButton></BillableToggleButton>
|
v-model="
|
||||||
</div>
|
currentTimeEntry.tags
|
||||||
<div class="border-l border-card-border">
|
"></TimeTrackerTagDropdown>
|
||||||
<input
|
<BillableToggleButton></BillableToggleButton>
|
||||||
placeholder="00:00:00"
|
</div>
|
||||||
@focus="pauseLiveTimerUpdate"
|
<div class="border-l border-card-border">
|
||||||
data-testid="time_entry_time"
|
<input
|
||||||
@blur="updateTimerAndStartLiveTimerUpdate"
|
placeholder="00:00:00"
|
||||||
@keydown.enter="onTimeEntryEnterPress"
|
@focus="pauseLiveTimerUpdate"
|
||||||
v-model="currentTime"
|
data-testid="time_entry_time"
|
||||||
class="w-40 h-full text-white py-4 rounded-r-lg text-center px-4 text-lg font-bold bg-card-background border-none placeholder-muted focus:ring-0 transition focus:bg-card-background-active"
|
@blur="updateTimerAndStartLiveTimerUpdate"
|
||||||
type="text" />
|
@keydown.enter="onTimeEntryEnterPress"
|
||||||
|
v-model="currentTime"
|
||||||
|
class="w-[110px] sm:w-[130px] h-full text-white py-2.5 rounded-r-lg text-center px-4 text-lg font-bold bg-card-background border-none placeholder-muted focus:ring-0 transition focus:bg-card-background-active"
|
||||||
|
type="text" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="pl-6 pr-3">
|
<div class="pl-6 pr-3 absolute sm:relative top-[7px] right-0">
|
||||||
<TimeTrackerStartStop
|
<TimeTrackerStartStop
|
||||||
:active="isActive"
|
:active="isActive"
|
||||||
@changed="onToggleButtonPress"
|
@changed="onToggleButtonPress"
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ import {
|
|||||||
TagIcon,
|
TagIcon,
|
||||||
UserCircleIcon,
|
UserCircleIcon,
|
||||||
UserGroupIcon,
|
UserGroupIcon,
|
||||||
|
Bars3Icon,
|
||||||
|
XMarkIcon,
|
||||||
} from '@heroicons/vue/20/solid';
|
} from '@heroicons/vue/20/solid';
|
||||||
import NavigationSidebarItem from '@/Components/NavigationSidebarItem.vue';
|
import NavigationSidebarItem from '@/Components/NavigationSidebarItem.vue';
|
||||||
import UserSettingsIcon from '@/Components/UserSettingsIcon.vue';
|
import UserSettingsIcon from '@/Components/UserSettingsIcon.vue';
|
||||||
import MainContainer from '@/Pages/MainContainer.vue';
|
import MainContainer from '@/Pages/MainContainer.vue';
|
||||||
import { onMounted } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { useProjectsStore } from '@/utils/useProjects';
|
import { useProjectsStore } from '@/utils/useProjects';
|
||||||
import { useTagsStore } from '@/utils/useTags';
|
import { useTagsStore } from '@/utils/useTags';
|
||||||
import { useTasksStore } from '@/utils/useTasks';
|
import { useTasksStore } from '@/utils/useTasks';
|
||||||
@@ -29,6 +31,8 @@ defineProps({
|
|||||||
title: String,
|
title: String,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const showSidebarMenu = ref(false);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
useProjectsStore().fetchProjects();
|
useProjectsStore().fetchProjects();
|
||||||
useTasksStore().fetchTasks();
|
useTasksStore().fetchTasks();
|
||||||
@@ -44,10 +48,17 @@ onMounted(async () => {
|
|||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
class="flex flex-wrap bg-default-background text-muted">
|
class="flex flex-wrap bg-default-background text-muted">
|
||||||
<div
|
<div
|
||||||
class="flex-shrink-0 h-screen fixed w-[230px] 2xl:w-[270px] px-2.5 2xl:px-4 py-4 flex flex-col justify-between">
|
:class="{
|
||||||
|
'!flex bg-default-background w-full z-50': showSidebarMenu,
|
||||||
|
}"
|
||||||
|
class="flex-shrink-0 h-screen hidden fixed w-[230px] 2xl:w-[270px] px-2.5 2xl:px-4 py-4 sm:flex flex-col justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="border-b border-default-background-separator pb-2">
|
<div
|
||||||
|
class="border-b border-default-background-separator pb-2 flex justify-between">
|
||||||
<OrganizationSwitcher></OrganizationSwitcher>
|
<OrganizationSwitcher></OrganizationSwitcher>
|
||||||
|
<XMarkIcon
|
||||||
|
@click="showSidebarMenu = false"
|
||||||
|
class="w-8"></XMarkIcon>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-b border-default-background-separator">
|
<div class="border-b border-default-background-separator">
|
||||||
<CurrentSidebarTimer></CurrentSidebarTimer>
|
<CurrentSidebarTimer></CurrentSidebarTimer>
|
||||||
@@ -115,7 +126,15 @@ onMounted(async () => {
|
|||||||
<UserSettingsIcon></UserSettingsIcon>
|
<UserSettingsIcon></UserSettingsIcon>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1 ml-[230px] 2xl:ml-[270px]">
|
<div class="flex-1 sm:ml-[230px] 2xl:ml-[270px]">
|
||||||
|
<div
|
||||||
|
class="sm:hidden w-full px-3 py-3 border-b border-b-default-background-separator text-muted flex justify-between items-center">
|
||||||
|
<Bars3Icon
|
||||||
|
@click="showSidebarMenu = !showSidebarMenu"
|
||||||
|
class="w-8 text-muted"></Bars3Icon>
|
||||||
|
<OrganizationSwitcher></OrganizationSwitcher>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Head :title="title" />
|
<Head :title="title" />
|
||||||
|
|
||||||
<Banner />
|
<Banner />
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const props = defineProps<{
|
|||||||
<TimeTracker></TimeTracker>
|
<TimeTracker></TimeTracker>
|
||||||
</MainContainer>
|
</MainContainer>
|
||||||
<MainContainer
|
<MainContainer
|
||||||
class="grid gap-x-6 grid-cols-2 xl:grid-cols-4 pt-5 pb-6 border-b border-default-background-separator items-stretch">
|
class="grid gap-6 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 pt-5 pb-6 border-b border-default-background-separator items-stretch">
|
||||||
<RecentlyTrackedTasksCard
|
<RecentlyTrackedTasksCard
|
||||||
:latestTasks="props.latestTasks"></RecentlyTrackedTasksCard>
|
:latestTasks="props.latestTasks"></RecentlyTrackedTasksCard>
|
||||||
<LastSevenDaysCard
|
<LastSevenDaysCard
|
||||||
@@ -64,6 +64,7 @@ const props = defineProps<{
|
|||||||
props.dailyTrackedHours
|
props.dailyTrackedHours
|
||||||
"></ActivityGraphCard>
|
"></ActivityGraphCard>
|
||||||
<TeamActivityCard
|
<TeamActivityCard
|
||||||
|
class="flex lg:hidden xl:flex"
|
||||||
:latestTeamActivity="
|
:latestTeamActivity="
|
||||||
props.latestTeamActivity
|
props.latestTeamActivity
|
||||||
"></TeamActivityCard>
|
"></TeamActivityCard>
|
||||||
|
|||||||
@@ -14,12 +14,15 @@ export default {
|
|||||||
|
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
|
containers: {
|
||||||
|
'2xs': '16rem',
|
||||||
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
sans: ['Outfit', ...defaultTheme.fontFamily.sans],
|
sans: ['Outfit', ...defaultTheme.fontFamily.sans],
|
||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
'white': '#D9DCFB',
|
'white': '#D9DCFB',
|
||||||
'default-background': '#040618',
|
'default-background': 'var(--theme-color-default-background)',
|
||||||
'default-background-separator': '#13152B',
|
'default-background-separator': '#13152B',
|
||||||
'card-background': 'var(--theme-color-card-background)',
|
'card-background': 'var(--theme-color-card-background)',
|
||||||
'card-background-active':
|
'card-background-active':
|
||||||
|
|||||||
Reference in New Issue
Block a user