Skip to content

Commit

Permalink
Merge branch 'main' into tag_set_overflow_disable
Browse files Browse the repository at this point in the history
  • Loading branch information
jeesonjohnson authored Aug 1, 2024
2 parents 980003c + 81d820d commit 1fd80a1
Show file tree
Hide file tree
Showing 7 changed files with 274 additions and 61 deletions.
22 changes: 12 additions & 10 deletions .github/workflows/release-base.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# This is the base release workflow dispatched by the `release-minor` or `release-patch` workflows
name: Release base
run-name:
${{ inputs.type }} - dry-run:${{ inputs.dry-run }}
run-name: ${{ inputs.type }} - dry-run:${{ inputs.dry-run }}

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down Expand Up @@ -50,7 +49,9 @@ jobs:
- name: Install dependencies
run: yarn install

- name: Run @ibm/telemetry-js-config-generator to regenerate telemetry config file
- name:
Run @ibm/telemetry-js-config-generator to regenerate telemetry config
file
working-directory: ./packages/ibm-products
run: |
yarn telemetry-config
Expand Down Expand Up @@ -88,31 +89,31 @@ jobs:
if: github.event.inputs.type == 'full minor release'
run: |
echo "DRY RUN: ${{ env.DRY_RUN }}"
yarn lerna publish minor --create-release github $(echo "${{ env.DRY_RUN }}")
yarn lerna publish minor --conventional-graduate --create-release github $(echo "${{ env.DRY_RUN }}")
- name: Publish first minor RC (ie. v1.x.0-rc.0)
if: github.event.inputs.type == 'first minor rc'
run: |
echo "DRY RUN: ${{ env.DRY_RUN }}"
yarn lerna publish preminor --create-release github --preid rc --pre-dist-tag next $(echo "${{ env.DRY_RUN }}")
yarn lerna publish preminor --conventional-prerelease --create-release github --preid rc --pre-dist-tag next $(echo "${{ env.DRY_RUN }}")
- name: Publish full patch release (ie. v1.0.x)
if: github.event.inputs.type == 'full patch release'
run: |
echo "DRY RUN: ${{ env.DRY_RUN }}"
yarn lerna publish patch --create-release github $(echo "${{ env.DRY_RUN }}")
yarn lerna publish patch --conventional-graduate --create-release github $(echo "${{ env.DRY_RUN }}")
- name: Publish first patch RC (ie. v1.0.x-rc.0)
if: github.event.inputs.type == 'first patch rc'
run: |
echo "DRY RUN: ${{ env.DRY_RUN }}"
yarn lerna publish prepatch --create-release github --preid rc --pre-dist-tag next $(echo "${{ env.DRY_RUN }}")
yarn lerna publish prepatch --conventional-prerelease --create-release github --preid rc --pre-dist-tag next $(echo "${{ env.DRY_RUN }}")
- name: Publish subsequent RC (ie. v1.0.0-rc.x)
if: github.event.inputs.type == 'subsequent rc'
run: |
echo "DRY RUN: ${{ env.DRY_RUN }}"
yarn lerna publish --create-release github --preid rc --pre-dist-tag next $(echo "${{ env.DRY_RUN }}")
yarn lerna publish --conventional-prerelease --create-release github --preid rc --pre-dist-tag next $(echo "${{ env.DRY_RUN }}")
# After successfully publishing a release candidate, trigger the staging storybook environment deployment workflow.
# Pass in the release branch name to the storybook deployment job so it build off the release branch
Expand All @@ -125,7 +126,9 @@ jobs:
# After successfully publishing a full release, trigger the production storybook environment deployment workflow.
# Pass in the release branch name to the storybook deployment job so it build off the release branch
- name: Dispatch production storybook deployment workflow
if: ${{ (github.event.inputs.type == 'full minor release') || (github.event.inputs.type == 'full patch release') }}
if:
${{ (github.event.inputs.type == 'full minor release') ||
(github.event.inputs.type == 'full patch release') }}
uses: peter-evans/repository-dispatch@v3
with:
event-type: deploy-latest-storybook
Expand All @@ -137,4 +140,3 @@ jobs:
with:
event-type: merge-to-main
client-payload: '{"branch": "${{ github.ref_name }}"}'

Original file line number Diff line number Diff line change
Expand Up @@ -6695,6 +6695,7 @@ button.c4p--add-select__global-filter-toggle--open {
--cds-link-inverse: #0f62fe;
--cds-link-inverse-active: #161616;
--cds-link-inverse-hover: #0043ce;
--cds-link-inverse-visited: #8a3ffc;
--cds-link-primary: #78a9ff;
--cds-link-primary-hover: #a6c8ff;
--cds-link-secondary: #a6c8ff;
Expand Down Expand Up @@ -10525,6 +10526,7 @@ button.c4p--add-select__global-filter-toggle--open {
--cds-link-inverse: #0f62fe;
--cds-link-inverse-active: #161616;
--cds-link-inverse-hover: #0043ce;
--cds-link-inverse-visited: #8a3ffc;
--cds-link-primary: #78a9ff;
--cds-link-primary-hover: #a6c8ff;
--cds-link-secondary: #a6c8ff;
Expand Down Expand Up @@ -10955,6 +10957,7 @@ button.c4p--add-select__global-filter-toggle--open {
--cds-link-inverse: #0f62fe;
--cds-link-inverse-active: #161616;
--cds-link-inverse-hover: #0043ce;
--cds-link-inverse-visited: #8a3ffc;
--cds-link-primary: #78a9ff;
--cds-link-primary-hover: #a6c8ff;
--cds-link-secondary: #a6c8ff;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
//

// Import portions of React that are needed.
import React, { useEffect, useState, useRef } from 'react';
import React, {
useEffect,
useState,
useRef,
PropsWithChildren,
Ref,
} from 'react';

// Other standard imports.
import PropTypes from 'prop-types';
Expand All @@ -20,6 +26,8 @@ import uuidv4 from '../../global/js/utils/uuidv4';
import { prepareProps } from '../../global/js/utils/props-helper';
import { ActionBarItem } from './ActionBarItem';
import { ActionBarOverflowItems } from './ActionBarOverflowItems';
import { ButtonProps } from '@carbon/type';
import { CarbonIconType } from '@carbon/icons-react/lib/CarbonIcon';

// The block part of our conventional BEM class names (blockClass__E--M).
const blockClass = `${pkg.prefix}--action-bar`;
Expand All @@ -30,6 +38,59 @@ const defaults = {
actions: Object.freeze([]),
};

interface Action extends ButtonProps {
id?: string;
key: string;
iconDescription: string;
label: string;
onClick?: () => void;
renderIcon: CarbonIconType;
}

interface ActionBarProps extends PropsWithChildren {
/**
* Specifies the action bar items. Each item is specified as an object
* with required fields: key for array rendering, renderIcon, iconDescription and
* label to provide the icon to display,
* and optional 'onClick' to receive notifications when the button is clicked.
* Additional fields in the object will be passed to the
* Button component, and these can include 'disabled', 'ref', 'className',
* and any other Button props.
*
* Note that the Button props 'kind', 'size',
* 'tooltipPosition', 'tooltipAlignment' and 'type' are ignored, as these
* cannot be used for an action bar item.
*
* Carbon Button API https://react.carbondesignsystem.com/?path=/docs/components-button--default#component-api
*/
actions?: readonly Action[];
// expects action bar item as array or in fragment,
/**
* className
*/
className?: string;
/**
* maxVisible : Maximum action bar items visible before going into the overflow menu
*/
maxVisible?: number;
/**
* class name applied to the overflow options
*/
menuOptionsClass?: string;
/**
* onItemCountChange - event reporting maxWidth
*/
onWidthChange?: (sizes: { minWidth: number; maxWidth: number }) => void;
/**
* overflowAriaLabel label for open close button overflow used for action bar items that do nto fit.
*/
overflowAriaLabel: string;
/**
* align tags to right of available space
*/
rightAlign?: boolean;
}

// NOTE: the component SCSS is not imported here: it is rolled up separately.

/**
Expand All @@ -50,18 +111,19 @@ export let ActionBar = React.forwardRef(

// Collect any other property values passed in.
...rest
},
ref
}: ActionBarProps,
ref: Ref<HTMLDivElement>
) => {
const [displayCount, setDisplayCount] = useState(0);
const [displayedItems, setDisplayedItems] = useState([]);
const [hiddenSizingItems, setHiddenSizingItems] = useState([]);
const [displayedItems, setDisplayedItems] = useState<JSX.Element[]>([]);
const [hiddenSizingItems, setHiddenSizingItems] =
useState<JSX.Element | null>(null);
const internalId = useRef(uuidv4());
const refDisplayedItems = useRef(null);
const sizingRef = useRef(null);
const sizes = useRef({});
const refDisplayedItems = useRef<HTMLDivElement>(null);
const sizingRef = useRef<HTMLDivElement>(null);
const sizes = useRef<{ minWidth?: number; maxWidth?: number }>({});

const backupRef = useRef();
const backupRef = useRef<HTMLDivElement>(null);
const localRef = ref || backupRef;

// create hidden sizing items
Expand Down Expand Up @@ -125,8 +187,8 @@ export let ActionBar = React.forwardRef(
const checkFullyVisibleItems = () => {
/* istanbul ignore if */
if (sizingRef.current) {
let sizingItems = Array.from(
sizingRef.current.querySelectorAll(
const sizingItems = Array.from(
sizingRef.current.querySelectorAll<HTMLElement>(
`.${blockClass}__hidden-sizing-item`
)
);
Expand All @@ -135,31 +197,36 @@ export let ActionBar = React.forwardRef(
const overflowItem = sizingItems.shift();

// determine how many will fit
let spaceAvailable = refDisplayedItems.current.offsetWidth;
let spaceAvailable = refDisplayedItems.current?.offsetWidth;
let willFit = 0;
let maxVisibleWidth = 0;
let fitLimit = maxVisible
const fitLimit = maxVisible
? Math.min(maxVisible, sizingItems.length)
: sizingItems.length;

// loop checking the space available
for (let i = 0; i < fitLimit; i++) {
const newSpaceAvailable = spaceAvailable - sizingItems[i].offsetWidth;
const newSpaceAvailable =
spaceAvailable && spaceAvailable - sizingItems[i].offsetWidth;

// update maxVisibleWidth for later use by onWidthChange
maxVisibleWidth += sizingItems[i].offsetWidth;

if (newSpaceAvailable >= 0) {
if (newSpaceAvailable && newSpaceAvailable >= 0) {
spaceAvailable = newSpaceAvailable;
willFit += 1;
}
}

// if not enough space for all items then make room for the overflow
const overflowWidth = overflowItem.offsetWidth;
const overflowWidth = overflowItem!.offsetWidth;
if (willFit < sizingItems.length) {
// Check space for overflow
while (willFit > 0 && spaceAvailable < overflowWidth) {
while (
willFit > 0 &&
spaceAvailable &&
spaceAvailable < overflowWidth
) {
willFit -= 1;

// Highly unlikely that any action bar item is narrower than the overflow item
Expand All @@ -178,7 +245,8 @@ export let ActionBar = React.forwardRef(
sizes.current.maxWidth = maxVisibleWidth;
// emit onWidthChange
onWidthChange({
...sizes.current,
minWidth: overflowWidth,
maxWidth: maxVisibleWidth,
});
}
if (willFit < 1) {
Expand Down Expand Up @@ -242,20 +310,24 @@ ActionBar.propTypes = {
*
* Carbon Button API https://react.carbondesignsystem.com/?path=/docs/components-button--default#component-api
*/
/**@ts-ignore */
actions: PropTypes.arrayOf(
PropTypes.shape({
/**@ts-ignore */
...prepareProps(Button.propTypes, [
// props not desired from Button.propTypes
'kind',
'size',
'tooltipPosition',
'tooltipAlignment',
]),
id: PropTypes.string,
// Additional props
key: PropTypes.string.isRequired,
// Redefine as form different to Button and a key prop used by ActionBarItems
iconDescription: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
/**@ts-ignore */
renderIcon: Button.propTypes.renderIcon.isRequired,
// We duplicate onClick here to improve DocGen in Storybook
onClick: PropTypes.func,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//

// Import portions of React that are needed.
import React from 'react';
import React, { ForwardedRef, PropsWithChildren } from 'react';

// Other standard imports.
import PropTypes from 'prop-types';
Expand All @@ -15,18 +15,56 @@ import { pkg } from '../../settings';

// Carbon and package components we use.
import { IconButton } from '@carbon/react';
import { CarbonIconType } from '@carbon/icons-react/lib/CarbonIcon';

// The block part of our conventional BEM class names (blockClass__E--M).
const componentName = 'ActionBarItem';
const blockClass = `${pkg.prefix}--action-bar-item`;

interface ActionBarItemProps extends PropsWithChildren {
/**
* Specify an optional className to be added to your Button
*
* (inherited from Carbon Button)
*/
className?: string;
/**
* If specifying the `renderIcon` prop, provide a description for that icon that can
* be read by screen readers
*
* (inherited from Carbon Button)
*/
label?: string;
/**
* Optional click handler
*
* (inherited from Carbon Button)
*/
onClick?: () => void;
/**
* Optional prop to allow overriding the icon rendering.
* Can be a React component class
*
* (inherited from Carbon Button)
*/
renderIcon?: CarbonIconType;

/**
* Optional tab index
*/
tabIndex?: number;
}

// NOTE: the component SCSS is not imported here: it is rolled up separately.

/**
* The ActionBarItem is used in the page header to populate the action bar
*/
export let ActionBarItem = React.forwardRef(
({ label, className, renderIcon, ...rest }, ref) => {
(
{ label, className, renderIcon, ...rest }: ActionBarItemProps,
ref: ForwardedRef<HTMLDivElement>
) => {
const Icon = renderIcon;

return (
Expand Down Expand Up @@ -98,5 +136,11 @@ ActionBarItem.propTypes = {
*
* (inherited from Carbon Button)
*/
/**@ts-ignore */
renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),

/**
* Optional tab index
*/
tabIndex: PropTypes.number,
};
Loading

0 comments on commit 1fd80a1

Please sign in to comment.