diff --git a/.github/workflows/pr-title-check.yml b/.github/workflows/pr-title-check.yml index 296566d06..7116b5e3e 100644 --- a/.github/workflows/pr-title-check.yml +++ b/.github/workflows/pr-title-check.yml @@ -2,7 +2,7 @@ name: PR Title Check on: pull_request: - types: [opened] + types: [opened, edited] jobs: pr-title: @@ -14,9 +14,9 @@ jobs: - name: Validate PR Title run: | - if [[ ! "${{ github.event.pull_request.title }}" =~ ^(feat|fix|chore|major|docs|ci))\([a-zA-Z0-9_-]+\):\ .+$ ]]; then + if [[ ! "${{ github.event.pull_request.title }}" =~ ^(feat|fix|chore|major|docs|ci)\(([a-z_-]+)\):(.+|\d+)$ ]]; then echo "The Pull Request title must follow the convention: 'type(context): description'." - "The types must be: feat, fix, chore, major." + echo "The types must be: feat, fix, chore, major, docs, ci." echo "Example of a correct title: feat(component): create link component" exit 1 fi diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 369edae82..4245250ef 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,4 +1,4 @@ { - "packages/core": "2.13.0", + "packages/core": "2.14.2", "packages/tokens": "1.2.0" } diff --git a/apps/docs-react/.storybook/preview.ts b/apps/docs-react/.storybook/preview.ts index 6689d19e9..50f2931c6 100644 --- a/apps/docs-react/.storybook/preview.ts +++ b/apps/docs-react/.storybook/preview.ts @@ -1,5 +1,5 @@ import { CustomViewports } from '@atomium/storybook-utils/custom-viewports' -import DocumentationTemplate from '@atomium/storybook-utils/DocumentationTemplate.mdx' +import DocumentationTemplate from '@atomium/storybook-utils/templates/DocumentationTemplate.mdx' import '@atomium/storybook-utils/preview.css' diff --git a/apps/docs-vue/.storybook/preview.ts b/apps/docs-vue/.storybook/preview.ts index 2eef9c7f6..d33577b66 100644 --- a/apps/docs-vue/.storybook/preview.ts +++ b/apps/docs-vue/.storybook/preview.ts @@ -1,5 +1,5 @@ import { CustomViewports } from '@atomium/storybook-utils/custom-viewports' -import DocumentationTemplate from '@atomium/storybook-utils/DocumentationTemplate.mdx' +import DocumentationTemplate from '@atomium/storybook-utils/templates/DocumentationTemplate.mdx' import '@atomium/storybook-utils/preview.css' diff --git a/apps/docs/.storybook/preview.ts b/apps/docs/.storybook/preview.ts index 0c521b403..1c8473a60 100644 --- a/apps/docs/.storybook/preview.ts +++ b/apps/docs/.storybook/preview.ts @@ -1,7 +1,7 @@ import { defineCustomElements } from '@juntossomosmais/atomium/loader' import { CustomViewports } from '@atomium/storybook-utils/custom-viewports' -import DocumentationTemplate from '@atomium/storybook-utils/DocumentationTemplate.mdx' +import DocumentationTemplate from '@atomium/storybook-utils/templates/DocumentationTemplate.mdx' import '@atomium/storybook-utils/preview.css' diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 2665c39a8..d19ae1038 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,35 @@ # Changelog +## [2.14.2](https://github.com/juntossomosmais/atomium/compare/atomium-v2.14.1...atomium-v2.14.2) (2024-08-23) + + +### Bug Fixes + +* **alert:** improve position of icon on single line ([#543](https://github.com/juntossomosmais/atomium/issues/543)) ([9c587d6](https://github.com/juntossomosmais/atomium/commit/9c587d6cbd7ab3e2cbe30502ec6a35cfe6ef873a)) + +## [2.14.1](https://github.com/juntossomosmais/atomium/compare/atomium-v2.14.0...atomium-v2.14.1) (2024-08-22) + + +### Bug Fixes + +* **icons:** rename verified outline icon ([#540](https://github.com/juntossomosmais/atomium/issues/540)) ([57e3b51](https://github.com/juntossomosmais/atomium/commit/57e3b517f331fe31d9bab207dd13a6e033575765)) +* **tag:** light tag color ([#542](https://github.com/juntossomosmais/atomium/issues/542)) ([c098357](https://github.com/juntossomosmais/atomium/commit/c098357e0cf1e4b7202febd0398f000a51c92cbc)) + +## [2.14.0](https://github.com/juntossomosmais/atomium/compare/atomium-v2.13.1...atomium-v2.14.0) (2024-08-16) + + +### Features + +* **icons:** add verified icons ([#539](https://github.com/juntossomosmais/atomium/issues/539)) ([f04d310](https://github.com/juntossomosmais/atomium/commit/f04d310243aae09c2465aae04d10875dc7c4dfc7)) +* **modal:** add modal component ([#534](https://github.com/juntossomosmais/atomium/issues/534)) ([f3fc1bb](https://github.com/juntossomosmais/atomium/commit/f3fc1bbe47362a88a0754324160f1e25f2fccc65)) + +## [2.13.1](https://github.com/juntossomosmais/atomium/compare/atomium-v2.13.0...atomium-v2.13.1) (2024-08-08) + + +### Bug Fixes + +* **button:** decrease horizontal padding size ([#531](https://github.com/juntossomosmais/atomium/issues/531)) ([1c6a7b7](https://github.com/juntossomosmais/atomium/commit/1c6a7b724b6abebadcb7cf98f78d416bc9f079cd)) + ## [2.13.0](https://github.com/juntossomosmais/atomium/compare/atomium-v2.12.0...atomium-v2.13.0) (2024-08-06) diff --git a/packages/core/package.json b/packages/core/package.json index 6a4044780..dc70442f3 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@juntossomosmais/atomium", - "version": "2.13.0", + "version": "2.14.2", "description": "Core of web components for Atomium", "repository": { "type": "git", diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index a4d963ced..d6f72ee80 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -38,7 +38,10 @@ export namespace Components { "disabled"?: boolean; "download"?: string; "expand"?: 'block'; - "fill": 'clear' | 'outline' | 'outline-filled' | 'solid'; + "fill": | 'clear' + | 'outline' + | 'outline-filled' + | 'solid'; "href"?: string; "loading"?: boolean; "mode": Mode; @@ -155,6 +158,16 @@ export namespace Components { } interface AtomListSliderItem { } + interface AtomModal { + "alertType"?: 'alert' | 'error'; + "hasDivider"?: boolean; + "hasFooter"?: boolean; + "headerTitle"?: string; + "primaryText"?: string; + "progress"?: number; + "secondaryText"?: string; + "trigger"?: string; + } interface AtomSelect { "color"?: 'primary' | 'secondary' | 'danger'; "disabled"?: boolean; @@ -261,6 +274,10 @@ export interface AtomListSliderCustomEvent extends CustomEvent { detail: T; target: HTMLAtomListSliderElement; } +export interface AtomModalCustomEvent extends CustomEvent { + detail: T; + target: HTMLAtomModalElement; +} export interface AtomSelectCustomEvent extends CustomEvent { detail: T; target: HTMLAtomSelectElement; @@ -431,6 +448,27 @@ declare global { prototype: HTMLAtomListSliderItemElement; new (): HTMLAtomListSliderItemElement; }; + interface HTMLAtomModalElementEventMap { + "atomCloseClick": any; + "atomDidDismiss": any; + "atomDidPresent": any; + "atomPrimaryClick": any; + "atomSecondaryClick": any; + } + interface HTMLAtomModalElement extends Components.AtomModal, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLAtomModalElement, ev: AtomModalCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLAtomModalElement, ev: AtomModalCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLAtomModalElement: { + prototype: HTMLAtomModalElement; + new (): HTMLAtomModalElement; + }; interface HTMLAtomSelectElementEventMap { "atomBlur": void; "atomCancel": void; @@ -494,6 +532,7 @@ declare global { "atom-link": HTMLAtomLinkElement; "atom-list-slider": HTMLAtomListSliderElement; "atom-list-slider-item": HTMLAtomListSliderItemElement; + "atom-modal": HTMLAtomModalElement; "atom-select": HTMLAtomSelectElement; "atom-tag": HTMLAtomTagElement; "atom-textarea": HTMLAtomTextareaElement; @@ -528,7 +567,10 @@ declare namespace LocalJSX { "disabled"?: boolean; "download"?: string; "expand"?: 'block'; - "fill"?: 'clear' | 'outline' | 'outline-filled' | 'solid'; + "fill"?: | 'clear' + | 'outline' + | 'outline-filled' + | 'solid'; "href"?: string; "loading"?: boolean; "mode"?: Mode; @@ -651,6 +693,21 @@ declare namespace LocalJSX { } interface AtomListSliderItem { } + interface AtomModal { + "alertType"?: 'alert' | 'error'; + "hasDivider"?: boolean; + "hasFooter"?: boolean; + "headerTitle"?: string; + "onAtomCloseClick"?: (event: AtomModalCustomEvent) => void; + "onAtomDidDismiss"?: (event: AtomModalCustomEvent) => void; + "onAtomDidPresent"?: (event: AtomModalCustomEvent) => void; + "onAtomPrimaryClick"?: (event: AtomModalCustomEvent) => void; + "onAtomSecondaryClick"?: (event: AtomModalCustomEvent) => void; + "primaryText"?: string; + "progress"?: number; + "secondaryText"?: string; + "trigger"?: string; + } interface AtomSelect { "color"?: 'primary' | 'secondary' | 'danger'; "disabled"?: boolean; @@ -754,6 +811,7 @@ declare namespace LocalJSX { "atom-link": AtomLink; "atom-list-slider": AtomListSlider; "atom-list-slider-item": AtomListSliderItem; + "atom-modal": AtomModal; "atom-select": AtomSelect; "atom-tag": AtomTag; "atom-textarea": AtomTextarea; @@ -778,6 +836,7 @@ declare module "@stencil/core" { "atom-link": LocalJSX.AtomLink & JSXBase.HTMLAttributes; "atom-list-slider": LocalJSX.AtomListSlider & JSXBase.HTMLAttributes; "atom-list-slider-item": LocalJSX.AtomListSliderItem & JSXBase.HTMLAttributes; + "atom-modal": LocalJSX.AtomModal & JSXBase.HTMLAttributes; "atom-select": LocalJSX.AtomSelect & JSXBase.HTMLAttributes; "atom-tag": LocalJSX.AtomTag & JSXBase.HTMLAttributes; "atom-textarea": LocalJSX.AtomTextarea & JSXBase.HTMLAttributes; diff --git a/packages/core/src/components/alert/alert.scss b/packages/core/src/components/alert/alert.scss index c66b63e41..9e1da1ba7 100644 --- a/packages/core/src/components/alert/alert.scss +++ b/packages/core/src/components/alert/alert.scss @@ -1,5 +1,7 @@ @import '~@atomium/scss-utils/index'; +$min-height-title: var(--spacing-large); + :host { --close-size: var(--spacing-xxxlarge); --icon-size: var(--spacing-medium); @@ -75,6 +77,7 @@ .atom-title { font-weight: var(--font-weight-bold); margin: 0; + min-height: $min-height-title; &:not(:last-child) { margin-bottom: var(--spacing-xsmall); @@ -118,8 +121,10 @@ } .atom-icon { + align-items: center; + display: flex; font-size: var(--icon-size); - width: var(--space-large); + height: $min-height-title; } .atom-close { diff --git a/packages/core/src/components/button/button.scss b/packages/core/src/components/button/button.scss index 9f5b3fe1c..ad2b87cff 100644 --- a/packages/core/src/components/button/button.scss +++ b/packages/core/src/components/button/button.scss @@ -14,6 +14,7 @@ } .atom-button { + margin: 0; text-transform: inherit; &[color='white'] { @@ -26,10 +27,17 @@ --ion-color-contrast: var(--color-neutral-black); } + &[size='small'], + &[size='default'], + &[size='large'] { + --padding-start: var(--spacing-base); + --padding-end: var(--spacing-base); + height: var(--button-size); + } + &[size='default'] { --button-size: var(--spacing-xxxxlarge); font: var(--button-medium); - height: var(--button-size); letter-spacing: var(--button-medium-letter); &.is-circle { @@ -40,7 +48,6 @@ &[size='small'] { --button-size: var(--spacing-xxxlarge); font: var(--button-small); - height: var(--button-size); letter-spacing: var(--button-small-letter); &.is-circle { @@ -51,7 +58,6 @@ &[size='large'] { --button-size: var(--spacing-giant); font: var(--button-large); - height: var(--button-size); letter-spacing: var(--button-large-letter); &.is-circle { @@ -67,7 +73,7 @@ } } - &.is-outline-filled{ + &.is-outline-filled { --background: var(--color-neutral-white); --color: var(--ion-color-base); --border-width: 2px; @@ -98,5 +104,3 @@ top: 50%; transform: translate(-50%, -50%); } - - diff --git a/packages/core/src/components/button/button.spec.ts b/packages/core/src/components/button/button.spec.ts index 1e7fc3d8b..2c0027d2f 100644 --- a/packages/core/src/components/button/button.spec.ts +++ b/packages/core/src/components/button/button.spec.ts @@ -25,7 +25,7 @@ describe('AtomButton', () => { expect(page.root).toEqualHtml(` - + @@ -47,7 +47,7 @@ describe('AtomButton', () => { expect(page.root).toEqualHtml(` - + @@ -69,7 +69,7 @@ describe('AtomButton', () => { await page.waitForChanges() expect(page.root?.shadowRoot).toEqualHtml(` - + @@ -89,7 +89,7 @@ describe('AtomButton', () => { await page.waitForChanges() expect(page.root?.shadowRoot).toEqualHtml(` - + @@ -106,7 +106,7 @@ describe('AtomButton', () => { await page.waitForChanges() expect(page.root?.shadowRoot).toEqualHtml(` - + diff --git a/packages/core/src/components/button/button.tsx b/packages/core/src/components/button/button.tsx index 276047f7a..60cfff316 100644 --- a/packages/core/src/components/button/button.tsx +++ b/packages/core/src/components/button/button.tsx @@ -19,7 +19,11 @@ export class AtomButton { @Prop({ mutable: true }) disabled?: boolean @Prop({ mutable: true }) download?: string @Prop({ mutable: true }) expand?: 'block' - @Prop({ mutable: true }) fill: 'clear' | 'outline' | 'outline-filled' | 'solid' = 'solid' + @Prop({ mutable: true }) fill: + | 'clear' + | 'outline' + | 'outline-filled' + | 'solid' = 'solid' @Prop({ mutable: true }) shape?: 'round' | 'circle' = 'round' @Prop({ mutable: true }) href?: string @Prop({ mutable: true }) loading?: boolean @@ -89,6 +93,7 @@ export class AtomButton { target={this.target} download={this.download} onClick={this.handleClick.bind(this)} + part='button' > {this.loading && ( diff --git a/packages/core/src/components/modal/modal.scss b/packages/core/src/components/modal/modal.scss new file mode 100644 index 000000000..34a1dbe51 --- /dev/null +++ b/packages/core/src/components/modal/modal.scss @@ -0,0 +1,93 @@ +@import '~@atomium/scss-utils/index'; + +.atom-modal { + &__close { + position: absolute; + right: var(--spacing-small); + top: var(--spacing-small); + } + + &__close-icon { + color: var(--color-neutral-regular); + font-size: var(--spacing-large); + } + + &__content { + color: var(--color-neutral-light-1); + font: var(--text-body-medium); + height: 100%; + letter-spacing: var(--text-body-medium-letter); + padding: var(--spacing-large); + padding-top: 0; + + &--divided { + border-bottom: 1px solid var(--color-neutral-light-3); + border-top: 1px solid var(--color-neutral-light-3); + padding-top: var(--spacing-large); + } + } + + &__footer { + display: flex; + flex-wrap: wrap; + gap: var(--spacing-medium); + justify-content: flex-end; + padding: var(--spacing-large); + } + + &__header { + color: var(--color-neutral-light-1); + padding: var(--spacing-large); + position: relative; + } + + &__icon-type { + font-size: var(--spacing-xxxxlarge); + margin-bottom: var(--spacing-large); + + &--warning { + color: var(--color-contextual-warning-dark-1); + } + + &--error { + color: var(--color-contextual-error-regular); + } + } + + &__title, + &__header { + font: var(--title-headline-xsmall); + letter-spacing: var(--title-headline-xsmall-letter); + margin: 0; + } + + &--progress { + .atom-modal__content--divided { + border-top: 0; + } + } + + ion-progress-bar::part(track) { + background-color: var(--color-brand-primary-light-2); + } + + @include below(small) { + &__btn-action { + width: 100%; + + &::part(button) { + width: 100%; + } + } + } +} + +ion-modal::part(content) { + --border-radius: 8px; + height: auto; + + @include below(small) { + --border-radius: 0; + height: 100%; + } +} diff --git a/packages/core/src/components/modal/modal.spec.ts b/packages/core/src/components/modal/modal.spec.ts new file mode 100644 index 000000000..303b93887 --- /dev/null +++ b/packages/core/src/components/modal/modal.spec.ts @@ -0,0 +1,132 @@ +import { newSpecPage, SpecPage } from '@stencil/core/testing' + +import { AtomModal } from './modal' + +describe('atom-modal', () => { + let page: SpecPage + + beforeEach(async () => { + page = await newSpecPage({ + components: [AtomModal], + html: ` + + Modal content + `, + }) + }) + + it('should render modal with default values', async () => { + expect(page.root).toEqualHtml(` + + +
+
+ + + +
+
+ Modal content +
+
+ + Secondary + + + Primary + +
+
+
+ `) + }) + + it('should render header slot when headerTitle is not passed', async () => { + await page.setContent(` + + Modal content +
Custom Header
+
+ `) + + expect(page.root?.textContent).toContain('Custom Header') + }) + + it('should render header from prop when headerTitle is passed', async () => { + await page.setContent(` + + Modal content +
Custom Header
+
+ `) + + expect(page.root?.innerHTML).not.toContain('