add base things: button, text field, toggle button, sidebar and registration screen

This commit is contained in:
Ilia 2021-03-26 12:55:28 +03:00
parent 147ff6ab58
commit a02ad3e417
40 changed files with 24620 additions and 305 deletions

11
.storybook/main.js Normal file
View File

@ -0,0 +1,11 @@
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/preset-create-react-app"
]
}

View File

@ -0,0 +1,2 @@
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@600&display=swap" rel="stylesheet">

4
.storybook/preview.js Normal file
View File

@ -0,0 +1,4 @@
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
}

14
codegen.yml Normal file
View File

@ -0,0 +1,14 @@
overwrite: true
schema: "http://localhost:8000/graphql/"
documents: "./regSchema.graphql"
generates:
src/generated/graphql.tsx:
plugins:
- 'typescript'
- 'typescript-react-apollo'
- 'typescript-operations'
config:
preResolveTypes: true
./graphql.schema.json:
plugins:
- "introspection"

13716
graphql.schema.json Normal file

File diff suppressed because it is too large Load Diff

8292
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,16 +3,25 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@apollo/client": "^3.3.13",
"@graphql-codegen/introspection": "^1.18.1",
"@graphql-codegen/typescript-operations": "^1.17.15",
"@graphql-codegen/typescript-react-apollo": "^2.2.3",
"@material-ui/core": "^4.11.3",
"@material-ui/lab": "^4.0.0-alpha.57",
"@testing-library/jest-dom": "^5.11.9",
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^12.8.3",
"@types/jest": "^26.0.21",
"@types/node": "^12.20.6",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.2",
"@types/react-sidebar": "^3.0.0",
"graphql": "^15.5.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.3",
"react-router-dom": "^5.2.0",
"react-scripts": "^4.0.3",
"react-sidebar": "^3.0.2",
"typescript": "^4.2.3",
"web-vitals": "^1.1.1"
},
@ -20,7 +29,10 @@
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"storybook": "start-storybook -p 6006 -s public",
"build-storybook": "build-storybook -s public",
"generate": "graphql-codegen"
},
"eslintConfig": {
"extends": [
@ -39,5 +51,17 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@graphql-codegen/cli": "^1.21.3",
"@graphql-codegen/typescript": "^1.21.1",
"@storybook/addon-actions": "^6.1.21",
"@storybook/addon-essentials": "^6.1.21",
"@storybook/addon-links": "^6.1.21",
"@storybook/node-logger": "^6.1.21",
"@storybook/preset-create-react-app": "^3.1.7",
"@storybook/react": "^6.1.21",
"@types/react-dom": "^17.0.3",
"@types/react-router-dom": "^5.1.7"
}
}

View File

@ -1,6 +1,8 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@600&display=swap" rel="stylesheet">
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
@ -27,6 +29,20 @@
<title>React App</title>
</head>
<body>
<style>
*{
transition: 0.3s;
text-decoration: none;
font-family: Montserrat;
font-weight: 600;
}
a{
text-decoration: none!important;
}
a:visited{
color: black!important;
}
</style>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--

11
regSchema.graphql Normal file
View File

@ -0,0 +1,11 @@
mutation auth($username:String!, $password:String!){
tokenAuth(username:$username, password:$password){
token
}
}
mutation register($username:String!, $password:String!){
registerUser(input:{username:$username, password:$password}){
ok
}
}

View File

@ -1,38 +0,0 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

View File

@ -1,9 +0,0 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

View File

@ -1,26 +1,24 @@
import React from 'react';
import logo from './logo.svg';
import './App.css';
import react from "react";
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
import {
BrowserRouter as Router,
Route,
Switch,
Redirect
} from "react-router-dom";
export default App;
import {RegScreen} from "./screens/WriteCred/RegScreen/RegScreen";
import {BaseScreen} from "./screens/BaseScreen/BaseScreen";
export const App:react.FC = () => {
return <Router>
<Switch>
<Route path="/enter-user">
<RegScreen></RegScreen>
</Route>
<Route path="">
<BaseScreen></BaseScreen>
</Route>
</Switch>
</Router>
}

View File

@ -0,0 +1,3 @@
export const CheckUser = () => {
return localStorage.getItem("token")?.length
}

View File

@ -0,0 +1,3 @@
export const UserAuth = (token:string) => {
localStorage.setItem("token", token);
}

24
src/client.js Normal file
View File

@ -0,0 +1,24 @@
import {ApolloClient, InMemoryCache} from "@apollo/client";
const defaultOptions = {
watchQuery: {
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
}
const client = new ApolloClient({
uri: "http://127.0.0.1:8000/graphql/",
cache: new InMemoryCache(),
fetchOptions: {
mode: "no-cors"
},
defaultOptions: defaultOptions
})
export default client;

1891
src/generated/graphql.tsx Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

View File

@ -1,17 +1,14 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {App} from "./App";
import client from "./client";
import {ApolloProvider} from "@apollo/client";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
<ApolloProvider client={client}>
<App></App>
</ApolloProvider>
,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

View File

@ -1 +0,0 @@
/// <reference types="react-scripts" />

View File

@ -1,15 +0,0 @@
import { ReportHandler } from 'web-vitals';
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

View File

@ -0,0 +1,21 @@
import react from "react";
import {ApplicationSidebar} from "../../uiKit/Sidebar/Sidebar";
export const BaseScreen:react.FC = () => {
return <ApplicationSidebar
content={[
{
link: "",
name: "name1"
},
{
link: "",
name: "name2"
}
]}
closed={true}
>
fuck you
</ApplicationSidebar>
}

View File

@ -0,0 +1,42 @@
import React from "react";
import { DefaultButton } from "../../../uiKit/Button/Button";
import { DefaultInput } from "../../../uiKit/Input/Input";
import "./style.css"
import {useAuthMutation} from "../../../generated/graphql"
import {useHistory} from "react-router-dom";
import {UserAuth} from "../../../UserInteraction/UserAuth";
interface IEvent{
target: {
value: string
}
}
export const Login_inputs:React.FC = () =>
{
let name:string, password:string;
let history = useHistory();
const [setToken] = useAuthMutation({onCompleted:(data:any) => {
UserAuth(data.tokenAuth.token)
history.push("/")
}});
return <div className="inputs_flex">
<DefaultInput handleChange={(e:IEvent) => {
name = e.target.value;
}} class="reg-input" placeHolder="Логин"></DefaultInput>
<DefaultInput handleChange={(e:IEvent) => {
password = e.target.value;
}} class="reg-input" placeHolder="Пароль" type="password"></DefaultInput>
<div className="password-refresh">Восстановить пароль</div>
<DefaultButton handleClick={()=>{
setToken({variables:{username:name, password:password}})
}} class="reg-btn">
Войти
</DefaultButton>
</div>
}

View File

@ -0,0 +1,8 @@
.inputs_flex{
display: flex;
width:100%;
flex-direction: column;
gap:32px;
justify-content: center;
align-items: center;
}

View File

@ -0,0 +1,43 @@
import react from "react";
import "./style.css";
import {Login_inputs} from "../Login/Login";
import {Registration_inputs} from "../Registration/Registration";
import {CheckUser} from "../../../UserInteraction/CheckUser"
import {
Link, Switch, Route, useRouteMatch, useLocation, Redirect
} from "react-router-dom";
export const RegScreen:react.FC = () => {
const {path, url} = useRouteMatch();
const location = useLocation();
console.log(location);
const isSign = location.pathname.split("/").pop() == "Login";
if (CheckUser()) return <Redirect to=""></Redirect>
return (
<div className="centered">
<div className="registration__container">
<div className="heading-evgen-app">Добро пожаловать в EvgenApp</div>
<div className="toggle__reg">
<Link to="/enter-user/Login">
<div className={"toggle-text " + (isSign ? "" : "disabled")}>Вход</div>
</Link>
<Link to="/enter-user/Registration">
<div className={"toggle-text " + (isSign ? "disabled": "")}>Регистрация</div>
</Link>
</div>
<Switch>
<Route path={`${url}/Login`}>
<Login_inputs></Login_inputs>
</Route>
<Route path={`${url}/Registration`}>
<Registration_inputs></Registration_inputs>
</Route>
</Switch>
</div>
</div>
);
}

View File

@ -0,0 +1,121 @@
.heading{
font-family: Montserrat;
font-style: normal;
font-weight: 800;
font-size: 28px;
line-height: 56px;
color: #373F41;
margin-bottom: 10vh;
}
.registration__container{
display: inline-flex;
margin: 0 auto;
justify-content: center;
align-items: center;
flex-direction: column;
gap:3vh;
}
.centered{
display: flex;
justify-content: center;
align-items: center;
}
.toggle__reg{
display:flex;
justify-content: center;
align-items: center;
gap:50px;
font-family: Montserrat;
font-style: normal;
font-weight: 600;
font-size: 20px;
line-height: 29px;
}
.reg-input{
width:100%!important;
}
.password-refresh{
font-family: Montserrat;
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 22px;
text-decoration: underline;
color: #404040;
}
.reg-btn{
width:100%;
}
.vk-button{
display: flex;
justify-content: center;
gap:32px;
height:26px;
}
.vk-button__img{
width:44px;
}
.vk-button__text{
margin:0px;
vertical-align: middle;
display: inline-flex;
justify-content: center;
align-items: center;
}
.google-btn{
background-color: #fff!important;
border: 1px solid #eee!important;
}
.google-text-color{
color:#3C3C3C;
}
.or-container{
display: flex;
gap:10px;
justify-content: center;
align-items: center;
width:100%;
}
.line{
width:100%;
height:1px;
background-color:#EDEDED;
}
.or-content{
font-family: Montserrat;
font-style: normal;
font-weight: 600;
font-size: 14px;
line-height: 56px;
color: #676767;
}
.vk-btn{
background-color: #5671FE!important;
}
.disabled{
color:#5A5A5A;
}
.heading-evgen-app{
font-family: Montserrat;
font-style: normal;
font-weight: 800;
font-size: 28px;
line-height: 56px;
color: #373F41;
margin-bottom: 10vh;
}

View File

@ -0,0 +1,42 @@
import React from "react"
import { DefaultButton } from "../../../uiKit/Button/Button";
import { DefaultInput } from "../../../uiKit/Input/Input";
import "../Login/style.css"
import {useRegisterMutation} from "../../../generated/graphql";
import {useHistory} from "react-router-dom";
interface IEvent{
target: {
value:string;
}
}
export const Registration_inputs:React.FC = () => {
const history = useHistory();
const [registerUser] = useRegisterMutation();
let name_input:string, password_input:string;
return <div className="inputs_flex">
<DefaultInput handleChange={(e:IEvent) => {
name_input = e.target.value;
}}
class="reg-input" placeHolder="ФИО"></DefaultInput>
<DefaultInput handleChange={(e:IEvent) => {
}} class="reg-input" placeHolder="E-mail"></DefaultInput>
<DefaultInput handleChange={(e:IEvent) => {
password_input = e.target.value;
}} class="reg-input" placeHolder="Password" type="password"></DefaultInput>
<DefaultButton handleClick={()=>{
registerUser({variables:{username:name_input,
password:password_input}});
history.push("/enter-user/Login")
}} class="reg-btn">
Зарегистрироваться
</DefaultButton>
</div>
}

View File

@ -1,5 +0,0 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

3
src/svg/vkImg.svg Normal file
View File

@ -0,0 +1,3 @@
<svg width="44" height="26" viewBox="0 0 44 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M36.5121 14.9091C35.8007 13.9991 36.0042 13.5943 36.5121 12.7809C36.5213 12.7716 42.3936 4.55186 42.9987 1.76429L43.0023 1.76243C43.303 0.746571 43.0023 0 41.5484 0H36.7376C35.5129 0 34.9482 0.640714 34.6457 1.35757C34.6457 1.35757 32.1963 7.29671 28.7312 11.1466C27.6128 12.259 27.0958 12.6156 26.4853 12.6156C26.1846 12.6156 25.7171 12.259 25.7171 11.2431V1.76243C25.7171 0.544143 25.3742 0 24.3603 0H16.7957C16.0276 0 15.571 0.568286 15.571 1.09757C15.571 2.25271 17.3036 2.51829 17.4833 5.76829V12.8199C17.4833 14.365 17.2064 14.6491 16.5922 14.6491C14.9569 14.6491 10.9875 8.68586 8.6353 1.86086C8.16045 0.536714 7.6966 0.00185701 6.46272 0.00185701H1.65006C0.276843 0.00185701 0 0.642571 0 1.35943C0 2.626 1.63539 8.92357 7.60493 17.2436C11.5834 22.9227 17.1863 26 22.2831 26C25.3467 26 25.7207 25.3166 25.7207 24.141C25.7207 18.7144 25.4439 18.2019 26.9784 18.2019C27.6898 18.2019 28.9145 18.5584 31.7746 21.2977C35.0435 24.5459 35.5807 26 37.4105 26H42.2213C43.5927 26 44.2875 25.3166 43.8879 23.9683C42.973 21.1324 36.7908 15.2991 36.5121 14.9091Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,12 @@
import {DefaultButton} from "./Button";
import react from "react";
export const Default:react.VFC = () => {
return <DefaultButton handleClick={() => {}}>Button</DefaultButton>
}
export default {
title: "Default Widget/Buttons"
}

View File

@ -0,0 +1,21 @@
import React, {useState} from 'react';
import "./style.css"
interface ButtonsConfig{
text?:String;
handleClick:Function;
style?:boolean;
class?:string;
children?:React.ReactNode;
};
export const DefaultButton : React.FC<ButtonsConfig> = (props) => {
const btnStyle = {
width:"30vw",
height:"5vw"
};
const classes = "defaultButton " + (props.class == undefined ? "" : props.class);
return (
<button className={classes} style={props.style == true? btnStyle:{}} onClick={()=> props.handleClick()}>{props.children}</button>
);
}

View File

@ -0,0 +1,44 @@
.defaultButton{
background: #707EFF;
border: 1px solid #5E77FF;
box-sizing: border-box;
border-radius: 10px;
font-family: 'Montserrat', sans-serif;
font-style: normal;
font-weight: 600;
font-size: 18px;
/* identical to box height */
padding : 20px 20px;
color: #FFFFFF;
letter-spacing: 0.2px;
}
.defaultButton:hover{
outline: none;
box-shadow: 0px 0px 0.5vw 0.1vw #707EFF;
}
.defaultButton:active{
outline: none;
box-shadow: 0px 0px 1vw 0.5vw #707EFF;
}
.DownloadButton{
padding:1vw;
background: #FFFFFF;
border: 0.25vw solid #98C7FF;
box-sizing: border-box;
border-radius: 1vw;
}
.DownloadButton:hover{
box-shadow: 0px 0px 0.5vw 0.25vw rgba(101, 171, 255, 0.5);
}
.DownloadButton:active{
background: #DFEAF8;
}
*{
outline: none;
}

View File

@ -0,0 +1,16 @@
import react from "react";
import { DefaultButton } from "../Button/Button";
import {DefaultInput} from "./Input";
export const TextInput:react.VFC = () => {
return <DefaultInput placeHolder="input" type="text"></DefaultInput>
}
export const PasswordInput:react.VFC = () => {
return <DefaultInput placeHolder="password" type="password"></DefaultInput>
}
export default {
title: "Default Widget/TextInputs"
}

19
src/uiKit/Input/Input.tsx Normal file
View File

@ -0,0 +1,19 @@
import React from 'react';
import "./style.css"
interface InputsConfig{
placeHolder?:string;
handleChange?:Function;
value?:string;
type?: string;
class?:string;
};
export const DefaultInput : React.FC<InputsConfig> = (props) => {
const classes = "myInput " + (props.class == undefined ? "" : props.class);
return (
<input className={classes} placeholder={props.placeHolder} onChange={
(event)=> props.handleChange != undefined ? props.handleChange(event) : {}}
type={props.type} value={props.value!}></input>
);
}

37
src/uiKit/Input/style.css Normal file
View File

@ -0,0 +1,37 @@
.myInput{
background: #FFFFFF;
border: 1px solid #E1E1E1;
box-sizing: border-box;
border-radius: 10px;
padding: 20px 32px;
font-family: 'Montserrat', sans-serif;
font-style: normal;
font-weight: 600;
font-size: 18px;
/* identical to box height */
color: #000000;
}
.myInput::placeholder{
font-style: normal;
font-weight: 600;
font-size: 18px;
/* identical to box height */
color: #6F6F6F;
font-family:'Montserrat', sans-serif;;
}
.myInput:hover{
}
.myInput:active{
}
*{
outline:none
}

View File

@ -0,0 +1,38 @@
import react from "react";
import {ApplicationSidebar} from "./Sidebar";
import {
BrowserRouter as Router,
Switch,
Route
} from "react-router-dom";
export const Sidebar:react.VFC = () => {
return <Router>
<Switch>
<Route path="">
<ApplicationSidebar
content={[
{
link: "",
name: "name1"
},
{
link: "",
name: "name2"
}
]}
closed={true}
></ApplicationSidebar>
</Route>
</Switch>
</Router>
}
export default {
title: "Sidebar"
}

View File

@ -0,0 +1,72 @@
import react, {useState} from "react"
import "./style.css";
import {
useParams, useRouteMatch, Link, Switch, Route, Redirect
} from "react-router-dom"
import Sidebar from "react-sidebar";
interface IMenuItem{
name: string;
}
interface ILobby{
content: {
name:string;
link:string;
}[];
}
interface ISidebar extends ILobby{
closed:boolean;
}
export const ApplicationSidebar:react.FC<ISidebar> = (props) => {
const phoneAdaptation = window.matchMedia("(min-width:880px)")
const {url} = useRouteMatch();
const [docked, setDocked] = useState(true);
const [closed, setClosed] = useState(props.closed);
phoneAdaptation.addListener(() => {
setDocked(phoneAdaptation.matches)
})
return <Sidebar
sidebar={<ApplicationSidebarRoute content={props.content}></ApplicationSidebarRoute>}
open={closed}
onSetOpen={setClosed}
sidebarClassName={"sidebar__container"}
docked={docked}
shadow={false}
>
{props.children}
</Sidebar>
}
const ApplicationSidebarRoute:react.FC<ILobby> = (props) => {
const {url} = useRouteMatch();
let widgets = [];
for (let i of props.content) {
widgets.push(
<Link to={`${url}/${i.link}`}>
<div>{i.name}</div>
</Link>
)
}
return <div className="lobby__menu">
<div className="lobby__heading">
EvgenApp
</div>
<div className="lobby-menu__content">
{widgets}
</div>
</div>
}

View File

@ -0,0 +1,82 @@
.lobby__container{
display: grid;
grid-template-columns: 1fr 3fr;
height: 100vh;
width:100vw;
}
.lobby__menu{
background-color: #fff;
border-right: 1px solid #E4E4E4;
padding: 20px 40px;
height: inherit;
}
.lobby__heading{
font-family: Montserrat;
font-style: normal;
font-weight: 600;
font-size: 28px;
line-height: 56px;
letter-spacing: 0.2px;
color: #707EFF;
}
.lobby__content{
overflow: scroll;
}
.lobby-menu__content{
margin-top:20vh;
display: flex;
flex-direction: column;
gap:3vh;
font-family: Montserrat;
font-style: normal;
font-weight: 600;
font-size: 24px;
line-height: 56px;
letter-spacing: 0.2px;
color: #6B6B6B;
}
.company{
position: absolute;
bottom:0px;
font-family: Montserrat;
font-style: normal;
font-weight: 600;
font-size: 18px;
line-height: 56px;
display: flex;
align-items: center;
letter-spacing: 0.2px;
color: #000000;
}
.active{
color: black;
}
.sidebar__container{
height: 100%;
}
.sidebar__container::-webkit-scrollbar{
display: none;
}
a{
text-decoration: none;
color: black;
}
a:active{
color: black;
}

View File

@ -0,0 +1,23 @@
import react from "react";
import {MyToogleButton} from "./ToggleButton";
import {BrowserRouter as Router} from "react-router-dom";
export const ToggleButton:react.VFC = () => {
return <Router>
<MyToogleButton handleChange={()=>{}} buttons={[{
name:"name1", link:""
},
{
name:"name1", link:""
}
]}></MyToogleButton>
</Router>
}
export default {
title:"Default Widget/Toggle Button"
}

View File

@ -0,0 +1,72 @@
import React, {useState} from 'react';
import "./style.css"
import { ToggleButton, ToggleButtonGroup} from '@material-ui/lab';
import {Link} from "react-router-dom";
interface IEButton {
name:string;
link:string;
}
interface ToogleConfig{
handleChange:Function;
buttons:Array<IEButton>;
}
export const MyToogleButton : React.FC<ToogleConfig> = (props) =>{
let [active, setActive] = useState(false)
const TGbtn = {
fontFamily: "'Montserrat', sans-serif",
background: "#FFFFFF",
border: "1px solid #F5F5F5",
borderRadius: "10px",
fontSize: "20px",
color:"#000000",
outline:"none!important;",
padding:"20px;",
width: "220px"
}
const TGbtnActive = {
background: "#F5F5F5",
border: "none",
fontFamily: "'Montserrat', sans-serif",
fontSize: "20px",
display: "flex",
alignItems: "center",
letterSpacing: "0.2px",
color:"#636363",
borderRadius: "10px",
width: "220px"
}
const TGbtnGroup = {
border: "none",
background: "#F5F5F5",
borderRadius: "10px"
}
let buttons = new Array<JSX.Element>()
props.buttons.forEach((el) => {
buttons.push(
<Link to={el.link}>
<ToggleButton
onClick={(e:any) => setActive(!active)}
style={props.buttons.indexOf(el)==0? active? TGbtn:TGbtnActive: !active? TGbtn:TGbtnActive}
value={el.name} aria-label={el.name}>
{el.name}
</ToggleButton>
</Link>
)
})
return(
<ToggleButtonGroup style={TGbtnGroup} orientation="horizontal">
{buttons}
</ToggleButtonGroup>
);
}

View File

@ -0,0 +1,44 @@
.defaultButton{
background: #707EFF;
border: 1px solid #5E77FF;
box-sizing: border-box;
border-radius: 10px;
font-family: 'Montserrat', sans-serif;
font-style: normal;
font-weight: 600;
font-size: 18px;
/* identical to box height */
padding : 20px 20px;
color: #FFFFFF;
letter-spacing: 0.2px;
}
.defaultButton:hover{
outline: none;
box-shadow: 0px 0px 0.5vw 0.1vw #707EFF;
}
.defaultButton:active{
outline: none;
box-shadow: 0px 0px 1vw 0.5vw #707EFF;
}
.DownloadButton{
padding:1vw;
background: #FFFFFF;
border: 0.25vw solid #98C7FF;
box-sizing: border-box;
border-radius: 1vw;
}
.DownloadButton:hover{
box-shadow: 0px 0px 0.5vw 0.25vw rgba(101, 171, 255, 0.5);
}
.DownloadButton:active{
background: #DFEAF8;
}
*{
outline: none;
}