Add price-only MapPin variant (no name)
Name is now optional. When omitted, renders a compact single-line pill with just "From $X" using the bolder name styling. Useful for denser map views or when provider identity isn't needed at pin level. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -74,6 +74,30 @@ export const NameOnlyUnverified: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Price-only pill — no name, verified */
|
||||||
|
export const PriceOnly: Story = {
|
||||||
|
args: {
|
||||||
|
price: 900,
|
||||||
|
verified: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Price-only pill — unverified */
|
||||||
|
export const PriceOnlyUnverified: Story = {
|
||||||
|
args: {
|
||||||
|
price: 1200,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Price-only pill — active */
|
||||||
|
export const PriceOnlyActive: Story = {
|
||||||
|
args: {
|
||||||
|
price: 900,
|
||||||
|
verified: true,
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/** Custom price label */
|
/** Custom price label */
|
||||||
export const CustomPriceLabel: Story = {
|
export const CustomPriceLabel: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import type { SxProps, Theme } from '@mui/material/styles';
|
|||||||
|
|
||||||
/** Props for the FA MapPin atom */
|
/** Props for the FA MapPin atom */
|
||||||
export interface MapPinProps {
|
export interface MapPinProps {
|
||||||
/** Provider or venue name — always shown on the pin */
|
/** Provider or venue name — omit for a price-only pill */
|
||||||
name: string;
|
name?: string;
|
||||||
/** Starting package price in dollars — shown as "From $X" */
|
/** Starting package price in dollars — shown as "From $X" */
|
||||||
price?: number;
|
price?: number;
|
||||||
/** Custom price label (e.g. "POA") — overrides formatted price */
|
/** Custom price label (e.g. "POA") — overrides formatted price */
|
||||||
@@ -81,7 +81,8 @@ const colours = {
|
|||||||
* Usage:
|
* Usage:
|
||||||
* ```tsx
|
* ```tsx
|
||||||
* <MapPin name="H.Parsons" price={900} verified onClick={...} />
|
* <MapPin name="H.Parsons" price={900} verified onClick={...} />
|
||||||
* <MapPin name="Smith & Sons" /> {/* No price, unverified *\/}
|
* <MapPin name="Smith & Sons" /> {/* Name only, unverified *\/}
|
||||||
|
* <MapPin price={900} verified /> {/* Price-only pill, no name *\/}
|
||||||
* <MapPin name="H.Parsons" price={900} verified active />
|
* <MapPin name="H.Parsons" price={900} verified active />
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@@ -105,7 +106,7 @@ export const MapPin = React.forwardRef<HTMLDivElement, MapPinProps>(
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
aria-label={`${name}${hasPrice ? `, packages from $${price?.toLocaleString('en-AU') ?? priceLabel}` : ''}${verified ? ', verified' : ''}${active ? ' (selected)' : ''}`}
|
aria-label={`${name ?? (verified ? 'Verified' : 'Unverified') + ' provider'}${hasPrice ? `, packages from $${price?.toLocaleString('en-AU') ?? priceLabel}` : ''}${verified ? ', verified' : ''}${active ? ' (selected)' : ''}`}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
sx={[
|
sx={[
|
||||||
@@ -150,34 +151,42 @@ export const MapPin = React.forwardRef<HTMLDivElement, MapPinProps>(
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Name */}
|
{/* Name */}
|
||||||
<Box
|
{name && (
|
||||||
component="span"
|
<Box
|
||||||
sx={{
|
component="span"
|
||||||
fontSize: 12,
|
sx={{
|
||||||
fontWeight: 700,
|
fontSize: 12,
|
||||||
fontFamily: (t: Theme) => t.typography.fontFamily,
|
fontWeight: 700,
|
||||||
lineHeight: 1.3,
|
fontFamily: (t: Theme) => t.typography.fontFamily,
|
||||||
color: active ? palette.activeName : palette.name,
|
lineHeight: 1.3,
|
||||||
whiteSpace: 'nowrap',
|
color: active ? palette.activeName : palette.name,
|
||||||
overflow: 'hidden',
|
whiteSpace: 'nowrap',
|
||||||
textOverflow: 'ellipsis',
|
overflow: 'hidden',
|
||||||
maxWidth: '100%',
|
textOverflow: 'ellipsis',
|
||||||
transition: 'color 150ms ease-in-out',
|
maxWidth: '100%',
|
||||||
}}
|
transition: 'color 150ms ease-in-out',
|
||||||
>
|
}}
|
||||||
{name}
|
>
|
||||||
</Box>
|
{name}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Price line */}
|
{/* Price line */}
|
||||||
{hasPrice && (
|
{hasPrice && (
|
||||||
<Box
|
<Box
|
||||||
component="span"
|
component="span"
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: 11,
|
fontSize: !name ? 12 : 11,
|
||||||
fontWeight: 600,
|
fontWeight: !name ? 700 : 600,
|
||||||
fontFamily: (t: Theme) => t.typography.fontFamily,
|
fontFamily: (t: Theme) => t.typography.fontFamily,
|
||||||
lineHeight: 1.2,
|
lineHeight: 1.2,
|
||||||
color: active ? palette.activePrice : palette.price,
|
color: !name
|
||||||
|
? active
|
||||||
|
? palette.activeName
|
||||||
|
: palette.name
|
||||||
|
: active
|
||||||
|
? palette.activePrice
|
||||||
|
: palette.price,
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
transition: 'color 150ms ease-in-out',
|
transition: 'color 150ms ease-in-out',
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user