Skip to content

Commit 29430be

Browse files
authored
Merge pull request velopert#123 from velopert/feature/mobile-write
Feature/mobile write
2 parents edef095 + 3e2025c commit 29430be

19 files changed

+722
-346
lines changed

src/components/base/HeaderUserMenu.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as React from 'react';
22
import styled from 'styled-components';
33
import OutsideClickHandler from 'react-outside-click-handler';
44
import HeaderUserMenuItem from './HeaderUserMenuItem';
5+
import media from '../../lib/styles/media';
56

67
const HeaderUserMenuBlock = styled.div`
78
position: absolute;
@@ -14,6 +15,13 @@ const HeaderUserMenuBlock = styled.div`
1415
width: 12rem;
1516
background: white;
1617
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1);
18+
19+
.mobile-only {
20+
display: none;
21+
${media.medium} {
22+
display: block;
23+
}
24+
}
1725
}
1826
`;
1927

@@ -38,6 +46,9 @@ const HeaderUserMenu: React.FC<HeaderUserMenuProps> = ({
3846
<HeaderUserMenuItem to={`/@${username}`}>
3947
내 벨로그
4048
</HeaderUserMenuItem>
49+
<div className="mobile-only">
50+
<HeaderUserMenuItem to="/write">새 글 작성</HeaderUserMenuItem>
51+
</div>
4152
<HeaderUserMenuItem to="/saves">임시 글</HeaderUserMenuItem>
4253
<HeaderUserMenuItem to="/lists/liked">읽기 목록</HeaderUserMenuItem>
4354
<HeaderUserMenuItem to="/setting">설정</HeaderUserMenuItem>

src/components/main/MainHeader.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import HeaderUserIcon from '../base/HeaderUserIcon';
88
import useToggle from '../../lib/hooks/useToggle';
99
import HeaderUserMenu from '../base/HeaderUserMenu';
1010
import { Link } from 'react-router-dom';
11-
import { mediaQuery } from '../../lib/styles/media';
11+
import media, { mediaQuery } from '../../lib/styles/media';
1212

1313
export type MainHeaderProps = {};
1414

@@ -102,7 +102,7 @@ const Right = styled.div`
102102
align-items: center;
103103
position: relative;
104104
.write-button {
105-
${mediaQuery(376)} {
105+
${media.medium} {
106106
display: none;
107107
}
108108
}

src/components/write/PublishActionButtons.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import * as React from 'react';
22
import styled from 'styled-components';
33
import Button from '../common/Button';
4+
import media from '../../lib/styles/media';
45

56
const PublishActionButtonsBlock = styled.div`
67
display: flex;
78
justify-content: flex-end;
9+
${media.custom(767)} {
10+
margin-top: 2rem;
11+
}
812
`;
913

1014
export interface PublishActionButtonsProps {

src/components/write/PublishPrivacySetting.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,16 @@ const Button = styled.button<{ active: boolean }>`
4141
`}
4242
4343
svg {
44-
margin-right: 1.5rem;
4544
}
4645
& + & {
4746
margin-left: 1rem;
4847
}
48+
.description {
49+
flex: 1;
50+
display: flex;
51+
justify-content: center;
52+
align-items: center;
53+
}
4954
`;
5055

5156
export interface PublishPrivacySettingProps {
@@ -69,11 +74,11 @@ const PublishPrivacySetting: React.FC<PublishPrivacySettingProps> = ({
6974
<PublishPrivacySettingBlock title="공개 설정">
7075
<Button active={!isPrivate} onClick={onClickPublic}>
7176
<GlobeIcon />
72-
전체 공개
77+
<div className="description">전체 공개</div>
7378
</Button>
7479
<Button active={isPrivate} onClick={onClickPrivate}>
7580
<LockIcon />
76-
비공개
81+
<div className="description">비공개</div>
7782
</Button>
7883
</PublishPrivacySettingBlock>
7984
);

src/components/write/PublishScreenTemplate.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,29 @@ import palette from '../../lib/styles/palette';
44
import zIndexes from '../../lib/styles/zIndexes';
55
import transitions from '../../lib/styles/transitions';
66
import HideScroll from '../common/HideScroll';
7+
import media from '../../lib/styles/media';
78

89
const PublishScreenTemplateBlock = styled.div<{ visible: boolean }>`
910
display: flex;
1011
justify-content: center;
1112
align-items: center;
1213
position: fixed;
14+
@media (max-width: 1024px) and (orientation: landscape) {
15+
align-items: flex-start;
16+
padding-top: 2rem;
17+
padding-bottom: 2rem;
18+
overflow: auto;
19+
}
20+
21+
${media.custom(767)} {
22+
align-items: flex-start;
23+
padding-top: 2rem;
24+
padding-bottom: 2rem;
25+
overflow: auto;
26+
padding-left: 1rem;
27+
padding-right: 1rem;
28+
}
29+
1330
left: 0;
1431
top: 0;
1532
width: 100%;
@@ -30,6 +47,12 @@ const PublishScreenTemplateBlock = styled.div<{ visible: boolean }>`
3047
const Wrapper = styled.div`
3148
width: 768px;
3249
display: flex;
50+
${media.medium} {
51+
width: 704px;
52+
}
53+
${media.custom(767)} {
54+
flex-direction: column;
55+
}
3356
`;
3457
const Pane = styled.div`
3558
flex: 1;
@@ -46,6 +69,9 @@ const Separator = styled.div`
4669
background: ${palette.gray2};
4770
margin-left: 2rem;
4871
margin-right: 2rem;
72+
${media.custom(767)} {
73+
display: none;
74+
}
4975
`;
5076

5177
export interface PublishScreenTemplateProps {

src/components/write/TagInput.tsx

Lines changed: 104 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,8 @@ import * as React from 'react';
22
import styled, { css } from 'styled-components';
33
import palette from '../../lib/styles/palette';
44
import transitions from '../../lib/styles/transitions';
5-
6-
const TagInputBlock = styled.div`
7-
color: ${palette.gray8};
8-
font-size: 1.125rem;
9-
margin-bottom: 4rem;
10-
display: flex;
11-
flex-wrap: wrap;
12-
[contenteditable='true']:empty:before {
13-
content: attr(placeholder);
14-
display: block; /* For Firefox */
15-
color: ${palette.gray5};
16-
}
17-
`;
18-
const StyledInput = styled.input`
19-
display: inline-flex;
20-
outline: none;
21-
cursor: text;
22-
font-size: 1.125rem;
23-
line-height: 2rem;
24-
margin-bottom: 0.75rem;
25-
min-width: 8rem;
26-
border: none;
27-
`;
28-
29-
const Tag = styled.div`
30-
color: ${palette.gray9};
31-
font-size: 1rem;
32-
display: inline-flex;
33-
align-items: center;
34-
height: 2rem;
35-
border-radius: 1rem;
36-
padding-left: 1rem;
37-
padding-right: 1rem;
38-
background: ${palette.gray1};
39-
color: ${palette.teal7};
40-
margin-right: 0.75rem;
41-
transition: ease-in 0.125s;
42-
cursor: pointer;
43-
&:hover {
44-
opacity: 0.6;
45-
}
46-
margin-bottom: 0.75rem;
47-
animation: ${transitions.popIn} 0.125s forwards ease-in-out;
48-
`;
5+
import media, { mediaQuery } from '../../lib/styles/media';
6+
import { useTransition, animated } from 'react-spring';
497

508
export interface TagInputProps {
519
ref?: React.RefObject<HTMLDivElement>;
@@ -59,24 +17,6 @@ const TagItem: React.FC<{
5917
return <Tag onClick={onClick}>{children}</Tag>;
6018
};
6119

62-
const Help = styled.div<{ visible: boolean }>`
63-
display: block;
64-
width: 100%;
65-
font-size: 0.875rem;
66-
color: ${palette.gray7};
67-
transition: ease-in 0.125s;
68-
opacity: 0;
69-
& > .inside {
70-
margin-top: 0.5rem;
71-
position: absolute;
72-
}
73-
${props =>
74-
props.visible &&
75-
css`
76-
opacity: 1;
77-
`}
78-
`;
79-
8020
const { useState, useCallback, useEffect, useRef } = React;
8121
const TagInput: React.FC<TagInputProps> = ({ onChange, tags: initialTags }) => {
8222
const [tags, setTags] = useState<string[]>(initialTags);
@@ -170,15 +110,110 @@ const TagInput: React.FC<TagInputProps> = ({ onChange, tags: initialTags }) => {
170110
onFocus={() => setFocus(true)}
171111
onBlur={() => setFocus(false)}
172112
/>
173-
<Help visible={focus}>
174-
<div className="inside">
175-
쉼표 혹은 엔터를 입력하여 태그를 등록 할 수 있습니다.
176-
<br />
177-
등록된 태그를 클릭하면 삭제됩니다.
178-
</div>
179-
</Help>
113+
<Help focus={focus} />
180114
</TagInputBlock>
181115
);
182116
};
183117

118+
function Help({ focus }: { focus: boolean }) {
119+
const transitions = useTransition(focus, null, {
120+
from: { opacity: 0, transform: 'translateY(-1rem)' },
121+
enter: { opacity: 1, transform: 'translateY(0rem)' },
122+
leave: { opacity: 0, transform: 'translateY(-1rem)' },
123+
config: {
124+
tension: 350,
125+
friction: 22,
126+
},
127+
});
128+
129+
return (
130+
<HelpBlock>
131+
{transitions.map(({ item, key, props }) =>
132+
item ? (
133+
<animated.div className="inside" style={props} key={key}>
134+
쉼표 혹은 엔터를 입력하여 태그를 등록 할 수 있습니다.
135+
<br />
136+
등록된 태그를 클릭하면 삭제됩니다.
137+
</animated.div>
138+
) : null,
139+
)}
140+
</HelpBlock>
141+
);
142+
}
143+
144+
const HelpBlock = styled.div`
145+
display: block;
146+
width: 100%;
147+
148+
color: ${palette.gray7};
149+
transition: ease-in 0.125s;
150+
151+
& > .inside {
152+
position: absolute;
153+
background: ${palette.gray8};
154+
color: white;
155+
padding: 0.75rem;
156+
z-index: 20;
157+
line-height: 1.5;
158+
font-size: 0.75rem;
159+
}
160+
`;
161+
162+
const TagInputBlock = styled.div`
163+
color: ${palette.gray8};
164+
font-size: 1.125rem;
165+
166+
display: flex;
167+
flex-wrap: wrap;
168+
[contenteditable='true']:empty:before {
169+
content: attr(placeholder);
170+
display: block; /* For Firefox */
171+
color: ${palette.gray5};
172+
}
173+
`;
174+
const StyledInput = styled.input`
175+
display: inline-flex;
176+
outline: none;
177+
cursor: text;
178+
font-size: 1.125rem;
179+
line-height: 2rem;
180+
${mediaQuery(767)} {
181+
line-height: 1.5rem;
182+
font-size: 0.75rem;
183+
}
184+
margin-bottom: 0.75rem;
185+
min-width: 8rem;
186+
border: none;
187+
`;
188+
189+
const Tag = styled.div`
190+
color: ${palette.gray9};
191+
font-size: 1rem;
192+
display: inline-flex;
193+
align-items: center;
194+
height: 2rem;
195+
border-radius: 1rem;
196+
padding-left: 1rem;
197+
padding-right: 1rem;
198+
background: ${palette.gray1};
199+
color: ${palette.teal7};
200+
margin-right: 0.75rem;
201+
transition: ease-in 0.125s;
202+
cursor: pointer;
203+
&:hover {
204+
opacity: 0.6;
205+
}
206+
margin-bottom: 0.75rem;
207+
animation: ${transitions.popIn} 0.125s forwards ease-in-out;
208+
${mediaQuery(767)} {
209+
height: 1.5rem;
210+
font-size: 0.75rem;
211+
border-radius: 0.75rem;
212+
padding-left: 0.75rem;
213+
padding-right: 0.75rem;
214+
margin-right: 0.5rem;
215+
margin-bottom: 0.5rem;
216+
}
217+
`;
218+
184219
export default TagInput;

src/components/write/TitleTextarea.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import styled, { css } from 'styled-components';
22
import TextareaAutosize from 'react-textarea-autosize';
33
import palette from '../../lib/styles/palette';
4+
import { mediaQuery } from '../../lib/styles/media';
45

56
const style = css`
67
display: block;
78
padding: 0;
89
font-size: 2.75rem;
10+
${mediaQuery(767)} {
11+
font-size: 1.8rem;
12+
}
913
width: 100%;
1014
resize: none;
1115
line-height: 1.5;

0 commit comments

Comments
 (0)