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

chore(web): design beta navBar #486

Merged
merged 17 commits into from
Jun 13, 2023
11 changes: 11 additions & 0 deletions web/src/beta/components/Avatar/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Meta } from "@storybook/react";

import Avatar from ".";

export default {
title: "atoms/Avatar",
component: Avatar,
} as Meta;

export const Default = () => <Avatar innerText="ReEarth" />;
export const Large = () => <Avatar size="large" innerText="ReEarth" />;
58 changes: 58 additions & 0 deletions web/src/beta/components/Avatar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from "react";

import Flex from "@reearth/beta/components/Flex";
import Text from "@reearth/beta/components/Text";
import { styled, useTheme } from "@reearth/services/theme";

export type Size = "small" | "large";

export type Props = {
className?: string;
size?: Size;
color?: string;
avatar?: string;
innerText?: string | number;
boarderRadius?: string;
};

const Avatar: React.FC<Props> = ({
className,
size = "small",
color,
avatar,
innerText,
boarderRadius = "50%",
}) => {
const theme = useTheme();

return (
<StyledAvatar
className={className}
align="center"
justify="center"
size={size}
avatar={avatar}
color={color ?? theme.main.avatarBg}
boardeRradius={boarderRadius}>
{innerText && (
<Text size={"l"} color={theme.text.pale}>
{typeof innerText === "number" ? `+${innerText.toString()}` : innerText.charAt(0)}
</Text>
)}
</StyledAvatar>
);
};
const StyledAvatar = styled(Flex)<{
size?: Size;
avatar?: string;
color?: string;
boardeRradius?: string;
}>`
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
width: ${({ size }) => (size === "large" ? "64px" : "32px")};
height: ${({ size }) => (size === "large" ? "64px" : "32px")};
border-radius: ${({ boardeRradius }) => (boardeRradius ? boardeRradius : "50%")};
background: ${({ avatar, color }) => (avatar ? `url(${avatar});` : color)};
`;

export default Avatar;
23 changes: 23 additions & 0 deletions web/src/beta/components/Button/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Meta } from "@storybook/react";

import Button from ".";

export default {
title: "atoms/Buttons/Button",
component: Button,
} as Meta;

export const PrimarySmall = () => <Button buttonType="primary" text="Primary" />;
export const PrimaryLarge = () => <Button buttonType="primary" text="Primary" large />;
export const SecondarySmall = () => <Button buttonType="secondary" text="secondary" />;
export const SecondaryLarge = () => <Button buttonType="secondary" text="secondary" large />;
export const DangerSmall = () => <Button buttonType="danger" text="danger" />;
export const DangerLarge = () => <Button buttonType="danger" text="danger" large />;
export const Disabled = () => (
<Button buttonType="primary" text="disabled" icon="datasetAdd" disabled />
);

export const WithIcon = () => <Button buttonType="primary" text="Primary" icon="datasetAdd" />;
export const WithIconRight = () => (
<Button buttonType="secondary" text="secondary" icon="datasetAdd" iconRight />
);
163 changes: 163 additions & 0 deletions web/src/beta/components/Button/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import { ReactNode } from "react";

import Icon from "@reearth/beta/components/Icon";
import Text from "@reearth/beta/components/Text";
import { styled } from "@reearth/services/theme";
import { metricsSizes } from "@reearth/services/theme/metrics";

export type Type = "primary" | "secondary" | "danger";

export interface Props {
className?: string;
children?: ReactNode;
large?: boolean;
type?: "reset" | "button" | "submit" | undefined;
buttonType?: Type;
disabled?: boolean;
text?: string;
icon?: string;
iconRight?: boolean;
margin?: string;
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
onMouseEnter?: () => void;
onMouseLeave?: () => void;
}

const Button: React.FC<Props> = ({
className,
children,
large,
type,
buttonType,
disabled,
text,
icon,
iconRight,
margin,
onClick,
onMouseEnter,
onMouseLeave,
}) => {
const hasText = !!text || !!children;
const iSize = large ? "16px" : "12px";

const WrappedIcon = icon ? (
<IconWrapper text={hasText} iconRight={iconRight} large={large}>
<Icon icon={icon} size={iSize} notransition />
</IconWrapper>
) : null;

return (
<StyledButton
className={className}
large={large}
type={type}
buttonType={buttonType}
text={hasText}
disabled={disabled}
margin={margin}
onClick={onClick}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}>
{!iconRight && WrappedIcon}
{large ? (
<Text size="m" weight="bold" customColor>
{text}
</Text>
) : (
<Text size="xs" customColor>
{text}
</Text>
)}
{children}
{iconRight && WrappedIcon}
</StyledButton>
);
};

type ButtonProps = {
large?: boolean;
buttonType?: Type;
text?: boolean;
disabled?: boolean;
margin?: string;
};

const StyledButton = styled.button<ButtonProps>`
border-radius: ${({ large }) => (large ? "8px" : "6px")};
border-style: solid;
border-width: 1px;
border-color: ${({ buttonType, disabled, theme }) =>
buttonType === "danger"
? disabled
? theme.buttonDanger.disabled
: theme.buttonDanger.color
: buttonType === "secondary"
? disabled
? theme.buttonSecondary.disabled
: theme.buttonSecondary.color
: disabled
? theme.buttonPrimary.disabled
: theme.buttonPrimary.color};
background: inherit;
color: ${({ buttonType, disabled, theme }) =>
buttonType === "danger"
? disabled
? theme.buttonDanger.disabled
: theme.buttonDanger.color
: buttonType === "secondary"
? disabled
? theme.buttonSecondary.disabled
: theme.buttonSecondary.color
: disabled
? theme.buttonPrimary.disabled
: theme.buttonPrimary.color};
padding: ${({ large }) =>
large
? `${metricsSizes["s"]}px ${metricsSizes["2xl"]}px`
: `${metricsSizes["xs"]}px ${metricsSizes["xl"]}px`};
margin: ${({ margin }) => margin || `${metricsSizes["m"]}px`};
user-select: none;
cursor: ${({ disabled }) => (disabled ? "not-allowed" : "pointer")};
justify-content: center;
align-items: center;
display: flex;
align-items: center;
transition-property: color, background;
transition-duration: 0.4s;

&:hover {
background: ${({ buttonType, disabled, theme }) =>
disabled
? "inherit"
: buttonType === "danger"
? theme.buttonDanger.bgHover
: buttonType === "secondary"
? theme.buttonSecondary.bgHover
: theme.buttonPrimary.bgHover};
color: ${({ buttonType, disabled, theme }) =>
buttonType === "danger"
? disabled
? theme.buttonDanger.disabled
: theme.buttonDanger.colorHover
: buttonType === "secondary"
? disabled
? theme.buttonSecondary.disabled
: theme.buttonSecondary.colorHover
: disabled
? theme.buttonPrimary.disabled
: theme.buttonPrimary.colorHover};
}
`;

const IconWrapper = styled.span<{ text: boolean; iconRight?: boolean; large?: boolean }>`
display: inline-flex;
align-items: center;
user-select: none;
margin-left: ${({ text, iconRight, large }) =>
text && iconRight ? (large ? "12px" : "8px") : "none"};
margin-right: ${({ text, iconRight, large }) =>
text && !iconRight ? (large ? "12px" : "8px") : "none"};
`;

export default Button;
37 changes: 37 additions & 0 deletions web/src/beta/components/Dropdown/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Meta } from "@storybook/react";
import { ReactNode } from "react";

import Dropdown from ".";

const Wrapper: React.FC<{ children: ReactNode }> = ({ children }) => (
<div style={{ width: "100px", height: "60px" }}>{children}</div>
);

export default {
title: "atoms/Dropdown",
component: Dropdown,
} as Meta;

export const Default = () => (
<Wrapper>
<Dropdown isOpen label="Sample">
<ul>
<li>Apple</li>
<li>Banana</li>
<li>Orange</li>
</ul>
</Dropdown>
</Wrapper>
);

export const DirectionRight = () => (
<Wrapper>
<Dropdown isOpen label="Sample" direction="right">
<ul>
<li>Apple</li>
<li>Banana</li>
<li>Orange</li>
</ul>
</Dropdown>
</Wrapper>
);
Loading