Skip to content

Commit

Permalink
add: resizeble panels, fix: search, refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
mnenie committed Jul 15, 2024
1 parent c245aca commit c2a6edc
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 43 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"floating-vue": "^5.2.2",
"lucide-vue-next": "^0.396.0",
"pinia": "^2.1.7",
"splitpanes": "^3.1.5",
"vee-validate": "^4.13.1",
"vue": "^3.4.29",
"vue-router": "^4.3.3",
Expand Down
1 change: 1 addition & 0 deletions public/icons/arrow-back.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/arrows.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/app/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ import { Toaster } from 'vue-sonner';
</KeepAlive>
</RouterView>
</component>
<Toaster position="bottom-right" closeButton />
<Toaster position="bottom-right" close-button />
</template>
6 changes: 3 additions & 3 deletions src/app/providers/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const router = createRouter({
router.beforeEach((to, from) => {
// TODO(@mnenie): Add guards logic
// Needs to add guard auth logic in router
if (to.meta.requiresAuth === true) {
return router.push({ name: RouteNames.login });
}
// if (to.meta.requiresAuth === true) {
// return router.push({ name: RouteNames.login });
// }
});
12 changes: 12 additions & 0 deletions src/app/styles/primary/exceptions.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,15 @@ canvas{
width: 100% !important;
height: 100% !important;
}

.splitpanes--vertical .splitpanes__pane{
transition: none;
}

.splitpanes--vertical > .splitpanes__splitter {
display: none;
}

.splitpanes__pane{
overflow: unset;
}
40 changes: 40 additions & 0 deletions src/features/filter/lib/composables/useFilter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { nextTick, onMounted, onUnmounted } from 'vue';
import type { Ref } from 'vue';

export default function useFilter(
inputRef: Ref<HTMLElement | null>,
props: { isExpanded: boolean },
emit: (e: 'onToggle') => void
) {
const onToggleArea = () => {
if (!props.isExpanded) {
emit('onToggle');
nextTick(() => {
inputRef.value = document.getElementById('input') as HTMLInputElement;
if (inputRef.value) {
inputRef.value.focus();
}
});
}
};
const handleKeyDownFilter = (e: KeyboardEvent) => {
if (document) {
inputRef.value = document.getElementById('input')!;
if (e.metaKey && e.key === 'k') {
inputRef.value.focus();
}
}
};

onMounted(() => {
window.addEventListener('keydown', handleKeyDownFilter);
});
onUnmounted(() => {
window.removeEventListener('keydown', handleKeyDownFilter);
});

return {
handleKeyDownFilter,
onToggleArea
};
}
36 changes: 33 additions & 3 deletions src/features/filter/ui/SearchFilter.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
<script setup lang="ts">
import { UiInput, UiBadge } from '@/shared/ui';
import { Search } from 'lucide-vue-next';
import { ref } from 'vue';
import { computed, ref } from 'vue';
import useFilter from '../lib/composables/useFilter';
const props = defineProps<{
isExpanded: boolean;
}>();
const emit = defineEmits<{
(e: 'onToggle'): void;
}>();
const search = ref('');
const inputRef = ref<HTMLElement | null>(null);
const iconColor = computed(() => {
return props.isExpanded ? 'rgb(82 82 91 / 0.9)' : 'var(--zinc-700)';
});
const { onToggleArea } = useFilter(inputRef, props, emit);
</script>

<template>
<div :class="$style.search_container">
<Search :class="$style.icon" :color="'rgb(82 82 91 / 0.9)'" />
<Search
:class="[isExpanded ? $style.icon : $style.icon_no_expanded]"
:color="iconColor"
@click="onToggleArea"
/>
<UiInput
v-show="isExpanded"
id="input"
ref="inputRef"
v-model.trim="search"
:placeholder="'Search'"
:class="$style.input_filter"
/>
<UiBadge variant="secondary" :class="$style.badge">
<UiBadge v-show="isExpanded" variant="secondary" :class="$style.badge">
<span>⌘</span>
<span>K</span>
</UiBadge>
Expand All @@ -38,6 +58,16 @@ const search = ref('');
width: 16px;
}
.icon_no_expanded {
cursor: pointer;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
height: 16px;
width: 16px;
}
.input_filter {
padding-left: 24px;
padding-right: 40px;
Expand Down
47 changes: 42 additions & 5 deletions src/features/plan/ui/PlanCard.vue
Original file line number Diff line number Diff line change
@@ -1,33 +1,51 @@
<script setup lang="ts">
import { UiProgressBar } from '@/shared/ui';
import { WandSparkles } from 'lucide-vue-next';
import { computed } from 'vue';
const props = defineProps<{
isExpanded: boolean;
}>();
const planPosition = computed(() => {
return props.isExpanded ? 'flex-start' : 'center';
});
const iconSize = computed(() => {
return props.isExpanded ? '18px' : '17px';
});
</script>
<template>
<div>
<div :class="$style.content">
<WandSparkles :class="$style.icon" :color="'var(--zinc-900)'" />
<div :class="$style.plan_about">
<WandSparkles :class="$style.icon" :color="'var(--zinc-700)'" />
<div v-if="isExpanded" :class="$style.plan_about">
<div :class="$style.text">
<span class="text-xs">Upgrade your plan</span>
<span class="text-xs">6/10</span>
</div>
<UiProgressBar :progress="6" />
</div>
<div v-else :class="$style.absolute_plan">
<span>6</span>
</div>
</div>
</div>
</template>

<style module lang="scss">
.content {
position: relative;
display: flex;
align-items: flex-start;
align-items: v-bind('planPosition');
justify-content: v-bind('planPosition');
gap: 8px;
width: 100%;
.icon {
min-width: 16px;
width: 18px;
height: 18px;
width: v-bind('iconSize');
height: v-bind('iconSize');
}
.plan_about {
Expand All @@ -50,5 +68,24 @@ import { WandSparkles } from 'lucide-vue-next';
}
}
}
.absolute_plan {
position: absolute;
right: -2px;
top: -4px;
width: 11px;
height: 11px;
display: flex;
align-items: center;
justify-content: center;
background-color: var(--purple-main);
border-radius: 50%;
& > span {
color: white;
font-weight: 500 !important;
font-size: 9px;
}
}
}
</style>
45 changes: 36 additions & 9 deletions src/layouts/ui/SidebarLayout.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,45 @@
<script setup lang="ts">
// @ts-expect-error missing type
import { Splitpanes, Pane } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';
import { computed, ref } from 'vue';
import { Sidebar, HeaderMain } from '@/widgets/layout';
import { useLocalStorage } from '@vueuse/core';
const isExpanded = useLocalStorage('isExpanded', true);
const transitionFl = ref(false);
const widthSidebar = computed(() => {
return isExpanded.value ? '22%' : '4%';
});
const widthMainContainer = computed(() => {
return `calc(100% - ${widthSidebar.value})`;
});
const onToggleArea = () => {
isExpanded.value = !isExpanded.value;
transitionFl.value = true;
};
</script>

<template>
<div :class="$style.sidebar_layout">
<Sidebar />
<div :class="$style.main_part">
<HeaderMain />
<div :class="$style.slot">
<slot />
<Splitpanes :class="$style.sidebar_layout">
<Pane
min-size="4"
max-size="22"
:size="widthSidebar"
:style="{ transition: transitionFl && 'width .2s ease-out' }"
>
<Sidebar :is-expanded @on-toggle="onToggleArea" />
</Pane>
<Pane :size="widthMainContainer">
<div :class="$style.main_part">
<HeaderMain />
<div :class="$style.slot">
<slot />
</div>
</div>
</div>
</div>
</Pane>
</Splitpanes>
</template>

<style module lang="scss">
Expand All @@ -26,7 +54,6 @@ import { Sidebar, HeaderMain } from '@/widgets/layout';
display: flex;
flex-direction: column;
height: 100%;
width: calc(100% - 260px);
.slot {
background-color: var(--zinc-50);
Expand Down
Loading

0 comments on commit c2a6edc

Please sign in to comment.