Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: handy typo 적용 #119

Merged
merged 10 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .storybook/preview-head.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<link
href="//spoqa.github.io/spoqa-han-sans/css/SpoqaHanSansNeo.css"
rel="stylesheet"
type="text/css"
as="style"
crossorigin
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css"
/>
126 changes: 98 additions & 28 deletions src/style/foundation/typo/Typo.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from 'react';
import React, { useState } from 'react';

import { Primary as PrimaryBlock, Controls, Markdown } from '@storybook/blocks';
import { Meta, StoryObj } from '@storybook/react';
import { styled } from 'styled-components';

import TypoDocs from './TypoDocs.md?raw';

import { typos, Typo } from '.';
import { typos, TypoType } from '.';

const meta: Meta = {
title: 'Foundation/Typos',
Expand All @@ -24,46 +24,116 @@ const meta: Meta = {
};
export default meta;

const TypoRow = styled.div`
display: flex;
height: 64px;
align-items: center;
const extractTypoDetails = (typoStyles: string) => {
const lines = typoStyles.replace(/\s/g, '').split(';');
const fontSizeLine = lines.find((line: string) => line.includes('font-size:'));
const lineHeightLine = lines.find((line: string) => line.includes('line-height:'));
const letterSpacingLine = lines.find((line: string) => line.includes('letter-spacing:'));

const fontSize = fontSizeLine?.match(/font-size:(\d+)px/)?.[1];
const lineHeight = lineHeightLine?.match(/line-height:(\d+)px/)?.[1];
const letterSpacing = letterSpacingLine?.match(/letter-spacing:(-?[0-9]+(\.[0-9]+)*)/)?.[1];

return [fontSize, lineHeight, letterSpacing];
};

const TypoGrid = styled.div`
display: grid;
grid-template-columns: 160px minmax(520px, 1fr) 60px 60px 60px;
gap: 20px;
margin-bottom: 80px;
`;

const TypoExample = styled.div<{ $typo: Typo }>`
const TypoName = styled.div`
align-self: center;
`;

const TypoOptionValue = styled.div`
justify-self: center;
align-self: center;
`;

const TypoExample = styled.div<{ $typo: TypoType }>`
white-space: normal;
line-break: anywhere;
${(props) => props.theme.typo[props.$typo]};
`;

const TypoName = styled.div`
${(props) => props.theme.typo.caption0};
color: ${(props) => props.theme.color.textPrimary};
width: 120px;
const TypoHeader = styled.header`
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 48px;
`;

const extractTypoDetails = (typoStyles: string) => {
const lines = typoStyles.replace(/\s/g, '').split(';');
return lines.filter(
(line: string) =>
line.includes('font-size:') || line.includes('font-weight:') || line.includes('line-height:')
const TypoGridTitle = styled.div`
font-weight: 500;
font-size: 22px;
`;

const TypoPreviewInput = styled.input`
all: unset;
max-width: 700px;
width: 100%;

border: 1px solid #d2d0d2;
border-radius: 9999px;
padding: 20px 28px;

&:focus {
border-color: #222022;
}
`;

const TypoGridHead = () => {
return (
<>
<div>이름</div>
<div>미리보기</div>
<div>
크기<small>(px)</small>
</div>
<div>
행간<small>(px)</small>
</div>
<div>
자간<small>(em)</small>
</div>
</>
);
};

const TypoStory = () => {
const [preview, setPreivew] = useState('나무잎새남실');

const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setPreivew(e.target.value);
};

return (
<>
{Object.entries(typos).map(([typo, styleText]) => (
<TypoRow key={typo}>
<TypoName>
{extractTypoDetails(styleText).map((line) => (
<React.Fragment key={typo + line}>
{line}
<br />
</React.Fragment>
<TypoHeader>
<TypoGridTitle>타이포그래피</TypoGridTitle>
<div>
<TypoPreviewInput
placeholder="텍스트를 입력해주세요..."
value={preview}
onChange={onChange}
/>
</div>
</TypoHeader>
<TypoGrid>
<TypoGridHead />
{Object.entries(typos).map(([typo, typoStyles]) => (
<React.Fragment key={typo}>
<TypoName>{typo}</TypoName>
<TypoExample $typo={typo as TypoType}>{preview}</TypoExample>
{extractTypoDetails(typoStyles).map((detail, index) => (
<TypoOptionValue key={index}>{detail}</TypoOptionValue>
))}
</TypoName>
<TypoExample $typo={typo as Typo}>{typo}</TypoExample>
</TypoRow>
))}
</React.Fragment>
))}
</TypoGrid>
</>
);
};
Expand Down
38 changes: 35 additions & 3 deletions src/style/foundation/typo/TypoDocs.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,44 @@
# Typos

YDS Typo는 YDS에서 사용하는 타이포그래피 스타일입니다.<br/>
Handy Typography는 Handy에서 사용하는 타이포그래피 스타일입니다.

- 폰트는 **Pretendard**를 사용합니다. 단, 필기체와 같은 브랜딩 폰트는 가이드에서 벗어나 자유롭게 사용 가능합니다.
- 폰트의 **한글과 영문을 잘 구분**해서 사용합니다.
- 굵기는 Light(300), Regular(400), Semibold(600) 만 사용합니다.
- subset 파일을 사용하므로, 지원하지 않는 글자에 대해 유의해주세요.

<br />

또한, 타이포그래피의 이름은 아래의 규칙을 따릅니다.

> <이름>\_<한글or영문>\_<굵기>\_<크기>

<br />

모든 타이포그래피 스타일은 아래에서 확인할 수 있습니다.

```typescript
<br />

## 한글 타이포그래피 사용법

```ts
import { styled } from 'styled-components';

const StyledDiv = styled.div`
${({ theme }) => theme.typo.body1};
${({ theme }) => theme.typo.kr.D1_EN_Sb_96};
`;
```

<br />

## 영문 타이포그래피 사용법

```ts
import { styled } from 'styled-components';

const StyledDiv = styled.div`
${({ theme }) => theme.typo.en.D1_EN_Sb_96};
`;
```

## 미리보기
3 changes: 2 additions & 1 deletion src/style/foundation/typo/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export type { FontWeight, Typo } from './typo.type';
export type { FontWeight, TypoType } from './typo.type';
export type { Typos } from './typo';
export { typos, fontWeights } from './typo';
Loading