From 7eae7e5599ce775bc004d1b485ade4663d33ec47 Mon Sep 17 00:00:00 2001 From: Antoine Kingue <contact@antoinek.fr> Date: Wed, 10 Jan 2024 13:04:56 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20move=20kitchen/next/link=20to=20?= =?UTF-8?q?kitchen/link=20compatible=20with=20next?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/fair-bottles-nail.md | 5 + docs/components/Footer/index.tsx | 2 +- docs/components/Landing/Featured/index.tsx | 10 +- .../Landing/Showcase/List/index.tsx | 3 +- docs/pages/docs/frameworks/nextjs.mdx | 148 +--------------- examples/next-typescript/src/pages/index.tsx | 2 +- .../src/components/GlobalStyle/main.ts | 3 +- .../src/components/Link/Fragment/index.tsx | 8 +- .../kitchen/src/components/Link/index.tsx | 22 ++- packages/kitchen/src/index.ts | 2 + .../next/components/Link/Fragment/index.tsx | 18 -- .../src/next/components/Link/index.tsx | 167 ------------------ packages/kitchen/src/next/index.ts | 6 - packages/kitchen/src/types/index.ts | 1 + packages/kitchen/src/types/window.ts | 7 + workshop/pages/link.tsx | 10 +- workshop/pages/template.tsx | 2 +- 17 files changed, 61 insertions(+), 355 deletions(-) create mode 100644 .changeset/fair-bottles-nail.md delete mode 100644 packages/kitchen/src/next/components/Link/Fragment/index.tsx delete mode 100644 packages/kitchen/src/next/components/Link/index.tsx create mode 100644 packages/kitchen/src/types/window.ts diff --git a/.changeset/fair-bottles-nail.md b/.changeset/fair-bottles-nail.md new file mode 100644 index 000000000..884cf47ce --- /dev/null +++ b/.changeset/fair-bottles-nail.md @@ -0,0 +1,5 @@ +--- +"@tonightpass/kitchen": minor +--- + +Move kitchen/next/link to kitchen/link compatible with next diff --git a/docs/components/Footer/index.tsx b/docs/components/Footer/index.tsx index 4d5fc28ad..d95c759a1 100644 --- a/docs/components/Footer/index.tsx +++ b/docs/components/Footer/index.tsx @@ -1,11 +1,11 @@ import Logo from "@components/Logo/TonightPass"; import kitchen, { Container, + Link, Footer, FooterGroup, FooterLink, } from "@tonightpass/kitchen"; -import { Link } from "@tonightpass/kitchen/next"; import { ThemeSwitch } from "nextra-theme-docs"; const navigation = { diff --git a/docs/components/Landing/Featured/index.tsx b/docs/components/Landing/Featured/index.tsx index 20b6e9383..c0f408b10 100644 --- a/docs/components/Landing/Featured/index.tsx +++ b/docs/components/Landing/Featured/index.tsx @@ -1,5 +1,11 @@ -import { Button, Container, Text, Image, useTheme } from "@tonightpass/kitchen"; -import { Link } from "@tonightpass/kitchen/next"; +import { + Button, + Container, + Link, + Text, + Image, + useTheme, +} from "@tonightpass/kitchen"; const Featured: React.FC = () => { const { theme } = useTheme(); diff --git a/docs/components/Landing/Showcase/List/index.tsx b/docs/components/Landing/Showcase/List/index.tsx index d7f562e20..2a247885e 100644 --- a/docs/components/Landing/Showcase/List/index.tsx +++ b/docs/components/Landing/Showcase/List/index.tsx @@ -1,5 +1,4 @@ -import kitchen, { Container, Text } from "@tonightpass/kitchen"; -import { Link } from "@tonightpass/kitchen/next"; +import kitchen, { Container, Text, Link } from "@tonightpass/kitchen"; import showcases from "data/showcases"; import ShowcaseCard from "./Card"; diff --git a/docs/pages/docs/frameworks/nextjs.mdx b/docs/pages/docs/frameworks/nextjs.mdx index 34998df91..d8ebcb3ff 100644 --- a/docs/pages/docs/frameworks/nextjs.mdx +++ b/docs/pages/docs/frameworks/nextjs.mdx @@ -6,9 +6,8 @@ category: frameworks --- import Playground from "@components/Playground"; -import kitchen, { Container } from "@tonightpass/kitchen"; +import kitchen, { Container, FragmentLink, Link } from "@tonightpass/kitchen"; import { Tab, Tabs } from "nextra-theme-docs"; -import { FragmentLink, Link } from "@tonightpass/kitchen/next"; # Getting Started with Next.js @@ -77,148 +76,3 @@ Deploy the example using [Vercel](https://vercel.com/new/clone?repository-url=ht [](https://vercel.com/new/clone?repository-url=https://github.com/tonightpass/kitchen/tree/master/examples/next-typescript&project-name=kitchen-next&repository-name=kitchen-next) In addition, here is a complete [project example](https://github.com/tonightpass/kitchen/tree/master/examples/next-typescript) using Kitchen with Next.js. - -## Kitchen with Next.js Link - -If you're using Next.js 13, we've provided a `@tonightpass/kitchen/next` package that -gives you a smoother experience when using Kitchen Link component with -`next/link`. - -export const Card = kitchen(Container)` - border: 1px solid ${({ theme }) => theme.colors.layout.dark}; - border-radius: 8px; - padding: 16px; -`; - -### Usage - -First of all, you need to import the `Link` component from the `@tonightpass/kitchen` package. - -```js -import { Link } from "@tonightpass/kitchen" -``` - -### Default - -<Playground -scope={{ Link }} - code={` - <Link href="/">Return to the home page</Link> -`} -/> - -### Using onClick - -<Playground -scope={{ Link }} - code={` - <Link onClick={() => router.push("/")}>Return to the home page</Link> -`} -/> - -### Disabled - -<Playground -scope={{ Link }} - code={` -<Container gap={"small"}> - <Link disabled>Disabled link</Link> - <Link href={undefined} onClick={undefined}> - Disabled link (no href or onClick) - </Link> - <Link href="#" disabled> - {"Disabled link (href=#)"} - </Link> -</Container> -`} -/> - -### Non text - -<Playground -scope={{ Link, Card }} - code={` -<Link href="/"> - <Card>This entire div is wrapped in a link</Card> -</Link> -`} -/> - -### Variants - -<Playground -scope={{ Link }} - code={` -<Container gap={"small"}> - <Container gap={"small"}> - <Text size={"small"}>highlight</Text> - <Link href="#" variant="highlight"> - Highlight variant - </Link> - </Container> - <Container gap={"small"}> - <Text size={"small"}>primary</Text> - <Link href="#" variant="primary"> - Primary variant - </Link> - </Container> - <Container gap={"small"} align={"flex-start"}> - <Text size={"small"}>secondary</Text> - <Link href="#" variant="secondary"> - Secondary variant - </Link> - </Container> - <Container gap={"small"}> - <Text size={"small"}>blend</Text> - <Note type="danger" label={false}> - <Link href="#" variant="blend"> - Blend variant - </Link>{" "} - works well with themed components. - </Note> - </Container> -</Container> -`} -/> - -### Fragment link (anchor) - -<Playground -scope={{ FragmentLink }} - code={` -<FragmentLink id="fragment-link-example"> - Click on this to jump to this section of the page -</FragmentLink> -`} -/> - -### Internal href - -<Playground -scope={{ Link }} - code={` -<Link href="/">Click on this to jump back to the home page</Link> -`} -/> - -### External href - -<Playground -scope={{ Link }} - code={` -<Link href="https://tonightpass.com/"> - Click on this to go to our website -</Link> -`} -/> - -### Props - -| Name | Type | Default | Required | Description | Accepted values | -| :--- | :--- | :-----: | :------: | :---------- | :-------------- | -| `href` | `string` \| `UrlObject` | - | - | The href of the link. | - | -| `locale` | `string` | - | - | The locale of the link. | - | -| `className` | `string` | - | - | The classname of the link. | - | -| `onClick` | `(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void` | - | - | The click event handler of the link. | - | -| `disabled` | `boolean` | `false` | - | The status (disabled or not) of the link. | - | -| `variant` | `string` | `primary` | - | The variant of the link. | `highlight`, `primary`, `secondary`, `blend` | diff --git a/examples/next-typescript/src/pages/index.tsx b/examples/next-typescript/src/pages/index.tsx index c7d2f60d4..5069a749e 100644 --- a/examples/next-typescript/src/pages/index.tsx +++ b/examples/next-typescript/src/pages/index.tsx @@ -3,9 +3,9 @@ import kitchen, { convertRGBToRGBA, Image, Text, + Link, rotate, } from "@tonightpass/kitchen"; -import { Link } from "@tonightpass/kitchen/next"; import Head from "next/head"; const IndexPage = () => { diff --git a/packages/kitchen/src/components/GlobalStyle/main.ts b/packages/kitchen/src/components/GlobalStyle/main.ts index 36e12b1e0..0649d20a4 100644 --- a/packages/kitchen/src/components/GlobalStyle/main.ts +++ b/packages/kitchen/src/components/GlobalStyle/main.ts @@ -74,8 +74,7 @@ const mainCss = css` a { text-decoration: none; - color: ${({ theme }) => theme.colors.text.lightest}; - transition: all 0.2s; + color: inherit; cursor: pointer; &:hover { diff --git a/packages/kitchen/src/components/Link/Fragment/index.tsx b/packages/kitchen/src/components/Link/Fragment/index.tsx index 358ca8c4e..d531a4a9e 100644 --- a/packages/kitchen/src/components/Link/Fragment/index.tsx +++ b/packages/kitchen/src/components/Link/Fragment/index.tsx @@ -2,14 +2,20 @@ import React from "react"; import styled from "styled-components"; import Link, { LinkProps } from ".."; +import { KitchenComponent } from "../../../types"; -export type FragmentLinkProps = LinkProps & { +type Props = LinkProps & { /** * The link's id. */ id: string; }; +export type FragmentLinkProps = KitchenComponent< + Props, + React.AnchorHTMLAttributes<HTMLAnchorElement> +>; + const FragmentLink = styled(({ id, ...props }: FragmentLinkProps) => { const href = `#${id}`; return <Link id={id} href={href} {...props} />; diff --git a/packages/kitchen/src/components/Link/index.tsx b/packages/kitchen/src/components/Link/index.tsx index 051911986..3bf0c64c0 100644 --- a/packages/kitchen/src/components/Link/index.tsx +++ b/packages/kitchen/src/components/Link/index.tsx @@ -56,10 +56,7 @@ const Link = styled( }; if (isString(href)) { - href = href as string; - // regex to check if the href is internal or external - - const internal = href.match(/^(\/(?!\/)[^#]*|#.*)$/); + const internal = (href as string).match(/^(\/(?!\/)[^#]*|#.*)$/); if (!internal) { return ( <Component @@ -76,6 +73,23 @@ const Link = styled( } } + if (typeof window !== "undefined" && window.next) { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const NextLink = require("next/link").default; + if (href && NextLink) { + return ( + <NextLink + href={href} + className={className} + onClick={handleClick} + {...props} + > + {children} + </NextLink> + ); + } + } + return ( <Component className={className} diff --git a/packages/kitchen/src/index.ts b/packages/kitchen/src/index.ts index 1d1724542..6a65da4b4 100644 --- a/packages/kitchen/src/index.ts +++ b/packages/kitchen/src/index.ts @@ -71,6 +71,8 @@ export { default as UnorderedList } from "./components/List/Unordered"; export { default as Link } from "./components/Link"; export type { LinkProps } from "./components/Link"; +export { default as FragmentLink } from "./components/Link/Fragment"; +export type { FragmentLinkProps } from "./components/Link/Fragment"; export { default as Modal } from "./components/Modal"; export type { ModalProps, ModalActionProps } from "./components/Modal"; diff --git a/packages/kitchen/src/next/components/Link/Fragment/index.tsx b/packages/kitchen/src/next/components/Link/Fragment/index.tsx deleted file mode 100644 index 358ca8c4e..000000000 --- a/packages/kitchen/src/next/components/Link/Fragment/index.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from "react"; -import styled from "styled-components"; - -import Link, { LinkProps } from ".."; - -export type FragmentLinkProps = LinkProps & { - /** - * The link's id. - */ - id: string; -}; - -const FragmentLink = styled(({ id, ...props }: FragmentLinkProps) => { - const href = `#${id}`; - return <Link id={id} href={href} {...props} />; -})``; - -export default FragmentLink; diff --git a/packages/kitchen/src/next/components/Link/index.tsx b/packages/kitchen/src/next/components/Link/index.tsx deleted file mode 100644 index a47f9e55b..000000000 --- a/packages/kitchen/src/next/components/Link/index.tsx +++ /dev/null @@ -1,167 +0,0 @@ -import NextLink from "next/link"; -import React from "react"; -import styled from "styled-components"; -import { UrlObject } from "url"; - -import { KitchenComponent } from "../../../types"; -import isString from "../../../utils/isString"; - -export type Props = { - /** - * The link's href. - */ - href?: string | UrlObject; - - /** - * The link's locale. - */ - locale?: string; - - /** - * The link's classname. - */ - className?: string; - - /** - * The link's onClick. - */ - onClick?: (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void; - - /** - * The link's status (if it's disabled or not). - */ - disabled?: boolean; - - /** - * The link's variant. - */ - variant?: "highlight" | "primary" | "secondary" | "blend"; -}; - -export type LinkProps = KitchenComponent< - Props, - React.AnchorHTMLAttributes<HTMLAnchorElement> ->; - -const Link = styled( - ({ - as: Component = "a", - href, - locale, - className, - disabled, - onClick, - variant, - children, - ...props - }: LinkProps) => { - disabled = disabled || (!onClick && !href); - - const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => { - if (disabled) return event.preventDefault(); - if (onClick) onClick(event); - }; - - if (isString(href)) { - href = href as string; - // regex to check if the href is internal or external - - const internal = href.match(/^(\/(?!\/)[^#]*|#.*)$/); - if (!internal) { - return ( - <Component - href={href} - className={className} - target={"_blank"} - rel={"noopener noreferrer"} - onClick={handleClick} - {...props} - > - {children} - </Component> - ); - } - } - - if (href) { - return ( - <NextLink - href={href} - locale={locale} - className={className} - onClick={handleClick} - {...props} - > - {children} - </NextLink> - ); - } - - return ( - <Component - className={className} - onClick={handleClick} - href={href} - variant={variant} - {...props} - > - {children} - </Component> - ); - }, -)<LinkProps>` - box-sizing: border-box; - display: inline-flex; - font-size: ${({ theme }) => theme.size.normal}; - font-weight: ${({ theme, variant }) => - variant === "blend" ? theme.weight.medium : theme.weight.regular}; - text-decoration: none; - transition: opacity filter 0.2s ease-in-out; - 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") { - return theme.colors.accent.primary; - } else if (variant === "blend") { - return "inherit"; - } else if (variant === "secondary") { - return theme.colors.text.lighter; - } else { - return theme.colors.text.lightest; - } - }}; - - &:hover { - ${({ theme, disabled, variant, onClick, href }) => { - disabled = disabled || (!onClick && !href); - - return ` - cursor: ${disabled ? "default" : "pointer"}; - filter: ${ - (variant && variant !== "blend") || disabled - ? "none" - : "brightness(0.8)" - }; - ${ - 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};` - : "" - }; - `; - }} - } -`; - -export default Link; diff --git a/packages/kitchen/src/next/index.ts b/packages/kitchen/src/next/index.ts index 1e3f180c2..69530f130 100644 --- a/packages/kitchen/src/next/index.ts +++ b/packages/kitchen/src/next/index.ts @@ -1,9 +1,3 @@ export { default as KitchenDocument } from "./components/Document"; export { default as withKitchenConfig } from "./hoc/withKitchenConfig"; - -export { default as Link } from "./components/Link"; -export type { LinkProps } from "./components/Link"; - -export { default as FragmentLink } from "./components/Link/Fragment"; -export type { FragmentLinkProps } from "./components/Link/Fragment"; diff --git a/packages/kitchen/src/types/index.ts b/packages/kitchen/src/types/index.ts index a3737fce5..0fc15e780 100644 --- a/packages/kitchen/src/types/index.ts +++ b/packages/kitchen/src/types/index.ts @@ -1,5 +1,6 @@ export * from "./theme"; export * from "./styled-components"; +export * from "./window"; export type KitchenComponent<P, N = React.HTMLAttributes<any>> = { /** diff --git a/packages/kitchen/src/types/window.ts b/packages/kitchen/src/types/window.ts new file mode 100644 index 000000000..d16b6b111 --- /dev/null +++ b/packages/kitchen/src/types/window.ts @@ -0,0 +1,7 @@ +declare global { + interface Window { + next?: any; + } +} + +export type window = object; diff --git a/workshop/pages/link.tsx b/workshop/pages/link.tsx index ad55ec6c7..f4b969f2a 100644 --- a/workshop/pages/link.tsx +++ b/workshop/pages/link.tsx @@ -1,6 +1,10 @@ -import kitchen, { Container, Note, Text } from "@tonightpass/kitchen"; -import { FragmentLink, Link } from "@tonightpass/kitchen/next"; -import { NextPage } from "next"; +import kitchen, { + Container, + Link, + Note, + Text, + FragmentLink, +} from "@tonightpass/kitchen"; import { useRouter } from "next/router"; const LinkPage: NextPage = () => { diff --git a/workshop/pages/template.tsx b/workshop/pages/template.tsx index df351b9ac..9363b1d36 100644 --- a/workshop/pages/template.tsx +++ b/workshop/pages/template.tsx @@ -3,9 +3,9 @@ import kitchen, { convertRGBToRGBA, Image, Text, + Link, rotate, } from "@tonightpass/kitchen"; -import { Link } from "@tonightpass/kitchen/next"; const TemplatePage = () => { return (