diff --git a/.gitea/pull_request_template.md b/.gitea/pull_request_template.md new file mode 100644 index 0000000..53a925b --- /dev/null +++ b/.gitea/pull_request_template.md @@ -0,0 +1,28 @@ +# [PR Title] + +## Overview + +Brief description of what this PR does and why. +Mention any context, background, or goals. + +## Changes + +- High-level summary of key changes +- List of components, features, or files added/modified +- Reference design tokens, breakpoints, or accessibility improvements if relevant + +## Screenshots + + + +## How to Test + +1. Steps to run locally or in Storybook +2. List what to verify (e.g., responsive layout, accessibility, functional links) +3. Include breakpoints, browsers, or devices if relevant + +## Notes + +- Any future follow-ups, TODOs, or known limitations +- Temporary setups or workarounds (e.g., personal deployments, placeholder assets) +- External dependencies (e.g., design tokens, API connections) diff --git a/.gitignore b/.gitignore index a46e550..9cf2b15 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,7 @@ next-env.d.ts *storybook.log storybook-static + +# storybook config files (to avoid git changes when switching between local and production) +.storybook/main.js +.storybook/preview.js diff --git a/.storybook/main.github.js b/.storybook/main.github.js new file mode 100644 index 0000000..7afbb5d --- /dev/null +++ b/.storybook/main.github.js @@ -0,0 +1,35 @@ +/** @type { import('@storybook/nextjs-vite').StorybookConfig } */ +const config = { + stories: [ + "../stories/**/*.mdx", + "../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)", + ], + addons: [ + "@chromatic-com/storybook", + "@storybook/addon-docs", + "@storybook/addon-onboarding", + "@storybook/addon-a11y", + "@storybook/addon-vitest", + ], + framework: { + name: "@storybook/nextjs-vite", + options: {}, + }, + staticDirs: ["../public"], + managerHead: (head) => `${head}`, + previewHead: (head) => `${head}`, + async viteFinal(cfg) { + // IMPORTANT: Set base path for GitHub Pages sub-path hosting + cfg.base = "/communityrulestorybook/"; + // Ensure esbuild treats .js as JSX during dep pre-bundling + cfg.optimizeDeps ??= {}; + cfg.optimizeDeps.esbuildOptions ??= {}; + cfg.optimizeDeps.esbuildOptions.loader = { + ...(cfg.optimizeDeps.esbuildOptions.loader || {}), + ".js": "jsx", + ".ts": "tsx", + }; + return cfg; + }, +}; +export default config; diff --git a/.storybook/main.js b/.storybook/main.js index 6e3993d..7afbb5d 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -16,7 +16,11 @@ const config = { options: {}, }, staticDirs: ["../public"], + managerHead: (head) => `${head}`, + previewHead: (head) => `${head}`, async viteFinal(cfg) { + // IMPORTANT: Set base path for GitHub Pages sub-path hosting + cfg.base = "/communityrulestorybook/"; // Ensure esbuild treats .js as JSX during dep pre-bundling cfg.optimizeDeps ??= {}; cfg.optimizeDeps.esbuildOptions ??= {}; diff --git a/.storybook/main.local.js b/.storybook/main.local.js new file mode 100644 index 0000000..6e3993d --- /dev/null +++ b/.storybook/main.local.js @@ -0,0 +1,31 @@ +/** @type { import('@storybook/nextjs-vite').StorybookConfig } */ +const config = { + stories: [ + "../stories/**/*.mdx", + "../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)", + ], + addons: [ + "@chromatic-com/storybook", + "@storybook/addon-docs", + "@storybook/addon-onboarding", + "@storybook/addon-a11y", + "@storybook/addon-vitest", + ], + framework: { + name: "@storybook/nextjs-vite", + options: {}, + }, + staticDirs: ["../public"], + async viteFinal(cfg) { + // Ensure esbuild treats .js as JSX during dep pre-bundling + cfg.optimizeDeps ??= {}; + cfg.optimizeDeps.esbuildOptions ??= {}; + cfg.optimizeDeps.esbuildOptions.loader = { + ...(cfg.optimizeDeps.esbuildOptions.loader || {}), + ".js": "jsx", + ".ts": "tsx", + }; + return cfg; + }, +}; +export default config; diff --git a/.storybook/preview.github.js b/.storybook/preview.github.js new file mode 100644 index 0000000..1fd25df --- /dev/null +++ b/.storybook/preview.github.js @@ -0,0 +1,16 @@ +import "../app/globals.css"; + +/** @type { import('@storybook/react').Preview } */ +const preview = { + parameters: { + actions: { argTypesRegex: "^on[A-Z].*" }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +}; + +export default preview; diff --git a/.storybook/preview.js b/.storybook/preview.js index bd769ce..1fd25df 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,62 +1,15 @@ import "../app/globals.css"; -/** @type { import('@storybook/nextjs-vite').Preview } */ +/** @type { import('@storybook/react').Preview } */ const preview = { parameters: { - nextjs: { appDirectory: true }, + actions: { argTypesRegex: "^on[A-Z].*" }, controls: { matchers: { color: /(background|color)$/i, date: /Date$/i, }, }, - - a11y: { - // 'todo' - show a11y violations in the test UI only - // 'error' - fail CI on a11y violations - // 'off' - skip a11y checks entirely - test: "todo", - }, - - backgrounds: { - default: "dark", - values: [ - { - name: "dark", - value: "#000000", - }, - { - name: "light", - value: "#ffffff", - }, - ], - }, - - viewport: { - defaultViewport: "md", - viewports: { - xsm: { - name: "XSmall (≤429px)", - styles: { width: "429px", height: "800px" }, - }, - sm: { - name: "Small (≥430px)", - styles: { width: "430px", height: "800px" }, - }, - md: { - name: "Medium (≥640px)", - styles: { width: "640px", height: "800px" }, - }, - lg: { - name: "Large (≥1024px)", - styles: { width: "1024px", height: "800px" }, - }, - xl: { - name: "XLarge (≥1440px)", - styles: { width: "1440px", height: "900px" }, - }, - }, - }, }, }; diff --git a/.storybook/preview.local.js b/.storybook/preview.local.js new file mode 100644 index 0000000..1fd25df --- /dev/null +++ b/.storybook/preview.local.js @@ -0,0 +1,16 @@ +import "../app/globals.css"; + +/** @type { import('@storybook/react').Preview } */ +const preview = { + parameters: { + actions: { argTypesRegex: "^on[A-Z].*" }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +}; + +export default preview; diff --git a/README.md b/README.md index 66bb426..b70ece1 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,79 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). +# Community Rule + +A Next.js application for community decision-making and governance documentation. ## Getting Started -First, run the development server: +Run the development server: ```bash npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file. +## Storybook Development -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. +This project includes Storybook for component development and documentation. The setup supports both local development and GitHub Pages deployment. -## Learn More +### Local Development -To learn more about Next.js, take a look at the following resources: +For local Storybook development (no base path): -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +```bash +npm run storybook:local +``` -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +This will: -## Deploy on Vercel +- Copy local configuration files (without GitHub Pages base path) +- Start Storybook at `http://localhost:6006` +- Ignore configuration changes in git -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. +### Production Deployment -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +When ready to deploy to GitHub Pages: + +1. **Restore GitHub Pages configuration:** + + ```bash + npm run storybook:restore + ``` + +2. **Build Storybook:** + + ```bash + npm run build-storybook + ``` + +3. **Deploy to GitHub Pages repository:** + + ```bash + # Copy the build to your GitHub Pages repository + cp -r storybook-static/* /path/to/communityrulestorybook/ + + # Or if you have it as a git submodule: + cp -r storybook-static/* communityrulestorybook/ + cd communityrulestorybook + git add . + git commit -m "Update Storybook build" + git push origin main + ``` + +### Switching Between Configurations + +- **Local Development:** `npm run storybook:local` +- **Production Build:** `npm run storybook:restore` then `npm run build-storybook` +- **Back to Local:** `npm run storybook:local` + +The gitignore is configured to prevent configuration file changes from triggering git changes during local development. + +### Available Scripts + +- `npm run dev` - Start Next.js development server +- `npm run build` - Build Next.js application for production +- `npm run start` - Start Next.js production server +- `npm run storybook:local` - Start Storybook with local configuration +- `npm run storybook:restore` - Restore GitHub Pages configuration +- `npm run build-storybook` - Build Storybook for production +- `npm run storybook` - Start Storybook with current configuration diff --git a/app/components/Button.js b/app/components/Button.js index bfc2dc1..2324ee2 100644 --- a/app/components/Button.js +++ b/app/components/Button.js @@ -25,16 +25,11 @@ export default function Button({ }; const fontStyles = { - xsmall: - "font-['Inter'] text-[10px] leading-[12px] font-medium tracking-[0%]", - small: - "font-['Inter'] text-[12px] leading-[14px] font-medium tracking-[0%]", - medium: - "font-['Inter'] text-[14px] leading-[16px] font-medium tracking-[0%]", - large: - "font-['Inter'] text-[16px] leading-[20px] font-medium tracking-[0%]", - xlarge: - "font-['Inter'] text-[24px] leading-[28px] font-normal tracking-[0%]", + xsmall: "font-inter text-[10px] leading-[12px] font-medium tracking-[0%]", + small: "font-inter text-[12px] leading-[14px] font-medium tracking-[0%]", + medium: "font-inter text-[14px] leading-[16px] font-medium tracking-[0%]", + large: "font-inter text-[16px] leading-[20px] font-medium tracking-[0%]", + xlarge: "font-inter text-[24px] leading-[28px] font-normal tracking-[0%]", }; const variantStyles = { diff --git a/app/components/ContentLockup.js b/app/components/ContentLockup.js new file mode 100644 index 0000000..b544105 --- /dev/null +++ b/app/components/ContentLockup.js @@ -0,0 +1,68 @@ +"use client"; + +import Button from "./Button"; + +const ContentLockup = ({ + title, + subtitle, + description, + ctaText, + ctaHref, + buttonClassName = "", +}) => { + return ( +
+ {/* Text content container */} +
+ {/* Title and subtitle group - no gap between them at xl */} +
+ {/* Title container */} +
+

+ {title} +

+ Decorative shapes +
+ + {/* Subtitle */} +

+ {subtitle} +

+
+ + {/* Description - 20px gap from subtitle at xl */} +

+ {description} +

+
+ + {/* CTA Button */} +
+ {/* Small button for xsm and sm breakpoints */} +
+ +
+ {/* Large button for md and lg breakpoints */} +
+ +
+ {/* XLarge button for xl breakpoint */} +
+ +
+
+
+ ); +}; + +export default ContentLockup; diff --git a/app/components/Footer.js b/app/components/Footer.js index cc7b60d..e98da53 100644 --- a/app/components/Footer.js +++ b/app/components/Footer.js @@ -23,7 +23,7 @@ export default function Footer() { />