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

✨ add error #104

Merged
merged 11 commits into from
Jan 17, 2023
91 changes: 91 additions & 0 deletions examples/next-typescript/pages/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { Container, Error, Text } from "@tonightpass/kitchen";
import { NextPage } from "next";
import React from "react";

const ErrorPage: NextPage = () => {
return (
<>
<Container
gap={10}
style={{
maxWidth: 700,
margin: "0 auto",
}}
>
<Container gap={5}>
<Text>default</Text>
<Error>This email address is already in use.</Error>
</Container>

<Container gap={5}>
<Text>custom label</Text>
<Error label="Email Error">
This email address is already in use.
</Error>
</Container>

<Container gap={5}>
<Text>no label</Text>
<Error label={false}>This email address is already in use. </Error>
</Container>

<Container gap={5}>
<Text>sizes</Text>
<Container direction={["column", "row", "row"]} row>
<Container align={"flex-start"}>
<Error size="small">This email is in use.</Error>
</Container>
<Container align={"flex-start"}>
<Error>This email is in use.</Error>
</Container>
<Container align={"flex-start"}>
<Error size="large">This email is in use.</Error>
</Container>
</Container>
</Container>

<Container gap={5}>
<Text>multiline</Text>
<Container>
<Container>
<Error size="small">
A valid email address is required so that we can verify your
GitHub installation. In the event that you cannot provide a
valid email address, please contact support.
</Error>
</Container>
<Container>
<Error>
A valid email address is required so that we can verify your
GitHub installation. In the event that you cannot provide a
valid email address, please contact support.
</Error>
</Container>
<Container>
<Error size="large">
A valid email address is required so that we can verify your
GitHub installation. In the event that you cannot provide a
valid email address, please contact support.
</Error>
</Container>
</Container>
</Container>

<Container gap={5}>
<Text>with an `error` property</Text>
<Container row>
<Error
error={{
message: "The request failed.",
action: "Contact Us",
link: "https://tonightpass.com/contact",
}}
/>
</Container>
</Container>
</Container>
</>
);
};

export default ErrorPage;
1 change: 1 addition & 0 deletions examples/next-typescript/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const IndexPage: NextPage = () => {
<Link href={"/button"}>Button</Link>
<Link href={"/checkbox"}>Checkbox</Link>
<Link href={"/drawer"}>Drawer</Link>
<Link href={"/error"}>Error</Link>
<Link href={"/icon"}>Icon</Link>
<Link href={"/link"}>Link</Link>
<Link href={"/modal"}>Modal</Link>
Expand Down
2 changes: 1 addition & 1 deletion examples/next-typescript/pages/link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const LinkPage: NextPage = () => {
</Link>
</Container>

<Container>
<Container align={"flex-start"}>
<Text size={"small"}>secondary</Text>
<Link href="#" variant="secondary">
Secondary variant
Expand Down
10 changes: 5 additions & 5 deletions packages/kitchen/src/components/Badge/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from "react";
import styled from "styled-components";
import { KitchenComponent } from "../../types";
import { KitchenComponent, NormalSizes } from "../../types";

export type BadgeProps = KitchenComponent & {
/**
* The size of the badge.
* @default "normal"
* @default "medium"
*/
size?: "small" | "normal" | "large";
size?: NormalSizes;

/**
* The type of the badge.
Expand Down Expand Up @@ -41,7 +41,7 @@ const Badge = styled((props: BadgeProps) => {
return "2px 4px";
case "large":
return "8px 12px";
case "normal":
case "medium":
default:
return "4px 8px";
}
Expand All @@ -53,7 +53,7 @@ const Badge = styled((props: BadgeProps) => {
return props.theme.size.tiny;
case "large":
return props.theme.size.normal;
case "normal":
case "medium":
default:
return props.theme.size.small;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/kitchen/src/components/Button/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from "react";
import styled, { useTheme } from "styled-components";
import { KitchenComponent } from "../../types";
import { KitchenComponent, NormalSizes } from "../../types";
import { AccentColors } from "../../types/theme";
import convertRGBToRGBA from "../../utils/convertRGBToRGBA";
import isNumber from "../../utils/isNumber";
import Spinner from "../Spinner";

export type ButtonProps = KitchenComponent & {
shape?: "square" | "round";
size?: "small" | "medium" | "large";
size?: NormalSizes;
loading?: boolean;
disabled?: boolean;
onClick?: (event?: React.MouseEvent<HTMLButtonElement>) => void;
Expand Down
113 changes: 113 additions & 0 deletions packages/kitchen/src/components/Error/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import React from "react";
import { RiErrorWarningLine, RiExternalLinkLine } from "react-icons/ri";
import styled from "styled-components";
import { KitchenComponent, NormalSizes } from "../../types";
import Icon from "../Icon";
import Text from "../Text";
import Link from "../Link";

export type ErrorProps = KitchenComponent & {
/**
* The label of the error.
* @default true
*/
label?: boolean | string;

/**
* The size of the error.
* @default "medium"
*/
size?: NormalSizes;

error?: { message: string; action?: string; link?: string };
};

const Error = styled(
({ label = true, size, error, children, ...props }: ErrorProps) => {
return (
<div {...props}>
<IconContainer>
<Icon
icon={RiErrorWarningLine}
accent={"danger"}
size={size === "small" ? 18 : size === "large" ? 24 : 20}
align="bottom"
/>
</IconContainer>
<TextContainer>
<ErrorText size={size} accent={"danger"}>
{label && (
<Label>
{typeof label === "string" ? label : "Error"}
{label ? ": " : ""}
</Label>
)}
<Content>{error ? error.message : children}</Content>
{error && (
<Action href={error.link} variant="blend">
{error.action}
<ActionIcon
accent={"danger"}
icon={RiExternalLinkLine}
size={size}
/>
</Action>
)}
</ErrorText>
</TextContainer>
</div>
);
}
)<ErrorProps>`
display: flex;

*,
*:before,
*:after {
box-sizing: inherit;
}
`;

const IconContainer = styled.div``;

const TextContainer = styled.div`
margin-left: 8px;
`;

const ErrorText = styled(Text)<{ size: ErrorProps["size"] }>`
font-size: ${(props) => {
switch (props.size) {
case "small":
return props.theme.size.small;
case "large":
return props.theme.size.medium;
case "medium":
default:
return props.theme.size.normal;
}
}};
word-break: break-word;
`;

const Label = styled.b`
font-size: inherit;
font-weight: ${({ theme }) => theme.weight.semiBold};
color: ${({ theme }) => theme.colors.accent.danger};
`;

const Content = styled.span`
font-size: inherit;
font-family: inherit;
color: ${({ theme }) => theme.colors.accent.danger};
`;

const Action = styled(Link)`
display: inline-block;
margin-left: ${({ theme }) => theme.gap.tiny};
`;

const ActionIcon = styled(Icon)`
margin-left: ${({ theme }) => theme.gap.tiny};
`;

export default Error;
38 changes: 20 additions & 18 deletions packages/kitchen/src/components/Link/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,23 +106,19 @@ const Link = styled(
)<LinkProps>`
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: space-between;
user-select: none;
flex: 1;
gap: 10px;
border-radius: 8px;
font-size: ${({ theme }) => theme.size.normal};
font-weight: ${({ theme, variant }) =>
variant === "blend" ? theme.weight.bold : theme.weight.regular};
text-decoration: ${({ variant }) =>
variant === "blend" ? "underline" : "none"};

background-color: ${({ theme }) => {
return theme.colors.layout.dark;
}}
return "transparent";
}};
variant === "blend" ? theme.weight.medium : theme.weight.regular};
text-decoration: none;
transition: opacity 0.1s ease;
line-height: 1.25;
${({ variant }) =>
variant === "blend" &&
`
background-image: linear-gradient(currentColor, currentColor);
background-size: 100% 1px;
background-position: 0 100%;
background-repeat: no-repeat;`};

color: ${({ theme, variant }) => {
if (variant === "highlight") {
Expand All @@ -147,10 +143,16 @@ const Link = styled(
? "none"
: "brightness(0.8)"
};
text-decoration: ${
variant && variant !== "secondary" ? "underline" : "none"
${
variant === "secondary"
? `
background-image: linear-gradient(currentColor, currentColor);
background-size: 100% 1px;
background-position: 0 100%;
background-repeat: no-repeat;
color: ${theme.colors.text.lightest};`
: ""
};
${variant === "secondary" ? `color: ${theme.colors.text.lightest};` : ""}
`;
}}
}
Expand Down
10 changes: 5 additions & 5 deletions packages/kitchen/src/components/Note/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from "react";
import styled from "styled-components";
import { KitchenComponent } from "../../types";
import { KitchenComponent, NormalSizes } from "../../types";
import capitalize from "../../utils/capitalize";

export type NoteProps = KitchenComponent & {
/**
* The size of the note.
* @default "normal"
* @default "medium"
*/
size?: "small" | "normal" | "large";
size?: NormalSizes;

/**
* The type of the note.
Expand Down Expand Up @@ -132,7 +132,7 @@ const Note = styled(
return "4px 8px";
case "large":
return "12px 16px";
case "normal":
case "medium":
default:
return "8px 12px";
}
Expand All @@ -144,7 +144,7 @@ const Note = styled(
return props.theme.size.small;
case "large":
return props.theme.size.medium;
case "normal":
case "medium":
default:
return props.theme.size.normal;
}
Expand Down
3 changes: 3 additions & 0 deletions packages/kitchen/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ export type { ContainerProps } from "./components/Container";
export { default as Drawer } from "./components/Drawer";
export type { DrawerProps } from "./components/Drawer";

export { default as Error } from "./components/Error";
export type { ErrorProps } from "./components/Error";

export { default as FragmentLink } from "./components/FragmentLink";
export type { FragmentLinkProps } from "./components/FragmentLink";

Expand Down
2 changes: 2 additions & 0 deletions packages/kitchen/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export type KitchenComponent = {
*/
children?: React.ReactNode;
} & React.HTMLAttributes<HTMLElement>;

export type NormalSizes = "small" | "medium" | "large";