mirror of https://github.com/Lissy93/dashy.git
Adds item size switching functionality and styles
This commit is contained in:
parent
84459b4864
commit
2baccdb718
|
@ -2,7 +2,7 @@
|
||||||
<a @click="itemOpened"
|
<a @click="itemOpened"
|
||||||
:href="target !== 'iframe' ? url : '#'"
|
:href="target !== 'iframe' ? url : '#'"
|
||||||
:target="target === 'newtab' ? '_blank' : ''"
|
:target="target === 'newtab' ? '_blank' : ''"
|
||||||
:class="`item ${!icon? 'short': ''}`"
|
:class="`item ${!icon? 'short': ''} size-${itemSize}`"
|
||||||
:id="`link-${id}`"
|
:id="`link-${id}`"
|
||||||
v-tooltip="getTooltipOptions()"
|
v-tooltip="getTooltipOptions()"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
|
@ -16,7 +16,8 @@
|
||||||
<!-- Item Icon -->
|
<!-- Item Icon -->
|
||||||
<Icon :icon="icon" :url="url" />
|
<Icon :icon="icon" :url="url" />
|
||||||
<!-- Small icon, showing opening method on hover -->
|
<!-- Small icon, showing opening method on hover -->
|
||||||
<ItemOpenMethodIcon class="opening-method-icon" :openingMethod="target" :isSmall="!icon" />
|
<ItemOpenMethodIcon class="opening-method-icon" :isSmall="!icon" :openingMethod="target"
|
||||||
|
:position="itemSize === 'medium'? 'bottom right' : 'top right'"/>
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ export default {
|
||||||
default: 'newtab',
|
default: 'newtab',
|
||||||
validator: (value) => ['newtab', 'sametab', 'iframe'].indexOf(value) !== -1,
|
validator: (value) => ['newtab', 'sametab', 'iframe'].indexOf(value) !== -1,
|
||||||
},
|
},
|
||||||
|
itemSize: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -93,14 +95,8 @@ export default {
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '../../../src/styles/constants.scss';
|
@import '../../../src/styles/constants.scss';
|
||||||
|
|
||||||
/* Item wrapper */
|
|
||||||
.item-wrapper {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
height: 100px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
@ -123,9 +119,6 @@ export default {
|
||||||
&.short {
|
&.short {
|
||||||
height: 18px;
|
height: 18px;
|
||||||
}
|
}
|
||||||
.item {
|
|
||||||
color: var(--primary);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Text in tile */
|
/* Text in tile */
|
||||||
|
@ -200,13 +193,42 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tile-icon {
|
/* Specify layout for alternate sized icons */
|
||||||
width: 60px;
|
.item {
|
||||||
filter: drop-shadow(2px 4px 6px var(--transparent-50)) saturate(0.65);
|
&.size-small {
|
||||||
}
|
display: flex;
|
||||||
|
flex-direction: row-reverse;
|
||||||
.tile-svg {
|
justify-content: flex-end;
|
||||||
width: 56px;
|
align-items: center;
|
||||||
|
height: 2rem;
|
||||||
|
img {
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
|
.tile-title {
|
||||||
|
height: fit-content;
|
||||||
|
min-height: 1rem;
|
||||||
|
span.text {
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 10%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.size-medium {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
height: auto;
|
||||||
|
img {
|
||||||
|
width: 2rem;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
.tile-title {
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.size-large {
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
:description="item.description"
|
:description="item.description"
|
||||||
:icon="item.icon"
|
:icon="item.icon"
|
||||||
:target="item.target"
|
:target="item.target"
|
||||||
:svg="item.svg"
|
:itemSize="itemSize"
|
||||||
@itemClicked="$emit('itemClicked')"
|
@itemClicked="$emit('itemClicked')"
|
||||||
@triggerModal="triggerModal"
|
@triggerModal="triggerModal"
|
||||||
/>
|
/>
|
||||||
|
@ -47,6 +47,7 @@ export default {
|
||||||
title: String,
|
title: String,
|
||||||
displayData: Object,
|
displayData: Object,
|
||||||
items: Array,
|
items: Array,
|
||||||
|
itemSize: String,
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Collapsable,
|
Collapsable,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="`opening-method-icon ${isSmall? 'short': ''}`">
|
<div :class="makeClass(position, isSmall, isTransparent)">
|
||||||
<NewTabOpenIcon v-if="openingMethod === 'newtab'" />
|
<NewTabOpenIcon v-if="openingMethod === 'newtab'" />
|
||||||
<SameTabOpenIcon v-else-if="openingMethod === 'sametab'" />
|
<SameTabOpenIcon v-else-if="openingMethod === 'sametab'" />
|
||||||
<IframeOpenIcon v-else-if="openingMethod === 'iframe'" />
|
<IframeOpenIcon v-else-if="openingMethod === 'iframe'" />
|
||||||
|
@ -14,8 +14,19 @@ import IframeOpenIcon from '@/assets/icons/open-iframe.svg';
|
||||||
export default {
|
export default {
|
||||||
name: 'ItemOpenMethodIcon',
|
name: 'ItemOpenMethodIcon',
|
||||||
props: {
|
props: {
|
||||||
openingMethod: String,
|
openingMethod: String, // newtab | sametab | iframe
|
||||||
isSmall: Boolean,
|
isSmall: Boolean, // If true, will apply small class
|
||||||
|
position: String, // Position classes: top, bottom, left, right
|
||||||
|
isTransparent: Boolean, // If true, will apply opacity
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/* Returns custom class string, from optional props */
|
||||||
|
makeClass(position = 'top right', isSmall = false, transparent = false) {
|
||||||
|
return `opening-method-icon
|
||||||
|
${position || 'top right'}
|
||||||
|
${isSmall ? 'short' : ''}
|
||||||
|
${transparent ? 'transparent' : ''}`;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
NewTabOpenIcon,
|
NewTabOpenIcon,
|
||||||
|
@ -31,16 +42,23 @@ export default {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
path {
|
path {
|
||||||
fill: var(--primary-transparent);
|
fill: var(--primary-transparent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.top svg { top: 0; }
|
||||||
|
&.bottom svg { bottom: 0; }
|
||||||
|
&.left svg { left: 0; }
|
||||||
|
&.right svg { right: 0; }
|
||||||
|
|
||||||
&.short svg {
|
&.short svg {
|
||||||
width: 0.5rem;
|
width: 0.8rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.transparent svg {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
<div>
|
<div>
|
||||||
<span class="options-label">Icon Size</span>
|
<span class="options-label">Icon Size</span>
|
||||||
<div class="display-options">
|
<div class="display-options">
|
||||||
<IconSmall @click="updateIconSize('default')"
|
<IconSmall @click="updateIconSize('small')" v-tooltip="tooltip('Small')"
|
||||||
:class="`layout-icon ${iconSize === 'small' ? 'selected' : ''}`" />
|
:class="`layout-icon ${iconSize === 'small' ? 'selected' : ''}`" />
|
||||||
<IconMedium class="layout-icon" @click="updateIconSize('horizontal')"
|
<IconMedium @click="updateIconSize('medium')" v-tooltip="tooltip('Medium')"
|
||||||
:class="`layout-icon ${iconSize === 'medium' ? 'selected' : ''}`" />
|
:class="`layout-icon ${iconSize === 'medium' ? 'selected' : ''}`" />
|
||||||
<IconLarge class="layout-icon" @click="updateIconSize('vertical')"
|
<IconLarge @click="updateIconSize('large')" v-tooltip="tooltip('Large')"
|
||||||
:class="`layout-icon ${iconSize === 'large' ? 'selected' : ''}`" />
|
:class="`layout-icon ${iconSize === 'large' ? 'selected' : ''}`" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,6 +36,9 @@ export default {
|
||||||
updateIconSize(iconSize) {
|
updateIconSize(iconSize) {
|
||||||
this.$emit('iconSizeUpdated', iconSize);
|
this.$emit('iconSizeUpdated', iconSize);
|
||||||
},
|
},
|
||||||
|
tooltip(content) {
|
||||||
|
return { content, trigger: 'hover focus', delay: 250 };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
<div class="close" title="Hide forever [Esc]" @click="hideWelcomeHelper()">x</div>
|
<div class="close" title="Hide forever [Esc]" @click="hideWelcomeHelper()">x</div>
|
||||||
<p title="Press [Esc] to hide this tip forever. See there's even a shortcut for that! 🚀">
|
<p title="Press [Esc] to hide this tip forever. See there's even a shortcut for that! 🚀">
|
||||||
Just start typing to filter. Then use the tab key to cycle through results,
|
Just start typing to filter. Then use the tab key to cycle through results,
|
||||||
and press enter to launch the selected item. You can hit Esc at anytime to
|
and press enter to launch the selected item, or alt + enter to open in a modal.
|
||||||
clear the search. Easy 🥳
|
You can hit Esc at anytime to clear the search. Easy 🥳
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
<div>
|
<div>
|
||||||
<span class="options-label">Layout</span>
|
<span class="options-label">Layout</span>
|
||||||
<div class="display-options">
|
<div class="display-options">
|
||||||
<IconDeafault @click="updateDisplayLayout('default')"
|
<IconDeafault @click="updateDisplayLayout('default')" v-tooltip="tooltip('Auto')"
|
||||||
:class="`layout-icon ${displayLayout === 'default' ? 'selected' : ''}`" />
|
:class="`layout-icon ${displayLayout === 'default' ? 'selected' : ''}`" />
|
||||||
<IconHorizontal class="layout-icon" @click="updateDisplayLayout('horizontal')"
|
<IconHorizontal @click="updateDisplayLayout('horizontal')" v-tooltip="tooltip('Horizontal')"
|
||||||
:class="`layout-icon ${displayLayout === 'horizontal' ? 'selected' : ''}`" />
|
:class="`layout-icon ${displayLayout === 'horizontal' ? 'selected' : ''}`" />
|
||||||
<IconVertical class="layout-icon" @click="updateDisplayLayout('vertical')"
|
<IconVertical @click="updateDisplayLayout('vertical')" v-tooltip="tooltip('Vertical')"
|
||||||
:class="`layout-icon ${displayLayout === 'vertical' ? 'selected' : ''}`" />
|
:class="`layout-icon ${displayLayout === 'vertical' ? 'selected' : ''}`" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,6 +36,9 @@ export default {
|
||||||
updateDisplayLayout(layout) {
|
updateDisplayLayout(layout) {
|
||||||
this.$emit('layoutUpdated', layout);
|
this.$emit('layoutUpdated', layout);
|
||||||
},
|
},
|
||||||
|
tooltip(content) {
|
||||||
|
return { content, trigger: 'hover focus', delay: 250 };
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -66,6 +66,7 @@ export default {
|
||||||
border-radius: 20px 0 0;
|
border-radius: 20px 0 0;
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
div {
|
div {
|
||||||
|
margin-left: 0.5rem;
|
||||||
opacity: 0.85;
|
opacity: 0.85;
|
||||||
&:hover { opacity: 1; }
|
&:hover { opacity: 1; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,6 @@ export default {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 0 1rem;
|
|
||||||
span.theme-label {
|
span.theme-label {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
|
|
|
@ -4,12 +4,15 @@
|
||||||
<SettingsContainer ref="filterComp"
|
<SettingsContainer ref="filterComp"
|
||||||
@user-is-searchin="searching"
|
@user-is-searchin="searching"
|
||||||
@change-display-layout="setLayoutOrientation"
|
@change-display-layout="setLayoutOrientation"
|
||||||
|
@change-icon-size="setItemSize"
|
||||||
:displayLayout="layout"
|
:displayLayout="layout"
|
||||||
|
:iconSize="itemSizeBound"
|
||||||
:availableThemes="getAvailibleThemes()"
|
:availableThemes="getAvailibleThemes()"
|
||||||
class="filter-container"
|
class="filter-container"
|
||||||
/>
|
/>
|
||||||
<!-- Main content, section for each group of items -->
|
<!-- Main content, section for each group of items -->
|
||||||
<div :class="`item-group-container orientation-${layout}`" v-if="checkTheresData(sections)">
|
<div v-if="checkTheresData(sections)"
|
||||||
|
:class="`item-group-container orientation-${layout} item-size-${itemSizeBound}`">
|
||||||
<ItemGroup
|
<ItemGroup
|
||||||
v-for="(section, index) in sections"
|
v-for="(section, index) in sections"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
@ -18,6 +21,7 @@
|
||||||
:groupId="`section-${index}`"
|
:groupId="`section-${index}`"
|
||||||
:items="filterTiles(section.items)"
|
:items="filterTiles(section.items)"
|
||||||
@itemClicked="finishedSearching()"
|
@itemClicked="finishedSearching()"
|
||||||
|
:itemSize="itemSizeBound"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="no-data">No Data Found Yet</div>
|
<div v-else class="no-data">No Data Found Yet</div>
|
||||||
|
@ -42,6 +46,7 @@ export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
searchValue: '',
|
searchValue: '',
|
||||||
layout: '',
|
layout: '',
|
||||||
|
itemSizeBound: '',
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
layoutOrientation: {
|
layoutOrientation: {
|
||||||
|
@ -51,6 +56,13 @@ export default {
|
||||||
this.layout = layout;
|
this.layout = layout;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
iconSize: {
|
||||||
|
get: () => localStorage.iconSize || 'medium',
|
||||||
|
set: function setIconSize(iconSize) {
|
||||||
|
localStorage.setItem('iconSize', iconSize);
|
||||||
|
this.itemSizeBound = iconSize;
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/* Returns true if there is one or more sections in the config */
|
/* Returns true if there is one or more sections in the config */
|
||||||
|
@ -92,9 +104,9 @@ export default {
|
||||||
setLayoutOrientation(layout) {
|
setLayoutOrientation(layout) {
|
||||||
this.layoutOrientation = layout;
|
this.layoutOrientation = layout;
|
||||||
},
|
},
|
||||||
/* Either gets user's preferred layout from session, or returns default */
|
/* Sets item size attribute, which is used by ItemGroup */
|
||||||
getLayoutOrientation() {
|
setItemSize(itemSize) {
|
||||||
return localStorage.layoutOrientation || 'default';
|
this.iconSize = itemSize;
|
||||||
},
|
},
|
||||||
getAvailibleThemes() {
|
getAvailibleThemes() {
|
||||||
const availibleThemes = {};
|
const availibleThemes = {};
|
||||||
|
@ -134,7 +146,8 @@ export default {
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initiateFontAwesome();
|
this.initiateFontAwesome();
|
||||||
this.layout = this.getLayoutOrientation();
|
this.layoutOrientation = this.layoutOrientation;
|
||||||
|
this.itemSizeBound = this.iconSize;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue