Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"unpkg": "dist/stencil/stencil.js",
"collection:main": "dist/collection/index.js",
"collection": "dist/collection/collection-manifest.json",
"sideEffects": false,
"sideEffects": true,
"description": "Contains all web components that belong to KoliBri - The accessible HTML-Standard.",
"keywords": [
"accessibility",
Expand Down Expand Up @@ -65,6 +65,7 @@
"lint:stylelint": "stylelint \"src/**/*.{css,scss}\"",
"lint:tsc": "tsc --noemit",
"dev": "cross-env NODE_ENV=development stencil build --prod --watch",
"prod": "stencil build --prod",
"test": "pnpm test:unit",
"test:e2e": "playwright test",
"test:unit": "cross-env NODE_ENV=test stencil test --spec --json --outputFile dist/jest-test-results.json",
Expand All @@ -84,6 +85,7 @@
"query-selector-all-shadow-root": "0.0.3",
"query-selector-shadow-root": "0.0.3",
"rgba-convert": "0.3.0",
"typed-bem": "1.0.0-rc.7",
"wcag-contrast": "3.0.0"
},
"devDependencies": {
Expand Down

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/components/src/components/combobox/shadow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import KolInputContainerFc from '../../functional-component-wrappers/InputContai
import CustomSuggestionsToggleFc from '../../functional-components/CustomSuggestionsToggle';
import CustomSuggestionsOptionFc from '../../functional-components/CustomSuggestionsOption/CustomSuggestionsOption';
import CustomSuggestionsOptionsGroupFc from '../../functional-components/CustomSuggestionsOptionsGroup';
import { EventDetail } from '../../schema/interfaces/EventDetail';
import type { EventDetail } from '../../schema/interfaces/EventDetail';

/**
* @slot - Die Beschriftung des Eingabefeldes.
Expand Down
32 changes: 32 additions & 0 deletions packages/components/src/components/icon/bem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { generateBemClassNames } from 'typed-bem';

type SCHEMA = {
'kol-icon': {
elements: {
icon: {
modifiers: null;
};
};
modifiers: null;
};
};

const bem = generateBemClassNames<SCHEMA>();

const BEM: SCHEMA = {
'kol-icon': {
elements: {
icon: { modifiers: null },
},
modifiers: null,
},
};

/**
* Define the static BEM class names for the alert component.
*/
const BEM_CLASS_ICON = bem('kol-icon');
const BEM_CLASS_ICON__ICON = bem('kol-icon', 'icon');

export { bem as genBemAlert, BEM as BEM_ICON };
export { BEM_CLASS_ICON, BEM_CLASS_ICON__ICON };
8 changes: 5 additions & 3 deletions packages/components/src/components/icon/shadow.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Component, h, Host, Prop, State, Watch } from '@stencil/core';
import type { IconAPI, IconStates, LabelPropType } from '../../schema';
import { validateLabel, watchString } from '../../schema';
import { Component, h, Host, Prop, State, Watch } from '@stencil/core';

import type { JSX } from '@stencil/core';
import clsx from 'clsx';
import { BEM_CLASS_ICON, BEM_CLASS_ICON__ICON } from './bem';

/**
* @part icon - Ermöglicht das Styling des inneren Icons.
*/
Expand All @@ -18,7 +20,7 @@ export class KolIcon implements IconAPI {
public render(): JSX.Element {
const ariaShow = this.state._label.length > 0;
return (
<Host exportparts="icon" class="kol-icon">
<Host exportparts="icon" class={BEM_CLASS_ICON}>
<i
aria-hidden={ariaShow ? undefined : 'true'}
/**
Expand All @@ -28,7 +30,7 @@ export class KolIcon implements IconAPI {
* Referenz: https://www.w3.org/TR/wai-aria/states_and_properties#aria-hidden
*/
aria-label={ariaShow ? this.state._label : undefined}
class={clsx('kol-icon__icon', this.state._icons)}
class={clsx(BEM_CLASS_ICON__ICON, this.state._icons)}
part="icon"
role="img"
></i>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { KolProgress } from '../shadow';
import { executeSnapshotTests } from '../../../utils/testing';
import { ProgressProps } from '../../../schema';
import type { ProgressProps } from '../../../schema';
import { KolProgressTag } from '../../../core/component-names';

executeSnapshotTests<ProgressProps>(
Expand Down
59 changes: 45 additions & 14 deletions packages/components/src/functional-components/Alert/Alert.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { type FunctionalComponent as FC, h } from '@stencil/core';
import type { JSXBase } from '@stencil/core/internal';
import { type JSXBase } from '@stencil/core/internal';
import clsx from 'clsx';

import { type InternalAlertProps } from '../../schema';
import { translate } from '../../i18n';
import { KolButtonWcTag } from '../../core/component-names';

import { translate } from '../../i18n';
import { type InternalAlertProps } from '../../schema';
import AlertIcon from '../AlertIcon';
import KolHeadingFc from '../Heading';
import { genBemAlert as bem, BEM_CLASS_ALERT__CLOSER, BEM_CLASS_ALERT__CONTENT } from './bem';

export type KolAlertFcProps = JSXBase.HTMLAttributes<HTMLDivElement> &
Partial<Omit<InternalAlertProps, 'on'>> & {
Expand All @@ -16,7 +16,18 @@ export type KolAlertFcProps = JSXBase.HTMLAttributes<HTMLDivElement> &
};

const KolAlertFc: FC<KolAlertFcProps> = (props, children) => {
const { class: classNames = {}, type = 'default', variant = 'msg', label, hasCloser, alert, onAlertTimeout, onCloserClick, level, ...other } = props;
const {
class: classNames = {},
alert = false,
hasCloser = false,
label,
level = 0,
type = 'default',
variant = 'msg',
onAlertTimeout,
onCloserClick,
...other
} = props;

if (alert) {
/**
Expand All @@ -34,9 +45,21 @@ const KolAlertFc: FC<KolAlertFcProps> = (props, children) => {
}, 10000);
}

/**
* Define the dynamic BEM class names for the alert component.
*/
const BEM_CLASS_ROOT = bem('kol-alert', {
hasCloser: !!hasCloser,
[`type-${type}`]: true,
[`variant-${variant}`]: true,
});
const BEM_CLASS__HEADING = bem('kol-alert', 'heading', {
[`h${level}`]: true,
});

const rootProps: Partial<JSXBase.HTMLAttributes<HTMLDivElement>> = {
class: clsx('kol-alert', `kol-alert--${type}`, `kol-alert--${variant}`, { 'kol-alert--hasCloser': !!hasCloser }, classNames),
role: alert ? 'alert' : undefined,
class: clsx(classNames, BEM_CLASS_ROOT),
role: alert ? (type === 'error' ? 'alert' : 'status') : undefined,
...other,
};

Expand All @@ -45,16 +68,20 @@ const KolAlertFc: FC<KolAlertFcProps> = (props, children) => {
<div class="kol-alert__container">
<AlertIcon label={label} type={type} />
<div class="kol-alert__container-content">
{label ? (
<KolHeadingFc class="kol-alert__heading" level={level}>
{label && (
<KolHeadingFc class={BEM_CLASS__HEADING} level={level} id="heading">
{label}
</KolHeadingFc>
) : null}
{variant === 'msg' && <div class="kol-alert__content">{children}</div>}
)}
{variant === 'msg' && (
<span class={BEM_CLASS_ALERT__CONTENT} aria-describedby={label ? 'heading' : undefined}>
{children}
</span>
)}
</div>
{hasCloser && (
<KolButtonWcTag
class="kol-alert__close-button close"
class={BEM_CLASS_ALERT__CLOSER}
data-testid="alert-close-button"
_ariaDescription={label?.trim() || ''}
_hideLabel
Expand All @@ -66,10 +93,14 @@ const KolAlertFc: FC<KolAlertFcProps> = (props, children) => {
_label={translate('kol-close-alert')}
_on={{ onClick: onCloserClick }}
_tooltipAlign="left"
></KolButtonWcTag>
/>
)}
</div>
{variant === 'card' && <div class="kol-alert__content">{children}</div>}
{variant === 'card' && (
<div class={BEM_CLASS_ALERT__CONTENT} aria-describedby={label ? 'heading' : undefined}>
{children}
</div>
)}
</div>
);
};
Expand Down
76 changes: 76 additions & 0 deletions packages/components/src/functional-components/Alert/bem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { generateBemClassNames } from 'typed-bem';

/**
* This file defines the BEM schema for the kol-alert component.
*/

/**
* The schema defines the structure of the BEM class names
*/
type SCHEMA = {
'kol-alert': {
/**
* Here we define the elements we needed
* to realize a minimal full featured alert
* component (DOM).
*/
elements: {
container: {
modifiers: null;
};
icon: {
modifiers: null;
};
heading: {
/**
* Some elements needs modifiers to
* style them properly.
*/
modifiers: Set<'h0' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'>;
};
content: {
modifiers: null;
};
closer: {
modifiers: null;
};
};
/**
* Here we define the modifiers related to the
* kol-alert component properties.
*/
modifiers: Set<'hasCloser' | 'type-default' | 'type-error' | 'type-info' | 'type-success' | 'type-warning' | 'variant-card' | 'variant-msg'>;
};
};

/**
* Define the generator function for the BEM class names.
*/
const bem = generateBemClassNames<SCHEMA>();

/**
* Define a constants object that contains the BEM schema for
* reuse to generate SCSS files in themes.
*/
const BEM: SCHEMA = {
'kol-alert': {
elements: {
closer: { modifiers: null },
heading: { modifiers: new Set(['h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']) },
icon: { modifiers: null },
content: { modifiers: null },
container: { modifiers: null },
},
modifiers: new Set(['hasCloser', 'type-default', 'type-error', 'type-info', 'type-success', 'type-warning', 'variant-card', 'variant-msg']),
},
};

/**
* Define the static BEM class names for the alert component.
*/
const BEM_CLASS_ALERT__CLOSER = bem('kol-alert', 'closer');
const BEM_CLASS_ALERT__CONTENT = bem('kol-alert', 'content');
const BEM_CLASS_ALERT__ICON = bem('kol-alert', 'icon');

export { bem as genBemAlert, BEM as BEM_ALERT };
export { BEM_CLASS_ALERT__CLOSER, BEM_CLASS_ALERT__CONTENT, BEM_CLASS_ALERT__ICON };
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`KolAlertFc should render 1`] = `
<div class="kol-alert kol-alert--default kol-alert--msg">
<div class="kol-alert kol-alert--type-default kol-alert--variant-msg">
<div class="kol-alert__container">
<span class="visually-hidden">
kol-message
</span>
<kol-icon _icons="codicon codicon-comment" _label="" class="kol-alert__heading-icon"></kol-icon>
<kol-icon _icons="codicon codicon-comment" _label="" class="kol-alert__icon"></kol-icon>
<div class="kol-alert__container-content">
<div class="kol-alert__content"></div>
<span class="kol-alert__content"></span>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Fragment, type FunctionalComponent as FC, h } from '@stencil/core';
import { KolIconTag } from '../../core/component-names';
import type { AlertType } from '../../schema';
import { translate } from '../../i18n';
import { BEM_CLASS_ALERT__ICON } from '../Alert/bem';

/**
* The icon uses a visually-hidden span instead of an aria-label because the Alert might be referenced as content for aria-describedby.
Expand All @@ -12,7 +13,7 @@ const Icon: FC<{ ariaLabel: string; icon: string; label?: string }> = ({ ariaLab
return (
<>
<span class="visually-hidden">{ariaLabel}</span>
<KolIconTag class="kol-alert__heading-icon" _label="" _icons={icon} />
<KolIconTag class={BEM_CLASS_ALERT__ICON} _label="" _icons={icon} />
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,16 @@ exports[`KolFormFieldFc should render with error message 1`] = `
</span>
</label>
<div class="kol-form-field__input"></div>
<div aria-hidden="true" class="kol-alert kol-alert--error kol-alert--msg kol-form-field__msg" description="Error message" id="test-id-msg">
<div aria-hidden="true" class="kol-alert kol-alert--type-error kol-alert--variant-msg kol-form-field__msg" description="Error message" id="test-id-msg">
<div class="kol-alert__container">
<span class="visually-hidden">
kol-error
</span>
<kol-icon _icons="codicon codicon-error" _label="" class="kol-alert__heading-icon"></kol-icon>
<kol-icon _icons="codicon codicon-error" _label="" class="kol-alert__icon"></kol-icon>
<div class="kol-alert__container-content">
<div class="kol-alert__content">
<span class="kol-alert__content">
Error message
</div>
</span>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`FormFieldMsgFc should render with all props 1`] = `
<div aria-hidden="true" class="custom-class kol-alert kol-alert--error kol-alert--msg kol-form-field__msg" description="This is an error message" id="test-id-msg" role="alert">
<div aria-hidden="true" class="custom-class kol-alert kol-alert--type-error kol-alert--variant-msg kol-form-field__msg" description="This is an error message" id="test-id-msg" role="alert">
<div class="kol-alert__container">
<span class="visually-hidden">
kol-error
</span>
<kol-icon _icons="codicon codicon-error" _label="" class="kol-alert__heading-icon"></kol-icon>
<kol-icon _icons="codicon codicon-error" _label="" class="kol-alert__icon"></kol-icon>
<div class="kol-alert__container-content">
<div class="kol-alert__content">
<span class="kol-alert__content">
This is an error message
</div>
</span>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@

exports[`ToastItemFc should render with basic props and status 1`] = `
<div class="kol-toast-item kol-toast-item--settled">
<div class="kol-alert kol-alert--card kol-alert--hasCloser kol-alert--info kol-toast-item__alert" role="alert">
<div class="kol-alert kol-alert--hasCloser kol-alert--type-info kol-alert--variant-card kol-toast-item__alert" role="status">
<div class="kol-alert__container">
<span class="visually-hidden">
kol-info
</span>
<kol-icon _icons="codicon codicon-info" _label="" class="kol-alert__heading-icon"></kol-icon>
<kol-icon _icons="codicon codicon-info" _label="" class="kol-alert__icon"></kol-icon>
<div class="kol-alert__container-content">
<strong class="kol-alert__heading kol-headline kol-headline--single kol-headline--strong">
<strong class="kol-alert__heading kol-alert__heading--h0 kol-headline kol-headline--single kol-headline--strong" id="heading">
Test Toast
</strong>
</div>
<kol-button-wc _ariadescription="Test Toast" _hidelabel="" _label="kol-close-alert" _tooltipalign="left" class="close kol-alert__close-button" data-testid="alert-close-button"></kol-button-wc>
<kol-button-wc _ariadescription="Test Toast" _hidelabel="" _label="kol-close-alert" _tooltipalign="left" class="kol-alert__closer" data-testid="alert-close-button"></kol-button-wc>
</div>
<div class="kol-alert__content">
<div aria-describedby="heading" class="kol-alert__content">
<div>
Test Description
</div>
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ export type {
Toast,
ToasterOptions,
} from './schema';
export { BEM_ALERT } from './functional-components/Alert/bem';
export { BEM_ICON } from './components/icon/bem';
Loading
Loading