Skip to content

Commit

Permalink
Re-implement (Action)MenuButton success and loading states (#677)
Browse files Browse the repository at this point in the history
* Fix TextInput.stories actions

* Implement success and loading state

Also success variant

* Use new ActionMenuItem/MenuButton API in stories

* Remove unused imports

* Add loading and left content story

* Add right content

- Refactor internal structure of menubutton

* Add prettier caching

* Set success variant color to black

* Add success variant in stories
  • Loading branch information
lindskogen authored Nov 23, 2023
1 parent 6c8115b commit a070488
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 75 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"check-builds": "node scripts/check-builds.js",
"check-imports": "node scripts/check-imports.js",
"check-prettier": "prettier -l 'packages/**/src/**/*.{ts,tsx,css}' --ignore-path .gitignore --no-config",
"prettier": "prettier --write 'packages/**/src/**/*.{ts,tsx,css}' --ignore-path .gitignore --no-config",
"prettier": "prettier --write 'packages/**/src/**/*.{ts,tsx,css}' --ignore-path .gitignore --no-config --cache",
"check-circular-deps": "find ./packages -type d -name dist | xargs yarn dpdm --transform --warning false --tree false --exit-code circular:1",
"check-circular-deps-stories": "find ./packages -type f -name '*.stories.tsx' | xargs yarn dpdm --transform --warning false --tree false --exit-code circular:1"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ export const AsyncItem = () => {
<ActionMenuItem
label={saved ? "Saved" : loading ? "Saving..." : "Save"}
leftIcon={stenaSave}
success={saved}
loading={loading}
onClick={start}
/>
<ActionMenuItem
Expand All @@ -219,6 +221,8 @@ export const AsyncItem = () => {
? "Saving with danger..."
: "Save dangerously"
}
success={savedDanger}
loading={loadingDanger}
leftIcon={isDangerOn ? stenaSave : faSadCry}
onClick={startDanger}
variant={"danger"}
Expand All @@ -239,6 +243,8 @@ export const AsyncItem = () => {
? "Saving with success..."
: "Save successfully"
}
success={savedSuccess}
loading={loadingSuccess}
leftIcon={isSuccessOn ? stenaSave : faSadCry}
onClick={startSuccess}
disabled={!isSuccessOn}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,40 @@
background-color: var(--current-background-color);

.label {
text-align: start;
flex: 1;
font-size: var(--current-text-size, var(--swui-font-size-medium));
}

.buttonLink {
display: flex;
align-items: center;
text-decoration: none;
}

.button {
display: inline-flex;
align-items: center;
justify-content: space-between;

border: 0;
padding: 4px 0;
cursor: pointer;
border-radius: var(--swui-max-border-radius);
background: var(--current-background-color);
min-height: var(--swui-menu-button-item-height);
min-width: var(--swui-menu-button-item-height);

padding: 0 calc(1 * var(--swui-metrics-indent));

&.hasLabel {
padding: 0 calc(2 * var(--swui-metrics-indent));
}

&.success {
--current-text-color: var(--swui-menu-button-text-color);
--current-background-color-hover: var(--lhds-color-green-100);
--current-background-color-focus: var(--lhds-color-green-100);
--current-background-color-active: var(--lhds-color-ui-200);
}

&.danger {
--current-text-color: var(--lhds-color-red-600);
--current-background-color-hover: var(--lhds-color-red-100);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { MenuButton } from "./MenuButton";
import { MenuButtonLink } from "./MenuButtonLink";
import { MenuButtonGroupBox } from "./MenuButtonGroupBox";
import { Column, Text, useBoolean } from "@stenajs-webui/core";
import {
Column,
Text,
Txt,
useBoolean,
useTimeoutState,
} from "@stenajs-webui/core";
import * as React from "react";
import cx from "classnames";
import {
stenaCopy,
stenaExternalLink,
stenaStatisticsBar,
} from "../../../../icons/generated/CommonIcons";
import { InputSpinner } from "../../spinner/InputSpinner";

export default {
title: "elements/MenuButton",
Expand All @@ -20,6 +26,7 @@ export default {

export const Overview = () => {
const [expanded, , , toggle] = useBoolean(false);
const [copyClicked, setCopyClicked] = useTimeoutState(false, 3000);
return (
<Column width={"230px"} gap>
<MenuButton label={"Just a button"} />
Expand All @@ -32,6 +39,16 @@ export const Overview = () => {

<MenuButton label={"I am dangerous"} variant={"danger"} />

<MenuButton label={"I am success"} variant={"success"} />

<MenuButton
label={"Copy value"}
success={copyClicked}
variant={copyClicked ? "success" : undefined}
leftIcon={stenaCopy}
onClick={() => setCopyClicked(true)}
/>

<MenuButtonLink
label={"Link to google"}
href={"https://www.google.com"}
Expand Down Expand Up @@ -92,7 +109,8 @@ export const Overview = () => {
<Text>I am great really content!</Text>
</MenuButton>

<MenuButton left={<InputSpinner />} label={"Content left"} />
<MenuButton loading label={"Loading"} />
<MenuButton left={<Txt>kg</Txt>} label={"Content left"} />
</Column>
);
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import * as React from "react";
import { forwardRef, ReactNode } from "react";
import {
Box,
ButtonElementProps,
Indent,
Row,
Space,
} from "@stenajs-webui/core";
import { Box, ButtonElementProps, Space } from "@stenajs-webui/core";
import cx from "classnames";
import styles from "./MenuButton.module.css";
import { cssColor } from "@stenajs-webui/theme";
Expand All @@ -18,8 +12,10 @@ import {
stenaAngleDown,
stenaAngleUp,
} from "../../../../icons/generated/ArrowIcons";
import { stenaCheck } from "../../../../icons/generated/CommonIcons";
import { InputSpinner } from "../../spinner/InputSpinner";

export type MenuButtonVariant = "standard" | "danger";
export type MenuButtonVariant = "standard" | "danger" | "success";

export interface MenuButtonProps extends ButtonElementProps {
label: string;
Expand All @@ -29,8 +25,11 @@ export interface MenuButtonProps extends ButtonElementProps {
leftIcon?: IconDefinition;
left?: ReactNode;
right?: ReactNode;
rightIcon?: IconDefinition;
variant?: MenuButtonVariant;
children?: ReactNode;
success?: boolean;
loading?: boolean;
}

export const MenuButton = forwardRef<HTMLButtonElement, MenuButtonProps>(
Expand All @@ -42,11 +41,14 @@ export const MenuButton = forwardRef<HTMLButtonElement, MenuButtonProps>(
selected,
className,
leftIcon,
rightIcon,
children,
disabled,
variant = "standard",
left,
right,
success = false,
loading = false,
...buttonProps
},
ref
Expand All @@ -66,37 +68,28 @@ export const MenuButton = forwardRef<HTMLButtonElement, MenuButtonProps>(
selected && styles.selected,
disabled && styles.disabled,
styles[variant],
label ? styles.hasLabel : undefined,
iconOnly && styles.iconOnly,
className
)}
disabled={disabled}
ref={ref}
{...buttonProps}
>
<Row
justifyContent={iconOnly ? "center" : "space-between"}
alignItems={"center"}
indent={label ? 2 : 1}
>
<MenuButtonContent
label={label}
leftIcon={leftIcon}
left={left}
<MenuButtonContent
label={label}
leftIcon={leftIcon}
left={left}
right={loading ? <InputSpinner /> : right}
rightIcon={success ? stenaCheck : rightIcon}
/>
{expandable && (
<Icon
icon={expanded ? stenaAngleUp : stenaAngleDown}
size={18}
color={cssColor("--lhds-color-blue-600")}
/>
<Row gap={1} alignItems={"center"}>
{right && <Row alignItems={"center"}>{right}</Row>}
{expandable && (
<Row>
<Indent />
<Icon
icon={expanded ? stenaAngleUp : stenaAngleDown}
size={18}
color={cssColor("--lhds-color-blue-600")}
/>
</Row>
)}
</Row>
</Row>
)}
</button>
</Box>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from "react";
import { forwardRef, ReactNode } from "react";
import { AnchorElementProps, Box, Row } from "@stenajs-webui/core";
import { AnchorElementProps, Box } from "@stenajs-webui/core";
import cx from "classnames";
import styles from "./MenuButton.module.css";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
Expand Down Expand Up @@ -56,18 +56,15 @@ export const MenuButtonLink = forwardRef<
},
ref
) {
const innerChildren = (
<Row justifyContent={"space-between"} indent={label ? 2 : 1}>
<MenuButtonContent label={label} leftIcon={leftIcon} />
</Row>
);
const innerChildren = <MenuButtonContent label={label} leftIcon={leftIcon} />;

const renderLinkProps = "renderLink" in linkProps ? linkProps : undefined;
const noRenderLinkProps = "selected" in linkProps ? linkProps : undefined;

const linkClassName = cx(
styles.button,
styles.buttonLink,
label ? styles.hasLabel : undefined,
disabled && styles.disabled,
noRenderLinkProps?.selected && styles.selected,
styles[variant],
Expand Down Expand Up @@ -96,11 +93,7 @@ export const MenuButtonLink = forwardRef<
);

return (
<Box
className={cx(styles.menuButton)}
width={"100%"}
justifyContent={"space-between"}
>
<Box className={cx(styles.menuButton)} width={"100%"}>
{link}
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,20 @@ export interface MenuButtonContentProps {
leftIcon?: IconDefinition;
left?: ReactNode;
label: string;
rightIcon?: IconDefinition;
right?: ReactNode;
}

export const MenuButtonContent: React.FC<MenuButtonContentProps> = ({
label,
leftIcon,
left,
right,
rightIcon,
}) => {
return (
<Row gap={2} alignItems={"center"}>
{left}
{leftIcon && !left && (
<>
<Box alignItems={"center"} justifyContent={"center"} width={"20px"}>
<Icon
icon={leftIcon}
size={20}
color={"var(--current-text-color)"}
data-hover={true}
/>
</Box>
</>
)}
<Row flex={1} gap={2} alignItems={"center"}>
<MenuButtonAside content={left} icon={leftIcon} />
{label && (
<Text
variant={"bold"}
Expand All @@ -40,6 +32,32 @@ export const MenuButtonContent: React.FC<MenuButtonContentProps> = ({
{label}
</Text>
)}
<MenuButtonAside content={right} icon={rightIcon} />
</Row>
);
};

function MenuButtonAside({
content,
icon,
}: {
content?: ReactNode;
icon?: IconDefinition;
}) {
if (content) {
return <>{content}</>;
} else if (icon) {
return (
<Box alignItems={"center"} justifyContent={"center"} width={"20px"}>
<Icon
icon={icon}
size={20}
color={"var(--current-text-color)"}
data-hover={true}
/>
</Box>
);
}

return null;
}
Loading

0 comments on commit a070488

Please sign in to comment.