diff --git a/apps/docs/stories/architecture-decision-records/0009-why-use-onclick-event-on-breadcrumb-component-event-undocumented.stories.mdx b/apps/docs/stories/architecture-decision-records/0009-why-use-onclick-event-on-breadcrumb-component-event-undocumented.stories.mdx new file mode 100644 index 000000000..c2ac33c96 --- /dev/null +++ b/apps/docs/stories/architecture-decision-records/0009-why-use-onclick-event-on-breadcrumb-component-event-undocumented.stories.mdx @@ -0,0 +1,17 @@ +import { Meta } from '@storybook/addon-docs' + + + +# Why use `onClick` event on breadcrumb component even undocumented? + +🗓️ 2023-07 · ✍️ [@denilsonrp](https://github.com/denilsonrp) + +## Context + +In the [breadcrumb component's pull request](https://github.com/juntossomosmais/atomium/pull/163) a [doubt arose about the correct functioning of the `onClick` event](https://github.com/juntossomosmais/atomium/pull/163#discussion_r1250986555), as this event isn't documented in [ion-breadcrumb docs](https://ionicframework.com/docs/api/breadcrumb#events). + +## Decision + +We ran some tests on Atomium's breadcrumb component in order to ensure the correct firing of the event and even though the `onClick` event isn't documented in the events section of the [ion-breadcrumb docs](https://ionicframework.com/docs/api/breadcrumb#events), the tests were successful and the event fired correctly. + +Based on these tests, we can assume that, even without event documentation, it's possible to use it. The idea of ​​exposing this decision is to serve as a reference in possible similar scenarios in the future. diff --git a/packages/core/src/components/alert/alert.scss b/packages/core/src/components/alert/alert.scss index 054509d0e..43b30e229 100644 --- a/packages/core/src/components/alert/alert.scss +++ b/packages/core/src/components/alert/alert.scss @@ -7,8 +7,8 @@ } .atom-alert { - border-radius: var(--border-radius); border: 1px solid transparent; + border-radius: var(--border-radius); font: var(--text-body-medium); letter-spacing: var(--text-body-medium-letter); padding: var(--spacing-base); diff --git a/packages/core/src/components/breadcrumb/breadcrumb.scss b/packages/core/src/components/breadcrumb/breadcrumb.scss new file mode 100644 index 000000000..60bce3839 --- /dev/null +++ b/packages/core/src/components/breadcrumb/breadcrumb.scss @@ -0,0 +1,60 @@ +@import '~@atomium/scss-utils/index'; + +.atom-breadcrumbs { + display: none; + + @include above(medium) { + display: flex; + } +} + +.atom-breadcrumb { + --color: var(--color-brand-secondary-regular); + --color-active: var(--color-neutral-regular); + font: var(--text-body-small); + letter-spacing: var(--text-body-small-letter); + + &:not(:last-of-type) { + &::part(native) { + cursor: pointer; + + &:hover { + text-decoration: underline; + } + } + + .atom-breadcrumb__text { + max-width: 100px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + + &::part(native) { + padding: 0; + } + + &::part(separator) { + color: var(--color-neutral-regular); + margin: 0 var(--spacing-xxsmall); + } +} + +.atom-button__back { + align-items: center; + background-color: transparent; + border: 0; + color: var(--color-brand-secondary-regular); + cursor: pointer; + display: flex; + font: var(--text-link-small); + gap: var(--spacing-xsmall); + letter-spacing: var(--text-link-small-letter); + padding: 0; + text-decoration: underline; + + @include above(medium) { + display: none; + } +} diff --git a/packages/core/src/components/breadcrumb/breadcrumb.spec.ts b/packages/core/src/components/breadcrumb/breadcrumb.spec.ts new file mode 100644 index 000000000..370469f67 --- /dev/null +++ b/packages/core/src/components/breadcrumb/breadcrumb.spec.ts @@ -0,0 +1,90 @@ +import { newSpecPage } from '@stencil/core/testing' + +import { AtomBreadcrumb } from './breadcrumb' + +const breadcrumbItemsMock = [ + { + text: 'First level', + title: 'Go to first level', + redirect: () => console.log('/first'), + }, + { + text: 'Intermediary level', + title: 'Go to intermediary level', + redirect: () => console.log('/intermediary'), + }, + { + text: 'Current level', + title: 'This is the current level', + }, +] + +describe('atom-breadcrumb', () => { + it('should render breadcrumb items and mobile back button correctly', async () => { + const page = await newSpecPage({ + components: [AtomBreadcrumb], + html: ``, + }) + + page.rootInstance.items = breadcrumbItemsMock + + await page.waitForChanges() + + expect(page.root).toEqualHtml(` + + + + + + + First level + + + + + + Intermediary level + + + + + + Current level + + + + + + + `) + }) + + it('should not render mobile back button when only one breadcrumb item is sent as prop', async () => { + const page = await newSpecPage({ + components: [AtomBreadcrumb], + html: ``, + }) + + page.rootInstance.items = [breadcrumbItemsMock[0]] + + await page.waitForChanges() + + expect(page.root).toEqualHtml(` + + + + + + First level + + + + + + + `) + }) +}) diff --git a/packages/core/src/components/breadcrumb/breadcrumb.tsx b/packages/core/src/components/breadcrumb/breadcrumb.tsx new file mode 100644 index 000000000..85c2fe1ed --- /dev/null +++ b/packages/core/src/components/breadcrumb/breadcrumb.tsx @@ -0,0 +1,50 @@ +import { Component, h, Host, Prop } from '@stencil/core' + +type BreadcrumbItemProp = { + redirect?: (event: MouseEvent) => void + text: string + title: string +} + +@Component({ + tag: 'atom-breadcrumb', + styleUrl: 'breadcrumb.scss', + shadow: true, +}) +export class AtomBreadcrumb { + @Prop({ mutable: true }) items: BreadcrumbItemProp[] = [] + + render() { + const prevItem = this.items[this.items.length - 2] + + return ( + + {this.items.length > 1 && ( + + )} + + + {this.items.map((item) => ( + + + {item.text} + + + + ))} + + + ) + } +} diff --git a/packages/core/src/components/breadcrumb/stories/breadcrumb.args.ts b/packages/core/src/components/breadcrumb/stories/breadcrumb.args.ts new file mode 100644 index 000000000..e94512111 --- /dev/null +++ b/packages/core/src/components/breadcrumb/stories/breadcrumb.args.ts @@ -0,0 +1,25 @@ +import { Category } from '@atomium/storybook-utils/enums/table' + +export const BreadcrumbStoryArgs = { + decorators: [], + parameters: { + actions: { + handles: [], + }, + docs: { + description: { + component: + 'Breadcrumbs are navigation items that are used to indicate where a user is on site. Read the [Ionic documentation](https://ionicframework.com/docs/api/breadcrumbs) for more information about this component.', + }, + }, + }, + argTypes: { + items: { + description: + 'This is the list of items that will be displayed in the breadcrumb. Items must have `title` and `text` and optionally a `redirect` function when clicking on the item.', + table: { + category: Category.PROPERTIES, + }, + }, + }, +} diff --git a/packages/core/src/components/breadcrumb/stories/breadcrumb.core.stories.tsx b/packages/core/src/components/breadcrumb/stories/breadcrumb.core.stories.tsx new file mode 100644 index 000000000..b8f0d3380 --- /dev/null +++ b/packages/core/src/components/breadcrumb/stories/breadcrumb.core.stories.tsx @@ -0,0 +1,45 @@ +import { Meta, StoryObj } from '@storybook/web-components' + +import { html } from 'lit' + +import { BreadcrumbStoryArgs } from './breadcrumb.args' + +export default { + title: 'Components/Breadcrumb', + ...BreadcrumbStoryArgs, +} as Meta + +const createBreadcrumb = () => { + return html` + + + + ` +} + +export const Default: StoryObj = { + render: () => createBreadcrumb(), +} diff --git a/packages/core/src/components/breadcrumb/stories/breadcrumb.react.stories.tsx b/packages/core/src/components/breadcrumb/stories/breadcrumb.react.stories.tsx new file mode 100644 index 000000000..262551576 --- /dev/null +++ b/packages/core/src/components/breadcrumb/stories/breadcrumb.react.stories.tsx @@ -0,0 +1,37 @@ +import { Meta, StoryObj } from '@storybook/react' +import React from 'react' + +import { AtomBreadcrumb } from '@juntossomosmais/atomium/react' + +import { BreadcrumbStoryArgs } from './breadcrumb.args' + +export default { + title: 'Components/Breadcrumb', + ...BreadcrumbStoryArgs, +} as Meta + +const createBreadcrumb = (args) => ( + +) + +export const Default: StoryObj = { + render: (args) => createBreadcrumb(args), + args: { + items: [ + { + text: 'First level', + title: 'Go to first level', + redirect: () => console.log('/first'), + }, + { + text: 'Intermediary level', + title: 'Go to intermediary level', + redirect: () => console.log('/intermediary'), + }, + { + text: 'Current level', + title: 'This is the current level', + }, + ], + }, +} diff --git a/packages/icons/svg/mdi/arrow-right.svg b/packages/icons/svg/mdi/arrow-right.svg new file mode 100644 index 000000000..cb91467f0 --- /dev/null +++ b/packages/icons/svg/mdi/arrow-right.svg @@ -0,0 +1 @@ + diff --git a/packages/icons/svg/mdi/west.svg b/packages/icons/svg/mdi/west.svg new file mode 100644 index 000000000..2633b747e --- /dev/null +++ b/packages/icons/svg/mdi/west.svg @@ -0,0 +1 @@ +