Skip to content

Commit

Permalink
fix(react-card): improve API naming
Browse files Browse the repository at this point in the history
  • Loading branch information
marcosmoura committed Nov 3, 2022
1 parent 64ad7aa commit 1f83d63
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 63 deletions.
26 changes: 13 additions & 13 deletions packages/react-components/react-card/docs/Spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,19 @@ Card goes for a more structural and generic approach to a card component and is

#### API

| Property | Values | Default | Purpose |
| --------------- | ------------------------------------------------------------------------------------ | ---------- | -------------------------------------------------------------------------------- |
| orientation | `vertical`, `horizontal` | `vertical` | Orientation of the card |
| size | `small`, `medium`, `large` | `medium` | Define the minimum size of the card. Smaller sizes only apply to horizontal card |
| scale | `fixed`, `auto-width`, `auto-height`, `auto`, `fluid-width`, `fluid-height`, `fluid` | `auto` | Manages how the card handles it's scaling depending on the content |
| appearance | `filled`, `filled-alternative`, `outline`, `subtle` | `filled` | Define the appearance of the card |
| select | slot | undefined | Slot for a custom checkbox element for when a card is selectable |
| selected | boolean | false | Set to `true` if card is selected |
| defaultSelected | boolean | false | Set to `true` if card is selected by default |
| onCardSelect | function | undefined | Callback called when the card selection changes |
| expandable | boolean | false | Allow card to expand to show whole content |
| disabled | boolean | false | Makes the card and card selection disabled (not propagated to children) |
| focusMode | `off`, `no-tab`, `tab-exit`, `tab-only` | `off` | Sets the focus behavior for the card. |
| Property | Values | Default | Purpose |
| ----------------- | ------------------------------------------------------------------------------------ | ---------- | -------------------------------------------------------------------------------- |
| orientation | `vertical`, `horizontal` | `vertical` | Orientation of the card |
| size | `small`, `medium`, `large` | `medium` | Define the minimum size of the card. Smaller sizes only apply to horizontal card |
| scale | `fixed`, `auto-width`, `auto-height`, `auto`, `fluid-width`, `fluid-height`, `fluid` | `auto` | Manages how the card handles it's scaling depending on the content |
| appearance | `filled`, `filled-alternative`, `outline`, `subtle` | `filled` | Define the appearance of the card |
| select | slot | undefined | Slot for a custom checkbox element for when a card is selectable |
| selected | boolean | false | Set to `true` if card is selected |
| defaultSelected | boolean | false | Set to `true` if card is selected by default |
| onSelectionChange | function | undefined | Callback called when the card selection changes |
| expandable | boolean | false | Allow card to expand to show whole content |
| disabled | boolean | false | Makes the card and card selection disabled (not propagated to children) |
| focusMode | `off`, `no-tab`, `tab-exit`, `tab-only` | `off` | Sets the focus behavior for the card. |

#### `scale` property

Expand Down
14 changes: 7 additions & 7 deletions packages/react-components/react-card/etc/react-card.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,6 @@ export type CardHeaderSlots = {
// @public
export type CardHeaderState = ComponentState<CardHeaderSlots>;

// @public
export type CardOnSelectEvent = React_2.MouseEvent | React_2.KeyboardEvent | React_2.ChangeEvent;

// @public
export const CardPreview: ForwardRefComponent<CardPreviewProps>;

Expand All @@ -96,7 +93,7 @@ export type CardProps = ComponentProps<CardSlots> & {
size?: 'small' | 'medium' | 'large';
selected?: boolean;
defaultSelected?: boolean;
onCardSelect?: (event: CardOnSelectEvent, data: CardOnSelectData) => void;
onSelectionChange?: (event: CarOnSelectionChangeEvent, data: CardOnSelectData) => void;
};

// @public
Expand All @@ -107,12 +104,15 @@ export type CardSlots = {

// @public
export type CardState = ComponentState<CardSlots> & Required<Pick<CardProps, 'appearance' | 'orientation' | 'size'> & {
isInteractive: boolean;
isSelectable: boolean;
interactive: boolean;
selectable: boolean;
hasSelectSlot: boolean;
isCardSelected: boolean;
selected: boolean;
}>;

// @public
export type CarOnSelectionChangeEvent = React_2.MouseEvent | React_2.KeyboardEvent | React_2.ChangeEvent;

// @public
export const renderCard_unstable: (state: CardState) => JSX.Element;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,11 +280,11 @@ describe('Card', () => {
cy.get('#card').should('have.attr', 'role', 'checkbox');
});

it('should role="checkbox" when selectable - onCardSelect prop', () => {
it('should role="checkbox" when selectable - onSelectionChange prop', () => {
const Example = () => {
const onCardSelect = React.useCallback(() => null, []);
const onSelectionChange = React.useCallback(() => null, []);

return <CardSample onCardSelect={onCardSelect} />;
return <CardSample onSelectionChange={onSelectionChange} />;
};

mountFluent(<Example />);
Expand Down Expand Up @@ -354,12 +354,12 @@ describe('Card', () => {
const Example = () => {
const [checked, setChecked] = React.useState(false);

const onCardSelect = React.useCallback((event, { selected }) => setChecked(selected), []);
const onSelectionChange = React.useCallback((event, { selected }) => setChecked(selected), []);

return (
<CardSample
select={<input type="checkbox" className="custom-select-slot" checked={checked} />}
onCardSelect={onCardSelect}
onSelectionChange={onSelectionChange}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type CardRefElement = HTMLDivElement | HTMLButtonElement | HTMLAnchorElem
*
* This event is fired when a selectable card changes its selection state.
*/
export type CardOnSelectEvent = React.MouseEvent | React.KeyboardEvent | React.ChangeEvent;
export type CarOnSelectionChangeEvent = React.MouseEvent | React.KeyboardEvent | React.ChangeEvent;

/**
* Data sent from the selection events on a selectable card.
Expand Down Expand Up @@ -111,7 +111,7 @@ export type CardProps = ComponentProps<CardSlots> & {
/**
* Callback to be called when the selected state value changes.
*/
onCardSelect?: (event: CardOnSelectEvent, data: CardOnSelectData) => void;
onSelectionChange?: (event: CarOnSelectionChangeEvent, data: CardOnSelectData) => void;
};

/**
Expand All @@ -125,14 +125,14 @@ export type CardState = ComponentState<CardSlots> &
*
* @default false
*/
isInteractive: boolean;
interactive: boolean;

/**
* Represents a selectable card.
*
* @default false
*/
isSelectable: boolean;
selectable: boolean;

/**
* Represents a selectable card that contains a slot for the select element.
Expand All @@ -146,6 +146,6 @@ export type CardState = ComponentState<CardSlots> &
*
* @default false
*/
isCardSelected: boolean;
selected: boolean;
}
>;
23 changes: 10 additions & 13 deletions packages/react-components/react-card/src/components/Card/useCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ const focusMap = {
} as const;

type UseCardFocusAttributesOptions = {
isInteractive: boolean;
interactive: boolean;
};

const useCardFocusAttributes = ({ focusMode = 'off' }: CardProps, { isInteractive }: UseCardFocusAttributesOptions) => {
const internalFocusMode = isInteractive ? 'no-tab' : focusMode;
const useCardFocusAttributes = ({ focusMode = 'off' }: CardProps, { interactive }: UseCardFocusAttributesOptions) => {
const internalFocusMode = interactive ? 'no-tab' : focusMode;

const groupperAttrs = useFocusableGroup({
tabBehavior: focusMap[internalFocusMode],
Expand Down Expand Up @@ -46,13 +46,10 @@ export const useCard_unstable = (props: CardProps, ref: React.Ref<CardRefElement
const { appearance = 'filled', orientation = 'vertical', size = 'medium', as = 'div' } = props;
const cardRef = React.useRef<CardRefElement>(null);

const { isSelectable, hasSelectSlot, isCardSelected, selectableSlot, selectableProps } = useCardSelectable(
props,
cardRef,
);
const { selectable, hasSelectSlot, selected, selectableSlot, selectableProps } = useCardSelectable(props, cardRef);

const isInteractive = Boolean(
isSelectable ||
const interactive = Boolean(
selectable ||
['a', 'button'].includes(as) ||
props.onClick ||
props.onDoubleClick ||
Expand All @@ -64,16 +61,16 @@ export const useCard_unstable = (props: CardProps, ref: React.Ref<CardRefElement
props.onTouchEnd,
);

const focusAttributes = useCardFocusAttributes(props, { isInteractive });
const focusAttributes = useCardFocusAttributes(props, { interactive });

return {
appearance,
orientation,
size,
isInteractive,
isSelectable,
interactive,
selectable,
hasSelectSlot,
isCardSelected,
selected,

components: {
root: as,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ import { Enter, Space } from '@fluentui/keyboard-keys';
import { resolveShorthand } from '@fluentui/react-utilities';
import { useFocusFinders } from '@fluentui/react-tabster';

import type { CardOnSelectEvent, CardProps, CardRefElement } from './Card.types';
import type { CarOnSelectionChangeEvent, CardProps, CardRefElement } from './Card.types';

export const useCardSelectable = (props: CardProps, cardRef: React.RefObject<CardRefElement>) => {
const { select, selected, defaultSelected, onCardSelect } = props;
const { select, selected, defaultSelected, onSelectionChange } = props;

const { findAllFocusable } = useFocusFinders();
const selectableRef = React.useRef<HTMLDivElement>(null);

const isSelectable = [selected, defaultSelected, onCardSelect, select].some(bool => typeof bool !== 'undefined');
const isSelectable = [selected, defaultSelected, onSelectionChange, select].some(bool => typeof bool !== 'undefined');
const hasSelectSlot = Boolean(select);

const [isCardSelected, setIsCardSelected] = React.useState(false);

const shouldRestrictTriggerAction = React.useCallback(
(event: CardOnSelectEvent) => {
(event: CarOnSelectionChangeEvent) => {
if (!cardRef.current) {
return false;
}
Expand All @@ -32,7 +32,7 @@ export const useCardSelectable = (props: CardProps, cardRef: React.RefObject<Car
[cardRef, findAllFocusable],
);
const onChangeHandler = React.useCallback(
(event: CardOnSelectEvent) => {
(event: CarOnSelectionChangeEvent) => {
if (shouldRestrictTriggerAction(event)) {
return;
}
Expand All @@ -41,13 +41,13 @@ export const useCardSelectable = (props: CardProps, cardRef: React.RefObject<Car

setIsCardSelected(newCheckedValue);

if (onCardSelect) {
onCardSelect(event, {
if (onSelectionChange) {
onSelectionChange(event, {
selected: newCheckedValue,
});
}
},
[onCardSelect, isCardSelected, shouldRestrictTriggerAction],
[onSelectionChange, isCardSelected, shouldRestrictTriggerAction],
);
const onKeyDownHandler = React.useCallback(
(event: React.KeyboardEvent<HTMLElement>) => {
Expand Down Expand Up @@ -99,8 +99,8 @@ export const useCardSelectable = (props: CardProps, cardRef: React.RefObject<Car
]);

return {
isCardSelected,
isSelectable,
selected: isCardSelected,
selectable: isSelectable,
hasSelectSlot,
selectableProps,
selectableSlot,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,7 @@ const getInteractiveClassnames = (state: CardState, styles: ReturnType<typeof us
outline: styles.outlineInteractive,
subtle: styles.subtleInteractive,
};
const baseClass = mergeClasses(
interactiveMap[state.appearance],
state.isCardSelected && selectedMap[state.appearance],
);
const baseClass = mergeClasses(interactiveMap[state.appearance], state.selected && selectedMap[state.appearance]);

if (state.components.root === 'button') {
return mergeClasses(baseClass, styles.interactiveButton);
Expand Down Expand Up @@ -356,7 +353,7 @@ export const useCardStyles_unstable = (state: CardState): CardState => {
orientationMap[state.orientation],
sizeMap[state.size],
appearanceMap[state.appearance],
state.isInteractive && getInteractiveClassnames(state, styles),
state.interactive && getInteractiveClassnames(state, styles),
state.root.className,
);

Expand Down
2 changes: 1 addition & 1 deletion packages/react-components/react-card/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export {
useCardStyles_unstable,
useCard_unstable,
} from './Card';
export type { CardProps, CardSlots, CardState, CardOnSelectEvent } from './Card';
export type { CardProps, CardSlots, CardState, CarOnSelectionChangeEvent } from './Card';
export {
CardFooter,
cardFooterClassNames,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ export const Selectable = () => {
<CardExample
aria-label={getCardLabel(selected1)}
selected={selected1}
onCardSelect={(_, { selected }) => setSelected1(selected)}
onSelectionChange={(_, { selected }) => setSelected1(selected)}
/>
<CardExample
aria-label={getCardLabel(selected2)}
selected={selected2}
onCardSelect={(_, { selected }) => setSelected2(selected)}
onSelectionChange={(_, { selected }) => setSelected2(selected)}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,13 @@ export const SelectableWithCheckbox = () => {
aria-label={getCardLabel(selected1)}
select={<Checkbox checked={selected1} aria-label={getCardLabel(selected1)} />}
selected={selected1}
onCardSelect={onFirstCardSelected}
onSelectionChange={onFirstCardSelected}
/>
<CardExample
aria-label={getCardLabel(selected2)}
select={<Checkbox checked={selected2} aria-label={getCardLabel(selected2)} />}
selected={selected2}
onCardSelect={onSecondCardSelected}
onSelectionChange={onSecondCardSelected}
/>
</div>
);
Expand Down

0 comments on commit 1f83d63

Please sign in to comment.