-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #329 from matematikk-mooc/TheresePersen-KURSP-901-…
…Module-selector Module selector menu
- Loading branch information
Showing
10 changed files
with
1,408 additions
and
487 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
<template> | ||
<div class="module-package"> | ||
<div | ||
class="module-package__title" | ||
:class="{ 'module-package__title--active': isActive }" | ||
@click="toggleCollapse" | ||
@keydown.enter="toggleCollapse" | ||
@keydown.space="toggleCollapse" | ||
tabindex="0" | ||
:aria-expanded="!collapsed" | ||
:role="isLeaf ? 'button' : 'treeitem'" | ||
> | ||
<div :class="{ 'module-package__indicator--active': isActive }"></div> | ||
<h4> | ||
<span | ||
class="module-package__dropdown-indicator" | ||
:class="{ 'module-package__dropdown-indicator--collapsed': collapsed }" | ||
> | ||
<Icon name="expand_more" size="2em" /> | ||
</span> | ||
<span class="title">{{ label }}</span> | ||
</h4> | ||
</div> | ||
|
||
<ul | ||
class="module-package__child-nodes" | ||
:class="{ 'module-package__child-nodes--hidden': collapsed }" | ||
tabindex="0" | ||
:aria-hidden="collapsed || isLeaf" | ||
:role="collapsed || isLeaf ? 'presentation' : 'group'" | ||
> | ||
<li v-for="course in nodes" :key="course.label"> | ||
<TreeView | ||
:type="course.type" | ||
:label="course.label" | ||
:nodes="course.nodes" | ||
:isCompleted="course.isCompleted" | ||
:isActive="isActive && course.label === selectedNode" | ||
@toggleActiveModule="toggleActiveModule" | ||
/> | ||
</li> | ||
</ul> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
import { ref, computed, defineProps, defineEmits } from 'vue'; | ||
import Icon from '../icon/Icon.vue'; | ||
import TreeView from '../tree-view/TreeView.vue'; | ||
const props = defineProps({ | ||
type: String, | ||
label: String, | ||
nodes: Array, | ||
isActive: Boolean, | ||
}); | ||
const emits = defineEmits(['toggleActiveModule']); | ||
const collapsed = ref(true); | ||
const selectedNode = ref(null); | ||
const isLeaf = computed(() => props.nodes.length === 0); | ||
const toggleCollapse = () => { | ||
if (!isLeaf.value) { | ||
collapsed.value = !collapsed.value; | ||
emits('toggleActiveModule', { module: props.label, isOpen: !collapsed.value }); | ||
} | ||
}; | ||
const toggleActiveModule = ({module, isOpen}) => { | ||
if (selectedNode.value === module) { | ||
if (isOpen) { | ||
selectedNode.value = module; | ||
} else { | ||
selectedNode.value = null; | ||
} | ||
} else { | ||
if (isOpen) { | ||
selectedNode.value = module; | ||
} else { | ||
selectedNode.value = null; | ||
} | ||
} | ||
}; | ||
</script> | ||
|
||
<style lang="scss"> | ||
@import '../../design/hide-show-effect'; | ||
@import '../../design/colors.scss'; | ||
.module-package { | ||
border-top: 0.0625rem solid $color-grey-400; | ||
position:relative; | ||
&__title { | ||
cursor: pointer; | ||
display: flex; | ||
align-items: center; | ||
padding:0.5rem 1.5rem 0.5rem 1.5rem; | ||
height: 4.375rem; | ||
color: $color-black; | ||
font-family: Roboto; | ||
font-size: 1.125rem; | ||
vertical-align: center; | ||
position: relative; | ||
.module-package__indicator--active{ | ||
position: absolute; | ||
z-index:2; | ||
border-radius: 0rem 0.4375rem 0.4375rem 0rem; | ||
background: map-get($color-palette-green, background, 500); | ||
width: 0.875rem; | ||
height: 100%; | ||
right: -0.875rem; | ||
pointer-events: none; | ||
@include hide-show-effect; | ||
} | ||
h4 { | ||
font-weight: 400; | ||
font-size: 1.125rem; | ||
line-height: normal; | ||
letter-spacing:0.063rem ; | ||
display:flex; | ||
align-items: center; | ||
} | ||
&--active { | ||
h4 { | ||
font-weight: 700; | ||
} | ||
} | ||
} | ||
.module-package__dropdown-indicator { | ||
display: inline-block; | ||
transition: transform 0.3s; | ||
font-size: 1.125rem; | ||
&--collapsed { | ||
transform: rotate(-90deg); | ||
} | ||
} | ||
&__child-nodes { | ||
list-style-type: none; | ||
background: map-get($color-palette-slate, background, 200); | ||
padding: 0.2rem 0 0.2rem 1.5rem; | ||
margin:0; | ||
@include hide-show-effect; | ||
&--hidden{ | ||
display: none; | ||
} | ||
} | ||
} | ||
</style> | ||
|
||
|
||
|
||
|
||
|
25 changes: 25 additions & 0 deletions
25
src/vue/components/course-modules/CourseModules.stories.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { defineComponent } from "vue"; | ||
import CourseModules from "./CourseModules.vue" | ||
import { tree_data_2_levels, tree_data_3_levels } from "./test-data"; | ||
|
||
export default { | ||
title: "Components/CourseModules", | ||
}; | ||
const Template = (args) => | ||
defineComponent({ | ||
components: { CourseModules }, | ||
setup() { | ||
return { args }; | ||
}, | ||
template: '<CourseModules v-bind="args" />', | ||
}); | ||
|
||
export const TwoLevelTree = Template.bind({}); | ||
TwoLevelTree.args = { | ||
nodes: tree_data_2_levels, | ||
}; | ||
|
||
export const ThreeLevelTree = Template.bind({}); | ||
ThreeLevelTree.args = { | ||
nodes: tree_data_3_levels, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<template> | ||
<div class="courses"> | ||
<div class="courses__header-section"> | ||
<h3 tabindex="0" class="courses__header-section__header" @keydown.enter="toggleActiveModule(null)"> | ||
<Icon name="format_list_numbered" size="1em" /> | ||
<span class="courses__header-section__header__title">Moduler</span> | ||
</h3> | ||
</div> | ||
<div class="courses__treeview"> | ||
<div | ||
class="courses__treeview__item" | ||
v-for="(module, index) in treestructure" | ||
:key="index" | ||
> | ||
<CourseModule | ||
:type="module.type" | ||
:label="module.label" | ||
:nodes="module.nodes" | ||
:isActive="isActiveModule(module.label)" | ||
@toggleActiveModule="toggleActiveModule" | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
import { defineProps, ref } from 'vue'; | ||
import Icon from '../icon/Icon.vue'; | ||
import CourseModule from './CourseModule.vue'; | ||
const props = defineProps({ | ||
nodes: Array, | ||
}); | ||
const treestructure = props.nodes; // Assign nodes prop to treestructure | ||
const selectedNode = ref(null); | ||
const toggleActiveModule = ({module, isOpen}) => { | ||
if (selectedNode.value === module) { | ||
if (isOpen) { | ||
selectedNode.value = module; | ||
} else { | ||
selectedNode.value = null; | ||
} | ||
} else { | ||
if (isOpen) { | ||
selectedNode.value = module; | ||
} else { | ||
selectedNode.value = null; | ||
} | ||
} | ||
}; | ||
const isActiveModule = (nodeLabel) => { | ||
return nodeLabel === selectedNode.value; | ||
}; | ||
</script> | ||
|
||
|
||
<style lang="scss"> | ||
@import '../../design/box-shadow'; | ||
@import '../../design/colors.scss'; | ||
.courses { | ||
width: 100%; | ||
max-width: 35rem; | ||
border-radius: 1.6875rem 0rem 0rem 1.6875rem; | ||
border: 0.0625rem solid $color-grey-400; | ||
background: $color-white; | ||
margin: 0 1rem 0 1rem; | ||
padding: 0 0 0.75rem 0; | ||
@include box-shadow(medium); | ||
&__header-section { | ||
color: black; | ||
word-wrap: break-word; | ||
border-bottom: 0.125rem solid $color-grey-400; | ||
padding: 1.75rem 1rem 0.625rem 1.5rem; | ||
&__header{ | ||
display:flex; | ||
align-items: center; | ||
justify-content: flex-start; | ||
font-size: 1.25rem; | ||
font-family: Roboto; | ||
font-weight: 600; | ||
margin-left: 1rem; | ||
&__title{ | ||
margin-left:1.5rem; | ||
margin-top: -0.5rem; | ||
} | ||
} | ||
} | ||
&__treeview { | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: flex-start; | ||
padding-bottom:1rem; | ||
} | ||
} | ||
</style> |
Oops, something went wrong.