Skip to content

Commit

Permalink
feat(wip): 偏見作成フォームの仮デザイン途中 (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
SnO2WMaN authored Oct 16, 2021
1 parent d7d13f1 commit 9cfce14
Show file tree
Hide file tree
Showing 40 changed files with 1,270 additions and 12 deletions.
5 changes: 1 addition & 4 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import * as nextImage from "next/image";

import TypesafeI18n from "~/i18n/i18n-react";

import {
INITIAL_VIEWPORTS,
MINIMAL_VIEWPORTS,
} from "@storybook/addon-viewport";
import { INITIAL_VIEWPORTS, MINIMAL_VIEWPORTS } from "@storybook/addon-viewport";
import "~/styles/index.css";
import { TAILWIND_VIEWPORTS } from "./tailwindViewports";

Expand Down
6 changes: 4 additions & 2 deletions dprint.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
"incremental": true,
"typescript": {
"lineWidth": 80,
"lineWidth": 120,
"semiColons": "always",
"indentWidth": 2,
"quoteStyle": "alwaysDouble"
"quoteStyle": "alwaysDouble",
"operatorPosition": "sameLine",
"conditionalExpression.operatorPosition": "nextLine"
},
"json": {},
"markdown": {},
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"react-dom": "17.0.2",
"react-hook-form": "7.15.4",
"react-use": "17.3.1",
"recoil": "^0.4.1",
"styled-components": "5.3.1",
"typesafe-i18n": "2.40.1",
"urql": "2.0.5"
Expand Down
Binary file added public/.mock/avatar_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/.mock/avatar_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/.mock/avatar_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/.mock/avatar_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/.mock/avatar_6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions src/auth/useViewer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { atom, useRecoilValue, useSetRecoilState } from "recoil";

export type Viewer = { id: string; alias: string; displayName: string; avatar: string; };

export const viewerState = atom<undefined | null | Viewer>({
key: "viewer",
default: undefined,
});

export const useViewer = (): Viewer | null | undefined => {
const viewer = useRecoilValue(viewerState);
return viewer;
};

export const useUpdateViewer = () => {
const setter = useSetRecoilState(viewerState);
return (viewer: Viewer) => setter(viewer);
};
28 changes: 28 additions & 0 deletions src/components/atoms/Avatar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import clsx from "clsx";
import React from "react";

import { Image } from "~/components/atoms/Image";

export const AvatarSmall: React.VFC<{
user: { alias: string; avatar: string; };
}> = ({ user: { alias, avatar } }) => (
<Image
className={clsx(["rounded-full"])}
width={96}
height={96}
src={avatar}
alt={alias}
/>
);

export const AvatarLarge: React.VFC<{
user: { alias: string; avatar: string; };
}> = ({ user: { alias, avatar } }) => (
<Image
className={clsx(["rounded-full"])}
width={256}
height={256}
src={avatar}
alt={alias}
/>
);
11 changes: 11 additions & 0 deletions src/components/atoms/Icon/icons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { solid } from "@fortawesome/fontawesome-svg-core/import.macro";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React from "react";

export const IconLoading = (props) => <FontAwesomeIcon fixedWidth icon={solid("circle-notch")} spin {...props} />;

export const IconUnknownUser = (props) => <FontAwesomeIcon fixedWidth icon={solid("question")} {...props} />;

export const IconNoSuggestion = (props) => <FontAwesomeIcon fixedWidth icon={solid("circle-question")} {...props} />;

export const IconNoImage = (props) => <FontAwesomeIcon fixedWidth icon={solid("image")} {...props} />;
5 changes: 5 additions & 0 deletions src/components/atoms/Icon/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from "react";

export * from "./icons";

export type IconType = React.VFC<{ className?: string; }>;
3 changes: 3 additions & 0 deletions src/components/atoms/Image/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import NextImage from "next/image";

export const Image = NextImage;
25 changes: 25 additions & 0 deletions src/components/organisms/CreateHenkenForm/Content/Info.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Meta, Story } from "@storybook/react";
import React, { ComponentProps } from "react";

import { Component } from "./Info";

export default {
title: "CreateHenkenForm/Content/Info",
component: Component,
argTypes: {},
} as Meta;

type StoryProps = ComponentProps<typeof Component>;

export const HasImage: Story<StoryProps> = ({ ...props }) => {
return <Component {...props} />;
};
HasImage.args = {
title: "タイトル",
image: "/.mock/bookcover_1.jpg",
};

export const NoImage: Story<StoryProps> = ({ ...props }) => {
return <Component {...props} />;
};
NoImage.args = { title: "タイトル" };
55 changes: 55 additions & 0 deletions src/components/organisms/CreateHenkenForm/Content/Info.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import clsx from "clsx";
import React from "react";

import { IconNoImage } from "~/components/atoms/Icon";
import { Image } from "~/components/atoms/Image";
import { useTranslation } from "~/i18n/useTranslation";

export const Component: React.VFC<{
title: string;
image: string | null;
}> = ({ title, image }) => {
const { LL } = useTranslation();
return (
<div className={clsx(["h-64"], ["inline-flex", ["flex-col"], ["items-center"]])}>
<div className={clsx(["h-48"], ["flex", ["justify-center"]])}>
{image && <Image src={image} layout="fill" objectFit="contain" />}
{!image && (
<div
className={clsx(
["w-full"],
["h-full"],
["flex", ["flex-col"], ["justify-center"], ["items-center"]],
)}
>
<IconNoImage />
<span className={clsx(["text-sm"])}>{LL.CreateHenkenForm.Content.Info.NoImage()}</span>
</div>
)}
</div>
<div className={clsx(["w-full"], ["flex-grow"], ["mt-2"])}>
<span className={clsx([["text-lg"]])}>{title}</span>
</div>
</div>
);
};

export const Info: React.VFC<{
className?: string;
content:
| { type: "book"; value: { id: string; title: string; cover: string; }; }
| { type: "bookseries"; value: { id: string; title: string; }; }
| { type: "author"; value: { id: string; name: string; }; };
}> = ({
content,
...props
}) => {
switch (content.type) {
case "author":
return <Component {...props} title={content.value.name} image={null} />;
case "book":
return <Component {...props} title={content.value.title} image={content.value.cover} />;
case "bookseries":
return <Component {...props} title={content.value.title} image={null} />;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import clsx from "clsx";
import React from "react";

import { IconNoSuggestion } from "~/components/atoms/Icon";
import { useTranslation } from "~/i18n/useTranslation";

export const NoResult: React.VFC<{ className?: string; }> = ({ className }) => {
const { LL } = useTranslation();
return (
<div
className={clsx(className, [["px-6"], ["py-4"]], ["flex", ["flex-col"], ["items-center"]])}
>
<IconNoSuggestion
className={clsx([["text-2xl"], ["text-blue-300"]])}
/>
<span className={clsx(["mt-4"], ["text-xs"])}>{LL.CreateHenkenForm.Content.SearchBox.NoResult()}</span>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import clsx from "clsx";
import React from "react";

export const ComponentForBook: React.VFC<
{
className?: string;
title: string;
onSelect(): void;
}
> = ({ className, title, onSelect }) => {
return (
<div
onClick={() => onSelect()}
onKeyPress={() => onSelect()}
className={clsx(
className,
[["px-4"], ["py-2"]],
["flex", ["items-center"]],
["bg-white", "hover:bg-blue-50"],
)}
>
{title}
</div>
);
};

export const Suggestion: React.VFC<
{
className?: string;
content: (
| { type: "book"; value: { id: string; title: string; cover: string; }; }
| { type: "bookseries"; value: { id: string; title: string; }; }
| { type: "author"; value: { id: string; name: string; }; }
);
onSelect(
value:
| { type: "book"; value: { id: string; title: string; cover: string; }; }
| { type: "bookseries"; value: { id: string; title: string; }; }
| { type: "author"; value: { id: string; name: string; }; },
): void;
}
> = ({ className, content, onSelect }) => {
return (
<div
onClick={() => onSelect(content)}
onKeyPress={() => onSelect(content)}
className={clsx(
className,
[["px-4"], ["py-2"]],
["flex", ["items-center"]],
["bg-white", "hover:bg-blue-50"],
)}
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import clsx from "clsx";
import React from "react";

import { NoResult } from "./NoResult";
import { Suggestion } from "./Suggestions";

import { useTranslation } from "~/i18n/useTranslation";

export const Component: React.VFC<
{
className?: string;
suggestions: (
| { type: "book"; value: { id: string; title: string; cover: string; }; }
| { type: "bookseries"; value: { id: string; title: string; }; }
| { type: "author"; value: { id: string; name: string; }; }
)[];
onSelect(
value:
| { type: "book"; value: { id: string; title: string; cover: string; }; }
| { type: "bookseries"; value: { id: string; title: string; }; }
| { type: "author"; value: { id: string; name: string; }; },
): void;
}
> = ({ className, suggestions, onSelect, ...props }) => {
const { LL } = useTranslation();
return (
<div
className={clsx(
className,
[["inline-flex"], ["flex-col"]],
["bg-white"],
["divide-y", ["divide-gray-100"]],
)}
>
{suggestions.length > 0 &&
suggestions.map((content) => <Suggestion key={content.value.id} content={content} onSelect={onSelect} />)}
{suggestions.length === 0 &&
<NoResult className={clsx(["w-full"])} />}
</div>
);
};

export const Suggestions: React.VFC<
{
className?: string;
suggestions: (
| { type: "book"; value: { id: string; title: string; cover: string; }; }
| { type: "bookseries"; value: { id: string; title: string; }; }
| { type: "author"; value: { id: string; name: string; }; }
)[];
onSelect(
value:
| { type: "book"; value: { id: string; title: string; cover: string; }; }
| { type: "bookseries"; value: { id: string; title: string; }; }
| { type: "author"; value: { id: string; name: string; }; },
): void;
}
> = ({ ...props }) => {
return <Component {...props} />;
};
Loading

0 comments on commit 9cfce14

Please sign in to comment.