diff --git a/scm-ui/ui-buttons/.storybook/.babelrc b/scm-ui/ui-buttons/.storybook/.babelrc deleted file mode 100644 index 2fa1f1e174..0000000000 --- a/scm-ui/ui-buttons/.storybook/.babelrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets": ["@scm-manager/babel-preset"], - "plugins": ["@babel/plugin-syntax-dynamic-import"] -} diff --git a/scm-ui/ui-buttons/.storybook/RemoveThemesPlugin.js b/scm-ui/ui-buttons/.storybook/RemoveThemesPlugin.js deleted file mode 100644 index 9976554354..0000000000 --- a/scm-ui/ui-buttons/.storybook/RemoveThemesPlugin.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2020-present Cloudogu GmbH and Contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -const HtmlWebpackPlugin = require('html-webpack-plugin'); - -class RemoveThemesPlugin { - apply (compiler) { - compiler.hooks.compilation.tap('RemoveThemesPlugin', (compilation) => { - - HtmlWebpackPlugin.getHooks(compilation).beforeAssetTagGeneration.tapAsync( - 'RemoveThemesPlugin', - (data, cb) => { - - // remove generated style-loader bundles from the page - // there should be a better way, which does not generate the bundles at all - // but for now it works - if (data.assets.js) { - data.assets.js = data.assets.js.filter(bundle => !bundle.startsWith("ui-theme-")) - .filter(bundle => !bundle.startsWith("runtime~ui-theme-")) - } - - // remove css links to avoid conflicts with the themes - // so we remove all and add our own via preview-head.html - if (data.assets.css) { - data.assets.css = data.assets.css.filter(css => !css.startsWith("ui-theme-")) - } - - // Tell webpack to move on - cb(null, data) - } - ) - }) - } -} - -module.exports = RemoveThemesPlugin diff --git a/scm-ui/ui-buttons/.storybook/preview-head.html b/scm-ui/ui-buttons/.storybook/preview-head.html deleted file mode 100644 index d1c34ac7ef..0000000000 --- a/scm-ui/ui-buttons/.storybook/preview-head.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - diff --git a/scm-ui/ui-buttons/README.md b/scm-ui/ui-buttons/README.md deleted file mode 100644 index 8be9d65a53..0000000000 --- a/scm-ui/ui-buttons/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Bulma - -See Bulma element: https://bulma.io/documentation/elements/button diff --git a/scm-ui/ui-text/.storybook/main.js b/scm-ui/ui-buttons/index.ts similarity index 89% rename from scm-ui/ui-text/.storybook/main.js rename to scm-ui/ui-buttons/index.ts index 87d3241ed0..e727f1b8ff 100644 --- a/scm-ui/ui-text/.storybook/main.js +++ b/scm-ui/ui-buttons/index.ts @@ -22,10 +22,4 @@ * SOFTWARE. */ -module.exports = { - stories: ["../src/**/*.stories.@(ts|tsx)"], - framework: "@storybook/react", - core: { - builder: "webpack5", - }, -}; +export { Icon, Button, LinkButton, ExternalLinkButton, ExternalLink, ButtonVariants } from "@scm-manager/ui-core"; diff --git a/scm-ui/ui-buttons/package.json b/scm-ui/ui-buttons/package.json index 864b5407e9..952741d82e 100644 --- a/scm-ui/ui-buttons/package.json +++ b/scm-ui/ui-buttons/package.json @@ -2,77 +2,14 @@ "name": "@scm-manager/ui-buttons", "version": "3.0.0-SNAPSHOT", "private": false, - "main": "build/index.js", - "module": "build/index.mjs", - "types": "build/index.d.ts", - "files": [ - "build" - ], - "scripts": { - "build": "tsup ./src/index.ts -d build --format esm,cjs --dts", - "dev": "tsup ./src/index.ts -d build --format esm,cjs --dts --watch", - "lint": "eslint src", - "typecheck": "tsc", - "storybook": "start-storybook -p 6006 -s ../ui-webapp/public", - "build-storybook": "build-storybook", - "image-snapshots": "jest \"image-snapshot.test.ts\"", - "a11y-check": "jest \"a11y.test.ts\"", - "depcheck": "depcheck" - }, + "main": "index.ts", "peerDependencies": { - "react": "^17.0.1", - "react-dom": "^17.0.1", - "react-router-dom": "^5.3.1", - "classnames": "^2.2.6", - "@scm-manager/ui-components": "3.0.0-SNAPSHOT" + "@scm-manager/ui-core": "3.0.0-SNAPSHOT" }, "devDependencies": { "@scm-manager/prettier-config": "^2.11.1", - "@scm-manager/ui-api": "3.0.0-SNAPSHOT", "@scm-manager/eslint-config": "^2.17.0", - "@babel/core": "^7.17.8", - "@scm-manager/tsconfig": "^2.12.0", - "@storybook/addon-essentials": "^6.4.20", - "@storybook/addon-interactions": "^6.4.20", - "@storybook/addon-a11y": "^6.4.20", - "@storybook/addon-links": "^6.4.20", - "@storybook/builder-webpack5": "^6.4.20", - "@storybook/manager-webpack5": "^6.4.20", - "@storybook/react": "^6.4.20", - "@storybook/addon-storyshots-puppeteer": "^6.4.20", - "@storybook/addon-storyshots": "^6.4.20", - "@storybook/testing-library": "^0.0.9", - "jest-transform-css": "^4.0.1", - "puppeteer": "^15.5.0", - "storybook-addon-pseudo-states": "^1.15.1", - "storybook-react-router": "^1.0.8", - "@types/storybook-react-router": "^1.0.2", - "sass-loader": "^12.3.0", - "storybook-addon-themes": "^6.1.0", - "babel-loader": "^8.2.4", - "postcss": "^8.4.12", - "postcss-loader": "^6.2.1", - "webpack": "5", - "tsup": "^6.1.2", - "mini-css-extract-plugin": "^1.6.2", - "html-webpack-plugin": "^5.5.0", - "react-query": "^3.25.1", - "i18next": "^19.9.2", - "react-i18next": "11", - "i18next-fetch-backend": "^2.3.1", - "depcheck": "^1.4.3" - }, - "babel": { - "presets": [ - "@scm-manager/babel-preset" - ] - }, - "jest": { - "transform": { - "^.+\\.[tj]sx?$": "babel-jest", - "^.+\\.(css|less|scss)$": "jest-transform-css", - "^.+\\.mdx?$": "@storybook/addon-docs/jest-transform-mdx" - } + "@scm-manager/tsconfig": "^2.13.0" }, "prettier": "@scm-manager/prettier-config", "eslintConfig": { @@ -81,4 +18,4 @@ "publishConfig": { "access": "public" } -} \ No newline at end of file +} diff --git a/scm-ui/ui-components/src/BackendErrorNotification.tsx b/scm-ui/ui-components/src/BackendErrorNotification.tsx index 45e1a4797a..3b2952091d 100644 --- a/scm-ui/ui-components/src/BackendErrorNotification.tsx +++ b/scm-ui/ui-components/src/BackendErrorNotification.tsx @@ -30,6 +30,10 @@ type Props = Omit, "type" | "role"> & { error: BackendError; }; +/** + * @deprecated Please import the identical module from "@scm-manager/ui-core" + */ + const BackendErrorNotification: FC = ({ error, ...props }) => { const [t] = useTranslation("plugins"); diff --git a/scm-ui/ui-components/src/ErrorNotification.tsx b/scm-ui/ui-components/src/ErrorNotification.tsx index 6d18b34019..b01536f10b 100644 --- a/scm-ui/ui-components/src/ErrorNotification.tsx +++ b/scm-ui/ui-components/src/ErrorNotification.tsx @@ -50,6 +50,9 @@ const BasicErrorMessage: FC, "type" | " ); }; +/** + * @deprecated Please import the identical module from "@scm-manager/ui-core" + */ const ErrorNotification: FC = ({ error, ...props }) => { const [t] = useTranslation("commons"); if (error) { diff --git a/scm-ui/ui-components/src/Image.tsx b/scm-ui/ui-components/src/Image.tsx index 2e55624fc7..af1e0067ac 100644 --- a/scm-ui/ui-components/src/Image.tsx +++ b/scm-ui/ui-components/src/Image.tsx @@ -31,6 +31,9 @@ type Props = { className?: string; }; +/** + * @deprecated Please import the identical module from "@scm-manager/ui-core" + */ class Image extends React.Component { createImageSrc = () => { const { src } = this.props; diff --git a/scm-ui/ui-components/src/Loading.tsx b/scm-ui/ui-components/src/Loading.tsx index ec86c36f51..1d24005300 100644 --- a/scm-ui/ui-components/src/Loading.tsx +++ b/scm-ui/ui-components/src/Loading.tsx @@ -40,6 +40,10 @@ const FixedSizedImage = styled(Image)` height: 128px; `; +/** + * @deprecated Please import the identical module from "@scm-manager/ui-core" + */ + class Loading extends React.Component { render() { const { message, t } = this.props; diff --git a/scm-ui/ui-components/src/Notification.tsx b/scm-ui/ui-components/src/Notification.tsx index 9a97770ea8..b03dfb35c3 100644 --- a/scm-ui/ui-components/src/Notification.tsx +++ b/scm-ui/ui-components/src/Notification.tsx @@ -34,6 +34,10 @@ type Props = { role?: string; }; +/** + * @deprecated Please import the identical module from "@scm-manager/ui-core" + */ + const Notification: FC = ({ type = "info", onClose, className, children, role }) => { const renderCloseButton = () => { if (onClose) { diff --git a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap index 661171f18a..fbaef7432c 100644 --- a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap +++ b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap @@ -71110,7 +71110,7 @@ exports[`Storyshots Repositories/RepositoryEntry Archived 1`] = `
(window.scmStage || "").toUpperCase() !== "PRODUCTION"; +/** + * @deprecated Please import the identical module from "@scm-manager/ui-core" + */ + export const createAttributesForTesting = (testId?: string) => { if (!testId) { return undefined; diff --git a/scm-ui/ui-components/src/layout/Level.tsx b/scm-ui/ui-components/src/layout/Level.tsx index 9076114c1b..d9280bd650 100644 --- a/scm-ui/ui-components/src/layout/Level.tsx +++ b/scm-ui/ui-components/src/layout/Level.tsx @@ -31,6 +31,10 @@ type Props = { right?: ReactNode; }; +/** + * @deprecated Please import the identical module from "@scm-manager/ui-core" + */ + export default class Level extends React.Component { render() { const { className, left, children, right } = this.props; diff --git a/scm-ui/ui-components/src/layout/SubSubtitle.tsx b/scm-ui/ui-components/src/layout/SubSubtitle.tsx index ece0352106..48f5e09cf6 100644 --- a/scm-ui/ui-components/src/layout/SubSubtitle.tsx +++ b/scm-ui/ui-components/src/layout/SubSubtitle.tsx @@ -28,6 +28,10 @@ type Props = { className?: string; }; +/** + * @deprecated Please import the identical module from "@scm-manager/ui-core" + */ + class SubSubtitle extends React.Component { render() { const { className, children } = this.props; diff --git a/scm-ui/ui-components/src/layout/Subtitle.tsx b/scm-ui/ui-components/src/layout/Subtitle.tsx index cf6602dc52..3169cb06a0 100644 --- a/scm-ui/ui-components/src/layout/Subtitle.tsx +++ b/scm-ui/ui-components/src/layout/Subtitle.tsx @@ -29,6 +29,10 @@ type Props = { className?: string; }; +/** + * @deprecated Please import the identical module from "@scm-manager/ui-core" + */ + const Subtitle: FC = ({ subtitle, className, children }) => { if (subtitle) { return

{subtitle}

; diff --git a/scm-ui/ui-components/src/layout/Title.tsx b/scm-ui/ui-components/src/layout/Title.tsx index adf42d775c..1502f89715 100644 --- a/scm-ui/ui-components/src/layout/Title.tsx +++ b/scm-ui/ui-components/src/layout/Title.tsx @@ -31,6 +31,10 @@ type Props = { className?: string; }; +/** + * @deprecated Please import the identical module from "@scm-manager/ui-core" + */ + const Title: FC = ({ title, preventRefreshingPageTitle, customPageTitle, className, children }) => { useEffect(() => { if (!preventRefreshingPageTitle) { diff --git a/scm-ui/ui-components/src/useGeneratedId.tsx b/scm-ui/ui-components/src/useGeneratedId.tsx index 1ae7473e1b..cccd211d25 100644 --- a/scm-ui/ui-components/src/useGeneratedId.tsx +++ b/scm-ui/ui-components/src/useGeneratedId.tsx @@ -22,10 +22,11 @@ * SOFTWARE. */ -import { useMemo } from "react"; - -let counter = 0; +import { useAriaId } from "@scm-manager/ui-core"; +/** + * @deprecated Please import the identical module from "@scm-manager/ui-core" + */ export default function useGeneratedId(fallback?: string) { - return useMemo(() => fallback ?? `scm-id-${++counter}`, [fallback]); + return useAriaId(fallback); } diff --git a/scm-ui/ui-core/.storybook/.babelrc b/scm-ui/ui-core/.storybook/.babelrc new file mode 100644 index 0000000000..a138b1182a --- /dev/null +++ b/scm-ui/ui-core/.storybook/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@scm-manager/babel-preset"] +} diff --git a/scm-ui/ui-forms/.storybook/RemoveThemesPlugin.js b/scm-ui/ui-core/.storybook/RemoveThemesPlugin.js similarity index 95% rename from scm-ui/ui-forms/.storybook/RemoveThemesPlugin.js rename to scm-ui/ui-core/.storybook/RemoveThemesPlugin.js index 9976554354..13e07247d0 100644 --- a/scm-ui/ui-forms/.storybook/RemoveThemesPlugin.js +++ b/scm-ui/ui-core/.storybook/RemoveThemesPlugin.js @@ -31,13 +31,13 @@ class RemoveThemesPlugin { HtmlWebpackPlugin.getHooks(compilation).beforeAssetTagGeneration.tapAsync( 'RemoveThemesPlugin', (data, cb) => { - + // remove generated style-loader bundles from the page // there should be a better way, which does not generate the bundles at all // but for now it works if (data.assets.js) { data.assets.js = data.assets.js.filter(bundle => !bundle.startsWith("ui-theme-")) - .filter(bundle => !bundle.startsWith("runtime~ui-theme-")) + .filter(bundle => !bundle.startsWith("runtime~ui-theme-")) } // remove css links to avoid conflicts with the themes diff --git a/scm-ui/ui-buttons/.storybook/main.js b/scm-ui/ui-core/.storybook/main.js similarity index 99% rename from scm-ui/ui-buttons/.storybook/main.js rename to scm-ui/ui-core/.storybook/main.js index f5e456bcaa..68c4366cb1 100644 --- a/scm-ui/ui-buttons/.storybook/main.js +++ b/scm-ui/ui-core/.storybook/main.js @@ -30,6 +30,7 @@ const ReactDOM = require("react-dom"); const root = path.resolve(".."); + const themedir = path.join(root, "ui-styles", "src"); ReactDOM.createPortal = (node) => node; diff --git a/scm-ui/ui-overlays/.storybook/preview-head.html b/scm-ui/ui-core/.storybook/preview-head.html similarity index 99% rename from scm-ui/ui-overlays/.storybook/preview-head.html rename to scm-ui/ui-core/.storybook/preview-head.html index d1c34ac7ef..107692c5ee 100644 --- a/scm-ui/ui-overlays/.storybook/preview-head.html +++ b/scm-ui/ui-core/.storybook/preview-head.html @@ -23,4 +23,3 @@ --> - diff --git a/scm-ui/ui-buttons/.storybook/preview.js b/scm-ui/ui-core/.storybook/preview.js similarity index 100% rename from scm-ui/ui-buttons/.storybook/preview.js rename to scm-ui/ui-core/.storybook/preview.js diff --git a/scm-ui/ui-buttons/.storybook/withApiProvider.js b/scm-ui/ui-core/.storybook/withApiProvider.js similarity index 99% rename from scm-ui/ui-buttons/.storybook/withApiProvider.js rename to scm-ui/ui-core/.storybook/withApiProvider.js index 8aa561d39c..4d799d292e 100644 --- a/scm-ui/ui-buttons/.storybook/withApiProvider.js +++ b/scm-ui/ui-core/.storybook/withApiProvider.js @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ + import * as React from "react"; import { ApiProvider } from "@scm-manager/ui-api"; diff --git a/scm-ui/ui-buttons/docs/introduction.stories.mdx b/scm-ui/ui-core/docs/introduction.stories.mdx similarity index 100% rename from scm-ui/ui-buttons/docs/introduction.stories.mdx rename to scm-ui/ui-core/docs/introduction.stories.mdx diff --git a/scm-ui/ui-buttons/docs/usage.stories.mdx b/scm-ui/ui-core/docs/usage.stories.mdx similarity index 100% rename from scm-ui/ui-buttons/docs/usage.stories.mdx rename to scm-ui/ui-core/docs/usage.stories.mdx diff --git a/scm-ui/ui-core/package.json b/scm-ui/ui-core/package.json new file mode 100644 index 0000000000..6aafb5ab4c --- /dev/null +++ b/scm-ui/ui-core/package.json @@ -0,0 +1,81 @@ +{ + "name": "@scm-manager/ui-core", + "version": "3.0.0-SNAPSHOT", + "main": "./src/index.ts", + "license": "MIT", + "scripts": { + "storybook": "start-storybook -p 6006", + "build-storybook": "build-storybook" + }, + "peerDependencies": { + "react": "^17.0.1", + "react-dom": "^17.0.1", + "react-router-dom": "^5.3.1", + "classnames": "^2.3.1", + "react-hook-form": "7", + "react-i18next": "11", + "react-query": "3", + "styled-components": "5" + }, + "dependencies": { + "@headlessui/react": "^1.7.15", + "@radix-ui/react-radio-group": "^1.1.3", + "@radix-ui/react-slot": "^1.0.1", + "@radix-ui/react-visually-hidden": "^1.0.3", + "@radix-ui/react-dialog": "1.0.4", + "@radix-ui/react-dropdown-menu": "2.0.5", + "@radix-ui/react-popover": "1.0.6", + "@radix-ui/react-tooltip": "1.0.2", + "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-collapsible": "^1.0.3", + "mousetrap": "1.6.5" + }, + "devDependencies": { + "@scm-manager/prettier-config": "^2.11.1", + "@scm-manager/eslint-config": "^2.17.0", + "@scm-manager/tsconfig": "^2.12.0", + "@scm-manager/babel-preset": "^2.13.1", + "@types/mousetrap": "1.6.5", + "@testing-library/react-hooks": "8.0.1", + "@testing-library/react": "12.1.5", + "@storybook/addon-actions": "^6.5.10", + "@storybook/addon-docs": "^6.5.14", + "@storybook/addon-essentials": "^6.5.10", + "@storybook/addon-interactions": "^6.5.10", + "@storybook/addon-links": "^6.5.10", + "@storybook/addon-a11y": "^6.5.10", + "storybook-addon-i18next": "^1.3.0", + "storybook-addon-pseudo-states": "^1.15.1", + "@storybook/builder-webpack5": "^6.5.10", + "@storybook/manager-webpack5": "^6.5.10", + "@storybook/react": "^6.5.10", + "@storybook/testing-library": "^0.0.13", + "@storybook/addon-storyshots-puppeteer": "^6.4.20", + "@storybook/addon-storyshots": "^6.4.20", + "storybook-addon-mock": "^3.2.0", + "storybook-addon-themes": "^6.1.0", + "storybook-react-router": "^1.0.8", + "mini-css-extract-plugin": "^1.6.2", + "html-webpack-plugin": "^5.5.0", + "webpack": "5", + "@babel/core": "^7.19.0", + "i18next": "^19.9.2", + "react-i18next": "11", + "i18next-fetch-backend": "^2.3.1", + "babel-loader": "^8.2.5", + "depcheck": "^1.4.3", + "jest-extended": "3.1.0" + }, + "prettier": "@scm-manager/prettier-config", + "eslintConfig": { + "extends": "@scm-manager/eslint-config" + }, + "publishConfig": { + "access": "public" + }, + "jest": { + "setupFilesAfterEnv": [ + "jest-extended/all" + ] + } +} diff --git a/scm-ui/ui-buttons/src/Button.stories.tsx b/scm-ui/ui-core/src/base/buttons/Button.stories.tsx similarity index 100% rename from scm-ui/ui-buttons/src/Button.stories.tsx rename to scm-ui/ui-core/src/base/buttons/Button.stories.tsx diff --git a/scm-ui/ui-buttons/src/Button.test.stories.mdx b/scm-ui/ui-core/src/base/buttons/Button.test.stories.mdx similarity index 100% rename from scm-ui/ui-buttons/src/Button.test.stories.mdx rename to scm-ui/ui-core/src/base/buttons/Button.test.stories.mdx diff --git a/scm-ui/ui-buttons/src/Button.tsx b/scm-ui/ui-core/src/base/buttons/Button.tsx similarity index 98% rename from scm-ui/ui-buttons/src/Button.tsx rename to scm-ui/ui-core/src/base/buttons/Button.tsx index 2ae0c17f1f..b66883f405 100644 --- a/scm-ui/ui-buttons/src/Button.tsx +++ b/scm-ui/ui-core/src/base/buttons/Button.tsx @@ -25,7 +25,7 @@ import React, { AnchorHTMLAttributes, ButtonHTMLAttributes } from "react"; import { Link as ReactRouterLink, LinkProps as ReactRouterLinkProps } from "react-router-dom"; import classNames from "classnames"; -import { createAttributesForTesting } from "@scm-manager/ui-components"; +import { createAttributesForTesting } from "../helpers"; /** * @beta diff --git a/scm-ui/ui-buttons/src/Icon.tsx b/scm-ui/ui-core/src/base/buttons/Icon.tsx similarity index 100% rename from scm-ui/ui-buttons/src/Icon.tsx rename to scm-ui/ui-core/src/base/buttons/Icon.tsx diff --git a/scm-ui/ui-buttons/src/a11y.test.ts b/scm-ui/ui-core/src/base/buttons/a11y.test.ts similarity index 100% rename from scm-ui/ui-buttons/src/a11y.test.ts rename to scm-ui/ui-core/src/base/buttons/a11y.test.ts diff --git a/scm-ui/ui-core/src/base/buttons/docs/introduction.stories.mdx b/scm-ui/ui-core/src/base/buttons/docs/introduction.stories.mdx new file mode 100644 index 0000000000..03a67c26cf --- /dev/null +++ b/scm-ui/ui-core/src/base/buttons/docs/introduction.stories.mdx @@ -0,0 +1,64 @@ +import { Meta } from "@storybook/addon-docs"; +import { Button } from "../"; + + + +# Buttons + +The `@scm-manager/ui-core` library provides [atoms](https://atomicdesign.bradfrost.com/chapter-2/#atoms) implemented +as minimal wrappers around native html elements styled to match the general SCM-Manager aesthetic. + +## Components + +There are three actionable components available. Styling is consistent amongst them and all have the required `variant` property. + +1. [Button](?path=/story/components--button) +2. [Link Button](?path=/story/components--link-button) +3. [External Link Button](?path=/story/components--external-link-button) + +## Usage + +Actionable components serve a dedicated purpose. It is therefore important to know when and how to use them. + +### Variants + +There are four variants available to each of the three button types, varying in importance. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EmphasisButton VariantUsage Examples
Very HighDestructive actions
HighForm submit
NormalCancel action in dialog
LowCircumstantially relevant action on page with many actionable elements
+ +## Content + +Buttons exclusively contain text and no icons. Icons tend to be ambiguous and not always applicable which leads to inconsistent +and cluttered layouts. + +Button text should be short, concise and describe the action performed. diff --git a/scm-ui/ui-core/src/base/buttons/docs/usage.stories.mdx b/scm-ui/ui-core/src/base/buttons/docs/usage.stories.mdx new file mode 100644 index 0000000000..cf5d43c41c --- /dev/null +++ b/scm-ui/ui-core/src/base/buttons/docs/usage.stories.mdx @@ -0,0 +1,22 @@ +import { Meta, Story } from "@storybook/addon-docs"; +import { Button } from "../"; + + + +In confirmation dialogs, there are two actions.
+One to cancel the current process and one to confirm it.
+Aborting is always the secondary action, confirmation always the primary. +Focus is always on the cancelling action. + + +
+

Delete User

+

Do you really want to delete this user ?

+
+ + +
+
+
diff --git a/scm-ui/ui-buttons/src/image-snapshot.test.ts b/scm-ui/ui-core/src/base/buttons/image-snapshot.test.ts similarity index 100% rename from scm-ui/ui-buttons/src/image-snapshot.test.ts rename to scm-ui/ui-core/src/base/buttons/image-snapshot.test.ts diff --git a/scm-ui/ui-buttons/src/index.ts b/scm-ui/ui-core/src/base/buttons/index.ts similarity index 100% rename from scm-ui/ui-buttons/src/index.ts rename to scm-ui/ui-core/src/base/buttons/index.ts diff --git a/scm-ui/ui-forms/src/AddListEntryForm.tsx b/scm-ui/ui-core/src/base/forms/AddListEntryForm.tsx similarity index 98% rename from scm-ui/ui-forms/src/AddListEntryForm.tsx rename to scm-ui/ui-core/src/base/forms/AddListEntryForm.tsx index c4c130082f..3fe4b0c149 100644 --- a/scm-ui/ui-forms/src/AddListEntryForm.tsx +++ b/scm-ui/ui-core/src/base/forms/AddListEntryForm.tsx @@ -26,7 +26,7 @@ import React, { useCallback, useEffect } from "react"; import { ScmFormPathContextProvider, useScmFormPathContext } from "./FormPathContext"; import { ScmFormContextProvider, useScmFormContext } from "./ScmFormContext"; import { DeepPartial, UseFieldArrayReturn, useForm, UseFormReturn } from "react-hook-form"; -import { Button } from "@scm-manager/ui-buttons"; +import { Button } from "../buttons"; import { prefixWithoutIndices } from "./helpers"; import { useScmFormListContext } from "./ScmFormListContext"; import { useTranslation } from "react-i18next"; diff --git a/scm-ui/ui-forms/src/ConfigurationForm.tsx b/scm-ui/ui-core/src/base/forms/ConfigurationForm.tsx similarity index 97% rename from scm-ui/ui-forms/src/ConfigurationForm.tsx rename to scm-ui/ui-core/src/base/forms/ConfigurationForm.tsx index 09c8adecf6..829a6564db 100644 --- a/scm-ui/ui-forms/src/ConfigurationForm.tsx +++ b/scm-ui/ui-core/src/base/forms/ConfigurationForm.tsx @@ -23,7 +23,7 @@ */ import { useConfigLink } from "@scm-manager/ui-api"; -import { Loading } from "@scm-manager/ui-components"; +import { Loading } from "../misc"; import React, { ComponentProps } from "react"; import { HalRepresentation } from "@scm-manager/ui-types"; import Form from "./Form"; diff --git a/scm-ui/ui-forms/src/Form.stories.tsx b/scm-ui/ui-core/src/base/forms/Form.stories.tsx similarity index 100% rename from scm-ui/ui-forms/src/Form.stories.tsx rename to scm-ui/ui-core/src/base/forms/Form.stories.tsx diff --git a/scm-ui/ui-forms/src/Form.tsx b/scm-ui/ui-core/src/base/forms/Form.tsx similarity index 98% rename from scm-ui/ui-forms/src/Form.tsx rename to scm-ui/ui-core/src/base/forms/Form.tsx index e12c29a5ca..0fcc6c0648 100644 --- a/scm-ui/ui-forms/src/Form.tsx +++ b/scm-ui/ui-core/src/base/forms/Form.tsx @@ -24,10 +24,11 @@ import React, { FC, useCallback, useEffect, useState } from "react"; import { DeepPartial, SubmitHandler, useForm, UseFormReturn } from "react-hook-form"; -import { ErrorNotification, Level } from "@scm-manager/ui-components"; +import { ErrorNotification } from "../notifications"; +import { Level } from "../misc"; import { ScmFormContextProvider } from "./ScmFormContext"; import { useTranslation } from "react-i18next"; -import { Button } from "@scm-manager/ui-buttons"; +import { Button } from "../buttons"; import styled from "styled-components"; import { setValues } from "./helpers"; diff --git a/scm-ui/ui-forms/src/FormPathContext.tsx b/scm-ui/ui-core/src/base/forms/FormPathContext.tsx similarity index 100% rename from scm-ui/ui-forms/src/FormPathContext.tsx rename to scm-ui/ui-core/src/base/forms/FormPathContext.tsx diff --git a/scm-ui/ui-forms/src/FormRow.tsx b/scm-ui/ui-core/src/base/forms/FormRow.tsx similarity index 100% rename from scm-ui/ui-forms/src/FormRow.tsx rename to scm-ui/ui-core/src/base/forms/FormRow.tsx diff --git a/scm-ui/ui-forms/src/ScmFormContext.tsx b/scm-ui/ui-core/src/base/forms/ScmFormContext.tsx similarity index 100% rename from scm-ui/ui-forms/src/ScmFormContext.tsx rename to scm-ui/ui-core/src/base/forms/ScmFormContext.tsx diff --git a/scm-ui/ui-forms/src/ScmFormListContext.tsx b/scm-ui/ui-core/src/base/forms/ScmFormListContext.tsx similarity index 100% rename from scm-ui/ui-forms/src/ScmFormListContext.tsx rename to scm-ui/ui-core/src/base/forms/ScmFormListContext.tsx diff --git a/scm-ui/ui-forms/src/base/Control.tsx b/scm-ui/ui-core/src/base/forms/base/Control.tsx similarity index 100% rename from scm-ui/ui-forms/src/base/Control.tsx rename to scm-ui/ui-core/src/base/forms/base/Control.tsx diff --git a/scm-ui/ui-forms/src/base/Field.tsx b/scm-ui/ui-core/src/base/forms/base/Field.tsx similarity index 100% rename from scm-ui/ui-forms/src/base/Field.tsx rename to scm-ui/ui-core/src/base/forms/base/Field.tsx diff --git a/scm-ui/ui-forms/src/base/field-message/FieldMessage.tsx b/scm-ui/ui-core/src/base/forms/base/field-message/FieldMessage.tsx similarity index 100% rename from scm-ui/ui-forms/src/base/field-message/FieldMessage.tsx rename to scm-ui/ui-core/src/base/forms/base/field-message/FieldMessage.tsx diff --git a/scm-ui/ui-forms/src/base/help/Help.tsx b/scm-ui/ui-core/src/base/forms/base/help/Help.tsx similarity index 96% rename from scm-ui/ui-forms/src/base/help/Help.tsx rename to scm-ui/ui-core/src/base/forms/base/help/Help.tsx index 80b602cfdf..d41f58b6b8 100644 --- a/scm-ui/ui-forms/src/base/help/Help.tsx +++ b/scm-ui/ui-core/src/base/forms/base/help/Help.tsx @@ -23,7 +23,7 @@ */ import React from "react"; -import { Tooltip } from "@scm-manager/ui-overlays"; +import { Tooltip } from "../../../overlays"; type Props = { text?: string; className?: string }; const Help = ({ text, className }: Props) => ( diff --git a/scm-ui/ui-forms/src/base/label/Label.tsx b/scm-ui/ui-core/src/base/forms/base/label/Label.tsx similarity index 100% rename from scm-ui/ui-forms/src/base/label/Label.tsx rename to scm-ui/ui-core/src/base/forms/base/label/Label.tsx diff --git a/scm-ui/ui-forms/src/checkbox/Checkbox.stories.mdx b/scm-ui/ui-core/src/base/forms/checkbox/Checkbox.stories.mdx similarity index 100% rename from scm-ui/ui-forms/src/checkbox/Checkbox.stories.mdx rename to scm-ui/ui-core/src/base/forms/checkbox/Checkbox.stories.mdx diff --git a/scm-ui/ui-forms/src/checkbox/Checkbox.tsx b/scm-ui/ui-core/src/base/forms/checkbox/Checkbox.tsx similarity index 97% rename from scm-ui/ui-forms/src/checkbox/Checkbox.tsx rename to scm-ui/ui-core/src/base/forms/checkbox/Checkbox.tsx index bc6c361859..d01afc9803 100644 --- a/scm-ui/ui-forms/src/checkbox/Checkbox.tsx +++ b/scm-ui/ui-core/src/base/forms/checkbox/Checkbox.tsx @@ -23,7 +23,7 @@ */ import React, { InputHTMLAttributes } from "react"; -import { createAttributesForTesting } from "@scm-manager/ui-components"; +import { createAttributesForTesting } from "../../helpers"; import Help from "../base/help/Help"; import styled from "styled-components"; import classNames from "classnames"; diff --git a/scm-ui/ui-forms/src/checkbox/CheckboxField.tsx b/scm-ui/ui-core/src/base/forms/checkbox/CheckboxField.tsx similarity index 100% rename from scm-ui/ui-forms/src/checkbox/CheckboxField.tsx rename to scm-ui/ui-core/src/base/forms/checkbox/CheckboxField.tsx diff --git a/scm-ui/ui-forms/src/checkbox/ControlledCheckboxField.stories.mdx b/scm-ui/ui-core/src/base/forms/checkbox/ControlledCheckboxField.stories.mdx similarity index 100% rename from scm-ui/ui-forms/src/checkbox/ControlledCheckboxField.stories.mdx rename to scm-ui/ui-core/src/base/forms/checkbox/ControlledCheckboxField.stories.mdx diff --git a/scm-ui/ui-forms/src/checkbox/ControlledCheckboxField.tsx b/scm-ui/ui-core/src/base/forms/checkbox/ControlledCheckboxField.tsx similarity index 100% rename from scm-ui/ui-forms/src/checkbox/ControlledCheckboxField.tsx rename to scm-ui/ui-core/src/base/forms/checkbox/ControlledCheckboxField.tsx diff --git a/scm-ui/ui-forms/src/chip-input/ChipInputField.stories.tsx b/scm-ui/ui-core/src/base/forms/chip-input/ChipInputField.stories.tsx similarity index 100% rename from scm-ui/ui-forms/src/chip-input/ChipInputField.stories.tsx rename to scm-ui/ui-core/src/base/forms/chip-input/ChipInputField.stories.tsx diff --git a/scm-ui/ui-forms/src/chip-input/ChipInputField.tsx b/scm-ui/ui-core/src/base/forms/chip-input/ChipInputField.tsx similarity index 95% rename from scm-ui/ui-forms/src/chip-input/ChipInputField.tsx rename to scm-ui/ui-core/src/base/forms/chip-input/ChipInputField.tsx index 7668269c08..23ee53aea0 100644 --- a/scm-ui/ui-forms/src/chip-input/ChipInputField.tsx +++ b/scm-ui/ui-core/src/base/forms/chip-input/ChipInputField.tsx @@ -22,8 +22,8 @@ * SOFTWARE. */ -import React, { KeyboardEventHandler, PropsWithRef, ReactElement, Ref, RefObject, useCallback } from "react"; -import { createAttributesForTesting, useGeneratedId } from "@scm-manager/ui-components"; +import React, { KeyboardEventHandler, PropsWithRef, ReactElement, Ref, useCallback } from "react"; +import { createAttributesForTesting, useAriaId } from "../../helpers"; import Field from "../base/Field"; import Label from "../base/label/Label"; import Help from "../base/help/Help"; @@ -114,9 +114,9 @@ const ChipInputField = function ChipInputField( (item) => (createDeleteText ? createDeleteText(item) : t("delete", { item })), [createDeleteText, t] ); - const inputId = useGeneratedId(id ?? testId); - const labelId = useGeneratedId(); - const inputDescriptionId = useGeneratedId(); + const inputId = useAriaId(id ?? testId); + const labelId = useAriaId(); + const inputDescriptionId = useAriaId(); const variant = error ? "danger" : undefined; return ( diff --git a/scm-ui/ui-forms/src/chip-input/ControlledChipInputField.tsx b/scm-ui/ui-core/src/base/forms/chip-input/ControlledChipInputField.tsx similarity index 100% rename from scm-ui/ui-forms/src/chip-input/ControlledChipInputField.tsx rename to scm-ui/ui-core/src/base/forms/chip-input/ControlledChipInputField.tsx diff --git a/scm-ui/ui-forms/src/combobox/Combobox.stories.tsx b/scm-ui/ui-core/src/base/forms/combobox/Combobox.stories.tsx similarity index 100% rename from scm-ui/ui-forms/src/combobox/Combobox.stories.tsx rename to scm-ui/ui-core/src/base/forms/combobox/Combobox.stories.tsx diff --git a/scm-ui/ui-forms/src/combobox/Combobox.tsx b/scm-ui/ui-core/src/base/forms/combobox/Combobox.tsx similarity index 98% rename from scm-ui/ui-forms/src/combobox/Combobox.tsx rename to scm-ui/ui-core/src/base/forms/combobox/Combobox.tsx index 688884c4d5..340dd06c0a 100644 --- a/scm-ui/ui-forms/src/combobox/Combobox.tsx +++ b/scm-ui/ui-core/src/base/forms/combobox/Combobox.tsx @@ -36,7 +36,7 @@ import { Combobox as HeadlessCombobox } from "@headlessui/react"; import classNames from "classnames"; import styled from "styled-components"; import { withForwardRef } from "../helpers"; -import { createAttributesForTesting } from "@scm-manager/ui-components"; +import { createAttributesForTesting } from "../../helpers"; import { Option } from "@scm-manager/ui-types"; const OptionsWrapper = styled(HeadlessCombobox.Options).attrs({ diff --git a/scm-ui/ui-forms/src/combobox/ComboboxField.tsx b/scm-ui/ui-core/src/base/forms/combobox/ComboboxField.tsx similarity index 95% rename from scm-ui/ui-forms/src/combobox/ComboboxField.tsx rename to scm-ui/ui-core/src/base/forms/combobox/ComboboxField.tsx index 479f019465..b48602f42a 100644 --- a/scm-ui/ui-forms/src/combobox/ComboboxField.tsx +++ b/scm-ui/ui-core/src/base/forms/combobox/ComboboxField.tsx @@ -26,7 +26,7 @@ import Field from "../base/Field"; import Label from "../base/label/Label"; import Help from "../base/help/Help"; import React from "react"; -import { useGeneratedId } from "@scm-manager/ui-components"; +import { useAriaId } from "../../helpers"; import { withForwardRef } from "../helpers"; import Combobox, { ComboboxProps } from "./Combobox"; import classNames from "classnames"; @@ -46,7 +46,7 @@ const ComboboxField = function ComboboxField( }: ComboboxProps & { label: string; helpText?: string; error?: string; isLoading?: boolean }, ref: React.ForwardedRef ) { - const labelId = useGeneratedId(); + const labelId = useAriaId(); return (