Skip to content

Commit a3faf58

Browse files
mu-hundevunt
authored andcommitted
메인 헤더 UI 리뉴얼
1 parent 7adc19f commit a3faf58

File tree

3 files changed

+122
-133
lines changed

3 files changed

+122
-133
lines changed

apps/penxle.com/src/routes/(default)/Header.svelte

+67-51
Original file line numberDiff line numberDiff line change
@@ -51,63 +51,79 @@
5151
position: 'sticky',
5252
borderBottomWidth: '1px',
5353
borderBottomColor: 'gray.100',
54-
paddingX: { base: '20px', sm: '40px' },
54+
paddingX: '20px',
5555
top: '0',
56-
height: { base: '56px', sm: '77px' },
5756
backgroundColor: 'gray.5',
5857
zIndex: '10',
5958
})}
6059
>
61-
<nav class={css({ width: 'full', maxWidth: '1200px' })}>
62-
<section class={flex({ justify: 'space-between', align: 'center' })}>
63-
<a class={flex({ marginRight: '24px' })} href="/">
64-
<Logo class={css({ height: '25px', color: 'gray.900' })} />
65-
</a>
60+
<nav
61+
class={flex({
62+
width: 'full',
63+
maxWidth: '1280px',
64+
justify: 'space-between',
65+
align: 'center',
66+
position: 'relative',
67+
gap: '24px',
68+
})}
69+
>
70+
<a
71+
class={css({
72+
sm: { marginTop: '20px', marginBottom: '17px' },
73+
smDown: { marginTop: '18px', marginBottom: '13px' },
74+
})}
75+
href="/"
76+
>
77+
<Logo class={css({ height: '25px', color: 'gray.900' })} />
78+
</a>
6679

67-
<div
68-
class={flex({
69-
flex: '1',
70-
justify: { base: 'flex-end', sm: 'space-between' },
71-
align: 'center',
72-
sm: { gap: '12px' },
73-
})}
74-
>
75-
<SearchBar style={css.raw({ flex: '1', maxWidth: { base: '400px', smDown: { _focusWithin: 'full' } } })} />
80+
<SearchBar
81+
style={css.raw({
82+
position: 'absolute',
83+
left: '[50%]',
84+
transform: 'translateX(-50%)',
85+
marginRight: '130px',
86+
flex: '1',
87+
hideBelow: 'sm',
88+
maxWidth: '[32%]',
89+
width: 'full',
90+
})}
91+
open
92+
/>
7693

77-
<div class={flex({ align: 'center', gap: { base: '12px', sm: '14px' } })}>
78-
{#if $query.me}
79-
<Button
80-
style={flex.raw({
81-
align: 'center',
82-
gap: '4px',
83-
paddingLeft: '12px',
84-
paddingRight: '14px',
85-
hideBelow: 'sm',
86-
})}
87-
size="md"
88-
type="button"
89-
variant="gray-outline"
90-
on:click={async () => {
91-
const { permalink } = await createPost({ spaceId: undefined });
92-
mixpanel.track('post:create', { via: 'feed' });
93-
await goto(`/editor/${permalink}`);
94-
}}
95-
>
96-
<Icon icon={IconPlus} />
97-
포스트 작성
98-
</Button>
99-
<NotificationMenu $user={$query.me} />
100-
<UserMenu $user={$query.me} />
101-
{:else}
102-
<Button style={css.raw({ hideFrom: 'sm' })} href="/login" size="sm" type="link" variant="gray-outline">
103-
로그인/회원가입
104-
</Button>
105-
<Button style={css.raw({ hideBelow: 'sm' })} href="/login" size="md" type="link" variant="gray-outline">
106-
로그인/회원가입
107-
</Button>
108-
{/if}
109-
</div>
110-
</div>
111-
</section>
94+
<div class={flex({ align: 'center', gap: { base: '24px', sm: '28px' } })}>
95+
<SearchBar style={css.raw({ hideFrom: 'sm', maxWidth: 'full' })} />
96+
{#if $query.me}
97+
<Button
98+
style={flex.raw({
99+
align: 'center',
100+
gap: '4px',
101+
paddingLeft: '12px',
102+
paddingRight: '14px',
103+
hideBelow: 'sm',
104+
})}
105+
size="sm"
106+
type="button"
107+
variant="gray-outline"
108+
on:click={async () => {
109+
const { permalink } = await createPost({ spaceId: undefined });
110+
mixpanel.track('post:create', { via: 'feed' });
111+
await goto(`/editor/${permalink}`);
112+
}}
113+
>
114+
<Icon icon={IconPlus} />
115+
포스트 작성
116+
</Button>
117+
<NotificationMenu $user={$query.me} />
118+
<UserMenu $user={$query.me} />
119+
{:else}
120+
<Button style={css.raw({ hideFrom: 'sm' })} href="/login" size="sm" type="link" variant="gray-outline">
121+
로그인/회원가입
122+
</Button>
123+
<Button style={css.raw({ hideBelow: 'sm' })} href="/login" size="md" type="link" variant="gray-outline">
124+
로그인/회원가입
125+
</Button>
126+
{/if}
127+
</div>
112128
</nav>
113129
</header>

apps/penxle.com/src/routes/(default)/SearchBar.svelte

+51-82
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@
33
import { onMount } from 'svelte';
44
import IconSearch from '~icons/effit/search';
55
import IconChevronLeft from '~icons/tabler/chevron-left';
6-
import IconCircleXFilled from '~icons/tabler/circle-x-filled';
6+
import IconX from '~icons/tabler/x';
77
import { afterNavigate, beforeNavigate, goto } from '$app/navigation';
88
import { page } from '$app/stores';
99
import { Icon } from '$lib/components';
10-
import { css, cx } from '$styled-system/css';
10+
import { TextInput } from '$lib/components/v2/forms';
11+
import { css } from '$styled-system/css';
1112
import { center } from '$styled-system/patterns';
1213
import type { SystemStyleObject } from '$styled-system/types';
1314
1415
export let style: SystemStyleObject | undefined = undefined;
1516
1617
let value = ($page.url.pathname === '/search' && $page.url.searchParams.get('q')) || '';
1718
18-
let open = false;
19+
export let open = false;
1920
2021
afterNavigate(({ from, to }) => {
2122
if (!from || !to) return;
@@ -34,9 +35,17 @@
3435
});
3536
3637
onMount(() => {
37-
if (window.innerWidth >= 800) {
38-
open = true;
39-
}
38+
const toggleSearchBar = () => {
39+
open = window.innerWidth >= 800;
40+
};
41+
42+
toggleSearchBar();
43+
44+
window.addEventListener('resize', toggleSearchBar);
45+
46+
return () => {
47+
window.removeEventListener('resize', toggleSearchBar);
48+
};
4049
});
4150
4251
beforeNavigate(() => {
@@ -48,95 +57,55 @@
4857

4958
{#if open}
5059
<div
51-
class={css({
52-
flexGrow: '1',
53-
smDown: {
54-
position: 'absolute',
55-
left: '0',
56-
right: '0',
57-
top: '0',
58-
zIndex: '50',
59-
display: 'flex',
60-
alignItems: 'center',
61-
gap: '8px',
62-
borderBottomWidth: '1px',
63-
borderBottomColor: 'gray.100',
64-
paddingX: '20px',
65-
backgroundColor: 'gray.5',
66-
height: '56px',
60+
class={css(
61+
{
62+
smDown: {
63+
position: 'absolute',
64+
inset: '0',
65+
zIndex: '50',
66+
display: 'flex',
67+
alignItems: 'center',
68+
gap: '8px',
69+
backgroundColor: 'gray.5',
70+
height: 'full',
71+
},
6772
},
68-
})}
73+
style,
74+
)}
6975
>
7076
<button class={css({ hideFrom: 'sm' })} type="button" on:click={() => (open = false)}>
7177
<Icon icon={IconChevronLeft} size={24} />
7278
</button>
7379
<form
74-
class={css(
75-
{
76-
position: 'relative',
77-
smDown: { maxWidth: 'full' },
78-
},
79-
style,
80-
)}
8180
on:submit|preventDefault={async () => {
8281
await goto(qs.stringifyUrl({ url: '/search', query: { q: value } }));
8382
}}
8483
>
85-
<input
86-
class={cx(
87-
'peer',
88-
css({
89-
borderRadius: '6px',
90-
paddingLeft: '16px',
91-
paddingRight: '68px',
92-
paddingY: '10px',
93-
fontSize: '15px',
94-
backgroundColor: 'gray.50',
95-
width: 'full',
96-
height: { base: '45px', sm: '43px' },
97-
transition: 'common',
98-
_focusWithin: {
99-
ringWidth: '1px',
100-
ringColor: 'teal.500',
101-
backgroundColor: 'gray.5',
102-
},
103-
}),
104-
)}
105-
placeholder="검색어를 입력하세요"
106-
type="search"
107-
bind:value
108-
/>
109-
110-
<button
111-
class={center({
112-
position: 'absolute',
113-
insetY: '0',
114-
right: '48px',
115-
color: 'gray.400',
116-
hideFrom: 'sm',
117-
})}
118-
type="button"
119-
on:click={() => (value = '')}
120-
>
121-
<Icon icon={IconCircleXFilled} size={20} />
122-
</button>
123-
124-
<button
125-
class={center({
126-
position: 'absolute',
127-
insetY: '0',
128-
right: '16px',
129-
transition: 'common',
130-
color: { base: 'gray.500', _peerFocus: 'teal.500' },
131-
})}
132-
type="submit"
133-
>
134-
<Icon icon={IconSearch} size={20} />
135-
</button>
84+
<TextInput placeholder="검색어를 입력하세요" size="sm" type="search" bind:value>
85+
<button slot="left-icon" class={center({ transition: 'common', color: 'gray.500' })} type="submit">
86+
<Icon icon={IconSearch} size={20} />
87+
</button>
88+
<button
89+
slot="right-icon"
90+
class={center({ color: 'gray.600', display: { _disabled: 'none' } })}
91+
aria-label="지우기"
92+
disabled={value.length === 0}
93+
type="button"
94+
on:click={() => (value = '')}
95+
>
96+
<Icon icon={IconX} size={20} />
97+
</button>
98+
</TextInput>
13699
</form>
137100
</div>
138101
{:else}
139-
<button class={center({ marginRight: '8px', size: '34px' })} type="button" on:click={() => (open = true)}>
102+
<button
103+
class={css(style)}
104+
type="button"
105+
on:click={async () => {
106+
open = true;
107+
}}
108+
>
140109
<Icon style={css.raw({ color: 'gray.900' })} icon={IconSearch} size={24} />
141110
</button>
142111
{/if}

apps/penxle.com/src/styles/global.ts

+4
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,8 @@ export const globalCss = defineGlobalStyles({
6161
'::placeholder': {
6262
color: 'gray.600',
6363
},
64+
65+
'::-webkit-search-cancel-button': {
66+
WebkitAppearance: 'none',
67+
},
6468
});

0 commit comments

Comments
 (0)