refactor: toggles CSS를 Tailwind + @wing/ui로 전환
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
부모
e9a41c6663
커밋
2adcbc9a93
@ -6,9 +6,8 @@
|
||||
|
||||
@import "./styles/base.css";
|
||||
|
||||
/* Components (layout.css, topbar.css → inline Tailwind) */
|
||||
/* Components (layout/topbar/toggles → inline Tailwind + @wing/ui) */
|
||||
@import "./styles/components/panels.css";
|
||||
@import "./styles/components/toggles.css";
|
||||
@import "./styles/components/speed.css";
|
||||
@import "./styles/components/vessel-list.css";
|
||||
@import "./styles/components/ais-list.css";
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
/* Type grid */
|
||||
.tg {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.tb {
|
||||
background: var(--card);
|
||||
border: 1px solid transparent;
|
||||
border-radius: 5px;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
transition: all 0.15s;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tb:hover {
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
.tb.on {
|
||||
border-color: var(--accent);
|
||||
background: rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
.tb .c {
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.tb .n {
|
||||
font-size: 8px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
/* Toggles */
|
||||
.tog {
|
||||
display: flex;
|
||||
gap: 3px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.tog.tog-map {
|
||||
/* Keep "지도 표시 설정" buttons in a predictable 2-row layout (4 columns). */
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.tog.tog-map .tog-btn {
|
||||
flex: 1 1 calc(25% - 4px);
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.tog-btn {
|
||||
font-size: 8px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--card);
|
||||
color: var(--muted);
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tog-btn.on {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
border-color: var(--accent);
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
import { ToggleButton } from '@wing/ui';
|
||||
import type { Map3DSettings } from "../../widgets/map3d/Map3D";
|
||||
|
||||
type Props = {
|
||||
@ -13,11 +14,11 @@ export function Map3DSettingsToggles({ value, onToggle }: Props) {
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="tog">
|
||||
<div className="flex flex-wrap gap-0.75 mb-1.5">
|
||||
{items.map((t) => (
|
||||
<div key={t.id} className={`tog-btn ${value[t.id] ? "on" : ""}`} onClick={() => onToggle(t.id)}>
|
||||
<ToggleButton key={t.id} on={value[t.id]} onClick={() => onToggle(t.id)}>
|
||||
{t.label}
|
||||
</div>
|
||||
</ToggleButton>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -146,8 +146,7 @@ export function MapSettingsPanel({ value, onChange }: MapSettingsPanelProps) {
|
||||
<div className="ms-label" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
수심 구간 색상
|
||||
<span
|
||||
className={`tog-btn${autoGradient ? ' on' : ''}`}
|
||||
style={{ fontSize: 8, padding: '1px 5px', marginLeft: 8 }}
|
||||
className={`ml-2 cursor-pointer rounded border px-1.5 py-px text-[8px] transition-all duration-150 select-none ${autoGradient ? 'border-wing-accent bg-wing-accent text-white' : 'border-wing-border bg-wing-card text-wing-muted'}`}
|
||||
onClick={toggleAutoGradient}
|
||||
title="최소/최대 색상 기준으로 중간 구간을 자동 보간합니다"
|
||||
>
|
||||
@ -176,11 +175,11 @@ export function MapSettingsPanel({ value, onChange }: MapSettingsPanelProps) {
|
||||
{/* ── Depth font size ───────────────────────────── */}
|
||||
<div className="ms-section">
|
||||
<div className="ms-label">수심 폰트 크기</div>
|
||||
<div className="tog" style={{ gap: 3 }}>
|
||||
<div className="flex flex-wrap gap-0.75">
|
||||
{FONT_SIZES.map((fs) => (
|
||||
<div
|
||||
key={fs.value}
|
||||
className={`tog-btn${value.depthFontSize === fs.value ? ' on' : ''}`}
|
||||
className={`cursor-pointer rounded border px-1.5 py-0.5 text-[8px] transition-all duration-150 select-none ${value.depthFontSize === fs.value ? 'border-wing-accent bg-wing-accent text-white' : 'border-wing-border bg-wing-card text-wing-muted'}`}
|
||||
onClick={() => update('depthFontSize', fs.value)}
|
||||
>
|
||||
{fs.label}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { ToggleButton } from '@wing/ui';
|
||||
|
||||
export type MapToggleState = {
|
||||
pairLines: boolean;
|
||||
pairRange: boolean;
|
||||
@ -27,11 +29,16 @@ export function MapToggles({ value, onToggle }: Props) {
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="tog tog-map">
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{items.map((t) => (
|
||||
<div key={t.id} className={`tog-btn ${value[t.id] ? "on" : ""}`} onClick={() => onToggle(t.id)}>
|
||||
<ToggleButton
|
||||
key={t.id}
|
||||
on={value[t.id]}
|
||||
onClick={() => onToggle(t.id)}
|
||||
className="flex-[1_1_calc(25%-4px)] overflow-hidden text-center text-ellipsis whitespace-nowrap"
|
||||
>
|
||||
{t.label}
|
||||
</div>
|
||||
</ToggleButton>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -9,26 +9,26 @@ type Props = {
|
||||
onToggleAll: () => void;
|
||||
};
|
||||
|
||||
const TB = "cursor-pointer rounded-[5px] border p-1 text-center transition-all duration-150 select-none";
|
||||
const TB_ON = "border-wing-accent bg-wing-accent/10";
|
||||
const TB_OFF = "border-transparent bg-wing-card hover:border-wing-border";
|
||||
|
||||
export function TypeFilterGrid({ enabled, totalCount, countsByType, onToggle, onToggleAll }: Props) {
|
||||
const allOn = VESSEL_TYPE_ORDER.every((c) => enabled[c]);
|
||||
|
||||
return (
|
||||
<div className="tg">
|
||||
<div className={`tb ${allOn ? "on" : ""}`} onClick={onToggleAll} style={{ gridColumn: "1/-1" }}>
|
||||
<div className="c" style={{ color: "var(--accent)" }}>
|
||||
전체
|
||||
</div>
|
||||
<div className="n">{totalCount}척</div>
|
||||
<div className="grid grid-cols-3 gap-0.75">
|
||||
<div className={`col-span-full ${TB} ${allOn ? TB_ON : TB_OFF}`} onClick={onToggleAll}>
|
||||
<div className="text-[11px] font-extrabold text-wing-accent">전체</div>
|
||||
<div className="text-[8px] text-wing-muted">{totalCount}척</div>
|
||||
</div>
|
||||
{VESSEL_TYPE_ORDER.map((code) => {
|
||||
const t = VESSEL_TYPES[code];
|
||||
const cnt = countsByType[code] ?? 0;
|
||||
return (
|
||||
<div key={code} className={`tb ${enabled[code] ? "on" : ""}`} onClick={() => onToggle(code)}>
|
||||
<div className="c" style={{ color: t.color }}>
|
||||
{code}
|
||||
</div>
|
||||
<div className="n">{cnt}척</div>
|
||||
<div key={code} className={`${TB} ${enabled[code] ? TB_ON : TB_OFF}`} onClick={() => onToggle(code)}>
|
||||
<div className="text-[11px] font-extrabold" style={{ color: t.color }}>{code}</div>
|
||||
<div className="text-[8px] text-wing-muted">{cnt}척</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ToggleButton } from '@wing/ui';
|
||||
import type { AisTarget } from '../../entities/aisTarget/model/types';
|
||||
import type { LegacyVesselIndex } from '../../entities/legacyVessel/lib';
|
||||
import type { LegacyVesselDataset, LegacyVesselInfo } from '../../entities/legacyVessel/model/types';
|
||||
@ -97,9 +98,9 @@ export function DashboardSidebar({
|
||||
<div className="flex flex-col overflow-y-auto border-r border-wing-border bg-wing-surface max-md:hidden">
|
||||
<div className="sb">
|
||||
<div className="sb-t">업종 필터</div>
|
||||
<div className="tog">
|
||||
<div
|
||||
className={`tog-btn ${showTargets ? 'on' : ''}`}
|
||||
<div className="flex flex-wrap gap-0.75 mb-1.5">
|
||||
<ToggleButton
|
||||
on={showTargets}
|
||||
onClick={() => {
|
||||
setShowTargets((v) => {
|
||||
const next = !v;
|
||||
@ -110,10 +111,10 @@ export function DashboardSidebar({
|
||||
title="레거시(CN permit) 대상 선박 표시"
|
||||
>
|
||||
대상 선박
|
||||
</div>
|
||||
<div className={`tog-btn ${showOthers ? 'on' : ''}`} onClick={() => setShowOthers((v) => !v)} title="대상 외 AIS 선박 표시">
|
||||
</ToggleButton>
|
||||
<ToggleButton on={showOthers} onClick={() => setShowOthers((v) => !v)} title="대상 외 AIS 선박 표시">
|
||||
기타 AIS
|
||||
</div>
|
||||
</ToggleButton>
|
||||
</div>
|
||||
<TypeFilterGrid
|
||||
enabled={typeEnabled}
|
||||
@ -138,14 +139,15 @@ export function DashboardSidebar({
|
||||
<div className="sb-t" style={{ display: 'flex', alignItems: 'center' }}>
|
||||
지도 표시 설정
|
||||
<div style={{ flex: 1 }} />
|
||||
<div
|
||||
className={`tog-btn ${projection === 'globe' ? 'on' : ''}${isProjectionToggleDisabled ? ' disabled' : ''}`}
|
||||
<ToggleButton
|
||||
on={projection === 'globe'}
|
||||
onClick={isProjectionToggleDisabled ? undefined : () => setProjection((p) => (p === 'globe' ? 'mercator' : 'globe'))}
|
||||
title={isProjectionToggleDisabled ? '3D 모드 준비 중...' : '3D 지구본 투영: 드래그로 회전, 휠로 확대/축소'}
|
||||
style={{ fontSize: 9, padding: '2px 8px', opacity: isProjectionToggleDisabled ? 0.4 : 1, cursor: isProjectionToggleDisabled ? 'not-allowed' : 'pointer' }}
|
||||
className="px-2 py-0.5 text-[9px]"
|
||||
style={{ opacity: isProjectionToggleDisabled ? 0.4 : 1, cursor: isProjectionToggleDisabled ? 'not-allowed' : 'pointer' }}
|
||||
>
|
||||
3D
|
||||
</div>
|
||||
</ToggleButton>
|
||||
</div>
|
||||
<MapToggles value={overlays} onToggle={(k) => setOverlays((prev) => ({ ...prev, [k]: !prev[k] }))} />
|
||||
</div>
|
||||
|
||||
불러오는 중...
Reference in New Issue
Block a user