2

I have an existing Astro component that already includes some classes in its template; however I'm trying to reuse this component on a different view and change the color of its header only on that view.

So I read the docs saying that I can pass a class prop to add classes from a parent to a child; however, I'm not understanding how can I keep the existing classes in the component and just override something or add another class to the already existing ones.

<ExpansionQuestion question={question.question}>
  <Fragment slot="body" set:html={question.answer} />
</ExpansionQuestion>

ExpansionQuestion root element:

<details
  class="group bg-blue-gray duration-300 rounded-lg p-4 w-full shadow-md focus:outline-none focus:ring-0"
>

I just want to add a different bg-secondary class to the details element on one specific view, the rest of the classes should stay the same everywhere.

Is it possible to do this?

IvanS95
  • 5,364
  • 4
  • 24
  • 62

2 Answers2

5

One good approach here is to use Astro’s class:list directive. This let’s you combine various classes more easily.

In your example, you might do something like this:

  1. Pass the additional class to the component where you use it (here using a bg prop, but you could adapt this for whatever situation):

    <ExpansionQuestion question={question.question} bg="bg-secondary">
      <Fragment slot="body" set:html={question.answer} />
    </ExpansionQuestion>
    
  2. Use the prop to control the background in ExpansionQuestion.astro component:

    ---
    const { bg } = Astro.props;
    ---
    <details
      class:list={[
        "group duration-300 rounded-lg p-4 w-full",
        "shadow-md focus:outline-none focus:ring-0",
        bg || "bg-blue-gray"
      ]}
    >
    

    Astro will automatically combine the items in the class:list array, and in this case will use the bg prop if it is passed, but will default to the blue gray colour if no prop was passed.

swithinbank
  • 1,127
  • 1
  • 6
  • 15
  • Worked perfectly! I did notice the `class:list` directive, but I thought the list would get overwritten if I passed something to it; I didn't think of using a `prop` as a control for specific classes only – IvanS95 Apr 04 '23 at 23:26
0

Accept a class prop in the child component and apply it to the root element. When destructuring, you must rename it, because class is a reserved word in JavaScript.

Child component:

---
const { class: className } = Astro.props
---

<div class:list={['child-component', className]}>
  Child component
</div>

<style>
.child-component {
  border: 2px solid blue;
}
</style>

Using it from parent:

---
import ChildComponent from '...'
---

<div class="parent">
  <ChildComponent class="my-child-component"/>
</div>

<style>
.my-child-component {
  background: red;
}
</style>

More on that in docs

Seangle
  • 359
  • 2
  • 10