Skip to content

Instantly share code, notes, and snippets.

@CamKem
Created December 14, 2023 08:45
Show Gist options
  • Save CamKem/a7107b9a120025772e792dbdfd0afd60 to your computer and use it in GitHub Desktop.
Save CamKem/a7107b9a120025772e792dbdfd0afd60 to your computer and use it in GitHub Desktop.
Example of Responsive Layout Using HTML & CSS (Plus JavaScript)
<template>
<SidebarLayout v-if="$page.props.auth.user"
@newPost="handleNewPost"/>
<div id="wrapper"
class="flex w-full place-content-center">
<main id="main"
:class="[
layout.isMedium ? 'max-w-[980px]' : '',
layout.isLarge && !layout.isSidebarExpanded ? 'max-w-[956px]' : '',
layout.isLarge && layout.isSidebarExpanded ? 'max-w-[762px]' : '',
layout.is2xl || layout.isExtraLarge ? 'max-w-[1272px]' : '',
layout.isSmall ? 'max-w-screen min-w-[360px]' : '',
]"
class="h-full min-h-screen">
<div
v-if="layout.is2xl"
class="sticky top-20 ml-4 hidden h-80 w-[300px] column lg:block">
This the right column that will be sticky
and will contain the left sidebar
</div>
<div
:class="[
layout.isSmall ? 'w-screen' : 'border-x-2 border-gray-700',
layout.isMedium ? 'w-[580px] mx-4' : '',
layout.isLarge && layout.isSidebarExpanded ? 'w-[490px] mx-4' : '',
layout.isLarge && !layout.isSidebarExpanded ? 'w-[608px] mx-4' : '',
layout.isExtraLarge || layout.is2xl ? 'w-[608px] mx-4' : '',
]"
class="relative flex flex-col bg-sky-300 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-200"
>
<div
id="main-header"
:class="[
layout.greaterThanMedium ? 'fixed' : 'hidden',
layout.isSmall ? 'w-screen' : '',
layout.isMedium ? 'w-[576px]' : '',
layout.isLarge && layout.isSidebarExpanded ? 'w-[486px]' : '',
layout.isLarge && !layout.isSidebarExpanded ? 'w-[604px]' : '',
layout.isExtraLarge || layout.is2xl ? 'w-[604px]' : '',
]"
class="fixed flex items-center border-b-2 border-gray-700 pl-4 transition-all duration-300 ease-in-out pr-1.5 h-[54px] mt-[66px] dark:bg-gray-800"
>
<div
class="flex w-full h-full items-center justify-between">
<div
class="h-full flex items-center">
# <span
class="crumb">Dashboard</span> /
<span class="crumb">Feed</span>
</div>
<FeedButtonLayout/>
</div>
</div>
<div
:class="!layout.isSmall ? 'mt-[120px]' : 'mt-[66px]'"
class="overflow-y-auto overscroll-none"
scroll-region
>
<div ref="target"></div>
<slot/>
</div>
</div>
<div
:class="layout.isLarge && layout.isSidebarExpanded ? 'w-[218px]' : 'w-[300px]'"
class="sticky lg:flex lg:flex-col top-20 h-full hidden"
>
<p class="h-fit w-full column mb-4">
This the right column that will be
sticky
and will contain the right sidebar
</p>
<p class="h-fit w-full column">
Click here for support menu
<!-- TODO: support menu svg -->
</p>
</div>
</main>
</div>
<NewPostModal v-if="showNewPostModal"
@close="showNewPostModal = false"/>
</template>
<script setup>
import {computed, nextTick, onMounted, onUpdated, ref, watch} from "vue";
import {useElementVisibility, useWindowSize} from "@vueuse/core";
import useElementById from "../Composables/useElementById";
import {useLayoutStore} from "../Stores/layoutStore";
import SidebarLayout from "./Sidebar/SidebarLayout.vue";
import NewPostModal from "../Pages/Community/Dashboard/NewPostModal.vue";
import {usePage} from "@inertiajs/vue3";
import useButtons from "../Composables/useButtons";
import FeedButtonLayout from "./FeedButtonLayout.vue";
const layout = useLayoutStore();
const isLoggedIn = computed(() => usePage().props.auth.user);
onMounted(() => {
console.log("DashboardLayout mounted");
const number = ref(0);
onUpdated(() => {
number.value++;
console.log('DashboardLayout updated', number.value);
});
});
const tokens = ["bg-clip-padding", "backdrop-filter", "backdrop-blur-sm", "bg-opacity-60", "bg-gray-900"];
const target = ref(null);
const isVisible = useElementVisibility(target);
const header = useElementById("main-header");
const {buttonTokens, buttonsArray} = useButtons();
onMounted(() => {
watch(isVisible, (value) => {
buttonTokens.forEach(token => {
buttonsArray.value.forEach(button => {
button.classList.toggle(token, !value);
});
});
tokens.forEach(token => {
header.value.classList.toggle(token, !value);
header.value.classList.toggle("dark:bg-gray-800", value);
});
});
});
const handleNewPost = () => {
showNewPostModal.value = true;
}
const showNewPostModal = ref(false);
const handleResize = () => {
if (isLoggedIn.value) {
if (layout.greaterThanMedium) {
main.value.classList.add(openLeftMargin);
layout.setExpanded(false);
layout.openSidebar();
}
if (layout.isSmall) {
layout.closeSidebar();
main.value.classList.remove(openLeftMargin);
}
}
};
const {width} = useWindowSize();
watch(width, () => {
handleResize();
});
const main = useElementById("main");
const openLeftMargin = "ml-[64px]";
const expandedLeftMargin = "ml-[262px]";
watch(() => layout.isSidebarExpanded, (expanded) => {
if (isLoggedIn.value) {
if (layout.greaterThanLarge && layout.isSidebarOpen && expanded) {
nextTick(() => {
main.value.classList.remove(openLeftMargin);
main.value.classList.add(expandedLeftMargin);
});
}
if (layout.greaterThanLarge && layout.isSidebarOpen && !expanded) {
nextTick(() => {
main.value.classList.remove(expandedLeftMargin);
main.value.classList.add(openLeftMargin);
});
}
}
});
onMounted(() => {
if (layout.greaterThanMedium && isLoggedIn.value) {
main.value.classList.add(openLeftMargin);
layout.openSidebar();
}
});
</script>
<style scoped>
.column {
@apply rounded-lg bg-white p-4 shadow-lg transition-all duration-300 ease-in-out dark:bg-gray-800;
}
#main {
@apply relative flex transition-all duration-300 ease-in-out;
}
.crumb {
@apply text-gray-400 text-[0.9rem] hover:border-b-4 hover:border-yellow-300 hover:text-white dark:hover:border-sky-400;
@apply transform capitalize transition-all duration-200 ease-in-out hover:-translate-y-1 dark:hover:border-sky-400 dark:hover:text-sky-400;
@apply mx-2;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment