블로그가 반응형을 지원하도록, 모바일 사이즈인 경우 좌측 메뉴 리스트 노출 로직을 달리 적용해 보자.
일단 Header.svelte
, Aside.svelte
화면을 반응형으로 만들어보고, 이후에 toggle 기능을 추가하자.
사실 Header.svelte
는 이미 반응형이 적용되어 있는 상태이므로 Aside.svelte
만 수정하면 됨.(블로그 틀 만들기 - svelte & material ui 참조)
Aside.svelte
<!-- Don't include fixed={false} if this is a page wide drawer.
It adds a style for absolute positioning. -->
<Drawer variant={drawerVariant} fixed={false} bind:open={drawerOpen}>
...
</Drawer>
<svelte:window bind:innerWidth={innerWidth}/>
<script>
import Drawer, { Content, Header, Title, Subtitle, Scrim } from '@smui/drawer';
import List from '@smui/list';
let innerWidth;
let drawerVariant = 'static';
let drawerOpen = false;
...
const setVisible = () => {
if (innerWidth > 480) {
drawerVariant = 'static';
drawerOpen = true;
} else {
drawerVariant = 'modal';
drawerOpen = false;
}
};
$: setVisible(innerWidth);
</script>
단순히 노출 여부 뿐 아니라 <Drawer />
컴포넌트의 variant
값도 바꿔야 한다.
참고로 variant
값이 static
인 경우 고정된 화면 영역을 가지고 다른 element 들의 위치에 영향을 주고, modal
인 경우에는 다른 element 들 위치에 영향을 주지 않고 위에 겹쳐서 노출한다. (https://sveltematerialui.com/demo/drawer/ 참조)
따라서 Aside.svelte
에서 window 의 innerWidth
를 체크 & 감지할 필요가 있고, <svelte:window />
로 innerWidth
를 bind 함으로서 체크 & 감지할 수 있다.
<!-- window 의 innerWidth 값 bind -->
<svelte:window bind:innerWidth={innerWidth}/>
<script>
...
let innerWidth;
...
// innerWidth 의 변화 감지하고 setVisible 함수 실행
$: setVisible(innerWidth);
</script>
참고로 <svelte:window />
로 innerWidth
뿐만 아니라 여러 프로퍼티들을 bind 할 수 있고 click 과 같은 이벤트도 걸 수도 있고, 또한 svelte 에서는 window 뿐 아니라 self, body, head 등등 여러개의 special element 를 제공한다. (https://svelte.dev/tutorial/svelte-self 참조)
이제 toggle 기능을 추가하자.
Header.svelte
에서 click event 가 발생하면 Aside.svelte
에 전달해줘야 한다.
다만 svelte 에서는 부모 - 자식 컴포넌트 관계가 아니라면 event 전달이 쉽지 않다.
걍 복잡하게 머리 굴리지 말고 store
를 통해 asideOpen
변수를 만들고 관리하자.
Header.svelte
에서는 click event 발생시 store
의 asideOpen
업데이트Aside.svelte
에서는 asideOpen
가 변경되면 화면 갱신먼저 store/aside.js
를 만들고 위 로직에 맞춰 Header.svelte
, Aside.svelte
를 수정하자.
store/aside.js
import { writable } from 'svelte/store';
export default asideOpen = writable(false);
Header.svelte
<script>
...
import asideOpen from '../store/aside.js';
const onClick = () => {
asideOpen.update(open => !open);
};
</script>
Aside.svelte
<!-- Don't include fixed={false} if this is a page wide drawer.
It adds a style for absolute positioning. -->
<Drawer variant={drawerVariant} fixed={false} bind:open={drawerOpen}>
...
</Drawer>
<!-- Don't include fixed={false} if this is a page wide drawer.
It adds a style for absolute positioning. -->
<Scrim fixed={false} />
<svelte:window bind:innerWidth={innerWidth}/>
<script>
import Drawer, { Content, Header, Title, Subtitle, Scrim } from '@smui/drawer';
import List from '@smui/list';
import asideOpen from '../../store/aside.js';
let innerWidth;
let drawerVariant = 'static';
let drawerOpen = false;
const setVisible = () => {
if (innerWidth > 480) {
drawerVariant = 'static';
asideOpen.update(open => false);
} else {
drawerVariant = 'modal';
}
};
asideOpen.subscribe(value => {
drawerOpen = value;
});
$: setVisible(innerWidth);
</script>
최종 화면은 아래와 같다.
모바일 버전일때 헤더 메뉴 아이콘 클릭시 좌측 메뉴 리스트도 잘 toggle 되는 것 확인~.
pc 화면
mobile 화면
숨김 상태 | 노출 상태 |
---|---|
![]() | ![]() |