diff --git a/.changeset/config.json b/.changeset/config.json index a4ba8a2969..6f539e3e30 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -7,5 +7,5 @@ "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": ["storybook", "web"] + "ignore": ["@/storybook", "@/web"] } diff --git a/.changeset/huge-parrots-fail.md b/.changeset/huge-parrots-fail.md new file mode 100644 index 0000000000..59904c44f2 --- /dev/null +++ b/.changeset/huge-parrots-fail.md @@ -0,0 +1,21 @@ +--- +"create-flowbite-react": minor +--- + +- Added new project templates: + + - `blitzjs` - Blitz.js + - `bun` - Bun + - `esbuild` - ESBuild + - `farm` - Farm + - `meteorjs` - Meteor.js + - `modernjs` - Modern.js + - `react-router` - React Router + - `react-server` - React Server + - `rsbuild` - Rsbuild + - `rspack` - Rspack + - `tanstack-router` - TanStack Router + - `tanstack-start` - TanStack Start + - `vike` - Vike + - `waku` - Waku + - `webpack` - Webpack diff --git a/.changeset/sad-papers-crash.md b/.changeset/sad-papers-crash.md new file mode 100644 index 0000000000..5aed1485bd --- /dev/null +++ b/.changeset/sad-papers-crash.md @@ -0,0 +1,346 @@ +--- +"flowbite-react": minor +--- + +## Summary + +This release brings massive improvements to Flowbite React's capabilities, introducing the first automatic Tailwind CSS class generation system and native support for both Tailwind CSS v3 and v4. Key highlights include: + +- **Automatic Class Generation**: First UI library to automatically detect and generate Tailwind CSS classes +- **Tailwind CSS v4 Support**: Native compatibility with both Tailwind CSS v3 and v4 +- **Comprehensive Prefix Support**: Complete system for customizing class prefixes +- **Enhanced CLI Tools**: New project initialization and component creation commands +- **Expanded Framework Support**: 15 new framework integration guides and templates + +## New Engine + +### Automatic Class Generation + +- First UI library to implement automatic Tailwind CSS class detection +- Only includes styles for components you actually import and use +- Works like tree-shaking but for Tailwind CSS classes +- Real-time class list updates during development +- Optimized production builds with minimal CSS output + +Learn more about class generation in our [CLI documentation](https://flowbite-react.com/docs/getting-started/cli#cli-commands). + +### One-Command Setup + +```bash +npx flowbite-react@latest init +``` + +This single command: + +- Detects your project's environment +- Installs necessary dependencies +- Configures Tailwind CSS +- Sets up the appropriate bundler plugin +- Creates optimal VSCode configuration +- Initializes the `.flowbite-react` directory + +See our [quickstart guide](https://flowbite-react.com/docs/getting-started/quickstart) for detailed setup instructions. + +### Smart Version Handling + +- Automatic detection of Tailwind CSS version (v3 or v4) +- No manual configuration needed +- Adapts class generation to version-specific syntax +- Ensures compatibility with both versions simultaneously + +Read more about version compatibility in our [compatibility guide](https://flowbite-react.com/docs/getting-started/compatibility). + +## Major Features + +### 1. Enhanced Integration Support + +- Added new framework integration guides and templates: + - Blitz.js + - Bun + - ESBuild + - Farm + - Meteor.js + - Modern.js + - React Router + - React Server + - Rsbuild + - Rspack + - TanStack Router + - TanStack Start + - Vike + - Waku + - Webpack + +Explore all integration guides in our [framework guides section](https://flowbite-react.com/docs/guides). + +### 2. Prefix Support System + +- Added support for customizing Tailwind CSS class prefixes +- Different configuration options for Tailwind CSS v3 and v4: + + ```js + // Tailwind CSS v3 + /** @type {import('tailwindcss').Config} */ + export default { + prefix: "tw-", + // ... rest of your config + }; + + // Tailwind CSS v4 + @import "tailwindcss" prefix(tw); + ``` + +- Prefix configuration in `.flowbite-react/config.json`: + + ```json + { + "$schema": "https://unpkg.com/flowbite-react/schema.json", + "prefix": "tw" + } + ``` + +- ThemeConfig component support for prefix configuration: + + ```tsx + import { ThemeConfig } from "flowbite-react"; + + export default function App() { + return ( + <> + + {/* ... */} + + ); + } + ``` + +Learn more about prefix configuration in our [prefix documentation](https://flowbite-react.com/docs/customize/prefix). + +### 3. CLI Enhancements + +- New project initialization command: + + ```bash + npx flowbite-react@latest init + ``` + +Learn more about CLI features in our [CLI documentation](https://flowbite-react.com/docs/getting-started/cli). + +### 4. Tailwind CSS Version Compatibility + +- Automatic version detection between Tailwind CSS v3 and v4 +- Seamless support for both versions without manual configuration +- Improved class merging and prefix handling for each version + +### 5. Configuration System + +- New `.flowbite-react/config.json` for centralized configuration (automatically generated): + + ```json + { + "$schema": "https://unpkg.com/flowbite-react/schema.json", + "components": [], + "dark": true, + "path": "src/components", + "prefix": "", + "rsc": true, + "tsx": true + } + ``` + +Learn more about configuration options in our [config documentation](https://flowbite-react.com/docs/customize/config). + +### 6. Custom Components + +#### Component Creation + +- Added CLI command for component generation: + + ```bash + npx flowbite-react@latest create my-component + ``` + +- Automatic setup based on `.flowbite-react/config.json` configuration: + - Component path location + - React Server Components support + - TypeScript/JavaScript selection + +#### Theme System Integration + +- Full theming system support for custom components: + - Global theme inheritance + - Component-level overrides + - Provider-level props + - Theme clearing and applying + - Type safety with TypeScript + +## Technical Improvements + +### Build System + +- Improved bundler compatibility and performance +- Added support for tree-shaking +- Enhanced TypeScript configuration +- Optimized production builds + +### Component Updates + +- Improved component primitives +- Enhanced type safety across components +- Added extensive test coverage + +### Developer Experience + +- Added comprehensive TypeScript types +- Improved VSCode integration +- Enhanced debugging capabilities + +### Exports and Package Structure + +- All components, hooks, and utilities are now exported from the root package +- Every internal part and primitive is exposed for advanced customization +- Improved module resolution with better tree-shaking support +- Direct access to component parts without compound components +- TypeScript types for all exports are available + +## Breaking Changes + +### Component Changes + +- Deprecated compound components in favor of simpler component primitives: + + ```tsx + // Before - Compound components + + + Title 1 + Content 1 + + + + // After - Simple primitives + + + Title 1 + Content 1 + + + ``` + +- Removed `helperText` prop from all form components in favor of using the `HelperText` component directly +- Deprecated `href` prop in `Badge` component +- Updated `Button` component to use new color system: + - Added `default` and `alternative` colors + - Changed default color from `blue` to `default` + - Modified hover states to use primary colors + - Moved theme size styles from inner span to root button element + +### Theme System + +- Changed theme application behavior: + - Enhanced `ThemeProvider` with deep merging of themes + - Added support for granular theme resets using `clearTheme` + - Improved theme resolution with better performance + - Updated color schemes to use primary colors consistently +- Modified component color schemes: + - Updated default colors to use `primary` instead of specific colors (e.g., `cyan`) + - Standardized color naming across components + - Enhanced color inheritance and theme customization + +Learn more about theming in our [theme documentation](https://flowbite-react.com/docs/customize/theme). + +### Package and Build System + +- Switched package type to `module` +- Added new entry points for better module resolution +- Removed `react-icons` dependency in favor of custom icon components +- Added support for [Yarn Plug'n'Play (PnP)](https://yarnpkg.com/features/pnp): + +### API Changes + +- Deprecated `` component in favor of `ThemeProvider` +- Removed `getStore()` export and limited to finite actions and getters +- Added `forwardRef` to almost all components +- Removed redundant `Flowbite` prefix from type names + +## Migration Guide + +1. Update to the latest version: + + ```bash + npm install flowbite-react@latest + ``` + +2. Initialize the new engine: + + ```bash + npx flowbite-react@latest init + ``` + + This will: + + - Set up the `.flowbite-react` directory + - Configure your bundler + - Update VSCode settings + - Create necessary configuration files + +3. Clean up your Tailwind configuration: + + ```diff + - import flowbite from 'flowbite-react/tailwind'; + + /** @type {import('tailwindcss').Config} */ + export default { + content: [ + - flowbite.content(), + + // The init command will add the correct content paths + ], + plugins: [ + - flowbite.plugin(), + + // The init command will add the correct plugins + ], + } + ``` + +## Fixed Issues and Pull Requests + +### Resolved Issues + +- [#339](https://github.com/themesberg/flowbite-react/issues/339) +- [#1197](https://github.com/themesberg/flowbite-react/issues/1197) +- [#1286](https://github.com/themesberg/flowbite-react/issues/1286) +- [#1389](https://github.com/themesberg/flowbite-react/issues/1389) +- [#1447](https://github.com/themesberg/flowbite-react/issues/1447) +- [#1454](https://github.com/themesberg/flowbite-react/issues/1454) +- [#1473](https://github.com/themesberg/flowbite-react/issues/1473) +- [#1489](https://github.com/themesberg/flowbite-react/issues/1489) +- [#1508](https://github.com/themesberg/flowbite-react/issues/1508) +- [#1523](https://github.com/themesberg/flowbite-react/issues/1523) + +### Resolved Pull Requests + +- [#1155](https://github.com/themesberg/flowbite-react/pull/1155) + +## Technical Requirements + +- Node.js 16+ +- Tailwind CSS v3 or v4 +- React 18+ + +For detailed documentation on all new features and integrations, visit: + +## Core Documentation + +- [Quickstart (Updated)](https://flowbite-react.com/docs/getting-started/quickstart) +- [CLI (Updated)](https://flowbite-react.com/docs/getting-started/cli) +- [Compatibility (New)](https://flowbite-react.com/docs/getting-started/compatibility) +- [Editor Setup (Updated)](https://flowbite-react.com/docs/getting-started/editor-setup) +- [Server Components (Updated)](https://flowbite-react.com/docs/getting-started/server-components) + +## Customization + +- [Theme (Updated)](https://flowbite-react.com/docs/customize/theme) +- [Config (New)](https://flowbite-react.com/docs/customize/config) +- [Prefix (New)](https://flowbite-react.com/docs/customize/prefix) +- [Colors (New)](https://flowbite-react.com/docs/customize/colors) +- [Custom Components (New)](https://flowbite-react.com/docs/customize/custom-components) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 00926bafa9..243706b0a7 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -5,9 +5,9 @@ runs: using: composite steps: - name: Setup Bun - uses: oven-sh/setup-bun@v1 + uses: oven-sh/setup-bun@v2 with: - bun-version: 1.1.21 + bun-version: 1.2.2 - name: Setup Node uses: actions/setup-node@v4 diff --git a/.github/assets/flowbite-react-github.png b/.github/assets/flowbite-react-github.png deleted file mode 100644 index c313412823..0000000000 Binary files a/.github/assets/flowbite-react-github.png and /dev/null differ diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 7ceb3b627f..24b72a549d 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,11 +1,11 @@ { "recommendations": [ - "oven.bun-vscode", - "esbenp.prettier-vscode", - "dbaeumer.vscode-eslint", - "yoavbls.pretty-ts-errors", "bradlc.vscode-tailwindcss", + "DavidAnson.vscode-markdownlint", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "oven.bun-vscode", "unifiedjs.vscode-mdx", - "DavidAnson.vscode-markdownlint" + "yoavbls.pretty-ts-errors" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 8dbffc5778..9d57ae826d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,15 +4,23 @@ }, "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, - "eslint.workingDirectories": ["apps/web", "packages/ui"], + "editor.quickSuggestions": { + "strings": "on" + }, + "eslint.workingDirectories": [{ "mode": "auto" }], + "files.associations": { + "*.css": "tailwindcss" + }, "tailwindCSS.classAttributes": ["class", "className", "theme"], "tailwindCSS.experimental.classRegex": [ ["twMerge\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"], - ["createTheme\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"] + ["createTheme(?:<\\w+>)?\\s*\\(([^)]*)\\)", "{?\\s?[\\w].*:\\s*?[\"'`]([^\"'`]*).*?,?\\s?}?"] ], "tailwindCSS.experimental.configFile": { + "apps/storybook/tailwind.config.cjs": "apps/storybook/**", "apps/web/tailwind.config.cjs": "apps/web/**", "packages/ui/tailwind.config.cjs": "packages/ui/**" }, + "typescript.preferences.preferTypeOnlyAutoImports": true, "typescript.tsdk": "node_modules/typescript/lib" } diff --git a/apps/storybook/.eslintrc.cjs b/apps/storybook/.eslintrc.cjs new file mode 100644 index 0000000000..5ffe5a97cc --- /dev/null +++ b/apps/storybook/.eslintrc.cjs @@ -0,0 +1,44 @@ +/** @type {import("eslint").Linter.Config} */ +module.exports = { + root: true, + env: { + browser: true, + commonjs: true, + es2021: true, + }, + extends: [ + "eslint:recommended", + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:tailwindcss/recommended", + "prettier", + ], + overrides: [ + { + files: ["**/*.{ts,tsx}"], + plugins: ["@typescript-eslint"], + parser: "@typescript-eslint/parser", + extends: ["plugin:@typescript-eslint/recommended"], + }, + ], + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + }, + plugins: ["react-refresh"], + settings: { + react: { + version: "detect", + }, + tailwindcss: { + callees: ["twMerge", "createTheme"], + classRegex: "^(class(Name)|theme)?$", + }, + }, + ignorePatterns: ["storybook-static"], + rules: { + "react-refresh/only-export-components": ["warn", { allowConstantExport: true }], + "react/no-unescaped-entities": "off", + "react/prop-types": "off", + }, +}; diff --git a/apps/storybook/.flowbite-react/.gitignore b/apps/storybook/.flowbite-react/.gitignore new file mode 100644 index 0000000000..2b4407d0d5 --- /dev/null +++ b/apps/storybook/.flowbite-react/.gitignore @@ -0,0 +1,2 @@ +class-list.json +pid diff --git a/apps/storybook/.flowbite-react/config.json b/apps/storybook/.flowbite-react/config.json new file mode 100644 index 0000000000..c987f54cc8 --- /dev/null +++ b/apps/storybook/.flowbite-react/config.json @@ -0,0 +1,9 @@ +{ + "$schema": "../../../node_modules/flowbite-react/schema.json", + "components": [], + "dark": true, + "path": "src/components", + "prefix": "", + "rsc": true, + "tsx": true +} diff --git a/apps/storybook/.storybook/main.ts b/apps/storybook/.storybook/main.ts index 2daa674b2d..b049fa05f6 100644 --- a/apps/storybook/.storybook/main.ts +++ b/apps/storybook/.storybook/main.ts @@ -10,7 +10,7 @@ function getAbsolutePath(value: string): any { return dirname(require.resolve(join(value, "package.json"))); } const config: StorybookConfig = { - stories: ["../../../packages/ui/**/*.stories.@(ts|tsx)"], + stories: ["../src/**/*.stories.{ts,tsx}"], addons: [ getAbsolutePath("@storybook/addon-links"), getAbsolutePath("@storybook/addon-essentials"), diff --git a/apps/storybook/package.json b/apps/storybook/package.json index 09201890d7..57b0466e1e 100644 --- a/apps/storybook/package.json +++ b/apps/storybook/package.json @@ -1,18 +1,22 @@ { - "name": "storybook", + "name": "@/storybook", "version": "0.0.0", "private": true, "scripts": { "build": "storybook build", - "clean": "rimraf .turbo node_modules storybook-static", + "clean": "git clean -xdf", "dev": "storybook dev -p 6006", "format": "prettier . --write", "format:check": "prettier . --check", + "lint": "eslint .", + "lint:fix": "eslint . --fix", "typecheck": "tsc --noEmit" }, "dependencies": { + "flowbite-react": "workspace:*", "react": "18.3.1", - "react-dom": "18.3.1" + "react-dom": "18.3.1", + "react-icons": "5.2.1" }, "devDependencies": { "@storybook/addon-essentials": "8.1.10", @@ -25,12 +29,18 @@ "@storybook/test": "8.1.10", "@types/react": "18.3.3", "@types/react-dom": "18.3.0", - "@vitejs/plugin-react": "4.3.1", + "@typescript-eslint/eslint-plugin": "8.19.1", + "@typescript-eslint/parser": "8.19.1", + "@vitejs/plugin-react": "4.3.4", "autoprefixer": "10.4.20", - "postcss": "8.4.41", + "eslint-plugin-react": "7.37.3", + "eslint-plugin-react-refresh": "0.4.16", + "eslint-plugin-storybook": "0.11.1", + "eslint-plugin-vitest": "0.5.4", + "postcss": "8.4.49", "storybook": "8.1.10", - "tailwindcss": "3.4.7", - "typescript": "5.5.4", - "vite": "5.3.5" + "tailwindcss": "3.4.17", + "typescript": "5.6.3", + "vite": "6.0.7" } } diff --git a/apps/storybook/postcss.config.cjs b/apps/storybook/postcss.config.cjs index 12a703d900..1719dfd252 100644 --- a/apps/storybook/postcss.config.cjs +++ b/apps/storybook/postcss.config.cjs @@ -1,3 +1,4 @@ +/** @type {import('postcss-load-config').Config} */ module.exports = { plugins: { tailwindcss: {}, diff --git a/apps/storybook/prettier.config.cjs b/apps/storybook/prettier.config.cjs new file mode 100644 index 0000000000..e9e08307f7 --- /dev/null +++ b/apps/storybook/prettier.config.cjs @@ -0,0 +1,10 @@ +const rootPrettier = require("../../prettier.config.cjs"); + +/** @type {import('prettier').Config} */ +module.exports = { + ...rootPrettier, + plugins: [...rootPrettier.plugins, "prettier-plugin-tailwindcss"], + // tailwindcss + tailwindAttributes: ["theme"], + tailwindFunctions: ["twMerge", "createTheme"], +}; diff --git a/packages/ui/src/components/Accordion/Accordion.stories.tsx b/apps/storybook/src/Accordion.stories.tsx similarity index 81% rename from packages/ui/src/components/Accordion/Accordion.stories.tsx rename to apps/storybook/src/Accordion.stories.tsx index 2a7a37e777..26bdbc550d 100644 --- a/packages/ui/src/components/Accordion/Accordion.stories.tsx +++ b/apps/storybook/src/Accordion.stories.tsx @@ -1,8 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { ComponentProps, FC } from "react"; +import { Accordion, AccordionContent, AccordionPanel, AccordionTitle, type AccordionProps } from "flowbite-react"; import { HiChevronDown, HiOutlineArrowCircleDown } from "react-icons/hi"; -import type { AccordionProps } from "./Accordion"; -import { Accordion } from "./Accordion"; export default { title: "Components/Accordion", @@ -13,13 +11,11 @@ export default { }, } as Meta; -const icon: FC> = HiChevronDown; - const Template: StoryFn = (args) => ( - - - What is Flowbite? - + + + What is Flowbite? +

Flowbite is an open-source library of interactive components built on top of Tailwind CSS including buttons, dropdowns, modals, navbars, and more. @@ -34,11 +30,11 @@ const Template: StoryFn = (args) => (  and start developing websites even faster with components on top of Tailwind CSS.

-
-
- - Is there a Figma file available? - + + + + Is there a Figma file available? +

Flowbite is first conceptualized and designed using the Figma software so everything you see in the library has a design equivalent in our Figma file. @@ -50,11 +46,11 @@ const Template: StoryFn = (args) => (  based on the utility classes from Tailwind CSS and components from Flowbite.

-
-
- - What are the differences between Flowbite and Tailwind UI? - + + + + What are the differences between Flowbite and Tailwind UI? +

The main difference is that the core components from Flowbite are open source under the MIT license, whereas Tailwind UI is a paid product. Another difference is that Flowbite relies on smaller and standalone @@ -81,8 +77,8 @@ const Template: StoryFn = (args) => ( - - + + ); diff --git a/packages/ui/src/components/Alert/Alert.stories.tsx b/apps/storybook/src/Alert.stories.tsx similarity index 96% rename from packages/ui/src/components/Alert/Alert.stories.tsx rename to apps/storybook/src/Alert.stories.tsx index 9e7b4e331c..4b8ab0be6f 100644 --- a/packages/ui/src/components/Alert/Alert.stories.tsx +++ b/apps/storybook/src/Alert.stories.tsx @@ -1,15 +1,14 @@ import type { Meta, StoryFn } from "@storybook/react"; +import type { AlertProps } from "flowbite-react"; +import { Alert, alertTheme } from "flowbite-react"; import { HiEye, HiInformationCircle } from "react-icons/hi"; -import { theme } from "../../theme"; -import type { AlertProps } from "./Alert"; -import { Alert } from "./Alert"; export default { title: "Components/Alert", component: Alert, argTypes: { color: { - options: Object.keys(theme.alert.color), + options: Object.keys(alertTheme.color), control: { type: "inline-radio" }, }, }, diff --git a/packages/ui/src/components/Avatar/Avatar.stories.tsx b/apps/storybook/src/Avatar.stories.tsx similarity index 92% rename from packages/ui/src/components/Avatar/Avatar.stories.tsx rename to apps/storybook/src/Avatar.stories.tsx index c3b7a6fd77..b49c584052 100644 --- a/packages/ui/src/components/Avatar/Avatar.stories.tsx +++ b/apps/storybook/src/Avatar.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { AvatarProps } from "./Avatar"; -import { Avatar } from "./Avatar"; +import type { AvatarProps } from "flowbite-react"; +import { Avatar } from "flowbite-react"; export default { title: "Components/Avatar", diff --git a/packages/ui/src/components/Avatar/AvatarGroup.stories.tsx b/apps/storybook/src/AvatarGroup.stories.tsx similarity index 73% rename from packages/ui/src/components/Avatar/AvatarGroup.stories.tsx rename to apps/storybook/src/AvatarGroup.stories.tsx index f7c3b936b4..f489e3356f 100644 --- a/packages/ui/src/components/Avatar/AvatarGroup.stories.tsx +++ b/apps/storybook/src/AvatarGroup.stories.tsx @@ -1,20 +1,20 @@ import type { Meta, StoryFn } from "@storybook/react"; -import { Avatar } from "./Avatar"; -import type { AvatarGroupProps } from "./AvatarGroup"; +import type { AvatarGroupProps } from "flowbite-react"; +import { Avatar, AvatarGroup, AvatarGroupCounter } from "flowbite-react"; export default { title: "Components/Avatar", - component: Avatar.Group, + component: AvatarGroup, } as Meta; const Template: StoryFn = (args) => ( - + - - + + ); export const DefaultAvatarGroup = Template.bind({}); diff --git a/packages/ui/src/components/Badge/Badge.stories.tsx b/apps/storybook/src/Badge.stories.tsx similarity index 70% rename from packages/ui/src/components/Badge/Badge.stories.tsx rename to apps/storybook/src/Badge.stories.tsx index 70982e8935..2e86b850c8 100644 --- a/packages/ui/src/components/Badge/Badge.stories.tsx +++ b/apps/storybook/src/Badge.stories.tsx @@ -1,19 +1,18 @@ import type { Meta, StoryFn } from "@storybook/react"; +import type { BadgeProps } from "flowbite-react"; +import { Badge, badgeTheme } from "flowbite-react"; import { HiCheck } from "react-icons/hi"; -import { theme } from "../../theme"; -import type { BadgeProps } from "./Badge"; -import { Badge } from "./Badge"; export default { title: "Components/Badge", component: Badge, argTypes: { color: { - options: Object.keys(theme.badge.root.color), + options: Object.keys(badgeTheme.root.color), control: { type: "inline-radio" }, }, size: { - options: Object.keys(theme.badge.root.size), + options: Object.keys(badgeTheme.root.size), control: { type: "inline-radio" }, }, }, @@ -45,10 +44,3 @@ BadgeOnlyIcon.args = { color: "green", icon: HiCheck, }; - -export const BadgeAsLink = Template.bind({}); -BadgeAsLink.storyName = "As link"; -BadgeAsLink.args = { - href: "/badges", - children: "Read more →", -}; diff --git a/packages/ui/src/components/Banner/Banner.stories.tsx b/apps/storybook/src/Banner.stories.tsx similarity index 78% rename from packages/ui/src/components/Banner/Banner.stories.tsx rename to apps/storybook/src/Banner.stories.tsx index 77b295ba76..6c651b7742 100644 --- a/packages/ui/src/components/Banner/Banner.stories.tsx +++ b/apps/storybook/src/Banner.stories.tsx @@ -1,15 +1,15 @@ import type { Meta, StoryFn } from "@storybook/react"; +import type { BannerProps } from "flowbite-react"; +import { Banner, BannerCollapseButton } from "flowbite-react"; import { HiX } from "react-icons/hi"; import { MdAnnouncement } from "react-icons/md"; -import type { BannerComponentProps } from "./Banner"; -import { Banner } from "./Banner"; export default { title: "Components/Banner", component: Banner, } as Meta; -const Template: StoryFn = (args) => ; +const Template: StoryFn = (args) => ; export const DefaultBanner = Template.bind({}); DefaultBanner.storyName = "Default"; @@ -30,9 +30,9 @@ DefaultBanner.args = {

- + - + ), }; diff --git a/packages/ui/src/components/Blockquote/Blockquote.stories.tsx b/apps/storybook/src/Blockquote.stories.tsx similarity index 84% rename from packages/ui/src/components/Blockquote/Blockquote.stories.tsx rename to apps/storybook/src/Blockquote.stories.tsx index ad3ba76d20..be7877ca39 100644 --- a/packages/ui/src/components/Blockquote/Blockquote.stories.tsx +++ b/apps/storybook/src/Blockquote.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { BlockquoteProps } from "./Blockquote"; -import { Blockquote } from "./Blockquote"; +import type { BlockquoteProps } from "flowbite-react"; +import { Blockquote } from "flowbite-react"; export default { title: "Components/Blockquote", diff --git a/packages/ui/src/components/Breadcrumb/Breadcrumb.stories.tsx b/apps/storybook/src/Breadcrumb.stories.tsx similarity index 57% rename from packages/ui/src/components/Breadcrumb/Breadcrumb.stories.tsx rename to apps/storybook/src/Breadcrumb.stories.tsx index b6ca373932..2ccb4d2cc2 100644 --- a/packages/ui/src/components/Breadcrumb/Breadcrumb.stories.tsx +++ b/apps/storybook/src/Breadcrumb.stories.tsx @@ -1,20 +1,20 @@ import type { Meta, StoryFn } from "@storybook/react"; +import type { BreadcrumbProps } from "flowbite-react"; +import { Breadcrumb, BreadcrumbItem } from "flowbite-react"; import { HiHome } from "react-icons/hi"; -import type { BreadcrumbComponentProps } from "./Breadcrumb"; -import { Breadcrumb } from "./Breadcrumb"; export default { title: "Components/Breadcrumb", component: Breadcrumb, } as Meta; -const Template: StoryFn = (args) => ( +const Template: StoryFn = (args) => ( - + Home - - Projects - Flowbite React + + Projects + Flowbite React ); diff --git a/packages/ui/src/components/Button/Button.stories.tsx b/apps/storybook/src/Button.stories.tsx similarity index 74% rename from packages/ui/src/components/Button/Button.stories.tsx rename to apps/storybook/src/Button.stories.tsx index ab00a6b957..115a0473e5 100644 --- a/packages/ui/src/components/Button/Button.stories.tsx +++ b/apps/storybook/src/Button.stories.tsx @@ -1,14 +1,13 @@ import type { Meta, StoryFn } from "@storybook/react"; -import { theme } from "../../theme"; -import type { ButtonProps } from "./Button"; -import { Button } from "./Button"; +import type { ButtonProps } from "flowbite-react"; +import { Button, buttonTheme } from "flowbite-react"; export default { title: "Components/Button", component: Button, argTypes: { color: { - options: Object.keys(theme.button.color), + options: Object.keys(buttonTheme.color), control: { type: "inline-radio" }, }, size: { @@ -18,7 +17,6 @@ export default { }, args: { disabled: false, - isProcessing: false, }, } as Meta; diff --git a/packages/ui/src/components/Button/ButtonGroup.stories.tsx b/apps/storybook/src/ButtonGroup.stories.tsx similarity index 70% rename from packages/ui/src/components/Button/ButtonGroup.stories.tsx rename to apps/storybook/src/ButtonGroup.stories.tsx index 62b7e5e566..03f06da89a 100644 --- a/packages/ui/src/components/Button/ButtonGroup.stories.tsx +++ b/apps/storybook/src/ButtonGroup.stories.tsx @@ -1,18 +1,18 @@ import type { Meta, StoryFn } from "@storybook/react"; -import { Button } from "."; -import type { ButtonGroupProps } from "./ButtonGroup"; +import type { ButtonGroupProps } from "flowbite-react"; +import { Button, ButtonGroup } from "flowbite-react"; export default { title: "Components/Button", - component: Button.Group, + component: ButtonGroup, } as Meta; const Template: StoryFn = (args) => ( - + - + ); export const DefaultAvatarGroup = Template.bind({}); diff --git a/packages/ui/src/components/Card/Card.stories.tsx b/apps/storybook/src/Card.stories.tsx similarity index 93% rename from packages/ui/src/components/Card/Card.stories.tsx rename to apps/storybook/src/Card.stories.tsx index 679adc94f0..b1bed4091e 100644 --- a/packages/ui/src/components/Card/Card.stories.tsx +++ b/apps/storybook/src/Card.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { CardProps } from "./Card"; -import { Card } from "./Card"; +import type { CardProps } from "flowbite-react"; +import { Card } from "flowbite-react"; export default { title: "Components/Card", diff --git a/packages/ui/src/components/Carousel/Carousel.stories.tsx b/apps/storybook/src/Carousel.stories.tsx similarity index 93% rename from packages/ui/src/components/Carousel/Carousel.stories.tsx rename to apps/storybook/src/Carousel.stories.tsx index d20313a588..5fb994eb39 100644 --- a/packages/ui/src/components/Carousel/Carousel.stories.tsx +++ b/apps/storybook/src/Carousel.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { CarouselProps } from "./Carousel"; -import { Carousel } from "./Carousel"; +import type { CarouselProps } from "flowbite-react"; +import { Carousel } from "flowbite-react"; export default { title: "Components/Carousel", diff --git a/packages/ui/src/components/Checkbox/Checkbox.stories.tsx b/apps/storybook/src/Checkbox.stories.tsx similarity index 77% rename from packages/ui/src/components/Checkbox/Checkbox.stories.tsx rename to apps/storybook/src/Checkbox.stories.tsx index 11c8ac6777..8b91e5aaf7 100644 --- a/packages/ui/src/components/Checkbox/Checkbox.stories.tsx +++ b/apps/storybook/src/Checkbox.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { CheckboxProps } from "./Checkbox"; -import { Checkbox } from "./Checkbox"; +import type { CheckboxProps } from "flowbite-react"; +import { Checkbox } from "flowbite-react"; export default { title: "Components/Checkbox", diff --git a/packages/ui/src/components/Clipboard/Clipboard.stories.tsx b/apps/storybook/src/Clipboard.stories.tsx similarity index 84% rename from packages/ui/src/components/Clipboard/Clipboard.stories.tsx rename to apps/storybook/src/Clipboard.stories.tsx index 7374f0f54a..3382b4b368 100644 --- a/packages/ui/src/components/Clipboard/Clipboard.stories.tsx +++ b/apps/storybook/src/Clipboard.stories.tsx @@ -1,9 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -// import { FaClipboardList } from "react-icons/fa6"; -import type { ClipboardProps } from "./Clipboard"; -import { Clipboard } from "./Clipboard"; -import type { ClipboardWithIconProps } from "./ClipboardWithIcon"; -import type { ClipboardWithIconTextProps } from "./ClipboardWithIconText"; +import type { ClipboardProps, ClipboardWithIconProps, ClipboardWithIconTextProps } from "flowbite-react"; +import { Clipboard, ClipboardWithIcon, ClipboardWithIconText } from "flowbite-react"; export default { title: "Components/Clipboard", @@ -43,7 +40,7 @@ const CopyIconTemplate: StoryFn = () => ( disabled readOnly /> - + ); @@ -64,7 +61,7 @@ const CopyIconTextTemplate: StoryFn = () => ( disabled readOnly /> - + ); diff --git a/packages/ui/src/components/DarkThemeToggle/DarkThemeToggle.stories.tsx b/apps/storybook/src/DarkThemeToggle.stories.tsx similarity index 75% rename from packages/ui/src/components/DarkThemeToggle/DarkThemeToggle.stories.tsx rename to apps/storybook/src/DarkThemeToggle.stories.tsx index 7493367c11..8707c0b8c2 100644 --- a/packages/ui/src/components/DarkThemeToggle/DarkThemeToggle.stories.tsx +++ b/apps/storybook/src/DarkThemeToggle.stories.tsx @@ -1,6 +1,5 @@ import type { Meta, StoryFn } from "@storybook/react"; -import { Flowbite } from "../Flowbite"; -import { DarkThemeToggle } from "./DarkThemeToggle"; +import { DarkThemeToggle, ThemeProvider } from "flowbite-react"; export default { title: "Components/DarkThemeToggle", @@ -8,9 +7,9 @@ export default { } as Meta; const Template: StoryFn = (args) => ( - + - + ); export const DefaultDarkThemeToggle = Template.bind({}); diff --git a/packages/ui/src/components/Datepicker/Datepicker.stories.tsx b/apps/storybook/src/Datepicker.stories.tsx similarity index 95% rename from packages/ui/src/components/Datepicker/Datepicker.stories.tsx rename to apps/storybook/src/Datepicker.stories.tsx index 354773947f..084d98f061 100644 --- a/packages/ui/src/components/Datepicker/Datepicker.stories.tsx +++ b/apps/storybook/src/Datepicker.stories.tsx @@ -1,8 +1,7 @@ import type { Meta, StoryFn } from "@storybook/react"; +import type { DatepickerProps } from "flowbite-react"; +import { Datepicker, getFirstDateInRange, WeekStart } from "flowbite-react"; import { useEffect, useState } from "react"; -import type { DatepickerProps } from "./Datepicker"; -import { Datepicker } from "./Datepicker"; -import { getFirstDateInRange, WeekStart } from "./helpers"; export default { title: "Components/Datepicker", diff --git a/packages/ui/src/components/Drawer/Drawer.stories.tsx b/apps/storybook/src/Drawer.stories.tsx similarity index 91% rename from packages/ui/src/components/Drawer/Drawer.stories.tsx rename to apps/storybook/src/Drawer.stories.tsx index 3c1cad8822..41587f1d06 100644 --- a/packages/ui/src/components/Drawer/Drawer.stories.tsx +++ b/apps/storybook/src/Drawer.stories.tsx @@ -1,7 +1,5 @@ import type { Meta, StoryFn } from "@storybook/react"; -import { Drawer, DrawerProps } from "./Drawer"; -import { DrawerHeader } from "./DrawerHeader"; -import { DrawerItems } from "./DrawerItems"; +import { Drawer, DrawerHeader, DrawerItems, type DrawerProps } from "flowbite-react"; export default { title: "Components/Drawer", @@ -33,7 +31,7 @@ const Template: StoryFn = (args) => ( > Get access  Bonnie Green + name@flowbite.com + + Dashboard + Settings + Earnings + + Sign out + + ), +}; + +export const WithUsableInputHeader = Template.bind({}); +WithUsableInputHeader.storyName = "With usable input header"; +WithUsableInputHeader.args = { + enableTypeAhead: false, + children: ( + <> + + + + Dashboard + Settings + Earnings + Sign out + + ), +}; + +export const Inline = Template.bind({}); +Inline.args = { + inline: true, + children: ( + <> + Dashboard + Settings + Earnings + Sign out + + ), +}; + +export const CustomTrigger = Template.bind({}); +CustomTrigger.args = { + renderTrigger: () => , + children: ( + <> + Dashboard + Settings + Earnings + Sign out + + ), +}; + +export const CustomItem = Template.bind({}); +CustomItem.args = { + children: ( + <> + Default button + As span + + + As link + + + ), +}; + +export const ItemClickHandler = Template.bind({}); +ItemClickHandler.storyName = "Item click handlers"; +ItemClickHandler.args = { + children: ( + <> + Dashboard + Settings + Earnings + Sign out + + ), +}; diff --git a/packages/ui/src/components/FileInput/FileInput.stories.tsx b/apps/storybook/src/FileInput.stories.tsx similarity index 77% rename from packages/ui/src/components/FileInput/FileInput.stories.tsx rename to apps/storybook/src/FileInput.stories.tsx index 92afe0fa5f..4cdb403a80 100644 --- a/packages/ui/src/components/FileInput/FileInput.stories.tsx +++ b/apps/storybook/src/FileInput.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { FileInputProps } from "./FileInput"; -import { FileInput } from "./FileInput"; +import type { FileInputProps } from "flowbite-react"; +import { FileInput } from "flowbite-react"; export default { title: "Components/FileInput", diff --git a/packages/ui/src/components/FloatingLabel/FloatingLabel.stories.tsx b/apps/storybook/src/FloatingLabel.stories.tsx similarity index 88% rename from packages/ui/src/components/FloatingLabel/FloatingLabel.stories.tsx rename to apps/storybook/src/FloatingLabel.stories.tsx index 0c1081045c..6eae6add60 100644 --- a/packages/ui/src/components/FloatingLabel/FloatingLabel.stories.tsx +++ b/apps/storybook/src/FloatingLabel.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryFn } from "@storybook/react"; -import { FloatingLabel, type FloatingLabelProps } from "./FloatingLabel"; +import { FloatingLabel, type FloatingLabelProps } from "flowbite-react"; export default { title: "Components/FloatingLabel", @@ -101,10 +101,3 @@ SmallStandard.args = { label: "Small Standard", sizing: "sm", }; - -export const HelperText = Template.bind({}); -HelperText.args = { - variant: "filled", - label: "Floating Helper", - helperText: "Remember, contributions to this topic should follow our Community Guidelines.", -}; diff --git a/apps/storybook/src/Footer.stories.tsx b/apps/storybook/src/Footer.stories.tsx new file mode 100644 index 0000000000..f5590ef01f --- /dev/null +++ b/apps/storybook/src/Footer.stories.tsx @@ -0,0 +1,170 @@ +import type { Meta, StoryFn } from "@storybook/react"; +import { + Footer, + FooterBrand, + FooterCopyright, + FooterDivider, + FooterIcon, + FooterLink, + FooterLinkGroup, + FooterTitle, +} from "flowbite-react"; +import { BsDribbble, BsFacebook, BsGithub, BsInstagram, BsTwitter } from "react-icons/bs"; + +export default { + title: "Components/Footer", + component: Footer, +} as Meta; + +const Template: StoryFn = ({ children }) =>
{children}
; + +export const DefaultFooter = Template.bind({}); +DefaultFooter.storyName = "Default"; +DefaultFooter.args = { + children: ( +
+ + + About + Privacy Policy + Licensing + Contact + +
+ ), +}; + +export const WithLogoFooter = Template.bind({}); +WithLogoFooter.storyName = "With Logo"; +WithLogoFooter.args = { + children: ( +
+
+ + + About + Privacy Policy + Licensing + Contact + +
+ + +
+ ), +}; + +export const WithSocialMediaFooter = Template.bind({}); +WithSocialMediaFooter.storyName = "Social Media Icons"; +WithSocialMediaFooter.args = { + container: true, + children: ( +
+
+
+ +
+
+
+ + + Flowbite + Tailwind CSS + +
+
+ + + Github + Discord + +
+
+ + + Privacy Policy + Terms & Conditions + +
+
+
+ +
+ +
+ + + + + +
+
+
+ ), +}; + +export const SitemapLinksFooter = Template.bind({}); +SitemapLinksFooter.storyName = "Sitemap Links"; +SitemapLinksFooter.args = { + children: ( +
+
+
+ + + About + Careers + Brand Center + Blog + +
+
+ + + Discord Server + Twitter + Facebook + Contact Us + +
+
+ + + Privacy Policy + Licensing + Terms & Conditions + +
+
+ + + iOS + Android + Windows + MacOS + +
+
+
+ +
+ + + + + +
+
+
+ ), +}; diff --git a/packages/ui/src/components/HR/HR.stories.tsx b/apps/storybook/src/HR.stories.tsx similarity index 68% rename from packages/ui/src/components/HR/HR.stories.tsx rename to apps/storybook/src/HR.stories.tsx index 4ff5aef401..8454b79a8d 100644 --- a/packages/ui/src/components/HR/HR.stories.tsx +++ b/apps/storybook/src/HR.stories.tsx @@ -1,14 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { HRProps } from "./HR"; -import { HR } from "./HR"; -import { HRIcon } from "./HRIcon"; -import type { HRIconProps } from "./HRIcon"; -import type { HRSquareProps } from "./HRSquare"; -import { HRSquare } from "./HRSquare"; -import { HRText } from "./HRText"; -import type { HRTextProps } from "./HRText"; -import type { HRTrimmedProps } from "./HRTrimmed"; -import { HRTrimmed } from "./HRTrimmed"; +import type { HRIconProps, HRProps, HRSquareProps, HRTextProps, HRTrimmedProps } from "flowbite-react"; +import { HR, HRIcon, HRSquare, HRText, HRTrimmed } from "flowbite-react"; export default { title: "Components/HR", diff --git a/packages/ui/src/components/Kbd/Kbd.stories.tsx b/apps/storybook/src/Kbd.stories.tsx similarity index 88% rename from packages/ui/src/components/Kbd/Kbd.stories.tsx rename to apps/storybook/src/Kbd.stories.tsx index c130535196..f4c8bed079 100644 --- a/packages/ui/src/components/Kbd/Kbd.stories.tsx +++ b/apps/storybook/src/Kbd.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryFn } from "@storybook/react"; +import type { KbdProps } from "flowbite-react"; +import { Kbd } from "flowbite-react"; import { MdKeyboardArrowDown, MdKeyboardCommandKey } from "react-icons/md"; -import type { KbdProps } from "./Kbd"; -import { Kbd } from "./Kbd"; export default { title: "Components/Kbd", diff --git a/packages/ui/src/components/Label/Label.stories.tsx b/apps/storybook/src/Label.stories.tsx similarity index 78% rename from packages/ui/src/components/Label/Label.stories.tsx rename to apps/storybook/src/Label.stories.tsx index a8e9ea77b1..732509c22d 100644 --- a/packages/ui/src/components/Label/Label.stories.tsx +++ b/apps/storybook/src/Label.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { LabelProps } from "./Label"; -import { Label } from "./Label"; +import type { LabelProps } from "flowbite-react"; +import { Label } from "flowbite-react"; export default { title: "Components/Label", diff --git a/packages/ui/src/components/List/List.stories.tsx b/apps/storybook/src/List.stories.tsx similarity index 65% rename from packages/ui/src/components/List/List.stories.tsx rename to apps/storybook/src/List.stories.tsx index fc2b72d221..7c39e12cd3 100644 --- a/packages/ui/src/components/List/List.stories.tsx +++ b/apps/storybook/src/List.stories.tsx @@ -1,8 +1,7 @@ import type { Meta, StoryFn } from "@storybook/react"; +import { Avatar, List, ListItem } from "flowbite-react"; +import type { ListProps } from "flowbite-react"; import { HiCheckCircle } from "react-icons/hi"; -import { Avatar } from "../Avatar"; -import type { ListProps } from "./List"; -import { List } from "./List"; export default { title: "Components/List", @@ -16,9 +15,9 @@ DefaultList.storyName = "Default"; DefaultList.args = { children: ( <> - At least 10 characters (and up to 100 characters) - At least one lowercase character - Inclusion of at least one special character, e.g., ! @ # ? + At least 10 characters (and up to 100 characters) + At least one lowercase character + Inclusion of at least one special character, e.g., ! @ # ? ), }; @@ -29,9 +28,9 @@ UnstyledList.args = { unstyled: true, children: ( <> - At least 10 characters (and up to 100 characters) - At least one lowercase character - Inclusion of at least one special character, e.g., ! @ # ? + At least 10 characters (and up to 100 characters) + At least one lowercase character + Inclusion of at least one special character, e.g., ! @ # ? ), }; @@ -41,30 +40,30 @@ NestedList.storyName = "Nested"; NestedList.args = { children: ( <> - + List item one - You might feel like you are being really "organized" o - Nested navigation in UIs is a bad idea too, keep things as flat as possible. - Nesting tons of folders in your source code is also not helpful. + You might feel like you are being really "organized" o + Nested navigation in UIs is a bad idea too, keep things as flat as possible. + Nesting tons of folders in your source code is also not helpful. - - + + List item two - I'm not sure if we'll bother styling more than two levels deep. - Two is already too much, three is guaranteed to be a bad idea. - If you nest four levels deep you belong in prison. + I'm not sure if we'll bother styling more than two levels deep. + Two is already too much, three is guaranteed to be a bad idea. + If you nest four levels deep you belong in prison. - - + + List item three - Again please don't nest lists if you want - Nobody wants to look at this. - I'm upset that we even have to bother styling this. + Again please don't nest lists if you want + Nobody wants to look at this. + I'm upset that we even have to bother styling this. - + ), }; @@ -75,9 +74,9 @@ OrderedList.args = { ordered: true, children: ( <> - At least 10 characters (and up to 100 characters) - At least one lowercase character - Inclusion of at least one special character, e.g., ! @ # ? + At least 10 characters (and up to 100 characters) + At least one lowercase character + Inclusion of at least one special character, e.g., ! @ # ? ), }; @@ -88,13 +87,13 @@ HorizontalList.args = { horizontal: true, children: ( <> - About - Premium - Campaigns - Blog - Affiliate Program - FAQs - Contact + About + Premium + Campaigns + Blog + Affiliate Program + FAQs + Contact ), }; @@ -104,9 +103,9 @@ WithIconList.storyName = "With Icon"; WithIconList.args = { children: ( <> - At least 10 characters (and up to 100 characters) - At least one lowercase character - Inclusion of at least one special character, e.g., ! @ # ? + At least 10 characters (and up to 100 characters) + At least one lowercase character + Inclusion of at least one special character, e.g., ! @ # ? ), }; @@ -118,7 +117,7 @@ AdvancedList.args = { className: "max-w-md divide-y divide-gray-200 dark:divide-gray-700", children: ( <> - +
$320
-
- + +
$3467
-
- + +
$67
-
- + +
$2367
-
- + +
$367
-
+ ), }; diff --git a/apps/storybook/src/ListGroup.stories.tsx b/apps/storybook/src/ListGroup.stories.tsx new file mode 100644 index 0000000000..e1c044307d --- /dev/null +++ b/apps/storybook/src/ListGroup.stories.tsx @@ -0,0 +1,69 @@ +import type { Meta, StoryFn } from "@storybook/react"; +import type { ListGroupProps } from "flowbite-react"; +import { ListGroup, ListGroupItem } from "flowbite-react"; +import { HiCloudDownload, HiInbox, HiOutlineAdjustments, HiUserCircle } from "react-icons/hi"; + +export default { + title: "Components/ListGroup", + component: ListGroup, +} as Meta; + +const Template: StoryFn = (args) => ; + +export const DefaultListGroup = Template.bind({}); +DefaultListGroup.storyName = "Default"; +DefaultListGroup.args = { + children: ( + <> + Profile + Settings + Messages + Download + + ), +}; + +export const WithLinks = Template.bind({}); +WithLinks.storyName = "With links"; +WithLinks.args = { + children: ( + <> + + Profile + + Settings + Messages + Download + + ), +}; + +export const WithButtons = Template.bind({}); +WithButtons.storyName = "With buttons"; +WithButtons.args = { + children: ( + <> + alert("Profile clicked!")}> + Profile + + Settings + Messages + Download + + ), +}; + +export const WithIcons = Template.bind({}); +WithIcons.storyName = "With icons"; +WithIcons.args = { + children: ( + <> + + Profile + + Settings + Messages + Download + + ), +}; diff --git a/packages/ui/src/components/MegaMenu/MegaMenu.stories.tsx b/apps/storybook/src/MegaMenu.stories.tsx similarity index 92% rename from packages/ui/src/components/MegaMenu/MegaMenu.stories.tsx rename to apps/storybook/src/MegaMenu.stories.tsx index 78149c704d..771defff39 100644 --- a/packages/ui/src/components/MegaMenu/MegaMenu.stories.tsx +++ b/apps/storybook/src/MegaMenu.stories.tsx @@ -1,9 +1,14 @@ import type { Meta, StoryFn } from "@storybook/react"; -import { Button } from "../Button"; -import { NavbarBrand, NavbarCollapse, NavbarLink, NavbarToggle } from "../Navbar"; -import type { MegaMenuProps } from "./MegaMenu"; -import { MegaMenu } from "./MegaMenu"; -import { MegaMenuDropdown } from "./MegaMenuDropdown"; +import { + Button, + MegaMenu, + MegaMenuDropdown, + NavbarBrand, + NavbarCollapse, + NavbarLink, + NavbarToggle, +} from "flowbite-react"; +import type { MegaMenuProps } from "flowbite-react"; export default { title: "Components/MegaMenu", diff --git a/packages/ui/src/components/Modal/Modal.stories.tsx b/apps/storybook/src/Modal.stories.tsx similarity index 86% rename from packages/ui/src/components/Modal/Modal.stories.tsx rename to apps/storybook/src/Modal.stories.tsx index 975c5c805c..5add410f48 100644 --- a/packages/ui/src/components/Modal/Modal.stories.tsx +++ b/apps/storybook/src/Modal.stories.tsx @@ -1,12 +1,8 @@ import { action } from "@storybook/addon-actions"; import type { Meta, StoryFn } from "@storybook/react"; +import { Button, Checkbox, Label, Modal, ModalBody, ModalFooter, ModalHeader, TextInput } from "flowbite-react"; +import type { ModalProps } from "flowbite-react"; import { HiOutlineExclamationCircle } from "react-icons/hi"; -import { Button } from "../Button"; -import { Checkbox } from "../Checkbox"; -import { Label } from "../Label"; -import { TextInput } from "../TextInput"; -import type { ModalProps } from "./Modal"; -import { Modal } from "./Modal"; export default { title: "Components/Modal", @@ -31,8 +27,8 @@ export const Default = Template.bind({}); Default.args = { children: ( <> - Terms of Service - + Terms of Service +

With less than a month to go before the European Union enacts new consumer privacy laws for its citizens, @@ -44,13 +40,13 @@ Default.args = { soon as possible of high-risk data breaches that could personally affect them.

-
- + + - + ), }; @@ -59,7 +55,7 @@ export const PopUp = Template.bind({}); PopUp.storyName = "Pop-up modal"; PopUp.args = { children: ( - +

@@ -74,7 +70,7 @@ PopUp.args = {

-
+ ), }; @@ -83,19 +79,19 @@ FormElements.storyName = "Form elements"; FormElements.args = { children: ( <> - - + +

Sign in to our platform

-
-
@@ -118,7 +114,7 @@ FormElements.args = {
-
+ ), }; diff --git a/apps/storybook/src/Navbar.stories.tsx b/apps/storybook/src/Navbar.stories.tsx new file mode 100644 index 0000000000..015b50f4b1 --- /dev/null +++ b/apps/storybook/src/Navbar.stories.tsx @@ -0,0 +1,116 @@ +import type { Meta, StoryFn } from "@storybook/react"; +import { + Avatar, + Button, + Dropdown, + DropdownDivider, + DropdownHeader, + DropdownItem, + Navbar, + NavbarBrand, + NavbarCollapse, + NavbarLink, + NavbarToggle, + type NavbarProps, +} from "flowbite-react"; + +export default { + title: "Components/Navbar", + component: Navbar, +} as Meta; + +const Template: StoryFn = (args) => ( +
+ +
+); + +export const DefaultNavbar = Template.bind({}); +DefaultNavbar.storyName = "Default"; +DefaultNavbar.args = { + children: ( + <> + + Flowbite Logo + Flowbite + + + + + Home + + About + Services + Pricing + Contact + + + ), +}; + +export const WithCTA = Template.bind({}); +WithCTA.args = { + children: ( + <> + + Flowbite Logo + Flowbite + +
+ + +
+ + + Home + + About + Services + Pricing + Contact + + + ), +}; + +export const WithDropdown = Template.bind({}); +WithDropdown.storyName = "With dropdown"; +WithDropdown.args = { + children: ( + <> + + Flowbite Logo + Flowbite + +
+ + } + > + + Bonnie Green + name@flowbite.com + + Dashboard + Settings + Earnings + + Sign out + + +
+ + + Home + + About + Services + Pricing + Contact + + + ), +}; diff --git a/packages/ui/src/components/Pagination/Pagination.stories.tsx b/apps/storybook/src/Pagination.stories.tsx similarity index 93% rename from packages/ui/src/components/Pagination/Pagination.stories.tsx rename to apps/storybook/src/Pagination.stories.tsx index 21341e39af..2854e258d0 100644 --- a/packages/ui/src/components/Pagination/Pagination.stories.tsx +++ b/apps/storybook/src/Pagination.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryFn } from "@storybook/react"; +import type { PaginationProps } from "flowbite-react"; +import { Pagination } from "flowbite-react"; import { useEffect, useState } from "react"; -import type { PaginationProps } from "./Pagination"; -import { Pagination } from "./Pagination"; export default { title: "Components/Pagination", diff --git a/packages/ui/src/components/Popover/Popover.stories.tsx b/apps/storybook/src/Popover.stories.tsx similarity index 96% rename from packages/ui/src/components/Popover/Popover.stories.tsx rename to apps/storybook/src/Popover.stories.tsx index ef84f6e443..b3fb372545 100644 --- a/packages/ui/src/components/Popover/Popover.stories.tsx +++ b/apps/storybook/src/Popover.stories.tsx @@ -1,7 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; +import { Button, Popover, type PopoverProps } from "flowbite-react"; import { useState } from "react"; -import { Button } from "../Button"; -import { Popover, type PopoverProps } from "./Popover"; export default { title: "Components/Popover", diff --git a/packages/ui/src/components/Progress/Progress.stories.tsx b/apps/storybook/src/Progress.stories.tsx similarity index 96% rename from packages/ui/src/components/Progress/Progress.stories.tsx rename to apps/storybook/src/Progress.stories.tsx index 2b5adf343c..d6cdbcbb49 100644 --- a/packages/ui/src/components/Progress/Progress.stories.tsx +++ b/apps/storybook/src/Progress.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { ProgressProps } from "./Progress"; -import { Progress } from "./Progress"; +import type { ProgressProps } from "flowbite-react"; +import { Progress } from "flowbite-react"; export default { title: "Components/Progress", diff --git a/packages/ui/src/components/Radio/Radio.stories.tsx b/apps/storybook/src/Radio.stories.tsx similarity index 77% rename from packages/ui/src/components/Radio/Radio.stories.tsx rename to apps/storybook/src/Radio.stories.tsx index b3c28fe6e3..e16a8d1885 100644 --- a/packages/ui/src/components/Radio/Radio.stories.tsx +++ b/apps/storybook/src/Radio.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { RadioProps } from "./Radio"; -import { Radio } from "./Radio"; +import type { RadioProps } from "flowbite-react"; +import { Radio } from "flowbite-react"; export default { title: "Components/Radio", diff --git a/packages/ui/src/components/RangeSlider/RangeSlider.stories.tsx b/apps/storybook/src/RangeSlider.stories.tsx similarity index 75% rename from packages/ui/src/components/RangeSlider/RangeSlider.stories.tsx rename to apps/storybook/src/RangeSlider.stories.tsx index 8d392d94a1..efd8ea2b97 100644 --- a/packages/ui/src/components/RangeSlider/RangeSlider.stories.tsx +++ b/apps/storybook/src/RangeSlider.stories.tsx @@ -1,7 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import { theme } from "../../theme"; -import type { RangeSliderProps } from "./RangeSlider"; -import { RangeSlider } from "./RangeSlider"; +import type { RangeSliderProps } from "flowbite-react"; +import { RangeSlider, rangeSliderTheme } from "flowbite-react"; export default { title: "Components/RangeSlider", @@ -15,7 +14,7 @@ export default { ], argTypes: { sizing: { - options: Object.keys(theme.rangeSlider.field.input.sizes), + options: Object.keys(rangeSliderTheme.field.input.sizes), control: { type: "select" }, }, disabled: { diff --git a/packages/ui/src/components/Rating/Rating.stories.tsx b/apps/storybook/src/Rating.stories.tsx similarity index 62% rename from packages/ui/src/components/Rating/Rating.stories.tsx rename to apps/storybook/src/Rating.stories.tsx index 79be81766e..98df87d89f 100644 --- a/packages/ui/src/components/Rating/Rating.stories.tsx +++ b/apps/storybook/src/Rating.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { RatingProps } from "./Rating"; -import { Rating } from "./Rating"; +import type { RatingProps } from "flowbite-react"; +import { Rating, RatingAdvanced, RatingStar } from "flowbite-react"; export default { title: "Components/Rating", @@ -14,11 +14,11 @@ DefaultRating.storyName = "Default"; DefaultRating.args = { children: ( <> - - - - - + + + + + ), }; @@ -28,11 +28,11 @@ WithText.storyName = "With text"; WithText.args = { children: ( <> - - - - - + + + + +

4.95 out of 5

), @@ -43,7 +43,7 @@ RatingCount.storyName = "With rating count"; RatingCount.args = { children: ( <> - +

4.95

@@ -56,18 +56,18 @@ RatingCount.args = { export const Advanced = (): JSX.Element => (
- - - - - + + + + +

4.95 out of 5

1,745 global ratings

- 5 star - 4 star - 3 star - 2 star - 1 star + 5 star + 4 star + 3 star + 2 star + 1 star
); diff --git a/packages/ui/src/components/Select/Select.stories.tsx b/apps/storybook/src/Select.stories.tsx similarity index 89% rename from packages/ui/src/components/Select/Select.stories.tsx rename to apps/storybook/src/Select.stories.tsx index 5eaa06e3ac..16861fb64a 100644 --- a/packages/ui/src/components/Select/Select.stories.tsx +++ b/apps/storybook/src/Select.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryFn } from "@storybook/react"; +import type { SelectProps } from "flowbite-react"; +import { Select } from "flowbite-react"; import { BsFlagFill } from "react-icons/bs"; -import type { SelectProps } from "./Select"; -import { Select } from "./Select"; export default { title: "Components/Select", diff --git a/apps/storybook/src/Sidebar.stories.tsx b/apps/storybook/src/Sidebar.stories.tsx new file mode 100644 index 0000000000..1aa350ae0e --- /dev/null +++ b/apps/storybook/src/Sidebar.stories.tsx @@ -0,0 +1,298 @@ +import type { Meta, StoryFn } from "@storybook/react"; +import { + Badge, + Button, + Sidebar, + SidebarCollapse, + SidebarCTA, + SidebarItem, + SidebarItemGroup, + SidebarItems, + SidebarLogo, + type SidebarProps, +} from "flowbite-react"; +import { BiBuoy } from "react-icons/bi"; +import { HiArrowSmRight, HiChartPie, HiInbox, HiShoppingBag, HiTable, HiUser, HiViewBoards } from "react-icons/hi"; + +export default { + title: "Components/Sidebar", + component: Sidebar, +} as Meta; + +const Template: StoryFn = (props) => ; + +export const Default = Template.bind({}); +Default.args = { + children: ( + <> + + + + Dashboard + + + Kanban + + + Inbox + + + Users + + + Products + + + Sign In + + + Sign Up + + + + + ), + collapsed: false, +}; + +export const WithoutIcons = Template.bind({}); +WithoutIcons.storyName = "No icons"; +WithoutIcons.args = { + children: ( + <> + + + Dashboard + + Kanban + + + Inbox + + Users + Products + Sign In + Sign Up + + + + ), + collapsed: false, +}; + +export const MultiLevelDropdown = Template.bind({}); +MultiLevelDropdown.storyName = "Multi-level dropdown"; +MultiLevelDropdown.args = { + children: ( + <> + + + + Dashboard + + + Products + + + Inbox + + + Users + + + Products + + + Sign In + + + Sign Up + + + + + ), + collapsed: false, +}; + +export const DefaultExpandedDropdown = Template.bind({}); +DefaultExpandedDropdown.args = { + children: ( + <> + + + + Dashboard + + + Products + + + Usage Summary + + + Inbox + + + Users + + + Products + + + Sign In + + + Sign Up + + + + + ), + collapsed: false, +}; + +export const ContentSeparator = Template.bind({}); +ContentSeparator.storyName = "Content separator"; +ContentSeparator.args = { + children: ( + <> + + + + Dashboard + + + Kanban + + + Inbox + + + Users + + + Products + + + Sign In + + + Sign Up + + + + + Upgrade to Pro + + + Documentation + + + Help + + + + + ), + collapsed: false, +}; + +export const CTAButton = Template.bind({}); +CTAButton.storyName = "CTA button"; +CTAButton.args = { + children: ( + <> + + + + Dashboard + + + Kanban + + + Inbox + + + Users + + + Products + + + Sign In + + + Sign Up + + + + +
+ Beta +
+ +
+
+

+ Preview the new Flowbite dashboard navigation! You can turn the new navigation off for a limited time in your + profile. +

+
+ Turn new navigation off + + + + ), + collapsed: false, +}; + +export const LogoBranding = Template.bind({}); +LogoBranding.storyName = "Logo branding"; +LogoBranding.args = { + children: ( + <> + + Flowbite + + + + + Dashboard + + + Kanban + + + Inbox + + + Users + + + Products + + + Sign In + + + Sign Up + + + + + ), + collapsed: false, +}; diff --git a/packages/ui/src/components/Spinner/Spinner.stories.tsx b/apps/storybook/src/Spinner.stories.tsx similarity index 96% rename from packages/ui/src/components/Spinner/Spinner.stories.tsx rename to apps/storybook/src/Spinner.stories.tsx index d2a74b95ed..da7a49df17 100644 --- a/packages/ui/src/components/Spinner/Spinner.stories.tsx +++ b/apps/storybook/src/Spinner.stories.tsx @@ -1,6 +1,5 @@ import type { Meta, StoryFn } from "@storybook/react"; -import { Button } from "../Button"; -import { Spinner } from "./Spinner"; +import { Button, Spinner } from "flowbite-react"; export default { title: "Components/Spinner", diff --git a/apps/storybook/src/Table.stories.tsx b/apps/storybook/src/Table.stories.tsx new file mode 100644 index 0000000000..0366872df4 --- /dev/null +++ b/apps/storybook/src/Table.stories.tsx @@ -0,0 +1,90 @@ +import type { Meta, StoryFn } from "@storybook/react"; +import type { TableProps } from "flowbite-react"; +import { Table, TableBody, TableCell, TableHead, TableHeadCell, TableRow } from "flowbite-react"; + +export default { + title: "Components/Tables", + component: Table, +} as Meta; + +const Template: StoryFn = (args) => ( + + + + Product name + Color + Category + Price + + Edit + + + + + + + Apple MacBook Pro 17" + + Sliver + Laptop + $2999 + + + Edit + + + + + + Microsoft Surface Pro + + White + Laptop PC + $1999 + + + Edit + + + + + Magic Mouse 2 + Black + Accessories + $99 + + + Edit + + + + + + Google Pixel Phone + + Gray + Phone + $799 + + + Edit + + + + + Apple Watch 5 + Red + Wearables + $999 + + + Edit + + + + +
+); + +export const DefaultTable = Template.bind({}); +DefaultTable.storyName = "Default"; diff --git a/apps/storybook/src/Tabs.stories.tsx b/apps/storybook/src/Tabs.stories.tsx new file mode 100644 index 0000000000..ea0635aa79 --- /dev/null +++ b/apps/storybook/src/Tabs.stories.tsx @@ -0,0 +1,105 @@ +import type { Meta } from "@storybook/react"; +import type { TabsProps } from "flowbite-react"; +import { TabItem, Tabs } from "flowbite-react"; +import { HiAdjustments, HiClipboardList, HiUserCircle } from "react-icons/hi"; +import { MdDashboard } from "react-icons/md"; + +export default { + title: "Components/Tabs", + component: Tabs, + args: { + className: "bg-white rounded-lg dark:bg-gray-800 dark:text-white", + }, + argTypes: { + className: { + control: "text", + }, + variant: { + control: "radio", + options: ["default", "underline", "pills", "fullWidth"], + }, + }, +} as Meta; + +export const Default = (args: TabsProps): JSX.Element => ( + + Profile content + Dashboard content + Settings content + Contacts content + + Disabled content + + +); + +export const WithUnderline = (args: TabsProps): JSX.Element => ( + + Profile content + Dashboard content + Settings content + Contacts content + + Disabled content + + +); +WithUnderline.args = { + variant: "underline", +}; +WithUnderline.storyName = "With underline"; + +export const WithIcons = (args: TabsProps): JSX.Element => ( + + + Profile content + + + Dashboard content + + + Settings content + + + Contacts content + + + Disabled content + + +); +WithIcons.args = { + variant: "underline", +}; +WithIcons.storyName = "With icons"; + +export const Pills = (args: TabsProps): JSX.Element => ( + + Profile content + Dashboard content + Settings content + Contacts content + + Disabled content + + +); +Pills.args = { + variant: "pills", +}; + +export const FullWidth = (args: TabsProps): JSX.Element => ( + + Profile content + Dashboard content + Settings content + Contacts content + + Disabled content + + +); +FullWidth.args = { + variant: "fullWidth", +}; +FullWidth.storyName = "Full width"; diff --git a/packages/ui/src/components/TextInput/TextInput.stories.tsx b/apps/storybook/src/TextInput.stories.tsx similarity index 64% rename from packages/ui/src/components/TextInput/TextInput.stories.tsx rename to apps/storybook/src/TextInput.stories.tsx index da05865ae8..94f5349a57 100644 --- a/packages/ui/src/components/TextInput/TextInput.stories.tsx +++ b/apps/storybook/src/TextInput.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { TextInputProps } from "./TextInput"; -import { TextInput } from "./TextInput"; +import type { TextInputProps } from "flowbite-react"; +import { TextInput } from "flowbite-react"; export default { title: "Components/TextInput", @@ -11,4 +11,6 @@ const Template: StoryFn = (args) => ; export const Default = Template.bind({}); Default.storyName = "Text input"; -Default.args = {}; +Default.args = { + placeholder: "Write your thoughts here...", +}; diff --git a/packages/ui/src/components/Textarea/Textarea.stories.tsx b/apps/storybook/src/Textarea.stories.tsx similarity index 66% rename from packages/ui/src/components/Textarea/Textarea.stories.tsx rename to apps/storybook/src/Textarea.stories.tsx index b232a87f15..5346783878 100644 --- a/packages/ui/src/components/Textarea/Textarea.stories.tsx +++ b/apps/storybook/src/Textarea.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryFn } from "@storybook/react"; -import type { TextareaProps } from "./Textarea"; -import { Textarea } from "./Textarea"; +import type { TextareaProps } from "flowbite-react"; +import { Textarea } from "flowbite-react"; export default { title: "Components/Textarea", @@ -12,5 +12,6 @@ const Template: StoryFn = (args) =>