-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
836cde0
commit 67c468c
Showing
8 changed files
with
290 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<script lang="ts"> | ||
export let testId: string | undefined = undefined; | ||
import { DEFAULT_ICON_SIZE } from "$lib/constants/constants"; | ||
import IconClose from "$lib/icons/IconClose.svelte"; | ||
import { createEventDispatcher } from "svelte"; | ||
export let visible: boolean = true; | ||
const dispatch = createEventDispatcher(); | ||
function setVisibilityFalse() { | ||
visible = false; | ||
dispatch("nnsClose"); | ||
} | ||
</script> | ||
|
||
{#if visible} | ||
<div | ||
class="banner" | ||
data-tid={testId} | ||
style="--default-icon-size: {DEFAULT_ICON_SIZE}px;" | ||
> | ||
<div class="icon-background"> | ||
<div class="icon-wrapper"> | ||
<slot name="icon" /> | ||
</div> | ||
</div> | ||
<div class="text-content"> | ||
<slot name="title" /> | ||
<slot name="description" /> | ||
</div> | ||
<div class="action-wrapper"> | ||
<slot name="action" /> | ||
</div> | ||
<button class="close-button icon-only" on:click={setVisibilityFalse}> | ||
<IconClose /> | ||
</button> | ||
</div> | ||
{/if} | ||
|
||
<style lang="scss"> | ||
@use "../styles/mixins/fonts"; | ||
.banner { | ||
display: flex; | ||
align-items: center; | ||
background: var(--banner-background, var(--input-background)); | ||
border-radius: var(--banner-radius, var(--border-radius)); | ||
padding: var(--banner-top-bottom-padding, var(--padding)) | ||
var(--banner-left-right-padding, var(--padding-1_5x)); | ||
column-gap: var(--banner-column-gap, var(--padding-1_5x)); | ||
} | ||
.icon-background { | ||
padding: var(--icon-background-padding, 6px); | ||
background-color: var( | ||
--icon-background-color, | ||
var(--dropdown-border-color) | ||
); | ||
border-radius: var(--icon-border-radius, 50%); | ||
} | ||
.icon-wrapper { | ||
color: var(--icon-color, var(--elements-icons)); | ||
} | ||
.action-wrapper { | ||
flex-shrink: 0; | ||
--button-min-height: 40px; | ||
} | ||
.text-content { | ||
display: flex; | ||
flex-direction: column; | ||
flex-grow: 1; | ||
} | ||
.close-button { | ||
padding: var(--close-button-padding, 10px); | ||
border-radius: var(--close-button-border-radius, var(--border-radius)); | ||
background: var(--close-button-background, var(--card-background)); | ||
color: var(--elements-icons); | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
<script lang="ts"> | ||
import Banner from "$lib/components/Banner.svelte"; | ||
import IconInfo from "$lib/icons/IconInfo.svelte"; | ||
</script> | ||
|
||
# Banner | ||
|
||
A versatile component to render informative banners with customizable content, actions, and visibility control. | ||
|
||
| Property | Description | Type | Default | | ||
| --------- | --------------------------------------------------------------- | ----------------------- | ----------- | | ||
| `testId` | Add a `data-tid` attribute to the DOM, useful for test purpose. | `string` or `undefined` | `undefined` | | ||
| `visible` | Controls the visibility of the banner. | `boolean` | `true` | | ||
|
||
## Slots | ||
|
||
| Slot name | Description | | ||
| ------------- | --------------------------------------------------------------------------- | | ||
| `icon` | Icon appearing at the start of the banner. | | ||
| `title` | Title of the banner. | | ||
| `description` | Description text below the title. It should explain the banner's purpose. | | ||
| `action` | Located on the right side of the banner. Useful for call-to-action buttons. | | ||
|
||
## Events | ||
|
||
| Event | Description | | ||
| ---------- | -------------------------------------------- | | ||
| `nnsClose` | Dispatched when the close button is clicked. | | ||
|
||
## Showcase | ||
|
||
The component has its own background color and visibility control, which can be customized using props and CSS variables. | ||
|
||
### Example | ||
|
||
<Banner> | ||
<IconInfo slot="icon" /> | ||
<span slot="title" class='title'>Your ICP Wallet</span> | ||
<span slot="description" class="description"> | ||
Create and link accounts, transfer ICP, participate in governance, and earn | ||
rewards. | ||
</span> | ||
<button class="secondary" slot="action">Make Neurons Public</button> | ||
</Banner> | ||
|
||
<br /> | ||
|
||
<style lang="scss"> | ||
@use "../../../../lib/styles/mixins/fonts"; | ||
|
||
.title { | ||
@include fonts.secondary(true); | ||
} | ||
.description { | ||
@include fonts.secondary(false); | ||
} | ||
</style> | ||
|
||
#### Code | ||
|
||
```text | ||
<Banner> | ||
<IconInfo slot="icon" /> | ||
<span slot="title">Your ICP Wallet</span> | ||
<span slot="description" class="description"> | ||
Create and link accounts, transfer ICP, participate in governance, and earn | ||
rewards. | ||
</span> | ||
<button class="primary" slot="action">Connect Wallet</button> | ||
</Banner> | ||
<style lang="scss"> | ||
@use "../../../../lib/styles/mixins/fonts"; | ||
.title { | ||
@include fonts.secondary(true); | ||
} | ||
.description { | ||
@include fonts.secondary(false); | ||
} | ||
</style> | ||
``` | ||
|
||
## Visibility Control | ||
|
||
The Banner component includes built-in visibility control: | ||
|
||
- The `visible` prop controls the visibility of the banner. | ||
- When the close button is clicked, the `visible` prop is set to `false` and an `nnsClose` event is dispatched. | ||
|
||
## Customization | ||
|
||
You can customize the appearance of the Banner component using CSS variables: | ||
|
||
| CSS Variable | Description | Default Value | | ||
| ------------------------------ | ------------------------------------ | ------------------------------ | | ||
| `--banner-background` | Background color of the banner | `var(--input-background)` | | ||
| `--banner-radius` | Border radius of the banner | `var(--border-radius)` | | ||
| `--banner-top-bottom-padding` | Vertical padding inside the banner | `var(--padding)` | | ||
| `--banner-left-right-padding` | Horizontal padding inside the banner | `var(--padding-1_5x)` | | ||
| `--banner-column-gap` | Gap between banner elements | `var(--padding-1_5x)` | | ||
| `--icon-background-padding` | Padding around the icon | `6px` | | ||
| `--icon-background-color` | Background color of the icon wrapper | `var(--dropdown-border-color)` | | ||
| `--icon-border-radius` | Border radius of the icon wrapper | `50%` | | ||
| `--icon-color` | Color of the icon | `var(--elements-icons)` | | ||
| `--close-button-padding` | Padding of the close button | `10px` | | ||
| `--close-button-border-radius` | Border radius of the close button | `var(--border-radius)` | | ||
| `--close-button-background` | Background color of the close button | `var(--card-background)` | | ||
|
||
Example of customization: | ||
|
||
```svelte | ||
<Banner> | ||
<!-- Banner content --> | ||
</Banner> | ||
<style lang="scss"> | ||
:global(.banner) { | ||
--banner-background: #f0f8ff; | ||
--banner-radius: 10px; | ||
--banner-top-bottom-padding: 12px; | ||
--banner-left-right-padding: 18px; | ||
--banner-column-gap: 18px; | ||
--icon-background-color: #e6f3ff; | ||
--icon-color: #0056b3; | ||
--close-button-background: #ffffff; | ||
} | ||
</style> | ||
``` | ||
|
||
This customization will apply a light blue theme to the banner and adjust the padding, border radius, and colors. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import Banner from "$lib/components/Banner.svelte"; | ||
import { fireEvent, render } from "@testing-library/svelte"; | ||
import BannerTest from "./BannerTest.svelte"; | ||
|
||
describe("Banner", () => { | ||
it("should render the banner when visible is true", () => { | ||
const { container } = render(Banner); | ||
expect(container.querySelector(".banner")).not.toBeNull(); | ||
}); | ||
|
||
it("should not render the banner when visible is false", () => { | ||
const { container } = render(Banner, { props: { visible: false } }); | ||
expect(container.querySelector(".banner")).toBeNull(); | ||
}); | ||
|
||
it("should render slotted content", () => { | ||
const { getByText } = render(BannerTest); | ||
expect(getByText("Test Icon")).toBeInTheDocument(); | ||
expect(getByText("Test Title")).toBeInTheDocument(); | ||
expect(getByText("Test Description")).toBeInTheDocument(); | ||
expect(getByText("Test Action")).toBeInTheDocument(); | ||
}); | ||
|
||
it("should close the banner when close button is clicked", async () => { | ||
const { container, component } = render(Banner); | ||
|
||
const closeButton = container.querySelector( | ||
".close-button", | ||
) as HTMLButtonElement; | ||
expect(closeButton).not.toBeNull(); | ||
|
||
const onClose = vi.fn(); | ||
component.$on("nnsClose", onClose); | ||
|
||
await fireEvent.click(closeButton); | ||
|
||
expect(onClose).toHaveBeenCalled(); | ||
expect(container.querySelector(".banner")).toBeNull(); | ||
}); | ||
|
||
it("should apply custom test ID", () => { | ||
const testId = "custom-banner-id"; | ||
const { container } = render(Banner, { props: { testId } }); | ||
|
||
const banner = container.querySelector(".banner"); | ||
expect(banner).not.toBeNull(); | ||
expect(banner?.getAttribute("data-tid")).toBe(testId); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<script lang="ts"> | ||
import Banner from "$lib/components/Banner.svelte"; | ||
</script> | ||
|
||
<Banner> | ||
<span slot="icon">Test Icon</span> | ||
<span slot="title">Test Title</span> | ||
<span slot="description">Test Description</span> | ||
<button slot="action">Test Action</button> | ||
</Banner> |