Playing Next Lesson In
seconds

EdgeJS Components #4.0

Creating Our Base Alert

In This Lesson

We'll create our base alert to serve as our building block for our content, variant, and style options. We'll also fix a pseudo-selector issue.

Created by
@tomgobich
Published

Another component likely needed within most applications is an alert, because at some point we’ll need to provide feedback to our users. So, let’s tackle an alert component.

💡 Small note - if you’re using Firefox, and you’re looking at the Pines UI alerts, you’ll notice the icon is overlapping the headline. This is just because they’re using the :has() pseudo selector to determine if there is an icon, and Firefox support for :has() is currently only in the nightly build. We’ll fix this in our component though.

Creating An Alert Demo Page

First, let’s create a new demonstration page for our alert component.

touch resources/views/pages/components/alert.edge
Copied!

Then, inside our new alert.edge page, let’s copy over the layout and base button markup from our button.edge page, changing “Button” to “Alert”.

@layout.app({ title: request.params().name })

  <h3 class="font-bold">Base Alert</h3>
  <div x-data class="mb-8 space-x-3 space-y-3">

  </div>

@end
Copied!
  • resources
  • views
  • pages
  • components
  • alert.edge

Next, we’ll add this page to our components list inside our routes file.

const components = [
  'alert',
  'button',
]
Copied!
  • start
  • routes.ts

This will add it to the list of components we have on our home page.

Creating Our Base Alert

First, let’s give ourselves a place to work by creating a new alert folder with an index.edge file inside.

mkdir resources/views/components/alert
touche resources/views/components/alert/index.edge
Copied!

Now let’s jump into the Pines UI alert documentation and give the base alert markup a copy, or you can copy it from below.

<div class="relative w-full rounded-lg border bg-white p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-nuetral-900">
    <svg class="w-4 h-4" xmlns="<http://www.w3.org/2000/svg>" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" x2="20" y1="19" y2="19"></line></svg>
    <h5 class="mb-1 font-medium leading-none tracking-tight">Alert Message Headline</h5>
    <div class="text-sm opacity-70">This is the subtext for your alert message, providing important information or instructions.</div>
</div>
Copied!

Then, let’s paste that inside of our new alert/index.edge file.

<div class="relative w-full rounded-lg border bg-white p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-nuetral-900">
    <svg class="w-4 h-4" xmlns="<http://www.w3.org/2000/svg>" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" x2="20" y1="19" y2="19"></line></svg>
    <h5 class="mb-1 font-medium leading-none tracking-tight">Alert Message Headline</h5>
    <div class="text-sm opacity-70">This is the subtext for your alert message, providing important information or instructions.</div>
</div>
Copied!
  • resources
  • views
  • components
  • alert
  • index.edge

First, you might notice that our alert has three different distinct portions to it.

  1. The SVG icon

  2. The H5 heading

  3. The DIV message

As we progress with our component, we may or may not want to utilize any one of these within our component, so we’ll make each one of these optional.

For now, though, let’s go ahead and add what we have for our base alert into the base alert section of our demo page.

@layout.app({ title: request.params().name })

  <h3 class="font-bold">Base Alert</h3>
  <div x-data class="mb-8 space-x-3 space-y-3">
    @alert()
      Default, Base Alert
    @end
  </div>

@end
Copied!
  • resources
  • views
  • pages
  • components
  • alert.edge

Replacing the :has Pseudo Selector

Lastly, in this lesson, let’s fix the :has() pseudo selector since its support is still a little hit or miss.

On our alert’s outermost div, you should find the class [&:has(svg)]:pl-11, this is the class causing our svg and headline to overlap on browsers that don’t support :has(). This is essentially adding a pl-11 when the outermost div contains an svg element.

We can remedy this for now using a variable, but we’ll add an even better solution when we add our component’s slots.

++@set('showIcon', showIcon ?? true)

<div class="relative w-full rounded-lg border bg-white p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] text-nuetral-900 {{ showIcon ? 'pl-11' : '' }}">
    @if (showIcon)
      <svg class="w-4 h-4" xmlns="<http://www.w3.org/2000/svg>" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" x2="20" y1="19" y2="19"></line></svg>
    @endif
<div class="relative w-full rounded-lg border bg-white p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-nuetral-900">
    <svg class="w-4 h-4" xmlns="<http://www.w3.org/2000/svg>" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" x2="20" y1="19" y2="19"></line></svg>
    <h5 class="mb-1 font-medium leading-none tracking-tight">Alert Message Headline</h5>
    <div class="text-sm opacity-70">This is the subtext for your alert message, providing important information or instructions.</div>
</div>
Copied!
  • resources
  • views
  • components
  • alert
  • index.edge

So, here we’re adding a variable called showIcon, allowing it as a prop and defaulting to true if it’s not provided. Then, we’re removing the [&:has(svg)]:pl-11 class and replacing it with a ternary that applies pl-11 if showIcon is truthy. Lastly, we’re wrapping the svg icon itself in an if check, only rendering it if showIcon is truthy.

Join the Discussion 0 comments

Create a free account to join in on the discussion
robot comment bubble

Be the first to comment!