Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(alert): new local alert component #20

Merged
merged 15 commits into from
Dec 19, 2024
9 changes: 3 additions & 6 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: latest
- name: Run Biome
run: biome ci ./packages
- uses: oven-sh/setup-bun@v2
- run: bun install
- run: bun run lint
Binary file modified bun.lockb
Binary file not shown.
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
"workspaces": ["packages/*"],
"scripts": {
"dev": "storybook dev -p 6006",
"lint": "biome check ./packages",
"lint": "biome check ./packages && bun run check-types",
"build-docs": "tsc && storybook build",
"build-designsystem": "bun --filter '@computas/lib' build",
"check-types": "lit-analyzer packages/lib/components",
"build-designsystem": "bun run check-types && bun --filter '@computas/lib' build",
"create-icon-registry": "bun --filter '@computas/lib' create-icon-registry",
"start-react-test-project": "bun --filter '@computas/react-test-project' dev"
},
Expand All @@ -23,7 +24,9 @@
"@storybook/theming": "^8.4.7",
"@storybook/web-components": "^8.4.7",
"@storybook/web-components-vite": "^8.4.7",
"lit-analyzer": "^2.0.3",
"storybook": "^8.4.7",
"ts-lit-plugin": "^2.0.2",
"typescript": "~5.7.2",
"vite": "^6.0.3"
}
Expand Down
23 changes: 23 additions & 0 deletions packages/lib/components/alert/Overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Canvas, Meta, Subtitle, Title } from '@storybook/blocks';

import * as stories from './alert.stories';

<Meta of={stories} />

<Title>Alert</Title>
<Subtitle>
Alerts convey information or warnings to the users and should grab their
attention to help make informed actions and decisions.
</Subtitle>

### Local alert

This alert should be placed next to the content it is related to and should not be confused with toast (pops up and disappear) or global alerts (static at the top of the entire web-site). They should help the user correct a problem and then disappear once the problem is corrected.

<Canvas of={stories.AlertInfo} />

<Canvas of={stories.AlertDanger} />

<Canvas of={stories.AlertWarning} />

<Canvas of={stories.AlertSuccess} />
33 changes: 33 additions & 0 deletions packages/lib/components/alert/alert.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { Meta, StoryObj } from '@storybook/web-components';
import { html } from 'lit';

import './alert';

export default {
title: 'Components/Alert',
} satisfies Meta;

export const AlertInfo: StoryObj = {
render: () =>
html` <cx-alert header=${'Info alert'}>
Lorem ipsum dolor sit amet consectetur. Justo orci pellentesque magna quis. Lorem ipsum dolor sit amet consectetur. Justo orci pellentesque magna quis.
</cx-alert>`,
};
export const AlertDanger: StoryObj = {
render: () =>
html` <cx-alert header=${'Danger alert'} priority=${'Danger'}>
Lorem ipsum dolor sit amet consectetur. Justo orci pellentesque magna quis. Lorem ipsum dolor sit amet consectetur. Justo orci pellentesque magna quis.
</cx-alert>`,
};
export const AlertWarning: StoryObj = {
render: () =>
html` <cx-alert header=${'Warning alert'} priority=${'Warning'}>
Lorem ipsum dolor sit amet consectetur. Justo orci pellentesque magna quis. Lorem ipsum dolor sit amet consectetur. Justo orci pellentesque magna quis.
</cx-alert>`,
};
export const AlertSuccess: StoryObj = {
render: () =>
html` <cx-alert header=${'Success alert'} priority=${'Success'}>
Lorem ipsum dolor sit amet consectetur. Justo orci pellentesque magna quis. Lorem ipsum dolor sit amet consectetur. Justo orci pellentesque magna quis.
</cx-alert>`,
};
107 changes: 107 additions & 0 deletions packages/lib/components/alert/alert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { LitElement, css, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { addIcons } from '../icon';
import { type IconName, checkCircle, errorCircle, infoCircle, warning } from '../icon/iconRegistry';

addIcons(errorCircle, infoCircle, warning, checkCircle);

type AlertPriorityType = 'Info' | 'Danger' | 'Warning' | 'Success';
@customElement('cx-alert')
export class Alert extends LitElement {
static styles = css`
.cx-alert {
eTallang marked this conversation as resolved.
Show resolved Hide resolved
padding: var(--cx-spacing-6);
border-radius: var(--cx-radius-medium);
background-color: var(--cx-color-background-accent-5-soft);
border: 1px solid var(--cx-color-signal-info);
display: flex;
flex-direction: row;
align-items: flex-start;
gap: var(--cx-spacing-6);

color: var(--cx-color-text-primary);
font-family: 'Open Sans', Arial, sans-serif;

@media only screen and (max-width: 360px) {
flex-direction: column;
align-items: center;
gap: var(--cx-spacing-3);
}
}
.cx-alert--danger {
background-color: var(--cx-color-background-accent-4-soft);
border-color: var(--cx-color-signal-danger);
}
.cx-alert--warning {
background-color: var(--cx-color-background-accent-3-soft);
border-color: var(--cx-color-signal-warning);
}
.cx-alert--success {
background-color: var(--cx-color-background-accent-2-soft);
border-color: var(--cx-color-signal-success);
}

.cx-alert__content {
display: flex;
flex-direction: column;
gap: 0;
}
.cx-alert__header {
font-weight: 600;
font-size: 1.125rem;
line-height: 1.6;
}
.cx-alert__body {
font-weight: 400;
font-size: 1rem;
line-height: 1.6;
}
`;

@property({ type: String, reflect: true }) header = 'Tab title';

@property({ type: String, reflect: true }) priority: AlertPriorityType = 'Info';

render() {
let priorityIcon: IconName = 'info-circle';
switch (this.priority) {
case 'Danger':
priorityIcon = 'error-circle';
break;
case 'Warning':
priorityIcon = 'warning';
break;
case 'Success':
priorityIcon = 'check-circle';
break;
default:
priorityIcon = 'info-circle';
break;
}
return html`
<div
role="alert"
class=${classMap({
'cx-alert': true,
'cx-alert--info': this.priority === 'Info',
'cx-alert--danger': this.priority === 'Danger',
'cx-alert--warning': this.priority === 'Warning',
'cx-alert--success': this.priority === 'Success',
})}
>
<cx-icon name=${priorityIcon} size="8"></cx-icon>
<div class="cx-alert__content">
<div class="cx-alert__header">${this.header}</div>
<slot class="cx-alert__body"></slot>
</div>
</div>
`;
}
}

declare global {
interface HTMLElementTagNameMap {
'cx-alert': Alert;
}
}
1 change: 1 addition & 0 deletions packages/lib/components/alert/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './alert';
10 changes: 10 additions & 0 deletions packages/lib/components/alert/react.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { createComponent } from '@lit/react';
import * as React from 'react';

import { Alert } from './index';

export const CxAlert = createComponent({
tagName: 'cx-alert',
elementClass: Alert,
react: React,
});
2 changes: 2 additions & 0 deletions packages/lib/components/button/button.stories.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Meta, StoryObj } from '@storybook/web-components';
import { html } from 'lit';

import '../icon';

export default {
title: 'Components/Button',
} satisfies Meta;
Expand Down
1 change: 1 addition & 0 deletions packages/lib/components/icon/icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export class Icon extends LitElement {
display: inline-block;
width: var(--_icon-size);
height: var(--_icon-size);
flex: none;
line-height: 0;
}

Expand Down
2 changes: 2 additions & 0 deletions packages/lib/components/input/input.stories.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Meta, StoryObj } from '@storybook/web-components';
import { html } from 'lit';

import '../icon';

export default {
title: 'Components/Input',
} satisfies Meta;
Expand Down
1 change: 1 addition & 0 deletions packages/lib/components/tabs/tabs.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { html } from 'lit';

import './tab';
import './tab-group';
import '../icon';

export default {
title: 'Components/Tabs',
Expand Down
8 changes: 7 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
"noUncheckedSideEffectImports": true,
"plugins": [
{
"name": "ts-lit-plugin",
"strict": true,
}
]
},
"include": ["packages/lib/**/*.ts", "vite-env.d.ts"],
"exclude": ["packages/lib/**/*.stories.ts"]
Expand Down
Loading