Skip to content
Open
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
62 changes: 62 additions & 0 deletions .changeset/eighty-peaches-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
"@wpmudev/sui-navigation-wpmudev": major
"@wpmudev/sui-segmented-control": major
"@wpmudev/sui-dashboard-widget": major
"@wpmudev/sui-rich-text-editor": major
"@wpmudev/sui-advanced-banner": major
"@wpmudev/sui-editor-toolbar": major
"@wpmudev/sui-setting-block": major
"@wpmudev/sui-upsell-notice": major
"@wpmudev/sui-alert-banner": major
"@wpmudev/sui-code-snippet": major
"@wpmudev/sui-color-picker": major
"@wpmudev/sui-config-table": major
"@wpmudev/sui-notification": major
"@wpmudev/sui-progress-bar": major
"@wpmudev/sui-setup-banner": major
"@wpmudev/sui-code-editor": major
"@wpmudev/sui-date-picker": major
"@wpmudev/sui-empty-state": major
"@wpmudev/sui-integration": major
"@wpmudev/sui-page-header": major
"@wpmudev/sui-summary-box": major
"@wpmudev/sui-field-list": major
"@wpmudev/sui-form-field": major
"@wpmudev/sui-navigation": major
"@wpmudev/sui-pagination": major
"@wpmudev/sui-accordion": major
"@wpmudev/sui-basic-box": major
"@wpmudev/sui-recipient": major
"@wpmudev/sui-tree-view": major
"@wpmudev/sui-checkbox": major
"@wpmudev/sui-dropdown": major
"@wpmudev/sui-selector": major
"@wpmudev/sui-skeleton": major
"@wpmudev/sui-uploader": major
"@wpmudev/sui-css": major
"@wpmudev/sui-builder": major
"@wpmudev/sui-popover": major
"@wpmudev/sui-sidebar": major
"@wpmudev/sui-spinner": major
"@wpmudev/sui-tooltip": major
"@wpmudev/sui-avatar": major
"@wpmudev/sui-drawer": major
"@wpmudev/sui-footer": major
"@wpmudev/sui-search": major
"@wpmudev/sui-select": major
"@wpmudev/sui-toggle": major
"@wpmudev/sui-upsell": major
"@wpmudev/sui-input": major
"@wpmudev/sui-modal": major
"@wpmudev/sui-radio": major
"@wpmudev/sui-score": major
"@wpmudev/sui-table": major
"@wpmudev/sui-grid": major
"@wpmudev/sui-icon": major
"@wpmudev/sui-link": major
"@wpmudev/sui-tabs": major
"@wpmudev/sui-box": major
"@wpmudev/sui-tag": major
---

Added missing ids to components
2 changes: 1 addition & 1 deletion packages/assets/css/src/scss/_utils/_tokens.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

// Do not edit directly
// Generated on Mon, 03 Nov 2025 10:48:23 GMT
// Generated on Tue, 16 Dec 2025 09:32:11 GMT

$accordion-border-radius-sm: 10px;
$advanced-banner-background: linear-gradient(90deg, #222 0%, #383323 48.96%, #514524 100%);
Expand Down
38 changes: 29 additions & 9 deletions packages/ui/accordion/src/accordion-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { AccordionItemProps } from "./accordion.types"

// The AccordionItem component is defined as a functional component using React.FC.
const AccordionItem: React.FC<AccordionItemProps> = ({
id,
title = "{title}",
description,
children,
Expand All @@ -40,7 +41,8 @@ const AccordionItem: React.FC<AccordionItemProps> = ({
const [isPressed, setIsPressed] = useState(false)

// Custom hook to generate a unique ID for the accordion item.
const uniqueId = useId()
const generatedId = useId()
const uniqueId = id || `sui_accordion_${generatedId}`

// Get the "toggle" method and "isCurrentlyExpanded" state from the current AccordionItem
const { toggle, isCurrentlyExpanded } = useAccordion({
Expand All @@ -50,8 +52,8 @@ const AccordionItem: React.FC<AccordionItemProps> = ({
const { spacing } = useContext(AccordionContext)

// IDs for the accordion and its panel to manage accessibility.
const accordionId = `sui-accordion-${uniqueId}`
const accordionPanelId = `sui-accordion-panel-${uniqueId}`
const accordionId = uniqueId
const accordionPanelId = `${uniqueId}_panel`

const onMouseDownCapture = () => {
setIsPressed(true)
Expand Down Expand Up @@ -100,6 +102,7 @@ const AccordionItem: React.FC<AccordionItemProps> = ({
// Render the AccordionItem component with proper accessibility attributes.
return (
<div
id={uniqueId}
className={generateCN(
"sui-accordion__item",
{
Expand Down Expand Up @@ -150,13 +153,19 @@ const AccordionItem: React.FC<AccordionItemProps> = ({
)}

{/* Content of the accordion item's header */}
<div className="sui-accordion__header-info">
<div
className="sui-accordion__header-info"
id={`${accordionId}_header_info`}
>
{(!!hasCheckbox || !!icon) && (
<div className="sui-accordion__header-actions">
<div
className="sui-accordion__header-actions"
id={`${accordionId}_header_actions`}
>
{hasCheckbox && (
<Checkbox
name={accordionId}
id={`${accordionId}-checkbox`}
id={`${accordionId}_checkbox`}
onChange={onCheckBoxChange}
isChecked={isChecked}
isDisabled={isDisabled ?? false}
Expand All @@ -165,13 +174,19 @@ const AccordionItem: React.FC<AccordionItemProps> = ({
{!!icon && icon}
</div>
)}
<div className="sui-accordion__header-title">
<div
className="sui-accordion__header-title"
id={`${accordionId}_header_title`}
>
<h2>{title}</h2>
{!isEmpty(description ?? "") && <p>{description}</p>}
</div>
</div>
{/* Icon component to display a chevron icon */}
<div className="sui-accordion__header-icon">
<div
className="sui-accordion__header-icon"
id={`${accordionId}_header_icon`}
>
<Icon iconHeight={16} iconWidth={16} />
</div>
</div>
Expand All @@ -188,7 +203,12 @@ const AccordionItem: React.FC<AccordionItemProps> = ({
})}
data-testid="accordion-item-panel"
>
<div className={panelContentClassName}>{children}</div>
<div
className={panelContentClassName}
id={`${accordionId}_panel_content`}
>
{children}
</div>
</div>
</div>
)
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/accordion/src/accordion.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Import necessary modules and types
import React, { useState } from "react"
import React, { useState, useId } from "react"

import { _renderHTMLPropsSafely, generateCN, isEmpty } from "@wpmudev/sui-utils"
import { AccordionProps } from "./accordion.types"
Expand All @@ -8,6 +8,7 @@ import { useDefaultChildren, useStyles } from "@wpmudev/sui-hooks"

// Define the Accordion component as a functional component (React.FC)
const Accordion: React.FC<AccordionProps> = ({
id,
className,
state = "default",
noBorderRadius = false,
Expand All @@ -19,6 +20,8 @@ const Accordion: React.FC<AccordionProps> = ({
_htmlProps = {},
_style = {},
}) => {
const generatedId = useId()
const accordionId = id || `sui_accordion_${generatedId}`
const [expandState, setExpandState] = useState<Record<string, boolean>>({})

// Default children content
Expand Down Expand Up @@ -48,7 +51,11 @@ const Accordion: React.FC<AccordionProps> = ({
isFlushed,
}}
>
<div className={classNames} {..._renderHTMLPropsSafely(_htmlProps)}>
<div
id={accordionId}
className={classNames}
{..._renderHTMLPropsSafely(_htmlProps)}
>
{children}
</div>
</AccordionProvider>
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/accordion/src/accordion.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SuiHTMLAttributes, SuiStyleType } from "@wpmudev/sui-utils"
interface AccordionProps
extends SuiHTMLAttributes<HTMLProps<HTMLDivElement>>,
SuiStyleType {
id?: string // Optional custom ID for the accordion item.
/** Additional CSS class name for styling the accordion component. */
className?: string
/** Remove border-radius when true */
Expand Down Expand Up @@ -36,6 +37,7 @@ type AccordionCheckboxProps =
interface AccordionItemBaseProps
extends SuiHTMLAttributes<HTMLProps<HTMLDivElement>>,
SuiStyleType {
id?: string // Optional custom ID for the accordion item.
title?: string // The title of the accordion item.
description?: string // The description of the accordion item.
children?: React.ReactNode // The content of the accordion item, which can be any valid React node.
Expand Down
6 changes: 5 additions & 1 deletion packages/ui/advanced-banner/src/advanced-banner.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react"
import React, { useId } from "react"

import { _renderHTMLPropsSafely, generateCN, isEmpty } from "@wpmudev/sui-utils"
import { Button, ButtonProps } from "@wpmudev/sui-button"
Expand All @@ -7,6 +7,7 @@ import { useStyles } from "@wpmudev/sui-hooks"

// Build "advanced-banner" component
const AdvancedBanner: React.FC<AdvancedBannerProps> = ({
id,
variation = "plugin",
imageUrl = "https://placehold.co/100",
title = "Banner Title",
Expand All @@ -23,6 +24,8 @@ const AdvancedBanner: React.FC<AdvancedBannerProps> = ({
_htmlProps = {},
_style = {},
}) => {
const generatedId = useId()
const advancedBannerId = id || `sui_advanced_banner_${generatedId}`
const { suiInlineClassname } = useStyles(_style, className)

// Define class name
Expand All @@ -43,6 +46,7 @@ const AdvancedBanner: React.FC<AdvancedBannerProps> = ({

return (
<div
id={advancedBannerId}
className={classNames}
data-testid="advanced-banner"
{..._renderHTMLPropsSafely(_htmlProps)}
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/advanced-banner/src/advanced-banner.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { SuiHTMLAttributes, SuiStyleType } from "@wpmudev/sui-utils"
export interface AdvancedBannerBasePros
extends SuiHTMLAttributes<HTMLProps<HTMLDivElement>>,
SuiStyleType {
/**
* Unique identifier for the advanced banner.
*/
id?: string
/**
* Sets the headline text
*/
Expand Down
6 changes: 5 additions & 1 deletion packages/ui/alert-banner/src/alert-banner.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useCallback } from "react"
import React, { useId, useState, useCallback } from "react"
import { _renderHTMLPropsSafely, generateCN, isEmpty } from "@wpmudev/sui-utils"
import { Button, ButtonProps } from "@wpmudev/sui-button"
import Icons from "@wpmudev/sui-icons"
Expand All @@ -7,6 +7,7 @@ import { useDefaultChildren, useStyles } from "@wpmudev/sui-hooks"
import { AlertBannerProps } from "./alert-banner.types"

const AlertBanner: React.FC<AlertBannerProps> = ({
id,
children,
variation = "informative",
actions,
Expand All @@ -18,6 +19,8 @@ const AlertBanner: React.FC<AlertBannerProps> = ({
_style = {},
_htmlProps,
}) => {
const generatedId = useId()
const alertBannerId = id || `sui_alert_banner_${generatedId}`
// State to control the visibility of the alert banner
const [isVisible, setIsVisible] = useState(true)

Expand Down Expand Up @@ -85,6 +88,7 @@ const AlertBanner: React.FC<AlertBannerProps> = ({

return (
<div
id={alertBannerId}
className={classNames}
data-testid="alert-banner"
{..._renderHTMLPropsSafely(_htmlProps)}
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/alert-banner/src/alert-banner.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import { SuiHTMLAttributes, SuiStyleType } from "@wpmudev/sui-utils"
interface AlertBannerProps
extends SuiStyleType,
SuiHTMLAttributes<HTMLProps<HTMLDivElement>> {
/**
* Unique identifier for the alert banner.
*/
id?: string
/**
* Alert Banner content
*/
Expand Down
21 changes: 17 additions & 4 deletions packages/ui/avatar/src/avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react"
import React, { useId } from "react"
import {
_renderHTMLPropsSafely,
generateCN,
Expand All @@ -16,6 +16,7 @@ import { useStyles } from "@wpmudev/sui-hooks"

// Build "avatar" component
const Avatar: React.FC<AvatarProps> = ({
id,
image,
status = "none",
isSmall = false,
Expand All @@ -25,6 +26,9 @@ const Avatar: React.FC<AvatarProps> = ({
_style = {},
onClick,
}) => {
const generatedId = useId()
const avatarId = id || `sui_avatar_${generatedId}`

// Define image object
const imageObj = Object.assign(
{
Expand All @@ -51,6 +55,7 @@ const Avatar: React.FC<AvatarProps> = ({
)

const attributes = {
id: avatarId,
className: classNames,
..._renderHTMLPropsSafely(_htmlProps),
"data-testid": "avatar",
Expand All @@ -59,9 +64,17 @@ const Avatar: React.FC<AvatarProps> = ({

return (
<span {...attributes}>
{hasImage && <Image source={imageObj.src} text={imageObj.alt} />}
{!hasImage && <Icon iconName={icon} />}
{hasStatus && status !== "none" && <Status status={status} />}
{hasImage && (
<Image
id={`${avatarId}_image`}
source={imageObj.src}
text={imageObj.alt}
/>
)}
{!hasImage && <Icon id={`${avatarId}_icon`} iconName={icon} />}
{hasStatus && status !== "none" && (
<Status id={`${avatarId}_status`} status={status} />
)}
</span>
)
}
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/avatar/src/avatar.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import { IconsNamesType } from "@wpmudev/sui-icons"
interface AvatarProps
extends SuiHTMLAttributes<HTMLProps<HTMLSpanElement>>,
SuiStyleType {
/**
* Unique identifier for the avatar.
*/
id?: string
/**
* The image source for the avatar.
*/
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/avatar/src/elements/icon-avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { Fragment } from "react"
import Icons, { IconsNamesType, User, UserAlt } from "@wpmudev/sui-icons"
// Build "icon avatar" element
const Icon = ({ iconName }: { iconName: IconsNamesType }) => {
const Icon = ({ id, iconName }: { id?: string; iconName: IconsNamesType }) => {
const IconTag = Icons?.[iconName as IconsNamesType]
return (
<span className="sui-avatar__icon" aria-hidden="true">
<span id={id} className="sui-avatar__icon" aria-hidden="true">
<IconTag data-testid="avatar-icon" />
</span>
)
Expand Down
Loading
Loading