Can't Style Grommet icon inside Anchor

1.2k views Asked by At

I'm new to Grommet with styled components. I Have already checked all the docs and can't find the solution.

PROBLEM

I have an Anchor with an icon and a label. Problem is I cannot target the icon for styling when i hover or it is active. Text / Label changes the styling though. How can i achieve/fix this?

I've also tried using styled components and putting an Icon and a Text inside a Grommet Box, but didn't work.

Please help!

import React from "react";
import { Anchor, Box, Text } from "grommet";
import styled from "styled-components";
import { Currency as PayoutIcon, Menu as MenuIcon } from "grommet-icons";

const StyledAnchor = styled(Anchor)`
  display: flex;
  height: 56px;
  color: #808191;
  padding: px 20px;
  border-radius: 12px;
  background: transparent;
  width: max-content;

  text-decoration: none;
  font-family: Inter;
  color: #808191;
  padding: 0px 20px;
  background: transparent;
  transition: all 0.25s ease 0s;
  text-decoration: none;
  border: none;

  &:visited {
    text-decoration: none;
    border: none;
  }

  &:hover {
    color: #6c5dd3;
    text-decoration: none;
  }
  &:active {
    color: #fff;
    background: #6c5dd3;
    text-decoration: none;
    border: none;
  }

  &:focus {
    color: #fff;
    background: #6c5dd3;
    textdecoration: none;
    border: none;
  }
`;
const SidebarItem = () => {
  return (
    // <Box color="#808191" hoverIndicator="true">
    <StyledAnchor
      color="#808191"
      label="Payouts"
      onClick={() => {}}
      href="#"
      icon={<PayoutIcon />}
    />
    // </Box>
  );
};

export default SidebarItem;

1

There are 1 answers

7
Shimi On BEST ANSWER

For the granularity of styles you are looking for, I think you can directly use the Button component instead of Anchor, nevertheless, the usage of Button is more compliant with accessibility standards (WCAG) for the Sidebar interactive elements that you are describing above.

Grommet works best with styled-components, yet grommet theme-ing is also very powerful, and knowing how to leverage its capabilities will help you use styled-components much less. Recently, grommet extended the Button theme (kind/default button), and that should do the trick for you with no sweat and no need for styled-components, here is an example:

import React, { useState } from "react";
import { render } from "react-dom";
import { Box, Grommet, Button } from "grommet";
import { Currency as PayoutIcon } from "grommet-icons";

const theme = {
  global: {
    colors: {
      myColor: "#808191",
      "background-contrast": {
        dark: "#FFFFFF14",
        light: "#0000000A"
      },
      "active-background": "background-contrast",
      "active-text": "red",
      icon: "text",
      // focus color is an important indication for keyboard navigation accessibility, 
      // it will be an ill advice to set it to undefined and remove focus 
      focus: "teal",
      text: {
        dark: "#C0CADC",
        light: "#444444"
      }
    }
  },
  button: {
    default: {
      color: "#808191",
      border: undefined,
      font: {
        weight: 700
      },
      padding: {
        horizontal: "12px",
        vertical: "6px"
      }
    },
    hover: {
      default: {
        background: {
          color: "background-contrast"
        },
        color: "brand"
      },
      secondary: {
        border: {
          width: "3px"
        },
        padding: {
          horizontal: "9px",
          vertical: "3px"
        }
      }
    },
    active: {
      background: {
        color: "aliceblue"
      },
      color: "teal",
      secondary: {
        border: {
          color: "transparent"
        }
      }
    }
  }
};

const SidebarItem = () => {
  const [active, setActive] = useState();
  return (
    <Button
      active={active}
      label="Payouts"
      icon={<PayoutIcon />}
      onClick={() => {
        setActive(!active);
      }}
      href="#"
    />
  );
};

export const App = () => {
  return (
    <Grommet theme={theme}>
      <Box pad="small" align="start">
        <SidebarItem />
      </Box>
    </Grommet>
  );
};

render(<App />, document.getElementById("root"));

Here is a codesandbox for running it live.

The Button has the granularity for active/hover/disabled and more, you can basically gain the same functionality in Anchor using the theme anchor.extend but this way is a much cleaner approach.