Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "chore: Create InfoTip component.",
"packageName": "@fluentui/react-infobutton",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,32 @@ export type InfoLabelSlots = {
// @public
export type InfoLabelState = ComponentState<InfoLabelSlots> & Pick<InfoLabelProps, 'size'>;

// @public
export const InfoTip: ForwardRefComponent<InfoTipProps>;

// @public (undocumented)
export const infoTipClassNames: SlotClassNames<InfoTipSlots>;

// @public
export type InfoTipProps = ComponentProps<InfoTipSlots> & {};

// @public (undocumented)
export type InfoTipSlots = {
root: Slot<'div'>;
};

// @public
export type InfoTipState = ComponentState<InfoTipSlots>;

// @public
export const renderInfoButton_unstable: (state: InfoButtonState) => JSX.Element;

// @public
export const renderInfoLabel_unstable: (state: InfoLabelState) => JSX.Element;

// @public
export const renderInfoTip_unstable: (state: InfoTipState) => JSX.Element;

// @public
export const useInfoButton_unstable: (props: InfoButtonProps, ref: React_2.Ref<HTMLElement>) => InfoButtonState;

Expand All @@ -76,6 +96,12 @@ export const useInfoLabel_unstable: (props: InfoLabelProps, ref: React_2.Ref<HTM
// @public
export const useInfoLabelStyles_unstable: (state: InfoLabelState) => InfoLabelState;

// @public
export const useInfoTip_unstable: (props: InfoTipProps, ref: React_2.Ref<HTMLElement>) => InfoTipState;

// @public
export const useInfoTipStyles_unstable: (state: InfoTipState) => InfoTipState;

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components/InfoTip/index';
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import { InfoTip } from './InfoTip';
import { isConformant } from '../../testing/isConformant';

describe('InfoTip', () => {
isConformant({
Component: InfoTip,
displayName: 'InfoTip',
});

// TODO add more tests here, and create visual regression tests in /apps/vr-tests

it('renders a default state', () => {
const result = render(<InfoTip>Default InfoTip</InfoTip>);
expect(result.container).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from 'react';
import { useInfoTip_unstable } from './useInfoTip';
import { renderInfoTip_unstable } from './renderInfoTip';
import { useInfoTipStyles_unstable } from './useInfoTipStyles.styles';
import type { InfoTipProps } from './InfoTip.types';
import type { ForwardRefComponent } from '@fluentui/react-utilities';

/**
* InfoTip component - TODO: add more docs
*/
export const InfoTip: ForwardRefComponent<InfoTipProps> = React.forwardRef((props, ref) => {
const state = useInfoTip_unstable(props, ref);

useInfoTipStyles_unstable(state);
return renderInfoTip_unstable(state);
});

InfoTip.displayName = 'InfoTip';
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';

export type InfoTipSlots = {
root: Slot<'div'>;
};

/**
* InfoTip Props
*/
export type InfoTipProps = ComponentProps<InfoTipSlots> & {};

/**
* State used in rendering InfoTip
*/
export type InfoTipState = ComponentState<InfoTipSlots>;
// TODO: Remove semicolon from previous line, uncomment next line, and provide union of props to pick from InfoTipProps.
// & Required<Pick<InfoTipProps, 'propName'>>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`InfoTip renders a default state 1`] = `
<div>
<div
class="fui-InfoTip"
>
Default InfoTip
</div>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './InfoTip';
export * from './InfoTip.types';
export * from './renderInfoTip';
export * from './useInfoTip';
export * from './useInfoTipStyles.styles';
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/** @jsxRuntime classic */
/** @jsx createElement */

import { createElement } from '@fluentui/react-jsx-runtime';
import { getSlotsNext } from '@fluentui/react-utilities';
import type { InfoTipState, InfoTipSlots } from './InfoTip.types';

/**
* Render the final JSX of InfoTip
*/
export const renderInfoTip_unstable = (state: InfoTipState) => {
const { slots, slotProps } = getSlotsNext<InfoTipSlots>(state);

// TODO Add additional slots in the appropriate place
return <slots.root {...slotProps.root} />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as React from 'react';
import { getNativeElementProps } from '@fluentui/react-utilities';
import type { InfoTipProps, InfoTipState } from './InfoTip.types';

/**
* Create the state required to render InfoTip.
*
* The returned state can be modified with hooks such as useInfoTipStyles_unstable,
* before being passed to renderInfoTip_unstable.
*
* @param props - props from this instance of InfoTip
* @param ref - reference to root HTMLElement of InfoTip
*/
export const useInfoTip_unstable = (props: InfoTipProps, ref: React.Ref<HTMLElement>): InfoTipState => {
return {
// TODO add appropriate props/defaults
components: {
// TODO add each slot's element type or component
root: 'div',
},
// TODO add appropriate slots, for example:
// mySlot: resolveShorthand(props.mySlot),
root: getNativeElementProps('div', {
ref,
...props,
}),
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { makeStyles, mergeClasses } from '@griffel/react';
import type { InfoTipSlots, InfoTipState } from './InfoTip.types';
import type { SlotClassNames } from '@fluentui/react-utilities';

export const infoTipClassNames: SlotClassNames<InfoTipSlots> = {
root: 'fui-InfoTip',
// TODO: add class names for all slots on InfoTipSlots.
// Should be of the form `<slotName>: 'fui-InfoTip__<slotName>`
};

/**
* Styles for the root slot
*/
const useStyles = makeStyles({
root: {
// TODO Add default styles for the root element
},

// TODO add additional classes for different states and/or slots
});

/**
* Apply styling to the InfoTip slots based on the state
*/
export const useInfoTipStyles_unstable = (state: InfoTipState): InfoTipState => {
const styles = useStyles();
state.root.className = mergeClasses(infoTipClassNames.root, styles.root, state.root.className);

// TODO Add class names to slots, for example:
// state.mySlot.className = mergeClasses(styles.mySlot, state.mySlot.className);

return state;
};
8 changes: 8 additions & 0 deletions packages/react-components/react-infobutton/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,11 @@ export {
useInfoLabel_unstable,
} from './InfoLabel';
export type { InfoLabelProps, InfoLabelSlots, InfoLabelState } from './InfoLabel';
export {
InfoTip,
infoTipClassNames,
renderInfoTip_unstable,
useInfoTipStyles_unstable,
useInfoTip_unstable,
} from './InfoTip';
export type { InfoTipProps, InfoTipSlots, InfoTipState } from './InfoTip';
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Best practices

### Do

### Don't
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as React from 'react';
import { InfoTip, InfoTipProps } from '@fluentui/react-infobutton';

export const Default = (props: Partial<InfoTipProps>) => <InfoTip {...props} />;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { InfoTip } from '@fluentui/react-infobutton';

import descriptionMd from './InfoTipDescription.md';
import bestPracticesMd from './InfoTipBestPractices.md';

export { Default } from './InfoTipDefault.stories';

export default {
title: 'Preview Components/InfoTip',
component: InfoTip,
parameters: {
docs: {
description: {
component: [descriptionMd, bestPracticesMd].join('\n'),
},
},
},
};