ecomlab-components-next 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +36 -0
  2. package/package.json +49 -0
  3. package/src/app/favicon.ico +0 -0
  4. package/src/app/globals.css +42 -0
  5. package/src/app/layout.js +27 -0
  6. package/src/app/page.js +95 -0
  7. package/src/app/page.module.css +168 -0
  8. package/src/components/Button.js +14 -0
  9. package/src/components/Button.module.scss +18 -0
  10. package/src/components/Button.stories.js +24 -0
  11. package/src/index.js +1 -0
  12. package/src/stories/Button.jsx +44 -0
  13. package/src/stories/Button.stories.js +49 -0
  14. package/src/stories/Configure.mdx +446 -0
  15. package/src/stories/Header.jsx +60 -0
  16. package/src/stories/Header.stories.js +30 -0
  17. package/src/stories/Page.jsx +68 -0
  18. package/src/stories/Page.stories.js +28 -0
  19. package/src/stories/assets/accessibility.png +0 -0
  20. package/src/stories/assets/accessibility.svg +1 -0
  21. package/src/stories/assets/addon-library.png +0 -0
  22. package/src/stories/assets/assets.png +0 -0
  23. package/src/stories/assets/avif-test-image.avif +0 -0
  24. package/src/stories/assets/context.png +0 -0
  25. package/src/stories/assets/discord.svg +1 -0
  26. package/src/stories/assets/docs.png +0 -0
  27. package/src/stories/assets/figma-plugin.png +0 -0
  28. package/src/stories/assets/github.svg +1 -0
  29. package/src/stories/assets/share.png +0 -0
  30. package/src/stories/assets/styling.png +0 -0
  31. package/src/stories/assets/testing.png +0 -0
  32. package/src/stories/assets/theming.png +0 -0
  33. package/src/stories/assets/tutorials.svg +1 -0
  34. package/src/stories/assets/youtube.svg +1 -0
  35. package/src/stories/button.css +30 -0
  36. package/src/stories/header.css +32 -0
  37. package/src/stories/page.css +68 -0
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
2
+
3
+ ## Getting Started
4
+
5
+ First, run the development server:
6
+
7
+ ```bash
8
+ npm run dev
9
+ # or
10
+ yarn dev
11
+ # or
12
+ pnpm dev
13
+ # or
14
+ bun dev
15
+ ```
16
+
17
+ Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18
+
19
+ You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
20
+
21
+ This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
22
+
23
+ ## Learn More
24
+
25
+ To learn more about Next.js, take a look at the following resources:
26
+
27
+ - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28
+ - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29
+
30
+ You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
31
+
32
+ ## Deploy on Vercel
33
+
34
+ The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35
+
36
+ Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "ecomlab-components-next",
3
+ "version": "0.1.0",
4
+ "description": "A set of common and reusable React components",
5
+ "main": "build/index.js",
6
+ "files": [
7
+ "build",
8
+ "src"
9
+ ],
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "scripts": {
14
+ "dev": "next dev",
15
+ "build": "next build",
16
+ "start": "next start",
17
+ "lint": "next lint",
18
+ "storybook": "storybook dev -p 6006",
19
+ "build-storybook": "storybook build"
20
+ },
21
+ "dependencies": {
22
+ "@types/styled-components": "^5.1.34",
23
+ "next": "15.1.5",
24
+ "react": "^19.0.0",
25
+ "react-dom": "^19.0.0",
26
+ "styled-components": "^6.1.14",
27
+ "sass": "^1.55.0"
28
+ },
29
+ "devDependencies": {
30
+ "@chromatic-com/storybook": "^3.2.4",
31
+ "@eslint/eslintrc": "^3",
32
+ "@storybook/addon-essentials": "^8.5.0",
33
+ "@storybook/addon-interactions": "^8.5.0",
34
+ "@storybook/addon-onboarding": "^8.5.0",
35
+ "@storybook/blocks": "^8.5.0",
36
+ "@storybook/nextjs": "^8.5.0",
37
+ "@storybook/react": "^8.5.0",
38
+ "@storybook/test": "^8.5.0",
39
+ "eslint": "^9",
40
+ "eslint-config-next": "15.1.5",
41
+ "eslint-plugin-storybook": "^0.11.2",
42
+ "storybook": "^8.5.0"
43
+ },
44
+ "eslintConfig": {
45
+ "extends": [
46
+ "plugin:storybook/recommended"
47
+ ]
48
+ }
49
+ }
Binary file
@@ -0,0 +1,42 @@
1
+ :root {
2
+ --background: #ffffff;
3
+ --foreground: #171717;
4
+ }
5
+
6
+ @media (prefers-color-scheme: dark) {
7
+ :root {
8
+ --background: #0a0a0a;
9
+ --foreground: #ededed;
10
+ }
11
+ }
12
+
13
+ html,
14
+ body {
15
+ max-width: 100vw;
16
+ overflow-x: hidden;
17
+ }
18
+
19
+ body {
20
+ color: var(--foreground);
21
+ background: var(--background);
22
+ font-family: Arial, Helvetica, sans-serif;
23
+ -webkit-font-smoothing: antialiased;
24
+ -moz-osx-font-smoothing: grayscale;
25
+ }
26
+
27
+ * {
28
+ box-sizing: border-box;
29
+ padding: 0;
30
+ margin: 0;
31
+ }
32
+
33
+ a {
34
+ color: inherit;
35
+ text-decoration: none;
36
+ }
37
+
38
+ @media (prefers-color-scheme: dark) {
39
+ html {
40
+ color-scheme: dark;
41
+ }
42
+ }
@@ -0,0 +1,27 @@
1
+ import { Geist, Geist_Mono } from "next/font/google";
2
+ import "./globals.css";
3
+
4
+ const geistSans = Geist({
5
+ variable: "--font-geist-sans",
6
+ subsets: ["latin"],
7
+ });
8
+
9
+ const geistMono = Geist_Mono({
10
+ variable: "--font-geist-mono",
11
+ subsets: ["latin"],
12
+ });
13
+
14
+ export const metadata = {
15
+ title: "Create Next App",
16
+ description: "Generated by create next app",
17
+ };
18
+
19
+ export default function RootLayout({ children }) {
20
+ return (
21
+ <html lang="en">
22
+ <body className={`${geistSans.variable} ${geistMono.variable}`}>
23
+ {children}
24
+ </body>
25
+ </html>
26
+ );
27
+ }
@@ -0,0 +1,95 @@
1
+ import Image from "next/image";
2
+ import styles from "./page.module.css";
3
+
4
+ export default function Home() {
5
+ return (
6
+ <div className={styles.page}>
7
+ <main className={styles.main}>
8
+ <Image
9
+ className={styles.logo}
10
+ src="/next.svg"
11
+ alt="Next.js logo"
12
+ width={180}
13
+ height={38}
14
+ priority
15
+ />
16
+ <ol>
17
+ <li>
18
+ Get started by editing <code>src/app/page.js</code>.
19
+ </li>
20
+ <li>Save and see your changes instantly.</li>
21
+ </ol>
22
+
23
+ <div className={styles.ctas}>
24
+ <a
25
+ className={styles.primary}
26
+ href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
27
+ target="_blank"
28
+ rel="noopener noreferrer"
29
+ >
30
+ <Image
31
+ className={styles.logo}
32
+ src="/vercel.svg"
33
+ alt="Vercel logomark"
34
+ width={20}
35
+ height={20}
36
+ />
37
+ Deploy now
38
+ </a>
39
+ <a
40
+ href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
41
+ target="_blank"
42
+ rel="noopener noreferrer"
43
+ className={styles.secondary}
44
+ >
45
+ Read our docs
46
+ </a>
47
+ </div>
48
+ </main>
49
+ <footer className={styles.footer}>
50
+ <a
51
+ href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
52
+ target="_blank"
53
+ rel="noopener noreferrer"
54
+ >
55
+ <Image
56
+ aria-hidden
57
+ src="/file.svg"
58
+ alt="File icon"
59
+ width={16}
60
+ height={16}
61
+ />
62
+ Learn
63
+ </a>
64
+ <a
65
+ href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
66
+ target="_blank"
67
+ rel="noopener noreferrer"
68
+ >
69
+ <Image
70
+ aria-hidden
71
+ src="/window.svg"
72
+ alt="Window icon"
73
+ width={16}
74
+ height={16}
75
+ />
76
+ Examples
77
+ </a>
78
+ <a
79
+ href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
80
+ target="_blank"
81
+ rel="noopener noreferrer"
82
+ >
83
+ <Image
84
+ aria-hidden
85
+ src="/globe.svg"
86
+ alt="Globe icon"
87
+ width={16}
88
+ height={16}
89
+ />
90
+ Go to nextjs.org →
91
+ </a>
92
+ </footer>
93
+ </div>
94
+ );
95
+ }
@@ -0,0 +1,168 @@
1
+ .page {
2
+ --gray-rgb: 0, 0, 0;
3
+ --gray-alpha-200: rgba(var(--gray-rgb), 0.08);
4
+ --gray-alpha-100: rgba(var(--gray-rgb), 0.05);
5
+
6
+ --button-primary-hover: #383838;
7
+ --button-secondary-hover: #f2f2f2;
8
+
9
+ display: grid;
10
+ grid-template-rows: 20px 1fr 20px;
11
+ align-items: center;
12
+ justify-items: center;
13
+ min-height: 100svh;
14
+ padding: 80px;
15
+ gap: 64px;
16
+ font-family: var(--font-geist-sans);
17
+ }
18
+
19
+ @media (prefers-color-scheme: dark) {
20
+ .page {
21
+ --gray-rgb: 255, 255, 255;
22
+ --gray-alpha-200: rgba(var(--gray-rgb), 0.145);
23
+ --gray-alpha-100: rgba(var(--gray-rgb), 0.06);
24
+
25
+ --button-primary-hover: #ccc;
26
+ --button-secondary-hover: #1a1a1a;
27
+ }
28
+ }
29
+
30
+ .main {
31
+ display: flex;
32
+ flex-direction: column;
33
+ gap: 32px;
34
+ grid-row-start: 2;
35
+ }
36
+
37
+ .main ol {
38
+ font-family: var(--font-geist-mono);
39
+ padding-left: 0;
40
+ margin: 0;
41
+ font-size: 14px;
42
+ line-height: 24px;
43
+ letter-spacing: -0.01em;
44
+ list-style-position: inside;
45
+ }
46
+
47
+ .main li:not(:last-of-type) {
48
+ margin-bottom: 8px;
49
+ }
50
+
51
+ .main code {
52
+ font-family: inherit;
53
+ background: var(--gray-alpha-100);
54
+ padding: 2px 4px;
55
+ border-radius: 4px;
56
+ font-weight: 600;
57
+ }
58
+
59
+ .ctas {
60
+ display: flex;
61
+ gap: 16px;
62
+ }
63
+
64
+ .ctas a {
65
+ appearance: none;
66
+ border-radius: 128px;
67
+ height: 48px;
68
+ padding: 0 20px;
69
+ border: none;
70
+ border: 1px solid transparent;
71
+ transition:
72
+ background 0.2s,
73
+ color 0.2s,
74
+ border-color 0.2s;
75
+ cursor: pointer;
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ font-size: 16px;
80
+ line-height: 20px;
81
+ font-weight: 500;
82
+ }
83
+
84
+ a.primary {
85
+ background: var(--foreground);
86
+ color: var(--background);
87
+ gap: 8px;
88
+ }
89
+
90
+ a.secondary {
91
+ border-color: var(--gray-alpha-200);
92
+ min-width: 180px;
93
+ }
94
+
95
+ .footer {
96
+ grid-row-start: 3;
97
+ display: flex;
98
+ gap: 24px;
99
+ }
100
+
101
+ .footer a {
102
+ display: flex;
103
+ align-items: center;
104
+ gap: 8px;
105
+ }
106
+
107
+ .footer img {
108
+ flex-shrink: 0;
109
+ }
110
+
111
+ /* Enable hover only on non-touch devices */
112
+ @media (hover: hover) and (pointer: fine) {
113
+ a.primary:hover {
114
+ background: var(--button-primary-hover);
115
+ border-color: transparent;
116
+ }
117
+
118
+ a.secondary:hover {
119
+ background: var(--button-secondary-hover);
120
+ border-color: transparent;
121
+ }
122
+
123
+ .footer a:hover {
124
+ text-decoration: underline;
125
+ text-underline-offset: 4px;
126
+ }
127
+ }
128
+
129
+ @media (max-width: 600px) {
130
+ .page {
131
+ padding: 32px;
132
+ padding-bottom: 80px;
133
+ }
134
+
135
+ .main {
136
+ align-items: center;
137
+ }
138
+
139
+ .main ol {
140
+ text-align: center;
141
+ }
142
+
143
+ .ctas {
144
+ flex-direction: column;
145
+ }
146
+
147
+ .ctas a {
148
+ font-size: 14px;
149
+ height: 40px;
150
+ padding: 0 16px;
151
+ }
152
+
153
+ a.secondary {
154
+ min-width: auto;
155
+ }
156
+
157
+ .footer {
158
+ flex-wrap: wrap;
159
+ align-items: center;
160
+ justify-content: center;
161
+ }
162
+ }
163
+
164
+ @media (prefers-color-scheme: dark) {
165
+ .logo {
166
+ filter: invert();
167
+ }
168
+ }
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import styles from './Button.module.scss';
3
+
4
+ export default Button = ({ label, onClick, disabled = false, variant = 'primary' }) => {
5
+ return (
6
+ <button
7
+ className={`${styles.button} ${styles[variant]}`}
8
+ onClick={onClick}
9
+ disabled={disabled}
10
+ >
11
+ {label}
12
+ </button>
13
+ );
14
+ };
@@ -0,0 +1,18 @@
1
+ .button {
2
+ padding: 10px 20px;
3
+ font-size: 16px;
4
+ border: none;
5
+ cursor: pointer;
6
+ }
7
+
8
+ .primary {
9
+ background-color: #0070f3;
10
+ color: white;
11
+ }
12
+
13
+ .secondary {
14
+ background-color: white;
15
+ color: #0070f3;
16
+ border: 1px solid #0070f3;
17
+ }
18
+
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import { Button } from './Button';
3
+ import { ComponentMeta, ComponentStory } from '@storybook/react';
4
+
5
+ export default {
6
+ title: 'Components/Button',
7
+ component: Button,
8
+ }
9
+
10
+ const Template = (args) => <Button {...args} />;
11
+
12
+ export const Primary = Template.bind({});
13
+ Primary.args = {
14
+ label: 'Primary Button',
15
+ variant: 'primary',
16
+ onClick: () => alert('Clicked!'),
17
+ };
18
+
19
+ export const Secondary = Template.bind({});
20
+ Secondary.args = {
21
+ label: 'Secondary Button',
22
+ variant: 'secondary',
23
+ onClick: () => alert('Clicked!'),
24
+ };
package/src/index.js ADDED
@@ -0,0 +1 @@
1
+ export { default as Button } from './components/Button/Button'
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+
3
+ import PropTypes from 'prop-types';
4
+
5
+ import './button.css';
6
+
7
+ /** Primary UI component for user interaction */
8
+ export const Button = ({ primary, backgroundColor, size, label, ...props }) => {
9
+ const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
10
+ return (
11
+ <button
12
+ type="button"
13
+ className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
14
+ {...props}
15
+ >
16
+ {label}
17
+ <style jsx>{`
18
+ button {
19
+ background-color: ${backgroundColor};
20
+ }
21
+ `}</style>
22
+ </button>
23
+ );
24
+ };
25
+
26
+ Button.propTypes = {
27
+ /** Is this the principal call to action on the page? */
28
+ primary: PropTypes.bool,
29
+ /** What background color to use */
30
+ backgroundColor: PropTypes.string,
31
+ /** How large should the button be? */
32
+ size: PropTypes.oneOf(['small', 'medium', 'large']),
33
+ /** Button contents */
34
+ label: PropTypes.string.isRequired,
35
+ /** Optional click handler */
36
+ onClick: PropTypes.func,
37
+ };
38
+
39
+ Button.defaultProps = {
40
+ backgroundColor: null,
41
+ primary: false,
42
+ size: 'medium',
43
+ onClick: undefined,
44
+ };
@@ -0,0 +1,49 @@
1
+ import { fn } from '@storybook/test';
2
+
3
+ import { Button } from './Button';
4
+
5
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
6
+ export default {
7
+ title: 'Example/Button',
8
+ component: Button,
9
+ parameters: {
10
+ // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
11
+ layout: 'centered',
12
+ },
13
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
14
+ tags: ['autodocs'],
15
+ // More on argTypes: https://storybook.js.org/docs/api/argtypes
16
+ argTypes: {
17
+ backgroundColor: { control: 'color' },
18
+ },
19
+ // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
20
+ args: { onClick: fn() },
21
+ };
22
+
23
+ // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
24
+ export const Primary = {
25
+ args: {
26
+ primary: true,
27
+ label: 'Button',
28
+ },
29
+ };
30
+
31
+ export const Secondary = {
32
+ args: {
33
+ label: 'Button',
34
+ },
35
+ };
36
+
37
+ export const Large = {
38
+ args: {
39
+ size: 'large',
40
+ label: 'Button',
41
+ },
42
+ };
43
+
44
+ export const Small = {
45
+ args: {
46
+ size: 'small',
47
+ label: 'Button',
48
+ },
49
+ };