mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-12-22 16:29:51 +01:00
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:
committed by
GitHub
parent
09beb8cd3b
commit
27dbcbf28d
@@ -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
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user