mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-15 10:04:44 +00:00
Replace hand-rolled card, placeholder, and marker styling in the brewery UI with daisyUI card, skeleton, and theme-color classes
This commit is contained in:
@@ -32,7 +32,7 @@ const WORLD_BOUNDS: LatLngTuple[] = [
|
|||||||
|
|
||||||
const CURRENT_LOCATION_ICON = L.divIcon({
|
const CURRENT_LOCATION_ICON = L.divIcon({
|
||||||
className: 'brewery-map-current-location',
|
className: 'brewery-map-current-location',
|
||||||
html: '<span class="block h-3.5 w-3.5 rounded-full bg-blue-500 border-2 border-white shadow-md"></span>',
|
html: '<span class="block h-3.5 w-3.5 rounded-full bg-primary border-2 border-base-100 shadow-md"></span>',
|
||||||
iconSize: [14, 14],
|
iconSize: [14, 14],
|
||||||
iconAnchor: [7, 7],
|
iconAnchor: [7, 7],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import type { NearbyMapPin } from './NearbyBreweryMap';
|
|||||||
|
|
||||||
const NearbyBreweryMap = lazy(() => import('./NearbyBreweryMap'));
|
const NearbyBreweryMap = lazy(() => import('./NearbyBreweryMap'));
|
||||||
|
|
||||||
const MAP_PLACEHOLDER_CLASS = 'min-h-[30rem] h-full w-full rounded-box bg-base-300';
|
const MAP_PLACEHOLDER_CLASS = 'skeleton min-h-[30rem] h-full w-full rounded-box';
|
||||||
const DEFAULT_RADIUS_KM = 120;
|
const DEFAULT_RADIUS_KM = 120;
|
||||||
const MIN_RADIUS_KM = 10;
|
const MIN_RADIUS_KM = 10;
|
||||||
const MAX_RADIUS_KM = 150;
|
const MAX_RADIUS_KM = 150;
|
||||||
@@ -41,8 +41,8 @@ interface NearbyBreweriesSectionProps {
|
|||||||
const FILLER_NOTE = 'A stop worth the detour.';
|
const FILLER_NOTE = 'A stop worth the detour.';
|
||||||
|
|
||||||
const cardClassName = (selected: boolean) =>
|
const cardClassName = (selected: boolean) =>
|
||||||
`text-left rounded-box bg-base-100 shadow p-4 cursor-pointer transition-shadow hover:shadow-lg border-l-4 ${
|
`card card-sm card-border bg-base-100 text-left shadow transition-shadow hover:shadow-lg ${
|
||||||
selected ? 'border-l-primary' : 'border-l-transparent'
|
selected ? 'border-2 border-primary' : ''
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
interface BreweriesNearByHeaderParams {
|
interface BreweriesNearByHeaderParams {
|
||||||
@@ -288,21 +288,23 @@ const NearbyBreweriesSection = ({
|
|||||||
onClick={() => onSelect(brewery.breweryPostId)}
|
onClick={() => onSelect(brewery.breweryPostId)}
|
||||||
className={cardClassName(selectedId === brewery.breweryPostId)}
|
className={cardClassName(selectedId === brewery.breweryPostId)}
|
||||||
>
|
>
|
||||||
<div className="flex justify-between items-baseline gap-3">
|
<div className="card-body">
|
||||||
<h3 className="font-serif text-lg m-0">
|
<div className="flex justify-between items-baseline gap-3">
|
||||||
{brewery.breweryName}
|
<h3 className="card-title font-serif text-lg">
|
||||||
</h3>
|
{brewery.breweryName}
|
||||||
<span className="text-sm font-semibold text-primary whitespace-nowrap">
|
</h3>
|
||||||
{formatDistance(distanceMetres, unit)}
|
<span className="text-sm font-semibold text-primary whitespace-nowrap">
|
||||||
</span>
|
{formatDistance(distanceMetres, unit)}
|
||||||
</div>
|
</span>
|
||||||
{brewery.location && (
|
|
||||||
<div className="text-sm text-base-content/60 mt-1">
|
|
||||||
{brewery.location.cityName},{' '}
|
|
||||||
{brewery.location.stateProvinceCode}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
{brewery.location && (
|
||||||
<div className="text-sm mt-2">{FILLER_NOTE}</div>
|
<div className="text-sm text-base-content/60">
|
||||||
|
{brewery.location.cityName},{' '}
|
||||||
|
{brewery.location.stateProvinceCode}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="text-sm mt-2">{FILLER_NOTE}</div>
|
||||||
|
</div>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -19,6 +19,14 @@ interface NearbyBreweryMapProps {
|
|||||||
userLocationLabel: string;
|
userLocationLabel: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Leaflet paints markers as SVG attributes, which can't reference CSS custom
|
||||||
|
// properties the way class names can - resolve the current theme's colors instead.
|
||||||
|
const resolveThemeColor = (variable: string, fallback: string) => {
|
||||||
|
if (typeof document === 'undefined') return fallback;
|
||||||
|
const value = getComputedStyle(document.documentElement).getPropertyValue(variable).trim();
|
||||||
|
return value || fallback;
|
||||||
|
};
|
||||||
|
|
||||||
const pinIcon = (active: boolean) =>
|
const pinIcon = (active: boolean) =>
|
||||||
L.divIcon({
|
L.divIcon({
|
||||||
className: '',
|
className: '',
|
||||||
@@ -85,7 +93,12 @@ const NearbyBreweryMap = ({
|
|||||||
<CircleMarker
|
<CircleMarker
|
||||||
center={userLocation}
|
center={userLocation}
|
||||||
radius={6}
|
radius={6}
|
||||||
pathOptions={{ color: '#fff', weight: 2, fillColor: '#2b6cb0', fillOpacity: 1 }}
|
pathOptions={{
|
||||||
|
color: resolveThemeColor('--color-base-100', '#fff'),
|
||||||
|
weight: 2,
|
||||||
|
fillColor: resolveThemeColor('--color-primary', '#2b6cb0'),
|
||||||
|
fillOpacity: 1,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Popup>You are here — {userLocationLabel}</Popup>
|
<Popup>You are here — {userLocationLabel}</Popup>
|
||||||
</CircleMarker>
|
</CircleMarker>
|
||||||
|
|||||||
@@ -13,25 +13,27 @@ const RecentBreweries = ({ breweries }: RecentBreweriesProps) => {
|
|||||||
<h2 className="font-serif text-2xl mb-3.5">Recently added</h2>
|
<h2 className="font-serif text-2xl mb-3.5">Recently added</h2>
|
||||||
<div className="grid gap-5 grid-cols-[repeat(auto-fit,minmax(15rem,1fr))]">
|
<div className="grid gap-5 grid-cols-[repeat(auto-fit,minmax(15rem,1fr))]">
|
||||||
{breweries.map((brewery) => (
|
{breweries.map((brewery) => (
|
||||||
<div
|
<div key={brewery.breweryPostId} className="card bg-base-100 shadow">
|
||||||
key={brewery.breweryPostId}
|
<div className="card-body gap-1.5">
|
||||||
className="card bg-base-100 shadow p-6 flex flex-col gap-1.5"
|
<h3 className="card-title font-serif text-xl">
|
||||||
>
|
{brewery.breweryName}
|
||||||
<h3 className="font-serif text-xl m-0">{brewery.breweryName}</h3>
|
</h3>
|
||||||
{brewery.location && (
|
{brewery.location && (
|
||||||
<div className="text-sm text-base-content/60">
|
<div className="text-sm text-base-content/60">
|
||||||
{brewery.location.cityName}, {brewery.location.stateProvinceCode}
|
{brewery.location.cityName},{' '}
|
||||||
</div>
|
{brewery.location.stateProvinceCode}
|
||||||
)}
|
</div>
|
||||||
<p className="text-sm leading-snug mt-1 line-clamp-2">
|
)}
|
||||||
{brewery.description}
|
<p className="text-sm leading-snug mt-1 line-clamp-2">
|
||||||
</p>
|
{brewery.description}
|
||||||
<Link
|
</p>
|
||||||
to={`/breweries/${brewery.breweryPostId}`}
|
<Link
|
||||||
className="link link-hover text-sm font-semibold text-secondary hover:text-primary mt-2"
|
to={`/breweries/${brewery.breweryPostId}`}
|
||||||
>
|
className="link link-hover text-sm font-semibold text-secondary hover:text-primary mt-2"
|
||||||
View brewery →
|
>
|
||||||
</Link>
|
View brewery →
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { useFetcher } from 'react-router';
|
|||||||
import type { BreweryMapPin } from '../components/BreweryMap';
|
import type { BreweryMapPin } from '../components/BreweryMap';
|
||||||
|
|
||||||
const PAGE_SIZE = 12;
|
const PAGE_SIZE = 12;
|
||||||
const MAP_PLACEHOLDER_CLASS = 'h-[28rem] md:h-[34rem] w-full rounded-box bg-base-300';
|
const MAP_PLACEHOLDER_CLASS = 'skeleton h-[28rem] md:h-[34rem] w-full rounded-box';
|
||||||
|
|
||||||
export const meta = ({}: Route.MetaArgs) => {
|
export const meta = ({}: Route.MetaArgs) => {
|
||||||
return [{ title: 'Brewery Directory | The Biergarten App' }];
|
return [{ title: 'Brewery Directory | The Biergarten App' }];
|
||||||
|
|||||||
Reference in New Issue
Block a user