fix: replace example chip gr.HTML+onclick with gr.Button for reliable input fill
gr.HTML inline onclick cannot update Gradio 6 Svelte component state. Replace _example_chips_html() with gr.Button per chip wired to msg_box via Gradio event system. CSS updated from .example-chip to .example-chip-btn. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -318,13 +318,6 @@ _EXAMPLE_QUESTIONS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def _example_chips_html() -> str:
|
|
||||||
"""D4-4: 예시 질문 chip 카드"""
|
|
||||||
chips = "".join(
|
|
||||||
f'<button class="example-chip" onclick="fillInput({repr(q)})">{_html.escape(q)}</button>'
|
|
||||||
for q in _EXAMPLE_QUESTIONS
|
|
||||||
)
|
|
||||||
return f'<div id="example-chips" class="example-chips-wrap">{chips}</div>'
|
|
||||||
|
|
||||||
|
|
||||||
# ── JavaScript (D3 + D4) ──────────────────────────────────────────
|
# ── JavaScript (D3 + D4) ──────────────────────────────────────────
|
||||||
@@ -364,14 +357,10 @@ _JS = """
|
|||||||
if (el) el.classList.add('nav-active');
|
if (el) el.classList.add('nav-active');
|
||||||
};
|
};
|
||||||
|
|
||||||
// D4-3/4: 예시 질문 chip 클릭 → 입력창 채우기
|
// D4-3: 입력창 포커스 유틸
|
||||||
window.fillInput = function(text) {
|
window.focusInput = function() {
|
||||||
const ta = document.querySelector('.pill-input textarea');
|
const ta = document.querySelector('.pill-input textarea');
|
||||||
if (!ta) return;
|
if (ta) ta.focus();
|
||||||
const setter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;
|
|
||||||
setter.call(ta, text);
|
|
||||||
ta.dispatchEvent(new Event('input', { bubbles: true }));
|
|
||||||
ta.focus();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// D4-5: 설정 패널 토글
|
// D4-5: 설정 패널 토글
|
||||||
@@ -575,22 +564,23 @@ footer { display: none !important; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ── 예시 질문 Chip (D4-4) ── */
|
/* ── 예시 질문 Chip (D4-4) ── */
|
||||||
.example-chips-wrap { display: flex; flex-wrap: wrap; gap: 8px; padding: 8px 0 4px; }
|
.example-chips-row { padding: 6px 0 4px !important; flex-wrap: wrap !important; gap: 8px !important; }
|
||||||
.example-chip {
|
.example-chip-btn button {
|
||||||
background: #fff;
|
border-radius: 20px !important;
|
||||||
border: 1.5px solid #e2e8f0;
|
border: 1.5px solid #e2e8f0 !important;
|
||||||
border-radius: 20px;
|
background: #fff !important;
|
||||||
padding: 8px 16px;
|
color: #374151 !important;
|
||||||
font-size: .875rem;
|
padding: 8px 18px !important;
|
||||||
color: #374151;
|
font-size: .875rem !important;
|
||||||
cursor: pointer;
|
box-shadow: none !important;
|
||||||
transition: all .15s;
|
white-space: nowrap !important;
|
||||||
white-space: nowrap;
|
transition: all .15s !important;
|
||||||
|
font-weight: 400 !important;
|
||||||
}
|
}
|
||||||
.example-chip:hover {
|
.example-chip-btn button:hover {
|
||||||
background: #eff6ff;
|
background: #eff6ff !important;
|
||||||
border-color: #93c5fd;
|
border-color: #93c5fd !important;
|
||||||
color: #1d4ed8;
|
color: #1d4ed8 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── 컨트롤 패널 (D4-5) ── */
|
/* ── 컨트롤 패널 (D4-5) ── */
|
||||||
@@ -655,8 +645,8 @@ footer { display: none !important; }
|
|||||||
.dark .message-wrap .bot { background: #1e293b !important; border-color: #334155 !important; }
|
.dark .message-wrap .bot { background: #1e293b !important; border-color: #334155 !important; }
|
||||||
.dark .nav-btn button:hover { background: #1e293b !important; }
|
.dark .nav-btn button:hover { background: #1e293b !important; }
|
||||||
.dark .nav-btn button.nav-active { background: #1e3a5f !important; color: #93c5fd !important; }
|
.dark .nav-btn button.nav-active { background: #1e3a5f !important; color: #93c5fd !important; }
|
||||||
.dark .example-chip { background: #1e293b !important; border-color: #334155 !important; color: #cbd5e1 !important; }
|
.dark .example-chip-btn button { background: #1e293b !important; border-color: #334155 !important; color: #cbd5e1 !important; }
|
||||||
.dark .example-chip:hover { background: #1e3a5f !important; border-color: #3b82f6 !important; }
|
.dark .example-chip-btn button:hover { background: #1e3a5f !important; border-color: #3b82f6 !important; }
|
||||||
.dark #control-panel { background: #1e293b !important; border-color: #334155 !important; }
|
.dark #control-panel { background: #1e293b !important; border-color: #334155 !important; }
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -756,8 +746,12 @@ with gr.Blocks(title="율봇", css=_CUSTOM_CSS, theme=_THEME, js=_JS) as demo:
|
|||||||
)
|
)
|
||||||
send_btn = gr.Button("↑", variant="primary", scale=0, min_width=48, elem_classes=["pill-send-btn"])
|
send_btn = gr.Button("↑", variant="primary", scale=0, min_width=48, elem_classes=["pill-send-btn"])
|
||||||
|
|
||||||
# D4-4: 예시 질문 Chips
|
# D4-4: 예시 질문 Chips (gr.Button — Gradio 이벤트로 msg_box 직접 업데이트)
|
||||||
gr.HTML(_example_chips_html())
|
with gr.Row(elem_classes=["example-chips-row"]):
|
||||||
|
chip_btns = [
|
||||||
|
gr.Button(q, elem_classes=["example-chip-btn"], size="sm")
|
||||||
|
for q in _EXAMPLE_QUESTIONS
|
||||||
|
]
|
||||||
|
|
||||||
# 첨부 Accordions
|
# 첨부 Accordions
|
||||||
with gr.Accordion("📷 이미지 첨부 (선택)", open=False):
|
with gr.Accordion("📷 이미지 첨부 (선택)", open=False):
|
||||||
@@ -816,6 +810,10 @@ with gr.Blocks(title="율봇", css=_CUSTOM_CSS, theme=_THEME, js=_JS) as demo:
|
|||||||
|
|
||||||
# ── 이벤트 바인딩 ─────────────────────────────────────────────
|
# ── 이벤트 바인딩 ─────────────────────────────────────────────
|
||||||
|
|
||||||
|
# 예시 질문 chips → msg_box 채우기
|
||||||
|
for _q, _btn in zip(_EXAMPLE_QUESTIONS, chip_btns):
|
||||||
|
_btn.click(fn=lambda x=_q: x, outputs=[msg_box])
|
||||||
|
|
||||||
# 사이드바 네비게이션
|
# 사이드바 네비게이션
|
||||||
_panels = [panel_chat, panel_doc_register, panel_doc_manage]
|
_panels = [panel_chat, panel_doc_register, panel_doc_manage]
|
||||||
chat_nav_btn.click(show_chat_panel, outputs=_panels,
|
chat_nav_btn.click(show_chat_panel, outputs=_panels,
|
||||||
|
|||||||
Reference in New Issue
Block a user