UNPKG

@reusable-ui/button

Version:

A button component for initiating an action.

133 lines (103 loc) 4.18 kB
// react: import { // react: default as React, } from 'react' // reusable-ui core: import { // a semantic management system for react web components: SemanticTag, SemanticRole, useSemantic, useTestSemantic, // a set of client-side functions: isClientSideLink, } from '@reusable-ui/core' // a set of reusable-ui packages which are responsible for building any component // reusable-ui components: import type { // react components: ActionControlProps, } from '@reusable-ui/action-control' // a base component // defaults: const _defaultSemanticTag : SemanticTag = ['button', 'a' ] // uses <button> as the default semantic tag , fallbacks to <a> const _defaultSemanticRole : SemanticRole = ['button', 'link'] // uses [role="button"] as the default semantic role, fallbacks to [role="link"] const _defaultLinkSemanticTag : SemanticTag = ['a' , 'button'] // uses <a> as the default semantic tag , fallbacks to <button> const _defaultLinkSemanticRole : SemanticRole = ['link', 'button'] // uses [role="link"] as the default semantic role, fallbacks to [role="button"] // hooks: // semantics: //#region SemanticButton export type ButtonType = 'button'|'submit'|'reset' export interface SemanticButtonProps<TElement extends Element = HTMLButtonElement> extends // bases: ActionControlProps<TElement>, // button: Omit<React.ButtonHTMLAttributes<TElement>, // semantics: |'role' // we redefined [role] in <Generic> // accessibilities: |'disabled' // we use [enabled] instead of [disabled] // formats: |'type' // we redefined [type] in <Button> >, // link: Omit<React.AnchorHTMLAttributes<TElement>, // semantics: |'role' // we redefined [role] in <Generic> // formats: |'type' // we redefined [type] in <Button> > { // actions: type ?: ButtonType | (string & {}) } export const useSemanticButton = <TElement extends Element = HTMLButtonElement>(props: SemanticButtonProps<TElement>) => { // fn props: const isNativeLink = !!props.href; // assigning [href] will render the <Button> as <a> const isClientLink = !isNativeLink && React.Children.toArray(props.children).some(isClientSideLink); /* if has [href] or <Link> => default to <a> or <foo role='link'> else => default to <button> or <foo role='button'> */ const semanticTag = props.semanticTag ?? ((isNativeLink || isClientLink) ? _defaultLinkSemanticTag : _defaultSemanticTag ); const semanticRole = props.semanticRole ?? ((isNativeLink || isClientLink) ? _defaultLinkSemanticRole : _defaultSemanticRole); const { tag : finalTag, role : finalRole, } = useSemantic({ tag : props.tag, role : props.role, semanticTag, semanticRole, }); const { isDesiredType : isButtonType, isSemanticTag : isSemanticButton, } = useTestSemantic( // test: { tag : props.tag, role : props.role, semanticTag, semanticRole, }, // expected: { semanticTag : 'button', semanticRole : 'button', } ); const type = props.type ?? (isSemanticButton ? 'button' : undefined); return { isNativeLink, isClientSideLink: isClientLink, semanticTag, semanticRole, tag : finalTag, role : finalRole, isButtonType, isSemanticButton, type, }; }; //#endregion SemanticButton