Fix period col dropdown dark mode: custom dropdown with theme-aware colors
Replaced native <select> (macOS ignores CSS on option elements) with a custom button+ul dropdown. Background/text/border colors are applied via useTheme so they respond correctly to dark mode toggle. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
52be043c1d
commit
e425c32134
@ -89,5 +89,6 @@ body { margin: 0; background-color: var(--bg-primary); color: var(--text-primary
|
|||||||
.dark ::selection { background-color: var(--accent-bg); color: var(--text-primary); }
|
.dark ::selection { background-color: var(--accent-bg); color: var(--text-primary); }
|
||||||
.dark input { background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border-color); }
|
.dark input { background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border-color); }
|
||||||
.dark select { background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border-color); }
|
.dark select { background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border-color); }
|
||||||
|
.dark select option { background-color: var(--bg-secondary); color: var(--text-primary); }
|
||||||
.dark textarea { background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border-color); }
|
.dark textarea { background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border-color); }
|
||||||
.dark .bg-transparent { background-color: transparent; }
|
.dark .bg-transparent { background-color: transparent; }
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect, useRef } from 'react'
|
||||||
|
import useTheme from '../theme.jsx'
|
||||||
|
|
||||||
const ROLES = ['ignore', 'dimension', 'value', 'units', 'date', 'filter']
|
const ROLES = ['ignore', 'dimension', 'value', 'units', 'date', 'filter']
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ const ROLE_STYLE = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Setup({ refreshSources }) {
|
export default function Setup({ refreshSources }) {
|
||||||
|
const { dark } = useTheme()
|
||||||
const [tables, setTables] = useState([])
|
const [tables, setTables] = useState([])
|
||||||
const [sources, setSources] = useState([])
|
const [sources, setSources] = useState([])
|
||||||
const [selectedSource, setSelectedSource] = useState(null)
|
const [selectedSource, setSelectedSource] = useState(null)
|
||||||
@ -25,6 +27,8 @@ export default function Setup({ refreshSources }) {
|
|||||||
const [generating, setGenerating] = useState(false)
|
const [generating, setGenerating] = useState(false)
|
||||||
const [msg, setMsg] = useState(null)
|
const [msg, setMsg] = useState(null)
|
||||||
const [dimPeriodCols, setDimPeriodCols] = useState([])
|
const [dimPeriodCols, setDimPeriodCols] = useState([])
|
||||||
|
const [openPeriodIdx, setOpenPeriodIdx] = useState(null)
|
||||||
|
const periodDropRef = useRef(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch('/api/tables').then(r => r.json()).then(setTables).catch(console.error)
|
fetch('/api/tables').then(r => r.json()).then(setTables).catch(console.error)
|
||||||
@ -32,6 +36,16 @@ export default function Setup({ refreshSources }) {
|
|||||||
loadSources()
|
loadSources()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (openPeriodIdx === null) return
|
||||||
|
function handleClick(e) {
|
||||||
|
if (periodDropRef.current && !periodDropRef.current.contains(e.target))
|
||||||
|
setOpenPeriodIdx(null)
|
||||||
|
}
|
||||||
|
document.addEventListener('mousedown', handleClick)
|
||||||
|
return () => document.removeEventListener('mousedown', handleClick)
|
||||||
|
}, [openPeriodIdx])
|
||||||
|
|
||||||
function loadSources() {
|
function loadSources() {
|
||||||
fetch('/api/sources').then(r => r.json()).then(data => {
|
fetch('/api/sources').then(r => r.json()).then(data => {
|
||||||
setSources(data)
|
setSources(data)
|
||||||
@ -325,16 +339,38 @@ export default function Setup({ refreshSources }) {
|
|||||||
className="border border-transparent hover:border-gray-200 focus:border-gray-300 rounded px-1.5 py-0.5 w-full outline-none bg-transparent disabled:opacity-20 disabled:cursor-default"
|
className="border border-transparent hover:border-gray-200 focus:border-gray-300 rounded px-1.5 py-0.5 w-full outline-none bg-transparent disabled:opacity-20 disabled:cursor-default"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-1.5">
|
<td className="px-3 py-1.5 relative">
|
||||||
<select
|
{(() => {
|
||||||
value={col.dim_period_col || ''}
|
const disabled = col.role !== 'dimension' || !col.dim_group
|
||||||
onChange={e => updateCol(i, 'dim_period_col', e.target.value || null)}
|
const isOpen = openPeriodIdx === i
|
||||||
disabled={col.role !== 'dimension' || !col.dim_group}
|
return (
|
||||||
className="text-xs px-1.5 py-0.5 rounded border border-transparent hover:border-gray-200 focus:border-gray-300 outline-none bg-transparent disabled:opacity-20 disabled:cursor-default font-mono w-full"
|
<div ref={isOpen ? periodDropRef : null} className="relative">
|
||||||
>
|
<button
|
||||||
<option value="">—</option>
|
type="button"
|
||||||
{dimPeriodCols.map(c => <option key={c} value={c}>{c}</option>)}
|
disabled={disabled}
|
||||||
</select>
|
onClick={() => setOpenPeriodIdx(isOpen ? null : i)}
|
||||||
|
className="text-xs px-1.5 py-0.5 rounded border border-transparent hover:border-gray-200 outline-none bg-white text-gray-700 disabled:opacity-20 disabled:cursor-default font-mono w-full text-left"
|
||||||
|
>
|
||||||
|
{col.dim_period_col || '—'}
|
||||||
|
</button>
|
||||||
|
{isOpen && (
|
||||||
|
<ul style={{ backgroundColor: dark ? '#2a2c2f' : '#ffffff', color: dark ? '#c5c9d0' : '#374151', borderColor: dark ? '#3b3f46' : '#e5e7eb' }} className="absolute z-50 left-0 top-full mt-0.5 min-w-full border rounded shadow-lg text-xs font-mono max-h-48 overflow-y-auto">
|
||||||
|
<li
|
||||||
|
className="px-2 py-1 cursor-pointer hover:bg-gray-100"
|
||||||
|
onMouseDown={() => { updateCol(i, 'dim_period_col', null); setOpenPeriodIdx(null) }}
|
||||||
|
>—</li>
|
||||||
|
{dimPeriodCols.map(c => (
|
||||||
|
<li
|
||||||
|
key={c}
|
||||||
|
className={`px-2 py-1 cursor-pointer hover:bg-gray-100 ${col.dim_period_col === c ? 'bg-blue-50 text-blue-700' : ''}`}
|
||||||
|
onMouseDown={() => { updateCol(i, 'dim_period_col', c); setOpenPeriodIdx(null) }}
|
||||||
|
>{c}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})()}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-1.5">
|
<td className="px-3 py-1.5">
|
||||||
<input
|
<input
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user