Integrate tailwind css and create new button library (#2098)

Introduce tailwind as new frontend styling library to replace bulma in the longer run. Also create the first new ui library `ui-buttons` which will be the new standard for buttons ins SCM-Manager. In this library we reconsidered which types of buttons should be used to create a clean and consistent ui.

Co-authored-by: Eduard Heimbuch <eduard.heimbuch@cloudogu.com>
This commit is contained in:
Konstantin Schaper
2022-08-02 08:39:37 +02:00
committed by GitHub
parent 09beb8cd3b
commit 27dbcbf28d
67 changed files with 8592 additions and 7519 deletions

View File

@@ -23,9 +23,10 @@
*/
import React, { FC, useState } from "react";
import { useHistory, useLocation } from "react-router-dom";
import classNames from "classnames";
import { Button, urls } from "./index";
import { urls } from "./index";
import { FilterInput, Select } from "./forms";
import { ButtonVariants, LinkButton } from "@scm-manager/ui-buttons";
import classNames from "classnames";
type Props = {
showCreateButton: boolean;
@@ -54,7 +55,7 @@ const OverviewPageActions: FC<Props> = ({
label,
testId,
searchPlaceholder,
groupAriaLabelledby
groupAriaLabelledby,
}) => {
const history = useHistory();
const location = useLocation();
@@ -66,7 +67,7 @@ const OverviewPageActions: FC<Props> = ({
<Select
ariaLabelledby={groupAriaLabelledby}
className="is-fullwidth"
options={groups.map(g => ({ value: g, label: g }))}
options={groups.map((g) => ({ value: g, label: g }))}
value={currentGroup}
onChange={groupSelected}
/>
@@ -76,8 +77,10 @@ const OverviewPageActions: FC<Props> = ({
const renderCreateButton = () => {
if (showCreateButton) {
return (
<div className={classNames("input-button", "control", "column")}>
<Button label={label} link={createLink || `${link}create/`} color="primary" />
<div className={classNames("control", "column")}>
<LinkButton variant={ButtonVariants.PRIMARY} to={createLink || `${link}create/`}>
{label}
</LinkButton>
</div>
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,6 @@ import Button from "../buttons/Button";
import { MemoryRouter } from "react-router-dom";
import { useForm } from "react-hook-form";
import { SubmitButton } from "../buttons";
import { Person } from "@scm-manager/ui-types";
const Decorator = styled.div`
padding: 2rem;
@@ -74,9 +73,9 @@ const ReactHookForm: FC = () => {
handleSubmit,
formState: { errors },
} = useForm<Name>();
const [stored, setStored] = useState<Person>();
const [stored, setStored] = useState<Name>();
const onSubmit = (person: Person) => {
const onSubmit = (person: Name) => {
setStored(person);
};

View File

@@ -25,7 +25,7 @@
import { nameRegex } from "../validation";
import { TFunction } from "i18next";
import { AstPlugin } from "./PluginApi";
import { Node, Parent } from "unist";
import { Literal, Node, Parent } from "unist";
const namePartRegex = nameRegex.source.substring(1, nameRegex.source.length - 1).replace(/\[\^([^\]s]+)\]/, "[^$1\\s]");
@@ -45,11 +45,11 @@ function match(value: string): RegExpMatchArray[] {
export const createTransformer = (t: TFunction): AstPlugin => {
return ({ visit }) => {
visit("text", (node: Node, index: number, parent?: Parent) => {
if (!parent || parent.type === "link" || !node.value) {
if (!parent || parent.type === "link" || !(node as Literal).value) {
return;
}
let nodeText = node.value as string;
let nodeText = (node as Literal).value as string;
const matches = match(nodeText);
if (matches.length > 0) {
@@ -92,7 +92,7 @@ export const createTransformer = (t: TFunction): AstPlugin => {
parent.children[index] = {
type: "text",
children,
};
} as Node;
}
});
};

View File

@@ -23,7 +23,7 @@
*/
import { AstPlugin } from "./PluginApi";
import { Node, Parent } from "unist";
import { Literal, Node, Parent } from "unist";
/**
* Some existing remark plugins (e.g. changesetShortLinkParser or the plugin for issue tracker links) create
@@ -54,8 +54,8 @@ import { Node, Parent } from "unist";
export const createTransformer = (): AstPlugin => {
return ({ visit }) => {
visit("text", (node: Node, index: number, parent?: Parent) => {
if (node.value === undefined && Array.isArray(node.children) && node.children.length > 0) {
const children = node.children;
if ((node as Literal).value === undefined && Array.isArray((node as Parent).children) && (node as Parent).children.length > 0) {
const children = (node as Parent).children;
const preChildren = parent?.children.slice(0, index) || [];
const postChildren = parent?.children.slice(index + 1) || [];
parent!.children = [...preChildren, ...children, ...postChildren];

View File

@@ -50,8 +50,8 @@ const Table: FC<Props> = ({ data, sortable, children, emptyMessage, className })
const sortFunctions: Comparator | undefined[] = [];
React.Children.forEach(children, (child, index) => {
if (child && isSortable(child)) {
sortFunctions.push(child.props.createComparator(child.props, index));
if (child && isSortable(child as ReactElement)) {
sortFunctions.push((child as ReactElement).props.createComparator((child as ReactElement).props, index));
} else {
sortFunctions.push(undefined);
}
@@ -61,9 +61,9 @@ const Table: FC<Props> = ({ data, sortable, children, emptyMessage, className })
return (
<tr key={rowIndex}>
{React.Children.map(children, (child, columnIndex) => {
const { className: columnClassName, ...childProperties } = child.props;
const { className: columnClassName, ...childProperties } = (child as ReactElement).props;
return (
<td className={columnClassName}>{React.cloneElement(child, { ...childProperties, columnIndex, row })}</td>
<td className={columnClassName}>{React.cloneElement((child as ReactElement), { ...childProperties, columnIndex, row })}</td>
);
})}
</tr>
@@ -112,14 +112,14 @@ const Table: FC<Props> = ({ data, sortable, children, emptyMessage, className })
<tr>
{React.Children.map(children, (child, index) => (
<th
className={isSortable(child) && "is-clickable"}
onClick={isSortable(child) ? () => tableSort(index) : undefined}
className={isSortable((child as ReactElement)) && "is-clickable"}
onClick={isSortable((child as ReactElement)) ? () => tableSort(index) : undefined}
onMouseEnter={() => setHoveredColumnIndex(index)}
onMouseLeave={() => setHoveredColumnIndex(undefined)}
key={index}
>
{child.props.header}
{isSortable(child) && renderSortIcon(child, ascending, shouldShowIcon(index))}
{(child as ReactElement).props.header}
{isSortable((child as ReactElement)) && renderSortIcon((child as ReactElement), ascending, shouldShowIcon(index))}
</th>
))}
</tr>