feat(link): stories improved

This commit is contained in:
Junior Garcia 2023-01-11 23:38:03 -03:00
parent 9402955299
commit 97451ae514
19 changed files with 3931 additions and 2929 deletions

View File

@ -1,6 +1,5 @@
import {mergeProps} from "@react-aria/utils";
import {forwardRef} from "@nextui-org/system";
import {link, twMerge} from "@nextui-org/theme";
import {__DEV__} from "@nextui-org/shared-utils";
import {UseLinkProps, useLink} from "./use-link";
@ -11,35 +10,17 @@ export interface LinkProps extends UseLinkProps {}
const Link = forwardRef<LinkProps, "a">((props, ref) => {
const {
as,
color,
size,
domRef,
classes,
children,
isUnderline,
isBlock,
isDisabled,
disableAnimation,
showAnchorIcon,
anchorIcon = <LinkIcon />,
linkProps,
className,
...otherProps
} = useLink({...props, ref});
const Component = as || "a";
const classes = twMerge(
link({
color,
size,
isUnderline,
isBlock,
isDisabled,
disableAnimation,
className,
}),
);
return (
<Component ref={domRef} className={classes} {...mergeProps(linkProps, otherProps)}>
<>

View File

@ -2,9 +2,11 @@ import type {AriaLinkProps} from "@react-types/link";
import type {LinkVariantProps} from "@nextui-org/theme";
import {useLink as useAriaLink} from "@react-aria/link";
import {link, twMerge} from "@nextui-org/theme";
import {HTMLNextUIProps} from "@nextui-org/system";
import {useDOMRef} from "@nextui-org/dom-utils";
import {ReactRef} from "@nextui-org/shared-utils";
import {useMemo} from "react";
export interface Props extends HTMLNextUIProps<"a">, LinkVariantProps {
/**
@ -39,9 +41,15 @@ export function useLink(props: UseLinkProps) {
const {
ref,
as = "a",
color,
size,
isUnderline,
isBlock,
disableAnimation,
isExternal = false,
showAnchorIcon = false,
isDisabled = false,
className,
...otherProps
} = props;
@ -54,7 +62,23 @@ export function useLink(props: UseLinkProps) {
otherProps.target = otherProps.target ?? "_blank";
}
return {as, domRef, linkProps, showAnchorIcon, isDisabled, ...otherProps};
const classes = useMemo(
() =>
twMerge(
link({
color,
size,
isUnderline,
isBlock,
isDisabled,
disableAnimation,
}),
className,
),
[color, size, isUnderline, isBlock, isDisabled, disableAnimation, className],
);
return {as, classes, domRef, linkProps, showAnchorIcon, isDisabled, ...otherProps};
}
export type UseLinkReturn = ReturnType<typeof useLink>;

View File

@ -1,164 +1,114 @@
import React from "react";
import {cva, linkVariants, type VariantProps, ExtendVariantProps} from "@nextui-org/theme";
// import {cva, linkVariants, type VariantProps, ExtendVariantProps} from "@nextui-org/theme";
import {Link, LinkProps} from "../src";
export default {
title: "Navigation/Link",
component: Link,
argTypes: {
color: {
control: {
type: "radio",
options: ["foreground", "primary", "secondary", "success", "warning", "error"],
},
},
size: {
control: {
type: "radio",
options: ["xs", "sm", "md", "xl"],
},
},
isDisabled: {
control: {
type: "boolean",
},
},
},
};
const text = `"First solve the problem. Then, write the code." - Jon Johnson.`;
export const Default = () => <Link href="#">{text}</Link>;
export const isDisabled = () => (
<Link isDisabled href="#">
const Template = (args: LinkProps) => (
<Link {...args} href="#">
{text}
</Link>
);
const customLink = cva(null, {
variants: {
color: {
...linkVariants.color,
teal: "text-teal-600",
},
link: {
true: "before:content-['👉'] before:mr-1",
},
},
});
type MyLinkProps = ExtendVariantProps<LinkProps, VariantProps<typeof customLink>>;
const MyLink = (props: MyLinkProps) => {
const {link, color, ...otherProps} = props;
return <Link {...otherProps} className={customLink({color, link})} isExternal={!!link} />;
export const Default = Template.bind({}) as any;
Default.args = {
isDisabled: false,
color: "foreground",
size: "md",
};
export const CustomVariant = () => {
return (
<MyLink link color="teal" href="#">
Visit out new Store
</MyLink>
);
export const isUnderline = Template.bind({}) as any;
isUnderline.args = {
isUnderline: true,
isDisabled: false,
size: "md",
};
export const Sizes = () => (
<div className="flex flex-col space-y-2">
<Link color="primary" href="#" size="xs">
{text}
</Link>
<Link color="secondary" href="#" size="sm">
{text}
</Link>
<Link color="success" href="#" size="md">
{text}
</Link>
<Link color="warning" href="#" size="xl">
{text}
</Link>
<Link className="text-2xl" color="error" href="#">
{text}
</Link>
<Link className="text-2xl text-pink-500" href="#">
{text}
</Link>
</div>
const CustomLink = () => (
<svg
className="custom-link-icon ml-1"
fill="none"
height="1em"
shapeRendering="geometricPrecision"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
width="1em"
>
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" />
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
</svg>
);
export const Colors = () => (
<div className="flex flex-col space-y-2">
<Link color="foreground" href="#">
{text}
</Link>
<Link color="primary" href="#">
{text}
</Link>
<Link color="secondary" href="#">
{text}
</Link>
<Link color="success" href="#">
{text}
</Link>
<Link color="warning" href="#">
{text}
</Link>
<Link color="error" href="#">
{text}
</Link>
<Link className="text-teal-600" href="#">
{text}
</Link>
</div>
);
export const isUnderline = () => (
<Link isUnderline color="primary" href="#">
{text}
</Link>
);
export const isExternal = () => {
const CustomLink = () => {
return (
<svg
className="custom-link-icon ml-1"
fill="none"
height="1em"
shapeRendering="geometricPrecision"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
width="1em"
>
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" />
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
</svg>
);
};
return (
<div className="flex flex-col space-y-2">
<Link isExternal showAnchorIcon href="#">
{text}
</Link>
<Link isExternal showAnchorIcon color="secondary" href="#">
{text}
</Link>
<Link isExternal showAnchorIcon anchorIcon={<CustomLink />} color="success" href="#">
{text}
</Link>
</div>
);
export const isExternal = Template.bind({}) as any;
isExternal.args = {
isExternal: true,
isDisabled: false,
showAnchorIcon: true,
size: "md",
anchorIcon: <CustomLink />,
};
export const isBlock = () => (
<div className="flex flex-col space-y-2">
<Link isBlock color="foreground" href="#">
{text}
</Link>
<Link isBlock color="primary" href="#">
{text}
</Link>
<Link isBlock color="secondary" href="#">
{text}
</Link>
<Link isBlock color="success" href="#">
{text}
</Link>
<Link isBlock color="warning" href="#">
{text}
</Link>
<Link isBlock color="error" href="#">
{text}
</Link>
<Link isBlock className="text-pink-500 hover:after:bg-pink-500/25" href="#">
{text}
</Link>
</div>
);
export const isBlock = Template.bind({}) as any;
isBlock.args = {
isBlock: true,
isDisabled: false,
size: "md",
color: "secondary",
};
// const customLink = cva(null, {
// variants: {
// color: {
// ...linkVariants.color,
// teal: "text-teal-600",
// },
// link: {
// true: "before:content-['👉'] before:mr-1",
// },
// },
// });
// type MyLinkProps = ExtendVariantProps<LinkProps, VariantProps<typeof customLink>>;
// const MyLink = (props: MyLinkProps) => {
// const {link, color, ...otherProps} = props;
// return <Link {...otherProps} className={customLink({color, link})} isExternal={!!link} />;
// };
// export const CustomVariant = () => {
// return (
// <MyLink link color="teal" href="#">
// Visit out new Store
// </MyLink>
// );
// };

View File

@ -1,29 +1,29 @@
module.exports = {
stories: ["../../link/stories/*.stories.@(js|jsx|ts|tsx)"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/preset-create-react-app",
"@storybook/addon-interactions",
"storybook-dark-mode"
],
framework: {
name: "@storybook/react-webpack5",
options: {},
},
docs: {
docsPage: true,
},
typescript: {
reactDocgen: "none",
},
babel: async (options) => {
return {
...options,
presets: [...options.presets,[ "@babel/preset-react", {
runtime: 'automatic',
}], "@babel/preset-typescript"],
};
},
staticDirs: ["../public"],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'storybook-dark-mode',
'@storybook/addon-a11y',
'@storybook/addon-storysource',
{
name: '@storybook/addon-postcss',
options: {
cssLoaderOptions: {
// When you have splitted your css over multiple files
// and use @import('./other-styles.css')
importLoaders: 1,
},
postcssLoaderOptions: {
// When using postCSS 8
implementation: require('postcss'),
},
},
},
],
framework: '@storybook/react',
core: {
builder: 'webpack5',
},
};

View File

@ -1,7 +0,0 @@
import {addons} from "@storybook/addons";
import theme from "./theme";
addons.setConfig({
theme,
});

View File

@ -1 +0,0 @@
<link href="/tailwind.css" rel="stylesheet" />

View File

@ -1,4 +1,14 @@
import {DEFAULT_THEME, withTailwindTheme} from "./withTailwindTheme.decorator";
import {themes} from "@storybook/theming";
import Style from "./style";
export const decorators = [
(Story) => (
<div className="bg-dark">
<Style />
<Story />
</div>
),
];
export const parameters = {
actions: {argTypesRegex: "^on[A-Z].*"},
@ -8,24 +18,21 @@ export const parameters = {
date: /Date$/,
},
},
};
export const globalTypes = {
theme: {
name: "Theme",
description: "Global theme for components",
defaultValue: DEFAULT_THEME,
toolbar: {
icon: "paintbrush",
// Array of plain string values or MenuItem shape (see below)
items: [
{value: "light", title: "Light", left: "🌞"},
{value: "dark", title: "Dark", left: "🌛"},
],
// Change title based on selected value
dynamicTitle: true,
darkMode: {
current: "dark",
darkClass: "dark",
stylePreview: true,
dark: {
...themes.dark,
appBg: "#161616",
barBg: "black",
background: "black",
appContentBg: "black",
appBorderRadius: 14,
},
light: {
...themes.light,
appBorderRadius: 14
}
},
};
export const decorators = [withTailwindTheme];

View File

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@ -0,0 +1,7 @@
import './style.css';
function Style() {
return <div />;
}
export default Style;

View File

@ -1,26 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
html[data-mode="light"] {
@apply bg-white text-black;
}
html[data-mode="dark"] {
@apply bg-black text-white;
}
body {
margin: 0;
font-size: 16px;
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,9 +0,0 @@
import {create} from "@storybook/theming";
export default create({
base: "light",
brandTitle: "NextUI",
brandUrl: "https://nextui.org",
brandTarget: "_self",
brandImage: 'https://nextui.org/logotipo.svg',
});

View File

@ -1,17 +0,0 @@
import React, {useEffect} from "react";
export const DEFAULT_THEME = "light";
export const withTailwindTheme = (Story, context) => {
const {theme} = context.globals;
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
const htmlTag = document.documentElement;
// Set the "data-mode" attribute on the iFrame html tag
htmlTag.setAttribute("data-mode", theme || DEFAULT_THEME);
}, [theme]);
return <Story />;
};

View File

@ -25,41 +25,33 @@
"url": "https://github.com/nextui-org/nextui/issues"
},
"scripts": {
"storybook": "concurrently \"pnpm:watch:*\"",
"build-storybook": "concurrently \"pnpm:build:*\"",
"start-storybook": "pnpx serve storybook-static",
"build:css": "npx tailwindcss -i ./.storybook/tailwind.css -o ./public/tailwind.css",
"build:storybook": "storybook build",
"watch:css": "npx tailwindcss -i ./.storybook/tailwind.css -o ./public/tailwind.css --watch",
"watch:storybook": "storybook dev -p 6006"
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook -o storybook-static",
"start-storybook": "pnpx serve storybook-static"
},
"devDependencies": {
"@storybook/addon-a11y": "^6.5.13",
"@storybook/addon-actions": "^6.5.13",
"@storybook/addon-storysource": "^6.5.13",
"@storybook/addon-essentials": "^7.0.0-beta.20",
"@storybook/addon-interactions": "^7.0.0-beta.20",
"@storybook/addon-links": "^7.0.0-beta.20",
"@storybook/blocks": "^7.0.0-beta.20",
"@storybook/node-logger": "^7.0.0-beta.20",
"@storybook/preset-create-react-app": "^4.1.2",
"@storybook/react-webpack5": "^7.0.0-beta.20",
"@storybook/testing-library": "^0.0.14-next.1",
"@nextui-org/theme": "workspace:*",
"@babel/core": "^7.16.7",
"@babel/preset-env": "^7.14.5",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.14.5",
"babel-loader": "^8.2.3",
"postcss": "^8.0.9",
"@storybook/addon-a11y": "^6.5.12",
"@storybook/addon-actions": "^6.5.12",
"@storybook/addon-docs": "^6.5.10",
"@storybook/addon-essentials": "^6.5.12",
"@storybook/addon-interactions": "^6.5.10",
"@storybook/addon-links": "^6.5.12",
"@storybook/addon-postcss": "^2.0.0",
"@storybook/addon-storysource": "^6.5.12",
"@storybook/addons": "^6.5.10",
"@storybook/builder-webpack5": "^6.5.12",
"@storybook/manager-webpack5": "^6.5.12",
"@storybook/react": "^6.5.12",
"@storybook/theming": "^6.5.15",
"autoprefixer": "^10.4.13",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"prop-types": "^15.8.1",
"storybook": "^7.0.0-beta.20",
"concurrently": "^7.6.0",
"storybook-dark-mode": "^2.0.5",
"tailwindcss": "^3.2.4",
"webpack": "^5.75.0"
"babel-loader": "^8.2.3",
"postcss": "^8.4.21",
"storybook-dark-mode": "^1.1.2",
"tailwindcss": "^3.2.4"
},
"tsup": {
"clean": true,

View File

@ -2,5 +2,5 @@ module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}
},
};

View File

@ -1,8 +1,6 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["../**/src/**/*.{js,jsx,ts,tsx}"],
// Toggle dark-mode based on data-mode="dark"
darkMode: ["class", '[data-mode="dark"]'],
theme: {
extend: {},
},

View File

@ -52,7 +52,7 @@ export declare namespace ConfigType {
// stitches types
export type StitchesConfig = typeof config;
export type VariantProps<T> = Stitches.VariantProps<T>;
export type VariantProps<T extends {[key: symbol | string]: any}> = Stitches.VariantProps<T>;
export type PropertyValue<T extends keyof Stitches.CSSProperties> = Stitches.PropertyValue<T>;
export type ScaleValue<T> = Stitches.ScaleValue<T>;
export type CSSProperties = Stitches.CSSProperties;
@ -106,7 +106,7 @@ export type NextUIThemeContext = {
};
// tokens types
export type TokenKeyName = keyof typeof commonTheme["theme"];
export type TokenKeyName = keyof (typeof commonTheme)["theme"];
export interface TokenValue {
token: number | string;

View File

@ -44,6 +44,7 @@
"postpack": "clean-package restore"
},
"devDependencies": {
"@storybook/addon-storysource": "^6.5.12",
"clean-package": "2.1.1",
"tailwindcss": "^3.2.4"
},

View File

@ -1,3 +1,3 @@
export {twMerge} from "tailwind-merge";
export {cva, cx} from "class-variance-authority";
export {twMerge} from "tailwind-merge";
export * from "class-variance-authority";

6353
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff