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

Imple heading component #15

Merged
merged 14 commits into from
Apr 19, 2024
Merged
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
build

7,173 changes: 2,471 additions & 4,702 deletions package-lock.json

Large diffs are not rendered by default.

201 changes: 201 additions & 0 deletions src/components/Heading/Heading.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
.heading {
font-weight: bold;
box-sizing: border-box;
color: var(--color-text-main);
position: relative;

--medium-leading-border-width: 4px;
--large-leading-border-width: 5px;
}

:where(.heading) {
margin: 0;
}

.heading.left {
text-align: left;
}

.heading.center {
text-align: center;
}

.heading.right {
text-align: right;
}

.heading.secondary {
color: var(--color-text-main);
}

.heading.primary {
color: var(--color-primary);
}

.heading > a {
color: var(--color-text-link);
}

@media (hover: hover) {
.heading > a:hover {
color: var(--color-primary-darken);
}
}

.heading > a:active {
text-decoration: none;
}

.heading.accent,
.heading.accent > a {
color: var(--color-accent);
}

@media (hover: hover) {
.heading.accent > a:hover {
color: var(--color-accent-darken);
}
}

.heading.white {
color: var(--color-text-white);
}

.heading.white,
.heading.white > a {
color: var(--color-text-white);
}

@media (hover: hover) {
.heading.white > a:hover {
text-decoration: none;
}
}

.heading.white > a:active {
position: relative;
top: 1px;
text-decoration: underline;
}

.heading.xs {
font-size: var(--text-heading-xs-size);
line-height: var(--text-heading-xs-line);
}

.heading.sm {
font-size: var(--text-heading-sm-size);
line-height: var(--text-heading-sm-line);
}

.heading.md {
font-size: var(--text-heading-md-size);
line-height: var(--text-heading-md-line);
}

.heading.lg {
font-size: var(--text-heading-lg-size);
line-height: var(--text-heading-lg-line);
}

.heading.xl {
font-size: var(--text-heading-xl-size);
line-height: var(--text-heading-xl-line);
}

.heading.leadingBorder {
padding-left: calc(var(--size-spacing-sm) + var(--medium-leading-border-width));
}

.heading.leadingBorder::before {
position: absolute;
display: block;
top: 0;
left: 0;
content: '';
width: var(--medium-leading-border-width);
border-radius: 3px;
background-color: var(--color-primary);
vertical-align: top;
height: 100%;
}

.heading.lg.leadingBorder,
.heading.xl.leadingBorder {
padding-left: calc(var(--size-spacing-sm) + var(--large-leading-border-width));
}

.heading.lg.leadingBorder::before,
.heading.xl.leadingBorder::before {
width: var(--large-leading-border-width);
}

.icon {
position: absolute;
top: 0;
left: 0;
display: inline-block;
}

.icon.primary {
color: var(--color-primary);
}

.icon.accent {
color: var(--color-accent);
}

.icon.white {
color: var(--color-text-white);
}

.icon > svg {
vertical-align: baseline;
width: 100%;
height: 100%;
}

.heading.xs.hasIcon {
padding-left: calc(var(--text-heading-xs-size) * var(--text-heading-xs-line) + 0.5em);
}

.heading.sm.hasIcon {
padding-left: calc(var(--text-heading-sm-size) * var(--text-heading-sm-line) + 0.5em);
}

.heading.md.hasIcon {
padding-left: calc(var(--text-heading-md-size) * var(--text-heading-md-line) + 0.5em);
}

.heading.lg.hasIcon {
padding-left: calc(var(--text-heading-lg-size) * var(--text-heading-lg-line) + 0.5em);
}

.heading.xl.hasIcon {
padding-left: calc(var(--text-heading-xl-size) * var(--text-heading-xl-line) + 0.5em);
}

.heading.xs > .icon {
width: calc(var(--text-heading-xs-size) * var(--text-heading-xs-line));
height: calc(var(--text-heading-xs-size) * var(--text-heading-xs-line));
}

.heading.sm > .icon {
width: calc(var(--text-heading-sm-size) * var(--text-heading-sm-line));
height: calc(var(--text-heading-sm-size) * var(--text-heading-sm-line));
}

.heading.md > .icon {
width: calc(var(--text-heading-md-size) * var(--text-heading-md-line));
height: calc(var(--text-heading-md-size) * var(--text-heading-md-line));
}

.heading.lg > .icon {
width: calc(var(--text-heading-lg-size) * var(--text-heading-lg-line));
height: calc(var(--text-heading-lg-size) * var(--text-heading-lg-line));
}

.heading.xl > .icon {
width: calc(var(--text-heading-xl-size) * var(--text-heading-xl-line));
height: calc(var(--text-heading-xl-size) * var(--text-heading-xl-line));
}
100 changes: 100 additions & 0 deletions src/components/Heading/Heading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { clsx } from 'clsx';
import styles from './Heading.module.css';
import { HTMLTagname } from '../../utils/types';
import type { FC, PropsWithChildren, ReactNode } from 'react';

type Props = {
/**
* テキストの配置
* @default left
*/
textAlign?: 'left' | 'center' | 'right';
/**
* アイコン。プライマラーカラーで表示。icon propはどれかひとつのみを指定してください
*/
primaryIcon?: ReactNode;
/**
* アイコン。アクセントカラーで表示。icon propはどれかひとつのみを指定してください
*/
accentIcon?: ReactNode;
/**
* アイコン。ホワイトカラーで表示。icon propはどれかひとつのみを指定してください
*/
whiteIcon?: ReactNode;
/**
* サイズ。Typographyトークンの値を指定
* @default md
*/
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
/**
* 行の先頭にボーダーを表示
* @default false
*/
leadingBorder?: boolean;
/**
* レンダリングされるHTML要素
* @default p
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 4/19

I have dared to use the p element as the default.
I think it would be less problematic if it were a p element rather than specifying the wrong heading element.

*/
as: HTMLTagname;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 4/19

Element constraints removed

/**
* テキストのカラーバリエーション
* @default secondary
*/
variant?: 'primary' | 'secondary' | 'accent' | 'white';
/**
* HTMLのID属性
*/
id?: string;
/**
* HTMLのfor属性。label要素の場合に使用
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 4/19

I checked the product and found a comment asking for a label with the look and feel of a heading.

*/
htmlFor?: string;
};

const Heading: FC<PropsWithChildren<Props>> = ({
textAlign = 'left',
children,
primaryIcon,
accentIcon,
whiteIcon,
size = 'md',
variant = 'secondary',
leadingBorder,
as: HeadingComponent = 'p',
id,
htmlFor,
}) => {
const className = clsx(
styles.heading,
primaryIcon || accentIcon || whiteIcon ? styles.hasIcon : null,
styles[textAlign],
styles[size],
leadingBorder ? styles.secondary : styles[variant],
leadingBorder ? styles.leadingBorder : null,
);

return (
<HeadingComponent className={className} id={id} htmlFor={htmlFor}>
{primaryIcon && (
<span aria-hidden className={clsx(styles.icon, styles.primary)}>
{primaryIcon}
</span>
)}
{accentIcon && (
<span aria-hidden className={clsx(styles.icon, styles.accent)}>
{accentIcon}
</span>
)}
{whiteIcon && (
<span aria-hidden className={clsx(styles.icon, styles.white)}>
{whiteIcon}
</span>
)}
{children}
</HeadingComponent>
);
};

Heading.displayName = 'Heading';

export { Heading };
2 changes: 1 addition & 1 deletion src/components/RadioButton/RadioButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const RadioButton: FC<Props> = ({
...otherProps
}) => {
return (
<div className={clsx(styles.container, styles[size])}>
<div className={clsx(styles[size])}>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.container was gone.

<label className={styles.label}>
<input
type="radio"
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { ActionModal } from './components/ActionModal/ActionModal';
export { Box } from './components/Box/Box';
export { Button } from './components/Button/Button';
export { Center } from './components/Center/Center';
export { Heading } from './components/Heading/Heading';
export { LinkButton } from './components/Button/LinkButton';
export { ErrorMessage } from './components/ErrorMessage/ErrorMessage';
export { Flex } from './components/Flex/Flex';
Expand Down
Loading