컴포넌트/패널 외 영역 (Div, Span)
SearchPanel (조회패널)
VanillaFront
2026. 9. 18. 20:32
Va.SearchPanel — 조회 조건 전용 패널 컨테이너
목록/그리드 화면 상단의 "조회 조건 입력 영역"을 위한 전용 패널입니다. Va.Semantic을 상속받아 <section> 태그로 렌더링되며, va-search-panel 클래스가 부여되어 테두리·상단 강조선·hover 그림자 등 검색 폼 전용 시각 스타일이 자동 적용됩니다.
클래스 정보
Va.SearchPanel extends Va.Semantic extends Va.Component
tagName: 'searchPanel' (실제 렌더링은 <section>)
isContainer: true
기본 사용법
{
tagName: 'searchPanel',
layout: 'ds-flex fd-row ai-center gap-s',
tags: [
{ tagName: 'inputField', label: '이름', ref: 'refName' },
{ tagName: 'inputField', label: '부서', ref: 'refDept' },
{ tagName: 'div', style: { flex: 1 } },
{ tagName: 'button', text: '조회', appearance: 'primary', onClick: 'onClickSearch' }
]
}
왜 별도 컴포넌트인가
동일한 결과를 Va.Panel이나 Va.Div로도 만들 수 있지만, Va.SearchPanel은:
- 일관된 시각적 신호 — 상단에 primary 색 강조선(2px), 테두리, 배경색이 자동 부여되어 "이 영역은 조회 조건이다"라는 신호를 명확히 전달
- hover 인터랙션 — 마우스 올리면 그림자가 부드럽게 나타남 (transition 포함)
- 테마 대응 — Light/Dark/Paper 등 모든 테마에서 검색 패널 전용 스타일 자동 적용
- 의미 전달 — 코드만 봐도 "여기가 검색 조건 영역"임이 명확
- B2B 화면 표준화 — CRUD 화면에서 검색 폼 위치·룩앤필이 프로젝트 전체에서 일관됨
자동 적용되는 CSS
.va-search-panel {
display: flex;
flex-direction: column;
align-items: stretch;
border: 0.1rem solid var(--colorPanelBorder);
border-radius: var(--sizeBorderM);
background-color: var(--colorPanel);
}
/* light 테마 확장 */
.va-search-panel {
border-top: 2px solid var(--colorPrimary); /* 상단 강조선 */
transition: box-shadow var(--lt-duration-slow) var(--lt-easing);
}
.va-search-panel:hover {
box-shadow: var(--lt-shadow-1);
}
기본은 세로 방향 (flex-direction: column)이므로 가로 정렬을 원하면 layout: 'ds-flex fd-row ...'로 override 필요.
속성
Va.Semantic으로부터 상속:
속성타입설명
| text | String | 순수 텍스트 (자동 이스케이프) |
| innerHTML | String | HTML 문자열 |
| layout, style, class, hidden, attributes | — | 공통 속성 |
이벤트
Va.Semantic으로부터 상속 (기본 DOM 이벤트).
메서드
- setText(text) — 텍스트 변경 후 업데이트
- setInnerHTML(html) — HTML 변경 후 업데이트
- Va.Component / Va.Semantic 공통 메서드
내부 구조
<section class="va-search-panel">
<!-- containerElement에 필드 + 버튼 등 -->
</section>
사용 시점 — 언제 쓰나
- CRUD 화면의 조회 조건 영역 — 목록/그리드 위쪽의 검색 폼
- 필터 폼 — 상세 검색, 다중 조건 필터링
- 리포트 조회 조건 — 날짜 범위, 분류, 조건 선택 후 조회
사용하지 말아야 할 때
- 일반적인 폼 입력 → Va.Panel 또는 Va.Div
- 화면 최상위 → Va.Page
- 탭 인터페이스 → Va.Tab
- 입력 폼 자체 → SearchPanel은 컨테이너, 필드는 Va.InputField 등
자주 쓰는 조합 예시
단일 행 검색 폼
{
tagName: 'searchPanel',
layout: 'ds-flex fd-row ai-center gap-s',
style: { padding: '10px' },
tags: [
{ tagName: 'inputField', label: '이름', ref: 'refName' },
{ tagName: 'comboboxField', label: '부서', ref: 'refDept', items: [/* ... */] },
{ tagName: 'div', style: { flex: 1 } },
{ tagName: 'button', text: '조회', appearance: 'primary', onClick: 'onClickSearch' },
{ tagName: 'button', text: '초기화', onClick: 'onClickReset' }
]
}
다중 행 검색 폼
{
tagName: 'searchPanel',
style: { padding: '15px' },
tags: [{
tagName: 'div',
layout: 'ds-flex fd-row gap-s',
tags: [
{ tagName: 'inputField', label: '이름', ref: 'refName' },
{ tagName: 'inputField', label: '이메일', ref: 'refEmail' }
]
},{
tagName: 'div',
layout: 'ds-flex fd-row gap-s',
style: { marginTop: '10px' },
tags: [
{ tagName: 'dateField', label: '가입일 시작', ref: 'refStartDate' },
{ tagName: 'dateField', label: '가입일 종료', ref: 'refEndDate' },
{ tagName: 'div', style: { flex: 1 } },
{ tagName: 'button', text: '조회', appearance: 'primary', onClick: 'onClickSearch' }
]
}]
}
Page > SearchPanel + Grid 표준 CRUD
{
tagName: 'page',
tags: [{
tagName: 'searchPanel',
layout: 'ds-flex fd-row ai-center gap-s',
style: { padding: '10px' },
tags: [
{ tagName: 'inputField', label: '키워드', ref: 'refKeyword' },
{ tagName: 'div', style: { flex: 1 } },
{ tagName: 'button', text: '조회', appearance: 'primary', onClick: 'onClickSearch' }
]
},{
tagName: 'panel',
style: { flex: 1 },
tags: [{
ref: 'refGrid',
tagName: 'grid',
columns: [ /* ... */ ],
onRowClick: 'onRowClick'
}]
}]
}
collapsible한 고급 검색 (Details와 조합)
{
tagName: 'searchPanel',
tags: [{
tagName: 'div',
layout: 'ds-flex fd-row gap-s',
style: { padding: '10px' },
tags: [
{ tagName: 'inputField', label: '키워드' },
{ tagName: 'div', style: { flex: 1 } },
{ tagName: 'button', text: '조회', appearance: 'primary' }
]
},{
tagName: 'details',
title: '고급 검색',
open: false,
tags: [
{ tagName: 'dateField', label: '시작일' },
{ tagName: 'dateField', label: '종료일' },
{ tagName: 'comboboxField', label: '상태', items: [ /* ... */ ] }
]
}]
}
실전 예시 — 사용자 목록 화면
export default class UserList extends Va.View {
constructor(){ super(arguments); }
mounted(){ this.loadUsers(); }
onClickSearch(){
let name = this.getRef('refName').getValue();
let dept = this.getRef('refDept').getValue();
UserService.search(this, { name, dept }, (res) => {
this.getRef('refGrid').setData(res.data);
});
}
onClickReset(){
this.getRef('refName').setValue('');
this.getRef('refDept').setValue('');
}
config(){
return {
tagName: 'page',
tags: [{
tagName: 'searchPanel',
layout: 'ds-flex fd-row ai-center gap-s',
style: { padding: '10px' },
tags: [
{ tagName: 'inputField', label: '이름', ref: 'refName' },
{ tagName: 'comboboxField', label: '부서', ref: 'refDept', items: [
{ code: 'DEV', name: '개발' },
{ code: 'DES', name: '디자인' }
]},
{ tagName: 'div', style: { flex: 1 } },
{ tagName: 'button', text: '조회', appearance: 'primary', onClick: 'onClickSearch' },
{ tagName: 'button', text: '초기화', onClick: 'onClickReset' }
]
},{
tagName: 'panel',
style: { flex: 1 },
tags: [{
ref: 'refGrid',
tagName: 'grid',
columns: [
{ key: 'name', title: '이름', width: 100 },
{ key: 'dept', title: '부서', width: 100 },
{ key: 'email', title: '이메일', fillRatio: 1 }
]
}]
}]
};
}
}
Va.registerView('/view/user/UserList', UserList);
주의사항
- 기본 방향은 세로(column) — 가로 배치를 원하면 명시적으로 layout: 'ds-flex fd-row ...' 지정
- 자체 padding 없음 — 내용을 넣을 때 style: { padding: '10px' } 등을 직접 지정하는 편이 편함
- 상단 primary 강조선은 테마 확장 CSS에서 — light/dark 테마에만 있음. paper 테마에서는 다른 스타일 적용
- hover 시 그림자 자동 — 정적 화면이 아니라 인터랙션 UI라는 시각적 힌트
- Page > SearchPanel + Panel(그리드) 조합이 표준 CRUD 스캐폴드 — Panel과 동급으로 취급하여 Page 자식으로 나란히 놓기
- Panel과 혼동 주의 — Panel은 범용, SearchPanel은 검색 전용. 서로 다른 시각 스타일
대안 비교
상황추천
| 조회 조건 입력 영역 | Va.SearchPanel |
| 일반 섹션 컨테이너 | Va.Panel |
| 순수 그루핑 | Va.Div |
| 접기/펼치기 폼 | Va.Details + SearchPanel 조합 |
| 폼 액션 바 | Va.ActionBar |
| 페이지 최상위 | Va.Page |
참고
- API 문서 페이지: https://vanillafront.com/docs.html?theme=light#main#apisearchpanel
- 연관: Va.Semantic(부모), Va.Panel(범용 대응 컨테이너)