Skip to content

Commit

Permalink
Add access key to button (#5482)
Browse files Browse the repository at this point in the history
  • Loading branch information
deleonio authored Oct 27, 2023
2 parents dd2c486 + d021f57 commit 523609b
Show file tree
Hide file tree
Showing 30 changed files with 223 additions and 17 deletions.
50 changes: 50 additions & 0 deletions packages/components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { PropColor } from "./types/props/color";
import { KoliBriHorizontalIcons, KoliBriIconsProp } from "./types/icons";
import { ButtonProps } from "./components/button/types";
import { BreadcrumbLinkProps } from "./components/breadcrumb/types";
import { AccessKeyPropType } from "./types/props/access-key";
import { CustomClassPropType } from "./types/props/custom-class";
import { IconsPropType } from "./types/props/icons";
import { ButtonCallbacksPropType } from "./types/props/button-callbacks";
Expand Down Expand Up @@ -71,6 +72,7 @@ export { PropColor } from "./types/props/color";
export { KoliBriHorizontalIcons, KoliBriIconsProp } from "./types/icons";
export { ButtonProps } from "./components/button/types";
export { BreadcrumbLinkProps } from "./components/breadcrumb/types";
export { AccessKeyPropType } from "./types/props/access-key";
export { CustomClassPropType } from "./types/props/custom-class";
export { IconsPropType } from "./types/props/icons";
export { ButtonCallbacksPropType } from "./types/props/button-callbacks";
Expand Down Expand Up @@ -256,6 +258,10 @@ export namespace Components {
"_links": Stringified<BreadcrumbLinkProps[]>;
}
interface KolButton {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
*/
Expand Down Expand Up @@ -335,6 +341,10 @@ export namespace Components {
interface KolButtonGroupWc {
}
interface KolButtonLink {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
*/
Expand Down Expand Up @@ -414,6 +424,10 @@ export namespace Components {
"_link": ButtonOrLinkOrTextWithChildrenProps;
}
interface KolButtonWc {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
*/
Expand Down Expand Up @@ -2148,6 +2162,10 @@ export namespace Components {
"_links": Stringified<LinkProps[]>;
}
interface KolSpan {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Hides the caption by default and displays the caption text with a tooltip when the interactive element is focused or the mouse is over it.
* @TODO : Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
Expand All @@ -2163,6 +2181,10 @@ export namespace Components {
"_label": LabelWithExpertSlotPropType;
}
interface KolSpanWc {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Allows to use markdown in the label. Defaults to `false`.
*/
Expand Down Expand Up @@ -2435,6 +2457,10 @@ export namespace Components {
"enqueue": (toast: Toast) => Promise<void>;
}
interface KolTooltipWc {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Defines the alignment of the tooltip, popover or tabs in relation to the element.
*/
Expand Down Expand Up @@ -3009,6 +3035,10 @@ declare namespace LocalJSX {
"_links": Stringified<BreadcrumbLinkProps[]>;
}
interface KolButton {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
*/
Expand Down Expand Up @@ -3088,6 +3118,10 @@ declare namespace LocalJSX {
interface KolButtonGroupWc {
}
interface KolButtonLink {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
*/
Expand Down Expand Up @@ -3167,6 +3201,10 @@ declare namespace LocalJSX {
"_link": ButtonOrLinkOrTextWithChildrenProps;
}
interface KolButtonWc {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
*/
Expand Down Expand Up @@ -4901,6 +4939,10 @@ declare namespace LocalJSX {
"_links": Stringified<LinkProps[]>;
}
interface KolSpan {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Hides the caption by default and displays the caption text with a tooltip when the interactive element is focused or the mouse is over it.
* @TODO : Change type back to `HideLabelPropType` after Stencil#4663 has been resolved.
Expand All @@ -4916,6 +4958,10 @@ declare namespace LocalJSX {
"_label": LabelWithExpertSlotPropType;
}
interface KolSpanWc {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Allows to use markdown in the label. Defaults to `false`.
*/
Expand Down Expand Up @@ -5187,6 +5233,10 @@ declare namespace LocalJSX {
interface KolToastContainer {
}
interface KolTooltipWc {
/**
* Defines the elements access key.
*/
"_accessKey"?: AccessKeyPropType;
/**
* Defines the alignment of the tooltip, popover or tabs in relation to the element.
*/
Expand Down
7 changes: 7 additions & 0 deletions packages/components/src/components/button-link/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { TooltipAlignPropType } from '../../types/props/tooltip-align';
import { StencilUnknown } from '../../types/unknown';
import { propagateFocus } from '../../utils/reuse';
import { Props } from './types';
import { AccessKeyPropType } from '../../types/props/access-key';

@Component({
tag: 'kol-button-link',
Expand All @@ -35,6 +36,7 @@ export class KolButtonLink implements Props {
<Host>
<kol-button-wc
ref={this.catchRef}
_accessKey={this._accessKey}
_ariaControls={this._ariaControls}
_ariaExpanded={this._ariaExpanded}
_ariaSelected={this._ariaSelected}
Expand All @@ -58,6 +60,11 @@ export class KolButtonLink implements Props {
);
}

/**
* Defines the elements access key.
*/
@Prop() public _accessKey?: AccessKeyPropType;

/**
* Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
*/
Expand Down
22 changes: 21 additions & 1 deletion packages/components/src/components/button/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { propagateResetEventToForm, propagateSubmitEventToForm } from '../form/c
import { AssociatedInputController } from '../input-adapter-leanup/associated.controller';
import { API } from './types';
import { validateAriaSelected } from '../../types/props/aria-selected';
import { AccessKeyPropType, validateAccessKey } from '../../types/props/access-key';

/**
* @internal
Expand Down Expand Up @@ -75,6 +76,7 @@ export class KolButtonWc implements API {
<Host>
<button
ref={this.catchRef}
accessKey={this.state._accessKey || undefined}
aria-controls={this.state._ariaControls}
aria-expanded={mapBoolean2String(this.state._ariaExpanded)}
aria-label={this.state._hideLabel && typeof this.state._label === 'string' ? this.state._label : undefined}
Expand All @@ -96,7 +98,13 @@ export class KolButtonWc implements API {
tabIndex={this.state._tabIndex}
type={this.state._type}
>
<kol-span-wc class="button-inner" _icons={this.state._icons} _hideLabel={this.state._hideLabel} _label={hasExpertSlot ? '' : this.state._label}>
<kol-span-wc
class="button-inner"
_icons={this.state._icons}
_hideLabel={this.state._hideLabel}
_label={hasExpertSlot ? '' : this.state._label}
_accessKey={this.state._accessKey}
>
<slot name="expert" slot="expert"></slot>
</kol-span-wc>
</button>
Expand All @@ -107,6 +115,7 @@ export class KolButtonWc implements API {
*/
aria-hidden="true"
hidden={hasExpertSlot || !this.state._hideLabel}
_accessKey={this._accessKey}
_align={this.state._tooltipAlign}
_label={typeof this.state._label === 'string' ? this.state._label : ''}
></kol-tooltip-wc>
Expand All @@ -116,6 +125,11 @@ export class KolButtonWc implements API {

private readonly controller: AssociatedInputController;

/**
* Defines the elements access key.
*/
@Prop() public _accessKey?: AccessKeyPropType;

/**
* Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
*/
Expand Down Expand Up @@ -221,6 +235,11 @@ export class KolButtonWc implements API {
this.controller = new AssociatedInputController(this, 'button', this.host);
}

@Watch('_accessKey')
public validateAccessKey(value?: AccessKeyPropType): void {
validateAccessKey(this, value);
}

@Watch('_ariaControls')
public validateAriaControls(value?: string): void {
validateAriaControls(this, value);
Expand Down Expand Up @@ -316,6 +335,7 @@ export class KolButtonWc implements API {
}

public componentWillLoad(): void {
this.validateAccessKey(this._accessKey);
this.validateAriaControls(this._ariaControls);
this.validateAriaExpanded(this._ariaExpanded);
this.validateAriaSelected(this._ariaSelected);
Expand Down
7 changes: 7 additions & 0 deletions packages/components/src/components/button/shadow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { TooltipAlignPropType } from '../../types/props/tooltip-align';
import { StencilUnknown } from '../../types/unknown';
import { propagateFocus } from '../../utils/reuse';
import { Props } from './types';
import { AccessKeyPropType } from '../../types/props/access-key';

@Component({
tag: 'kol-button',
Expand Down Expand Up @@ -40,6 +41,7 @@ export class KolButton implements Props {
[this._variant as string]: this._variant !== 'custom',
[this._customClass as string]: this._variant === 'custom' && typeof this._customClass === 'string' && this._customClass.length > 0,
}}
_accessKey={this._accessKey}
_ariaControls={this._ariaControls}
_ariaExpanded={this._ariaExpanded}
_ariaSelected={this._ariaSelected}
Expand All @@ -65,6 +67,11 @@ export class KolButton implements Props {
);
}

/**
* Defines the elements access key.
*/
@Prop() public _accessKey?: AccessKeyPropType;

/**
* Defines which elements are controlled by this component. (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-controls)
*/
Expand Down
4 changes: 3 additions & 1 deletion packages/components/src/components/button/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { PropName } from '../../types/props/name';
import { PropSyncValueBySelector } from '../../types/props/sync-value-by-selector';
import { PropTooltipAlign } from '../../types/props/tooltip-align';
import { StencilUnknown } from '../../types/unknown';
import { PropAccessKey } from '../../types/props/access-key';

export type RequiredButtonProps = PropLabelWithExpertSlot;
export type OptionalButtonProps = {
Expand All @@ -38,7 +39,8 @@ export type OptionalButtonProps = {
PropId &
PropName &
PropSyncValueBySelector &
PropTooltipAlign;
PropTooltipAlign &
PropAccessKey;
export type ButtonProps = Generic.Element.Members<RequiredButtonProps, OptionalButtonProps>;

export type RequiredButtonStates = RequiredButtonProps &
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { h } from '@stencil/core';

type Props = {
label: string;
accessKey: string;
};
export const InternalUnderlinedAccessKey = ({ label, accessKey }: Props) => {
/* Prefer capitalization as defined in the access key, try uppercase/lowercase when there's no match. */
let [first, ...rest] = label.split(accessKey);
if (rest.length === 0) {
accessKey = accessKey.toUpperCase();
[first, ...rest] = label.split(accessKey);
}
if (rest.length === 0) {
accessKey = accessKey.toLowerCase();
[first, ...rest] = label.split(accessKey);
}
return (
<span>
{first}
{rest.length ? <u>{accessKey}</u> : null}
{rest.length ? rest.join(accessKey) : null}
</span>
);
};
26 changes: 25 additions & 1 deletion packages/components/src/components/span/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { md } from '../../utils/markdown';
import { watchBoolean } from '../../utils/prop.validators';
import { showExpertSlot } from '../../utils/reuse';
import { API, States } from './types';
import { AccessKeyPropType, validateAccessKey } from '../../types/props/access-key';
import { InternalUnderlinedAccessKey } from './InternalUnderlinedAccessKey';

/**
* @internal
Expand All @@ -33,21 +35,37 @@ export class KolSpanWc implements API {
this.state._allowMarkdown && typeof this.state._label === 'string' && this.state._label.length > 0 ? (
<span class="span-label md" innerHTML={md(this.state._label)} />
) : (
<span class="span-label">{this.state._label ?? ''}</span>
<span class="span-label">
{this.state._accessKey && this.state._label.length ? (
<InternalUnderlinedAccessKey label={this.state._label} accessKey={this.state._accessKey} />
) : (
this.state._label ?? ''
)}
</span>
)
) : (
''
)}
<span aria-hidden={hideExpertSlot ? 'true' : undefined} class="span-label" hidden={hideExpertSlot}>
<slot name="expert" />
</span>
{this.state._accessKey && (
<span class="access-key-hint" aria-hidden>
{this.state._accessKey}
</span>
)}
{this.state._icons.right && <kol-icon class="icon right" style={this.state._icons.right.style} _label="" _icons={this.state._icons.right.icon} />}
</span>
{this.state._icons.bottom && <kol-icon class="icon bottom" style={this.state._icons.bottom.style} _label="" _icons={this.state._icons.bottom.icon} />}
</Host>
);
}

/**
* Defines the elements access key.
*/
@Prop() public _accessKey?: AccessKeyPropType;

/**
* Allows to use markdown in the label. Defaults to `false`.
*/
Expand Down Expand Up @@ -77,6 +95,11 @@ export class KolSpanWc implements API {
_label: '', // ⚠ required
};

@Watch('_accessKey')
public validateAccessKey(value?: AccessKeyPropType): void {
validateAccessKey(this, value);
}

@Watch('_allowMarkdown')
public validateAllowMarkdown(value?: boolean): void {
watchBoolean(this, '_allowMarkdown', value, {
Expand All @@ -100,6 +123,7 @@ export class KolSpanWc implements API {
}

public componentWillLoad(): void {
this.validateAccessKey(this._accessKey);
this.validateAllowMarkdown(this._allowMarkdown);
this.validateHideLabel(this._hideLabel);
this.validateIcons(this._icons);
Expand Down
Loading

0 comments on commit 523609b

Please sign in to comment.