some ui optimization

This commit is contained in:
Anton 2024-01-14 12:12:25 +01:00
parent 13a7f3fd90
commit 825d5d233f
4 changed files with 44 additions and 23 deletions

View File

@ -3,7 +3,7 @@ import * as React from 'react'
export const Control = ({ position, children }: { position: "topLeft" | "topRight" | "bottomLeft" | "bottomRight", children: React.ReactNode }) => {
export const Control = ({ position, children, zIndex }: { position: "topLeft" | "topRight" | "bottomLeft" | "bottomRight", children: React.ReactNode, zIndex: string }) => {
const controlContainerRef = React.createRef<HTMLDivElement>()
@ -17,7 +17,7 @@ export const Control = ({ position, children }: { position: "topLeft" | "topRigh
}, [controlContainerRef])
return (
<div ref={controlContainerRef} className={`tw-absolute tw-z-[999] tw-flex-col ${position === 'topLeft' && "tw-top-4 tw-left-4"} ${position === 'bottomLeft' && "tw-bottom-4 tw-left-4"} ${position === 'topRight' && "tw-bottom-4 tw-right-4"} ${position === 'bottomRight' && "tw-bottom-4 tw-right-4"}`}>
<div ref={controlContainerRef} style={{zIndex: zIndex}} className={`tw-absolute tw-z-[999] tw-flex-col ${position === 'topLeft' && "tw-top-4 tw-left-4"} ${position === 'bottomLeft' && "tw-bottom-4 tw-left-4"} ${position === 'topRight' && "tw-bottom-4 tw-right-4"} ${position === 'bottomRight' && "tw-bottom-4 tw-right-4"}`}>
{children}
</div>

View File

@ -58,19 +58,21 @@ export const SearchControl = ({ clusterRef }) => {
return (<>
{!(windowDimensions.height < 500) &&
<div className='tw-w-[calc(100vw-2rem)] tw-max-w-[22rem] '>
<input type="text" placeholder="search ..." autoComplete="off" className="tw-input tw-input-bordered tw-w-full tw-shadow-xl tw-rounded-lg"
<input type="text" placeholder="search ..." autoComplete="off" value={value} className="tw-input tw-input-bordered tw-w-full tw-shadow-xl tw-rounded-lg"
ref={searchInput}
onChange={(e) => setValue(e.target.value)}
onFocus={() => setHideSuggestions(false)}
onBlur={async () => {
setTimeout(() => {
setHideSuggestions(true);
window.history.pushState({}, "", `/`)
}, 200);
}} />
{value.length > 0 && <button className="tw-btn tw-btn-sm tw-btn-circle tw-absolute tw-right-2 tw-top-2" onClick={() => setValue("")}></button>}
{hideSuggestions || Array.from(geoResults).length == 0 && itemsResults.length == 0 && tagsResults.length == 0 || value.length == 0 ? "" :
<div className='tw-card tw-card-body tw-bg-base-100 tw-p-4 tw-mt-2 tw-z-1000 tw-shadow-xl'>
<div className='tw-card tw-card-body tw-bg-base-100 tw-p-4 tw-mt-2 tw-shadow-xl'>
{tagsResults.length > 0 &&
<div className='tw-flex tw-flex-wrap tw-max-h-16 tw-overflow-hidden'>
<div className='tw-flex tw-flex-wrap tw-max-h-16 tw-overflow-hidden tw-min-h-[32px]'>
{tagsResults.map(tag => (
<div key={tag.id} className='tw-rounded-2xl tw-text-white tw-p-1 tw-px-4 tw-shadow-md tw-card tw-mr-2 tw-mb-2 tw-cursor-pointer' style={{ backgroundColor: tag.color }} onClick={() => {
addFilterTag(tag)
@ -81,8 +83,8 @@ export const SearchControl = ({ clusterRef }) => {
</div>
}
{itemsResults.length > 0 && tagsResults.length > 0 && <hr></hr>}
{itemsResults.slice(0, 10).map(item => (
{itemsResults.length > 0 && tagsResults.length > 0 && <hr className='tw-opacity-50'></hr>}
{itemsResults.slice(0, 5).map(item => (
<div key={item.id} className='tw-cursor-pointer hover:tw-font-bold' onClick={() => {
const marker = Object.entries(leafletRefs).find(r => r[1].item == item)?.[1].marker;
@ -96,19 +98,34 @@ export const SearchControl = ({ clusterRef }) => {
});
}
}
}>{item.name}</div>
))}
{Array.from(geoResults).length > 0 && (itemsResults.length > 0 || tagsResults.length > 0) && <hr></hr>}
{Array.from(geoResults).map((geo) => (
<div className='tw-cursor-pointer hover:tw-font-bold' key={Math.random()}
onClick={() => {
searchInput.current?.blur();
if (geo.properties.extent) map.fitBounds(new LatLngBounds(new LatLng(geo.properties.extent[1], geo.properties.extent[0]), new LatLng(geo.properties.extent[3], geo.properties.extent[2])));
else map.setView(new LatLng(geo.geometry.coordinates[1], geo.geometry.coordinates[0]), 15, { duration: 1 })
}}>
{geo?.properties.name}
}><div className='tw-flex tw-flex-row'>
<item.layer.menuIcon className="tw-text-current tw-w-5 tw-mr-2 tw-mt-0" />
<div>
<div className='tw-text-sm tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap tw-max-w-[17rem]'>{item.name}</div>
<div className='tw-text-xs tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap tw-max-w-[17rem]'>{item.text}</div>
</div>
</div>
</div>
))}
{Array.from(geoResults).length > 0 && (itemsResults.length > 0 || tagsResults.length > 0) && <hr className='tw-opacity-50'></hr>}
{Array.from(geoResults).map((geo) => (
<div className='tw-flex tw-flex-row' key={Math.random()}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="tw-text-current tw-mr-2 tw-mt-0 tw-w-5">
<path strokeLinecap="round" strokeLinejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
</svg>
<div className='tw-cursor-pointer hover:tw-font-bold'
onClick={() => {
searchInput.current?.blur();
if (geo.properties.extent) map.fitBounds(new LatLngBounds(new LatLng(geo.properties.extent[1], geo.properties.extent[0]), new LatLng(geo.properties.extent[3], geo.properties.extent[2])));
else map.setView(new LatLng(geo.geometry.coordinates[1], geo.geometry.coordinates[0]), 15, { duration: 1 })
}}>
<div className='tw-text-sm tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap tw-max-w-[17rem]'>{geo?.properties.name ? geo?.properties.name : value}</div>
<div className='tw-text-xs tw-overflow-hidden tw-text-ellipsis tw-whitespace-nowrap tw-max-w-[17rem]'>{geo?.properties?.city && `${capitalizeFirstLetter(geo?.properties?.city)}, `} {geo?.properties?.osm_value && geo?.properties?.osm_value !== "primary" && geo?.properties?.osm_value !== "path" && geo?.properties?.osm_value !== "secondary" && geo?.properties?.osm_value !== "residential" && geo?.properties?.osm_value !== "unclassified" && `${capitalizeFirstLetter(geo?.properties?.osm_value)}, `} {geo.properties.state && `${geo.properties.state}, `} {geo.properties.country && geo.properties.country}</div>
</div>
</div>
))}
</div>}
</div>
}

View File

@ -1,5 +1,9 @@
.leaflet-container {
text-align: left;
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='%23000' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_V8m1%7Btransform-origin:center;animation:spinner_zKoa 2s linear infinite%7D.spinner_V8m1 circle%7Bstroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite%7D%40keyframes spinner_zKoa%7B100%25%7Btransform:rotate(360deg)%7D%7D%40keyframes spinner_YpZS%7B0%25%7Bstroke-dasharray:0 150;stroke-dashoffset:0%7D47.5%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-16%7D95%25%2C100%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-59%7D%7D%3C%2Fstyle%3E%3Cg class='spinner_V8m1'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3'%3E%3C%2Fcircle%3E%3C%2Fg%3E%3C%2Fsvg%3E");
background-repeat: no-repeat;
background-attachment: fixed;
background-position: 50% 80%;
}

View File

@ -70,6 +70,7 @@ function UtopiaMap({
return (
<>
<Outlet></Outlet>
<LayersProvider initialLayers={[]}>
<TagsProvider initialTags={[]}>
<PermissionsProvider initialPermissions={[]}>
@ -78,11 +79,11 @@ function UtopiaMap({
<LeafletRefsProvider initialLeafletRefs={{}}>
<div className={(selectNewItemPosition != null ? "crosshair-cursor-enabled" : undefined)}>
<MapContainer ref={mapDivRef} style={{ height: height, width: width }} center={center} zoom={zoom} zoomControl={false}>
<Control position='topLeft'>
<SearchControl clusterRef={clusterRef}/>
<TagsControl/>
<Control position='topLeft' zIndex="1000">
<SearchControl clusterRef={clusterRef} />
<TagsControl />
</Control>
<Control position='bottomLeft'>
<Control position='bottomLeft' zIndex="999">
<QuestControl></QuestControl>
<LayerControl></LayerControl>
</Control>
@ -116,7 +117,6 @@ function UtopiaMap({
</PermissionsProvider>
</TagsProvider>
</LayersProvider>
<Outlet></Outlet>
</>
);
}