aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTerry Truong <terry06890@gmail.com>2022-06-25 12:10:58 +1000
committerTerry Truong <terry06890@gmail.com>2022-06-25 12:43:36 +1000
commit2a0c04245f8ab5017ca96449cca8aeb36336edf3 (patch)
tree9d8fed07810e7b22c2ed29b6db014f69f4023fe5
parenta1c5e2017ef80d360cc0d08ae73437ce32766c6e (diff)
Reduce degrees-of-variance in options set
Also add size prop to IconButton
-rw-r--r--src/App.vue93
-rw-r--r--src/components/AncestryBar.vue9
-rw-r--r--src/components/IconButton.vue6
-rw-r--r--src/components/SearchModal.vue10
-rw-r--r--src/components/SettingsModal.vue2
-rw-r--r--src/components/Tile.vue26
-rw-r--r--src/components/TileInfoModal.vue6
-rw-r--r--src/lib.ts26
8 files changed, 87 insertions, 91 deletions
diff --git a/src/App.vue b/src/App.vue
index 063f5ab..9abd5ac 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -55,39 +55,39 @@ function getDefaultLytOpts(): LayoutOptions {
sweepToParent: 'prefer', // 'none' | 'prefer' | 'fallback'
};
}
-function getDefaultUiOpts(){
+function getDefaultUiOpts(lytOpts: LayoutOptions){
let screenSz = getBreakpoint();
- let bgColorLight = '#44403c', altColor = '#a3e623';
+ // Reused option values
+ let textColor = '#fafaf9';
+ let bgColor = '#292524', bgColorLight = '#44403c', bgColorDark = '#1c1917',
+ bgColorLight2 = '#57534e', bgColorDark2 = '#0e0c0b';
+ let altColor = '#a3e623', altColorDark = '#65a30d';
+ let accentColor = '#f59e0b';
+ let scrollGap = getScrollBarWidth();
+ //
return {
- // Shared styling
- textColor: '#fafaf9',
- bgColor: '#292524',
+ // Shared coloring/sizing
+ textColor,
+ bgColor,
bgColorLight,
- bgColorDark: '#1c1917',
- bgColorLight2: '#57534e',
- bgColorDark2: '#0e0c0b',
+ bgColorDark,
+ bgColorLight2,
+ bgColorDark2,
altColor,
- altColorDark: '#65a30d',
+ altColorDark,
borderRadius: 5, // px
shadowNormal: '0 0 2px black',
- shadowHovered: '0 0 1px 2px' + altColor,
- shadowFocused: '0 0 1px 2px orange',
- // Styling for App
- mainTileMargin: screenSz == 'sm' ? 6 : 10, // px
- // Styling for tiles
- childQtyColors: [[1, altColor], [10, 'orange'], [100, 'red']],
- infoIconSz: 18, // px
- infoIconMargin: 2, // px
- leafPadding: 4, // px
- leafHeaderFontSz: 15, // px
- nonleafBgColors: ['#44403c', '#57534e'],
- nonleafHeaderFontSz: 15, // px
- // Styling for other components
- infoModalImgSz: 200, // px
+ shadowHovered: '0 0 1px 2px ' + altColor,
+ shadowFocused: '0 0 1px 2px ' + accentColor,
+ // Component coloring
+ childQtyColors: [[1, 'greenyellow'], [10, 'orange'], [100, 'red']],
+ nonleafBgColors: [bgColorLight, bgColorLight2],
+ nonleafHeaderColor: bgColorDark,
ancestryBarBgColor: bgColorLight,
- ancestryBarImgSz: 100, // px
- ancestryTileGap: 5, // px
+ // Component sizing
+ ancestryBarBreadth: lytOpts.maxTileSz / 2 + lytOpts.tileSpacing*2 + scrollGap, // px
tutPaneSz: 200, // px
+ scrollGap,
// Timing related
clickHoldDuration: 400, // ms
transitionDuration: 300, // ms
@@ -95,10 +95,9 @@ function getDefaultUiOpts(){
// Other
useReducedTree: false,
searchSuggLimit: 5,
- jumpToSearchedNode: false,
+ searchJumpMode: false,
tutorialSkip: false,
disabledActions: new Set() as Set<Action>,
- scrollGap: getScrollBarWidth(),
};
}
@@ -163,7 +162,7 @@ export default defineComponent({
}
return ancestors.reverse();
},
- iconButtonStyles(): Record<string,string> {
+ buttonStyles(): Record<string,string> {
return {
color: this.uiOpts.textColor,
backgroundColor: this.uiOpts.altColorDark,
@@ -179,8 +178,7 @@ export default defineComponent({
};
},
ancestryBarContainerStyles(): Record<string,string> {
- let ancestryBarBreadth = this.detachedAncestors == null ? 0 :
- this.uiOpts.ancestryBarImgSz + this.uiOpts.ancestryTileGap*2 + this.uiOpts.scrollGap;
+ let ancestryBarBreadth = this.detachedAncestors == null ? 0 : this.uiOpts.ancestryBarBreadth;
let styles = {
minWidth: 'auto',
maxWidth: 'none',
@@ -441,7 +439,7 @@ export default defineComponent({
while (!this.detachedAncestors!.includes(nodeInAncestryBar)){
nodeInAncestryBar = nodeInAncestryBar.parent!;
}
- if (!this.uiOpts.jumpToSearchedNode){
+ if (!this.uiOpts.searchJumpMode){
this.onDetachedAncestorClick(nodeInAncestryBar!);
setTimeout(() => this.expandToNode(name), this.uiOpts.transitionDuration);
} else{
@@ -451,7 +449,7 @@ export default defineComponent({
return;
}
// Attempt tile-expand
- if (this.uiOpts.jumpToSearchedNode){
+ if (this.uiOpts.searchJumpMode){
// Extend layout tree
let tolNode = this.tolMap.get(name)!;
let nodesToAdd = [name] as string[];
@@ -639,7 +637,7 @@ export default defineComponent({
onResetSettings(){
localStorage.clear();
let defaultLytOpts = getDefaultLytOpts();
- let defaultUiOpts = getDefaultUiOpts();
+ let defaultUiOpts = getDefaultUiOpts(defaultLytOpts);
if (this.uiOpts.useReducedTree != defaultUiOpts.useReducedTree){
this.onTreeChange();
}
@@ -699,7 +697,7 @@ export default defineComponent({
let handleResize = () => {
// Update unmodified layout/ui options with defaults
let lytOpts = getDefaultLytOpts();
- let uiOpts = getDefaultUiOpts();
+ let uiOpts = getDefaultUiOpts(lytOpts);
let changedTree = false;
for (let prop of Object.getOwnPropertyNames(lytOpts)){
let item = localStorage.getItem('lyt ' + prop);
@@ -710,6 +708,7 @@ export default defineComponent({
for (let prop of Object.getOwnPropertyNames(uiOpts)){
let item = localStorage.getItem('lyt ' + prop);
if (item == null && this.uiOpts[prop] != uiOpts[prop as keyof typeof uiOpts]){
+ console.log("Loaded UI prop " + prop)
this.uiOpts[prop] = uiOpts[prop as keyof typeof uiOpts];
if (prop == 'useReducedTree'){
changedTree = true;
@@ -757,8 +756,8 @@ export default defineComponent({
} else if (evt.key == 'F' && evt.ctrlKey){
// If search bar is open, swap search mode
if (this.searchOpen){
- this.uiOpts.jumpToSearchedNode = !this.uiOpts.jumpToSearchedNode;
- this.onSettingsChg([], ['jumpToSearchedNode']);
+ this.uiOpts.searchJumpMode = !this.uiOpts.searchJumpMode;
+ this.onSettingsChg([], ['searchJumpMode']);
}
}
},
@@ -813,7 +812,8 @@ export default defineComponent({
return opts;
},
getUiOpts(){
- let opts: {[x: string]: boolean|number|string|string[]|(string|number)[][]|Set<Action>} = getDefaultUiOpts();
+ let opts: {[x: string]: boolean|number|string|string[]|(string|number)[][]|Set<Action>} =
+ getDefaultUiOpts(getDefaultLytOpts());
for (let prop of Object.getOwnPropertyNames(opts)){
let item = localStorage.getItem('ui ' + prop);
if (item != null){
@@ -928,23 +928,20 @@ export default defineComponent({
<template>
<div class="absolute left-0 top-0 w-screen h-screen overflow-hidden flex flex-col"
:style="{backgroundColor: uiOpts.bgColor}">
- <div class="flex shadow" :style="{backgroundColor: uiOpts.bgColorDark2}">
- <h1 class="px-4 my-auto text-2xl" :style="{color: uiOpts.altColor}">Tree of Life</h1>
+ <div class="flex shadow gap-2 p-2" :style="{backgroundColor: uiOpts.bgColorDark2}">
+ <h1 class="my-auto text-2xl" :style="{color: uiOpts.altColor}">Tol Explorer</h1>
<!-- Icons -->
- <icon-button v-if="!uiOpts.disabledActions.has('search')"
- class="ml-auto mr-2 my-2" :style="iconButtonStyles" @click="onSearchIconClick">
+ <div class="mx-auto"/> <!-- Spacer -->
+ <icon-button v-if="!uiOpts.disabledActions.has('search')" :style="buttonStyles" @click="onSearchIconClick">
<search-icon/>
</icon-button>
- <icon-button v-if="!uiOpts.disabledActions.has('autoMode')"
- class="mr-2 my-2" :style="iconButtonStyles" @click="onPlayIconClick">
+ <icon-button v-if="!uiOpts.disabledActions.has('autoMode')" :style="buttonStyles" @click="onPlayIconClick">
<play-icon/>
</icon-button>
- <icon-button v-if="!uiOpts.disabledActions.has('settings')"
- class="mr-2 my-2" :style="iconButtonStyles" @click="onSettingsIconClick">
+ <icon-button v-if="!uiOpts.disabledActions.has('settings')" :style="buttonStyles" @click="onSettingsIconClick">
<settings-icon/>
</icon-button>
- <icon-button v-if="!uiOpts.disabledActions.has('help')"
- class="mr-2 my-2" :style="iconButtonStyles" @click="onHelpIconClick">
+ <icon-button v-if="!uiOpts.disabledActions.has('help')" :style="buttonStyles" @click="onHelpIconClick">
<help-icon/>
</icon-button>
</div>
@@ -964,7 +961,7 @@ export default defineComponent({
@ancestor-click="onDetachedAncestorClick" @info-click="onInfoClick"/>
</transition>
</div>
- <div class="relative grow" :style="{margin: uiOpts.mainTileMargin + 'px'}" ref="tileArea">
+ <div class="relative grow" :style="{margin: lytOpts.tileSpacing + 'px'}" ref="tileArea">
<tile :layoutNode="layoutTree" :tolMap="tolMap" :lytOpts="lytOpts" :uiOpts="uiOpts"
:overflownDim="overflownRoot ? tileAreaDims[1] : 0" :skipTransition="justInitialised"
@leaf-click="onLeafClick" @nonleaf-click="onNonleafClick"
diff --git a/src/components/AncestryBar.vue b/src/components/AncestryBar.vue
index a5bb1c0..0f95d00 100644
--- a/src/components/AncestryBar.vue
+++ b/src/components/AncestryBar.vue
@@ -15,10 +15,13 @@ export default defineComponent({
uiOpts: {type: Object as PropType<UiOptions>, required: true},
},
computed: {
+ imgSz(){
+ return this.uiOpts.ancestryBarBreadth - this.lytOpts.tileSpacing*2 - this.uiOpts.scrollGap;
+ },
usedNodes(){ // Childless versions of 'nodes' used to parameterise <tile>
return this.nodes.map(n => {
let newNode = new LayoutNode(n.name, []);
- newNode.dims = [this.uiOpts.ancestryBarImgSz, this.uiOpts.ancestryBarImgSz];
+ newNode.dims = [this.imgSz, this.imgSz];
return newNode;
});
},
@@ -29,8 +32,8 @@ export default defineComponent({
// For child layout
display: 'flex',
flexDirection: this.vert ? 'column' : 'row',
- gap: this.uiOpts.ancestryTileGap + 'px',
- padding: this.uiOpts.ancestryTileGap + 'px',
+ gap: this.lytOpts.tileSpacing + 'px',
+ padding: this.lytOpts.tileSpacing + 'px',
// Other
backgroundColor: this.uiOpts.ancestryBarBgColor,
boxShadow: this.uiOpts.shadowNormal,
diff --git a/src/components/IconButton.vue b/src/components/IconButton.vue
index 7ce5da4..71dddc3 100644
--- a/src/components/IconButton.vue
+++ b/src/components/IconButton.vue
@@ -3,14 +3,16 @@ import {defineComponent, PropType} from 'vue';
export default defineComponent({
props: {
+ size: {type: Number, default: 36},
disabled: {type: Boolean, default: false},
},
});
</script>
<template>
-<div class="w-9 h-9 p-2 rounded-full hover:cursor-pointer"
- :class="{'hover:brightness-125': !disabled, 'brightness-75': disabled}">
+<div class="p-2 rounded-full hover:cursor-pointer"
+ :class="{'hover:brightness-125': !disabled, 'brightness-75': disabled}"
+ :style="{width: size + 'px', height: size + 'px', padding: (size / 5) + 'px'}">
<slot class="w-full h-full">?</slot>
</div>
</template>
diff --git a/src/components/SearchModal.vue b/src/components/SearchModal.vue
index 1a3ef27..a3fbd14 100644
--- a/src/components/SearchModal.vue
+++ b/src/components/SearchModal.vue
@@ -24,13 +24,13 @@ export default defineComponent({
},
computed: {
infoIconStyles(): Record<string,string> {
- let size = this.uiOpts.infoIconSz + 'px';
+ let size = '18px';
return {
width: size,
height: size,
minWidth: size,
minHeight: size,
- margin: this.uiOpts.infoIconMargin + 'px',
+ margin: '2px',
};
},
suggDisplayStrings(): [string, string, string][] {
@@ -71,8 +71,8 @@ export default defineComponent({
}
},
onSearchModeChg(){
- this.uiOpts.jumpToSearchedNode = !this.uiOpts.jumpToSearchedNode;
- this.$emit('settings-chg', [], ['jumpToSearchedNode']);
+ this.uiOpts.searchJumpMode = !this.uiOpts.searchJumpMode;
+ this.$emit('settings-chg', [], ['searchJumpMode']);
},
resolveSearch(tolNodeName: string){
if (tolNodeName == ''){
@@ -223,7 +223,7 @@ export default defineComponent({
</div>
<div class="my-auto mx-2 hover:cursor-pointer hover:brightness-75 rounded">
<log-in-icon @click.stop="onSearchModeChg" class="block w-8 h-8"
- :class="uiOpts.jumpToSearchedNode ? 'text-stone-500' : 'text-stone-300'"/>
+ :class="uiOpts.searchJumpMode ? 'text-stone-500' : 'text-stone-300'"/>
</div>
</div>
</div>
diff --git a/src/components/SettingsModal.vue b/src/components/SettingsModal.vue
index 92f4dce..8cebf7c 100644
--- a/src/components/SettingsModal.vue
+++ b/src/components/SettingsModal.vue
@@ -151,7 +151,7 @@ export default defineComponent({
<hr class="border-stone-400"/>
<div>
<label>
- <input type="checkbox" v-model="uiOpts.jumpToSearchedNode" @change="onUiOptChg('jumpToSearchedNode')"/>
+ <input type="checkbox" v-model="uiOpts.searchJumpMode" @change="onUiOptChg('searchJumpMode')"/>
Jump to search result
</label>
</div>
diff --git a/src/components/Tile.vue b/src/components/Tile.vue
index df281f5..1559f06 100644
--- a/src/components/Tile.vue
+++ b/src/components/Tile.vue
@@ -102,6 +102,9 @@ export default defineComponent({
return this.uiOpts.shadowNormal;
}
},
+ fontSz(): number {
+ return 0.7 * this.lytOpts.headerSz;
+ },
styles(): Record<string,string> {
let layoutStyles = {
position: 'absolute',
@@ -151,7 +154,7 @@ export default defineComponent({
return {
// Image (and scrims)
backgroundImage: this.tolNode.imgName != null ?
- 'linear-gradient(to bottom, rgba(0,0,0,0.4), #0000 40%, #0000 60%, rgba(0,0,0,0.4) 100%),' +
+ 'linear-gradient(to bottom, rgba(0,0,0,0.4), #0000 40%),' +
'url(\'/img/' + (this.tolNode.imgName as string).replaceAll('\'', '\\\'') + '\')' :
'none',
backgroundColor: '#1c1917',
@@ -183,10 +186,10 @@ export default defineComponent({
}
}
return {
- height: (this.uiOpts.leafHeaderFontSz + this.uiOpts.leafPadding * 2) + 'px',
- padding: this.uiOpts.leafPadding + 'px',
- lineHeight: this.uiOpts.leafHeaderFontSz + 'px',
- fontSize: this.uiOpts.leafHeaderFontSz + 'px',
+ height: (this.fontSz * 1.3) + 'px',
+ padding: this.fontSz * 0.3 + 'px',
+ lineHeight: this.fontSz + 'px',
+ fontSize: this.fontSz + 'px',
color: textColor,
// For ellipsis
overflow: 'hidden',
@@ -220,7 +223,7 @@ export default defineComponent({
height: this.lytOpts.headerSz + 'px',
borderTopLeftRadius: 'inherit',
borderTopRightRadius: 'inherit',
- backgroundColor: this.uiOpts.bgColorDark,
+ backgroundColor: this.uiOpts.nonleafHeaderColor,
};
if (this.isOverflownRoot){
styles = {
@@ -238,7 +241,7 @@ export default defineComponent({
nonleafHeaderTextStyles(): Record<string,string> {
return {
lineHeight: this.lytOpts.headerSz + 'px',
- fontSize: this.uiOpts.nonleafHeaderFontSz + 'px',
+ fontSize: this.fontSz + 'px',
textAlign: 'center',
color: this.uiOpts.textColor,
paddingLeft: '5px',
@@ -249,15 +252,14 @@ export default defineComponent({
};
},
infoIconStyles(): Record<string,string> {
- let size = this.uiOpts.infoIconSz + 'px';
+ let size = (this.lytOpts.headerSz * 0.8) + 'px';
+ let marginSz = (this.lytOpts.headerSz * 0.2) + 'px';
return {
width: size,
height: size,
minWidth: size,
minHeight: size,
- margin: this.uiOpts.infoIconMargin + 'px',
- marginTop: 'auto',
- marginLeft: 'auto',
+ margin: this.isLeaf ? `auto ${marginSz} ${marginSz} auto` : `auto ${marginSz}`,
};
},
sepSweptAreaStyles(): Record<string,string> {
@@ -446,7 +448,7 @@ export default defineComponent({
height: '100%',
// Image (and scrims)
backgroundImage: (this.tolNode.imgName![idx]! != null) ?
- 'linear-gradient(to bottom, rgba(0,0,0,0.4), #0000 40%, #0000 60%, rgba(0,0,0,0.4) 100%),' +
+ 'linear-gradient(to bottom, rgba(0,0,0,0.4), #0000 40%),' +
'url(\'/img/' + this.tolNode.imgName![idx]!.replaceAll('\'', '\\\'') + '\')' :
'none',
backgroundColor: '#1c1917',
diff --git a/src/components/TileInfoModal.vue b/src/components/TileInfoModal.vue
index 423a2f5..90ad9a7 100644
--- a/src/components/TileInfoModal.vue
+++ b/src/components/TileInfoModal.vue
@@ -50,7 +50,7 @@ export default defineComponent({
},
dummyNode(): LayoutNode {
let newNode = new LayoutNode(this.nodeName, []);
- newNode.dims = [this.uiOpts.infoModalImgSz, this.uiOpts.infoModalImgSz];
+ newNode.dims = [this.lytOpts.maxTileSz, this.lytOpts.maxTileSz];
return newNode;
},
},
@@ -69,8 +69,8 @@ export default defineComponent({
'none',
backgroundColor: '#1c1917',
backgroundSize: 'cover',
- width: this.uiOpts.infoModalImgSz + 'px',
- height: this.uiOpts.infoModalImgSz + 'px',
+ width: this.lytOpts.maxTileSz + 'px',
+ height: this.lytOpts.maxTileSz + 'px',
};
},
licenseToUrl(license: string){
diff --git a/src/lib.ts b/src/lib.ts
index 6a1a5a1..0706a49 100644
--- a/src/lib.ts
+++ b/src/lib.ts
@@ -45,7 +45,7 @@ export type Action =
'tileInfo' | 'search' | 'autoMode' | 'settings' | 'help';
//
export type UiOptions = {
- // Shared styling
+ // Shared coloring/sizing
textColor: string, // CSS color
bgColor: string,
bgColorLight: string,
@@ -58,26 +58,19 @@ export type UiOptions = {
shadowNormal: string, // CSS box-shadow value
shadowHovered: string,
shadowFocused: string,
- // Styling for App
- mainTileMargin: number, // px
- // Styling for tiles
+ // Component coloring
childQtyColors: [number, string][],
// Specifies, for an increasing sequence of minimum-child-quantity values, CSS colors to use
//eg: [[1, 'green'], [10, 'orange'], [100, 'red']]
- infoIconSz: number, // px
- infoIconMargin: number, // px
- leafPadding: number, // px
- leafHeaderFontSz: number, // px
nonleafBgColors: string[],
// Specifies CSS colors to use at various tree depths
// With N strings, tiles at depth M use the color at index M % N
- nonleafHeaderFontSz: number, // px
- // Styling for other components
- infoModalImgSz: number, // px
- ancestryBarBgColor: string, // CSS color
- ancestryBarImgSz: number, // px
- ancestryTileGap: number, // Gap between ancestor tiles, in px
- tutPaneSz: number, // px
+ nonleafHeaderColor: string, // CSS color
+ ancestryBarBgColor: string,
+ // Component sizing
+ ancestryBarBreadth: number, // px (fixed value needed for transitions)
+ tutPaneSz: number, // px (fixed value needed for transitions)
+ scrollGap: number, // Size of scroll bar, in px
// Timing related
clickHoldDuration: number, // Time after mousedown when a click-and-hold is recognised, in ms
transitionDuration: number, // ms
@@ -85,8 +78,7 @@ export type UiOptions = {
// Other
useReducedTree: boolean,
searchSuggLimit: number, // Max number of search suggestions
- jumpToSearchedNode: boolean,
+ searchJumpMode: boolean,
tutorialSkip: boolean,
disabledActions: Set<Action>,
- scrollGap: number, // Size of scroll bar, in px
};