Browse Source

feat: Fixed sidebar expand issue in mobile, handles different topbar size for desktop and mobile, added changes to NcButton, layouts

pull/6474/head
Muhammed Mustafa 1 year ago
parent
commit
f97ae99bb8
  1. 4
      packages/nc-gui/assets/style.scss
  2. 2
      packages/nc-gui/components/dashboard/Sidebar.vue
  3. 17
      packages/nc-gui/components/dashboard/Sidebar/Header.vue
  4. 5
      packages/nc-gui/components/dashboard/Sidebar/TopSection.vue
  5. 29
      packages/nc-gui/components/dashboard/Sidebar/UserInfo.vue
  6. 34
      packages/nc-gui/components/dashboard/View.vue
  7. 8
      packages/nc-gui/components/general/OpenLeftSidebarBtn.vue
  8. 34
      packages/nc-gui/components/nc/Button.vue
  9. 11
      packages/nc-gui/components/smartsheet/Topbar.vue
  10. 1
      packages/nc-gui/components/smartsheet/grid/Table.vue
  11. 2
      packages/nc-gui/components/smartsheet/toolbar/ViewInfo.vue
  12. 20
      packages/nc-gui/layouts/base.vue
  13. 3
      packages/nc-gui/store/config.ts

4
packages/nc-gui/assets/style.scss

@ -48,6 +48,10 @@ main {
@apply m-0 h-full w-full bg-white;
}
.nc-app.mobile *:hover {
background-color:unset!important;
}
.nc-input-md {
@apply !rounded-lg !py-2 !px-3 mb-1;
}

2
packages/nc-gui/components/dashboard/Sidebar.vue

@ -52,7 +52,7 @@ onUnmounted(() => {
>
<LazyDashboardTreeView v-if="!isWorkspaceLoading" />
</div>
<div v-if="!isSharedBase" style="height: var(--sidebar-bottom-height)">
<div v-if="!isSharedBase">
<DashboardSidebarUserInfo />
</div>
</div>

17
packages/nc-gui/components/dashboard/Sidebar/Header.vue

@ -10,7 +10,11 @@ const { isMobileMode } = useGlobal()
<template>
<div
class="flex items-center px-2 nc-sidebar-header py-1.2 w-full border-b-1 border-gray-200 group"
class="flex items-center nc-sidebar-header w-full border-b-1 border-gray-200 group"
:class="{
'px-2 py-1.2': isMobileMode,
'px-1 py-1': isMobileMode,
}"
:data-workspace-title="activeWorkspace?.title"
style="height: var(--topbar-height)"
>
@ -20,7 +24,7 @@ const { isMobileMode } = useGlobal()
<div class="flex flex-grow min-w-1"></div>
<NcTooltip
class="flex opacity-0 group-hover:opacity-100 transition-opacity duration-50"
class="flex"
:class="{
'!opacity-100': !isLeftSidebarOpen,
}"
@ -35,13 +39,18 @@ const { isMobileMode } = useGlobal()
}}
</template>
<NcButton
type="text"
size="small"
:type="isMobileMode ? 'secondary' : 'text'"
:size="isMobileMode ? 'medium' : 'small'"
class="nc-sidebar-left-toggle-icon !text-gray-700 !hover:text-gray-800 !hover:bg-gray-200"
:class="{
'!h-10.5 !max-h-10.5 !max-w-10.5': isMobileMode,
}"
@click="isLeftSidebarOpen = !isLeftSidebarOpen"
>
<div class="flex items-center text-inherit">
<GeneralIcon v-if="isMobileMode" icon="close" />
<GeneralIcon
v-else
icon="doubleLeftArrow"
class="duration-150 transition-all !text-lg -mt-0.5"
:class="{

5
packages/nc-gui/components/dashboard/Sidebar/TopSection.vue

@ -4,7 +4,7 @@ const projectStore = useProject()
const { isUIAllowed } = useRoles()
const { appInfo } = useGlobal()
const { appInfo, isMobileMode } = useGlobal()
const { isWorkspaceLoading, isWorkspaceSettingsPageOpened } = storeToRefs(workspaceStore)
@ -47,7 +47,7 @@ const navigateToSettings = () => {
<DashboardSidebarTopSectionHeader />
<NcButton
v-if="isUIAllowed('workspaceSettings')"
v-if="isUIAllowed('workspaceSettings') && !isMobileMode"
type="text"
size="small"
class="nc-sidebar-top-button"
@ -65,6 +65,7 @@ const navigateToSettings = () => {
</div>
</NcButton>
<WorkspaceCreateProjectBtn
v-if="!isMobileMode"
v-model:is-open="isCreateProjectOpen"
modal
type="text"

29
packages/nc-gui/components/dashboard/Sidebar/UserInfo.vue

@ -19,6 +19,8 @@ const isAuthTokenCopied = ref(false)
const isLoggingOut = ref(false)
const { isMobileMode } = useGlobal()
const logout = async () => {
isLoggingOut.value = true
try {
@ -85,7 +87,7 @@ onMounted(() => {
<span class="menu-btn"> Log Out </span>
</NcMenuItem>
<NcDivider />
<a href="https://docs.nocodb.com" target="_blank" class="!underline-transparent">
<a v-if="!isMobileMode" href="https://docs.nocodb.com" target="_blank" class="!underline-transparent">
<NcMenuItem>
<GeneralIcon icon="help" class="menu-icon mt-0.5" />
<span class="menu-btn"> Help Center </span>
@ -130,21 +132,24 @@ onMounted(() => {
</a-popover>
</template>
<NcDivider />
<NcMenuItem @click="onCopy">
<GeneralIcon v-if="isAuthTokenCopied" icon="check" class="group-hover:text-black menu-icon" />
<GeneralIcon v-else icon="copy" class="menu-icon" />
<template v-if="isAuthTokenCopied"> Copied Auth Token </template>
<template v-else> Copy Auth Token </template>
</NcMenuItem>
<nuxt-link v-e="['c:navbar:user:email']" class="!no-underline" to="/account/profile">
<NcMenuItem> <GeneralIcon icon="settings" class="menu-icon" /> Account Settings </NcMenuItem>
</nuxt-link>
<template v-if="!isMobileMode">
<NcDivider />
<NcMenuItem @click="onCopy">
<GeneralIcon v-if="isAuthTokenCopied" icon="check" class="group-hover:text-black menu-icon" />
<GeneralIcon v-else icon="copy" class="menu-icon" />
<template v-if="isAuthTokenCopied"> Copied Auth Token </template>
<template v-else> Copy Auth Token </template>
</NcMenuItem>
<nuxt-link v-e="['c:navbar:user:email']" class="!no-underline" to="/account/profile">
<NcMenuItem> <GeneralIcon icon="settings" class="menu-icon" /> Account Settings </NcMenuItem>
</nuxt-link>
</template>
</NcMenu>
</template>
</NcDropdown>
<div v-if="appInfo.ee" class="text-gray-500 text-xs pl-3">© 2023 NocoDB. Inc</div>
<template v-if="isMobileMode"></template>
<div v-else-if="appInfo.ee" class="text-gray-500 text-xs pl-3">© 2023 NocoDB. Inc</div>
<div v-else-if="isMounted" class="flex flex-row justify-between pt-1 truncate">
<div class="flex flex-wrap mb-1">
<GithubButton

34
packages/nc-gui/components/dashboard/View.vue

@ -16,11 +16,9 @@ const {
const wrapperRef = ref<HTMLDivElement>()
const contentSize = computed(() => 100 - sideBarSize.value.current)
const animationDuration = 250
const viewportWidth = ref(window.innerWidth)
const sidebarWidth = computed(() => (sideBarSize.value.old * viewportWidth.value) / 100)
const currentSidebarSize = computed({
get: () => sideBarSize.value.current,
set: (val) => {
@ -29,6 +27,28 @@ const currentSidebarSize = computed({
},
})
const contentSize = computed(() => 100 - sideBarSize.value.current)
const mobileNormalizedSidebarSize = computed(() => {
if (isMobileMode.value) {
return isLeftSidebarOpen.value ? 100 : 0
}
return currentSidebarSize.value
})
const mobileNormalizedContentSize = computed(() => {
if (isMobileMode.value) {
return isLeftSidebarOpen.value ? 0 : 100
}
return contentSize.value
})
const sidebarWidth = computed(() =>
isMobileMode.value ? viewportWidth.value : (sideBarSize.value.old * viewportWidth.value) / 100,
)
watch(currentSidebarSize, () => {
leftSidebarWidthPercent.value = currentSidebarSize.value
})
@ -54,6 +74,7 @@ watch(isLeftSidebarOpen, () => {
})
function handleMouseMove(e: MouseEvent) {
if (isMobileMode.value) return
if (!wrapperRef.value) return
if (sidebarState.value === 'openEnd') return
@ -105,7 +126,12 @@ watch(isMobileMode, () => {
}"
@resize="currentSidebarSize = $event[0].size"
>
<Pane min-size="15%" :size="currentSidebarSize" max-size="40%" class="nc-sidebar-splitpane relative !overflow-visible">
<Pane
min-size="15%"
:size="mobileNormalizedSidebarSize"
max-size="40%"
class="nc-sidebar-splitpane relative !overflow-visible"
>
<div
ref="wrapperRef"
class="nc-sidebar-wrapper relative flex flex-col h-full justify-center !min-w-32 absolute overflow-visible"
@ -121,7 +147,7 @@ watch(isMobileMode, () => {
<slot name="sidebar" />
</div>
</Pane>
<Pane :size="contentSize">
<Pane :size="mobileNormalizedContentSize">
<slot name="content" />
</Pane>
</Splitpanes>

8
packages/nc-gui/components/general/OpenLeftSidebarBtn.vue

@ -27,8 +27,8 @@ const onClick = () => {
hide-on-click
class="transition-all duration-100"
:class="{
'!w-0 !opacity-0': isLeftSidebarOpen,
'!w-8 !opacity-100': !isLeftSidebarOpen,
'!opacity-0': !isMobileMode && isLeftSidebarOpen,
'!opacity-100': isMobileMode || !isLeftSidebarOpen,
}"
>
<template #title>
@ -40,10 +40,10 @@ const onClick = () => {
</template>
<NcButton
:type="isMobileMode ? 'secondary' : 'text'"
size="small"
:size="isMobileMode ? 'medium' : 'small'"
class="nc-sidebar-left-toggle-icon !text-gray-600 !hover:text-gray-800"
:class="{
'invisible !w-0': isLeftSidebarOpen,
'invisible !w-0': !isMobileMode && isLeftSidebarOpen,
}"
@click="onClick"
>

34
packages/nc-gui/components/nc/Button.vue

@ -41,6 +41,8 @@ const type = computed(() => props.type)
const loading = useVModel(props, 'loading', emits)
const { isMobileMode } = useGlobal()
const isFocused = ref(false)
const isClicked = ref(false)
@ -84,6 +86,7 @@ useEventListener(NcButton, 'mousedown', () => {
xsmall: size === 'xsmall',
xxsmall: size === 'xxsmall',
focused: isFocused,
mobile: isMobileMode,
}"
@focus="onFocus"
@blur="onBlur"
@ -141,8 +144,19 @@ useEventListener(NcButton, 'mousedown', () => {
outline: none;
}
.nc-button.ant-btn.focused {
box-shadow: 0px 0px 0px 2px #fff, 0px 0px 0px 4px #3069fe;
.nc-button.mobile {
box-shadow: none;
outline: none;
}
.desktop {
.nc-button.ant-btn.focused {
box-shadow: 0px 0px 0px 2px #fff, 0px 0px 0px 4px #3069fe;
}
.nc-button.ant-btn-text.focused {
@apply text-brand-500;
}
}
.nc-button.ant-btn {
@ -153,8 +167,16 @@ useEventListener(NcButton, 'mousedown', () => {
@apply py-1 px-1.75 h-8 min-w-8;
}
.nc-button.ant-btn.medium {
@apply py-2 px-4 h-10 min-w-10;
.desktop {
.nc-button.ant-btn.medium {
@apply py-2 px-4 h-10 min-w-10;
}
}
.mobile {
.nc-button.ant-btn.medium {
@apply h-10.5 max-h-10.5 min-w-10.5 !px-3;
}
}
.nc-button.ant-btn.xsmall {
@ -211,8 +233,4 @@ useEventListener(NcButton, 'mousedown', () => {
box-shadow: none;
}
}
.nc-button.ant-btn-text.focused {
@apply text-brand-500;
}
</style>

11
packages/nc-gui/components/smartsheet/Topbar.vue

@ -17,11 +17,7 @@ const isSharedBase = computed(() => route.value.params.typeOrId === 'base')
<template>
<div
class="nc-table-topbar h-20 py-1 flex gap-2 items-center pr-2 pl-2.5 border-b border-gray-200 overflow-hidden relative"
:class="{
'nc-table-toolbar-mobile': isMobileMode,
'max-h-[var(--topbar-height)] min-h-[var(--topbar-height)]': !isMobileMode,
}"
class="nc-table-topbar h-20 py-1 flex gap-2 items-center pr-2 pl-2.5 border-b border-gray-200 overflow-hidden relative max-h-[var(--topbar-height)] min-h-[var(--topbar-height)]"
style="z-index: 7"
>
<template v-if="isViewsLoading">
@ -39,7 +35,10 @@ const isSharedBase = computed(() => route.value.params.typeOrId === 'base')
<GeneralApiLoader v-if="!isMobileMode" />
<LazyGeneralShareProject v-if="(isForm || isGrid || isKanban || isGallery || isMap) && !isPublic" is-view-toolbar />
<LazyGeneralShareProject
v-if="(isForm || isGrid || isKanban || isGallery || isMap) && !isPublic && !isMobileMode"
is-view-toolbar
/>
<LazyGeneralLanguage
v-if="isSharedBase"

1
packages/nc-gui/components/smartsheet/grid/Table.vue

@ -1585,6 +1585,7 @@ const expandAndLooseFocus = (row: Row, col: Record<string, any>) => {
</div>
<LazySmartsheetPagination
v-else-if="headerOnly !== true"
:key="isMobileMode"
v-model:pagination-data="paginationDataRef"
show-api-timing
align-count-on-right

2
packages/nc-gui/components/smartsheet/toolbar/ViewInfo.vue

@ -14,7 +14,7 @@ const { activeTable } = storeToRefs(useTablesStore())
:class="{
'min-w-2/5 max-w-2/5': !isMobileMode && activeView?.type !== ViewTypes.KANBAN,
'min-w-1/4 max-w-1/4': !isMobileMode && activeView?.type === ViewTypes.KANBAN,
'min-w-1/2 max-w-1/2 text-base': isMobileMode,
'w-2/3 text-base ml-1.5': isMobileMode,
}"
>
<template v-if="!(isMobileMode && !activeView?.is_default)">

20
packages/nc-gui/layouts/base.vue

@ -20,6 +20,8 @@ const logout = async () => {
const { hooks } = useNuxtApp()
const { isMobileMode } = useGlobal()
const isDashboard = computed(() => !!route.params.typeOrId)
/** when page suspensions have finished, check if a sidebar element was teleported into the layout */
@ -31,12 +33,20 @@ hooks.hook('page:finish', () => {
</script>
<template>
<a-layout id="nc-app" has-sider>
<a-layout
id="nc-app"
class="nc-app"
:class="{
mobile: isMobileMode,
desktop: !isMobileMode,
}"
has-sider
>
<Transition name="slide">
<div v-show="hasSider" id="nc-sidebar-left" ref="sidebar" />
</Transition>
<a-layout class="!flex-col">
<a-layout class="!flex-col h-screen">
<a-layout-header v-if="!route.meta.public && signedIn && !route.meta.hideHeader" class="nc-navbar">
<div
v-if="!route.params.projectType"
@ -134,7 +144,7 @@ hooks.hook('page:finish', () => {
<LazyGeneralLanguage v-if="!signedIn && !route.params.projectId && !route.params.erdUuid" class="nc-lang-btn" />
</a-tooltip>
<div class="w-full h-full overflow-hidden">
<div class="w-full h-full overflow-hidden nc-layout-base-inner">
<slot />
</div>
</a-layout>
@ -163,4 +173,8 @@ hooks.hook('page:finish', () => {
.nc-navbar {
@apply flex !bg-white items-center !pl-2 !pr-5;
}
.nc-layout-base-inner > div {
@apply h-full;
}
</style>

3
packages/nc-gui/store/config.ts

@ -17,6 +17,9 @@ export const useConfigStore = defineStore('configStore', () => {
isMobileMode,
() => {
globalIsMobile.value = isMobileMode.value
// Change --topbar-height css variable
document.documentElement.style.setProperty('--topbar-height', isMobileMode.value ? '3.25rem' : '3.1rem')
},
{
immediate: true,

Loading…
Cancel
Save