Button component & Design System page
This commit is contained in:
parent
57930a5304
commit
8db6116636
101
src/front/components/DesignSystem/Button/classes.module.scss
Normal file
101
src/front/components/DesignSystem/Button/classes.module.scss
Normal file
@ -0,0 +1,101 @@
|
||||
@import "@Themes/constants.scss";
|
||||
|
||||
.root {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
border: 1px solid;
|
||||
gap: 12px;
|
||||
box-sizing: border-box;
|
||||
height: fit-content;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
background: transparent;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
|
||||
svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
&[variant="primary"] {
|
||||
color: $white;
|
||||
background-color: $purple-flash;
|
||||
border-color: $purple-flash;
|
||||
padding: 24px 48px;
|
||||
font-weight: 400;
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
|
||||
&:hover {
|
||||
border-color: $purple-hover;
|
||||
background-color: $purple-hover;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
border-color: $purple-soft;
|
||||
background-color: $purple-soft;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
&[variant="secondary"] {
|
||||
color: $white;
|
||||
background-color: $red-flash;
|
||||
border-color: $red-flash;
|
||||
padding: 24px 48px;
|
||||
font-weight: 400;
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
|
||||
&:hover {
|
||||
border-color: $re-hover;
|
||||
background-color: $re-hover;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
border-color: $red-soft;
|
||||
background-color: $red-soft;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
&[variant="ghost"] {
|
||||
color: $pink-flash;
|
||||
background-color: transparent;
|
||||
border-color: $pink-flash;
|
||||
padding: 24px 48px;
|
||||
font-weight: 400;
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
|
||||
svg {
|
||||
path {
|
||||
stroke: $white;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: $pink-hover;
|
||||
color: $pink-hover;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
border-color: $pink-soft;
|
||||
background-color: $pink-soft;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
&[fullwidth="true"] {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&[touppercase="false"] {
|
||||
text-transform: inherit;
|
||||
}
|
||||
}
|
50
src/front/components/DesignSystem/Button/index.tsx
Normal file
50
src/front/components/DesignSystem/Button/index.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import React from "react";
|
||||
import classes from "./classes.module.scss";
|
||||
|
||||
export enum EButtonVariant {
|
||||
PRIMARY = "primary",
|
||||
SECONDARY = "secondary",
|
||||
GHOST = "ghost",
|
||||
LINE = "line",
|
||||
}
|
||||
|
||||
type IProps = {
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined;
|
||||
children?: React.ReactNode;
|
||||
variant?: EButtonVariant;
|
||||
fullwidth?: "true" | "false";
|
||||
icon?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
type: "button" | "submit";
|
||||
isloading: string;
|
||||
};
|
||||
|
||||
type IState = {};
|
||||
|
||||
export default class Button extends React.Component<IProps, IState> {
|
||||
static defaultProps: IProps = {
|
||||
variant: EButtonVariant.PRIMARY,
|
||||
disabled: false,
|
||||
type: "button",
|
||||
isloading: "false",
|
||||
fullwidth: "false",
|
||||
};
|
||||
|
||||
public override render(): JSX.Element {
|
||||
const attributes = { ...this.props };
|
||||
delete attributes.icon;
|
||||
// let icon = this.props.isloading === "true" ? <Loader /> : this.props.icon; // Notion de loader
|
||||
let icon = this.props.icon;
|
||||
return (
|
||||
<button
|
||||
{...attributes}
|
||||
onClick={this.props.onClick}
|
||||
className={classes["root"]}
|
||||
type={this.props.type}
|
||||
>
|
||||
{this.props.children}
|
||||
{this.props.icon && icon}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
@import "@Themes/constants.scss";
|
||||
|
||||
@keyframes clickWave {
|
||||
from {
|
||||
box-shadow: 0 0 0 0 $primaryColor;
|
||||
}
|
||||
|
||||
to {
|
||||
box-shadow: 0 0 0 2px $primaryColor;
|
||||
}
|
||||
}
|
||||
|
||||
.root {
|
||||
height: 36px;
|
||||
text-align: center;
|
||||
border: none;
|
||||
font-family: 'Proxima Nova', Helvetica, Arial, sans-serif;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
border-radius: 6px;
|
||||
will-change: box-shadow;
|
||||
width: 100%;
|
||||
user-select: none;
|
||||
|
||||
&.clicked {
|
||||
animation: clickWave 500ms cubic-bezier(0.19, 1, 0.22, 1);
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
&.primary {
|
||||
color: $backgroundColor;
|
||||
background-color: $primaryColor;
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
color: white;
|
||||
background-color: $secondaryColor;
|
||||
}
|
||||
|
||||
&.transparent {
|
||||
color: $textColor;
|
||||
background-color: initial;
|
||||
}
|
||||
|
||||
&.loading {
|
||||
pointer-events: none;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
display: inline-block;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: inline-block;
|
||||
vertical-align: sub;
|
||||
margin-left: 15px;
|
||||
|
||||
&.primary {
|
||||
filter: brightness(0) saturate(100%) invert(15%) sepia(23%) saturate(909%) hue-rotate(194deg) brightness(98%) contrast(90%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes turn {
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes path {
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ButtonLoadingIcon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 15px;
|
||||
vertical-align: sub;
|
||||
stroke: white;
|
||||
stroke-width: 1px;
|
||||
stroke-dashoffset: 94.248;
|
||||
stroke-dasharray: 47.124;
|
||||
animation: turn 1.6s linear infinite forwards, path 1.6s linear infinite forwards;
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
import React from 'react'
|
||||
import { useState } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import classes from "./classes.module.scss"
|
||||
import Image from 'next/image'
|
||||
const PRIMARY = 'primary'
|
||||
export type ButtonColors = 'primary' | 'secondary' | 'transparent'
|
||||
|
||||
|
||||
type IProps = {
|
||||
text: string
|
||||
icon?: string
|
||||
color: ButtonColors
|
||||
onClick?: () => void
|
||||
}
|
||||
|
||||
export function Button(props: IProps) {
|
||||
const [clicked, setClicked] = useState(false)
|
||||
const clickCallback = () => {
|
||||
setClicked(true)
|
||||
setTimeout(() => setClicked(false), 1000)
|
||||
}
|
||||
let buttonClasses: string = clicked ? 'clicked' : '';
|
||||
|
||||
return (
|
||||
<div className={classNames(classes["root"], classes[props.color], classes[buttonClasses])}
|
||||
onClick={() => {
|
||||
clickCallback()
|
||||
props.onClick && props.onClick()
|
||||
}}>
|
||||
<div className={classes["text"]}>{props.text}</div>
|
||||
{props.icon && <Image className={classNames(classes["icon"], classes[props.color])} src={props.icon} alt="icon" />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Button.defaultProps = {
|
||||
icon: undefined,
|
||||
color: PRIMARY,
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
.root {
|
||||
.section {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.sub-section {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
43
src/front/components/Layouts/DesignSystem/index.tsx
Normal file
43
src/front/components/Layouts/DesignSystem/index.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import BasePage from "@Components/Layouts/Base";
|
||||
import DefaultTemplate from "@Components/LayoutTemplates/DefaultTemplate";
|
||||
import classes from "./classes.module.scss";
|
||||
import Typography, { ITypo } from "@Front/components/DesignSystem/Typography";
|
||||
import Button, { EButtonVariant } from "@Front/components/DesignSystem/Button";
|
||||
|
||||
export default class DesignSystem extends BasePage {
|
||||
public override render(): JSX.Element {
|
||||
return (
|
||||
<DefaultTemplate title={"HomePage"}>
|
||||
<div className={classes["root"]}>
|
||||
<div className={classes["section"]}>
|
||||
<div className={classes["sub-section"]}>
|
||||
<Typography typo={ITypo.H1}>Website design System</Typography>
|
||||
</div>
|
||||
<div className={classes["sub-section"]}>
|
||||
<Typography typo={ITypo.P_18}>
|
||||
This page allows to gather all the design system of the site. A
|
||||
Design System is a library of components, visuals and principles
|
||||
with reusable code. This evolving kit offers a UX and UI
|
||||
repository for designers and developers of digital products and
|
||||
services. The construction of a design system offers many
|
||||
advantages. This solution facilitates the work of the teams and
|
||||
reduces the "design debt" and the "technical debt". The result
|
||||
is a coherent ecosystem and therefore a better experience for
|
||||
users and customers.
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={classes["section"]}>
|
||||
<div className={classes["sub-section"]}>
|
||||
<Typography typo={ITypo.H3}>Button components</Typography>
|
||||
</div>
|
||||
<Button variant={EButtonVariant.PRIMARY}>Primary</Button>
|
||||
<Button variant={EButtonVariant.SECONDARY}>Secondary</Button>
|
||||
<Button variant={EButtonVariant.GHOST}>Ghost</Button>
|
||||
</div>
|
||||
</div>
|
||||
</DefaultTemplate>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
import { Button } from "@Components/Elements/Button";
|
||||
import BasePage from "@Components/Layouts/Base";
|
||||
import DefaultTemplate from "@Components/LayoutTemplates/DefaultTemplate"
|
||||
import UnpluggedIcon from "@Assets/icons/unplugged.svg"
|
||||
import Image from "next/image";
|
||||
import CardsIcon from "@Assets/icons/cards.svg"
|
||||
import Link from "next/link";
|
||||
import classes from "./classes.module.scss";
|
||||
|
||||
@ -16,7 +14,7 @@ export default class PageNotFound extends BasePage {
|
||||
<div className={classes["text"]}>There isn't anything here...</div>
|
||||
<div className={classes["home-button"]}>
|
||||
<Link href="/">
|
||||
<Button text="Go to Home" icon={CardsIcon} />
|
||||
{/* <Button text="Go to Home" icon={CardsIcon} /> */}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,12 +4,8 @@ import Image from "next/image";
|
||||
import TezosLinkLogo from "@Assets/link_logo.svg";
|
||||
import Logo from "@Assets/logo.svg";
|
||||
import classes from "./classes.module.scss";
|
||||
import { Button } from "@Components/Elements/Button";
|
||||
import Burger from "@Components/Elements/Burger";
|
||||
|
||||
import LoginIcon from "@Assets/icons/login.svg";
|
||||
import PlusCardIcon from "@Assets/icons/plus-card.svg";
|
||||
|
||||
type IProps = {};
|
||||
type IState = {
|
||||
status: boolean;
|
||||
@ -43,10 +39,10 @@ export default class Header extends React.Component<IProps, IState> {
|
||||
</div>
|
||||
<div className={classes["button"]}>
|
||||
<Link href="/show-project">
|
||||
<Button color="transparent" text="MY PROJECT" icon={LoginIcon} />
|
||||
{/* <Button color="transparent" text="MY PROJECT" icon={LoginIcon} /> */}
|
||||
</Link>
|
||||
<Link href="/new-project">
|
||||
<Button text="CREATE" icon={PlusCardIcon} />
|
||||
{/* <Button text="CREATE" icon={PlusCardIcon} /> */}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -8,8 +8,9 @@ $custom-easing: cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
|
||||
// Colors
|
||||
$black: #000000;
|
||||
$white: #ffffff;
|
||||
|
||||
$green-flash: #12BF4D;
|
||||
$green-flash: #12bf4d;
|
||||
$blue-flash: #005176;
|
||||
$turquoise-flash: #3fa79e;
|
||||
$purple-flash: #320756;
|
||||
|
5
src/pages/design-system.tsx
Normal file
5
src/pages/design-system.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import DesignSystem from "@Front/components/Layouts/DesignSystem";
|
||||
|
||||
export default function Route() {
|
||||
return <DesignSystem />;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user