如何在CSS中更改使用prop over transform选项创建的图标?

huangapple go评论75阅读模式
英文:

How Can I change the icon made with prop over transform option in css?

问题

我有一个带有定义主题和图标的React折叠组件。我需要通过样式组件和storybook中的transform选项来更改单击时的图标。此外,单击时标题div和内容div的背景颜色也需要更改。

我已经定义了颜色属性和图标,但不确定接下来该怎么做?

这是我的React组件:

import { string, node, oneOf, bool } from "prop-types";
import * as Styled from "./Accordion.styled";
import Icon from "design-system/components/icon";
import React, { useState } from 'react';

const Accordion = ({ children, icon, text, button,
  color, activeColor, }) =>  {
  const [isActive, setIsActive] = useState(false);
  return (
    <Styled.Accordion
      color={color}
    >
      <Styled.Title onClick={() => setIsActive(!isActive)}
        color={isActive ? activeColor : color}
      >
        {text}
        <Styled.Icon color={color}>
          <Icon name={icon}/>
        </Styled.Icon> 
      </Styled.Title>
      {isActive &&
        <Styled.Content
          color={isActive ? activeColor : color}
        >
          {children} 
          {button}
        </Styled.Content>
      }
    </Styled.Accordion>
  );
}

Accordion.propTypes = {
  text: string.isRequired,
  children: node.isRequired,
  icon: string,
  name: string,
  button: node,
  color: oneOf(["primary", "neutrals", "grey"]),
  activeColor: oneOf(["primary", "neutrals", "grey"]),
}

Accordion.defaultProps = {
  children: null,
  icon: null,
  name: null,
  button: null,
  color: "",
  activeColor: "",
}

export default Accordion;

这是样式:

import styled from "@emotion/styled";
import { css } from "@emotion/react";

export const Accordion = styled.div`
 display: flex;
 text-decoration: none;
 width: auto;
 height: auto;
 flex-direction: column;
 align-items: flex-start;
 justify-content: start;
 border-radius: 30px;
`

export const Title = styled.div`
  width: auto;
  height: auto;
  display: inline-flex;
  gap: 161px;
  border-radius: 10px 10px 0px 0px;
  padding: 10px 0px 0px 10px;
  color: ${({ color, theme }) => {
    switch (color) {
      case "grey":
        return theme.colors.grey[600]
      case "neutrals":
        return theme.colors.neutrals[100]
      case "primary":
        return theme.colors.primary[500]
      default:
        return theme.colors.grey[600]
    };
  }};
  background-color: ${({ color, theme }) => {
    switch (color) {
      case "grey":
        return theme.colors.grey[600]
      case "neutrals":
        return theme.colors.neutrals[100]
      case "primary":
        return theme.colors.primary[500]
      default:
        return theme.colors.grey[600]
    }
  }};
`

export const Content = styled.div`
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: start;
  width: auto;
  height: auto;
  border-radius: 0px 0px 10px 10px;
  padding: 10px 100px 0px 10px;
  background-color: ${({ color, theme }) => {
    switch (color) {
      case "grey":
        return theme.colors.grey[600]
      case "neutrals":
        return theme.colors.neutrals[100]
      case "primary":
        return theme.colors.primary[500]
      default:
        return theme.colors.grey[600]
    }
  }};
  color: ${({ color, theme }) => {
    switch (color) {
      case "grey":
        return theme.colors.grey[600]
      case "neutrals":
        return theme.colors.neutrals[100]
      case "primary":
        return theme.colors.primary[500]
      default:
        return theme.colors.grey[600]
    }
  }};
`

export const Icon = styled.div`
  display: flex;
  align-items: flex-start;
  width: auto;
  height: auto;
`
英文:

I have a React accordion component with defined themes and icons.
I need to change the icon with on click via transform option in styled components and storybook.

Also upon clicking, the background color of the title div and content div needs to change.

I have defined color prop and icon, but not sure what is next?

Here is my React component:

import { string, node, oneOf, bool } from &quot;prop-types&quot;
import * as Styled from &quot;./Accordion.styled&quot;
import Icon from &quot;design-system/components/icon&quot;
import React, { useState } from &#39;react&#39;
const Accordion = ({ children, icon, text, button,
color, activeColor, }) =&gt;  {
const [isActive, setIsActive] = useState(false);
return (
&lt;Styled.Accordion
color={color}
&gt;
&lt;Styled.Title onClick={() =&gt; setIsActive(!isActive)}
color={isActive ? activeColor : color}
&gt; {text}
&lt;Styled.Icon color={color}&gt;
&lt;Icon name={icon}/&gt;
&lt;/Styled.Icon&gt; 
&lt;/Styled.Title&gt;
{isActive &amp;&amp;
&lt;Styled.Content
color={isActive ? activeColor : color} &gt;
{children} 
{button}
&lt;/Styled.Content&gt;
}
&lt;/Styled.Accordion&gt;
);
}
Accordion.propTypes = {
text: string.isRequired,
children: node.isRequired,
icon: string,
name: string,
button: node,
color: oneOf([&quot;primary&quot;, &quot;neutrals&quot;, &quot;grey&quot;]),
activeColor: oneOf([&quot;primary&quot;, &quot;neutrals&quot;, &quot;grey&quot;]),
}
Accordion.defaultProps = {
children: null,
icon: null,
name: null,
button: null,
color: &quot;&quot;,
activeColor: &quot;&quot;,
}
export default Accordion

and here are the styles:

import styled from &quot;@emotion/styled&quot;
import { css } from &quot;@emotion/react&quot;
export const Accordion = styled.div`
display: flex;
text-decoration: none;
width: auto;
height: auto;
flex-direction: column;
align-items: flex-start;
justify-content: start;
border-radius: 30px;
`
export const Title = styled.div`
width: auto;
height: auto;
display: inline-flex;
gap: 161px;
border-radius: 10px 10px 0px 0px;
padding: 10px 0px 0px 10px;
color: ${({ color, theme }) =&gt; {
switch (color) {
case &quot;grey&quot;:
return theme.colors.grey[600]
case &quot;neutrals&quot;:
return theme.colors.neutrals[100]
case &quot;primary&quot;:
return theme.colors.primary[500]
default:
return theme.colors.grey[600]
};
}};
background-color: ${({ color, theme }) =&gt; {
switch (color) {
case &quot;grey&quot;:
return theme.colors.grey[600]
case &quot;neutrals&quot;:
return theme.colors.neutrals[100]
case &quot;primary&quot;:
return theme.colors.primary[500]
default:
return theme.colors.grey[600]
}
}};
`
export const Content = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: start;
width: auto;
height: auto;
border-radius: 0px 0px 10px 10px;
padding: 10px 100px 0px 10px;
background-color: ${({ color, theme }) =&gt; {
switch (color) {
case &quot;grey&quot;:
return theme.colors.grey[600]
case &quot;neutrals&quot;:
return theme.colors.neutrals[100]
case &quot;primary&quot;:
return theme.colors.primary[500]
default:
return theme.colors.grey[600]
}
}};
color: ${({ color, theme }) =&gt; {
switch (color) {
case &quot;grey&quot;:
return theme.colors.grey[600]
case &quot;neutrals&quot;:
return theme.colors.neutrals[100]
case &quot;primary&quot;:
return theme.colors.primary[500]
default:
return theme.colors.grey[600]
}
}};
`
export const Icon = styled.div`
display: flex;
align-items: flex-start;
width: auto;
height: auto;
`

答案1

得分: 1

我看到您已经将icon作为一个属性传递给这个组件了。如果您想在点击时更改图标,您可以创建一个状态并将其设置为初始值,然后在需要时更新它。

const [icon, setIcon] = useState(props.icon);

(您可以通过将状态提升来避免将属性用作初始值,并从父函数传递一个额外的点击处理程序)

然后,您可能希望为图标<div>创建一个onClick方法来设置此图标:

const changeIcon = () => {
    // 一些逻辑来选择更新的图标
    setIcon(newIcon);
}

或者您可以直接将一个图标传递给这个方法:

const changeIcon = newIcon => {
    setIcon(newIcon);
}

并将其分配给该<div>

return (
    ...
    <Styled.Icon onClick={changeIcon}>
        <Icon name={icon} />
    </Styled.Icon>
    ....
);

要在单击“背景”时执行任何操作,您可以为Accordion组件(或者您希望具有此行为的任何组件的背景)分配类似的点击监听器。如果您不希望在点击此背景上面的元素时发生任何操作,您可以使用event.stopPropagation()来停止事件传播,其中event会自动传递给点击处理程序:

return (
    <SomeElement onClick={event => event.stopPropagation()} />
);

希望这回答了您的问题。考虑查看React简短教程,它涵盖了React的基础知识,包括何时使用状态。

英文:

I see you're already passing icon as a prop to this component. If you want to change the icon on click, you can create a state and set that as the initial value, then update it when you like.

const [icon, setIcon] = useState(props.icon);

(you can avoid using a prop as the initial value by lifting state up and passing an additional click handler down from the parent function)

and then you might want to create an onClick method for the icon div that sets this icon:

const changeIcon = () =&gt; {
    // some logic to select an updated icon
    setIcon(newIcon);
}

or you could just pass an icon to this method:

const changeIcon = newIcon =&gt; {
    setIcon(newIcon);
}

and assign it to said div:

return (
    ...
    &lt;Styled.Icon onClick={changeIcon}&gt;
        &lt;Icon name={icon} /&gt;
    &lt;/Styled.Icon&gt;
    ....
);

For doing anything when the "background" is clicked, you can assign a similar click listener to the Accordion component (or whichever component's background you want to have this behaviour on) and if you don't want anything to happen if an element on top of this background is clicked, you can stop this event propagation with event.stopPropagation(), where event is automatically passed to the click handler:

return (
    &lt;SomeElement onClick={event =&gt; event.stopPropagation()} /&gt;
);

I hope that answers your questions. Consider going over the short React tutorial that covers the basics of React, including when to use state.

答案2

得分: 0

&gt; 点击时更改图标

假设您从props中获得一个活动图标”,然后根据您的`isActive`状态进行切换
```jsx
const Accordion = ({
  icon,
  activeIcon,
}) =&gt; {
  const [isActive, setIsActive] = useState(false);

  return (
    &lt;Styled.Title onClick={() =&gt; setIsActive(!isActive)}&gt;
      &lt;Styled.Icon&gt;
        {/* 根据状态提供所需的name prop值 */}
        &lt;Icon name={isActive ? activeIcon : icon}/&gt;
      &lt;/Styled.Icon&gt;
    &lt;/Styled.Title&gt;
  );
};

> 标题div和内容div的背景颜色需要更改

...可能是:

> 通过styled-components中的transform选项

为此,您可以确实使用styled-components 根据props进行自适应

const Accordion = ({
  color,
  activeColor,
}) =&gt; {
  const [isActive, setIsActive] = useState(false);

  return (
    &lt;Styled.Title
      onClick={() =&gt; setIsActive(!isActive)}
      color={isActive ? activeColor : color}
    &gt;
    &lt;/Styled.Title&gt;
  );
};

// Accordion.styled
export const Title = styled.div`
  // 根据color prop调整bgColor值
  background-color: ${(props) =&gt; props.color};
`;

<details>
<summary>英文:</summary>
&gt; change the icon with on click
Assuming you get an &quot;active icon&quot; from props, then just switch it depending on your `isActive` state:
```jsx
const Accordion = ({
icon,
activeIcon,
}) =&gt; {
const [isActive, setIsActive] = useState(false);
return (
&lt;Styled.Title onClick={() =&gt; setIsActive(!isActive)}&gt;
&lt;Styled.Icon&gt;
{/* Provide the desired name prop value depending on state */}
&lt;Icon name={isActive ? activeIcon : icon}/&gt;
&lt;/Styled.Icon&gt;
&lt;/Styled.Title&gt;
);
};

> the background color of the title di[v] and content div needs to change

...possibly:

> via transform option in styled components

For this, you can indeed use styled-components adapting based on props:

const Accordion = ({
  color,
  activeColor,
}) =&gt; {
  const [isActive, setIsActive] = useState(false);

  return (
    &lt;Styled.Title
      onClick={() =&gt; setIsActive(!isActive)}
      color={isActive ? activeColor : color}
    &gt;
    &lt;/Styled.Title&gt;
  );
};

// Accordion.styled
export const Title = styled.div`
  // Adapt the bgColor value based on color prop
  background-color: ${(props) =&gt; props.color};
`;

huangapple
  • 本文由 发表于 2023年1月9日 05:06:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051296.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定