teamdigitale/italia-app

View on GitHub
ts/features/design-system/core/DSButtons.tsx

Summary

Maintainability
F
1 wk
Test Coverage
import {
  ButtonLink,
  ButtonOutline,
  ButtonSolid,
  H4,
  HStack,
  IOColors,
  IconButton,
  IconButtonContained,
  IconButtonSolid,
  ListItemSwitch,
  VStack,
  useIOExperimentalDesign,
  useIOTheme
} from "@pagopa/io-app-design-system";
import * as React from "react";
import { useState } from "react";
import { Alert, StyleSheet, View } from "react-native";
import { DSComponentViewerBox } from "../components/DSComponentViewerBox";
import { DesignSystemScreen } from "../components/DesignSystemScreen";

const styles = StyleSheet.create({
  primaryBlockLegacy: {
    backgroundColor: IOColors.blue,
    padding: 16,
    borderRadius: 8
  },
  primaryBlock: {
    backgroundColor: IOColors["blueIO-500"],
    padding: 16,
    borderRadius: 16
  }
});

const onButtonPress = () => {
  Alert.alert("Alert", "Action triggered");
};

const sectionTitleMargin = 16;
const sectionMargin = 48;
const buttonBlockMargin = 24;
const buttonBlockInnerSpacing = 8;
const buttonBlockInnerSpacingLoose = 16;

export const DSButtons = () => {
  const { isExperimental } = useIOExperimentalDesign();
  const theme = useIOTheme();

  return (
    <DesignSystemScreen title={"Buttons"}>
      <VStack space={sectionMargin}>
        <VStack space={sectionTitleMargin}>
          <H4 color={theme["textHeading-default"]}>ButtonSolid</H4>
          {renderButtonSolid(isExperimental)}
        </VStack>

        <VStack space={sectionTitleMargin}>
          <H4 color={theme["textHeading-default"]}>ButtonOutline</H4>
          {renderButtonOutline(isExperimental)}
        </VStack>

        <VStack space={sectionTitleMargin}>
          <H4 color={theme["textHeading-default"]}>ButtonLink</H4>
          {renderButtonLink(isExperimental)}
        </VStack>

        <VStack space={sectionTitleMargin}>
          <H4 color={theme["textHeading-default"]}>IconButton</H4>
          {renderIconButton(isExperimental)}
        </VStack>

        <VStack space={sectionTitleMargin}>
          <H4 color={theme["textHeading-default"]}>IconButtonSolid</H4>
          {renderIconButtonSolid(isExperimental)}
        </VStack>

        <VStack space={sectionTitleMargin}>
          <H4 color={theme["textHeading-default"]}>
            IconButtonContained (Icebox)
          </H4>
          {renderIconButtonContained(isExperimental)}
        </VStack>
      </VStack>
    </DesignSystemScreen>
  );
};

const renderButtonSolid = (isExperimental: boolean) => (
  <VStack space={buttonBlockMargin}>
    <DSComponentViewerBox name="ButtonSolid · Primary variant">
      <VStack space={buttonBlockInnerSpacing}>
        <ButtonSolid
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button"}
          onPress={onButtonPress}
        />
        <ButtonSolid
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button"}
          icon="qrCode"
          onPress={onButtonPress}
        />
        <ButtonSolid
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button"}
          icon="qrCode"
          iconPosition="end"
          onPress={onButtonPress}
        />
        <View style={{ alignSelf: "center" }}>
          <ButtonSolid
            accessibilityLabel="Tap to trigger test alert"
            label={"Primary button (centered)"}
            onPress={onButtonPress}
          />
        </View>
      </VStack>
    </DSComponentViewerBox>
    <DSComponentViewerBox name="ButtonSolid · Primary, full width">
      <ButtonSolid
        fullWidth
        accessibilityLabel="Tap to trigger test alert"
        label={"Primary button (full width)"}
        onPress={onButtonPress}
      />
    </DSComponentViewerBox>

    <DSComponentViewerBox name="ButtonSolid · Primary · Full width, loading state">
      <LoadingSolidButtonExample />
    </DSComponentViewerBox>

    <DSComponentViewerBox name="ButtonSolid · Primary, disabled">
      <VStack space={buttonBlockInnerSpacing}>
        <ButtonSolid
          disabled
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button (disabled)"}
          onPress={onButtonPress}
        />
        <ButtonSolid
          disabled
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button (disabled)"}
          icon="qrCode"
          onPress={onButtonPress}
        />
      </VStack>
    </DSComponentViewerBox>

    <DSComponentViewerBox name="ButtonSolid · Danger variant">
      <VStack space={buttonBlockInnerSpacing}>
        <ButtonSolid
          color="danger"
          label={"Danger button"}
          onPress={onButtonPress}
          accessibilityLabel="Tap to trigger test alert"
        />

        <ButtonSolid
          color="danger"
          accessibilityLabel="Tap to trigger test alert"
          label={"Danger button"}
          icon="trashcan"
          onPress={onButtonPress}
        />

        <ButtonSolid
          color="danger"
          accessibilityLabel="Tap to trigger test alert"
          label={"Danger button"}
          icon="trashcan"
          iconPosition="end"
          onPress={onButtonPress}
        />
      </VStack>
    </DSComponentViewerBox>
    <DSComponentViewerBox name="ButtonSolid · Danger, full width">
      <ButtonSolid
        fullWidth
        color="danger"
        accessibilityLabel="Tap to trigger test alert"
        label={"Danger button (full width)"}
        onPress={onButtonPress}
      />
    </DSComponentViewerBox>

    <DSComponentViewerBox name="ButtonSolid · Danger, disabled">
      <VStack space={buttonBlockInnerSpacing}>
        <ButtonSolid
          color="danger"
          disabled
          accessibilityLabel="Tap to trigger test alert"
          label={"Danger button (disabled)"}
          onPress={onButtonPress}
        />

        <ButtonSolid
          color="danger"
          disabled
          accessibilityLabel="Tap to trigger test alert"
          label={"Danger button (disabled)"}
          icon="trashcan"
          onPress={onButtonPress}
        />

        <ButtonSolid
          color="danger"
          disabled
          fullWidth
          accessibilityLabel="Tap to trigger test alert"
          label={"Danger Button (full width, disabled)"}
          onPress={onButtonPress}
        />
      </VStack>
    </DSComponentViewerBox>

    <View
      style={isExperimental ? styles.primaryBlock : styles.primaryBlockLegacy}
    >
      <VStack space={buttonBlockMargin}>
        <DSComponentViewerBox
          name="ButtonSolid · Contrast variant"
          colorMode="dark"
        >
          <VStack space={buttonBlockInnerSpacing}>
            <ButtonSolid
              color="contrast"
              label={"Contrast button"}
              onPress={onButtonPress}
              accessibilityLabel="Tap to trigger test alert"
            />

            <ButtonSolid
              color="contrast"
              label={"Contrast button"}
              icon="add"
              onPress={onButtonPress}
              accessibilityLabel="Tap to trigger test alert"
            />

            <ButtonSolid
              color="contrast"
              label={"Contrast button"}
              icon="add"
              iconPosition="end"
              onPress={onButtonPress}
              accessibilityLabel="Tap to trigger test alert"
            />
          </VStack>
        </DSComponentViewerBox>

        <DSComponentViewerBox
          name="ButtonSolid · Contrast, full width"
          colorMode="dark"
        >
          <ButtonSolid
            fullWidth
            color="contrast"
            label={"Contrast button"}
            onPress={onButtonPress}
            accessibilityLabel="Tap to trigger test alert"
          />
        </DSComponentViewerBox>

        <DSComponentViewerBox
          name="ButtonSolid · Contrast, full width, loading state"
          colorMode="dark"
        >
          <ButtonSolid
            fullWidth
            loading
            color="contrast"
            label={"Contrast button"}
            onPress={onButtonPress}
            accessibilityLabel="Tap to trigger test alert"
          />
        </DSComponentViewerBox>

        <DSComponentViewerBox
          name="ButtonSolid · Contrast, disabled"
          colorMode="dark"
        >
          <VStack space={buttonBlockInnerSpacing}>
            <ButtonSolid
              disabled
              color="contrast"
              label={"Contrast button (disabled)"}
              onPress={onButtonPress}
              accessibilityLabel="Tap to trigger test alert"
            />
            <ButtonSolid
              disabled
              color="contrast"
              label={"Contrast button (disabled)"}
              icon="add"
              onPress={onButtonPress}
              accessibilityLabel="Tap to trigger test alert"
            />
            <ButtonSolid
              fullWidth
              disabled
              color="contrast"
              accessibilityLabel="Tap to trigger test alert"
              label={"Contrast button (full width, disabled)"}
              onPress={onButtonPress}
            />
          </VStack>
        </DSComponentViewerBox>
      </VStack>
    </View>
  </VStack>
);

const renderButtonOutline = (isExperimental: boolean) => (
  <VStack space={buttonBlockMargin}>
    <DSComponentViewerBox name="ButtonOutline · Primary variant">
      <VStack space={buttonBlockInnerSpacing}>
        <ButtonOutline
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button"}
          onPress={onButtonPress}
        />

        <ButtonOutline
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button"}
          icon="arrowLeft"
          onPress={onButtonPress}
        />

        <ButtonOutline
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button"}
          icon="arrowRight"
          iconPosition="end"
          onPress={onButtonPress}
        />

        <View style={{ alignSelf: "center" }}>
          <ButtonOutline
            accessibilityLabel="Tap to trigger test alert"
            label={"Primary button (centered)"}
            onPress={onButtonPress}
          />
        </View>
      </VStack>
    </DSComponentViewerBox>
    <DSComponentViewerBox name="ButtonOutline · Primary, full width">
      <ButtonOutline
        fullWidth
        accessibilityLabel="Tap to trigger test alert"
        label={"Primary button (full width)"}
        onPress={onButtonPress}
      />
    </DSComponentViewerBox>
    <DSComponentViewerBox name="ButtonOutline · Primary, disabled">
      <VStack space={buttonBlockInnerSpacing}>
        <ButtonOutline
          disabled
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button (disabled)"}
          onPress={onButtonPress}
        />

        <ButtonOutline
          disabled
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button (disabled)"}
          icon="arrowRight"
          iconPosition="end"
          onPress={onButtonPress}
        />
      </VStack>
    </DSComponentViewerBox>

    {!isExperimental && (
      <>
        <DSComponentViewerBox name="ButtonOutline · Danger variant">
          <VStack space={buttonBlockInnerSpacing}>
            <ButtonOutline
              color="danger"
              label={"Danger button"}
              onPress={onButtonPress}
              accessibilityLabel="Tap to trigger test alert"
            />

            <ButtonOutline
              color="danger"
              label={"Danger button"}
              icon="trashcan"
              accessibilityLabel="Tap to trigger test alert"
              onPress={onButtonPress}
            />

            <ButtonOutline
              color="danger"
              label={"Danger button"}
              icon="trashcan"
              iconPosition="end"
              accessibilityLabel="Tap to trigger test alert"
              onPress={onButtonPress}
            />
          </VStack>
        </DSComponentViewerBox>
        <DSComponentViewerBox name="ButtonOutline · Danger, full width">
          <ButtonOutline
            fullWidth
            color="danger"
            accessibilityLabel="Tap to trigger test alert"
            label={"Danger button (full width)"}
            onPress={() => {
              alert("Action triggered");
            }}
          />
        </DSComponentViewerBox>

        <DSComponentViewerBox name="ButtonOutline · Danger, disabled">
          <VStack space={buttonBlockInnerSpacing}>
            <ButtonOutline
              color="danger"
              disabled
              accessibilityLabel="Tap to trigger test alert"
              label={"Danger button (disabled)"}
              onPress={() => {
                alert("Action triggered");
              }}
            />
            <ButtonOutline
              color="danger"
              disabled
              fullWidth
              accessibilityLabel="Tap to trigger test alert"
              label={"Danger Button (full width, disabled)"}
              onPress={() => {
                alert("Action triggered");
              }}
            />
          </VStack>
        </DSComponentViewerBox>
      </>
    )}

    <View
      style={isExperimental ? styles.primaryBlock : styles.primaryBlockLegacy}
    >
      <VStack space={buttonBlockMargin}>
        <DSComponentViewerBox
          name="ButtonOutline · Contrast variant"
          colorMode="dark"
        >
          <VStack space={buttonBlockInnerSpacing}>
            <ButtonOutline
              color="contrast"
              label={"Contrast button"}
              onPress={onButtonPress}
              accessibilityLabel="Tap to trigger test alert"
            />

            <ButtonOutline
              color="contrast"
              label={"Contrast button"}
              icon="arrowLeft"
              onPress={onButtonPress}
              accessibilityLabel="Tap to trigger test alert"
            />

            <ButtonOutline
              color="contrast"
              label={"Contrast button"}
              icon="arrowRight"
              iconPosition="end"
              onPress={onButtonPress}
              accessibilityLabel="Tap to trigger test alert"
            />
          </VStack>
        </DSComponentViewerBox>

        <DSComponentViewerBox
          name="ButtonOutline · Contrast, full width"
          colorMode="dark"
        >
          <ButtonOutline
            fullWidth
            color="contrast"
            label={"Contrast button"}
            onPress={onButtonPress}
            accessibilityLabel="Tap to trigger test alert"
          />
        </DSComponentViewerBox>

        <DSComponentViewerBox
          name="ButtonOutline · Contrast, disabled"
          colorMode="dark"
        >
          <VStack space={buttonBlockInnerSpacing}>
            <ButtonOutline
              disabled
              color="contrast"
              label={"Contrast button (disabled)"}
              onPress={onButtonPress}
              accessibilityLabel="Tap to trigger test alert"
            />
            <ButtonOutline
              disabled
              color="contrast"
              label={"Contrast button (disabled)"}
              icon="arrowRight"
              iconPosition="end"
              onPress={onButtonPress}
              accessibilityLabel="Tap to trigger test alert"
            />
          </VStack>
        </DSComponentViewerBox>
      </VStack>
    </View>
  </VStack>
);

const renderButtonLink = (isExperimental: boolean) => (
  <VStack space={buttonBlockMargin}>
    <DSComponentViewerBox name="ButtonLink · Primary variant">
      <VStack space={buttonBlockInnerSpacingLoose}>
        <ButtonLink
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button"}
          onPress={onButtonPress}
        />

        <ButtonLink
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button"}
          icon="starEmpty"
          onPress={onButtonPress}
        />

        <ButtonLink
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button"}
          icon="starEmpty"
          iconPosition="end"
          onPress={onButtonPress}
        />

        <View style={{ alignSelf: "center" }}>
          <ButtonLink
            accessibilityLabel="Tap to trigger test alert"
            label={"Primary button (centered)"}
            onPress={onButtonPress}
          />
        </View>
      </VStack>
    </DSComponentViewerBox>
    <DSComponentViewerBox name="ButtonLink · Primary, disabled">
      <VStack space={buttonBlockInnerSpacingLoose}>
        <ButtonLink
          disabled
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button (disabled)"}
          onPress={onButtonPress}
        />

        <ButtonLink
          disabled
          accessibilityLabel="Tap to trigger test alert"
          label={"Primary button (disabled)"}
          icon="starEmpty"
          iconPosition="end"
          onPress={onButtonPress}
        />
      </VStack>
    </DSComponentViewerBox>

    <View
      style={isExperimental ? styles.primaryBlock : styles.primaryBlockLegacy}
    >
      <VStack space={buttonBlockMargin}>
        <DSComponentViewerBox
          name="ButtonLink · Contrast variant"
          colorMode="dark"
        >
          <VStack space={buttonBlockInnerSpacingLoose}>
            <ButtonLink
              color="contrast"
              accessibilityLabel="Tap to trigger test alert"
              label={"Primary button"}
              onPress={onButtonPress}
            />

            <ButtonLink
              color="contrast"
              accessibilityLabel="Tap to trigger test alert"
              label={"Primary button"}
              icon="starEmpty"
              onPress={onButtonPress}
            />

            <ButtonLink
              color="contrast"
              accessibilityLabel="Tap to trigger test alert"
              label={"Primary button"}
              icon="starEmpty"
              iconPosition="end"
              onPress={onButtonPress}
            />

            <View style={{ alignSelf: "center" }}>
              <ButtonLink
                color="contrast"
                accessibilityLabel="Tap to trigger test alert"
                label={"Primary button (centered)"}
                onPress={onButtonPress}
              />
            </View>
          </VStack>
        </DSComponentViewerBox>

        <DSComponentViewerBox
          name="ButtonLink · Contrast, disabled"
          colorMode="dark"
        >
          <VStack space={buttonBlockInnerSpacingLoose}>
            <ButtonLink
              disabled
              color="contrast"
              accessibilityLabel="Tap to trigger test alert"
              label={"Primary button (disabled)"}
              onPress={onButtonPress}
            />

            <ButtonLink
              disabled
              color="contrast"
              accessibilityLabel="Tap to trigger test alert"
              label={"Primary button (disabled)"}
              icon="starEmpty"
              iconPosition="end"
              onPress={onButtonPress}
            />
          </VStack>
        </DSComponentViewerBox>
      </VStack>
    </View>
  </VStack>
);

const renderIconButton = (isExperimental: boolean) => (
  <VStack space={buttonBlockMargin}>
    <DSComponentViewerBox name="IconButton · Primary variant">
      <HStack space={buttonBlockInnerSpacingLoose}>
        <IconButton
          accessibilityLabel="Tap to trigger test alert"
          icon="search"
          onPress={onButtonPress}
        />

        <IconButton
          accessibilityLabel="Tap to trigger test alert"
          icon="help"
          onPress={onButtonPress}
        />

        <IconButton
          accessibilityLabel="Tap to trigger test alert"
          icon="help"
          disabled
          onPress={onButtonPress}
        />
      </HStack>
    </DSComponentViewerBox>
    <DSComponentViewerBox name="IconButton · Neutral variant">
      <HStack space={buttonBlockInnerSpacingLoose}>
        <IconButton
          color="neutral"
          accessibilityLabel="Tap to trigger test alert"
          icon="search"
          onPress={onButtonPress}
        />

        <IconButton
          color="neutral"
          accessibilityLabel="Tap to trigger test alert"
          icon="help"
          onPress={onButtonPress}
        />

        <IconButton
          color="neutral"
          accessibilityLabel="Tap to trigger test alert"
          icon="help"
          disabled
          onPress={onButtonPress}
        />
      </HStack>
    </DSComponentViewerBox>
    <View
      style={isExperimental ? styles.primaryBlock : styles.primaryBlockLegacy}
    >
      <DSComponentViewerBox
        name="IconButton · Contrast variant"
        colorMode="dark"
      >
        <HStack space={buttonBlockInnerSpacingLoose}>
          <IconButton
            color="contrast"
            accessibilityLabel="Tap to trigger test alert"
            icon="search"
            onPress={onButtonPress}
          />

          <IconButton
            color="contrast"
            accessibilityLabel="Tap to trigger test alert"
            icon="help"
            onPress={onButtonPress}
          />

          <IconButton
            color="contrast"
            accessibilityLabel="Tap to trigger test alert"
            icon="help"
            disabled
            onPress={onButtonPress}
          />
        </HStack>
      </DSComponentViewerBox>
    </View>
  </VStack>
);

const renderIconButtonSolid = (isExperimental: boolean) => (
  <VStack space={buttonBlockMargin}>
    <DSComponentViewerBox name="IconButtonSolid · Primary variant, large">
      <HStack space={buttonBlockInnerSpacingLoose}>
        <IconButtonSolid
          color="primary"
          accessibilityLabel="Tap to trigger test alert"
          icon="arrowBottom"
          onPress={onButtonPress}
        />

        <IconButtonSolid
          color="primary"
          accessibilityLabel="Tap to trigger test alert"
          icon="arrowBottom"
          disabled
          onPress={onButtonPress}
        />
      </HStack>
    </DSComponentViewerBox>
    <View
      style={isExperimental ? styles.primaryBlock : styles.primaryBlockLegacy}
    >
      <DSComponentViewerBox
        name="IconButtonSolid · Contrast variant, large"
        colorMode="dark"
      >
        <HStack space={buttonBlockInnerSpacingLoose}>
          <IconButtonSolid
            color="contrast"
            accessibilityLabel="Tap to trigger test alert"
            icon="arrowBottom"
            onPress={onButtonPress}
          />

          <IconButtonSolid
            color="contrast"
            accessibilityLabel="Tap to trigger test alert"
            icon="arrowBottom"
            disabled
            onPress={onButtonPress}
          />
        </HStack>
      </DSComponentViewerBox>
    </View>
  </VStack>
);

const renderIconButtonContained = (isExperimental: boolean) => (
  <VStack space={buttonBlockMargin}>
    <DSComponentViewerBox name="IconButtonContained · Primary variant">
      <HStack space={buttonBlockInnerSpacing}>
        <IconButtonContained
          accessibilityLabel="Tap to trigger test alert"
          icon="help"
          onPress={onButtonPress}
        />

        <IconButtonContained
          accessibilityLabel="Tap to trigger test alert"
          icon="help"
          disabled
          onPress={onButtonPress}
        />
      </HStack>
    </DSComponentViewerBox>
    <DSComponentViewerBox name="IconButtonContained · Neutral variant">
      <HStack space={buttonBlockInnerSpacing}>
        <IconButtonContained
          color="neutral"
          accessibilityLabel="Tap to trigger test alert"
          icon="help"
          onPress={onButtonPress}
        />

        <IconButtonContained
          color="neutral"
          accessibilityLabel="Tap to trigger test alert"
          icon="help"
          disabled
          onPress={onButtonPress}
        />
      </HStack>
    </DSComponentViewerBox>
    <View
      style={isExperimental ? styles.primaryBlock : styles.primaryBlockLegacy}
    >
      <DSComponentViewerBox
        name="IconButtonContained · Contrast variant"
        colorMode="dark"
      >
        <HStack space={buttonBlockInnerSpacing}>
          <IconButtonContained
            color="contrast"
            accessibilityLabel="Tap to trigger test alert"
            icon="help"
            onPress={onButtonPress}
          />

          <IconButtonContained
            color="contrast"
            accessibilityLabel="Tap to trigger test alert"
            icon="help"
            disabled
            onPress={onButtonPress}
          />
        </HStack>
      </DSComponentViewerBox>
    </View>
  </VStack>
);

const LoadingSolidButtonExample = () => {
  const [isEnabled, setIsEnabled] = useState(false);
  const toggleSwitch = () => setIsEnabled(previousState => !previousState);

  return (
    <View>
      <ButtonSolid
        fullWidth
        loading={isEnabled}
        accessibilityLabel="Tap to trigger test alert"
        label={"Primary button"}
        onPress={() => setIsEnabled(true)}
      />
      <ListItemSwitch
        label="Enable loading state"
        onSwitchValueChange={toggleSwitch}
        value={isEnabled}
      />
    </View>
  );
};