Enhance Map Zoom Control and Improve Map Page Layout
Some checks failed
build.yaml / Enhance Map Zoom Control and Improve Map Page Layout (push) Failing after 0s
Some checks failed
build.yaml / Enhance Map Zoom Control and Improve Map Page Layout (push) Failing after 0s
- Refactored zoom control component for better accessibility and styling. - Added hover effects and improved button states for zoom in/out buttons. - Updated map page layout with enhanced dataset card design and responsive styles. - Introduced empty state for no datasets found and improved results header. - Added icons for dataset cards and improved author display.
This commit is contained in:
parent
88e37bfee8
commit
4229001572
7 changed files with 1520 additions and 452 deletions
|
|
@ -1,21 +1,27 @@
|
|||
<template>
|
||||
<div class="gba-control-zoom btn-group-vertical">
|
||||
<div class="zoom-control-container">
|
||||
<button
|
||||
ref="inputPlus"
|
||||
class="disabled:bg-gray-200 inline-flex cursor-pointer justify-center items-center whitespace-nowrap focus:outline-none transition-colors duration-150 border rounded ring-blue-700 bg-teal-50 text-black border-teal-50 text-sm p-1"
|
||||
class="zoom-button zoom-button-plus"
|
||||
type="button"
|
||||
@click.stop.prevent="zoomIn"
|
||||
:disabled="isZoomInDisabled"
|
||||
aria-label="Zoom in"
|
||||
>
|
||||
<BaseIcon v-if="mdiPlus" :path="mdiPlus" />
|
||||
<BaseIcon v-if="mdiPlus" :path="mdiPlus" :size="20" />
|
||||
</button>
|
||||
|
||||
<div class="zoom-separator"></div>
|
||||
|
||||
<button
|
||||
ref="inputMinus"
|
||||
class="disabled:bg-gray-200 inline-flex cursor-pointer justify-center items-center whitespace-nowrap focus:outline-none transition-colors duration-150 border rounded ring-blue-700 bg-teal-50 text-black border-teal-50 text-sm p-1"
|
||||
class="zoom-button zoom-button-minus"
|
||||
type="button"
|
||||
@click.stop.prevent="zoomOut"
|
||||
:disabled="isZoomOutDisabled"
|
||||
aria-label="Zoom out"
|
||||
>
|
||||
<BaseIcon v-if="mdiMinus" :path="mdiMinus" />
|
||||
<BaseIcon v-if="mdiMinus" :path="mdiMinus" :size="20" />
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -26,6 +32,7 @@ import { MapService } from '@/Stores/map.service';
|
|||
|
||||
import BaseIcon from '@/Components/BaseIcon.vue';
|
||||
import { mdiPlus, mdiMinus } from '@mdi/js';
|
||||
import { Map } from 'leaflet';
|
||||
|
||||
@Component({
|
||||
name: 'zoom-control',
|
||||
|
|
@ -33,7 +40,7 @@ import { mdiPlus, mdiMinus } from '@mdi/js';
|
|||
BaseIcon,
|
||||
},
|
||||
})
|
||||
export default class ZoomControlComponent extends Vue {
|
||||
export class ZoomControlComponent extends Vue {
|
||||
mdiPlus = mdiPlus;
|
||||
mdiMinus = mdiMinus;
|
||||
|
||||
|
|
@ -46,16 +53,23 @@ export default class ZoomControlComponent extends Vue {
|
|||
@Ref('inputMinus') inputMinus: HTMLButtonElement;
|
||||
|
||||
mapService = MapService();
|
||||
map;
|
||||
map: Map | null = null;
|
||||
isZoomInDisabled = false;
|
||||
isZoomOutDisabled = false;
|
||||
|
||||
// mounted() {
|
||||
// let map = (this.map = this.mapService.getMap(this.mapId));
|
||||
// map.on('zoomend zoomlevelschange', this.updateDisabled, this);
|
||||
// }
|
||||
mounted() {
|
||||
let map = (this.map = this.mapService.getMap(this.mapId));
|
||||
if (map) {
|
||||
map.on('zoomend zoomlevelschange', this.updateDisabled, this);
|
||||
this.updateDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
// unmounted() {
|
||||
// this.map.off('zoomend zoomlevelschange');
|
||||
// }
|
||||
unmounted() {
|
||||
if (this.map) {
|
||||
this.map.off('zoomend zoomlevelschange', this.updateDisabled, this);
|
||||
}
|
||||
}
|
||||
|
||||
public zoomIn() {
|
||||
let map = this.mapService.getMap(this.mapId);
|
||||
|
|
@ -69,44 +83,266 @@ export default class ZoomControlComponent extends Vue {
|
|||
|
||||
public updateDisabled() {
|
||||
let map = this.mapService.getMap(this.mapId);
|
||||
// let className = 'leaflet-disabled';
|
||||
if (!map) return;
|
||||
|
||||
this.inputPlus.disabled = false;
|
||||
this.inputPlus.setAttribute('aria-disabled', 'false');
|
||||
this.isZoomInDisabled = map.getZoom() >= map.getMaxZoom();
|
||||
this.isZoomOutDisabled = map.getZoom() <= map.getMinZoom();
|
||||
|
||||
this.inputMinus.disabled = false;
|
||||
this.inputMinus.setAttribute('aria-disabled', 'false');
|
||||
|
||||
if (map.getZoom() === map.getMinZoom()) {
|
||||
this.inputMinus.disabled = true;
|
||||
this.inputMinus.setAttribute('aria-disabled', 'true');
|
||||
if (this.inputPlus) {
|
||||
this.inputPlus.disabled = this.isZoomInDisabled;
|
||||
this.inputPlus.setAttribute('aria-disabled', this.isZoomInDisabled.toString());
|
||||
}
|
||||
if (map.getZoom() === map.getMaxZoom()) {
|
||||
this.inputPlus.disabled = true;
|
||||
this.inputPlus.setAttribute('aria-disabled', 'true');
|
||||
|
||||
if (this.inputMinus) {
|
||||
this.inputMinus.disabled = this.isZoomOutDisabled;
|
||||
this.inputMinus.setAttribute('aria-disabled', this.isZoomOutDisabled.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
export default ZoomControlComponent;
|
||||
</script>
|
||||
|
||||
<style lang="css">
|
||||
.gba-control-zoom {
|
||||
<style scoped>
|
||||
.zoom-control-container {
|
||||
position: absolute;
|
||||
left: 1rem;
|
||||
top: 1rem;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
background: white;
|
||||
border-radius: 0.75rem;
|
||||
box-shadow:
|
||||
0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
||||
0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
overflow: hidden;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
z-index: 40;
|
||||
transition: box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-group-vertical button {
|
||||
display: block;
|
||||
.zoom-control-container:hover {
|
||||
box-shadow:
|
||||
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
margin-left: 0;
|
||||
margin-top: 0.5em;
|
||||
.dark .zoom-control-container {
|
||||
background: #1f2937;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.dark .zoom-control-container:hover {
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.zoom-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
padding: 0;
|
||||
background: white;
|
||||
border: none;
|
||||
color: #374151;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.dark .zoom-button {
|
||||
background: #1f2937;
|
||||
color: #d1d5db;
|
||||
}
|
||||
|
||||
.zoom-button:hover:not(:disabled) {
|
||||
background: #65dc21;
|
||||
color: white;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.dark .zoom-button:hover:not(:disabled) {
|
||||
background: #65dc21;
|
||||
}
|
||||
|
||||
.zoom-button:active:not(:disabled) {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.zoom-button:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.4;
|
||||
background: #f3f4f6;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.dark .zoom-button:disabled {
|
||||
background: #111827;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.zoom-button:focus-visible {
|
||||
outline: 2px solid #65dc21;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
/* Icon sizing */
|
||||
.zoom-button :deep(svg) {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
/* Separator between buttons */
|
||||
.zoom-separator {
|
||||
height: 1px;
|
||||
background: #e5e7eb;
|
||||
}
|
||||
|
||||
.dark .zoom-separator {
|
||||
background: #374151;
|
||||
}
|
||||
|
||||
/* Hover effect for the plus button */
|
||||
.zoom-button-plus::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba(101, 220, 33, 0.1) 0%, rgba(53, 124, 6, 0.1) 100%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.zoom-button-plus:hover:not(:disabled)::after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Hover effect for the minus button */
|
||||
.zoom-button-minus::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba(101, 220, 33, 0.1) 0%, rgba(53, 124, 6, 0.1) 100%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.zoom-button-minus:hover:not(:disabled)::after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Responsive design */
|
||||
@media (max-width: 768px) {
|
||||
.zoom-control-container {
|
||||
left: 0.75rem;
|
||||
top: 0.75rem;
|
||||
}
|
||||
|
||||
.zoom-button {
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
}
|
||||
|
||||
.zoom-button :deep(svg) {
|
||||
width: 1.125rem;
|
||||
height: 1.125rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.zoom-control-container {
|
||||
left: 0.5rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
|
||||
.zoom-button {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.zoom-button :deep(svg) {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Animation for button press */
|
||||
@keyframes buttonPress {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.zoom-button:active:not(:disabled) {
|
||||
animation: buttonPress 0.2s ease;
|
||||
}
|
||||
|
||||
/* Tooltip-like effect on hover (optional) */
|
||||
.zoom-button-plus:hover:not(:disabled)::before {
|
||||
content: 'Zoom In';
|
||||
position: absolute;
|
||||
left: calc(100% + 0.5rem);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: #1f2937;
|
||||
color: white;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
animation: fadeIn 0.2s ease 0.5s forwards;
|
||||
pointer-events: none;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.zoom-button-minus:hover:not(:disabled)::before {
|
||||
content: 'Zoom Out';
|
||||
position: absolute;
|
||||
left: calc(100% + 0.5rem);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: #1f2937;
|
||||
color: white;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
animation: fadeIn 0.2s ease 0.5s forwards;
|
||||
pointer-events: none;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hide tooltips on mobile */
|
||||
@media (max-width: 768px) {
|
||||
.zoom-button-plus:hover:not(:disabled)::before,
|
||||
.zoom-button-minus:hover:not(:disabled)::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue