Skip to content

Commit 9a76520

Browse files
committed
fix: 改进移动端组件样式与 Legend 图标渲染,修正 release 脚本 bump 目标
- LegendIcon: 支持 URL 图标与文字图标两种渲染模式 - MobileToolbar: 重构为浮动胶囊样式,增加中文标签 - MobileSheetLegend: 改用 max-h 动画替代条件渲染 - BottomSheet: z-index 提升至 1000 避免遮挡 - tailwind.css: 清理未使用的 popup 样式 - IconFontLabel demo: 调整 iconBgShapeSize/cornerRadius - release.sh: bump 目标从根 package.json 改为 packages/core + packages/cli
1 parent f9974de commit 9a76520

7 files changed

Lines changed: 88 additions & 398 deletions

File tree

packages/core/src/components/Legend/LegendIcon.tsx

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import React, { useState } from 'react';
22
import type { LegendIconSchema, LegendInteractionCallbacks } from '../../schema/types';
33
import { cx } from '../../utils/style';
44

5+
/** 判断字符串是否为可加载的 URL(图片地址) */
6+
function isUrlIcon(icon: string): boolean {
7+
return /^(https?:|\/\/|data:)/i.test(icon);
8+
}
9+
510
export interface LegendIconProps extends LegendIconSchema {
611
className?: string;
712
interaction?: LegendInteractionCallbacks;
@@ -71,22 +76,30 @@ export function LegendIcon({ title, items, className, interaction }: LegendIconP
7176
onMouseLeave={handleMouseLeave}
7277
onClick={() => handleClick(i)}
7378
>
74-
<img
75-
src={item.icon}
76-
alt={item.label}
77-
className="size-5 object-contain shrink-0"
78-
onError={(e) => {
79-
const target = e.target as HTMLImageElement;
80-
target.style.display = 'none';
81-
const fallback = target.nextElementSibling as HTMLElement;
82-
if (fallback) fallback.style.display = 'flex';
83-
}}
84-
/>
85-
<span
86-
className="size-5 hidden items-center justify-center shrink-0 text-base leading-none text-on-surface-variant"
87-
>
88-
89-
</span>
79+
{isUrlIcon(item.icon) ? (
80+
<img
81+
src={item.icon}
82+
alt={item.label}
83+
className="size-5 object-contain shrink-0"
84+
onError={(e) => {
85+
const target = e.target as HTMLImageElement;
86+
target.style.display = 'none';
87+
const fallback = target.nextElementSibling as HTMLElement;
88+
if (fallback) fallback.style.display = 'flex';
89+
}}
90+
/>
91+
) : (
92+
<span className="size-5 flex items-center justify-center shrink-0 text-base leading-none">
93+
{item.icon}
94+
</span>
95+
)}
96+
{isUrlIcon(item.icon) && (
97+
<span
98+
className="size-5 hidden items-center justify-center shrink-0 text-base leading-none text-on-surface-variant"
99+
>
100+
101+
</span>
102+
)}
90103
<span className="text-xs leading-4 text-on-surface">{item.label}</span>
91104
</div>
92105
);

packages/core/src/components/Mobile/BottomSheet.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ export function BottomSheet({
220220
left: 0,
221221
width: '100%',
222222
height: currentHeight,
223-
zIndex: 50,
223+
zIndex: 1000,
224224
pointerEvents: 'auto',
225225
transition: isAnimating ? 'height 0.3s cubic-bezier(0.4, 0, 0.2, 1)' : 'none',
226226
willChange: 'height',

packages/core/src/components/Mobile/MobileSheetLegend.tsx

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,14 @@ export function MobileSheetLegend({
3737
return (
3838
<div
3939
className={cx(
40-
'absolute bottom-3 left-3 right-3 z-30 transition-all duration-300',
41-
expanded ? 'max-h-[65vh]' : 'max-h-14',
40+
'absolute bottom-3 left-3 right-3 z-[1000]',
4241
className,
4342
)}
4443
>
45-
<div className="rounded-xl border border-outline-variant/30 bg-surface/80 backdrop-blur-md p-3 px-3.5 text-on-surface shadow-lg">
44+
<div className="flex flex-col rounded-xl border border-outline-variant/30 bg-surface/80 backdrop-blur-md px-3.5 text-on-surface shadow-lg">
4645
<button
4746
onClick={() => setExpanded(!expanded)}
48-
className="w-full flex items-center justify-between px-0 py-3 text-label-caps font-label-caps uppercase"
47+
className="w-full flex items-center justify-between py-3 text-label-caps font-label-caps uppercase"
4948
style={{
5049
background: 'none',
5150
border: 'none',
@@ -67,17 +66,20 @@ export function MobileSheetLegend({
6766
<path d="M6 9l6 6 6-6" />
6867
</svg>
6968
</button>
70-
{expanded && (
71-
<div className="flex flex-col gap-4 [&>*+*]:border-t [&>*+*]:border-outline-variant/20 [&>*+*]:pt-4 custom-scrollbar" style={{ maxHeight: '55vh', overflowY: 'auto' }}>
72-
{legends.map((legend, index) => (
73-
<LegendItem
74-
key={`mobile-legend-${index}`}
75-
legend={legend}
76-
interaction={interaction}
77-
/>
78-
))}
79-
</div>
80-
)}
69+
<div
70+
className={cx(
71+
'flex flex-col gap-4 [&>*+*]:border-t [&>*+*]:border-outline-variant/20 [&>*+*]:pt-4 custom-scrollbar transition-all duration-300 overflow-y-auto',
72+
expanded ? 'max-h-[60vh] pb-3' : 'max-h-0',
73+
)}
74+
>
75+
{legends.map((legend, index) => (
76+
<LegendItem
77+
key={`mobile-legend-${index}`}
78+
legend={legend}
79+
interaction={interaction}
80+
/>
81+
))}
82+
</div>
8183
</div>
8284
</div>
8385
);

packages/core/src/components/Mobile/MobileToolbar.tsx

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,52 +49,67 @@ export function MobileToolbar({ config, className }: MobileToolbarProps) {
4949

5050
const ACTION_ICONS: Record<string, React.ReactNode> = {
5151
zoomIn: (
52-
<svg viewBox="0 0 24 24" className="w-5 h-5" fill="none" stroke="currentColor" strokeWidth={2}>
52+
<svg viewBox="0 0 24 24" className="w-6 h-6" fill="none" stroke="currentColor" strokeWidth={2}>
5353
<path d="M12 5v14m-7-7h14" />
5454
</svg>
5555
),
5656
zoomOut: (
57-
<svg viewBox="0 0 24 24" className="w-5 h-5" fill="none" stroke="currentColor" strokeWidth={2}>
57+
<svg viewBox="0 0 24 24" className="w-6 h-6" fill="none" stroke="currentColor" strokeWidth={2}>
5858
<path d="M5 12h14" />
5959
</svg>
6060
),
6161
locate: (
62-
<svg viewBox="0 0 24 24" className="w-5 h-5" fill="none" stroke="currentColor" strokeWidth={2}>
62+
<svg viewBox="0 0 24 24" className="w-6 h-6" fill="none" stroke="currentColor" strokeWidth={2}>
6363
<circle cx="12" cy="12" r="3" />
6464
<path d="M12 2v4m0 12v4m10-10h-4M6 12H2" />
6565
</svg>
6666
),
6767
reset: (
68-
<svg viewBox="0 0 24 24" className="w-5 h-5" fill="none" stroke="currentColor" strokeWidth={2}>
68+
<svg viewBox="0 0 24 24" className="w-6 h-6" fill="none" stroke="currentColor" strokeWidth={2}>
6969
<path d="M3 12a9 9 0 1 1 3.3 6.9" />
7070
<path d="M3 22v-7h7" />
7171
</svg>
7272
),
7373
layers: (
74-
<svg viewBox="0 0 24 24" className="w-5 h-5" fill="none" stroke="currentColor" strokeWidth={2}>
74+
<svg viewBox="0 0 24 24" className="w-6 h-6" fill="none" stroke="currentColor" strokeWidth={2}>
7575
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" />
7676
</svg>
7777
),
7878
};
7979

80+
const ACTION_LABELS: Record<string, string> = {
81+
zoomIn: '放大',
82+
zoomOut: '缩小',
83+
locate: '定位',
84+
reset: '复位',
85+
layers: '图层',
86+
};
87+
88+
const wrapperPosition =
89+
position === 'bottom'
90+
? 'bottom-0 left-0 right-0 flex justify-center pb-[calc(env(safe-area-inset-bottom,0px)+12px)] pt-2'
91+
: 'top-0 left-0 right-0 flex justify-center pt-[calc(env(safe-area-inset-top,0px)+12px)] pb-2';
92+
8093
return (
8194
<div
82-
className={cx(
83-
'absolute z-40 bg-surface/80 backdrop-blur-md border-t border-outline-variant/30 safe-area-inset shadow-lg',
84-
positionClasses,
85-
className,
86-
)}
95+
className={cx('absolute z-[1000] px-3 pointer-events-none', wrapperPosition)}
8796
>
88-
<div className="flex items-center justify-around py-3 px-4">
97+
<div className="pointer-events-auto flex items-center gap-1 rounded-[20px] border border-outline-variant/40 bg-surface/85 px-1.5 py-1.5 shadow-[0_8px_32px_rgba(0,0,0,0.16)] backdrop-blur-xl">
8998
{items.map((item, index) => (
9099
<button
91100
key={`${item}-${index}`}
92101
onClick={() => handleAction(item)}
93-
className="flex flex-col items-center gap-1 p-2 text-on-surface hover:bg-surface-variant transition-colors rounded-lg"
94-
aria-label={item}
102+
className="group flex flex-col items-center gap-1 rounded-2xl px-2.5 py-1.5 text-on-surface-variant transition-colors hover:bg-primary/10 hover:text-primary active:bg-primary/15"
103+
style={{ background: 'none', border: 'none', cursor: 'pointer' }}
104+
aria-label={ACTION_LABELS[item] ?? item}
105+
title={ACTION_LABELS[item] ?? item}
95106
>
96-
{ACTION_ICONS[item] ?? <span className="text-label-caps font-label-caps">{item}</span>}
97-
<span className="text-label-caps font-label-caps">{item}</span>
107+
<span className="flex h-6 w-6 shrink-0 items-center justify-center">
108+
{ACTION_ICONS[item]}
109+
</span>
110+
<span className="text-[11px] font-medium leading-none whitespace-nowrap">
111+
{ACTION_LABELS[item] ?? item}
112+
</span>
98113
</button>
99114
))}
100115
</div>

0 commit comments

Comments
 (0)