Rewrite landing part
This commit is contained in:
parent
42d6da841f
commit
5646769e12
@ -1,10 +0,0 @@
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import Button from "./Button";
|
||||
|
||||
storiesOf("Button", module).add("with text", () => {
|
||||
return <Button text="Hello World" />;
|
||||
});
|
||||
|
||||
storiesOf("Button", module).add("with emoji", () => {
|
||||
return <Button text="😀 😎 👍 💯" />;
|
||||
});
|
@ -1,7 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
type Props = {
|
||||
text: string;
|
||||
};
|
||||
|
||||
export default ({ text }: Props) => <button className={'border rounded'}>{text}</button>;
|
14
components/Footer.tsx
Normal file
14
components/Footer.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import * as React from 'react';
|
||||
|
||||
type Props = {};
|
||||
|
||||
export default ({}: Props) => (
|
||||
<footer className="footer relative pt-1 border-t-2 border-blue-300">
|
||||
<div className="container mx-auto px-6">
|
||||
<h6 className="text-center text-gray-500">
|
||||
© 2020. Aleksandr Mihailov.{' '}
|
||||
<a href="http://creativecommons.org/licenses/by/3.0/">Some Rights Reserved</a>.
|
||||
</h6>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
10
components/atom/Button.stories.tsx
Normal file
10
components/atom/Button.stories.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import Button from './Button';
|
||||
|
||||
storiesOf('Design System/Atoms/Button', module).add('with text', () => {
|
||||
return <Button text="Hello World" />;
|
||||
});
|
||||
|
||||
storiesOf('Design System/Atoms/Button', module).add('with emoji', () => {
|
||||
return <Button text="😀 😎 👍 💯" />;
|
||||
});
|
11
components/atom/Button.tsx
Normal file
11
components/atom/Button.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import * as React from 'react';
|
||||
|
||||
type Props = {
|
||||
text: string;
|
||||
};
|
||||
|
||||
export default ({ text }: Props) => (
|
||||
<button className={'bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded'}>
|
||||
{text}
|
||||
</button>
|
||||
);
|
6
components/personal-card/PersonalCard.stories.tsx
Normal file
6
components/personal-card/PersonalCard.stories.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import PersonalCard from './PersonalCard';
|
||||
|
||||
storiesOf('Components/Personal Card', module).add('with emoji', () => {
|
||||
return <PersonalCard />;
|
||||
});
|
16
components/personal-card/PersonalCard.tsx
Normal file
16
components/personal-card/PersonalCard.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import * as React from 'react';
|
||||
import Avatar from './elements/Avatar';
|
||||
import Contacts from './elements/Contacts';
|
||||
import Description from './elements/Description';
|
||||
import Title from './elements/Title';
|
||||
|
||||
type Props = {};
|
||||
|
||||
export default ({}: Props) => (
|
||||
<div className={'flex flex-col sm mx-auto lg:w-1/3 '}>
|
||||
<Avatar imgUrl="./avatar.jpg" />
|
||||
<Title />
|
||||
<Description />
|
||||
<Contacts />
|
||||
</div>
|
||||
);
|
9
components/personal-card/elements/Avatar.tsx
Normal file
9
components/personal-card/elements/Avatar.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import * as React from 'react';
|
||||
|
||||
type Props = {
|
||||
imgUrl: string;
|
||||
};
|
||||
|
||||
export default ({ imgUrl }: Props) => (
|
||||
<img src={imgUrl} className={'border rounded-full h-48 sm mx-auto'}></img>
|
||||
);
|
30
components/personal-card/elements/Contacts.tsx
Normal file
30
components/personal-card/elements/Contacts.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import * as React from 'react';
|
||||
import { Contact, ContactType } from '../../../src/contacts/contacts';
|
||||
|
||||
import ContactsButtons from './ContactsButtons';
|
||||
|
||||
type Props = {};
|
||||
const contactMe: Contact[] = [
|
||||
{ id: 'fido_node', type: 'tg' },
|
||||
{ id: 'aleksandr.mihailov@pm.me', type: 'mail' }
|
||||
];
|
||||
|
||||
const socialButtons: Contact[] = [
|
||||
{ id: 'fido_node', type: 'twitter' },
|
||||
{ id: 'michey', type: 'github' },
|
||||
{ id: 'alex-mihailov-870448187', type: 'linkedin' },
|
||||
{ id: 'fido_node', type: 'twitch' }
|
||||
];
|
||||
|
||||
export default ({}: Props) => (
|
||||
<>
|
||||
<div className={'flex flex-col flex-row-2 '}>
|
||||
<span className={'text-2xl text-center py-4'}>Contact me via: </span>
|
||||
<ContactsButtons contacts={contactMe} />
|
||||
</div>
|
||||
<div className={'flex flex-col flex-row-2'}>
|
||||
<span className={'text-2xl text-center py-4'}>Social buttons: </span>
|
||||
<ContactsButtons contacts={socialButtons} />
|
||||
</div>
|
||||
</>
|
||||
);
|
43
components/personal-card/elements/ContactsButtons.tsx
Normal file
43
components/personal-card/elements/ContactsButtons.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import * as React from 'react';
|
||||
import '@fortawesome/fontawesome-svg-core';
|
||||
import { faEnvelope } from '@fortawesome/free-solid-svg-icons';
|
||||
import {
|
||||
faTelegram,
|
||||
faTwitter,
|
||||
faGithub,
|
||||
faLinkedin,
|
||||
faTwitch
|
||||
} from '@fortawesome/free-brands-svg-icons';
|
||||
|
||||
import { IconDefinition, IconName, IconPrefix } from '@fortawesome/fontawesome-svg-core';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Contact, contactToLink, ContactType } from '../../../src/contacts/contacts';
|
||||
|
||||
type Props = {
|
||||
contacts: Contact[];
|
||||
};
|
||||
|
||||
const typeToIcon: { [key in ContactType]: [IconDefinition, string?] } = {
|
||||
tg: [faTelegram],
|
||||
mail: [faEnvelope],
|
||||
twitter: [faTwitter],
|
||||
github: [faGithub],
|
||||
linkedin: [faLinkedin],
|
||||
twitch: [faTwitch]
|
||||
};
|
||||
|
||||
const ContactComp = ({ id, type }: Contact) => {
|
||||
const iconDescr = typeToIcon[type];
|
||||
return (
|
||||
<a
|
||||
className={'text-5xl p-3 text-gray-600' + ' ' + iconDescr[1]}
|
||||
href={contactToLink({ id, type })}
|
||||
target="_blank">
|
||||
<FontAwesomeIcon key={type} icon={iconDescr[0]} />
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
export default ({ contacts }: Props) => (
|
||||
<div className={'text-center'}>{contacts.map((c) => ContactComp(c))}</div>
|
||||
);
|
21
components/personal-card/elements/Description.tsx
Normal file
21
components/personal-card/elements/Description.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import * as React from 'react';
|
||||
import Link from './Link';
|
||||
|
||||
type Props = {};
|
||||
|
||||
export default ({}: Props) => (
|
||||
<div className={'flex flex-col flex-row-2'}>
|
||||
<span className={'text-2xl text-center'}>Full stack engineer</span>
|
||||
<span className={'text-2xl text-center'}>
|
||||
FP-curious | λ-affected Wanna be rustacean 🦀 and/or secops guy 🔒
|
||||
</span>
|
||||
<span className={'text-lg text-center text-gray-500 font-light'}>
|
||||
Now <Link href="https://www.samsungnext.com/">@SamsungNEXT</Link> (
|
||||
<Link href="https://whisk.com/">Whisk product team</Link>). Previously{' '}
|
||||
<Link href="https://www.visualthreat.com/">@VisualThreat.</Link>
|
||||
</span>
|
||||
<span className={'text-lg text-center text-gray-500 font-light'}>
|
||||
Work with: Scala, TypeScript, Java, MongoDB, MySQL, Thrift, gRPC
|
||||
</span>
|
||||
</div>
|
||||
);
|
12
components/personal-card/elements/Link.tsx
Normal file
12
components/personal-card/elements/Link.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
import * as React from 'react';
|
||||
|
||||
type Props = {
|
||||
href: string;
|
||||
children: string;
|
||||
};
|
||||
|
||||
export default ({ href, children }: Props) => (
|
||||
<a className={'underline'} href={href}>
|
||||
{children}
|
||||
</a>
|
||||
);
|
9
components/personal-card/elements/Title.tsx
Normal file
9
components/personal-card/elements/Title.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import * as React from 'react';
|
||||
|
||||
type Props = {};
|
||||
|
||||
export default ({}: Props) => (
|
||||
<div className={'sm mx-auto'}>
|
||||
<span className={'text-5xl'}>{'Alex Mihailov'}</span>
|
||||
</div>
|
||||
);
|
@ -7,16 +7,21 @@
|
||||
"export": "next build && next export",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"storybook": "start-storybook -s ./public -p 6006 ",
|
||||
"build-storybook": "build-storybook"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.35",
|
||||
"@fortawesome/free-brands-svg-icons": "^5.15.3",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.3",
|
||||
"@fortawesome/react-fontawesome": "^0.1.14",
|
||||
"next": "^10.1.0",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.13.16",
|
||||
"@fortawesome/fontawesome-free": "^5.15.3",
|
||||
"@storybook/addon-actions": "^6.2.0",
|
||||
"@storybook/addon-essentials": "^6.2.0",
|
||||
"@storybook/addon-links": "^6.2.0",
|
||||
|
@ -1,7 +1,14 @@
|
||||
import * as React from "react";
|
||||
import * as React from 'react';
|
||||
import Footer from '../components/Footer';
|
||||
import PersonalCard from '../components/personal-card/PersonalCard';
|
||||
|
||||
const Home = () => {
|
||||
return <h1>Welcome to My Next App!</h1>;
|
||||
return (
|
||||
<div className="bg-gray-100 flex flex-col h-screen justify-between">
|
||||
<PersonalCard />
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Home;
|
||||
export default Home;
|
||||
|
BIN
public/avatar.jpg
Normal file
BIN
public/avatar.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
23
src/contacts/contacts.ts
Normal file
23
src/contacts/contacts.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import Contacts from '../../components/personal-card/elements/Contacts';
|
||||
|
||||
export type ContactType = 'tg' | 'mail' | 'twitter' | 'github' | 'linkedin' | 'twitch';
|
||||
|
||||
export interface Contact {
|
||||
id: string;
|
||||
type: ContactType;
|
||||
}
|
||||
|
||||
type MapType = { [key in ContactType]: (id: string) => string };
|
||||
|
||||
const typeToFormer: MapType = {
|
||||
tg: (id) => `https://t.me/${id}`,
|
||||
mail: (id) => `mailto:${id}`,
|
||||
twitter: (id) => `https://twitter.com/${id}`,
|
||||
github: (id) => `https://github.com/${id}`,
|
||||
linkedin: (id) => `https://linkedin.com/in/${id}`,
|
||||
twitch: (id) => `https://www.twitch.tv/${id}`
|
||||
};
|
||||
|
||||
export function contactToLink(contact: Contact): string {
|
||||
return typeToFormer[contact.type](contact.id);
|
||||
}
|
@ -1,11 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
@ -18,13 +14,7 @@
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"baseUrl": "./",
|
||||
}
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"],
|
||||
"baseUrl": "./"
|
||||
}
|
||||
|
38
yarn.lock
38
yarn.lock
@ -1212,6 +1212,44 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
|
||||
integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
|
||||
|
||||
"@fortawesome/fontawesome-common-types@^0.2.35":
|
||||
version "0.2.35"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.35.tgz#01dd3d054da07a00b764d78748df20daf2b317e9"
|
||||
integrity sha512-IHUfxSEDS9dDGqYwIW7wTN6tn/O8E0n5PcAHz9cAaBoZw6UpG20IG/YM3NNLaGPwPqgjBAFjIURzqoQs3rrtuw==
|
||||
|
||||
"@fortawesome/fontawesome-free@^5.15.3":
|
||||
version "5.15.3"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.3.tgz#c36ffa64a2a239bf948541a97b6ae8d729e09a9a"
|
||||
integrity sha512-rFnSUN/QOtnOAgqFRooTA3H57JLDm0QEG/jPdk+tLQNL/eWd+Aok8g3qCI+Q1xuDPWpGW/i9JySpJVsq8Q0s9w==
|
||||
|
||||
"@fortawesome/fontawesome-svg-core@^1.2.35":
|
||||
version "1.2.35"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.35.tgz#85aea8c25645fcec88d35f2eb1045c38d3e65cff"
|
||||
integrity sha512-uLEXifXIL7hnh2sNZQrIJWNol7cTVIzwI+4qcBIq9QWaZqUblm0IDrtSqbNg+3SQf8SMGHkiSigD++rHmCHjBg==
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-common-types" "^0.2.35"
|
||||
|
||||
"@fortawesome/free-brands-svg-icons@^5.15.3":
|
||||
version "5.15.3"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.3.tgz#bec2821d23b9c667be1d192a6c5bfb2667e588eb"
|
||||
integrity sha512-1hirPcbjj72ZJtFvdnXGPbAbpn3Ox6mH3g5STbANFp3vGSiE5u5ingAKV06mK6ZVqNYxUPlh4DlTnaIvLtF2kw==
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-common-types" "^0.2.35"
|
||||
|
||||
"@fortawesome/free-solid-svg-icons@^5.15.3":
|
||||
version "5.15.3"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.3.tgz#52eebe354f60dc77e0bde934ffc5c75ffd04f9d8"
|
||||
integrity sha512-XPeeu1IlGYqz4VWGRAT5ukNMd4VHUEEJ7ysZ7pSSgaEtNvSo+FLurybGJVmiqkQdK50OkSja2bfZXOeyMGRD8Q==
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-common-types" "^0.2.35"
|
||||
|
||||
"@fortawesome/react-fontawesome@^0.1.14":
|
||||
version "0.1.14"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.14.tgz#bf28875c3935b69ce2dc620e1060b217a47f64ca"
|
||||
integrity sha512-4wqNb0gRLVaBm/h+lGe8UfPPivcbuJ6ecI4hIgW0LjI7kzpYB9FkN0L9apbVzg+lsBdcTf0AlBtODjcSX5mmKA==
|
||||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
|
||||
"@fullhuman/postcss-purgecss@^3.1.3":
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@fullhuman/postcss-purgecss/-/postcss-purgecss-3.1.3.tgz#47af7b87c9bfb3de4bc94a38f875b928fffdf339"
|
||||
|
Loading…
Reference in New Issue
Block a user