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

feat: SNEGDEV-21 перенес компоненты из шаблона, адаптировал стиль #5

Merged
merged 1 commit into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/ui/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
67 changes: 0 additions & 67 deletions packages/ui/src/ArticleLayout.jsx

This file was deleted.

60 changes: 60 additions & 0 deletions packages/ui/src/ArticleLayout/ArticleLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Container } from "../Container/Container";
import { Prose } from "../Prose/Prose";
import { ArticleLayoutBack } from "./ArticleLayoutBack";
import { FC } from "react";

export function formatDate(dateString: string) {
return new Date(`${dateString}T00:00:00Z`).toLocaleDateString("en-US", {
day: "numeric",
month: "long",
year: "numeric",
timeZone: "UTC",
});
}

interface Article {
title: string;
description: string;
author: string;
date: string;
}

export interface ArticleWithSlug extends Article {
slug: string;
}

type ArticleLayoutProps = {
article: ArticleWithSlug;
children: React.ReactNode;
};
export const ArticleLayout: FC<ArticleLayoutProps> = ({
article,
children,
}) => {
return (
<Container className="mt-16 lg:mt-32">
<div className="xl:relative">
<div className="mx-auto max-w-2xl">
<ArticleLayoutBack />
<article>
<header className="flex flex-col">
<h1 className="mt-6 text-4xl font-bold tracking-tight text-zinc-800 dark:text-zinc-100 sm:text-5xl">
{article.title}
</h1>
<time
dateTime={article.date}
className="order-first flex items-center text-base text-zinc-400 dark:text-zinc-500"
>
<span className="h-4 w-0.5 rounded-full bg-zinc-200 dark:bg-zinc-500" />
<span className="ml-3">{formatDate(article.date)}</span>
</time>
</header>
<Prose className="mt-8" data-mdx-content>
{children}
</Prose>
</article>
</div>
</div>
</Container>
);
};
42 changes: 42 additions & 0 deletions packages/ui/src/ArticleLayout/ArticleLayoutBack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use client";

import { useRouter } from "next/navigation";
import { FC, useEffect, useState } from "react";

const ArrowLeftIcon: FC<React.ComponentPropsWithoutRef<"svg">> = (props) => {
return (
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true" {...props}>
<path
d="M7.25 11.25 3.75 8m0 0 3.5-3.25M3.75 8h8.5"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
};

export const ArticleLayoutBack: FC = () => {
let router = useRouter();
const [hasPreviousRoute, setHasPreviousRoute] = useState(false);
useEffect(() => {
if (window?.history?.length > 0) {
setHasPreviousRoute(true);
}
}, []);

if (!hasPreviousRoute) {
return null;
}

return (
<button
type="button"
onClick={() => router.back()}
aria-label="Go back to articles"
className="group mb-8 flex h-10 w-10 items-center justify-center rounded-full bg-white shadow-md shadow-zinc-800/5 ring-1 ring-zinc-900/5 transition dark:border dark:border-zinc-700/50 dark:bg-zinc-800 dark:ring-0 dark:ring-white/10 dark:hover:border-zinc-700 dark:hover:ring-white/20 lg:absolute lg:-left-5 lg:-mt-2 lg:mb-0 xl:-top-1.5 xl:left-0 xl:mt-0"
>
<ArrowLeftIcon className="h-4 w-4 stroke-zinc-500 transition group-hover:stroke-zinc-700 dark:stroke-zinc-500 dark:group-hover:stroke-zinc-400" />
</button>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@ import type { Meta, StoryObj } from "@storybook/react";

import { Button } from "./Button";

// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: "Example/Button2",
component: Button,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: "centered",
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ["autodocs"],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {},
} satisfies Meta<typeof Button>;

Expand All @@ -23,11 +19,13 @@ type Story = StoryObj<typeof meta>;
export const Primary: Story = {
args: {
variant: "primary",
children: "Awesome primary button",
},
};

export const Secondary: Story = {
args: {
variant: "secondary",
children: "Awesome secondary button",
},
};
25 changes: 12 additions & 13 deletions packages/ui/src/Button.tsx → packages/ui/src/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@
import { FC } from "react";
import Link from "next/link";
import clsx from "clsx";
import { ComponentPropsWithoutRef } from "react";

const variantStyles = {
primary:
"bg-zinc-800 font-semibold text-zinc-100 hover:bg-zinc-700 active:bg-zinc-800 active:text-zinc-100/70 dark:bg-zinc-700 dark:hover:bg-zinc-600 dark:active:bg-zinc-700 dark:active:text-zinc-100/70",
secondary:
"bg-zinc-50 font-medium text-zinc-900 hover:bg-zinc-100 active:bg-zinc-100 active:text-zinc-900/60 dark:bg-zinc-800/50 dark:text-zinc-300 dark:hover:bg-zinc-800 dark:hover:text-zinc-50 dark:active:bg-zinc-800/50 dark:active:text-zinc-50/70",
} as const;
};

/** @todo Сделать нормальный тип */
type Props = {
href?: string;
type ButtonProps = {
variant?: keyof typeof variantStyles;
className?: string;
};
} & (
| (ComponentPropsWithoutRef<"button"> & { href?: undefined })
| ComponentPropsWithoutRef<typeof Link>
);

export const Button: FC<Props> = ({
export const Button = ({
variant = "primary",
className,
href,
...props
}) => {
}: ButtonProps) => {
className = clsx(
"inline-flex items-center gap-2 justify-center rounded-md py-2 px-3 text-sm outline-offset-2 transition active:transition-none",
variantStyles[variant],
className,
);

return href ? (
<Link href={href} className={className} {...props} />
) : (
return typeof props.href === "undefined" ? (
<button className={className} {...props} />
) : (
<Link className={className} {...props} />
);
};
Loading