theme-ui#Label TypeScript Examples

The following examples show how to use theme-ui#Label. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: InputBox.tsx    From slice-machine with Apache License 2.0 6 votes vote down vote up
InputBox: React.FunctionComponent<InputBoxProps> = ({
  name,
  label,
  placeholder,
  error,
  dataCy,
}) => (
  <Box mb={3}>
    <Label htmlFor={name} mb={2}>
      {label}
    </Label>
    <Field
      name={name}
      type="text"
      placeholder={placeholder}
      as={Input}
      autoComplete="off"
      {...(dataCy ? { "data-cy": dataCy } : null)}
    />
    {error ? (
      <Text
        data-cy={dataCy ? `${dataCy}-error` : "input-error"}
        sx={{ color: "error", mt: 1 }}
      >
        {error}
      </Text>
    ) : null}
  </Box>
)
Example #2
Source File: create.tsx    From slice-machine with Apache License 2.0 6 votes vote down vote up
InputBox = ({
  name,
  label,
  placeholder,
  error,
}: {
  name: string;
  label: string;
  placeholder: string;
  error?: string;
}) => (
  <Box mb={3}>
    <Label htmlFor={name} mb={2}>
      {label}
    </Label>
    <Field
      name={name}
      type="text"
      placeholder={placeholder}
      as={Input}
      autoComplete="off"
    />
    {error ? <Text sx={{ color: "error", mt: 1 }}>{error}</Text> : null}
  </Box>
)
Example #3
Source File: update.tsx    From slice-machine with Apache License 2.0 6 votes vote down vote up
InputBox = ({
  name,
  label,
  placeholder,
  error,
  ...rest
}: {
  name: string;
  label: string;
  placeholder: string;
  error?: string;
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  [x: string]: any;
}) => (
  <Box mb={3}>
    <Label htmlFor={name} mb={2}>
      {label}
    </Label>
    <Field
      name={name}
      type="text"
      placeholder={placeholder}
      as={Input}
      autoComplete="off"
      {...rest}
    />
    {error ? <Text sx={{ color: "error", mt: 1 }}>{error}</Text> : null}
  </Box>
)
Example #4
Source File: Searchbar.tsx    From nextjs-shopify with MIT License 5 votes vote down vote up
SearchModalContent = (props: {
  initialSearch?: string
  onSearch: (term: string) => any
}) => {
  const [search, setSearch] = useState(
    props.initialSearch && String(props.initialSearch)
  )
  const [products, setProducts] = useState([] as any[])
  const [loading, setLoading] = useState(false)
  const getProducts = async (searchTerm: string) => {
    setLoading(true)
    const results = await searchProducts(
      shopifyConfig,
      String(searchTerm),
    )
    setSearch(searchTerm)
    setProducts(results)
    setLoading(false)
    if (searchTerm) {
      props.onSearch(searchTerm)
    }
  }

  useEffect(() => {
    if (search) {
      getProducts(search)
    }
  }, [])

  const throttleSearch = useCallback(throttle(getProducts), [])

  return (
    <Themed.div
      sx={{
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'center',
        p: [1, 2],
        width: '100%',
      }}
    >
      <Input
        type="search"
        sx={{ marginBottom: 15 }}
        defaultValue={props.initialSearch}
        placeholder="Search for products..."
        onChange={(event) => throttleSearch(event.target.value)}
      />
      {loading ? (
        <LoadingDots />
      ) : products.length ? (
        <>
          <Label>
            Search Results for "<strong>{search}</strong>"
          </Label>
          <ProductGrid
            cardProps={{
              imgHeight: 540,
              imgWidth: 540,
              imgPriority: false,
            }}
            products={products}
            offset={0}
            limit={products.length}
          ></ProductGrid>
        </>
      ) : (
        <span>
          {search ? (
            <>
              There are no products that match "<strong>{search}</strong>"
            </>
          ) : (
            <> </>
          )}
        </span>
      )}
    </Themed.div>
  )
}
Example #5
Source File: AddComment.tsx    From use-comments with MIT License 5 votes vote down vote up
AddComment = ({ onSubmit }: AddCommentProps) => {
  const [username, setUsername] = useState('');
  const [comment, setComment] = useState('');
  const [added, setAdded] = useState(false);

  return (
    <Box
      as="form"
      onSubmit={e => {
        console.log({ e });
        e.preventDefault();
        onSubmit({ content: comment, author: username });
        setAdded(true);
        setComment('');
        setUsername('');
      }}
    >
      <Label htmlFor="username">Username</Label>
      <Input
        name="username"
        id="username"
        placeholder="Jon Doe"
        value={username}
        onChange={e => setUsername(e.target.value)}
        sx={{ mb: 3 }}
        autoComplete="off"
      />
      <Label htmlFor="comment">Comment</Label>
      <Textarea
        name="comment"
        id="comment"
        rows={2}
        placeholder="Tell me what you think ?"
        value={comment}
        onChange={e => setComment(e.target.value)}
        sx={{ mb: 3, fontFamily: 'body' }}
      />
      <Button
        type="submit"
        sx={{
          mb: 3,
          ...((!username || !comment) && {
            pointerEvents: 'none',
            opacity: '0.5',
          }),
        }}
        disabled={!username || !comment}
      >
        Add comment
      </Button>
      {added && (
        <Message
          variant="primary"
          sx={{
            fontSize: '0.8em',
          }}
        >
          Thanks for your comment! ? Your comment status is{' '}
          <i>waiting for approval</i>. Comments on this website need to be
          approved before they are visible to others.
        </Message>
      )}
      <Divider />
    </Box>
  );
}
Example #6
Source File: CreateSliceModal.tsx    From slice-machine with Apache License 2.0 4 votes vote down vote up
CreateSliceModal: React.FunctionComponent<CreateSliceModalProps> = ({
  isOpen,
  isCreatingSlice,
  onSubmit,
  close,
  libraries,
  remoteSlices,
}) => {
  return (
    <ModalFormCard
      dataCy="create-slice-modal"
      isOpen={isOpen}
      widthInPx="530px"
      isLoading={isCreatingSlice}
      formId={formId}
      close={close}
      buttonLabel="Create"
      onSubmit={(values: FormValues) => onSubmit(values)}
      initialValues={{
        sliceName: "",
        from: libraries[0].name,
      }}
      validate={({ sliceName }) => {
        if (!sliceName) {
          return { sliceName: "Cannot be empty" };
        }
        if (!/^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$/.exec(sliceName)) {
          return { sliceName: "No special characters allowed" };
        }
        const cased = startCase(camelCase(sliceName)).replace(/\s/gm, "");
        if (cased !== sliceName.trim()) {
          return { sliceName: "Value has to be PascalCased" };
        }
        if (RESERVED_SLICE_NAME.includes(sliceName)) {
          return {
            sliceName: `${sliceName} is reserved for Slice Machine use`,
          };
        }

        const localNames = libraries.flatMap((lib) =>
          lib.components.map((slice) => slice.model.name)
        );
        const remoteNames = remoteSlices.map((slice) => slice.name);
        const usedNames = [...localNames, ...remoteNames];

        if (usedNames.includes(sliceName)) {
          return { sliceName: "Slice name is already taken." };
        }
      }}
      content={{
        title: "Create a new slice",
      }}
    >
      {({ touched, values, setFieldValue, errors }) => (
        <Box>
          <InputBox
            name="sliceName"
            label="Slice Name"
            placeholder="MySlice"
            error={touched.sliceName ? errors.sliceName : undefined}
            dataCy="slice-name-input"
          />
          <Label htmlFor="origin" sx={{ mb: 2 }}>
            Target Library
          </Label>
          <Select
            name="origin"
            options={libraries.map((v) => ({ value: v.name, label: v.name }))}
            onChange={(v: { label: string; value: string } | null) =>
              v ? setFieldValue("from", v.value) : null
            }
            defaultValue={{ value: values.from, label: values.from }}
            theme={(theme) => {
              return {
                ...theme,
                colors: {
                  ...theme.colors,
                  text: "text",
                  primary: "background",
                },
              };
            }}
          />
        </Box>
      )}
    </ModalFormCard>
  );
}
Example #7
Source File: VariationModal.tsx    From slice-machine with Apache License 2.0 4 votes vote down vote up
VariationModal: React.FunctionComponent<{
  isOpen: boolean;
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  onClose: () => any;
  onSubmit: (
    id: string,
    name: string,
    copiedVariation: Models.VariationSM
  ) => void;
  initialVariation: Models.VariationSM;
  variations: ReadonlyArray<Models.VariationSM>;
}> = ({ isOpen, onClose, onSubmit, initialVariation, variations }) => {
  const [errors, setErrors] = useState<{ [fieldKey: string]: string }>({});
  const [generatedId, setGeneratedId] = useState<string>("");
  const [isGeneratedFromName, setIsGeneratedFromName] = useState<boolean>(true);
  const [name, setName] = useState<string>("");
  const [origin, setOrigin] = useState<{ value: string; label: string }>({
    value: initialVariation.id,
    label: initialVariation.name,
  });

  function validateForm({
    id,
    name,
    origin,
  }: {
    id?: string;
    name?: string;
    origin: { value: string };
  }) {
    const idError = !(id && id.length) ? { id: "Required!" } : null;
    const existingIdError = variations.find((v) => v.id === id)
      ? { id: "This id already exists!" }
      : null;
    const nameError = !(name && name.length) ? { name: "Required!" } : null;
    const originError = !(
      origin.value.length && variations.find((v) => v.id === origin.value)
    )
      ? { id: "Yuu must select an existing variation!" }
      : null;
    const invalidIdError = id &&
      id.length &&
      !/^[A-Za-z0-9]+([A-Za-z0-9]+)*$/.exec(id) && {
        id: "No special characters allowed",
      };

    return {
      ...idError,
      ...existingIdError,
      ...nameError,
      ...originError,
      ...invalidIdError,
    };
  }

  function generateId(str: string) {
    const slug = Variation.generateId(str);
    setGeneratedId(slug);
  }

  function changeName(str: string) {
    setName(str);
    if (isGeneratedFromName) generateId(str);
  }

  function changeId(str: string) {
    setIsGeneratedFromName(false);
    generateId(str);
  }

  function handleClose() {
    reset();
    onClose();
  }

  function reset() {
    setGeneratedId("");
    setName("");
    setErrors({});
    setIsGeneratedFromName(true);
    setOrigin({ value: initialVariation.id, label: initialVariation.name });
  }

  useEffect(() => {
    reset();
  }, [initialVariation, isOpen]);

  // eslint-disable-next-line @typescript-eslint/require-await
  async function handleSubmit() {
    const data = { id: generatedId, name, origin };
    const errors = validateForm(data);
    if (Object.keys(errors).length) setErrors(errors);
    else {
      const copiedVariation = variations.find((v) => v.id === origin.value);
      if (copiedVariation) {
        onSubmit(generatedId, name, copiedVariation);
        handleClose();
      }
    }
  }

  return (
    <SliceMachineModal
      isOpen={isOpen}
      shouldCloseOnOverlayClick
      onRequestClose={() => handleClose()}
      contentLabel="Widget Form Modal"
      style={{
        content: {
          maxWidth: "700px",
        },
      }}
    >
      <Formik
        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
        initialValues={{ id: generatedId, name, origin } as any}
        onSubmit={handleSubmit}
      >
        <Form
          id={"variation-add"}
          onKeyDown={(e) => {
            if (e.key === "Enter") {
              e.preventDefault();
              // eslint-disable-next-line @typescript-eslint/no-floating-promises
              handleSubmit();
            }
          }}
        >
          <Box>
            <Card
              sx={{ textAlign: "left" }}
              HeaderContent={<Text as="h2">Add new Variation</Text>}
              FooterContent={
                <Flex sx={{ justifyContent: "flex-end" }}>
                  <Button onClick={handleClose} mr={2} variant="secondary">
                    Cancel
                  </Button>
                  <Button type="submit">Submit</Button>
                </Flex>
              }
              close={handleClose}
            >
              <Box sx={{ pb: 4, mt: 4 }}>
                <Label htmlFor="name" sx={{ mb: 1 }}>
                  Variation name*
                  {errors.name ? <Error msg={errors.name} /> : ""}
                </Label>
                <Field
                  autoComplete="off"
                  id="name"
                  name="name"
                  placeholder="e.g. Grid - With Icon"
                  as={Input}
                  maxLength={30}
                  value={name}
                  onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
                    changeName(e.currentTarget.value)
                  }
                />
                <Text>
                  It will appear here in Slice Machine, and in the page editor
                  in Prismic
                </Text>
              </Box>
              <Box sx={{ pb: 4 }}>
                <Label htmlFor="id" sx={{ mb: 1 }}>
                  Variation ID*{errors.id ? <Error msg={errors.id} /> : ""}
                </Label>
                <Field
                  autoComplete="off"
                  id="id"
                  name="id"
                  placeholder="e.g. GridWithIcon"
                  as={Input}
                  maxLength={30}
                  value={generatedId}
                  onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
                    changeId(e.currentTarget.value)
                  }
                />
                <Text>
                  It's generated automatically based on the variation name and
                  will appear in the API responses.
                </Text>
              </Box>

              <Box sx={{ pb: 4 }}>
                <Label htmlFor="origin" sx={{ mb: 1 }}>
                  Duplicate from
                </Label>
                <Select
                  name="origin"
                  options={variations.map((v) => ({
                    value: v.id,
                    label: v.name,
                  }))}
                  onChange={(v: { label: string; value: string } | null) => {
                    if (v) setOrigin(v);
                  }}
                  defaultValue={origin}
                  maxMenuHeight={150}
                  theme={(theme) => {
                    return {
                      ...theme,
                      colors: {
                        ...theme.colors,
                        text: "text",
                        primary: "background",
                      },
                    };
                  }}
                />
              </Box>
            </Card>
          </Box>
        </Form>
      </Formik>
    </SliceMachineModal>
  );
}
Example #8
Source File: ImagePreview.tsx    From slice-machine with Apache License 2.0 4 votes vote down vote up
ImagePreview: React.FC<ImagePreviewProps> = ({
  src,
  onScreenshot,
  imageLoading,
  onHandleFile,
  preventScreenshot,
}) => {
  const inputFile = useRef<HTMLInputElement>(null);
  const { isCheckingSetup } = useSelector((state: SliceMachineStoreType) => ({
    isCheckingSetup: isLoading(state, LoadingKeysEnum.CHECK_SIMULATOR),
  }));
  const [display, setDisplay] = useState(false);

  const handleFile = (file: File | undefined) => {
    if (inputFile?.current) {
      file && onHandleFile(file);
      inputFile.current.value = "";
    }
  };

  return (
    <div>
      <input
        id="input-file"
        type="file"
        ref={inputFile}
        style={{ display: "none" }}
        accept={acceptedImagesTypes.map((type) => `image/${type}`).join(",")}
        onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
          handleFile(e.target.files?.[0])
        }
      />
      <Flex
        sx={{
          position: "relative",
          alignItems: "center",
          justifyContent: "center",
          height: "290px",
          overflow: "hidden",
          backgroundImage: "url(/pattern.png)",
          backgroundColor: "headSection",
          backgroundRepeat: "repeat",
          backgroundSize: "20px",
          border: "1px solid #C9D0D8",
          boxShadow: "0px 8px 14px rgba(0, 0, 0, 0.1)",
          borderRadius: "4px",
        }}
        onMouseEnter={() => setDisplay(true)}
        onMouseLeave={() => setDisplay(false)}
      >
        {display || imageLoading || isCheckingSetup ? (
          <Flex
            sx={{
              width: "100%",
              height: "100%",
              position: "absolute",
              background: "rgba(0,0,0,.4)",
              alignItems: "center",
              justifyContent: "center",
              zIndex: "0",
            }}
          >
            {display ? (
              <Fragment>
                <Flex sx={{ flexDirection: "column" }}>
                  <Button
                    sx={{ mb: 3 }}
                    onClick={onScreenshot}
                    disabled={preventScreenshot}
                    variant={preventScreenshot ? "disabled" : "primary"}
                  >
                    Take screenshot
                  </Button>
                  <Label
                    htmlFor="input-file"
                    variant="buttons.primary"
                    sx={{ p: 2, borderRadius: "4px" }}
                  >
                    Custom screenshot
                  </Label>
                </Flex>
              </Fragment>
            ) : (
              <Spinner />
            )}
          </Flex>
        ) : null}
        {src ? (
          <MemoedImage src={src} />
        ) : (
          <Text
            sx={{
              display: "flex",
              flexDirection: "column",
              alignItems: "center",
            }}
          >
            <MdInfoOutline />
            You have no screenshot yet.
          </Text>
        )}
      </Flex>
    </div>
  );
}