From 7ca65a91078c046595f7b1371d0735d90f76d12d Mon Sep 17 00:00:00 2001 From: Maximilian Franzke Date: Wed, 19 Jun 2024 14:04:04 +0200 Subject: [PATCH 01/10] refactor: added a relevant selector part --- packages/components/src/components/tooltip/tooltip.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/tooltip/tooltip.scss b/packages/components/src/components/tooltip/tooltip.scss index a5673084270..ba9c88d4081 100644 --- a/packages/components/src/components/tooltip/tooltip.scss +++ b/packages/components/src/components/tooltip/tooltip.scss @@ -104,7 +104,7 @@ $tooltip-arrow-shadow-size: variables.$db-sizing-2xs; // Global styles @mixin show-popover($state) { - :has( + [aria-describedby]:has( > :is(db-tooltip, dbtooltip) > .db-tooltip:not([data-open]), > .db-tooltip:not([data-open]) ) { @@ -116,7 +116,7 @@ $tooltip-arrow-shadow-size: variables.$db-sizing-2xs; } } -:has(> db-tooltip, > dbtooltip, > .db-tooltip) { +[aria-describedby]:has(> db-tooltip, > dbtooltip, > .db-tooltip) { position: relative; } From af341718954b3befcd96325e432267c01552d520 Mon Sep 17 00:00:00 2001 From: Maximilian Franzke <787658+mfranzke@users.noreply.github.com> Date: Fri, 21 Jun 2024 08:36:14 +0200 Subject: [PATCH 02/10] Update tooltip.scss --- packages/components/src/components/tooltip/tooltip.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/components/tooltip/tooltip.scss b/packages/components/src/components/tooltip/tooltip.scss index ba9c88d4081..51aa876813a 100644 --- a/packages/components/src/components/tooltip/tooltip.scss +++ b/packages/components/src/components/tooltip/tooltip.scss @@ -104,7 +104,7 @@ $tooltip-arrow-shadow-size: variables.$db-sizing-2xs; // Global styles @mixin show-popover($state) { - [aria-describedby]:has( + [data-has-tooltip="true"]:has( > :is(db-tooltip, dbtooltip) > .db-tooltip:not([data-open]), > .db-tooltip:not([data-open]) ) { @@ -116,7 +116,7 @@ $tooltip-arrow-shadow-size: variables.$db-sizing-2xs; } } -[aria-describedby]:has(> db-tooltip, > dbtooltip, > .db-tooltip) { +[data-has-tooltip="true"]:has(> db-tooltip, > dbtooltip, > .db-tooltip) { position: relative; } From 3fc3f5b0444262d821f4eaae70b2220d35cac39a Mon Sep 17 00:00:00 2001 From: Nicolas Merget Date: Fri, 21 Jun 2024 11:54:17 +0200 Subject: [PATCH 03/10] chore: remove global has selectors and refactor tooltip & badge --- .../src/components/badge/badge.lite.tsx | 41 +++++++++++++++++-- .../src/components/badge/badge.scss | 25 ++++++++--- .../components/src/components/badge/model.ts | 10 ++++- .../src/components/tooltip/tooltip.lite.tsx | 17 ++++++-- .../src/components/tooltip/tooltip.scss | 7 +--- .../components/tooltip/tooltip.component.html | 3 +- .../src/components/tooltip/index.tsx | 8 ++-- .../src/components/tooltip/Tooltip.vue | 3 +- 8 files changed, 86 insertions(+), 28 deletions(-) diff --git a/packages/components/src/components/badge/badge.lite.tsx b/packages/components/src/components/badge/badge.lite.tsx index 0892d43033e..7bbef7371b1 100644 --- a/packages/components/src/components/badge/badge.lite.tsx +++ b/packages/components/src/components/badge/badge.lite.tsx @@ -1,6 +1,14 @@ -import { useMetadata, useRef, useStore } from '@builder.io/mitosis'; +import { + onMount, + onUpdate, + Show, + useMetadata, + useRef, + useStore +} from '@builder.io/mitosis'; import { DBBadgeProps, DBBadgeState } from './model'; import { cls } from '../../utils'; +import { DEFAULT_LABEL } from '../../shared/constants'; useMetadata({ isAttachedToShadowDom: true @@ -8,7 +16,30 @@ useMetadata({ export default function DBBadge(props: DBBadgeProps) { const ref = useRef(null); - const state = useStore({}); + const state = useStore({ + initialized: false + }); + + onMount(() => { + state.initialized = true; + }); + + onUpdate(() => { + if (ref && state.initialized) { + if (props.placement?.startsWith('corner')) { + let parent = ref.parentElement; + + if (parent && parent.localName.includes('badge')) { + // Angular workaround + parent = parent.parentElement; + } + + if (parent) { + parent.setAttribute('data-has-badge', 'true'); + } + } + } + }, [ref, state.initialized]); return ( + data-placement={props.placement} + data-label={ + props.placement?.startsWith('corner') && + (props.label ?? DEFAULT_LABEL) + }> {props.children} ); diff --git a/packages/components/src/components/badge/badge.scss b/packages/components/src/components/badge/badge.scss index a1a0f9d5f25..e92ecdee89a 100644 --- a/packages/components/src/components/badge/badge.scss +++ b/packages/components/src/components/badge/badge.scss @@ -36,6 +36,13 @@ } } +@mixin empty-badge { + &:empty, + > span:empty { + @content; + } +} + .db-badge { --badge-size: #{variables.$db-spacing-fixed-xs}; @extend %component-border; @@ -43,13 +50,12 @@ @extend %default-button; @include tag-components.get-tag-colors(); - border-radius: 42px; // extreme radius + border-radius: variables.$db-border-radius-full; padding-inline: variables.$db-spacing-fixed-2xs; block-size: fit-content; inline-size: fit-content; - &:empty, - > span:empty { + @include empty-badge { block-size: var(--badge-size); inline-size: var(--badge-size); padding: 0; @@ -69,8 +75,7 @@ @extend %db-overwrite-font-size-sm; padding-inline: variables.$db-spacing-fixed-xs; - &:empty, - > span:empty { + @include empty-badge { padding: 0; } @@ -86,11 +91,19 @@ &[data-placement^="corner"] { @extend %absolute-badge; + + &[data-label] { + &::before { + content: attr(data-label); + position: fixed; + font-size: 0; + } + } } } // Global styles -:has(> .db-badge[data-placement^="corner"]) { +[data-has-badge="true"] { position: relative; } diff --git a/packages/components/src/components/badge/model.ts b/packages/components/src/components/badge/model.ts index 63eec4002d8..b3dc12ca626 100644 --- a/packages/components/src/components/badge/model.ts +++ b/packages/components/src/components/badge/model.ts @@ -3,7 +3,8 @@ import { EmphasisProps, GlobalProps, GlobalState, - SizeProps + SizeProps, + InitializedState } from '../../shared/model'; export const BadgePlacementList = [ @@ -22,6 +23,11 @@ export interface DBBadgeDefaultProps { * The `placement` attributes `corner-*` values change the position to absolute and adds a transform based on the placement. */ placement?: BadgePlacementType; + + /** + * Describes the badge for a11y if you use placement attribute with `corner-*` + */ + label?: string; } export type DBBadgeProps = DBBadgeDefaultProps & @@ -32,4 +38,4 @@ export type DBBadgeProps = DBBadgeDefaultProps & export interface DBBadgeDefaultState {} -export type DBBadgeState = DBBadgeDefaultState & GlobalState; +export type DBBadgeState = DBBadgeDefaultState & GlobalState & InitializedState; diff --git a/packages/components/src/components/tooltip/tooltip.lite.tsx b/packages/components/src/components/tooltip/tooltip.lite.tsx index e8c3bb6d3e0..372a9116262 100644 --- a/packages/components/src/components/tooltip/tooltip.lite.tsx +++ b/packages/components/src/components/tooltip/tooltip.lite.tsx @@ -6,8 +6,9 @@ import { useStore } from '@builder.io/mitosis'; import { DBTooltipProps, DBTooltipState } from './model'; -import { cls, handleDataOutside } from '../../utils'; +import { cls, handleDataOutside, uuid } from '../../utils'; import { ClickEvent } from '../../shared/model'; +import { DEFAULT_ID } from '../../shared/constants'; useMetadata({ isAttachedToShadowDom: true @@ -17,6 +18,7 @@ export default function DBTooltip(props: DBTooltipProps) { const ref = useRef(null); // jscpd:ignore-start const state = useStore({ + _id: DEFAULT_ID, initialized: false, handleClick: (event: ClickEvent) => { event.stopPropagation(); @@ -27,18 +29,27 @@ export default function DBTooltip(props: DBTooltipProps) { }); onMount(() => { + state._id = props.id || 'tooltip-' + uuid(); state.initialized = true; }); onUpdate(() => { if (ref && state.initialized) { - const parent = ref.parentElement; + let parent = ref.parentElement; + + if (parent && parent.localName.includes('tooltip')) { + // Angular workaround + parent = parent.parentElement; + } + if (parent) { ['mouseenter', 'focus'].forEach((event) => { parent.addEventListener(event, () => state.handleAutoPlacement() ); }); + parent.setAttribute('data-has-tooltip', 'true'); + parent.setAttribute('aria-describedby', state._id); } state.initialized = false; @@ -53,7 +64,7 @@ export default function DBTooltip(props: DBTooltipProps) { role="tooltip" ref={ref} className={cls('db-tooltip', props.className)} - id={props.id} + id={state._id} data-emphasis={props.emphasis} data-animation={props.animation} data-delay={props.delay} diff --git a/packages/components/src/components/tooltip/tooltip.scss b/packages/components/src/components/tooltip/tooltip.scss index 51aa876813a..7add1ebd3b9 100644 --- a/packages/components/src/components/tooltip/tooltip.scss +++ b/packages/components/src/components/tooltip/tooltip.scss @@ -104,10 +104,7 @@ $tooltip-arrow-shadow-size: variables.$db-sizing-2xs; // Global styles @mixin show-popover($state) { - [data-has-tooltip="true"]:has( - > :is(db-tooltip, dbtooltip) > .db-tooltip:not([data-open]), - > .db-tooltip:not([data-open]) - ) { + [data-has-tooltip="true"] { &:#{$state} { .db-tooltip:first-of-type { @extend %show-popover; @@ -116,7 +113,7 @@ $tooltip-arrow-shadow-size: variables.$db-sizing-2xs; } } -[data-has-tooltip="true"]:has(> db-tooltip, > dbtooltip, > .db-tooltip) { +[data-has-tooltip="true"] { position: relative; } diff --git a/showcases/angular-showcase/src/app/components/tooltip/tooltip.component.html b/showcases/angular-showcase/src/app/components/tooltip/tooltip.component.html index b929342d532..f774cf65b91 100644 --- a/showcases/angular-showcase/src/app/components/tooltip/tooltip.component.html +++ b/showcases/angular-showcase/src/app/components/tooltip/tooltip.component.html @@ -10,7 +10,7 @@ let-exampleIndex="exampleIndex" let-variantIndex="variantIndex" > - + {{ exampleName }} {{ exampleProps.content }} diff --git a/showcases/react-showcase/src/components/tooltip/index.tsx b/showcases/react-showcase/src/components/tooltip/index.tsx index 78cfcbaae25..22934a924b3 100644 --- a/showcases/react-showcase/src/components/tooltip/index.tsx +++ b/showcases/react-showcase/src/components/tooltip/index.tsx @@ -12,10 +12,9 @@ const getTooltip = ({ delay, content, animation, - variant, - id + variant }: DBTooltipProps & { content: string }) => ( - + {children} + variant={variant}> {content} diff --git a/showcases/vue-showcase/src/components/tooltip/Tooltip.vue b/showcases/vue-showcase/src/components/tooltip/Tooltip.vue index dff1790cdff..23700436706 100644 --- a/showcases/vue-showcase/src/components/tooltip/Tooltip.vue +++ b/showcases/vue-showcase/src/components/tooltip/Tooltip.vue @@ -9,7 +9,7 @@ import { DBButton, DBTooltip } from "../../../../../output/vue/src";