Show opening method on hover. Allow items to be opened in an iframe

This commit is contained in:
Alicia Sykes
2021-04-06 15:47:34 +01:00
parent 8ddc2506ac
commit 7fd36d9ec6
14 changed files with 9255 additions and 37157 deletions

View File

@@ -143,16 +143,16 @@ export default {
span.options-label {
font-size: 0.8rem;
color: #5cabca;
color: $ascent-with-opacity;
width: 5.5rem;
text-align: left;
}
.display-options {
color: $ascent;
color: $ascent-with-opacity;
svg {
path {
fill: $ascent;
fill: $ascent-with-opacity;
}
width: 1rem;
height: 1rem;
@@ -165,7 +165,7 @@ export default {
opacity: 0.8;
cursor: pointer;
&:hover, &.selected {
background: $ascent;
background: $ascent-with-opacity;
path { fill: $background; }
}
}

View File

@@ -1,33 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String,
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@@ -0,0 +1,30 @@
<template>
<modal name="iframe-modal" :resizable="true"
:adaptive="true" width="80%" height="80%">
<iframe :src="url" class="frame" />
</modal>
</template>
<script>
export default {
name: 'IframeModal',
props: {
url: String,
},
methods: {
show: function show() {
this.$modal.show('iframe-modal');
},
},
};
</script>
<style scoped lang="scss">
.frame {
width: 100%;
height: 100%;
border: none;
}
</style>

View File

@@ -1,6 +1,13 @@
<template>
<a :href="url" :class="`item ${!icon? 'short': ''}`" v-on:click="$emit('itemClicked')"
tabindex="0" target="_blank" rel="noopener noreferrer" v-tooltip="getTooltipOptions()">
<a
:href="target !== 'iframe' ? url : '#'"
v-on:click="itemOpened()"
:class="`item ${!icon? 'short': ''}`"
v-tooltip="getTooltipOptions()"
:target="target === 'newtab' ? '_blank' : ''"
rel="noopener noreferrer"
tabindex="0"
>
<!-- Item Text -->
<div class="tile-title" :id="`tile-${id}`">
<span class="text">{{ title }}</span>
@@ -8,11 +15,22 @@
</div>
<!-- Item Icon -->
<Icon :icon="icon" :url="url" />
<div :class="`opening-method-icon ${!icon? 'short': ''}`">
<NewTabOpenIcon v-if="target === 'newtab'" />
<SameTabOpenIcon v-else-if="target === 'sametab'" />
<IframeOpenIcon v-else-if="target === 'iframe'" />
</div>
<IframeModal v-if="target === 'iframe'" :url="url" ref="iframeModal"/>
</a>
</template>
<script>
import Icon from '@/components/ItemIcon.vue';
import IframeModal from '@/components/IframeModal.vue';
import NewTabOpenIcon from '@/assets/icons/open-new-tab.svg';
import SameTabOpenIcon from '@/assets/icons/open-current-tab.svg';
import IframeOpenIcon from '@/assets/icons/open-iframe.svg';
export default {
name: 'Item',
@@ -25,7 +43,7 @@ export default {
svg: String, // Optional vector graphic, that is then dynamically filled
color: String, // Optional background color, specified in hex code
url: String, // URL to the resource, optional but recommended
openingMethod: { // Where resource will open, either 'newtab', 'sametab' or 'iframe'
target: { // Where resource will open, either 'newtab', 'sametab' or 'iframe'
type: String,
default: 'newtab',
validator: (value) => ['newtab', 'sametab', 'iframe'].indexOf(value) !== -1,
@@ -38,11 +56,18 @@ export default {
},
components: {
Icon,
NewTabOpenIcon,
SameTabOpenIcon,
IframeOpenIcon,
IframeModal,
},
methods: {
/* Called when an item is opened, so that search field can be reset */
itemOpened() {
this.$emit('itemClicked');
if (this.target === 'iframe') {
this.$refs.iframeModal.show();
}
},
/**
* Detects overflowing text, shows ellipse, and allows is to marguee on hover
@@ -78,107 +103,128 @@ export default {
@import '../../src/styles/color-pallet.scss';
@import '../../src/styles/constants.scss';
/* Item wrapper */
.item {
flex-grow: 1;
height: 100px;
color: $ascent;
vertical-align: middle;
margin: 0.5rem;
background: #607d8b33;
text-align: center;
padding: 2px;
border: 2px solid transparent;
border-radius: $curve-factor;
box-shadow: 1px 1px 2px #373737;
cursor: pointer;
&:hover {
box-shadow: 1px 2px 4px #373737;
background: #607d8b4d;
}
&:focus {
border: 2px solid $ascent;
outline: none;
}
&.short {
height: 18px;
}
flex-grow: 1;
height: 100px;
position: relative;
color: $ascent;
vertical-align: middle;
margin: 0.5rem;
background: #607d8b33;
text-align: center;
padding: 2px;
border: 2px solid transparent;
border-radius: $curve-factor;
box-shadow: 1px 1px 2px #373737;
cursor: pointer;
&:hover {
box-shadow: 1px 2px 4px #373737;
background: #607d8b4d;
}
&:focus {
border: 2px solid $ascent;
outline: none;
}
&.short {
height: 18px;
}
}
/* Text in tile */
.tile-title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 120px;
height: 30px;
overflow: hidden;
position: relative;
padding: 0;
span.text {
position: absolute;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 120px;
height: 30px;
overflow: hidden;
position: relative;
padding: 0;
transition: 1s;
float: left;
left: 0;
}
&:not(.is-overflowing) span.text{
width: 100%;
}
.overflow-dots {
opacity: 0;
}
&.is-overflowing {
span.text {
position: absolute;
white-space: nowrap;
transition: 1s;
float: left;
left: 0;
}
&:not(.is-overflowing) span.text{
width: 100%;
overflow: hidden;
}
.overflow-dots {
opacity: 0;
display: block;
opacity: 1;
background: $overflow-ellipse;
position: absolute;
z-index: 5;
right: 0;
transition: opacity 0.1s ease-in;
}
}
}
.tile-title.is-overflowing {
span.text {
overflow: hidden;
}
.overflow-dots {
display: block;
opacity: 1;
background: $overflow-ellipse;
position: absolute;
z-index: 5;
right: 0;
transition: opacity 0.1s ease-in;
}
}
/* Manage hover and focus actions */
.item:hover, .item:focus {
/* Show opening-method icon */
.opening-method-icon svg {
display: block;
}
.item:hover .tile-title.is-overflowing{
/* Trigger text-marquee for text that doesn't fit */
.tile-title.is-overflowing{
.overflow-dots {
opacity: 0;
opacity: 0;
}
span.text {
transform: translateX(calc(120px - 100%));
transform: translateX(calc(120px - 100%));
}
}
/* Colourize icons on hover */
.tile-svg {
filter: drop-shadow(4px 8px 3px $transparent-black);
}
.tile-icon {
filter:
drop-shadow(4px 8px 3px $transparent-black)
saturate(2);
}
}
.tile-icon {
width: 60px;
filter: drop-shadow(2px 4px 6px $transparent-black) saturate(0.65);
}
.item:hover {
.tile-svg {
filter: drop-shadow(4px 8px 3px $transparent-black);
}
.tile-icon {
filter:
drop-shadow(4px 8px 3px $transparent-black)
saturate(2);
}
width: 60px;
filter: drop-shadow(2px 4px 6px $transparent-black) saturate(0.65);
}
.tile-svg {
width: 56px;
filter:
invert(69%)
sepia(40%)
saturate(4686%)
hue-rotate(142deg)
brightness(96%)
contrast(102%);
width: 56px;
}
/* Opening-method icon */
.opening-method-icon {
svg {
position: absolute;
display: none;
width: 1rem;
margin: 2px;
right: 0;
top: 0;
path {
fill: $ascent-with-opacity;
}
}
&.short svg {
width: 0.5rem;
margin: 0;
}
}
</style>

View File

@@ -20,7 +20,7 @@
:title="item.title"
:description="item.description"
:icon="item.icon"
:iconType="item.iconType"
:target="item.target"
:svg="item.svg"
@itemClicked="$emit('itemClicked')"
/>