diff --git a/.changeset/neat-moons-tan.md b/.changeset/neat-moons-tan.md new file mode 100644 index 00000000..b97c8b1e --- /dev/null +++ b/.changeset/neat-moons-tan.md @@ -0,0 +1,15 @@ +--- +'@nordcom/nordstar-accented': patch +'@nordcom/nordstar-details': patch +'@nordcom/nordstar-heading': patch +'@nordcom/nordstar-button': patch +'@nordcom/nordstar-header': patch +'@nordcom/nordstar-input': patch +'@nordcom/nordstar-label': patch +'@nordcom/nordstar-card': patch +'@nordcom/nordstar-view': patch +'@nordcom/nordstar': patch +'@nordcom/nordstar-system': patch +--- + +- Refactor components to use tailwind and `cva`. diff --git a/.changeset/pink-eggs-float.md b/.changeset/pink-eggs-float.md new file mode 100644 index 00000000..554c967b --- /dev/null +++ b/.changeset/pink-eggs-float.md @@ -0,0 +1,17 @@ +--- +'@nordcom/nordstar-accented': patch +'@nordcom/nordstar-details': patch +'@nordcom/nordstar-heading': patch +'@nordcom/nordstar-button': patch +'@nordcom/nordstar-header': patch +'@nordcom/nordstar-input': patch +'@nordcom/nordstar-label': patch +'@nordcom/nordstar-card': patch +'@nordcom/nordstar-view': patch +'@nordcom/nordstar': patch +'@nordcom/nordstar-system': patch +'@nordcom/nordstar-storybook': patch +'@nordcom/nordstar-docs': patch +--- + +- Update domain to `https://nordstar.dev/` diff --git a/.eslintrc b/.eslintrc index 147304b1..557c4673 100644 --- a/.eslintrc +++ b/.eslintrc @@ -59,7 +59,15 @@ "prefer": "type-imports" } ], - "@typescript-eslint/no-require-imports": "error", + "@typescript-eslint/no-require-imports": [ + "error", + { + "allow": [ + "tailwindcss", + "autoprefixer" + ] + } + ], "@typescript-eslint/no-unnecessary-condition": "warn", "brace-style": [ "error", diff --git a/.hintrc b/.hintrc index e8a293f4..98c21b01 100644 --- a/.hintrc +++ b/.hintrc @@ -1,5 +1,13 @@ { "extends": ["development"], + "browserslist": [ + "defaults", + "not ie 11", + "not ie <= 10", + "not and_ff <= 119", + "not firefox <= 121", + "not opera <= 104" + ], "hints": { "typescript-config/is-valid": "off", "compat-api/css": [ @@ -10,9 +18,15 @@ "font-smooth", "overflow: clip", "overscroll-behavior", - "text-size-adjust" + "text-size-adjust", + "user-select" ] } - ] + ], + "no-inline-styles": "off", + "typescript-config/strict": "off", + "typescript-config/consistent-casing": "off", + "disown-opener": "off", + "manifest-is-valid": "off" } } diff --git a/.prettierignore b/.prettierignore index d8fa1abc..0658bc3c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,6 @@ # Ignore artifacts build +dist coverage node_modules .next diff --git a/.prettierrc.cjs b/.prettierrc.cjs new file mode 100644 index 00000000..c360f110 --- /dev/null +++ b/.prettierrc.cjs @@ -0,0 +1,9 @@ +const prettierConfig = require('@nordcom/prettier'); + +/** @type {import('prettier').Config} */ +module.exports = { + ...prettierConfig, + $schema: 'http://json.schemastore.org/prettierrc', + plugins: [...(prettierConfig.plugins || []), 'prettier-plugin-tailwindcss'], + quoteProps: 'consistent' +}; diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 4813c98b..fb9051a0 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -8,6 +8,7 @@ "formulahendry.auto-rename-tag", "jgclark.vscode-todo-highlight", "medo64.render-crlf", - "mikestead.dotenv" + "mikestead.dotenv", + "bradlc.vscode-tailwindcss" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 1cdad6d8..8c5949f8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -41,6 +41,7 @@ "cSpell.words": [ "Brandly", "compat", + "Docgen", "Filiph", "lockb", "Nordcom", @@ -52,6 +53,8 @@ "registrator", "Sandström", "Siitam", + "tailwindcss", + "testid", "treeshake", "tsbuildinfo", "typecheck", @@ -75,5 +78,23 @@ }, "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "tailwindCSS.classAttributes": ["class", "className", ".*ClassName", ".*Styles"], + "tailwindCSS.lint.invalidVariant": "warning", + "tailwindCSS.colorDecorators": true, + "tailwindCSS.experimental.classRegex": [ + "[a-zA-Z]*ClassName='([^']+)'", + "[a-zA-Z]*ClassName=\"([^\"]+)\"", + "[a-zA-Z]*ClassName={`([^`]+)`}", + ["Styles\\s*=\\s*([^;]*);", "'([^']*)'"], + ["Styles\\s*=\\s*([^;]*);", "\"([^\"]*)\""], + ["Styles\\s*=\\s*([^;]*);", "\\`([^\\`]*)\\`"], + ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"], + ["cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"] + ], + "tailwindCSS.includeLanguages": { + "html": "html", + "javascript": "javascript", + "css": "css" } } diff --git a/@types/declaration.d.ts b/@types/declaration.d.ts index 3a7fda42..a91c546b 100644 --- a/@types/declaration.d.ts +++ b/@types/declaration.d.ts @@ -16,3 +16,7 @@ declare module '*.scss' { const content: { [className: string]: string }; export = content; } + +declare module 'hex-to-hsl' { + export default function convert(input?: string): [number, number, number] | undefined; +} diff --git a/LICENSE b/LICENSE index 49b74e26..54d63b97 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ MIT License -Copyright (c) 2023 Nordcom Group Inc. +Copyright (c) 2023-2024 Nordcom AB +Copyright (c) 2023-2024 Filiph Sandström Copyright (c) 2020 Junior Garcia (Next UI) Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/SECURITY.md b/SECURITY.md index 8a6e5709..26865f4e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,6 +1,6 @@ # Security -Nordcom Group Inc. takes the security of its software extremely seriously. However, due to our size and being such a new and novel company, we do not accept and cannot offer any form of liability (legal or otherwise) as per the included license unless otherwise explicitly granted in writing. +Nordcom AB takes the security of its software extremely seriously. However, due to our size and being such a new and novel company, we do not accept and cannot offer any form of liability (legal or otherwise) as per the included license unless otherwise explicitly granted in writing. If you believe you have found a security flaw or vulnerability, If you believe you have found a security flaw or vulnerability, please report it to us following the instructions below. @@ -21,7 +21,7 @@ For any questions or need for clarification, feel free to reach out to us on ## Policy -**Nordcom Group Inc. is committed to the security of its software and the safety of its users.** +**Nordcom AB is committed to the security of its software and the safety of its users.** We will investigate all reported security vulnerabilities promptly and responsibly. We will prioritize and address vulnerabilities based on their severity and potential impact to our users. diff --git a/docs/.eslintrc b/docs/.eslintrc index 4ff338c2..0fd6bee7 100644 --- a/docs/.eslintrc +++ b/docs/.eslintrc @@ -1,24 +1,30 @@ { - "extends": ["../.eslintrc"], - "ignorePatterns": ["!**/*"], + "$schema": "https://json.schemastore.org/eslintrc.json", + "extends": ["next/core-web-vitals", "../.eslintrc"], + "ignorePatterns": [ "!**/*", "/*"], + "env": { + "browser": true, + "es2024": true, + "node": true + }, "overrides": [ { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "files": ["*.ts", "*.tsx", "*.mdx"], + "parser": "@typescript-eslint/parser", "parserOptions": { - "project": ["docs/tsconfig(.*)?.json"], "ecmaFeatures": { "jsx": true - } + }, + "sourceType": "module", + "ecmaVersion": "latest", + "project": ["./tsconfig.json", "./tsconfig.test.json"] }, "rules": {} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "rules": {} } - ] + ], + "settings": { + "next": { + "rootDir": "docs/" + } + } } diff --git a/docs/next.config.mjs b/docs/next.config.mjs index 94905330..4276672a 100644 --- a/docs/next.config.mjs +++ b/docs/next.config.mjs @@ -1,3 +1,15 @@ +import createVercelToolbar from '@vercel/toolbar/plugins/next'; + +const withVercelToolbar = createVercelToolbar(); + +export function getBaseUrl() { + if (process.env.VERCEL_ENV === 'production') { + return 'https://nordstar.dev'; + } + + return process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : undefined; +} + /** @type {import('next').NextConfig} */ let config = { poweredByHeader: false, @@ -6,13 +18,31 @@ let config = { swcMinify: true, productionBrowserSourceMaps: true, compress: true, + assetPrefix: getBaseUrl(), experimental: { - scrollRestoration: true, + appNavFailHandling: true, + caseSensitiveRoutes: true, + cssChunking: 'strict', esmExternals: true, - optimizePackageImports: [] + optimizePackageImports: [], + optimizeServerReact: true, + parallelServerBuildTraces: true, + parallelServerCompiles: true, + scrollRestoration: true, + serverComponentsHmrCache: true, + serverSourceMaps: true, + useEarlyImport: true, + webpackBuildWorker: true }, images: { + dangerouslyAllowSVG: true, + minimumCacheTTL: 60, + contentDispositionType: 'inline', remotePatterns: [ + { + protocol: 'https', + hostname: 'nordcom.io' + }, { protocol: 'https', hostname: '**.nordcom.io' @@ -20,12 +50,35 @@ let config = { { protocol: 'https', hostname: '**.github.io' + }, + { + protocol: 'https', + hostname: '**.gravatar.com' } - ] + ], + formats: ['image/webp', 'image/avif'] }, eslint: { ignoreDuringBuilds: true + }, + typescript: { + ignoreBuildErrors: true, + tsconfigPath: 'tsconfig.json' + }, + + async generateBuildId() { + return process.env.VERCEL_GIT_COMMIT_SHA || 'unknown'; + }, + + webpack(config, _context) { + return { + ...config, + experiments: { + ...config.experiments, + topLevelAwait: true + } + }; } }; -export default config; +export default withVercelToolbar(config); diff --git a/docs/package.json b/docs/package.json index 6dda4d5c..1c90b4f8 100644 --- a/docs/package.json +++ b/docs/package.json @@ -8,15 +8,18 @@ "cacheDirectories": [ ".next/cache" ], - "prettier": "@nordcom/prettier", "scripts": { "build": "next build", "dev": "next dev", "clean": "rm -rf dist coverage storybook-static .turbo .next *.tsbuildinfo *.log", "start": "next start -p $PORT", + "typecheck": "tsc --noEmit", "lint": "concurrently -i pnpm:lint:*", "lint:next": "next lint", - "lint:prettier": "prettier src/**/*.* --check" + "lint:prettier": "prettier --check \"./**/*.{ts,tsx}\"", + "fix": "concurrently -i pnpm:fix:*", + "fix:next": "next lint --fix", + "fix:prettier": "prettier --write \"./**/*.{cjs,mjs,ts,tsx,scss,json}\"" }, "keywords": [ "nordstar", @@ -24,7 +27,7 @@ "docs" ], "author": { - "name": "Nordcom Group Inc.", + "name": "Nordcom AB", "email": "opensource@nordcom.io", "url": "https://nordcom.io/" }, @@ -44,15 +47,25 @@ "bugs": { "url": "https://github.com/NordcomInc/nordstar/issues" }, - "homepage": "https://nordstar.nordcom.io/", + "homepage": "https://nordstar.dev/", "dependencies": { "@nordcom/nordstar": "workspace:*", + "@vercel/toolbar": "0.1.20", + "geist": "1.3.1", "next": "14.2.10", - "react": "18.3.1", - "react-dom": "18.3.1" + "react-dom": "18.3.1", + "react": "18.3.1" }, "devDependencies": { "@nordcom/prettier": "0.1.1", + "autoprefixer": "10.4.20", + "concurrently": "9.0.1", + "eslint-config-next": "15.0.0-canary.162", + "eslint": "8.57.1", + "postcss": "8.4.47", + "prettier": "3.3.3", + "rimraf": "6.0.1", + "tailwindcss": "3.4.13", "typescript": "5.6.2" } } diff --git a/docs/postcss.config.js b/docs/postcss.config.js new file mode 100644 index 00000000..badd1005 --- /dev/null +++ b/docs/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +}; diff --git a/docs/src/app/docs/components/[name]/not-found.tsx b/docs/src/app/docs/components/[name]/not-found.tsx new file mode 100644 index 00000000..4354942b --- /dev/null +++ b/docs/src/app/docs/components/[name]/not-found.tsx @@ -0,0 +1,26 @@ +import { Heading } from '@nordcom/nordstar'; + +import type { Metadata } from 'next'; + +export const metadata: Metadata = { + title: '404: Page Not Found', + icons: { + icon: ['/favicon.png'], + shortcut: ['/favicon.png'], + apple: ['/favicon.png'] + }, + robots: { + index: false, + follow: false + }, + referrer: 'origin' +}; + +export default function NotFound() { + return ( + <> + Page not found + Error 404 + + ); +} diff --git a/docs/src/app/docs/components/[name]/page.tsx b/docs/src/app/docs/components/[name]/page.tsx new file mode 100644 index 00000000..5a58ab4a --- /dev/null +++ b/docs/src/app/docs/components/[name]/page.tsx @@ -0,0 +1,27 @@ +import { Heading } from '@nordcom/nordstar'; +import type { Metadata } from 'next'; + +export type ComponentDocsPageParams = { + name: string; +}; + +export async function generateMetadata({ params: { name } }: { params: ComponentDocsPageParams }): Promise { + // TODO: Get component. + + return { + title: name, + alternates: { + canonical: `https://nordstar.dev/docs/components/${name}/` + } + }; +} + +export default async function ComponentDocsPage({ params: { name } }: { params: ComponentDocsPageParams }) { + // TODO: Get component. + + return ( + <> + {name} + + ); +} diff --git a/docs/src/app/docs/components/layout.tsx b/docs/src/app/docs/components/layout.tsx new file mode 100644 index 00000000..6f12ba82 --- /dev/null +++ b/docs/src/app/docs/components/layout.tsx @@ -0,0 +1,38 @@ +import { Card, Label } from '@nordcom/nordstar'; +import type { Metadata } from 'next'; +import Link from 'next/link'; + +export const metadata: Metadata = { + metadataBase: new URL(`https://nordstar.dev/docs/components/`), + title: { + default: 'Components | Docs | Nordstar Component Library', + template: `%s - Components | Docs | Nordstar Component Library` + } +}; + +export default async function DocsLayout({ children }: { children: React.ReactNode }) { + return ( +
+ + Overview + + + Button + Card + Details + Input + + + Header + View + + + Accented + Heading + label + + + {children} +
+ ); +} diff --git a/docs/src/app/docs/[component]/page.tsx b/docs/src/app/docs/components/page.tsx similarity index 50% rename from docs/src/app/docs/[component]/page.tsx rename to docs/src/app/docs/components/page.tsx index 0b5c2825..b1806575 100644 --- a/docs/src/app/docs/[component]/page.tsx +++ b/docs/src/app/docs/components/page.tsx @@ -2,16 +2,16 @@ import { Heading } from '@nordcom/nordstar'; import type { Metadata } from 'next'; export const metadata: Metadata = { - title: 'Documentation', + title: 'Components', alternates: { - canonical: 'https://nordstar.nordcom.io/docs/' + canonical: 'https://nordstar.dev/docs/components/' } }; -export default async function DocsComponentPage() { +export default async function ComponentsDocsPage() { return ( <> - Component + Components ); } diff --git a/docs/src/app/docs/layout.module.scss b/docs/src/app/docs/layout.module.scss deleted file mode 100644 index e3c8d8de..00000000 --- a/docs/src/app/docs/layout.module.scss +++ /dev/null @@ -1,27 +0,0 @@ -.container { - display: flex; - flex-direction: column; - gap: var(--layout-section-spacing); - - @media (min-width: 950px) { - display: grid; - grid-template-columns: 18rem 1fr; - } - - .sidebar { - a { - display: block; - font-weight: 800; - - transition: var(--duration-short) ease-in-out color; - - &:is(:hover, :active) { - color: var(--color-accent-primary); - } - } - - label { - padding-top: var(--layout-section-spacing); - } - } -} diff --git a/docs/src/app/docs/layout.tsx b/docs/src/app/docs/layout.tsx index 88678a7d..9c43c9e0 100644 --- a/docs/src/app/docs/layout.tsx +++ b/docs/src/app/docs/layout.tsx @@ -1,37 +1,16 @@ -import { Card, Label, View } from '@nordcom/nordstar'; +import '@/styles/base.scss'; + import type { Metadata } from 'next'; -import Link from 'next/link'; -import styles from './layout.module.scss'; +import type { ReactNode } from 'react'; export const metadata: Metadata = { - title: 'Documentation', - alternates: { - canonical: 'https://nordstar.nordcom.io/docs/' + metadataBase: new URL(`https://nordstar.dev/docs/`), + title: { + default: 'Docs | Nordstar Component Library', + template: `%s - Docs | Nordstar Component Library` } }; -export default async function DocsLayout({ children }: { children: React.ReactNode }) { - return ( - - - Overview - - - Button - Card - Details - Input - - - Header - View - - - Accented - Heading - label - - {children} - - ); +export default function DocsLayout({ children }: { children: ReactNode }) { + return <>{children}; } diff --git a/docs/src/app/docs/page.tsx b/docs/src/app/docs/page.tsx index 85579a9d..63c0d842 100644 --- a/docs/src/app/docs/page.tsx +++ b/docs/src/app/docs/page.tsx @@ -4,14 +4,14 @@ import type { Metadata } from 'next'; export const metadata: Metadata = { title: 'Documentation', alternates: { - canonical: 'https://nordstar.nordcom.io/docs/' + canonical: 'https://nordstar.dev/docs/' } }; export default async function DocsPage() { return ( <> - Overview + Docs ); } diff --git a/docs/src/app/layout.module.scss b/docs/src/app/layout.module.scss index b1888f0b..8703c039 100644 --- a/docs/src/app/layout.module.scss +++ b/docs/src/app/layout.module.scss @@ -1,15 +1,3 @@ -.header { - position: sticky; - top: 0; - - .logo { - display: contents; - font-size: 1.5em; - font-weight: 800; - line-height: 1; - } -} - .footer { display: grid; grid-auto-flow: column; diff --git a/docs/src/app/layout.tsx b/docs/src/app/layout.tsx index 964cb146..f07384b3 100644 --- a/docs/src/app/layout.tsx +++ b/docs/src/app/layout.tsx @@ -1,23 +1,35 @@ import '@/styles/base.scss'; -import { Card, Header, NordstarProvider, View } from '@nordcom/nordstar'; +import { Providers } from '@/components/providers'; +import { Card, cn, Header, View } from '@nordcom/nordstar'; +import { GeistMono } from 'geist/font/mono'; import type { Metadata, Viewport } from 'next'; import { Montserrat } from 'next/font/google'; import Link from 'next/link'; -import styles from './layout.module.scss'; const font = Montserrat({ weight: 'variable', subsets: ['latin'], display: 'swap', - variable: '--font-primary', + variable: '--font-sans', preload: true }); export const metadata: Metadata = { + metadataBase: new URL(`https://nordstar.dev/`), title: { default: '', template: `%s | Nordstar Component Library` + }, + robots: { + follow: true, + index: true + }, + referrer: 'origin', + formatDetection: { + email: false, + address: false, + telephone: false } }; @@ -34,21 +46,18 @@ export default function RootLayout({ children }: { children: React.ReactNode }) return ( - - + -
- nordstar +
+ + Nordstar + Home @@ -68,10 +77,25 @@ export default function RootLayout({ children }: { children: React.ReactNode })
- {children} + {children} - - + +
+ + Nordcom AB + + +
{' • '}
+ + + Swedish Candy Store + +
+
+ ); diff --git a/docs/src/app/manifest.ts b/docs/src/app/manifest.ts new file mode 100644 index 00000000..06842441 --- /dev/null +++ b/docs/src/app/manifest.ts @@ -0,0 +1,8 @@ +import type { MetadataRoute } from 'next'; + +export default function manifest(): MetadataRoute.Manifest { + return { + name: 'Nordstar Component Library', + short_name: 'Nordstar' + }; +} diff --git a/docs/src/app/page.module.scss b/docs/src/app/page.module.scss index 74b0511f..6537dd71 100644 --- a/docs/src/app/page.module.scss +++ b/docs/src/app/page.module.scss @@ -1,36 +1,30 @@ -.container { +.header { display: flex; flex-direction: column; - gap: var(--layout-section-spacing); + gap: calc(var(--layout-section-spacing) / 3); + padding-bottom: var(--layout-section-spacing); + width: 52rem; + max-width: 100%; +} + +.content { + display: grid; + grid-template-columns: 1fr; + gap: var(--layout-block-padding); - .header { - display: flex; - flex-direction: column; - gap: calc(var(--layout-section-spacing) / 3); - padding-bottom: var(--layout-section-spacing); - width: 52rem; - max-width: 100%; + @media (min-width: 950px) { + grid-template-columns: 1fr 1fr 1fr; } - .content { - display: grid; - grid-template-columns: 1fr; - gap: var(--layout-block-padding); + .block { + p { + margin-top: calc(var(--layout-block-padding) / 4); - @media (min-width: 950px) { - grid-template-columns: 1fr 1fr 1fr; + font-size: 0.95em; } - .block { - p { - margin-top: calc(var(--layout-block-padding) / 4); - - font-size: 0.95em; - } - - a { - width: 100%; - } + a { + width: 100%; } } } diff --git a/docs/src/app/page.tsx b/docs/src/app/page.tsx index 2b2c301f..b6fb1e08 100644 --- a/docs/src/app/page.tsx +++ b/docs/src/app/page.tsx @@ -1,4 +1,4 @@ -import { Accented, Button, Card, Heading, Label, View } from '@nordcom/nordstar'; +import { Accented, Button, Card, Heading, Label } from '@nordcom/nordstar'; import type { Metadata } from 'next'; import Link from 'next/link'; import styles from './page.module.scss'; @@ -8,15 +8,15 @@ export const metadata: Metadata = { absolute: 'Nordstar Component Library' }, description: - 'An opinionated component library for building human-centric user interfaces by Nordcom Group Inc. and contributors.', + 'An opinionated component library for building human-centric user interfaces by Nordcom AB and contributors.', alternates: { - canonical: 'https://nordstar.nordcom.io/' + canonical: 'https://nordstar.dev/' } }; export default async function IndexPage() { return ( - + <>
Nordstar by Nordcom Group Inc. and contributors @@ -28,7 +28,12 @@ export default async function IndexPage() {
- + + + +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae elementum curabitur vitae nunc. Turpis egestas maecenas @@ -38,12 +43,17 @@ export default async function IndexPage() { - - + + + +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae elementum curabitur vitae nunc. Turpis egestas maecenas @@ -53,12 +63,17 @@ export default async function IndexPage() { - - + + + +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae elementum curabitur vitae nunc. Turpis egestas maecenas @@ -68,11 +83,11 @@ export default async function IndexPage() { -

- + ); } diff --git a/docs/src/components/providers.tsx b/docs/src/components/providers.tsx new file mode 100644 index 00000000..10ac5ac3 --- /dev/null +++ b/docs/src/components/providers.tsx @@ -0,0 +1,24 @@ +import type { NordstarTheme } from '@nordcom/nordstar'; +import { NordstarProvider } from '@nordcom/nordstar'; +import { VercelToolbar } from '@vercel/toolbar/next'; +import type { ReactNode } from 'react'; + +export function Providers({ fonts, children }: { fonts: NordstarTheme['fonts']; children: ReactNode }) { + return ( + <> + + + + {children} + + + ); +} diff --git a/docs/src/styles/base.scss b/docs/src/styles/base.scss index e69de29b..b5c61c95 100644 --- a/docs/src/styles/base.scss +++ b/docs/src/styles/base.scss @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/docs/tailwind.config.cjs b/docs/tailwind.config.cjs new file mode 100644 index 00000000..86426747 --- /dev/null +++ b/docs/tailwind.config.cjs @@ -0,0 +1,88 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + darkMode: ['class'], + content: ['./src/**/*.{ts,tsx}'], + prefix: '', + theme: { + container: { + center: true, + padding: '2rem', + screens: { + '2xl': '1400px' + } + }, + extend: { + brightness: { + 65: '.65' + }, + transitionProperty: { + colors: 'color, background-color, border-color, text-decoration-color, fill, stroke, filter' + }, + transitionDuration: { + DEFAULT: '250ms' + }, + fontSize: { + inherit: 'inherit' + }, + fontFamily: { + DEFAULT: ['var(--font-sans, var(--font-fallback))', 'sans-serif'], + heading: ['var(--font-heading, var(--font-sans, var(--font-fallback)))', 'sans-serif'], + body: ['var(--font-heading, var(--font-sans, var(--font-fallback)))', 'sans-serif'], + sans: ['var(--font-sans, var(--font-fallback))', 'sans-serif'], + mono: ['var(--font-mono)', 'monospace'] + }, + fontWeight: { + inherit: 'inherit' + }, + colors: { + foreground: { + DEFAULT: 'hsl(var(--color-foreground))', + highlight: 'hsl(var(--color-foreground-highlight))' + }, + background: { + DEFAULT: 'hsl(var(--color-background))', + highlight: 'hsl(var(--color-background-highlight))' + }, + primary: { + DEFAULT: 'hsl(var(--color-accent-primary))', + foreground: 'hsl(var(--color-accent-primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--color-accent-secondary))', + foreground: 'hsl(var(--color-accent-secondary-foreground))' + } + }, + borderWidth: { + 1: 'var(--border-width-small, 1px)', + 2: 'var(--border-width, 2px)', + 4: 'var(--border-width-large, 4px)' + }, + strokeWidth: { + 1: '0.2rem', + 2: '0.25rem', + 3: '0.35rem' + }, + aspectRatio: { + '3/2': '3 / 2' + }, + keyframes: { + 'accordion-down': { + from: { height: '0' }, + to: { height: 'var(--radix-accordion-content-height)' } + }, + 'accordion-up': { + from: { height: 'var(--radix-accordion-content-height)' }, + to: { height: '0' } + } + }, + animation: { + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out' + } + } + }, + future: { + hoverOnlyWhenSupported: true + }, + plugins: [] +}; diff --git a/docs/tsconfig.json b/docs/tsconfig.json index 4b75aeca..67e23bd5 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -1,4 +1,6 @@ { + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../tsconfig.json", "compilerOptions": { "allowJs": true, "baseUrl": ".", diff --git a/docs/tsconfig.test.json b/docs/tsconfig.test.json new file mode 100644 index 00000000..357a25c4 --- /dev/null +++ b/docs/tsconfig.test.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./tsconfig.json", + "compilerOptions": { + "types": ["vitest/globals"] + }, + + "include": ["src/**/*.test.*", "tailwind.config.cjs", "postcss.config.cjs"], + "exclude": [ + "**/node_modules", + "**/dist", + "**/.turbo", + "**/storybook-static", + "**/coverage", + "**/build", + "**/public" + ] +} diff --git a/docs/vercel.json b/docs/vercel.json index b65add73..2e532cc1 100644 --- a/docs/vercel.json +++ b/docs/vercel.json @@ -6,11 +6,11 @@ "rewrites": [ { "source": "/storybook/", - "destination": "https://docs.nordstar.nordcom.io/" + "destination": "https://docs.nordstar.dev/" }, { "source": "/storybook/:path*", - "destination": "https://docs.nordstar.nordcom.io/:path*" + "destination": "https://docs.nordstar.dev/:path*" } ], "github": { diff --git a/package.json b/package.json index 0ccd8877..09b3a3ca 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "engines": { "node": "<=22" }, - "prettier": "@nordcom/prettier", "workspaces": [ "packages/core/*", "packages/components/*", @@ -17,23 +16,25 @@ "docs" ], "scripts": { - "dev": "concurrently -i pnpm:dev:*", + "dev": "concurrently -i pnpm:dev:* --", "dev:docs": "turbo dev --filter=@nordcom/nordstar-docs", "dev:storybook": "turbo dev --filter=@nordcom/nordstar-storybook", + "dev:packages": "turbo dev --filter=!@nordcom/nordstar-docs --filter=!@nordcom/nordstar-storybook --filter=!@nordcom/nordstar --filter=!@nordcom/nordstar-system", "build": "turbo build", "build:docs": "turbo build --filter=@nordcom/nordstar-docs", - "build:packages": "turbo build --filter=!@nordcom/nordstar-docs --filter=!@nordcom/nordstar-storybook --no-cache", + "build:packages": "turbo build --filter=!@nordcom/nordstar-docs --filter=!@nordcom/nordstar-storybook", "build:storybook": "turbo build --filter=@nordcom/nordstar-storybook", "typecheck": "turbo typecheck", - "lint": "eslint **/*.{ts,tsx}", + "lint": "eslint **/src/**/*.{ts,tsx}", + "prettier": "prettier --check **/src/**/*.{ts,tsx}", "fix": "concurrently -i pnpm:fix:*", - "fix:lint": "eslint **/*.{ts,tsx} --fix", - "prettier": "prettier **/src/**/*.* --write", - "fix:prettier": "prettier **/src/**/*.* --write", + "fix:docs": "turbo fix --filter=@nordcom/nordstar-docs", + "fix:packages": "turbo fix --filter=!@nordcom/nordstar-docs --filter=!@nordcom/nordstar-storybook", + "fix:eslint": "eslint --fix --ignore-pattern ./packages \"./**/*.{cjs,mjs,ts,tsx}\"", + "fix:prettier": "prettier --write \"./**/*.{cjs,mjs,ts,tsx,scss,json}\" \"!\\packages/**\"", "test": "vitest run --coverage", - "clean": "concurrently -i pnpm:clean:*", + "clean": "turbo clean --filter=!@nordcom/nordstar-docs --filter=!@nordcom/nordstar-storybook && concurrently -i pnpm:clean:*", "clean:repo": "rm -rf dist coverage storybook-static .turbo .next .tsbuildinfo *.log", - "clean:packages": "turbo clean --filter=!@nordcom/nordstar-docs --filter=!@nordcom/nordstar-storybook", "clean:docs": "turbo clean --filter=@nordcom/nordstar-docs", "clean:storybook": "turbo clean --filter=@nordcom/nordstar-storybook", "create": "plop --plopfile ./plop/plopfile.js", @@ -46,7 +47,7 @@ "changeset": "changeset" }, "author": { - "name": "Nordcom Group Inc.", + "name": "Nordcom AB", "email": "opensource@nordcom.io", "url": "https://nordcom.io/" }, @@ -65,7 +66,7 @@ "bugs": { "url": "https://github.com/NordcomInc/nordstar/issues" }, - "homepage": "https://nordstar.nordcom.io/", + "homepage": "https://nordstar.dev/", "devDependencies": { "@changesets/changelog-github": "0.5.0", "@changesets/cli": "2.27.8", @@ -92,39 +93,33 @@ "eslint-plugin-jsdoc": "50.2.4", "eslint-plugin-jsx-a11y": "6.10.0", "eslint-plugin-prettier": "5.2.1", - "eslint-plugin-react": "7.36.1", "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-react": "7.36.1", "eslint-plugin-unused-imports": "4.1.4", "glob": "11.0.0", "happy-dom": "15.7.4", - "inquirer": "11.0.2", "inquirer-directory": "2.2.0", + "inquirer": "11.0.2", "lint-staged": "15.2.10", "magic-string": "0.30.11", "plop": "4.0.1", - "prettier": "3.3.3", "prettier-eslint": "16.3.0", - "react": "18.3.1", + "prettier-plugin-tailwindcss": "0.6.6", + "prettier": "3.3.3", "react-dom": "18.3.1", + "react": "18.3.1", "rollup-preserve-directives": "1.1.1", "sass": "1.79.3", "strip-ansi": "7.1.0", + "tailwindcss": "3.4.13", "turbo": "2.1.2", - "typescript": "5.6.2", "typescript-plugin-css-modules": "5.1.0", + "typescript": "5.6.2", "vite-plugin-dts": "4.2.1", "vite-plugin-lib-inject-css": "2.1.1", "vite-tsconfig-paths": "4.3.2", "vite": "5.4.7", "vitest": "2.1.1" }, - "overrides": { - "@typescript-eslint/typescript-estree": "8.0.0", - "esbuild": "0.24.0", - "psl": "npm:@filiphsandstrom/psl@2.0.0" - }, - "trustedDependencies": [ - "spawn-sync" - ], "packageManager": "pnpm@9.11.0" } diff --git a/packages/components/accented/README.md b/packages/components/accented/README.md index ab754c36..62b58a4b 100644 --- a/packages/components/accented/README.md +++ b/packages/components/accented/README.md @@ -1,4 +1,4 @@ -# @nordcom/nordstar-accented +# [@nordcom/nordstar-accented](https://nordstar.dev/docs/components/accented/?utm_source=nordstar&utm_campaign=oss) Highlight text with an accent color. diff --git a/packages/components/accented/package.json b/packages/components/accented/package.json index 8cf62637..8da8a43e 100644 --- a/packages/components/accented/package.json +++ b/packages/components/accented/package.json @@ -7,7 +7,6 @@ "files": [ "dist" ], - "prettier": "@nordcom/prettier", "main": "./dist/index.js", "module": "./dist/index.js", "types": "./dist/index.d.ts", @@ -59,7 +58,11 @@ "build": "tsc && vite build", "dev": "vite build --watch", "clean": "rm -rf dist coverage storybook-static .turbo .next *.tsbuildinfo *.log", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "lint": "concurrently -i pnpm:lint:*", + "lint:prettier": "prettier --check src/**/*.*", + "fix": "concurrently -i pnpm:fix:*", + "fix:prettier": "prettier --write \"./**/*.{cjs,mjs,ts,tsx,json}\"" }, "keywords": [ "nordstar", @@ -70,7 +73,7 @@ "nordstar-accented" ], "author": { - "name": "Nordcom Group Inc.", + "name": "Nordcom AB", "email": "opensource@nordcom.io", "url": "https://nordcom.io/" }, @@ -90,7 +93,7 @@ "bugs": { "url": "https://github.com/NordcomInc/nordstar/issues" }, - "homepage": "https://nordstar.nordcom.io/docs/components/accented/", + "homepage": "https://nordstar.dev/docs/components/accented/", "dependencies": { "@nordcom/nordstar-system": "workspace:*" }, @@ -103,9 +106,12 @@ "@types/node": "20.16.2", "@types/react-dom": "18.3.0", "@types/react": "18.3.8", + "autoprefixer": "10.4.20", + "postcss": "8.4.47", "prettier": "3.3.3", "react-dom": "18.3.1", "react": "18.3.1", + "tailwindcss": "3.4.12", "typescript": "5.6.2", "vite": "5.4.7" } diff --git a/packages/components/accented/postcss.config.cjs b/packages/components/accented/postcss.config.cjs new file mode 100644 index 00000000..3ef13a61 --- /dev/null +++ b/packages/components/accented/postcss.config.cjs @@ -0,0 +1,10 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ +const path = require('node:path'); +const process = require('node:process'); + +module.exports = { + plugins: [ + require('tailwindcss')(path.resolve(path.join(process.cwd().split('/packages')[0], 'tailwind.config.cjs'))), + require('autoprefixer') + ] +}; diff --git a/packages/components/accented/src/accented.module.scss b/packages/components/accented/src/accented.module.scss deleted file mode 100644 index 7e8ad7c5..00000000 --- a/packages/components/accented/src/accented.module.scss +++ /dev/null @@ -1,9 +0,0 @@ -.container { - &:is([data-color='default'], [data-color='foreground'], [data-color='primary']) { - color: var(--color-accent-primary); - } - - &:is([data-color='secondary']) { - color: var(--color-accent-secondary); - } -} diff --git a/packages/components/accented/src/accented.stories.tsx b/packages/components/accented/src/accented.stories.tsx index a6e01273..f7ba39b5 100644 --- a/packages/components/accented/src/accented.stories.tsx +++ b/packages/components/accented/src/accented.stories.tsx @@ -8,8 +8,10 @@ const story: Meta = { title: 'System/Typography/Accented', component: Accented, argTypes: { - secondary: { - control: { type: 'boolean' } + color: { + control: 'inline-radio', + options: ['default', 'primary', 'secondary', 'foreground'], + defaultValue: 'default' } } }; @@ -24,8 +26,28 @@ const Template = (args: AccentedProps) => ( ); export const Standard: Story = { + render: Template, + args: {} +}; + +export const Primary: Story = { + render: Template, + args: { + ...Standard.args, + color: 'primary' + } +}; +export const Secondary: Story = { + render: Template, + args: { + ...Standard.args, + color: 'secondary' + } +}; +export const Foreground: Story = { render: Template, args: { - secondary: false + ...Standard.args, + color: 'foreground' } }; diff --git a/packages/components/accented/src/accented.test.tsx b/packages/components/accented/src/accented.test.tsx index 0d0d9867..b0f77e4b 100644 --- a/packages/components/accented/src/accented.test.tsx +++ b/packages/components/accented/src/accented.test.tsx @@ -1,3 +1,5 @@ +import React from 'react'; + import '@testing-library/jest-dom/vitest'; import '@testing-library/react'; @@ -18,7 +20,7 @@ describe('components', () => { }); it('renders with secondary accent', () => { - const wrapper = render(); + const wrapper = render(); expect(() => wrapper.unmount()).not.toThrow(); }); @@ -31,7 +33,7 @@ describe('components', () => { }); it('renders as secondary with className', () => { - const wrapper = render(); + const wrapper = render(); expect(wrapper.getByTestId('accented')).toHaveClass('hello-world'); expect(() => wrapper.unmount()).not.toThrow(); diff --git a/packages/components/accented/src/accented.tsx b/packages/components/accented/src/accented.tsx index 95c15958..9fd80f36 100644 --- a/packages/components/accented/src/accented.tsx +++ b/packages/components/accented/src/accented.tsx @@ -1,14 +1,10 @@ import type { As, NordstarColor } from '@nordcom/nordstar-system'; -import { forwardRef } from '@nordcom/nordstar-system'; -import styles from './accented.module.scss'; +import { cn, forwardRef } from '@nordcom/nordstar-system'; export type AccentedProps = { as?: As; color?: NordstarColor; - - /** @deprecated use the `color` prop instead */ - secondary?: boolean; }; /** @@ -20,13 +16,17 @@ export type AccentedProps = { * @returns {React.ReactNode} The `` component. */ const Accented = forwardRef<'span', AccentedProps>( - ({ as: Tag = 'span', color = 'default', secondary, className, ...props }, ref) => { + ({ as: Tag = 'span', color = 'default', className, ...props }, ref) => { return ( ); } diff --git a/packages/components/accented/src/globals.css b/packages/components/accented/src/globals.css new file mode 100644 index 00000000..7c05d4dd --- /dev/null +++ b/packages/components/accented/src/globals.css @@ -0,0 +1,2 @@ +@tailwind components; +@tailwind utilities; diff --git a/packages/components/accented/src/index.ts b/packages/components/accented/src/index.ts index a6207a10..d2a32669 100644 --- a/packages/components/accented/src/index.ts +++ b/packages/components/accented/src/index.ts @@ -1,3 +1,5 @@ +import './globals.css'; + import Accented from './accented'; export type { AccentedProps } from './accented'; diff --git a/packages/components/button/README.md b/packages/components/button/README.md index 9f65e7a9..974bb029 100644 --- a/packages/components/button/README.md +++ b/packages/components/button/README.md @@ -1,4 +1,4 @@ -# @nordcom/nordstar-button +# [@nordcom/nordstar-button](https://nordstar.dev/docs/components/button/?utm_source=nordstar&utm_campaign=oss) A button component for the Nordstar design system. diff --git a/packages/components/button/package.json b/packages/components/button/package.json index f2b77e37..05c0ed29 100644 --- a/packages/components/button/package.json +++ b/packages/components/button/package.json @@ -7,7 +7,6 @@ "files": [ "dist" ], - "prettier": "@nordcom/prettier", "main": "./dist/index.js", "module": "./dist/index.js", "types": "./dist/index.d.ts", @@ -46,7 +45,11 @@ "build": "tsc && vite build", "dev": "vite build --watch", "clean": "rm -rf dist coverage storybook-static .turbo .next *.tsbuildinfo *.log", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "lint": "concurrently -i pnpm:lint:*", + "lint:prettier": "prettier --check src/**/*.*", + "fix": "concurrently -i pnpm:fix:*", + "fix:prettier": "prettier --write \"./**/*.{cjs,mjs,ts,tsx,json}\"" }, "keywords": [ "nordstar", @@ -57,7 +60,7 @@ "nordstar-button" ], "author": { - "name": "Nordcom Group Inc.", + "name": "Nordcom AB", "email": "opensource@nordcom.io", "url": "https://nordcom.io/" }, @@ -77,9 +80,10 @@ "bugs": { "url": "https://github.com/NordcomInc/nordstar/issues" }, - "homepage": "https://nordstar.nordcom.io/docs/components/button/", + "homepage": "https://nordstar.dev/docs/components/button/", "dependencies": { - "@nordcom/nordstar-system": "workspace:*" + "@nordcom/nordstar-system": "workspace:*", + "class-variance-authority": "0.7.0" }, "peerDependencies": { "react": ">=18", @@ -90,9 +94,12 @@ "@types/node": "20.16.2", "@types/react-dom": "18.3.0", "@types/react": "18.3.8", + "autoprefixer": "10.4.20", + "postcss": "8.4.47", "prettier": "3.3.3", "react-dom": "18.3.1", "react": "18.3.1", + "tailwindcss": "3.4.12", "typescript": "5.6.2", "vite": "5.4.7" } diff --git a/packages/components/button/postcss.config.cjs b/packages/components/button/postcss.config.cjs new file mode 100644 index 00000000..3ef13a61 --- /dev/null +++ b/packages/components/button/postcss.config.cjs @@ -0,0 +1,10 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ +const path = require('node:path'); +const process = require('node:process'); + +module.exports = { + plugins: [ + require('tailwindcss')(path.resolve(path.join(process.cwd().split('/packages')[0], 'tailwind.config.cjs'))), + require('autoprefixer') + ] +}; diff --git a/packages/components/button/src/button.module.scss b/packages/components/button/src/button.module.scss deleted file mode 100644 index 78b252f9..00000000 --- a/packages/components/button/src/button.module.scss +++ /dev/null @@ -1,100 +0,0 @@ -.container { - -webkit-appearance: none; - appearance: none; - - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - gap: var(--layout-block-padding-half); - - width: -moz-fit-content; - width: fit-content; - padding: var(--layout-block-padding-half) var(--layout-block-padding); - - border-radius: var(--border-radius); - border-width: var(--border-width); - border-style: solid; - - text-align: center; - text-decoration: none; - - user-select: none; - transition: - 250ms ease-in-out background-color, - 250ms ease-in-out border-color, - 250ms ease-in-out color, - 250ms ease-in-out filter; - - &:not(:disabled, [aria-disabled='true']) { - cursor: pointer; - } - - &:is(:disabled, [aria-disabled='true']) { - cursor: not-allowed; - opacity: 0.5; - } - - &:is([data-color='default'], [data-color='foreground']) { - --button-accent: var(--color-foreground); - --button-foreground: var(--color-background); - } - &[data-color='primary'] { - --button-accent: var(--color-accent-primary); - --button-foreground: var(--color-foreground); // TODO: Get the contrasting color from the theme. - } - &[data-color='secondary'] { - --button-accent: var(--color-accent-secondary); - --button-foreground: var(--color-foreground); // TODO: Get the contrasting color from the theme. - } - - &[data-variant='solid'] { - background-color: var(--button-accent); - border-color: var(--button-accent); - color: var(--button-foreground); - - &:is(:hover, :active):not(:disabled, [aria-disabled='true']) { - filter: brightness(50%); - } - } - - &[data-variant='outline'] { - background-color: transparent; - border-color: var(--button-accent); - color: var(--button-accent); - - &:is(:hover, :active):not(:disabled, [aria-disabled='true']) { - background-color: var(--button-accent); - color: var(--button-foreground); - } - } - - [data-content] { - display: block; - text-transform: uppercase; - text-decoration: none; - text-align: center; - font-weight: 700; - font-family: var(--font-heading); - } - - [data-icon] { - display: contents; - - & > svg, - & > img { - display: block; - - width: 1rem; - aspect-ratio: 1 / 1; - - stroke-width: 1rem; - } - } - - :is([data-icon], [data-icon] svg) { - color: inherit; - font-size: inherit; - font-weight: inherit; - } -} diff --git a/packages/components/button/src/button.stories.tsx b/packages/components/button/src/button.stories.tsx index 319da23f..ec4b501c 100644 --- a/packages/components/button/src/button.stories.tsx +++ b/packages/components/button/src/button.stories.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import type { ButtonProps } from '@nordcom/nordstar-button'; import { Button } from '@nordcom/nordstar-button'; import type { Meta, StoryObj } from '@storybook/react'; @@ -8,6 +7,11 @@ const story: Meta = { title: 'System/Components/Button', component: Button, argTypes: { + children: { + table: { + disable: true + } + }, variant: { control: 'inline-radio', options: ['outline', 'solid'], @@ -15,7 +19,7 @@ const story: Meta = { }, color: { control: 'inline-radio', - options: ['default', 'primary', 'secondary'], + options: ['default', 'primary', 'secondary', 'foreground'], defaultValue: 'default' }, disabled: { @@ -28,43 +32,51 @@ const story: Meta = { export default story; type Story = StoryObj; -const Template = (args: ButtonProps) => ( - <> - {[ - , - - ]} - -); - export const Standard: Story = { - render: Template, - args: {} + args: { + children: 'Save to Drafts' + } }; export const Outline: Story = { - render: Template, args: { + ...Standard.args, + variant: 'outline' + } +}; + +export const WithColor: Story = { + name: 'With color', + args: { + ...Standard.args, + color: 'primary' + } +}; + +export const OutlineWithColor: Story = { + name: 'Outline with color', + args: { + ...Standard.args, + color: 'primary', variant: 'outline' } }; export const Disabled: Story = { - render: Template, args: { + ...Standard.args, disabled: true } }; + +export const Icon: Story = { + args: { + ...Standard.args, + icon: ( + + + + + ) + } +}; diff --git a/packages/components/button/src/button.test.tsx b/packages/components/button/src/button.test.tsx index 36117229..5db3abe2 100644 --- a/packages/components/button/src/button.test.tsx +++ b/packages/components/button/src/button.test.tsx @@ -1,3 +1,5 @@ +import React from 'react'; + import '@testing-library/jest-dom/vitest'; import '@testing-library/react'; diff --git a/packages/components/button/src/button.tsx b/packages/components/button/src/button.tsx index e048d1cd..1079ffa4 100644 --- a/packages/components/button/src/button.tsx +++ b/packages/components/button/src/button.tsx @@ -1,18 +1,72 @@ -import { forwardRef } from '@nordcom/nordstar-system'; -import styles from './button.module.scss'; +import { cn, forwardRef } from '@nordcom/nordstar-system'; import type { As, NordstarColor } from '@nordcom/nordstar-system'; +import type { VariantProps } from 'class-variance-authority'; +import { cva } from 'class-variance-authority'; import type { ReactNode } from 'react'; -export type ButtonProps = { +const variants = cva( + cn( + 'flex w-fit select-none appearance-none items-center justify-center gap-3 rounded-lg border-2 border-solid px-4 py-2 text-center text-sm font-bold no-underline transition-all' + ), + { + variants: { + color: { + primary: 'bg-primary border-primary text-primary-foreground', + secondary: 'bg-secondary border-secondary text-secondary-foreground', + foreground: 'bg-foreground border-foreground text-background' + }, + variant: { + outline: 'bg-transparent', + solid: 'hover:brightness-50 focus-visible:brightness-50 active:brightness-75' + } + }, + compoundVariants: [ + { + color: 'primary', + variant: 'outline', + class: 'text-primary hover:bg-primary hover:text-primary-foreground' + }, + { + color: 'secondary', + variant: 'outline', + class: 'text-secondary hover:bg-secondary hover:text-secondary-foreground' + }, + { + color: 'foreground', + variant: 'outline', + class: 'text-foreground hover:bg-foreground hover:text-background' + } + ], + defaultVariants: { + color: 'primary', + variant: 'solid' + } + } +); + +type ButtonBaseProps = { as?: As; variant?: 'outline' | 'solid'; color?: NordstarColor; icon?: ReactNode; disabled?: boolean; + + contentClassName?: string; +} & Omit, 'color'>; + +type ButtonIconProps = { + icon: ReactNode; + iconClassName?: string; +}; +type ButtonNoIconProps = { + icon?: undefined; + iconClassName?: never; }; +export type ButtonProps = ButtonBaseProps & (ButtonIconProps | ButtonNoIconProps); + /** * `