Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui): introduce collapsible section + harmonize collapser - WF-47 #599

Merged
merged 2 commits into from
Oct 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/ui/src/components/core/base/BaseCollapseButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<template>
<button
role="button"
class="BaseCollapseIcon"
:class="{ 'BaseCollapseIcon--collapsed': isCollapsed }"
@click="isCollapsed = !isCollapsed"
>
<i class="material-symbols-outlined">{{ icon }}</i>
</button>
</template>

<script setup lang="ts">
import { computed, PropType } from "vue";

const props = defineProps({
direction: {
type: String as PropType<"left-right" | "top-bottom">,
required: true,
},
});

const isCollapsed = defineModel({ type: Boolean, required: true });

const icon = computed(() =>
props.direction === "left-right" ? "chevron_left" : "keyboard_arrow_up",
);
</script>

<style scoped>
.BaseCollapseIcon {
border: none;
border-radius: 50%;
padding: 4px;
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;

height: 32px;
width: 32px;
cursor: pointer;

transition: all 0.3s ease-in-out;
transform: rotate(0deg);

border: 1px solid var(--separatorColor);
}
.BaseCollapseIcon:hover {
background: var(--separatorColor);
}

.BaseCollapseIcon--collapsed {
transform: rotate(180deg);
}
</style>
49 changes: 10 additions & 39 deletions src/ui/src/components/core/layout/CoreColumn.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,12 @@
<div v-if="!isCollapsed" class="titleContainer">
<h3 v-if="fields.title.value">{{ fields.title.value }}</h3>
</div>
<div
<BaseCollapseButton
v-if="isCollapsible"
v-model="isCollapsed"
class="collapser"
@click="toggleCollapsed"
>
<IconGen
class="collapserArrow"
icon-key="collapseArrow"
></IconGen>
</div>
direction="left-right"
/>
</div>
<div v-if="isCollapsed && fields.title.value" class="collapsedTitle">
<div class="transformed">
Expand All @@ -31,6 +27,7 @@
</div>
<BaseContainer
class="container"
:aria-expanded="isCollapsible ? isCollapsed : null"
:content-h-align="fields.contentHAlign.value"
:content-v-align="fields.contentVAlign.value"
:content-padding="fields.contentPadding.value"
Expand All @@ -48,7 +45,10 @@ import {
contentVAlign,
cssClasses,
separatorColor,
startCollapsed,
isCollapsible as isCollapsibleField,
} from "@/renderer/sharedStyleFields";
import BaseCollapseButton from "../base/BaseCollapseButton.vue";

const description =
"A layout component that organises its child components in columns. Must be inside a Column Container component.";
Expand Down Expand Up @@ -83,25 +83,9 @@ export default {
},
category: FieldCategory.Style,
},
isCollapsible: {
name: "Collapsible",
default: "no",
type: FieldType.Text,
options: {
yes: "Yes",
no: "No",
},
category: FieldCategory.Style,
},
isCollapsible: isCollapsibleField,
startCollapsed: {
name: "Start collapsed",
type: FieldType.Text,
category: FieldCategory.Style,
default: "no",
options: {
yes: "Yes",
no: "No",
},
...startCollapsed,
desc: "Only applied when the column is collapsible.",
},
separatorColor,
Expand All @@ -111,13 +95,11 @@ export default {
cssClasses,
},
},
components: { IconGen },
};
</script>
<script setup lang="ts">
import { computed, ComputedRef, inject, Ref, ref, watch } from "vue";
import injectionKeys from "@/injectionKeys";
import IconGen from "@/renderer/IconGen.vue";
import BaseContainer from "../base/BaseContainer.vue";
const instancePath = inject(injectionKeys.instancePath);
const instanceData = inject(injectionKeys.instanceData);
Expand All @@ -144,10 +126,6 @@ const rootStyle = computed(() => {
return style;
});

const toggleCollapsed = () => {
isCollapsed.value = !isCollapsed.value;
};

/* Collapsing direction
The minimum non-collapsible column position (mnccp) determines how other columns collapse.
Those with a position lower than mnccp collapse to the left.
Expand Down Expand Up @@ -232,13 +210,6 @@ watch(
.CoreColumn > .header > .collapser {
order: 2;
flex: 0 0 32px;
border-radius: 16px;
padding: 4px;
background: var(--separatorColor);
display: flex;
align-items: center;
justify-content: center;
stroke: var(--primaryTextColor);
}

.CoreColumn > .header > .collapser > .collapserArrow {
Expand Down
41 changes: 37 additions & 4 deletions src/ui/src/components/core/layout/CoreSection.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
<template>
<section class="CoreSection">
<h3 v-if="fields.title.value">{{ fields.title.value }}</h3>
<section
class="CoreSection"
:class="{ 'CoreSection--collapsible': isCollapsible }"
>
<div
v-if="fields.title.value || isCollapsible"
class="CoreSection__title"
:class="{
'CoreSection__title--collapsed': isCollapsible && isCollapsed,
}"
>
<h3>{{ fields.title.value }}</h3>
<BaseCollapseButton
v-if="isCollapsible"
v-model="isCollapsed"
direction="top-bottom"
/>
</div>
<BaseContainer
v-if="!isCollapsed"
:content-h-align="fields.contentHAlign.value"
:content-padding="fields.contentPadding.value"
:aria-expanded="isCollapsible ? isCollapsed : null"
>
<slot></slot>
</BaseContainer>
Expand All @@ -25,6 +43,8 @@ import {
cssClasses,
contentHAlign,
contentPadding,
isCollapsible as isCollapsibleField,
startCollapsed,
} from "@/renderer/sharedStyleFields";

const description =
Expand All @@ -43,6 +63,8 @@ export default {
desc: "Leave blank to hide.",
type: FieldType.Text,
},
isCollapsible: isCollapsibleField,
startCollapsed,
accentColor,
primaryTextColor,
secondaryTextColor,
Expand All @@ -64,11 +86,17 @@ export default {
};
</script>
<script setup lang="ts">
import { inject } from "vue";
import { computed, inject, ref } from "vue";
import injectionKeys from "@/injectionKeys";
import BaseContainer from "../base/BaseContainer.vue";
import BaseCollapseButton from "../base/BaseCollapseButton.vue";

const fields = inject(injectionKeys.evaluatedFields);

const isCollapsible = computed(() => fields.isCollapsible.value === "yes");
const isCollapsed = ref<boolean>(
isCollapsible.value && fields.startCollapsed.value === "yes",
);
</script>

<style scoped>
Expand All @@ -80,7 +108,12 @@ const fields = inject(injectionKeys.evaluatedFields);
background-color: var(--containerBackgroundColor);
}

h3 {
.CoreSection__title {
margin: 16px 16px 0 16px;
display: grid;
grid-template-columns: 1fr auto;
}
.CoreSection__title--collapsed {
margin: 16px;
}
</style>
33 changes: 5 additions & 28 deletions src/ui/src/components/core/layout/CoreSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@
}"
>
<div class="collapserContainer">
<div class="collapser" @click="toggleCollapsed">
<IconGen
class="collapserArrow"
icon-key="collapseArrow"
></IconGen>
</div>
<BaseCollapseButton v-model="isCollapsed" direction="left-right" />
</div>
<div class="container" data-writer-container>
<slot></slot>
Expand All @@ -33,7 +28,9 @@ import {
buttonTextColor,
buttonShadow,
cssClasses,
startCollapsed,
} from "@/renderer/sharedStyleFields";
import BaseCollapseButton from "../base/BaseCollapseButton.vue";

const description =
"A container component that organises its children in a sidebar. Its parent must be a Page component.";
Expand All @@ -49,14 +46,8 @@ export default {
category: "Layout",
fields: {
startCollapsed: {
name: "Start collapsed",
type: FieldType.Text,
category: FieldCategory.Style,
default: "no",
options: {
yes: "Yes",
no: "No",
},
...startCollapsed,
desc: undefined,
},
sidebarBackgroundColor: {
name: "Background",
Expand All @@ -82,7 +73,6 @@ export default {
<script setup lang="ts">
import { computed, inject, onMounted, Ref, ref, watch } from "vue";
import injectionKeys from "@/injectionKeys";
import IconGen from "@/renderer/IconGen.vue";

const fields = inject(injectionKeys.evaluatedFields);
const isCollapsed: Ref<boolean> = ref(fields.startCollapsed.value == "yes");
Expand All @@ -91,10 +81,6 @@ const ssbm = inject(injectionKeys.builderManager);
const componentId = inject(injectionKeys.componentId);
const selectedId = computed(() => ssbm?.getSelectedId());

const toggleCollapsed = () => {
isCollapsed.value = !isCollapsed.value;
};

const rendererTop = ref(0);

const rootStyle = computed(() => {
Expand Down Expand Up @@ -153,15 +139,6 @@ onMounted(() => {

.collapserContainer > .collapser {
flex: 0 0 32px;
min-width: 32px;
border-radius: 16px;
padding: 4px;
display: flex;
align-items: center;
justify-content: center;
stroke: var(--primaryTextColor);
border: 1px solid var(--separatorColor);
pointer: cursor;
}

.collapserContainer .collapserArrow {
Expand Down
29 changes: 0 additions & 29 deletions src/ui/src/renderer/IconGen.vue

This file was deleted.

Loading
Loading